127 lines
4.2 KiB
PHP
127 lines
4.2 KiB
PHP
<?php
|
|
|
|
app_require('modules/economic/helpers/economic_invoice_draft.php');
|
|
|
|
use helpers\economic_invoice_draft;
|
|
|
|
if (!class_exists('EconomicInvoiceDraftItemizedDiscountProbe')) {
|
|
class EconomicInvoiceDraftItemizedDiscountProbe extends economic_invoice_draft
|
|
{
|
|
public array $sentBatches = [];
|
|
|
|
public function __construct()
|
|
{
|
|
$this->draft_invoice_number = 123;
|
|
$this->currency = 'DKK';
|
|
$this->conversion_rate = 1.0;
|
|
$this->draft_invoice_data = (object)['draftInvoiceNumber' => 123];
|
|
}
|
|
|
|
protected function sendDraftLines(array $draft_lines): object
|
|
{
|
|
$this->sentBatches[] = $draft_lines;
|
|
return (object)['lines' => $draft_lines];
|
|
}
|
|
}
|
|
}
|
|
|
|
function economic_itemized_discount_order_item(array $overrides = []): array
|
|
{
|
|
return array_replace_recursive([
|
|
'id' => 123,
|
|
'quantity' => 2,
|
|
'price' => 80,
|
|
'reference' => '',
|
|
'notes' => '',
|
|
'include_in_invoice' => true,
|
|
'product' => [
|
|
'economic_product_id' => '5',
|
|
'name' => 'Premium wash',
|
|
'price' => 100,
|
|
],
|
|
], $overrides);
|
|
}
|
|
|
|
it('detects billable itemized discounts from original and final prices', function (): void {
|
|
$pricing = economic_invoice_draft::resolveOrderItemInvoicePricing(economic_itemized_discount_order_item());
|
|
|
|
expect($pricing['has_discount'])->toBeTrue()
|
|
->and($pricing['original_unit_price'])->toBe(100.0)
|
|
->and($pricing['final_unit_price'])->toBe(80.0)
|
|
->and($pricing['discount_unit_amount'])->toBe(20.0)
|
|
->and($pricing['discount_total_amount'])->toBe(40.0)
|
|
->and($pricing['discount_percentage'])->toBe(20.0);
|
|
});
|
|
|
|
it('does not mark equal prices, zero quantities, or zero final prices as itemized discounts', function (): void {
|
|
expect(economic_invoice_draft::orderItemHasBillableDiscount(economic_itemized_discount_order_item([
|
|
'price' => 100,
|
|
])))->toBeFalse();
|
|
expect(economic_invoice_draft::orderItemHasBillableDiscount(economic_itemized_discount_order_item([
|
|
'quantity' => 0,
|
|
])))->toBeFalse();
|
|
expect(economic_invoice_draft::orderItemHasBillableDiscount(economic_itemized_discount_order_item([
|
|
'price' => 0,
|
|
])))->toBeFalse();
|
|
});
|
|
|
|
it('uses original price and exact discount basis for itemized discount product lines', function (): void {
|
|
$draft = new EconomicInvoiceDraftItemizedDiscountProbe();
|
|
|
|
$draft->addOrderItemLine(
|
|
economic_itemized_discount_order_item(),
|
|
[
|
|
'economic_department_id' => 75,
|
|
'economic_dimension_id' => 1,
|
|
],
|
|
false,
|
|
true
|
|
);
|
|
$draft->flushLinesInBatches();
|
|
|
|
$line = $draft->sentBatches[0][0];
|
|
expect($line['product']['productNumber'])->toBe('5')
|
|
->and($line['description'])->toBe('Premium wash')
|
|
->and($line['quantity'])->toBe(2.0)
|
|
->and($line['unitNetPrice'])->toBe(100.0)
|
|
->and($line['discountPercentage'])->toBe(20.0);
|
|
});
|
|
|
|
it('keeps non-discount itemized product lines at the exact final price', function (): void {
|
|
$draft = new EconomicInvoiceDraftItemizedDiscountProbe();
|
|
|
|
$draft->addOrderItemLine(
|
|
economic_itemized_discount_order_item([
|
|
'price' => 125,
|
|
'product' => [
|
|
'price' => 100,
|
|
],
|
|
]),
|
|
[
|
|
'economic_department_id' => 75,
|
|
'economic_dimension_id' => 1,
|
|
],
|
|
false,
|
|
true
|
|
);
|
|
$draft->flushLinesInBatches();
|
|
|
|
$line = $draft->sentBatches[0][0];
|
|
expect($line['unitNetPrice'])->toBe(125.0)
|
|
->and($line['discountPercentage'])->toBe(0.0);
|
|
});
|
|
|
|
it('keeps fractional discount percentages instead of rounding itemized discounts to whole percentages', function (): void {
|
|
$pricing = economic_invoice_draft::resolveOrderItemInvoicePricing(economic_itemized_discount_order_item([
|
|
'quantity' => 1,
|
|
'price' => 2,
|
|
'product' => [
|
|
'price' => 3,
|
|
],
|
|
]));
|
|
|
|
expect($pricing['discount_unit_amount'])->toBe(1.0)
|
|
->and($pricing['discount_total_amount'])->toBe(1.0)
|
|
->and($pricing['discount_percentage'])->toBe(33.3333333333);
|
|
});
|