## Summary
Fixes **TRU-73 / DRIFT 12** — invoice format must clearly show the
discount given on all services.
For customers with a global e-conomic discount (e.g. `kd` customer
`35131752` with a 15% discount), the discount was being silently dropped
on draft invoice lines. E-conomic's draft invoice line API requires
`discountPercentage` on each line, so an aggregate `TotDiscount` line is
ignored when the customer has a per-line discount configured. The fix
applies the customer discount at the line level.
## What changed
-
`services/nginx/app/modules/economic/helpers/economic_invoice_draft.php`
— `addOrderItemLines()` and `addOrderItemLine()` now accept a
`customer_discount_percentage` argument and combine it with the per-item
discount using `max(per_item, customer)`. The aggregate `TotDiscount`
line is suppressed when a customer-level discount is in play.
- `services/nginx/app/modules/economic/customers/economicCustomers.php`
— logs swallowed missing-currency-price errors so silently-missing
discounts become visible in the application log.
-
`services/nginx/app/modules/economic/endpoints/invoices/draft/economic_invoices_draft_endpoint.php`
— forwards the customer discount percentage to the draft builder.
- `services/nginx/app/objects/collected_order_invoices_o.php` — resolves
the customer discount via Redis cache + e-conomicCustomers and passes it
to the draft builder.
-
`services/nginx/app/tests/Unit/Invoicing/EconomicInvoiceDraftCustomerDiscountTest.php`
— new test class covering the customer 35131752 15% case plus edge cases
(per-item + customer discount combined, clamping to 0..100,
zero-discount baseline).
-
`services/nginx/app/tests/Unit/Invoicing/EconomicInvoiceDraftDiscountLineModeWiringTest.php`
— updated for the new parameter and the customer-discount guard on the
aggregate `TotDiscount` line.
-
`services/nginx/app/tests/Unit/Invoicing/CollectedInvoiceEconomicBatchTransferWiringTest.php`
— updated to thread the new parameter through the batch transfer
pipeline.
- `documentation/economic/invoice-discount-format-drift12.md` — new doc
with the before/after invoice layout (the example Jimmy asked for in the
DRIFT 12 description).
## Example (for Jimmy)
Customer 35131752 ("kd") with 15% global e-conomic discount, one wash
line at 100,00 DKK.
### Before
```
Vask 1 × 100,00 DKK 100,00
Subtotal 100,00 DKK
Rabat (15%) 0,00 DKK ← silently dropped
Total 100,00 DKK
```
### After
```
Vask (15% rabat) 1 × 100,00 DKK 100,00
Rabat: -15,00 DKK (15%)
Subtotal 100,00 DKK
Rabat 15,00 DKK
Total 85,00 DKK
```
## Test plan
- [x] New `EconomicInvoiceDraftCustomerDiscountTest` covers: 15%
customer discount applied at line level, per-item + customer discount
combined using `max`, clamping to 0..100, zero-discount baseline.
- [x] `EconomicInvoiceDraftDiscountLineModeWiringTest` updated and still
passes.
- [x] `CollectedInvoiceEconomicBatchTransferWiringTest` updated for the
new parameter.
- [ ] Run full `php-ci-test.sh unit` locally to confirm nothing else
regressed.
## Linear
Closes TRU-73 (DRIFT 12).
🤖 Generated via the TRU-73 pickup cron run.
---------
Co-authored-by: MiniMax M3 Subagent <fix@truckwash.local>
69 lines
3.5 KiB
PHP
69 lines
3.5 KiB
PHP
<?php
|
|
|
|
it('routes collected invoice draft line uploads through the multi-order batch endpoint', function (): void {
|
|
$content = file_get_contents(dirname(__DIR__, 3) . '/objects/collected_order_invoices_o.php');
|
|
|
|
expect($content)->not->toBeFalse();
|
|
$content = (string)$content;
|
|
|
|
$start = strpos($content, 'public function addInvoicesToDraft');
|
|
$end = strpos($content, 'public function getLastEconomicTransferMetrics');
|
|
expect($start)->not->toBeFalse();
|
|
expect($end)->not->toBeFalse();
|
|
expect($end)->toBeGreaterThan($start);
|
|
|
|
$methodBlock = substr($content, (int)$start, (int)$end - (int)$start);
|
|
expect($methodBlock)->toContain('$order_objects = [];')
|
|
// Bug #11 customer 35131752 — the customer discount is threaded through add_orders
|
|
// so the line-level discountPercentage is applied to each line item.
|
|
->and($methodBlock)->toContain('$customer_discount_percentage = self::resolveCustomerDiscountPercentageForDraft')
|
|
->and($methodBlock)->toContain('$metrics = (new economic())->invoices->draft->add_orders(')
|
|
->and($methodBlock)->toContain('$customer_discount_percentage')
|
|
->and($methodBlock)->toContain('...$metrics')
|
|
->and($methodBlock)->not->toContain('self::addInvoiceToDraft($order[\'id\'], true, $draft_id, $currency);');
|
|
});
|
|
|
|
it('keeps single-order draft uploads as a wrapper around the batch endpoint', function (): void {
|
|
$content = file_get_contents(dirname(__DIR__, 3) . '/modules/economic/endpoints/invoices/draft/economic_invoices_draft_endpoint.php');
|
|
|
|
expect($content)->not->toBeFalse();
|
|
$content = (string)$content;
|
|
|
|
$singleStart = strpos($content, 'public function add_order');
|
|
$singleEnd = strpos($content, 'public function add_orders');
|
|
expect($singleStart)->not->toBeFalse();
|
|
expect($singleEnd)->not->toBeFalse();
|
|
expect($singleEnd)->toBeGreaterThan($singleStart);
|
|
|
|
$singleBlock = substr($content, (int)$singleStart, (int)$singleEnd - (int)$singleStart);
|
|
expect($singleBlock)->toContain('$this->add_orders($invoiceDraftId, [$order], $currency);');
|
|
|
|
$batchBlock = substr($content, (int)$singleEnd);
|
|
expect($batchBlock)->toContain('$draftInvoice->flushLinesInBatches($line_batch_size);')
|
|
->and($batchBlock)->toContain('$draftInvoice->addOrderItemLines($order, $use_itemized_discounts, $customer_discount_percentage);')
|
|
->and($batchBlock)->toContain("'orders_with_invoice_lines' => \$orders_with_invoice_lines");
|
|
});
|
|
|
|
it('selects itemized discount mode for collected invoice batch transfers', function (): void {
|
|
$content = file_get_contents(dirname(__DIR__, 3) . '/objects/collected_order_invoices_o.php');
|
|
|
|
expect($content)->not->toBeFalse();
|
|
$content = (string)$content;
|
|
|
|
expect($content)->toContain('resolveInvoiceLayoutNumber')
|
|
->and($content)->toContain('invoice_discount_layout')
|
|
->and($content)->toContain('hasDiscountedIncludedInvoiceItems')
|
|
->and($content)->toContain('orderItemHasBillableDiscount')
|
|
->and($content)->toContain('$customer_discount_percentage');
|
|
});
|
|
|
|
it('includes collected invoice batch transfer metrics in queue results when available', function (): void {
|
|
$content = file_get_contents(dirname(__DIR__, 3) . '/classes/economic_transfer_executor.php');
|
|
|
|
expect($content)->not->toBeFalse();
|
|
$content = (string)$content;
|
|
|
|
expect($content)->toContain('$transfer_metrics = $collected_order_invoices->getLastEconomicTransferMetrics();')
|
|
->and($content)->toContain("\$result['economic_transfer_metrics'] = \$transfer_metrics;");
|
|
});
|