private async Task <AccountingDocument> CreateAccountingDocumentForFxDeal(bool postOpClosedPolicy, long docId, int docTypeId, AccountingSetupDto accountingSetup, Company company, string companyId, DateTime companyDate)
        {
            AccountingDocument      accountingDocument   = new AccountingDocument();
            FxSettlementDocumentDto fxSettlementDocument = null;
            FxRateInformation       fxRates = null;

            fxSettlementDocument = await _accountingQueries.GetFxSettlementbyTransactionDocumentId(docId, company.CompanyId);

            if (fxSettlementDocument.FxSettlementDocumentTypeId == FxSettlementDocumentType.FxDeal)
            {
                fxRates = CommonRules.GetFxRateInformation(fxSettlementDocument.DocumentDate, fxSettlementDocument.CurrencyCode, company);
            }
            else
            {
                fxRates = CommonRules.GetFxRateInformation(fxSettlementDocument.DocumentDate, fxSettlementDocument.SettlementCurrencyCode, company);
            }

            if (fxSettlementDocument != null && fxRates.AreAllFilled())
            {
                accountingDocument = await CommonRules.CreateAccountingDocument(_masterDataService, _identityService.GetUserAtlasId(), postOpClosedPolicy, docId, docTypeId, CommonRules.BaseCurrency, fxRates.FxRateInvoiceCurrency, accountingSetup, null, null, null, null, null, null, null, null, fxSettlementDocument);

                accountingDocument.AccountingPeriod = CommonRules.CalculateAccountPeriod(accountingSetup, fxSettlementDocument.DocumentDate, postOpClosedPolicy);
                accountingDocument.AccrualNumber    = CommonRules.IsLastMonthForOperationOpen(accountingSetup.LastMonthClosedForOperation, fxSettlementDocument.DocumentDate) ?
                                                      fxSettlementDocument.AccrualNumber :
                                                      null;
                accountingDocument.AccountingDate = accountingDocument.DocumentDate.Year == accountingDocument.AccountingPeriod.Year &&
                                                    accountingDocument.DocumentDate.Month == accountingDocument.AccountingPeriod.Month ?
                                                    accountingDocument.DocumentDate :
                                                    new DateTime(accountingDocument.AccountingPeriod.Year, accountingDocument.AccountingPeriod.Month, 1);

                if (accountingDocument != null)
                {
                    accountingDocument.AccountingDocumentLines = await CreateAccountingDocumentLines(docTypeId, company, accountingSetup, fxRates, null, null, null, null, null, null, null, fxSettlementDocument);

                    accountingDocument.StatusId = await CommonRules.GetAccountingDocumentStatus(accountingSetup, _accountingQueries, accountingDocument, company.CompanyId, companyDate, null, null);
                }
            }

            return(accountingDocument);
        }
        private async Task UpdateFxDealInformation(long companyId, long docId, long accountingDocumentId, string company)
        {
            FxSettlementDocumentDto fxSettlementDocument = null;

            _unitOfWork.BeginTransaction();
            try
            {
                fxSettlementDocument = await _accountingQueries.GetFxSettlementbyTransactionDocumentId(docId, company);

                await _accountingDocumentRepository.CreateAccountingDocumentFxSettlement(
                    accountingDocumentId,
                    company,
                    string.Concat(fxSettlementDocument.CurrencyCode, "_", fxSettlementDocument.SettlementCurrencyCode),
                    fxSettlementDocument.Reference);

                _unitOfWork.Commit();
            }
            catch (Exception ex)
            {
                _unitOfWork.Rollback();
                throw;
            }
        }
        private async Task <AccountingDocumentLine> CreateAccountingDocumentLineForFJDocument(int docTypeId, int postingLineId, AccountingSetupDto accountingSetup, AccountLineType lineType, Company company, FxRateInformation fxRates, FxSettlementDocumentDto fxSettlementDocument)
        {
            AccountingDocumentLine accountingDocumentLine = new AccountingDocumentLine();

            accountingDocumentLine.PostingLineId       = postingLineId;
            accountingDocumentLine.AssociatedAccountId = fxSettlementDocument.CounterpartyId;
            accountingDocumentLine.DepartmentId        = fxSettlementDocument.DepartmentId;
            if (fxSettlementDocument.IsNdf)
            {
                accountingDocumentLine.Narrative = string.Concat(
                    Convert.ToString(fxSettlementDocument.Reference),
                    " ",
                    fxSettlementDocument.Memorandum,
                    " NDF ", ((DateTime)fxSettlementDocument.NdfAgreedDate).ToString("dd MMM yyyy"));
            }
            else
            {
                accountingDocumentLine.Narrative = string.Concat(
                    Convert.ToString(fxSettlementDocument.Reference),
                    " ",
                    fxSettlementDocument.Memorandum);
            }
            accountingDocumentLine.AccountLineTypeId          = (int)lineType;
            accountingDocumentLine.DepartmentId               = fxSettlementDocument.DepartmentId;
            accountingDocumentLine.AccountingCategoryId       = (int)AccountingCategory.N;
            accountingDocumentLine.TransactionDocumentId      = (int)DocumentType.FJ;
            accountingDocumentLine.CostTypeCode               = accountingSetup.FXReval;
            accountingDocumentLine.SecondaryDocumentReference = fxSettlementDocument.DocumentReference;
            accountingDocumentLine.AssociatedAccountId        = fxSettlementDocument.BrokerId;

            if (fxSettlementDocument.FxSettlementDocumentTypeId != FxSettlementDocumentType.FxDeal)
            {
                accountingDocumentLine.Amount = Math.Round(
                    CalculateFxDealAmountForSettlementCurrency(
                        fxSettlementDocument.Amount,
                        fxSettlementDocument.SpotRate,
                        fxSettlementDocument.FwPoints,
                        fxSettlementDocument.SpotRateType),
                    CommonRules.RoundDecimals);

                if (fxSettlementDocument.IsNdf)
                {
                    accountingDocumentLine.SecondaryDocumentReference = null;

                    decimal dealtAmount = fxSettlementDocument.Amount;

                    decimal settledAmount = accountingDocumentLine.Amount;

                    switch (lineType)
                    {
                    case AccountLineType.B:
                        if (fxSettlementDocument.DealDirectionId == (int)FxDealDirection.Buy)
                        {
                            settledAmount = -1 * settledAmount;
                        }
                        else
                        {
                            dealtAmount = -1 * dealtAmount;
                        }
                        break;

                    case AccountLineType.L:
                        if (fxSettlementDocument.DealDirectionId == (int)FxDealDirection.Buy)
                        {
                            dealtAmount = -1 * dealtAmount;
                        }
                        else
                        {
                            settledAmount = -1 * settledAmount;
                        }
                        break;

                    default:
                        throw new Exception("Unable to create document header and lines.");
                    }

                    if (fxSettlementDocument.CurrencyCode == "USD" && fxSettlementDocument.SettlementCurrencyCode != "USD")
                    {
                        FxRate fxRateUSD = await _masterDataService.GetFxRateAsync((DateTime)fxSettlementDocument.NdfAgreedDate, fxSettlementDocument.SettlementCurrencyCode);

                        if (fxRateUSD.CurrencyRoeType == "M")
                        {
                            accountingDocumentLine.Amount = fxSettlementDocument.NdfAgreedRate == null?Math.Round((dealtAmount / (decimal)fxRateUSD.Rate) + settledAmount, CommonRules.RoundDecimals) : Math.Round((dealtAmount / (decimal)fxSettlementDocument.NdfAgreedRate) + settledAmount, CommonRules.RoundDecimals);
                        }
                        else
                        {
                            accountingDocumentLine.Amount = fxSettlementDocument.NdfAgreedRate == null?Math.Round((dealtAmount * (decimal)fxRateUSD.Rate) + settledAmount, CommonRules.RoundDecimals) : Math.Round((dealtAmount * (decimal)fxSettlementDocument.NdfAgreedRate) + settledAmount, CommonRules.RoundDecimals);
                        }
                    }
                    else if (fxSettlementDocument.CurrencyCode != "USD" && fxSettlementDocument.SettlementCurrencyCode == "USD")
                    {
                        FxRate fxRateUSD = await _masterDataService.GetFxRateAsync((DateTime)fxSettlementDocument.NdfAgreedDate, fxSettlementDocument.CurrencyCode);

                        if (fxRateUSD.CurrencyRoeType == "D")
                        {
                            accountingDocumentLine.Amount = fxSettlementDocument.NdfAgreedRate == null?Math.Round((dealtAmount / (decimal)fxRateUSD.Rate) + settledAmount, CommonRules.RoundDecimals) : Math.Round((dealtAmount / (decimal)fxSettlementDocument.NdfAgreedRate) + settledAmount, CommonRules.RoundDecimals);
                        }
                        else
                        {
                            accountingDocumentLine.Amount = fxSettlementDocument.NdfAgreedRate == null?Math.Round((dealtAmount * (decimal)fxRateUSD.Rate) + settledAmount, CommonRules.RoundDecimals) : Math.Round((dealtAmount * (decimal)fxSettlementDocument.NdfAgreedRate) + settledAmount, CommonRules.RoundDecimals);
                        }
                    }
                    else if (fxSettlementDocument.CurrencyCode != "USD" && fxSettlementDocument.SettlementCurrencyCode != "USD")
                    {
                        FxRate fxRateUSD1 = await _masterDataService.GetFxRateAsync((DateTime)fxSettlementDocument.NdfAgreedDate, fxSettlementDocument.CurrencyCode);

                        FxRate fxRateUSD2 = await _masterDataService.GetFxRateAsync((DateTime)fxSettlementDocument.NdfAgreedDate, fxSettlementDocument.SettlementCurrencyCode);

                        decimal crossSettlementROESettCcy = 1;

                        if (fxSettlementDocument.NdfAgreedRate == null)
                        {
                            if (fxRateUSD1.CurrencyRoeType == "M" && fxRateUSD2.CurrencyRoeType == "M")
                            {
                                crossSettlementROESettCcy = (decimal)fxRateUSD1.Rate / (decimal)fxRateUSD2.Rate;
                            }
                            else if (fxRateUSD1.CurrencyRoeType == "M" && fxRateUSD2.CurrencyRoeType == "D")
                            {
                                crossSettlementROESettCcy = (decimal)fxRateUSD1.Rate * (decimal)fxRateUSD2.Rate;
                            }
                            else if (fxRateUSD1.CurrencyRoeType == "D" && fxRateUSD2.CurrencyRoeType == "M")
                            {
                                crossSettlementROESettCcy = (1 / (decimal)fxRateUSD1.Rate) / (decimal)fxRateUSD2.Rate;
                            }
                            else
                            {
                                crossSettlementROESettCcy = (decimal)fxRateUSD2.Rate / (decimal)fxRateUSD1.Rate;
                            }
                        }
                        else
                        {
                            crossSettlementROESettCcy = (decimal)fxSettlementDocument.NdfAgreedRate;
                        }

                        accountingDocumentLine.Amount = Math.Round((dealtAmount * crossSettlementROESettCcy) - settledAmount, CommonRules.RoundDecimals);
                    }
                    else
                    {
                        accountingDocumentLine.Amount = Math.Round(dealtAmount + settledAmount, CommonRules.RoundDecimals);
                    }
                }
            }
            else
            {
                accountingDocumentLine.Amount = Math.Round(fxSettlementDocument.Amount, CommonRules.RoundDecimals);
            }

            // Amount conversion for StaturoyCurrency and FunctionalCurrency
            decimal?amountInUSD = accountingDocumentLine.Amount;

            if (fxSettlementDocument.CurrencyCode != null && fxSettlementDocument.CurrencyCode.ToUpperInvariant() != CommonRules.BaseCurrency)
            {
                amountInUSD = (await _foreignExchangeRateService.Convert(fxSettlementDocument.CurrencyCode, CommonRules.BaseCurrency, accountingDocumentLine.Amount, fxSettlementDocument.DocumentDate)).ConvertedValue;
                if (amountInUSD != null)
                {
                    amountInUSD = Math.Round((decimal)amountInUSD, CommonRules.RoundDecimals);
                }
            }

            accountingDocumentLine.StatutoryCurrency  = amountInUSD;
            accountingDocumentLine.FunctionalCurrency = amountInUSD;

            if (company.StatutoryCurrencyCode != null && amountInUSD != null && company.StatutoryCurrencyCode.ToUpperInvariant() != CommonRules.BaseCurrency)
            {
                accountingDocumentLine.StatutoryCurrency = (await _foreignExchangeRateService.Convert(CommonRules.BaseCurrency, company.StatutoryCurrencyCode, (decimal)amountInUSD, fxSettlementDocument.DocumentDate)).ConvertedValue;
            }

            if (company.FunctionalCurrencyCode != null && amountInUSD != null && company.FunctionalCurrencyCode.ToUpperInvariant() != CommonRules.BaseCurrency)
            {
                accountingDocumentLine.FunctionalCurrency = (await _foreignExchangeRateService.Convert(CommonRules.BaseCurrency, company.FunctionalCurrencyCode, (decimal)amountInUSD, fxSettlementDocument.DocumentDate)).ConvertedValue;
            }

            // the default rounding option for .NET is MidPointRounding.ToEven, but that this option does not produce the desired result for some of values: -1119.965 was getting rounded to -1119.96 instead of -1119.97
            if (accountingDocumentLine.StatutoryCurrency != null)
            {
                accountingDocumentLine.StatutoryCurrency = Math.Round((decimal)accountingDocumentLine.StatutoryCurrency, CommonRules.RoundDecimals, MidpointRounding.AwayFromZero);
            }

            if (accountingDocumentLine.FunctionalCurrency != null)
            {
                accountingDocumentLine.FunctionalCurrency = Math.Round((decimal)accountingDocumentLine.FunctionalCurrency, CommonRules.RoundDecimals, MidpointRounding.AwayFromZero);
            }

            accountingDocumentLine.AccountReference = await GetAccountReferenceForFJDocument(
                lineType,
                company,
                fxSettlementDocument);

            if (!fxSettlementDocument.IsNdf)
            {
                switch (lineType)
                {
                case AccountLineType.B:
                    if (fxSettlementDocument.DealDirectionId == (int)FxDealDirection.Buy)
                    {
                        if (fxSettlementDocument.FxSettlementDocumentTypeId == FxSettlementDocumentType.FxDeal)
                        {
                            accountingDocumentLine.Amount = accountingDocumentLine.Amount;
                        }
                        else
                        {
                            accountingDocumentLine.Amount = (-1) * accountingDocumentLine.Amount;
                        }
                    }
                    else
                    {
                        if (fxSettlementDocument.FxSettlementDocumentTypeId == FxSettlementDocumentType.FxDeal)
                        {
                            accountingDocumentLine.Amount = (-1) * accountingDocumentLine.Amount;
                        }
                        else
                        {
                            accountingDocumentLine.Amount = accountingDocumentLine.Amount;
                        }
                    }

                    break;

                case AccountLineType.L:
                    if (fxSettlementDocument.DealDirectionId == (int)FxDealDirection.Buy)
                    {
                        if (fxSettlementDocument.FxSettlementDocumentTypeId == FxSettlementDocumentType.FxDeal)
                        {
                            accountingDocumentLine.Amount = (-1) * accountingDocumentLine.Amount;
                        }
                        else
                        {
                            accountingDocumentLine.Amount = accountingDocumentLine.Amount;
                        }
                    }
                    else
                    {
                        if (fxSettlementDocument.FxSettlementDocumentTypeId == FxSettlementDocumentType.FxDeal)
                        {
                            accountingDocumentLine.Amount = accountingDocumentLine.Amount;
                        }
                        else
                        {
                            accountingDocumentLine.Amount = (-1) * accountingDocumentLine.Amount;
                        }
                    }

                    break;

                default:
                    throw new Exception("Unable to create document header and lines.");
                }
            }

            return(accountingDocumentLine);
        }
        private async Task <string> GetAccountReferenceForFJDocument(
            AccountLineType lineType,
            Company company,
            FxSettlementDocumentDto fxSettlementDocument)
        {
            string         nominalAccountForAccountReference = string.Empty;
            NominalAccount nominalAccount = null;

            switch (lineType)
            {
            case AccountLineType.B:
                nominalAccount = fxSettlementDocument.FxSettlementDocumentTypeId == FxSettlementDocumentType.FxDeal ?
                                 await _masterDataService.GetNominalAccountsById(fxSettlementDocument.NominalAccountId, company.CompanyId) :
                                 await _masterDataService.GetNominalAccountsById(fxSettlementDocument.SettlementNominalAccountId, company.CompanyId);

                nominalAccountForAccountReference = nominalAccount.NominalAccountNumber;
                break;

            case AccountLineType.L:
                var dealthAmount = (await _foreignExchangeRateService.Convert(
                                        CommonRules.BaseCurrency,
                                        fxSettlementDocument.CurrencyCode,
                                        fxSettlementDocument.Amount,
                                        fxSettlementDocument.DocumentDate)).ConvertedValue;
                var settlementAmount = (await _foreignExchangeRateService.Convert(
                                            CommonRules.BaseCurrency,
                                            fxSettlementDocument.SettlementCurrencyCode,
                                            CalculateFxDealAmountForSettlementCurrency(
                                                fxSettlementDocument.Amount,
                                                fxSettlementDocument.SpotRate,
                                                fxSettlementDocument.FwPoints,
                                                fxSettlementDocument.SpotRateType),
                                            fxSettlementDocument.DocumentDate)).ConvertedValue;

                switch (fxSettlementDocument.DealDirectionId)
                {
                case (int)FxDealDirection.Buy:
                    if (dealthAmount < settlementAmount)
                    {
                        // pick the config for FX settlement Loss
                        nominalAccount = await _masterDataService.GetNominalAccountsById(company.SettlementLossNominalId, company.CompanyId);
                    }
                    else
                    {
                        // pick the config for FX settlement Gain
                        nominalAccount = await _masterDataService.GetNominalAccountsById(company.SettlementGainNominalId, company.CompanyId);
                    }

                    nominalAccountForAccountReference = nominalAccount.NominalAccountNumber;

                    break;

                case (int)FxDealDirection.Sell:
                    if (dealthAmount > settlementAmount)
                    {
                        // pick the config for FX settlement Loss
                        nominalAccount = await _masterDataService.GetNominalAccountsById(company.SettlementLossNominalId, company.CompanyId);
                    }
                    else
                    {
                        // pick the config for FX settlement Gain
                        nominalAccount = await _masterDataService.GetNominalAccountsById(company.SettlementGainNominalId, company.CompanyId);
                    }

                    nominalAccountForAccountReference = nominalAccount.NominalAccountNumber;
                    break;
                }

                break;
            }

            return(nominalAccountForAccountReference);
        }
Esempio n. 5
0
        internal static async Task <AccountingDocument> CreateAccountingDocument(
            IMasterDataService masterDataService,
            long userId,
            bool postOpClosedPrivilege,
            long docId,
            int docTypeId,
            string baseCurrency,
            FxRateConversion fxRate,
            AccountingSetupDto accountingSetup,
            InvoiceInformationDto invoiceInformation = null,
            CashInformationDto cashInformation       = null,
            DateTime?blDate = null,
            ManualJournalDocumentDto manualJournal             = null,
            RevaluationInformationDto revalInformation         = null,
            MonthEndTADocumentDto monthEndTADocument           = null,
            CounterpartyInformationDto counterpartyInformation = null,
            CashForCounterpartyDto cashForCounterpartyDto      = null,
            FxSettlementDocumentDto fxSettlementDocument       = null)
        {
            AccountingDocument accountingDocument = new AccountingDocument();

            accountingDocument.UserCreator           = userId;
            accountingDocument.TransactionDocumentId = docId;
            accountingDocument.ProvinceId            = null;
            accountingDocument.OriginalReferenceId   = null;

            if (fxRate.FxCurrency.ToUpperInvariant() == baseCurrency)
            {
                accountingDocument.Roe     = 1;
                accountingDocument.RoeType = "M";
            }
            else
            {
                FxRate fxRateUSD = await masterDataService.GetFxRateAsync(fxRate.FxDate, fxRate.FxCurrency);

                accountingDocument.Roe     = fxRateUSD != null ? fxRateUSD.Rate : null;
                accountingDocument.RoeType = fxRateUSD != null ? fxRateUSD.CurrencyRoeType : null;
            }

            accountingDocument.TransactionDocumentTypeId = docTypeId;
            accountingDocument.AcknowledgementDate       = null;

            switch (docTypeId)
            {
            case (int)DocumentType.PI:
            case (int)DocumentType.SI:
            case (int)DocumentType.CN:
            case (int)DocumentType.DN:
                accountingDocument.CurrencyCode      = invoiceInformation.Currency;
                accountingDocument.AccountingPeriod  = CommonRules.CalculateAccountPeriod(accountingSetup, invoiceInformation.InvoiceDate, postOpClosedPrivilege);
                accountingDocument.DocumentDate      = invoiceInformation.InvoiceDate;
                accountingDocument.ValueDate         = invoiceInformation.InvoiceDueDate;
                accountingDocument.GLDate            = blDate;
                accountingDocument.OriginalValueDate = invoiceInformation.InvoiceDueDate;
                accountingDocument.AccountingDate    = CommonRules.CalculateAccountPeriod(accountingSetup, invoiceInformation.InvoiceDate, postOpClosedPrivilege);

                break;

            case (int)DocumentType.CP:
            case (int)DocumentType.CI:
                if (counterpartyInformation != null && cashForCounterpartyDto.CashTypeId == (int)CashSelectionType.PaymentDifferentClient && cashForCounterpartyDto.JLTypeId == (int)JLType.CounterPartyTransfer)
                {
                    accountingDocument.CurrencyCode      = counterpartyInformation.CurrencyCode;
                    accountingDocument.AccountingPeriod  = CommonRules.CalculateAccountPeriod(accountingSetup, counterpartyInformation.DocumentDate, postOpClosedPrivilege);
                    accountingDocument.DocumentDate      = counterpartyInformation.DocumentDate;
                    accountingDocument.ValueDate         = counterpartyInformation.ValueDate == null ? counterpartyInformation.DocumentDate : (DateTime)counterpartyInformation.ValueDate;
                    accountingDocument.GLDate            = counterpartyInformation.DocumentDate;
                    accountingDocument.OriginalValueDate = counterpartyInformation.ValueDate == null ? counterpartyInformation.DocumentDate : (DateTime)counterpartyInformation.ValueDate;
                    accountingDocument.AccountingDate    = CommonRules.CalculateAccountPeriod(accountingSetup, counterpartyInformation.DocumentDate, postOpClosedPrivilege);
                }
                else
                {
                    accountingDocument.CurrencyCode      = cashInformation.Currency;
                    accountingDocument.AccountingPeriod  = CommonRules.CalculateAccountPeriod(accountingSetup, cashInformation.DocumentDate, postOpClosedPrivilege);
                    accountingDocument.DocumentDate      = cashInformation.DocumentDate;
                    accountingDocument.ValueDate         = cashInformation.ValueDate;
                    accountingDocument.GLDate            = cashInformation.DocumentDate;
                    accountingDocument.OriginalValueDate = cashInformation.ValueDate;
                    accountingDocument.AccountingDate    = CommonRules.CalculateAccountPeriod(accountingSetup, cashInformation.DocumentDate, postOpClosedPrivilege);
                }

                break;

            case (int)DocumentType.MTA:
            case (int)DocumentType.MJL:
                if (monthEndTADocument != null && (monthEndTADocument.TATypeId == (int)TAType.MonthEndTemporaryAdjustment || monthEndTADocument.TATypeId == (int)TAType.FxDealMonthTemporaryAdjustment))
                {
                    accountingDocument.CurrencyCode      = monthEndTADocument.CurrencyCode;
                    accountingDocument.ValueDate         = monthEndTADocument.ValueDate;
                    accountingDocument.DocumentDate      = new DateTime(accountingDocument.ValueDate.Value.Year, accountingDocument.ValueDate.Value.Month, 1).AddDays(-1);
                    accountingDocument.AccountingPeriod  = monthEndTADocument.AccountingPeriod.Value;
                    accountingDocument.GLDate            = monthEndTADocument.MonthEndTALines.FirstOrDefault().BLDate;
                    accountingDocument.OriginalValueDate = (DateTime)monthEndTADocument.ValueDate;
                    accountingDocument.AccountingDate    = accountingDocument.DocumentDate.Year == monthEndTADocument.AccountingPeriod.Value.Year && accountingDocument.DocumentDate.Month == monthEndTADocument.AccountingPeriod.Value.Month ? accountingDocument.DocumentDate : new DateTime(monthEndTADocument.AccountingPeriod.Value.Year, monthEndTADocument.AccountingPeriod.Value.Month, 1);
                }
                else
                {
                    accountingDocument.CurrencyCode      = manualJournal.CurrencyCode;
                    accountingDocument.AccountingPeriod  = manualJournal.AccountingPeriod;
                    accountingDocument.DocumentDate      = manualJournal.DocumentDate;
                    accountingDocument.GLDate            = manualJournal.DocumentDate;
                    accountingDocument.OriginalValueDate = manualJournal.ValueDate == null ? manualJournal.DocumentDate : (DateTime)manualJournal.ValueDate;
                    accountingDocument.AccountingDate    = manualJournal.DocumentDate;

                    if (docTypeId == (int)DocumentType.MTA)
                    {
                        accountingDocument.ValueDate = manualJournal.ValueDate == null ? new DateTime(manualJournal.DocumentDate.Year, manualJournal.DocumentDate.Month, 1).AddMonths(1) : (DateTime)manualJournal.ValueDate;
                    }

                    if (docTypeId == (int)DocumentType.MJL)
                    {
                        accountingDocument.ValueDate = manualJournal.ValueDate == null ? manualJournal.DocumentDate : manualJournal.ValueDate;
                    }
                }

                break;

            case (int)DocumentType.FJ:
                accountingDocument.DocumentReference = fxSettlementDocument.DocumentReference;
                if (fxSettlementDocument.IsNdf)
                {
                    accountingDocument.ValueDate = fxSettlementDocument.NdfAgreedDate;
                }
                else
                {
                    accountingDocument.ValueDate = fxSettlementDocument.MaturityDate;
                }
                accountingDocument.DocumentDate      = fxSettlementDocument.MaturityDate;
                accountingDocument.GLDate            = fxSettlementDocument.MaturityDate;
                accountingDocument.OriginalValueDate = fxSettlementDocument.DocumentDate;
                if (fxSettlementDocument != null && fxSettlementDocument.FxSettlementDocumentTypeId != FxSettlementDocumentType.FxDeal)
                {
                    accountingDocument.CurrencyCode = fxSettlementDocument.SettlementCurrencyCode;
                }
                else
                {
                    accountingDocument.CurrencyCode = fxSettlementDocument.CurrencyCode;
                }

                break;
            }

            return(accountingDocument);
        }
        private async Task <IEnumerable <AccountingDocumentLine> > CreateAccountingDocumentLines(
            int docTypeId, Company company, AccountingSetupDto accountingSetup, FxRateInformation fxRates,
            IEnumerable <Vat> vats = null, InvoiceInformationDto invoiceInformation = null,
            IEnumerable <SectionsInformationDto> sectionsInformation = null, CashInformationDto cashInformation = null,
            ManualJournalDocumentDto manualJournal       = null, RevaluationInformationDto revalInformation     = null,
            MonthEndTADocumentDto monthEndTADocument     = null,
            FxSettlementDocumentDto fxSettlementDocument = null)
        {
            List <AccountingDocumentLine> accountingDocumentLines = new List <AccountingDocumentLine>();

            AccountingDocumentLine accountingDocumentLine;

            int postingLineId = 1;

            switch (docTypeId)
            {
            case (int)DocumentType.PI:
            case (int)DocumentType.SI:
            case (int)DocumentType.CN:
            case (int)DocumentType.DN:

                // Nominal
                InvoiceFunction invoiceFunction = CommonRules.CheckInvoiceType(invoiceInformation.InvoiceType);
                for (int index = 0; index < invoiceInformation.InvoiceLines.Count(); index++)
                {
                    if (invoiceFunction == InvoiceFunction.Washout)
                    {
                        if (invoiceInformation.InvoiceLines.ToList()[index].Type == (int)Entities.ContractType.CommercialSale)
                        {
                            // [WASHOUT_E6] For washout E6, we expect to have only one 1 to 1 washout (ie we must have only one line for a purchase
                            // contract, and one line for a sales contract)
                            // This rule is also implemented in UpdateAccountingDocumentStatusToPostedCommandHandler.CalculateAmountUpdatesForWashoutInvoice
                            accountingDocumentLine = await CreateAccountingDocumentLineForInvoice(AccountingDocumentLineType.Nominal, invoiceInformation, sectionsInformation, vats, company, accountingSetup, fxRates, postingLineId, index, null);

                            accountingDocumentLines.Add(accountingDocumentLine);
                            postingLineId++;
                        }
                    }
                    else if (invoiceFunction == InvoiceFunction.Cancelled)
                    {
                        accountingDocumentLine = await CreateAccountingDocumentLineForInvoice(AccountingDocumentLineType.Nominal, invoiceInformation, sectionsInformation, vats, company, accountingSetup, fxRates, postingLineId, index, null);

                        accountingDocumentLines.Add(accountingDocumentLine);
                        postingLineId++;
                    }
                    else
                    {
                        accountingDocumentLine = await CreateAccountingDocumentLineForInvoice(AccountingDocumentLineType.Nominal, invoiceInformation, sectionsInformation, vats, company, accountingSetup, fxRates, postingLineId, index, null);

                        accountingDocumentLines.Add(accountingDocumentLine);
                        postingLineId++;
                    }
                }

                // Tax
                for (int index = 0; index < vats.Count(); index++)
                {
                    accountingDocumentLine = await CreateAccountingDocumentLineForInvoice(AccountingDocumentLineType.Tax, invoiceInformation, sectionsInformation, vats, company, accountingSetup, fxRates, postingLineId, index, accountingDocumentLines);

                    accountingDocumentLines.Add(accountingDocumentLine);
                    postingLineId++;
                }

                // Client
                accountingDocumentLine = await CreateAccountingDocumentLineForInvoice(AccountingDocumentLineType.Client, invoiceInformation, sectionsInformation, vats, company, accountingSetup, fxRates, postingLineId, 0, accountingDocumentLines);

                accountingDocumentLine.SourceInvoiceId = invoiceInformation.InvoiceId;
                accountingDocumentLines.Add(accountingDocumentLine);

                break;

            case (int)DocumentType.CP:
            case (int)DocumentType.CI:

                AccountingDocumentLine accountingDocumentLineForDocumentReference = new AccountingDocumentLine();

                accountingDocumentLine = await CreateAccountingDocumentLineForSimpleCash(AccountingDocumentLineType.Client, docTypeId, cashInformation, company, fxRates, postingLineId, accountingSetup);

                // Note: this is here for simple cash. There is no secondary reference, as at that time, the cash is no matched...
                accountingDocumentLines.Add(accountingDocumentLine);

                // Nominal
                postingLineId++;
                accountingDocumentLine = await CreateAccountingDocumentLineForSimpleCash(AccountingDocumentLineType.Nominal, docTypeId, cashInformation, company, fxRates, postingLineId, accountingSetup);

                accountingDocumentLines.Add(accountingDocumentLine);

                if (cashInformation.AdditionalCosts != null && cashInformation.AdditionalCosts.Any())
                {
                    for (int index = 0; index < cashInformation.AdditionalCosts.Count(); index++)
                    {
                        postingLineId++;
                        AccountingDocumentLine accountingDocumentLineForAdditionalCosts = new AccountingDocumentLine();
                        AdditionalCostsDto     additionalCostsDto = cashInformation.AdditionalCosts.ToList()[index];
                        accountingDocumentLineForAdditionalCosts.PostingLineId         = postingLineId;
                        accountingDocumentLineForAdditionalCosts.AccountLineTypeId     = (int)AccountLineType.L;
                        accountingDocumentLineForAdditionalCosts.Amount                = additionalCostsDto.CostDirectionId == (int)Entities.CostDirectionType.Pay ? cashInformation.AdditionalCosts.ToList()[index].Amount : -cashInformation.AdditionalCosts.ToList()[index].Amount;
                        accountingDocumentLineForAdditionalCosts.AccountReference      = additionalCostsDto.AccountReference;
                        accountingDocumentLineForAdditionalCosts.CostTypeCode          = additionalCostsDto.CostTypeCode;
                        accountingDocumentLineForAdditionalCosts.AssociatedAccountCode = accountingDocumentLine.AssociatedAccountCode;
                        accountingDocumentLineForAdditionalCosts.DepartmentId          = accountingDocumentLine.DepartmentId;
                        accountingDocumentLineForAdditionalCosts.Narrative             = additionalCostsDto.Narrative;
                        accountingDocumentLineForAdditionalCosts.AccountingCategoryId  = (int)AccountingCategory.N;
                        accountingDocumentLineForAdditionalCosts.Amount                = Math.Round(accountingDocumentLineForAdditionalCosts.Amount, CommonRules.RoundDecimals);
                        accountingDocumentLineForAdditionalCosts.ClientAccount         = null;
                        accountingDocumentLineForAdditionalCosts.SourceCostLineId      = cashInformation.AdditionalCosts.ToList()[index].CashAdditionalCostId;
                        decimal?amountInUSD = accountingDocumentLineForAdditionalCosts.Amount;

                        if (additionalCostsDto.CurrencyCode != null && additionalCostsDto.CurrencyCode.ToUpperInvariant() != CommonRules.BaseCurrency)
                        {
                            amountInUSD = (await _foreignExchangeRateService.Convert(additionalCostsDto.CurrencyCode, CommonRules.BaseCurrency, accountingDocumentLineForAdditionalCosts.Amount, cashInformation.DocumentDate)).ConvertedValue;
                        }

                        accountingDocumentLineForAdditionalCosts = await CommonRules.CalculateFunctionalAndStatutoryCurrency(_foreignExchangeRateService, accountingDocumentLineForAdditionalCosts, amountInUSD, fxRates, company, CommonRules.BaseCurrency, CommonRules.RoundDecimals);

                        accountingDocumentLines.Add(accountingDocumentLineForAdditionalCosts);
                    }
                }

                break;

            case (int)DocumentType.MJL:
                foreach (ManualJournalLineDto manualJournalLine in manualJournal.ManualJournalLines)
                {
                    accountingDocumentLine = await CreateAccountingDocumentLineForManualJournal(docTypeId, company, manualJournal, fxRates, manualJournalLine, postingLineId, accountingSetup);

                    accountingDocumentLines.Add(accountingDocumentLine);
                    postingLineId++;
                }

                break;

            case (int)DocumentType.MTA:

                if (manualJournal != null && (manualJournal.TATypeId == (int)TAType.ManualTemporaryAdjustment || manualJournal.TATypeId == (int)TAType.ManualMarkToMarket))
                {
                    IEnumerable <ManualJournalLineDto> manualJournalLines = manualJournal.ManualJournalLines.OrderBy(x => x.AccrualNumber);

                    int?previousAccuralNumber = manualJournal.ManualJournalLines.FirstOrDefault().AccrualNumber;

                    foreach (ManualJournalLineDto manualJournalLine in manualJournalLines)
                    {
                        if (previousAccuralNumber != manualJournalLine.AccrualNumber)
                        {
                            postingLineId         = 1;
                            previousAccuralNumber = manualJournalLine.AccrualNumber;
                        }

                        accountingDocumentLine = await CreateAccountingDocumentLineForManualJournal(docTypeId, company, manualJournal, fxRates, manualJournalLine, postingLineId, accountingSetup);

                        accountingDocumentLines.Add(accountingDocumentLine);

                        if (previousAccuralNumber == manualJournalLine.AccrualNumber)
                        {
                            postingLineId++;
                        }

                        previousAccuralNumber = manualJournalLine.AccrualNumber;
                    }
                }

                else if (monthEndTADocument != null && (monthEndTADocument.TATypeId == (int)TAType.MonthEndTemporaryAdjustment || monthEndTADocument.TATypeId == (int)TAType.FxDealMonthTemporaryAdjustment))
                {
                    IEnumerable <MonthEndTALineDto> monthEndLines = monthEndTADocument.MonthEndTALines.OrderBy(x => x.AccrualNumber);

                    foreach (MonthEndTALineDto monthEndLine in monthEndLines)
                    {
                        accountingDocumentLine = await CreateAccountingDocumentLineForMonthEndTA(docTypeId, company, monthEndTADocument, fxRates, monthEndLine, postingLineId);

                        if (monthEndTADocument.TATypeId == (int)TAType.FxDealMonthTemporaryAdjustment)
                        {
                            postingLineId++;
                            accountingDocumentLine.AccountingCategoryId = (int)AccountingCategory.N;
                            accountingDocumentLine.AccountLineTypeId    = (int)AccountLineType.L;
                        }

                        accountingDocumentLines.Add(accountingDocumentLine);
                    }
                }

                break;

            case (int)DocumentType.FJ:
                accountingDocumentLine = await CreateAccountingDocumentLineForFJDocument(docTypeId, postingLineId, accountingSetup, AccountLineType.B, company, fxRates, fxSettlementDocument);

                accountingDocumentLines.Add(accountingDocumentLine);
                postingLineId++;

                accountingDocumentLine = await CreateAccountingDocumentLineForFJDocument(docTypeId, postingLineId, accountingSetup, AccountLineType.L, company, fxRates, fxSettlementDocument);

                accountingDocumentLines.Add(accountingDocumentLine);
                break;
            }

            return(accountingDocumentLines);
        }