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); }