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); });