private void RecursiveSolveCombinations(JournalEntryLineModel targetLine, double currentSum, List <JournalEntryLineModel> included, List <JournalEntryLineModel> notIncluded, int startIndex, int milliseconds)
        {
            for (int index = startIndex; index < notIncluded.Count; index++)
            {
                if (_stopwatch.ElapsedMilliseconds > milliseconds)
                {
                    return;
                }
                double goal = targetLine.Debit == 0 ? targetLine.Credit : targetLine.Debit;
                JournalEntryLineModel nextLine = notIncluded[index];
                double nextAmount      = nextLine.Debit == 0 ? nextLine.Credit : nextLine.Debit;
                double amountToCompare = Math.Round(currentSum + nextAmount, _roundAccuracy);

                if (amountToCompare == goal)
                {
                    List <JournalEntryLineModel> newResult = new List <JournalEntryLineModel>(included)
                    {
                        nextLine
                    };
                    _sourceLines = newResult;
                    return;
                }
                else if (Math.Abs(amountToCompare) < Math.Abs(goal))
                {
                    List <JournalEntryLineModel> nextIncuded = new List <JournalEntryLineModel>(included)
                    {
                        nextLine
                    };
                    List <JournalEntryLineModel> nextNonIncluded = new List <JournalEntryLineModel>(notIncluded);
                    nextNonIncluded.Remove(nextLine);
                    RecursiveSolveCombinations(targetLine, amountToCompare, nextIncuded, nextNonIncluded, startIndex++, milliseconds);
                }
            }
        }
        private void RecursiveSolveCombinationsNegative(JournalEntryLineModel targetLine, double currentSum, List <JournalEntryLineModel> included, List <JournalEntryLineModel> notIncluded, int startIndex)
        {
            var roundTotalsAccuracy = _company.GetCompanyService().GetAdminInfo().TotalsAccuracy;

            for (int index = startIndex; index < notIncluded.Count; index++)
            {
                double goal = targetLine.Debit == 0 ? targetLine.Credit : targetLine.Debit;
                JournalEntryLineModel nextLine = notIncluded[index];
                double nextAmount      = nextLine.Debit == 0 ? nextLine.Credit : nextLine.Debit;
                double amountToCompare = Math.Round(currentSum + nextAmount, roundTotalsAccuracy);

                if (amountToCompare + goal == 0)
                {
                    List <JournalEntryLineModel> newResult = new List <JournalEntryLineModel>(included)
                    {
                        nextLine
                    };
                    _sourceLines = newResult;
                }
                else if (Math.Abs(amountToCompare) < Math.Abs(goal))
                {
                    List <JournalEntryLineModel> nextIncuded = new List <JournalEntryLineModel>(included)
                    {
                        nextLine
                    };
                    List <JournalEntryLineModel> nextNonIncluded = new List <JournalEntryLineModel>(notIncluded);
                    nextNonIncluded.Remove(nextLine);
                    RecursiveSolveCombinationsNegative(targetLine, amountToCompare, nextIncuded, nextNonIncluded, startIndex++);
                }
            }
        }
 public List <JournalEntryLineModel> SolveCombinations(JournalEntryLineModel targetLine, List <JournalEntryLineModel> searchLines, int milliseconds)
 {
     _stopwatch = new Stopwatch();
     _stopwatch.Start();
     _sourceLines = new List <JournalEntryLineModel>();
     RecursiveSolveCombinations(targetLine, 0, new List <JournalEntryLineModel>(), searchLines, 0, milliseconds);
     return(_sourceLines);
 }
예제 #4
0
        private List <JournalEntryLineModel> JournalEntryLineModelsFromRecordset(Recordset recSet)
        {
            List <JournalEntryLineModel> jdtLines = new List <JournalEntryLineModel>();

            while (!recSet.EoF)
            {
                JournalEntryLineModel model = new JournalEntryLineModel(_company)
                {
                    Account       = recSet.Fields.Item("Account").Value.ToString(),
                    ContraAccount = recSet.Fields.Item("ContraAct").Value.ToString(),
                    Credit        = double.Parse(recSet.Fields.Item("Credit").Value.ToString()),
                    Debit         = double.Parse(recSet.Fields.Item("Debit").Value.ToString()),
                    SortName      = recSet.Fields.Item("ShortName").Value.ToString(),
                    TransId       = int.Parse(recSet.Fields.Item("TransId").Value.ToString()),
                    LineId        = int.Parse(recSet.Fields.Item("Line_ID").Value.ToString())
                };
                jdtLines.Add(model);
                recSet.MoveNext();
            }

            return(jdtLines);
        }
 public List <JournalEntryLineModel> SolveCombinationsNegative(JournalEntryLineModel targetLine, List <JournalEntryLineModel> searchLines)
 {
     _sourceLines = new List <JournalEntryLineModel>();
     RecursiveSolveCombinationsNegative(targetLine, 0, new List <JournalEntryLineModel>(), searchLines, 0);
     return(_sourceLines);
 }
예제 #6
0
        private void MainLogicSecond(List <JournalEntryLineModel> jdtLines, int waitingTime)
        {
            Stopwatch st = new Stopwatch();

            st.Start();

            //ვაჯგუფებთ ტრანზაქციის ID-ს მიხედვით (ამოვაგდებთ სადაც დებიტი და კრედიტი 0 ის ტოლია)
            IEnumerable <IGrouping <int, JournalEntryLineModel> > groupBy = jdtLines
                                                                            .Where(y => y.Debit != 0 || y.Credit != 0)
                                                                            .GroupBy(x => x.TransId);
            int increment = 0;
            int total     = groupBy.Count();

            foreach (IGrouping <int, JournalEntryLineModel> journalEntryLineModels in groupBy)
            {
                int transId = journalEntryLineModels.Key; //ტრანზაქციის ID
                List <JournalEntryLineModel>
                debitLines =
                    journalEntryLineModels.Where(x => x.Debit != 0).Select(x => x)
                    .ToList();                                                                // სტრიქონები სადაც დებიტი არაა 0
                List <JournalEntryLineModel> creditLines =
                    journalEntryLineModels.Where(x => x.Credit != 0).Select(x => x).ToList(); // სტრიქონები სადაც კრედიტი არაა 0

                var negativeCredits = creditLines.Where(x => x.Credit > 0);
                List <JournalEntryLineModel> asd = new List <JournalEntryLineModel>(negativeCredits);
                foreach (JournalEntryLineModel journalEntryLineModel in asd)
                {
                    creditLines.Remove(creditLines.FirstOrDefault(y =>
                                                                  y.Credit == journalEntryLineModel.Credit && y.LineId == journalEntryLineModel.LineId));
                    creditLines.Add(journalEntryLineModel);
                }

                var negativeDebits = debitLines.Where(x => x.Credit > 0);
                foreach (JournalEntryLineModel journalEntryLineModel in negativeDebits)
                {
                    debitLines.Remove(debitLines.FirstOrDefault(y =>
                                                                y.Debit == journalEntryLineModel.Debit && y.LineId == journalEntryLineModel.LineId));
                    debitLines.Add(journalEntryLineModel);
                }


                // ლოგიკა რომელიც გვიბრუნებს საჟურნალო გატარების სტრიქონებს რომლის ჯამიც გვაძლებს გადაცემული სტრიქონის თანხას
                while (debitLines.Count > 0 || creditLines.Count > 0)
                {
                    JournalEntryLineModel maxDebitLine = debitLines
                                                         .Where(x => Math.Abs(x.Debit) == debitLines.Max(y => Math.Abs(y.Debit))).ToList()
                                                         .FirstOrDefault(); // მაქსიმალური დებიტის თანხა
                    JournalEntryLineModel maxCreditLine = creditLines
                                                          .Where(x => Math.Abs(x.Credit) == creditLines.Max(y => Math.Abs(y.Credit))).ToList()
                                                          .FirstOrDefault(); // მაქსიმალური კრედიტის თანხა


                    bool creditRecalc = false;
                    bool debitRecalc  = false;
                    if (maxCreditLine == null)
                    {
                        creditRecalc = true;
                        foreach (var xz in debitLines.Except(new[] { maxDebitLine }))
                        {
                            xz.Debit  = -1 * xz.Debit;
                            xz.Credit = -1 * xz.Credit;
                        }

                        creditLines.AddRange(debitLines.Except(new[] { maxDebitLine }));
                        debitLines = new List <JournalEntryLineModel>()
                        {
                            maxDebitLine
                        };
                        maxCreditLine = creditLines.Where(x => Math.Abs(x.Credit) == creditLines.Max(y => Math.Abs(y.Credit)))
                                        .ToList().FirstOrDefault(); // მაქსიმალური კრედიტის თანხა
                    }

                    if (maxDebitLine == null)
                    {
                        debitRecalc = true;
                        foreach (var xz in creditLines.Except(new[] { maxCreditLine }))
                        {
                            xz.Debit  = -1 * xz.Debit;
                            xz.Credit = -1 * xz.Credit;
                        }

                        debitLines.AddRange(creditLines.Except(new[] { maxCreditLine }));
                        creditLines = new List <JournalEntryLineModel>()
                        {
                            maxCreditLine
                        };
                        maxDebitLine = debitLines.Where(x => Math.Abs(x.Debit) == debitLines.Max(y => Math.Abs(y.Debit)))
                                       .ToList().FirstOrDefault(); // მაქსიმალური დებიტის თანხა, ეს იწვევს პრობლემას როდესაც გატარება ხელით არს გაკეთებული. FirstOrDefault აბრუნებს ნალს.
                    }

                    if (Math.Abs(maxCreditLine.Credit) == Math.Abs(maxDebitLine.Debit))
                    {
                        maxDebitLine.CorrectContraAccount   = maxCreditLine.Account;
                        maxDebitLine.ContraAccountLineId    = maxCreditLine.LineId;
                        maxDebitLine.CorrectContraShortName = maxCreditLine.SortName;
                        maxDebitLine.UpdateSql();
                        maxCreditLine.CorrectContraAccount = "SourceSimple";
                        maxCreditLine.ContraAccountLineId  = -1;
                        maxCreditLine.UpdateSql();
                        creditLines.Remove(maxCreditLine);
                        debitLines.Remove(maxDebitLine);
                    }

                    if (Math.Abs(maxCreditLine.Credit) > Math.Abs(maxDebitLine.Debit))
                    {
                        if (!debitRecalc)
                        {
                            foreach (var xz in creditLines.Except(new[] { maxCreditLine }))
                            {
                                xz.Debit  = -1 * xz.Debit;
                                xz.Credit = -1 * xz.Credit;
                            }

                            debitLines.AddRange(creditLines.Except(new[] { maxCreditLine }));
                            creditLines = new List <JournalEntryLineModel>()
                            {
                                maxCreditLine
                            };
                        }

                        List <JournalEntryLineModel> sources = _solver.SolveCombinations(maxCreditLine,
                                                                                         debitLines,
                                                                                         waitingTime * 1000);
                        foreach (JournalEntryLineModel journalEntryLineModel in sources)
                        {
                            journalEntryLineModel.CorrectContraAccount   = maxCreditLine.Account;
                            journalEntryLineModel.CorrectContraShortName = maxCreditLine.SortName;
                            journalEntryLineModel.ContraAccountLineId    = maxCreditLine.LineId;
                            journalEntryLineModel.UpdateSql();
                        }

                        maxCreditLine.CorrectContraAccount = "SourceComplex";
                        maxCreditLine.ContraAccountLineId  = -1;
                        maxCreditLine.UpdateSql();
                        creditLines.Remove(maxCreditLine);
                        debitLines = debitLines.Except(sources).ToList();
                    }
                    else if (Math.Abs(maxDebitLine.Debit) > Math.Abs(maxCreditLine.Credit))
                    {
                        if (!creditRecalc)
                        {
                            foreach (var xz in debitLines.Except(new[] { maxDebitLine }))
                            {
                                xz.Debit  = -1 * xz.Debit;
                                xz.Credit = -1 * xz.Credit;
                            }

                            creditLines.AddRange(debitLines.Except(new[] { maxDebitLine }));
                            debitLines = new List <JournalEntryLineModel>()
                            {
                                maxDebitLine
                            };
                        }

                        List <JournalEntryLineModel> sources = _solver.SolveCombinations(maxDebitLine,
                                                                                         creditLines,
                                                                                         waitingTime * 1000);
                        foreach (JournalEntryLineModel journalEntryLineModel in sources)
                        {
                            journalEntryLineModel.CorrectContraAccount   = maxDebitLine.Account;
                            journalEntryLineModel.CorrectContraShortName = maxDebitLine.SortName;
                            journalEntryLineModel.ContraAccountLineId    = maxDebitLine.LineId;
                            journalEntryLineModel.UpdateSql();
                        }

                        maxDebitLine.CorrectContraAccount = "SourceComplex";
                        maxDebitLine.ContraAccountLineId  = -1;
                        maxDebitLine.UpdateSql();
                        debitLines.Remove(maxDebitLine);
                        creditLines = creditLines.Except(sources).ToList();
                    }
                }
                increment++;
            }
            var wastedMinutes = st.ElapsedMilliseconds / 60000;

            st.Stop();
        }
예제 #7
0
        private void MainLogicFirst(List <JournalEntryLineModel> jdtLines, int waitingTime)
        {
            //ვაჯგუფებთ ტრანზაქციის ID-ს მიხედვით (ამოვაგდებთ სადაც დებიტი და კრედიტი 0 ის ტოლია)
            IEnumerable <IGrouping <int, JournalEntryLineModel> > groupBy = jdtLines
                                                                            .Where(y => y.Debit != 0 || y.Credit != 0)
                                                                            .GroupBy(x => x.TransId);

            foreach (IGrouping <int, JournalEntryLineModel> journalEntryLineModels in groupBy)
            {
                int transId = journalEntryLineModels.Key; //ტრანზაქციის ID
                List <JournalEntryLineModel> debitLines = journalEntryLineModels.Where(x => x.Debit != 0)
                                                          .Select(x => x)
                                                          .ToList(); // სტრიქონები სადაც დებიტი არაა 0
                List <JournalEntryLineModel> creditLines = journalEntryLineModels.Where(x => x.Credit != 0)
                                                           .Select(x => x)
                                                           .ToList(); // სტრიქონები სადაც კრედიტი არაა 0

                // ლოგიკა რომელიც გვიბრუნებს საჟურნალო გატარების სტრიქონებს რომლის ჯამიც გვაძლებს გადაცემული სტრიქონის თანხას

                while (debitLines.Count > 0 && creditLines.Count > 0)
                {
                    JournalEntryLineModel maxDebitLine = debitLines
                                                         .Where(x => Math.Abs(x.Debit) == debitLines.Max(y => Math.Abs(y.Debit))).ToList()
                                                         .First(); // მაქსიმალური დებიტის თანხა
                    JournalEntryLineModel maxCreditLine = creditLines
                                                          .Where(x => Math.Abs(x.Credit) == creditLines.Max(y => Math.Abs(y.Credit))).ToList()
                                                          .First(); // მაქსიმალური კრედიტის თანხა

                    var positiveDr  = debitLines.Count(x => x.Debit > 0);
                    var negatviveDr = debitLines.Count(x => x.Debit < 0);

                    var positiveCr  = creditLines.Count(x => x.Credit > 0);
                    var negatviveCr = creditLines.Count(x => x.Credit < 0);

                    if ((positiveDr > 0 && negatviveDr > 0) || (positiveCr > 0 && negatviveCr > 0) ||
                        (positiveDr > 0 && negatviveCr > 0) || (positiveCr > 0 && negatviveDr > 0))
                    {
                        break;
                    }

                    if (maxCreditLine.Credit == maxDebitLine.Debit)
                    {
                        maxDebitLine.CorrectContraAccount   = maxCreditLine.Account;
                        maxDebitLine.ContraAccountLineId    = maxCreditLine.LineId;
                        maxDebitLine.CorrectContraShortName = maxCreditLine.SortName;
                        maxDebitLine.UpdateSql();
                        maxCreditLine.CorrectContraAccount = "SourceSimple";
                        maxCreditLine.ContraAccountLineId  = -1;
                        maxCreditLine.UpdateSql();
                        creditLines.Remove(maxCreditLine);
                        debitLines.Remove(maxDebitLine);
                    }

                    if (Math.Abs(maxCreditLine.Credit) > Math.Abs(maxDebitLine.Debit))
                    {
                        List <JournalEntryLineModel> sources = _solver.SolveCombinations(maxCreditLine,
                                                                                         debitLines,
                                                                                         waitingTime * 1000);
                        foreach (JournalEntryLineModel journalEntryLineModel in sources)
                        {
                            journalEntryLineModel.CorrectContraAccount   = maxCreditLine.Account;
                            journalEntryLineModel.CorrectContraShortName = maxCreditLine.SortName;
                            journalEntryLineModel.ContraAccountLineId    = maxCreditLine.LineId;
                            journalEntryLineModel.UpdateSql();
                        }

                        maxCreditLine.CorrectContraAccount = "SourceComplex";
                        maxCreditLine.ContraAccountLineId  = -1;
                        maxCreditLine.UpdateSql();
                        creditLines.Remove(maxCreditLine);
                        debitLines = debitLines.Except(sources).ToList();
                    }
                    else if (Math.Abs(maxDebitLine.Debit) > Math.Abs(maxCreditLine.Credit))
                    {
                        List <JournalEntryLineModel> sources = _solver.SolveCombinations(maxDebitLine,
                                                                                         creditLines,
                                                                                         waitingTime * 1000);
                        foreach (JournalEntryLineModel journalEntryLineModel in sources)
                        {
                            journalEntryLineModel.CorrectContraAccount   = maxDebitLine.Account;
                            journalEntryLineModel.CorrectContraShortName = maxDebitLine.SortName;
                            journalEntryLineModel.ContraAccountLineId    = maxDebitLine.LineId;
                            journalEntryLineModel.UpdateSql();
                        }

                        maxDebitLine.CorrectContraAccount = "SourceComplex";
                        maxDebitLine.ContraAccountLineId  = -1;
                        maxDebitLine.UpdateSql();
                        debitLines.Remove(maxDebitLine);
                        creditLines = creditLines.Except(sources).ToList();
                    }
                }
            }
        }