diff --git a/services/nginx/app/routes/orderInvoicesRoute.php b/services/nginx/app/routes/orderInvoicesRoute.php index 3ca53127..f2af800c 100644 --- a/services/nginx/app/routes/orderInvoicesRoute.php +++ b/services/nginx/app/routes/orderInvoicesRoute.php @@ -128,6 +128,96 @@ class orderInvoicesRoute ] ); + /** Collected order invoices > Compare with E-conomic > GET */ + $this->get('/collected-invoices/economic/compare', function () { + global $response; + self::requirePermission('compare_collected_invoice_economic'); + //$user = (new authentication())->get_user(); + self::requireParameters(['collected_invoice_id']); + self::requireType((int)self::getParameter('collected_invoice_id'), self::type_int()); + $collected_invoice_id = (int)self::getParameter('collected_invoice_id'); + self::requireMinValue($collected_invoice_id, 1); + self::requireMaxValue($collected_invoice_id, 999999999); + // Define variables + $draft_id = null; // E-Conomic draft ID + $booked_id = null; // E-Conomic booked invoice ID + $warnings = []; + // Select the collected order invoice + /** @var collected_order_invoices_o $invoice */ + $invoice = (new collected_order_invoices_o())->select($collected_invoice_id); + $invoice->requireSelected(); // Require that the collected order invoice exists + // Get the E-Conomic draft ID and booked invoice ID + try { + $draft_id = $invoice->getInvoiceDraftId(); + + } catch (Exception $e) { + $warnings[] = 'Error fetching draft ID: ' . $e->getMessage(); + } + try { + $booked_id = $invoice->getInvoiceBookedId(); + + } catch (Exception $e) { + $warnings[] = 'Error fetching booked invoice ID: ' . $e->getMessage(); + } + // Define the variables for comparison + $draft_total = null; + $booked_total = null; + // Get the total price of the draft (if it exists) + if ($draft_id !== null) { + try { + $economic = new economic(); + $draft_invoice = $economic->getInvoiceDraft((int)$draft_id); + $draft_total = $draft_invoice['total_amount'] ?? null; + $internal_total = $invoice->getTotalAmount(); + if ($draft_total === null) { + $warnings[] = 'Could not fetch total amount for draft invoice ID ' . $draft_id; + } elseif (abs((float)$draft_total - (float)$internal_total) > 0.01) { + $warnings[] = 'Total amount mismatch for draft invoice ID ' . $draft_id . ': E-Conomic total is ' . $draft_total . ', internal total is ' . $internal_total; + } + } catch (Exception $e) { + $warnings[] = 'Error comparing draft total: ' . $e->getMessage(); + } + } + // Get the total price of the booked invoice (if it exists) + if ($booked_id !== null) { + try { + $economic = new economic(); + $booked_invoice = $economic->getInvoiceBookedFromExternalId((string)$invoice->external_id->value()); + /** + * stdClass Object ( [bookedInvoiceNumber] => 28368 [orderNumber] => 30342 [date] => 2025-12-31 [currency] => DKK [exchangeRate] => 100 [netAmount] => 694 [netAmountInBaseCurrency] => 694 [grossAmount] => 867.5 [grossAmountInBaseCurrency] => 867.5 [vatAmount] => 173.5 [roundingAmount] => 0 [remainder] => 0 [remainderInBaseCurrency] => 0 [dueDate] => 2026-01-08 [paymentTerms] => stdClass Object ( [paymentTermsNumber] => 1 [daysOfCredit] => 8 [name] => Netto 8 dage [paymentTermsType] => net [self] => https://restapi.e-conomic.com/payment-terms/1 ) [customer] => stdClass Object ( [customerNumber] => 42493959 [self] => https://restapi.e-conomic.com/customers/42493959 ) [recipient] => stdClass Object ( [name] => Dejen Transport ApS [address] => Æblehaven 144, st [zip] => 4000 [city] => Roskilde [vatZone] => stdClass Object ( [name] => Domestic [vatZoneNumber] => 1 [enabledForCustomer] => 1 [enabledForSupplier] => 1 [self] => https://restapi.e-conomic.com/vat-zones/1 ) ) [references] => stdClass Object ( [other] => 2ced7a3f-fab2-edbd-075f-ce981867c340 ) [layout] => stdClass Object ( [layoutNumber] => 12 [self] => https://restapi.e-conomic.com/layouts/12 ) [pdf] => stdClass Object ( [download] => https://restapi.e-conomic.com/invoices/booked/28368/pdf ) [lines] => Array ( [0] => stdClass Object ( [lineNumber] => 1 [sortKey] => 1 [description] => [ 01/12/2025 00:00 PLENO #38679 ] [discountPercentage] => 0 [unitCostPrice] => 0 [vatRate] => 0 ) [1] => stdClass Object ( [lineNumber] => 2 [sortKey] => 2 [description] => Reference: [discountPercentage] => 0 [unitCostPrice] => 0 [vatRate] => 0 ) [2] => stdClass Object ( [lineNumber] => 3 [sortKey] => 3 [description] => # Vaskeabonnementer [discountPercentage] => 0 [unitCostPrice] => 0 [vatRate] => 0 ) [3] => stdClass Object ( [lineNumber] => 4 [sortKey] => 4 [description] => Trækker [quantity] => 2 [unitNetPrice] => 579 [discountPercentage] => 0 [unitCostPrice] => 0 [vatRate] => 25 [vatAmount] => 289.5 [totalNetAmount] => 1158 [product] => stdClass Object ( [productNumber] => 1 [self] => https://restapi.e-conomic.com/products/1 ) [departmentalDistribution] => stdClass Object ( [departmentalDistributionNumber] => 75 [name] => Vaskeaftaler og fastprisaftaler [barred] => [distributionType] => department [distributions] => Array ( [0] => stdClass Object ( [percentage] => 100 [department] => stdClass Object ( [departmentNumber] => 75 [self] => https://restapi.e-conomic.com/departments/75 ) ) ) [self] => https://restapi.e-conomic.com/departmental-distributions/departments/75 ) ) [4] => stdClass Object ( [lineNumber] => 5 [sortKey] => 5 [description] => Reference: [discountPercentage] => 0 [unitCostPrice] => 0 [vatRate] => 0 ) [5] => stdClass Object ( [lineNumber] => 6 [sortKey] => 6 [description] => # EH89254 [discountPercentage] => 0 [unitCostPrice] => 0 [vatRate] => 0 ) [6] => stdClass Object ( [lineNumber] => 7 [sortKey] => 7 [description] => Spot Free- Lastbil [quantity] => 2 [unitNetPrice] => 39 [discountPercentage] => 0 [unitCostPrice] => 0 [vatRate] => 25 [vatAmount] => 19.5 [totalNetAmount] => 78 [product] => stdClass Object ( [productNumber] => 33 [self] => https://restapi.e-conomic.com/products/33 ) [departmentalDistribution] => stdClass Object ( [departmentalDistributionNumber] => 75 [name] => Vaskeaftaler og fastprisaftaler [barred] => [distributionType] => department [distributions] => Array ( [0] => stdClass Object ( [percentage] => 100 [department] => stdClass Object ( [departmentNumber] => 75 [self] => https://restapi.e-conomic.com/departments/75 ) ) ) [self] => https://restapi.e-conomic.com/departmental-distributions/departments/75 ) ) [7] => stdClass Object ( [lineNumber] => 8 [sortKey] => 8 [description] => Reference: [discountPercentage] => 0 [unitCostPrice] => 0 [vatRate] => 0 ) [8] => stdClass Object ( [lineNumber] => 9 [sortKey] => 9 [description] => # EH89254 [discountPercentage] => 0 [unitCostPrice] => 0 [vatRate] => 0 ) [9] => stdClass Object ( [lineNumber] => 10 [sortKey] => 10 [description] => Rabat [quantity] => 1 [unitNetPrice] => -542 [discountPercentage] => 0 [unitCostPrice] => 0 [vatRate] => 25 [vatAmount] => -135.5 [totalNetAmount] => -542 [product] => stdClass Object ( [productNumber] => TotDiscount [self] => https://restapi.e-conomic.com/products/TotDiscount ) [departmentalDistribution] => stdClass Object ( [departmentalDistributionNumber] => 75 [name] => Vaskeaftaler og fastprisaftaler [barred] => [distributionType] => department [distributions] => Array ( [0] => stdClass Object ( [percentage] => 100 [department] => stdClass Object ( [departmentNumber] => 75 [self] => https://restapi.e-conomic.com/departments/75 ) ) ) [self] => https://restapi.e-conomic.com/departmental-distributions/departments/75 ) ) [10] => stdClass Object ( [lineNumber] => 11 [sortKey] => 11 [discountPercentage] => 0 [unitCostPrice] => 0 [vatRate] => 0 ) ) [sent] => https://restapi.e-conomic.com/invoices/booked/28368/sent [self] => https://restapi.e-conomic.com/invoices/booked/28368 ) + */ + $booked_total = $booked_invoice->total_amount ?? null; + // Remove tax from booked total if prices are stored as tax inclusive + $booked_total = $booked_total - ($booked_invoice->vat_amount ?? 0); + $internal_total = $invoice->getTotalAmount(); + if ($booked_total === null) { + $warnings[] = 'Could not fetch total amount for booked invoice ID ' . $booked_id; + } elseif (abs((float)$booked_total - (float)$internal_total) > 0.01) { + $warnings[] = 'Total amount mismatch for booked invoice ID ' . $booked_id . ': E-Conomic total is ' . $booked_total . ', internal total is ' . $internal_total; + } + } catch (Exception $e) { + $warnings[] = 'Error comparing booked total: ' . $e->getMessage(); + } + } + // Return the comparison result + $response->success([ + 'collected_invoice_id' => $collected_invoice_id, + 'draft_id' => $draft_id, + 'booked_id' => $booked_id, + 'warnings' => $warnings, + 'draft_total' => $draft_total, + 'booked_total' => $booked_total, + 'difference' => ($draft_total !== null && $booked_total !== null) ? (float)$draft_total - (float)$booked_total : null, + 'internal_total' => $invoice->getTotalAmount(), + 'order_ids' => $invoice->getOrderIds(), + ]); + + }, + [ + 'compare_collected_invoice_economic' => 'Compare collected order invoices with E-Conomic. This is a superuser-only route.' + ] + ); + /** Collected order invoices > Ready to invoice > GET */ $this->get('/collected-invoices/ready-to-invoice', function () { global $response;