internal static async Task <AccountingDocument> CalculateFunctionalAndStatutoryCurrencyAccountingLine(IForeignExchangeRateService foreignExchangeRateService, AccountingDocument document) { AccountingDocument accountingDocumentStatus = new AccountingDocument(); accountingDocumentStatus.AccountingId = document.AccountingId; foreach (AccountingDocumentLine documentLine in document.AccountingDocumentLines) { documentLine.Amount = Math.Round(documentLine.Amount, CommonRules.RoundDecimals); decimal?amountInUSD = documentLine.Amount; if (document.CurrencyCode != null && document.CurrencyCode.ToUpperInvariant() != CommonRules.BaseCurrency) { var result = await foreignExchangeRateService.Convert(document.CurrencyCode, CommonRules.BaseCurrency, documentLine.Amount, (DateTime)document.GLDate); amountInUSD = result.ConvertedValue; document.Roe = result.Rate; } if (amountInUSD != null) { documentLine.StatutoryCurrency = amountInUSD; if (document.StatutoryCurrencyCode != null && document.StatutoryCurrencyCode.ToUpperInvariant() != CommonRules.BaseCurrency) { var result = await foreignExchangeRateService.Convert(CommonRules.BaseCurrency, document.StatutoryCurrencyCode, (decimal)amountInUSD, (DateTime)document.GLDate); documentLine.StatutoryCurrency = result.ConvertedValue; } documentLine.FunctionalCurrency = amountInUSD; if (document.FunctionalCurrencyCode != null && document.FunctionalCurrencyCode.ToUpperInvariant() != CommonRules.BaseCurrency) { var result = await foreignExchangeRateService.Convert(CommonRules.BaseCurrency, document.FunctionalCurrencyCode, (decimal)amountInUSD, (DateTime)document.GLDate); documentLine.FunctionalCurrency = result.ConvertedValue; } if (documentLine.StatutoryCurrency != null) { documentLine.StatutoryCurrency = Math.Round((decimal)documentLine.StatutoryCurrency, CommonRules.RoundDecimals, MidpointRounding.AwayFromZero); // 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 (documentLine.FunctionalCurrency != null) { documentLine.FunctionalCurrency = Math.Round((decimal)documentLine.FunctionalCurrency, CommonRules.RoundDecimals, MidpointRounding.AwayFromZero); // 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 } } else { documentLine.FunctionalCurrency = null; documentLine.StatutoryCurrency = null; } } return(document); }
internal static async Task <AccountingDocumentLine> CalculateFunctionalAndStatutoryCurrency(IForeignExchangeRateService foreignExchangeRateService, AccountingDocumentLine accountingDocumentLine, decimal?amountInUSD, FxRateInformation fxRates, Company company, string baseCurrency, int decimals) { if (amountInUSD != null) { amountInUSD = Math.Round((decimal)amountInUSD, decimals); accountingDocumentLine.StatutoryCurrency = amountInUSD; if (company.StatutoryCurrencyCode != null && amountInUSD != null && company.StatutoryCurrencyCode.ToUpperInvariant() != baseCurrency) { accountingDocumentLine.StatutoryCurrency = (await foreignExchangeRateService.Convert(baseCurrency, fxRates.FxRateStatutoryCurrency.FxCurrency, (decimal)amountInUSD, fxRates.FxRateStatutoryCurrency.FxDate)).ConvertedValue; } accountingDocumentLine.FunctionalCurrency = amountInUSD; if (company.FunctionalCurrencyCode != null && amountInUSD != null && company.FunctionalCurrencyCode.ToUpperInvariant() != baseCurrency) { accountingDocumentLine.FunctionalCurrency = (await foreignExchangeRateService.Convert(baseCurrency, fxRates.FxRateFunctionalCurrency.FxCurrency, (decimal)amountInUSD, fxRates.FxRateFunctionalCurrency.FxDate)).ConvertedValue; } if (accountingDocumentLine.StatutoryCurrency != null) { accountingDocumentLine.StatutoryCurrency = Math.Round((decimal)accountingDocumentLine.StatutoryCurrency, decimals, MidpointRounding.AwayFromZero); // 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.FunctionalCurrency != null) { accountingDocumentLine.FunctionalCurrency = Math.Round((decimal)accountingDocumentLine.FunctionalCurrency, decimals, MidpointRounding.AwayFromZero); // 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 } } else { accountingDocumentLine.StatutoryCurrency = null; accountingDocumentLine.FunctionalCurrency = null; } return(accountingDocumentLine); }
private async Task <AccountingDocument> MapCommandToAccountingDocument(UpdateAccountingDocumentCommand command) { AccountingDocument accountingDocument = new AccountingDocument(); accountingDocument.AccountingPeriod = command.AccountingPeriod; accountingDocument.AccountingId = command.AccountingId; accountingDocument.CurrencyCode = command.CurrencyCode; accountingDocument.DocumentDate = command.DocumentDate; accountingDocument.ValueDate = command.ValueDate; accountingDocument.ToInterface = command.ToInterface; accountingDocument.DmsId = command.DmsId; accountingDocument.TransactionDocumentTypeId = (int)command.TransactionDocumentTypeId; if (command.StatusId == PostingStatus.Posted) { accountingDocument.StatusId = command.StatusId; } else if (!command.IsAuthorizedControlEnabled) { accountingDocument.StatusId = PostingStatus.Incomplete; } accountingDocument.AccountingDocumentLines = command.AccountingDocumentLines; Company company = await _masterDataService.GetCompanyByIdAsync(command.Company); var fxRates = CommonRules.GetFxRateInformation(accountingDocument.DocumentDate, accountingDocument.CurrencyCode, company); if (fxRates.FxRateInvoiceCurrency != null) { foreach (AccountingDocumentLine accountingDocumentLine in accountingDocument.AccountingDocumentLines) { if (accountingDocumentLine.AccountingCategoryId <= 0 && accountingDocumentLine.AccountLineTypeId >= 1) { if (accountingDocumentLine.AccountLineTypeId == (int)AccountLineType.C || accountingDocumentLine.AccountLineTypeId == (int)AccountLineType.V) { accountingDocumentLine.AccountingCategoryId = (int)AccountingCategory.C; } else if (accountingDocumentLine.AccountLineTypeId == (int)AccountLineType.B || accountingDocumentLine.AccountLineTypeId == (int)AccountLineType.L) { accountingDocumentLine.AccountingCategoryId = (int)AccountingCategory.N; } } if (string.IsNullOrEmpty(accountingDocumentLine.Narrative) && accountingDocument.TransactionDocumentTypeId == (int)DocumentType.MTA) { accountingDocumentLine.Narrative = "Manual Accrual of " + accountingDocument.AccountingPeriod.ToString("MMM-yyyy", CultureInfo.InvariantCulture); } accountingDocumentLine.Amount = Math.Round(accountingDocumentLine.Amount, CommonRules.RoundDecimals); decimal?amountInUSD = accountingDocumentLine.Amount; if (accountingDocument.CurrencyCode != null && accountingDocument.CurrencyCode.ToUpperInvariant() != CommonRules.BaseCurrency) { amountInUSD = (await _foreignExchangeRateService.Convert(fxRates.FxRateInvoiceCurrency.FxCurrency, CommonRules.BaseCurrency, accountingDocumentLine.Amount, fxRates.FxRateInvoiceCurrency.FxDate)).ConvertedValue; } await CommonRules.CalculateFunctionalAndStatutoryCurrency(_foreignExchangeRateService, accountingDocumentLine, amountInUSD, fxRates, company, CommonRules.BaseCurrency, CommonRules.RoundDecimals); } } accountingDocument.GLDate = command.GLDate; 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); }
public async Task <ActionResult <Atlas.MasterData.Common.Entities.FxRateConvertResult> > Convert([FromQuery][Required] string currencyCodeFrom, [FromQuery][Required] string currencyCodeTo, [FromQuery][Required] decimal value, DateTime?fxRateDate) { var result = await _foreignExchangeRateService.Convert(currencyCodeFrom, currencyCodeTo, value, fxRateDate); return(result); }