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); }
// Note: contact and building of a Case can only be updated through this method // UpdateAsync() methods of a resource in OfferManager, OrdereManager, etc. prevent the update of the contact/building for an existing resource // That's why we directly call methods of the OfferDataProvider, OrderDataProvider, etc. here public async Task UpdateContactAndBuildingAsync(int?contactId, int?buildingId, int?requestId, int?interventionId, int?offerId, int?orderId, int?invoiceId) { int?relativeContactId = null; int?relativeBuildingId = null; try { if (contactId != null) { var contact = await _contactDataProvider.GetByIdAsync((int)contactId); relativeContactId = contact.Number; } if (buildingId != null) { var building = await _buildingDataProvider.GetByIdAsync((int)buildingId); relativeBuildingId = building.Number; } if (requestId != null) { await _requestDataProvider.UpdateContactAndBuildingAsync((int)requestId, relativeContactId, relativeBuildingId); } if (interventionId != null) { await _interventionDataProvider.UpdateContactAndBuildingAsync((int)interventionId, relativeContactId, relativeBuildingId); } if (offerId != null) { await _offerDataProvider.UpdateContactAndBuildingAsync((int)offerId, relativeContactId, relativeBuildingId); } if (orderId != null) { // updating the offer automatically updates the contact/building of the order too. No need to do that explicitly here. var query = new QuerySet(); query.Page.Size = 1000; // TODO we assume 1 case doesn't have more than 1000 deposit invoices. Ideally, we should query by page. var depositInvoices = await _depositInvoiceDataProvider.GetAllByOrderIdAsync((int)orderId, query); foreach (var depositInvoice in depositInvoices.Items) { await _depositInvoiceDataProvider.UpdateContactAndBuildingAsync(depositInvoice.Id, relativeContactId, relativeBuildingId); } } if (invoiceId != null) { await _invoiceDataProvider.UpdateContactAndBuildingAsync((int)invoiceId, relativeContactId, relativeBuildingId); } } catch (EntityNotFoundException e) { throw new IllegalArgumentException("IllegalEntity", $"Contact and building cannot be updated: ${e.Message}", e); } }
public async Task DeleteAsync(int id) { try { var invoice = await _invoiceDataProvider.GetByOrderIdAsync(id); var message = $"Order {id} cannot be deleted because invoice {invoice.Id} is attached to it."; _logger.LogError(message); throw new InvalidOperationException(message); } catch (EntityNotFoundException) { var pageQuery = new QuerySet(); pageQuery.Page.Size = 1; var depositInvoices = await _depositInvoiceDataProvider.GetAllByOrderIdAsync(id, pageQuery); if (depositInvoices.Count > 0) { var message = $"Order {id} cannot be deleted because {depositInvoices.Count} deposit-invoices attached to it."; _logger.LogError(message); throw new InvalidOperationException(message); } var deposits = await _depositDataProvider.GetAllByOrderIdAsync(id, pageQuery); if (deposits.Count > 0) { var message = $"Order {id} cannot be deleted because {deposits.Count} deposits are attached to it."; _logger.LogError(message); throw new InvalidOperationException(message); } // TODO reset ordered flag of offerlines on deletion instead of throwing an error? var offerlines = await _offerlineDataProvider.GetOrderedByOrderIdAsync(id, pageQuery); if (offerlines.Count > 0) { var message = $"Order {id} cannot be deleted because {offerlines.Count} ordered offerlines are attached to it."; _logger.LogError(message); throw new InvalidOperationException(message); } try { var order = await _orderDataProvider.GetByIdAsync(id); await _graphApiService.DeleteEventForPlanningAsync(order); await _orderDataProvider.DeleteByIdAsync(id); } catch (EntityNotFoundException) { // Order not found. Nothing should happen. } } }
public async Task <Paged <DepositInvoice> > GetAllByOrderIdAsync(int orderId, QuerySet query) { if (query.Sort.Field == null) { query.Sort.Order = SortQuery.ORDER_DESC; query.Sort.Field = "number"; } return(await _depositInvoiceDataProvider.GetAllByOrderIdAsync(orderId, query)); }
public async Task DeleteAsync(int id) { try { var invoice = await _invoiceDataProvider.GetByOrderIdAsync(id); var message = $"Order {id} cannot be deleted because invoice {invoice.Id} is attached to it."; _logger.LogError(message); throw new InvalidOperationException(message); } catch (EntityNotFoundException) { var pageQuery = new QuerySet(); pageQuery.Page.Size = 1; var depositInvoices = await _depositInvoiceDataProvider.GetAllByOrderIdAsync(id, pageQuery); if (depositInvoices.Count > 0) { var message = $"Order {id} cannot be deleted because {depositInvoices.Count} deposit-invoices attached to it."; _logger.LogError(message); throw new InvalidOperationException(message); } var deposits = await _depositDataProvider.GetAllByOrderIdAsync(id, pageQuery); if (deposits.Count > 0) { var message = $"Order {id} cannot be deleted because {deposits.Count} deposits are attached to it."; _logger.LogError(message); throw new InvalidOperationException(message); } try { var order = await _orderDataProvider.GetByIdAsync(id); await _documentGenerationManager.DeleteOrderDocumentAsync(id); await _documentGenerationManager.DeleteDeliveryNoteAsync(id); await _documentGenerationManager.DeleteProductionTicketTemplateAsync(id); await _documentGenerationManager.DeleteProductionTicketAsync(id); await _orderDataProvider.DeleteByIdAsync(id); } catch (EntityNotFoundException) { // Order not found. Nothing should happen. } } }
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 }