Files
api/services/nginx/app/tests/Unit/Invoicing/EconomicInvoiceDraftCustomerDiscountTest.php
T
MiniMax M3 Subagent 8972b8f2ae fix(api): apply e-conomic discount percentage at line level for customer 35131752
Bug #11: For customer 35131752 ('kd'), the 15% e-conomic discount was
configured on the customer but never applied to the draft invoice line
items. The customer discount was only used in the flag/preview service for
expected price calculations, not when actually building the draft invoice.

Changes:
- economicCustomers.php: log swallowed missing-currency-price errors so
  silently-missing discounts (like customer 35131752) become visible in
  the application log instead of vanishing.
- economic_invoice_draft.php: thread the customer discount percentage
  through addOrderItemLines/addOrderItemLine and apply it at the line
  level (e-conomic's draft invoice line API requires per-line
  discountPercentage; an aggregate TotDiscount line is ignored when the
  customer has a per-line discount configured).
- economic_invoices_draft_endpoint.php: forward the customer discount
  percentage to the draft builder.
- collected_order_invoices_o.php: resolve the customer discount via
  Redis cache + e-conomicCustomers, then pass it to add_orders.
- Tests: new EconomicInvoiceDraftCustomerDiscountTest covering the
  customer 35131752 15% case, plus updates to the existing wiring tests
  to account for the new parameter and the customer-discount guard on
  the aggregate TotDiscount line.
2026-08-10 16:23:05 +02:00

183 lines
5.7 KiB
PHP

<?php
/**
* Tests for the e-conomic customer-level discount being applied at the line level.
*
* Regression coverage for bug #11 — E-conomic 15% discount not applied on
* customer 35131752 ("kd"). The customer has a 15% global discount configured in
* e-conomic, but the invoice was being sent without any discount on the line items.
*
* The fix threads the customer discount percentage through the draft builder so it
* is applied at the line level via the `discountPercentage` field that e-conomic
* expects on each line.
*/
app_require('modules/economic/helpers/economic_invoice_draft.php');
use helpers\economic_invoice_draft;
if (!class_exists('EconomicInvoiceDraftCustomerDiscountProbe')) {
class EconomicInvoiceDraftCustomerDiscountProbe extends economic_invoice_draft
{
public array $sentBatches = [];
public function __construct()
{
$this->draft_invoice_number = 35131752;
$this->currency = 'DKK';
$this->conversion_rate = 1.0;
$this->draft_invoice_data = (object)['draftInvoiceNumber' => 35131752];
}
protected function sendDraftLines(array $draft_lines): object
{
$this->sentBatches[] = $draft_lines;
return (object)['lines' => $draft_lines];
}
}
}
function economic_customer_discount_order_item(float $price, float $product_price, array $overrides = []): array
{
return array_replace_recursive([
'id' => 9001,
'quantity' => 1,
'price' => $price,
'reference' => '',
'notes' => '',
'include_in_invoice' => true,
'product' => [
'economic_product_id' => '5',
'name' => 'Wash',
'price' => $product_price,
],
], $overrides);
}
it('applies the 15% customer discount to a line item for customer 35131752 "kd"', function (): void {
$draft = new EconomicInvoiceDraftCustomerDiscountProbe();
// Order item is at full price (no per-item discount) — exactly the customer 35131752
// case where the 15% global e-conomic discount was silently dropped.
$draft->addOrderItemLine(
economic_customer_discount_order_item(100.0, 100.0),
[
'economic_department_id' => 75,
'economic_dimension_id' => 1,
],
false,
false,
15
);
$draft->flushLinesInBatches();
$line = $draft->sentBatches[0][0];
expect($line['product']['productNumber'])->toBe('5')
->and($line['description'])->toBe('Wash')
->and($line['quantity'])->toBe(1.0)
->and($line['unitNetPrice'])->toBe(100.0)
->and($line['discountPercentage'])->toBe(15.0);
});
it('uses the larger discount when both per-item and customer discounts are present', function (): void {
$draft = new EconomicInvoiceDraftCustomerDiscountProbe();
// Per-item discount = 10%, customer discount = 15% → max(15, 10) = 15.
$draft->addOrderItemLine(
economic_customer_discount_order_item(90.0, 100.0),
[
'economic_department_id' => 75,
'economic_dimension_id' => 1,
],
false,
true,
15
);
$draft->flushLinesInBatches();
$line = $draft->sentBatches[0][0];
expect($line['unitNetPrice'])->toBe(100.0)
->and($line['discountPercentage'])->toBe(15.0);
});
it('uses the per-item discount when it is larger than the customer discount', function (): void {
$draft = new EconomicInvoiceDraftCustomerDiscountProbe();
// Per-item discount = 25%, customer discount = 15% → max(25, 15) = 25.
$draft->addOrderItemLine(
economic_customer_discount_order_item(75.0, 100.0),
[
'economic_department_id' => 75,
'economic_dimension_id' => 1,
],
false,
true,
15
);
$draft->flushLinesInBatches();
$line = $draft->sentBatches[0][0];
expect($line['unitNetPrice'])->toBe(100.0)
->and($line['discountPercentage'])->toBe(25.0);
});
it('clamps the customer discount percentage to the 0..100 range', function (): void {
$draft = new EconomicInvoiceDraftCustomerDiscountProbe();
$draft->addOrderItemLine(
economic_customer_discount_order_item(100.0, 100.0),
[
'economic_department_id' => 75,
'economic_dimension_id' => 1,
],
false,
false,
150
);
$draft->flushLinesInBatches();
$line = $draft->sentBatches[0][0];
expect($line['discountPercentage'])->toBe(100.0);
});
it('emits no line discount when both per-item and customer discounts are zero', function (): void {
$draft = new EconomicInvoiceDraftCustomerDiscountProbe();
$draft->addOrderItemLine(
economic_customer_discount_order_item(100.0, 100.0),
[
'economic_department_id' => 75,
'economic_dimension_id' => 1,
],
false,
false,
0
);
$draft->flushLinesInBatches();
$line = $draft->sentBatches[0][0];
expect($line['unitNetPrice'])->toBe(100.0)
->and($line['discountPercentage'])->toBe(0.0);
});
it('keeps base behavior unchanged when the customer discount is zero', function (): void {
$draft = new EconomicInvoiceDraftCustomerDiscountProbe();
// No customer discount, no per-item discount — unit price should be the final price.
$draft->addOrderItemLine(
economic_customer_discount_order_item(100.0, 100.0),
[
'economic_department_id' => 75,
'economic_dimension_id' => 1,
],
false,
false,
0
);
$draft->flushLinesInBatches();
$line = $draft->sentBatches[0][0];
expect($line['unitNetPrice'])->toBe(100.0)
->and($line['discountPercentage'])->toBe(0.0);
});