- Implemented `InvoicingPeriodDraftOverlayTest` with coverage for blocking and permitting invoicing actions based on draft states, transactions, and metadata. - Created `ReferenceSuggestionsApiTest` to validate ranked and filtered suggestions across bookings, orders, and vehicles with varied match relevance, context, and frequency. - Added `order_reference_suggestions_service` class, including query methods, normalization utilities, and aggregation logic for reference suggestions. - Enhanced query handling in `InvoicingPeriodDraftOverlayFakeDb` to validate SQL constraints and column cache resets in overlapping invoicing contexts.
167 lines
5.6 KiB
PHP
167 lines
5.6 KiB
PHP
<?php
|
|
|
|
use classes\economic_transfer_queue;
|
|
use classes\economic_transfer_queue_details_summary;
|
|
|
|
it('builds a completed collected-invoice queue summary from payload and result', function (): void {
|
|
$summary = economic_transfer_queue_details_summary::buildCollectedInvoiceSummary([
|
|
'status' => economic_transfer_queue::STATUS_COMPLETED,
|
|
'payload' => [
|
|
'collected_invoice_id' => '14578',
|
|
'send_as_is' => '1',
|
|
'requested_by' => '18',
|
|
],
|
|
'result' => [
|
|
'message' => 'Invoice transferred',
|
|
'customer_number' => '43425425',
|
|
'customer_name' => 'North Freight',
|
|
'economic_invoice_draft_id' => '2001',
|
|
'economic_invoice_booked_id' => '3001',
|
|
'external_id' => 'abc-123',
|
|
'total_net_amount' => '670',
|
|
'orders' => [
|
|
['id' => 1],
|
|
['id' => 2],
|
|
],
|
|
],
|
|
]);
|
|
|
|
expect($summary['message'])->toBe('Invoice transferred');
|
|
expect($summary['target'])->toBe([
|
|
'collected_invoice_id' => 14578,
|
|
'send_as_is' => true,
|
|
'requested_by' => 18,
|
|
]);
|
|
expect($summary['customer'])->toBe([
|
|
'customer_number' => 43425425,
|
|
'name' => 'North Freight',
|
|
]);
|
|
expect($summary['outcome'])->toBe([
|
|
'economic_invoice_draft_id' => 2001,
|
|
'economic_invoice_booked_id' => 3001,
|
|
'external_id' => 'abc-123',
|
|
'total_net_amount' => 670.0,
|
|
'order_count' => 2,
|
|
]);
|
|
expect($summary['raw_available'])->toBe([
|
|
'payload' => true,
|
|
'result' => true,
|
|
]);
|
|
});
|
|
|
|
it('prefers queue error messages for failed jobs and keeps null-safe outcome fields', function (): void {
|
|
$summary = economic_transfer_queue_details_summary::buildCollectedInvoiceSummary([
|
|
'status' => economic_transfer_queue::STATUS_FAILED,
|
|
'collected_invoice_id' => 9001,
|
|
'error_message' => 'No billable order items',
|
|
'payload' => [
|
|
'collected_invoice_id' => 9001,
|
|
],
|
|
'result' => null,
|
|
]);
|
|
|
|
expect($summary['message'])->toBe('No billable order items');
|
|
expect($summary['target']['collected_invoice_id'])->toBe(9001);
|
|
expect($summary['target']['send_as_is'])->toBeNull();
|
|
expect($summary['target']['requested_by'])->toBeNull();
|
|
|
|
expect($summary['customer'])->toBe([
|
|
'customer_number' => null,
|
|
'name' => null,
|
|
]);
|
|
expect($summary['outcome'])->toBe([
|
|
'economic_invoice_draft_id' => null,
|
|
'economic_invoice_booked_id' => null,
|
|
'external_id' => null,
|
|
'total_net_amount' => null,
|
|
'order_count' => null,
|
|
]);
|
|
expect($summary['raw_available'])->toBe([
|
|
'payload' => true,
|
|
'result' => false,
|
|
]);
|
|
});
|
|
|
|
it('uses queued job payload customer context before result data exists', function (): void {
|
|
$summary = economic_transfer_queue_details_summary::buildCollectedInvoiceSummary([
|
|
'status' => economic_transfer_queue::STATUS_QUEUED,
|
|
'payload' => [
|
|
'collected_invoice_id' => 17389,
|
|
'customer_number' => '778899',
|
|
'customer_name' => 'Queued Customer A/S',
|
|
],
|
|
'result' => null,
|
|
'progress_message' => 'Queued',
|
|
]);
|
|
|
|
expect($summary['target']['collected_invoice_id'])->toBe(17389);
|
|
expect($summary['customer'])->toBe([
|
|
'customer_number' => 778899,
|
|
'name' => 'Queued Customer A/S',
|
|
]);
|
|
});
|
|
|
|
it('uses deterministic status message fallback when no explicit message exists', function (): void {
|
|
$expectations = [
|
|
[economic_transfer_queue::STATUS_QUEUED, 'Queued'],
|
|
[economic_transfer_queue::STATUS_PROCESSING, 'Processing'],
|
|
[economic_transfer_queue::STATUS_COMPLETED, 'Completed'],
|
|
[economic_transfer_queue::STATUS_FAILED, 'Failed'],
|
|
['UNKNOWN', null],
|
|
];
|
|
|
|
foreach ($expectations as [$status, $expected]) {
|
|
$summary = economic_transfer_queue_details_summary::buildCollectedInvoiceSummary([
|
|
'status' => $status,
|
|
'payload' => null,
|
|
'result' => null,
|
|
'error_message' => null,
|
|
'progress_message' => null,
|
|
]);
|
|
|
|
expect($summary['message'])->toBe($expected);
|
|
}
|
|
});
|
|
|
|
it('handles object payload/result values and malformed fields without throwing', function (): void {
|
|
$summary = economic_transfer_queue_details_summary::buildCollectedInvoiceSummary([
|
|
'status' => economic_transfer_queue::STATUS_COMPLETED,
|
|
'payload' => (object)[
|
|
'collected_invoice_id' => '501',
|
|
'send_as_is' => 'invalid',
|
|
'requested_by' => '-1',
|
|
],
|
|
'result' => (object)[
|
|
'draft_invoice_id' => '44',
|
|
'booked_invoice_id' => '55',
|
|
'total_net_amount' => 'invalid',
|
|
'user' => (object)[
|
|
'customer_number' => '9345',
|
|
'company_name' => 'Acme Carrier',
|
|
],
|
|
],
|
|
'error_message' => null,
|
|
]);
|
|
|
|
expect($summary['target'])->toBe([
|
|
'collected_invoice_id' => 501,
|
|
'send_as_is' => null,
|
|
'requested_by' => null,
|
|
]);
|
|
expect($summary['customer'])->toBe([
|
|
'customer_number' => 9345,
|
|
'name' => 'Acme Carrier',
|
|
]);
|
|
expect($summary['outcome'])->toBe([
|
|
'economic_invoice_draft_id' => 44,
|
|
'economic_invoice_booked_id' => 55,
|
|
'external_id' => null,
|
|
'total_net_amount' => null,
|
|
'order_count' => null,
|
|
]);
|
|
expect($summary['raw_available'])->toBe([
|
|
'payload' => true,
|
|
'result' => true,
|
|
]);
|
|
});
|