private void EnsureValidityForExport(DataProvider.Models.Invoice invoice) { if (invoice.Number == null) { throw new InvalidDataException($"Invoice {invoice.Id} doesn't have an invoice date and cannot be exported."); } if (invoice.InvoiceDate == null) { throw new InvalidDataException($"Invoice {invoice.Id} doesn't have an invoice date and cannot be exported."); } if (invoice.DueDate == null) { throw new InvalidDataException($"Invoice {invoice.Id} doesn't have a due date and cannot be exported."); } if (invoice.Amount == null) { throw new InvalidDataException($"Invoice {invoice.Id} doesn't have an amount and cannot be exported."); } if (invoice.Vat == null) { throw new InvalidDataException($"Invoice {invoice.Id} doesn't have a VAT amount and cannot be exported."); } if (invoice.TotalAmount == null) { throw new InvalidDataException($"Invoice {invoice.Id} doesn't have a total amount and cannot be exported."); } }
private async Task CalculateAmountAndVatAsync(DataProvider.Models.Invoice invoice) { _logger.LogDebug("Recalculating amount and VAT of invoice {0}", invoice.Id); var depositInvoicesTotal = 0.0; if (invoice.OrderId != null) { var query = new QuerySet(); query.Page.Size = 1000; // TODO we assume 1 order doesn't have more than 1000 deposit invoices. Ideally, we should query by page. // don't GetByInvoiceId because invoice might not be persisted yet var depositInvoices = await _depositInvoiceDataProvider.GetAllByOrderIdAsync((int)invoice.OrderId, query); depositInvoicesTotal = depositInvoices.Items.Select(s => s.IsCreditNote ? s.Amount * -1.0 : s.Amount).Sum() ?? 0.0; } var baseAmount = invoice.BaseAmount ?? 0.0; // sum of invoicelines (as calculated by frontend) var amount = baseAmount - depositInvoicesTotal; var vat = 0.0; if (invoice.VatRateId != null) { // don't GetByInvoiceId because invoice might not be persisted yet var vatRate = await _vatRateDataProvider.GetByIdAsync((int)invoice.VatRateId); vat = amount * (vatRate.Rate / 100.0); } invoice.Amount = amount; // sum of base amount - all deposit invoices invoice.Vat = vat; // vat calculated on amount invoice.TotalAmount = amount + vat; // gross amount _logger.LogDebug("Recalculated amount of invoice {0}: amount {1}} ; vat {2} ; total amount {3}", invoice.Id, invoice.Amount, invoice.Vat, invoice.TotalAmount); }
private async Task CalculateAmountAndVatAsync(DataProvider.Models.Invoice invoice) { _logger.LogDebug("Recalculating amount and VAT of invoice {0}", invoice.Id); var depositInvoicesTotal = 0.0; if (invoice.OrderId != null) { var query = new QuerySet(); query.Page.Size = 1000; // TODO we assume 1 order doesn't have more than 1000 deposit invoices. Ideally, we should query by page. // don't GetByInvoiceId because invoice might not be persisted yet var depositInvoices = await _depositInvoiceDataProvider.GetAllByOrderIdAsync((int)invoice.OrderId, query); depositInvoicesTotal = depositInvoices.Items.Select(s => s.Amount).Sum() ?? 0.0; } var invoiceSupplementsTotal = 0.0; if (invoice.Id != 0) // invoice supplements can only be attached to an existing invoice { var query = new QuerySet(); query.Page.Size = 1000; // TODO we assume 1 invoice doesn't have more than 1000 supplements. Ideally, we should query by page. var invoiceSupplements = await _invoiceSupplementDataProvider.GetAllByInvoiceIdAsync(invoice.Id, query); invoiceSupplementsTotal = invoiceSupplements.Items.Select(s => s.Amount).Sum() ?? 0.0; } var baseAmount = invoice.BaseAmount ?? 0.0; var amount = baseAmount + invoiceSupplementsTotal - depositInvoicesTotal; var vat = 0.0; if (invoice.VatRateId != null) { // don't GetByInvoiceId because invoice might not be persisted yet var vatRate = await _vatRateDataProvider.GetByIdAsync((int)invoice.VatRateId); vat = amount * (vatRate.Rate / 100.0); } invoice.Amount = amount; // sum of base amount + all invoice supplements - all deposit invoices invoice.Vat = vat; // vat calculated on amount invoice.TotalAmount = amount + vat; // gross amount }
private async Task CalculateAmountAndVatAsync(DataProvider.Models.Invoice depositInvoice) { _logger.LogDebug("Recalculating amount and VAT of deposit invoice {0}", depositInvoice.Id); var amount = depositInvoice.BaseAmount ?? 0.0; var vat = 0.0; if (depositInvoice.VatRateId != null) { // don't GetByInvoiceId because invoice might not be persisted yet var vatRate = await _vatRateDataProvider.GetByIdAsync((int)depositInvoice.VatRateId); vat = amount * (vatRate.Rate / 100.0); } depositInvoice.Amount = amount; // base amount depositInvoice.Vat = vat; // vat calculated on amount depositInvoice.TotalAmount = amount + vat; // gross amount }
private IEnumerable <object> GenerateInvoiceExportLines(DataProvider.Models.Invoice invoice) { var invoiceDate = (DateTime)invoice.InvoiceDate; var invoiceDateStr = invoiceDate.ToString("yyyyMMdd", CultureInfo.InvariantCulture); var dueDate = invoice.DueDate != null ? (DateTime)invoice.DueDate : (DateTime)invoice.InvoiceDate; var dueDateStr = dueDate.ToString("yyyyMMdd", CultureInfo.InvariantCulture); var startYear = Int32.Parse(_accountancyConfig.WinbooksStart); var bookYear = GetBookYear(invoiceDate, startYear); var startBookYear = Int32.Parse(_accountancyConfig.WinbooksBookYear); var startMonth = startBookYear >= 100 ? startBookYear / 100 : 0; var period = GetPeriod(invoiceDate, startMonth); var amount = Math.Round((double)invoice.Amount, 2); var totalAmount = Math.Round((double)invoice.TotalAmount, 2); var vatAmount = Math.Round((double)invoice.Vat, 2); if (invoice.IsCreditNote) { amount *= -1; totalAmount *= -1; vatAmount *= -1; } var grossAmountSalesLine = new { DocType = "1", DBKCode = _accountancyConfig.WinbooksDiary, DBKType = "2", DocNumber = ((int)invoice.Number).ToString("D5"), // format with minimal 5 digits DocOrder = "001", OPCode = "", AccountGL = "400000", AccountRP = invoice.CustomerId.ToString(), BookYear = bookYear, Period = period, Date = invoiceDateStr, DateDoc = invoiceDateStr, DueDate = dueDateStr, Comment = "", CommentText = "", Amount = "0.000", AmountEUR = FormatDecimal(totalAmount), VATBase = FormatDecimal(amount), VATCode = "", CurrAmount = "0.000", CurrCode = "", CurEURBase = "0.000", VATTax = FormatDecimal(vatAmount), VATInput = "", CurrRate = "0.00000", RemindLev = "0", MatchNo = "", OldDate = " ", IsMatched = "T", IsLocked = "F", IsImported = "F", IsPositve = "T", IsTemp = "F", MemoType = " ", IsDoc = "F", DocStatus = " ", DICFrom = "", CODAKey = "" }; var account = GetAccount(invoice.VatRate); var vatCode = GetVatCode(invoice.VatRate); var netAmountSalesLine = new { DocType = "3", DBKCode = _accountancyConfig.WinbooksDiary, DBKType = "2", DocNumber = ((int)invoice.Number).ToString("D5"), // format with minimal 5 digits DocOrder = "002", OPCode = "", AccountGL = account, AccountRP = invoice.CustomerId.ToString(), BookYear = bookYear, Period = period, Date = invoiceDateStr, DateDoc = invoiceDateStr, DueDate = dueDateStr, Comment = "", CommentText = "", Amount = "0.000", AmountEUR = FormatDecimal(amount * -1), VATBase = "0.000", VATCode = "", CurrAmount = "0.000", CurrCode = "", CurEURBase = "0.000", VATTax = "0.000", VATInput = vatCode, CurrRate = "0.00000", RemindLev = "0", MatchNo = "", OldDate = " ", IsMatched = "T", IsLocked = "F", IsImported = "F", IsPositve = "T", IsTemp = "F", MemoType = " ", IsDoc = "F", DocStatus = " ", DICFrom = "", CODAKey = "" }; var docType = GetDocType(invoice.VatRate); var vatLine = new { DocType = docType, DBKCode = _accountancyConfig.WinbooksDiary, DBKType = "2", DocNumber = ((int)invoice.Number).ToString("D5"), // format with minimal 5 digits DocOrder = "VAT", OPCode = "FIXED", AccountGL = docType == "4" ? "" : "451000", AccountRP = invoice.CustomerId.ToString(), BookYear = bookYear, Period = period, Date = invoiceDateStr, DateDoc = invoiceDateStr, DueDate = dueDateStr, Comment = "", CommentText = "", Amount = "0.000", AmountEUR = FormatDecimal(vatAmount * -1), VATBase = FormatDecimal(invoice.IsCreditNote ? amount : Math.Abs(amount)), VATCode = vatCode, CurrAmount = "0.000", CurrCode = "", CurEURBase = "0.000", VATTax = "0.000", VATInput = "", CurrRate = "0.00000", RemindLev = "0", MatchNo = "", OldDate = " ", IsMatched = "F", IsLocked = "F", IsImported = "F", IsPositve = "T", IsTemp = "F", MemoType = " ", IsDoc = "F", DocStatus = " ", DICFrom = "", CODAKey = "" }; return(new object[] { grossAmountSalesLine, netAmountSalesLine, vatLine }); }
protected async Task EmbedCustomerAttributesAsync(DataProvider.Models.Invoice invoice) { var customer = await _context.Customers.Where(c => c.Number == invoice.CustomerId).FirstOrDefaultAsync(); invoice.CustomerName = customer.Name; invoice.CustomerAddress1 = customer.Address1; invoice.CustomerAddress2 = customer.Address2; invoice.CustomerAddress3 = customer.Address3; invoice.CustomerPostalCodeId = customer.PostalCodeId; invoice.CustomerPostalCode = customer.EmbeddedPostalCode; invoice.CustomerCity = customer.EmbeddedCity; invoice.CustomerLanguageId = customer.LanguageId; invoice.CustomerCountryId = customer.CountryId; invoice.CustomerHonorificPrefixId = customer.HonorificPrefixId; invoice.CustomerPrefix = customer.Prefix; invoice.CustomerSuffix = customer.Suffix; invoice.CustomerIsCompany = customer.IsCompany; invoice.CustomerVatNumber = customer.VatNumber; // TODO embed phone, mobile and fax number invoice.CustomerSearchName = customer.SearchName; if (invoice.RelativeBuildingId != null) { var building = await _context.Buildings. Where(b => b.CustomerId == invoice.CustomerId && b.Number == invoice.RelativeBuildingId).FirstOrDefaultAsync(); invoice.BuildingName = building.Name; invoice.BuildingAddress1 = building.Address1; invoice.BuildingAddress2 = building.Address2; invoice.BuildingAddress3 = building.Address3; invoice.BuildingPostalCodeId = building.PostalCodeId; invoice.BuildingPostalCode = building.EmbeddedPostalCode; invoice.BuildingCity = building.EmbeddedCity; invoice.BuildingCountryId = building.CountryId; invoice.BuildingPrefix = building.Prefix; invoice.BuildingSuffix = building.Suffix; // TODO embed phone, mobile and fax number invoice.BuildingSearchName = building.SearchName; } if (invoice.RelativeContactId != null) { var contact = await _context.Contacts. Where(b => b.CustomerId == invoice.CustomerId && b.Number == invoice.RelativeContactId).FirstOrDefaultAsync(); invoice.ContactName = contact.Name; invoice.ContactAddress1 = contact.Address1; invoice.ContactAddress2 = contact.Address2; invoice.ContactAddress3 = contact.Address3; invoice.ContactPostalCodeId = contact.PostalCodeId; invoice.ContactPostalCode = contact.EmbeddedPostalCode; invoice.ContactCity = contact.EmbeddedCity; invoice.ContactLanguageId = contact.LanguageId; invoice.ContactCountryId = contact.CountryId; invoice.ContactHonorificPrefixId = contact.HonorificPrefixId; invoice.ContactPrefix = contact.Prefix; invoice.ContactSuffix = contact.Suffix; // TODO embed phone, mobile and fax number invoice.ContactSearchName = contact.SearchName; } if (invoice.BuildingCountryId == null) { invoice.BuildingCountryId = customer.CountryId; // not-NULL DB contstraint } if (invoice.ContactCountryId == null) { invoice.ContactCountryId = customer.CountryId; // not-NULL DB contstraint } }