Improve the superuser invoice-period review API, stale-preview protection, queue visibility, review blockers, and e-conomic eligibility.
95 lines
3.8 KiB
PHP
95 lines
3.8 KiB
PHP
<?php
|
|
|
|
app_require('classes/invoice_collection_bulk_action_service.php');
|
|
|
|
use classes\invoice_collection_bulk_action_service;
|
|
|
|
it('rejects stale bulk-action previews with a content digest and conflict response', function (): void {
|
|
$service = (string)file_get_contents(app_path('classes/invoice_collection_bulk_action_service.php'));
|
|
$route = (string)file_get_contents(app_path('routes/orderInvoicesRoute.php'));
|
|
|
|
expect($service)
|
|
->toContain('$preview[\'content_digest\'] = $this->previewContentDigest($preview);')
|
|
->toContain('hash_equals((string)($cached[\'preview\'][\'content_digest\'] ?? \'\'), $freshDigest)')
|
|
->toContain('throw new invoice_collection_bulk_action_conflict(')
|
|
->and($route)
|
|
->toContain('catch (invoice_collection_bulk_action_conflict $e)')
|
|
->toContain('$response->error($e->getMessage(), 409);');
|
|
});
|
|
|
|
it('changes the stale-preview digest when an export-relevant line changes', function (): void {
|
|
global $db;
|
|
|
|
$previousDb = $GLOBALS['db'] ?? null;
|
|
$hadDb = array_key_exists('db', $GLOBALS);
|
|
$db = new class {
|
|
public array $rows = [];
|
|
|
|
public function query(string $sql): object
|
|
{
|
|
expect($sql)
|
|
->toContain('oi.price')
|
|
->toContain('oi.quantity')
|
|
->toContain('p.economic_product_id')
|
|
->toContain('o.reference AS order_reference');
|
|
return new class($this->rows) {
|
|
private int $index = 0;
|
|
|
|
public function __construct(private readonly array $rows)
|
|
{
|
|
}
|
|
|
|
public function fetch_assoc(): ?array
|
|
{
|
|
return $this->rows[$this->index++] ?? null;
|
|
}
|
|
};
|
|
}
|
|
};
|
|
|
|
try {
|
|
$service = (new ReflectionClass(invoice_collection_bulk_action_service::class))->newInstanceWithoutConstructor();
|
|
$method = (new ReflectionClass(invoice_collection_bulk_action_service::class))
|
|
->getMethod('collectionExportContentDigest');
|
|
|
|
$db->rows = [[
|
|
'order_id' => 91,
|
|
'order_item_id' => 191,
|
|
'product_id' => 7,
|
|
'price' => 100,
|
|
'quantity' => 1,
|
|
'product_name' => 'Wash',
|
|
'economic_product_id' => 700,
|
|
]];
|
|
$before = $method->invoke($service, 41);
|
|
$db->rows[0]['price'] = 125;
|
|
$after = $method->invoke($service, 41);
|
|
|
|
expect($before)->toMatch('/^[a-f0-9]{64}$/')
|
|
->and($after)->toMatch('/^[a-f0-9]{64}$/')
|
|
->and($after)->not->toBe($before);
|
|
} finally {
|
|
if ($hadDb) {
|
|
$db = $previousDb;
|
|
} else {
|
|
unset($GLOBALS['db']);
|
|
}
|
|
}
|
|
});
|
|
|
|
it('enqueues bulk E-conomic transfers durably and deduplicates active jobs by global target', function (): void {
|
|
$service = (string)file_get_contents(app_path('classes/invoice_collection_bulk_action_service.php'));
|
|
$queue = (string)file_get_contents(app_path('classes/economic_transfer_queue.php'));
|
|
|
|
expect($service)
|
|
->toContain('self::ACTION_QUEUE_ECONOMIC => $this->applyQueueEconomic(')
|
|
->toContain('economic_transfer_queue::TYPE_COLLECTED_INVOICE_EXPORT')
|
|
->toContain("'queue_job_ids'")
|
|
->toContain('public static function assertCollectionCanQueueEconomic(')
|
|
->toContain('(new economic())->assertCustomerNumberIsNotDraft(')
|
|
->and($queue)
|
|
->toContain('Active work is unique by transfer type and business target across all requesting users.')
|
|
->toContain('CAST(JSON_UNQUOTE(JSON_EXTRACT(payload_json, \'$json_path\')) AS UNSIGNED) = ?')
|
|
->not->toContain("CAST(JSON_UNQUOTE(JSON_EXTRACT(payload_json, '$" . "json_path')) AS UNSIGNED) = ?\n AND created_by = ?");
|
|
});
|