internal List <TrialBalanceEntry> GenerateTotalSummaryConsolidatedByLedger(
            List <TrialBalanceEntry> summaryCurrencies)
        {
            var summaryConsolidatedByLedger = new EmpiriaHashTable <TrialBalanceEntry>(summaryCurrencies.Count);
            List <TrialBalanceEntry> returnedListEntries = new List <TrialBalanceEntry>();

            if (_command.TrialBalanceType == TrialBalanceType.Balanza && _command.ShowCascadeBalances)
            {
                foreach (var currencyEntry in summaryCurrencies.Where(
                             a => a.ItemType == TrialBalanceItemType.BalanceTotalCurrency))
                {
                    TrialBalanceEntry entry = TrialBalanceMapper.MapToTrialBalanceEntry(currencyEntry);

                    entry.GroupName = $"TOTAL CONSOLIDADO {entry.Ledger.FullName}";
                    entry.Currency  = Currency.Empty;
                    string hash = $"{entry.Ledger.Id}||{entry.GroupName}||{Sector.Empty.Code}";

                    GenerateOrIncreaseEntries(summaryConsolidatedByLedger, entry, StandardAccount.Empty, Sector.Empty,
                                              TrialBalanceItemType.BalanceTotalConsolidatedByLedger, hash);
                }

                returnedListEntries.AddRange(summaryConsolidatedByLedger.Values.ToList());
            }
            return(returnedListEntries.OrderBy(a => a.Ledger.Number).ToList());
        }
        private void GenerateOrIncreaseEntries(EmpiriaHashTable <TrialBalanceEntry> summaryEntries,
                                               TrialBalanceEntry entry,
                                               StandardAccount targetAccount, Sector targetSector,
                                               TrialBalanceItemType itemType, string hash)
        {
            TrialBalanceEntry summaryEntry;

            summaryEntries.TryGetValue(hash, out summaryEntry);

            if (summaryEntry == null)
            {
                summaryEntry = new TrialBalanceEntry {
                    Ledger                   = entry.Ledger,
                    Currency                 = entry.Currency,
                    Sector                   = targetSector,
                    Account                  = targetAccount,
                    ItemType                 = itemType,
                    GroupNumber              = entry.GroupNumber,
                    GroupName                = entry.GroupName,
                    DebtorCreditor           = entry.DebtorCreditor,
                    SubledgerAccountIdParent = entry.SubledgerAccountIdParent
                };
                summaryEntry.Sum(entry);

                summaryEntries.Insert(hash, summaryEntry);
            }
            else
            {
                summaryEntry.Sum(entry);
            }
        }
        private List <TrialBalanceEntry> CreateOrAccumulateTotalBySubsidiaryEntry(
            List <TrialBalanceEntry> returnedEntries,
            TrialBalanceEntry entry)
        {
            var helper = new TrialBalanceHelper(_command);

            var parentEntries = new EmpiriaHashTable <TrialBalanceEntry>();

            var existTotalByAccount = returnedEntries.FirstOrDefault(
                a => a.SubledgerAccountId == entry.SubledgerAccountIdParent &&
                a.Ledger.Number == entry.Ledger.Number &&
                a.Currency.Code == entry.Currency.Code);

            if (existTotalByAccount == null)
            {
                helper.SummaryBySubsidiaryEntry(parentEntries, entry, TrialBalanceItemType.BalanceSummary);

                var parent = parentEntries.Values.FirstOrDefault();
                parent.SubledgerAccountId     = parent.SubledgerAccountIdParent;
                parent.SubledgerAccountNumber = SubsidiaryAccount.Parse(entry.SubledgerAccountIdParent).Number ?? "";
                returnedEntries.Add(parent);
            }
            else
            {
                existTotalByAccount.Sum(entry);
            }

            return(returnedEntries);
        }
        internal void SummaryByCurrencyEntries(EmpiriaHashTable <TrialBalanceEntry> summaryEntries,
                                               TrialBalanceEntry balanceEntry,
                                               StandardAccount targetAccount, Sector targetSector,
                                               TrialBalanceItemType itemType)
        {
            TrialBalanceEntry entry = TrialBalanceMapper.MapToTrialBalanceEntry(balanceEntry);

            if (_command.TrialBalanceType != TrialBalanceType.SaldosPorCuentaYMayor &&
                entry.ItemType == TrialBalanceItemType.BalanceTotalCreditor)
            {
                entry.InitialBalance = -1 * entry.InitialBalance;
                entry.CurrentBalance = -1 * entry.CurrentBalance;
            }

            entry.GroupName = "TOTAL MONEDA " + entry.Currency.FullName;
            string hash;

            if (_command.TrialBalanceType == TrialBalanceType.SaldosPorCuentaYMayor)
            {
                entry.GroupNumber = "";
                hash = $"{entry.GroupName}||{entry.Currency.Id}";
            }
            else
            {
                hash = $"{entry.GroupName}||{targetSector.Code}||{entry.Currency.Id}||{entry.Ledger.Id}";
            }
            GenerateOrIncreaseEntries(summaryEntries, entry, targetAccount, targetSector, itemType, hash);
        }
        private void SummaryByGroupEntries(EmpiriaHashTable <TrialBalanceEntry> summaryEntries,
                                           TrialBalanceEntry balanceEntry)
        {
            TrialBalanceEntry groupEntry = TrialBalanceMapper.MapToTrialBalanceEntry(balanceEntry);

            groupEntry.GroupName      = $"TOTAL GRUPO {balanceEntry.Account.GroupNumber}";
            groupEntry.GroupNumber    = balanceEntry.Account.GroupNumber;
            groupEntry.Account        = StandardAccount.Empty;
            groupEntry.Sector         = Sector.Empty;
            groupEntry.DebtorCreditor = balanceEntry.Account.DebtorCreditor;

            string hash;

            if (groupEntry.DebtorCreditor == DebtorCreditorType.Deudora)
            {
                hash = $"{balanceEntry.Ledger.Id}||{balanceEntry.Currency.Id}||{balanceEntry.Account.GroupNumber}||D";

                GenerateOrIncreaseEntries(summaryEntries, groupEntry, StandardAccount.Empty, Sector.Empty,
                                          TrialBalanceItemType.BalanceTotalGroupDebtor, hash);
            }
            else
            {
                hash = $"{balanceEntry.Ledger.Id}||{balanceEntry.Currency.Id}||{balanceEntry.Account.GroupNumber}||A";

                GenerateOrIncreaseEntries(summaryEntries, groupEntry, StandardAccount.Empty, Sector.Empty,
                                          TrialBalanceItemType.BalanceTotalGroupCreditor, hash);
            }
        }
        internal FixedList <TrialBalanceEntry> ConsolidateToTargetCurrency(
            FixedList <TrialBalanceEntry> trialBalance,
            TrialBalanceCommandPeriod commandPeriod)
        {
            var targetCurrency = Currency.Parse(commandPeriod.ValuateToCurrrencyUID);

            var summaryEntries = new EmpiriaHashTable <TrialBalanceEntry>();

            foreach (var entry in trialBalance)
            {
                string hash = $"{entry.Account.Number}||{entry.Sector.Code}||{targetCurrency.Id}||{entry.Ledger.Id}";

                if (entry.Currency.Equals(targetCurrency))
                {
                    summaryEntries.Insert(hash, entry);
                }
                else if (summaryEntries.ContainsKey(hash))
                {
                    summaryEntries[hash].Sum(entry);
                }
                else
                {
                    entry.Currency = targetCurrency;
                    summaryEntries.Insert(hash, entry);
                }
            }

            return(summaryEntries.Values.ToList()
                   .ToFixedList());
        }
        internal List <TrialBalanceEntry> GenerateTotalSummaryConsolidated(List <TrialBalanceEntry> balanceEntries)
        {
            var totalSummaryConsolidated = new EmpiriaHashTable <TrialBalanceEntry>(balanceEntries.Count);

            foreach (var currencyEntry in balanceEntries.Where(
                         a => a.ItemType == TrialBalanceItemType.BalanceTotalCurrency))
            {
                TrialBalanceEntry entry = TrialBalanceMapper.MapToTrialBalanceEntry(currencyEntry);

                entry.GroupName = "TOTAL CONSOLIDADO GENERAL";

                string hash;
                if (_command.TrialBalanceType == TrialBalanceType.SaldosPorCuentaYMayor ||
                    (_command.TrialBalanceType == TrialBalanceType.Balanza && _command.ShowCascadeBalances))
                {
                    hash = $"{entry.GroupName}";
                    entry.GroupNumber = "";
                }
                else
                {
                    hash = $"{entry.GroupName}||{Sector.Empty.Code}||{entry.Ledger.Id}";
                }

                GenerateOrIncreaseEntries(totalSummaryConsolidated, entry, StandardAccount.Empty, Sector.Empty,
                                          TrialBalanceItemType.BalanceTotalConsolidated, hash);
            }

            balanceEntries.AddRange(totalSummaryConsolidated.Values.ToList());

            return(balanceEntries);
        }
        private void CreateOrAccumulateParentWithoutSector(
            List <TrialBalanceEntry> returnedEntries,
            TrialBalanceEntry entry,
            EmpiriaHashTable <TrialBalanceEntry> summaryParentEntries,
            StandardAccount currentParent)
        {
            var helper = new TrialBalanceHelper(_command);

            var entryWithoutSector = returnedEntries.FirstOrDefault(
                a => a.Ledger.Number == entry.Ledger.Number &&
                a.Currency.Code == entry.Currency.Code &&
                a.SubledgerAccountIdParent == entry.SubledgerAccountId &&
                a.Account.Number == currentParent.Number &&
                a.NotHasSector);


            if (entryWithoutSector == null)
            {
                helper.SummaryByEntry(summaryParentEntries, entry, currentParent, Sector.Empty,
                                      TrialBalanceItemType.BalanceSummary);
            }
            else
            {
                entryWithoutSector.Sum(entry);
            }
        }
        private void GenerateOrIncreaseParentEntries(List <TrialBalanceEntry> subsidiaryEntries,
                                                     List <TrialBalanceEntry> returnedEntries)
        {
            var helper = new TrialBalanceHelper(_command);

            foreach (var entry in subsidiaryEntries)
            {
                int count = 0;
                List <TrialBalanceEntry> summaryEntries = new List <TrialBalanceEntry>();
                var             summaryParentEntries    = new EmpiriaHashTable <TrialBalanceEntry>();
                StandardAccount account = entry.Account;

                while (true)
                {
                    var parent = returnedEntries.FirstOrDefault(a => a.Ledger.Number == entry.Ledger.Number &&
                                                                a.Currency.Code == entry.Currency.Code && a.SubledgerAccountId == 0 &&
                                                                a.SubledgerAccountIdParent == entry.SubledgerAccountId &&
                                                                a.Account.Number == account.Number && a.Sector.Code == entry.Sector.Code);

                    if (parent == null)
                    {
                        count++;
                        TrialBalanceItemType itemType = count == 1 ? TrialBalanceItemType.BalanceEntry :
                                                        TrialBalanceItemType.BalanceSummary;
                        helper.SummaryByEntry(summaryParentEntries, entry, account, entry.Sector, itemType);

                        if (!account.HasParent && entry.HasSector && entry.SubledgerAccountId > 0)
                        {
                            CreateOrAccumulateParentWithoutSector(returnedEntries, entry, summaryParentEntries, account);
                            break;
                        }
                        else if (!account.HasParent)
                        {
                            break;
                        }
                        else
                        {
                            account = account.GetParent();
                        }
                    }
                    else
                    {
                        parent.Sum(entry);

                        if (!account.HasParent)
                        {
                            AccumulateSubledgerAccount(returnedEntries, entry, account);
                            break;
                        }
                        else
                        {
                            account = account.GetParent();
                        }
                    }
                } // while
                summaryEntries.AddRange(summaryParentEntries.Values.ToList());
                returnedEntries.AddRange(summaryEntries);
            } // foreach
        }
        internal void SummaryByEntry(EmpiriaHashTable <TrialBalanceEntry> summaryEntries,
                                     TrialBalanceEntry entry,
                                     StandardAccount targetAccount, Sector targetSector,
                                     TrialBalanceItemType itemType)
        {
            string hash = $"{targetAccount.Number}||{targetSector.Code}||{entry.Currency.Id}||{entry.Ledger.Id}";

            GenerateOrIncreaseEntries(summaryEntries, entry, targetAccount, targetSector, itemType, hash);
        }
        internal FixedList <TrialBalanceEntry> GenerateTotalSummaryGroups(FixedList <TrialBalanceEntry> entries)
        {
            var toReturnSummaryGroupEntries = new EmpiriaHashTable <TrialBalanceEntry>(entries.Count);

            foreach (var entry in entries)
            {
                SummaryByGroupEntries(toReturnSummaryGroupEntries, entry);
            }

            return(toReturnSummaryGroupEntries.ToFixedList());
        }
        internal void SummaryBySubsidiaryEntry(EmpiriaHashTable <TrialBalanceEntry> summaryEntries,
                                               TrialBalanceEntry entry, TrialBalanceItemType itemType)
        {
            TrialBalanceEntry balanceEntry = TrialBalanceMapper.MapToTrialBalanceEntry(entry);

            balanceEntry.SubledgerAccountIdParent = entry.SubledgerAccountIdParent;

            string hash = $"{entry.Account.Number}||{entry.Sector.Code}||{entry.Currency.Id}||{entry.Ledger.Id}";

            GenerateOrIncreaseEntries(summaryEntries, balanceEntry,
                                      StandardAccount.Empty, Sector.Empty, itemType, hash);
        }
        internal void SummaryByLedgersGroupEntries(EmpiriaHashTable <TrialBalanceEntry> totalsListByGroupEntries,
                                                   TrialBalanceEntry balanceEntry)
        {
            TrialBalanceEntry groupEntry = TrialBalanceMapper.MapToTrialBalanceEntry(balanceEntry);

            groupEntry.GroupName      = $"TOTAL GRUPO {balanceEntry.Account.GroupNumber}";
            groupEntry.GroupNumber    = balanceEntry.Account.GroupNumber;
            groupEntry.Account        = StandardAccount.Empty;
            groupEntry.Sector         = Sector.Empty;
            groupEntry.DebtorCreditor = balanceEntry.Account.DebtorCreditor;

            string hash = $"{balanceEntry.Account.GroupNumber}||{balanceEntry.Currency.Id}||{balanceEntry.Sector.Code}";

            GenerateOrIncreaseEntries(totalsListByGroupEntries, groupEntry, StandardAccount.Empty, Sector.Empty,
                                      TrialBalanceItemType.BalanceTotalGroupDebtor, hash);
        }
        internal List <TrialBalanceEntry> GenerateTotalSummaryCurrency(List <TrialBalanceEntry> entries)
        {
            var totalSummaryCurrencies = new EmpiriaHashTable <TrialBalanceEntry>(entries.Count);

            foreach (var debtorOrCreditorEntry in entries.Where(
                         a => a.ItemType == TrialBalanceItemType.BalanceTotalDebtor ||
                         a.ItemType == TrialBalanceItemType.BalanceTotalCreditor))
            {
                SummaryByCurrencyEntries(totalSummaryCurrencies, debtorOrCreditorEntry, StandardAccount.Empty,
                                         Sector.Empty, TrialBalanceItemType.BalanceTotalCurrency);
            }

            entries.AddRange(totalSummaryCurrencies.Values.ToList());

            return(entries);
        }
        internal void SummaryByAccount(EmpiriaHashTable <TrialBalanceEntry> summaryEntries,
                                       TrialBalanceEntry balanceEntry,
                                       StandardAccount targetAccount, Sector targetSector,
                                       TrialBalanceItemType itemType)
        {
            TrialBalanceEntry entry = TrialBalanceMapper.MapToTrialBalanceEntry(balanceEntry);

            entry.Ledger         = Ledger.Empty;
            entry.GroupName      = entry.Account.Name.ToUpper();
            entry.InitialBalance = 0;
            entry.Debit          = 0;
            entry.Credit         = 0;
            entry.CurrentBalance = 0;

            string hash = $"{targetAccount.Number}||{targetSector.Code}||{entry.Currency.Id}||{entry.Ledger.Id}";

            GenerateOrIncreaseEntries(summaryEntries, entry, targetAccount, targetSector, itemType, hash);
        }
        private void SummaryByDebtorCreditorEntries(EmpiriaHashTable <TrialBalanceEntry> summaryEntries,
                                                    TrialBalanceEntry balanceEntry,
                                                    StandardAccount targetAccount, Sector targetSector,
                                                    TrialBalanceItemType itemType)
        {
            TrialBalanceEntry entry = TrialBalanceMapper.MapToTrialBalanceEntry(balanceEntry);

            if (itemType == TrialBalanceItemType.BalanceTotalDebtor)
            {
                entry.GroupName = "TOTAL DEUDORAS " + entry.Currency.FullName;
            }
            else if (itemType == TrialBalanceItemType.BalanceTotalCreditor)
            {
                entry.GroupName = "TOTAL ACREEDORAS " + entry.Currency.FullName;
            }

            string hash = $"{entry.GroupName}||{targetSector.Code}||{entry.Currency.Id}||{entry.Ledger.Id}";

            GenerateOrIncreaseEntries(summaryEntries, entry, targetAccount, targetSector, itemType, hash);
        }
        private void GetDetailSummaryEntries(List <TrialBalanceEntry> detailSummaryEntries,
                                             EmpiriaHashTable <TrialBalanceEntry> summaryEntries,
                                             StandardAccount currentParent, TrialBalanceEntry entry)
        {
            TrialBalanceEntry detailsEntry;
            string            key = $"{currentParent.Number}||{entry.Sector.Code}||{entry.Currency.Id}||{entry.Ledger.Id}";

            summaryEntries.TryGetValue(key, out detailsEntry);
            if (detailsEntry != null)
            {
                var existEntry = detailSummaryEntries.FirstOrDefault(a => a.Ledger.Id == detailsEntry.Ledger.Id &&
                                                                     a.Currency.Id == detailsEntry.Currency.Id &&
                                                                     a.Account.Number == detailsEntry.Account.Number &&
                                                                     a.Sector.Code == detailsEntry.Sector.Code);
                if (existEntry == null)
                {
                    detailSummaryEntries.Add(detailsEntry);
                }
            }
        }
        internal List <TrialBalanceEntry> GenerateTotalSummaryDebtorCreditor(List <TrialBalanceEntry> postingEntries)
        {
            var totalSummaryDebtorCredtor = new EmpiriaHashTable <TrialBalanceEntry>(postingEntries.Count);

            foreach (var entry in postingEntries)
            {
                if (entry.Account.DebtorCreditor == DebtorCreditorType.Deudora)
                {
                    SummaryByDebtorCreditorEntries(totalSummaryDebtorCredtor, entry, StandardAccount.Empty,
                                                   Sector.Empty, TrialBalanceItemType.BalanceTotalDebtor);
                }
                if (entry.Account.DebtorCreditor == DebtorCreditorType.Acreedora)
                {
                    SummaryByDebtorCreditorEntries(totalSummaryDebtorCredtor, entry, StandardAccount.Empty,
                                                   Sector.Empty, TrialBalanceItemType.BalanceTotalCreditor);
                }
            }

            return(totalSummaryDebtorCredtor.Values.ToList());
        }
        internal List <TrialBalanceEntry> CombineTotalConsolidatedByLedgerAndPostingEntries(
            List <TrialBalanceEntry> trialBalance,
            List <TrialBalanceEntry> totalConsolidatedByLedger)
        {
            if (totalConsolidatedByLedger.Count == 0)
            {
                return(trialBalance);
            }
            var returnedEntries   = new List <TrialBalanceEntry>();
            var totalConsolidated = new EmpiriaHashTable <TrialBalanceEntry>();

            foreach (var consolidatedByLedger in totalConsolidatedByLedger)
            {
                var listSummaryByLedger = trialBalance.Where(a => a.Ledger.Id == consolidatedByLedger.Ledger.Id).ToList();
                if (listSummaryByLedger.Count > 0)
                {
                    listSummaryByLedger.Add(consolidatedByLedger);
                    returnedEntries.AddRange(listSummaryByLedger);
                }
            }
            return(returnedEntries);
        }
        internal List <TrialBalanceEntry> GenerateSummaryEntries(FixedList <TrialBalanceEntry> entries)
        {
            var summaryEntries       = new EmpiriaHashTable <TrialBalanceEntry>(entries.Count);
            var detailSummaryEntries = new List <TrialBalanceEntry>();

            foreach (var entry in entries)
            {
                entry.DebtorCreditor         = entry.Account.DebtorCreditor;
                entry.SubledgerAccountNumber = SubsidiaryAccount.Parse(entry.SubledgerAccountId).Number ?? "";
                StandardAccount currentParent;

                if (_command.ReturnSubledgerAccounts)
                {
                    currentParent = entry.Account;
                }
                else if (_command.DoNotReturnSubledgerAccounts && entry.Account.HasParent)
                {
                    currentParent = entry.Account.GetParent();
                }
                else if (_command.DoNotReturnSubledgerAccounts && entry.Account.NotHasParent)
                {
                    continue;
                }
                else
                {
                    throw Assertion.AssertNoReachThisCode();
                }

                int cont = 0;
                while (true)
                {
                    entry.DebtorCreditor           = entry.Account.DebtorCreditor;
                    entry.SubledgerAccountIdParent = entry.SubledgerAccountId;

                    SummaryByEntry(summaryEntries, entry, currentParent, entry.Sector,
                                   TrialBalanceItemType.BalanceSummary);

                    cont++;
                    if (cont == 1 && _command.TrialBalanceType == TrialBalanceType.SaldosPorCuenta)
                    {
                        GetDetailSummaryEntries(detailSummaryEntries, summaryEntries, currentParent, entry);
                    }

                    if (!currentParent.HasParent && entry.HasSector)
                    {
                        SummaryByEntry(summaryEntries, entry, currentParent, Sector.Empty,
                                       TrialBalanceItemType.BalanceSummary);
                        break;
                    }
                    else if (!currentParent.HasParent)
                    {
                        break;
                    }
                    else
                    {
                        currentParent = currentParent.GetParent();
                    }
                } // while
            }     // foreach

            if (detailSummaryEntries.Count > 0 && _command.TrialBalanceType == TrialBalanceType.SaldosPorCuenta)
            {
                return(detailSummaryEntries);
            }
            return(summaryEntries.Values.ToList());
        }