52 lines
3.7 KiB
PHP
52 lines
3.7 KiB
PHP
<?php
|
|||
|
|
declare(strict_types=1);
|
||
|
|
|
||
|
|
require_once __DIR__ . '/../app/Domain/Client/ContactEditCommand.php';
|
||
|
|
require_once __DIR__ . '/../app/Domain/Reporting/ClientHistoryService.php';
|
||
|
|
require_once __DIR__ . '/../app/Domain/Jobcard/TimeEntryCorrectionCommand.php';
|
||
|
|
|
||
|
|
use App\Domain\Client\ContactEditCommand;
|
||
|
|
use App\Domain\Reporting\ClientHistoryService;
|
||
|
|
use App\Domain\Jobcard\TimeEntryCorrectionCommand;
|
||
|
|
|
||
|
|
function regression_assert(bool $condition, string $message): void
|
||
|
|
{
|
||
|
|
if (!$condition) throw new RuntimeException($message);
|
||
|
|
}
|
||
|
|
|
||
|
|
$contacts = [
|
||
|
|
['id' => 1, 'client_id' => 7, 'name' => 'Jane', 'email' => 'jane@example.test', 'is_primary' => true],
|
||
|
|
['id' => 2, 'client_id' => 7, 'name' => 'John', 'email' => 'john@example.test', 'is_primary' => false],
|
||
|
|
];
|
||
|
|
$contact = new ContactEditCommand();
|
||
|
|
|
||
|
|
$badEdit = $contact->validateEdit('not-an-id', ['client_id' => 7, 'name' => 'John'], $contacts);
|
||
|
|
regression_assert($badEdit['valid'] === false && isset($badEdit['errors']['id']), 'Malformed contact IDs must return validation errors.');
|
||
|
|
$move = $contact->validateEdit(2, ['client_id' => 8, 'name' => 'John'], $contacts);
|
||
|
|
regression_assert($move['valid'] === false && isset($move['errors']['client_id']), 'A contact client ID must be immutable during edit.');
|
||
|
|
$sole = $contact->validateDelete('2', [['id' => 2, 'client_id' => 7, 'is_primary' => true]]);
|
||
|
|
regression_assert($sole['valid'] === false && isset($sole['errors']['delete']), 'The sole contact must not be deletable.');
|
||
|
|
$badPrimary = $contact->setPrimary('0', $contacts);
|
||
|
|
regression_assert($badPrimary['valid'] === false && isset($badPrimary['errors']['id']), 'Malformed primary IDs must return validation errors.');
|
||
|
|
$primary = $contact->setPrimary(2, $contacts);
|
||
|
|
regression_assert($primary['valid'] === true && $primary['replace_primary_contact_ids'] === [1] && $primary['audit']['event'] === 'client_contact_primary_set', 'Set-primary must nominate demotions and expose an audit payload.');
|
||
|
|
|
||
|
|
$history = new ClientHistoryService();
|
||
|
|
$badHistory = $history->validateForClient('7x', [['id' => 1, 'client_id' => 7, 'changed_at' => '2026-09-01']]);
|
||
|
|
regression_assert($badHistory['valid'] === false && isset($badHistory['errors']['client_id']), 'Malformed history client IDs must return validation errors.');
|
||
|
|
$timeline = $history->timeline([['id' => 2, 'client_id' => 7, 'changed_at' => '2026-09-02'], ['id' => 1, 'client_id' => 7, 'changed_at' => '2026-09-01']], 7);
|
||
|
|
regression_assert($timeline['valid'] === true && array_column($timeline['timeline'], 'id') === [1, 2], 'Client history timeline must be deterministic and controller-ready.');
|
||
|
|
|
||
|
|
$entry = ['id' => 9, 'jobcard_id' => 12, 'technician_id' => 4, 'work_date' => '2026-09-01', 'hours' => 2, 'notes' => 'old', 'counts_toward_sla' => true, 'voided' => false];
|
||
|
|
$correction = new TimeEntryCorrectionCommand();
|
||
|
|
$immutable = $correction->validateCorrection($entry, ['technician_id' => 99]);
|
||
|
|
regression_assert($immutable['valid'] === false && isset($immutable['errors']['technician_id']), 'Technician ID must be immutable during correction.');
|
||
|
|
$fixed = $correction->validateCorrection($entry, ['hours' => '3.25', 'notes' => ' corrected ']);
|
||
|
|
regression_assert($fixed['valid'] === true && $fixed['audit']['changed_fields'] === ['hours', 'notes'], 'Correction must expose changed fields for audit.');
|
||
|
|
$missingReason = $correction->validateVoid($entry, []);
|
||
|
|
regression_assert($missingReason['valid'] === false && isset($missingReason['errors']['reason']), 'Void reason is mandatory.');
|
||
|
|
$void = $correction->validateVoid($entry, ['reason' => 'Duplicate entry']);
|
||
|
|
regression_assert($void['valid'] === true && $void['audit']['void_reason'] === 'Duplicate entry', 'Void must expose the normalized reason in its audit payload.');
|
||
|
|
|
||
|
|
printf("Domain workflow regression tests: 10 passed\n");
|