2026-09-01 18:54:47 +02:00
<? php
declare ( strict_types = 1 );
require_once __DIR__ . '/../app/Domain/Jobcard/JobcardReference.php' ;
require_once __DIR__ . '/../app/Domain/Jobcard/StatusTransitionValidator.php' ;
require_once __DIR__ . '/../app/Domain/Jobcard/TimeEntryValidator.php' ;
require_once __DIR__ . '/../app/Domain/Jobcard/TimeAggregator.php' ;
use App\Domain\Jobcard\JobcardReference ;
use App\Domain\Jobcard\StatusTransitionValidator ;
use App\Domain\Jobcard\TimeEntryValidator ;
use App\Domain\Jobcard\TimeAggregator ;
$reference = JobcardReference :: generate ( 42 , 2026 );
if ( $reference !== 'JC-2026-000042' ) throw new RuntimeException ( 'Expected generated jobcard reference.' );
if ( ! JobcardReference :: isValid ( $reference ) || JobcardReference :: isValid ( 'bad-reference' )) throw new RuntimeException ( 'Expected reference format validation.' );
$transitions = new StatusTransitionValidator ();
if ( ! $transitions -> canTransition ( 'new' , 'assigned' )) throw new RuntimeException ( 'new should transition to assigned.' );
if ( $transitions -> canTransition ( 'new' , 'completed' )) throw new RuntimeException ( 'new should not skip to completed.' );
if ( ! $transitions -> canTransition ( 'in_progress' , 'in_progress' )) throw new RuntimeException ( 'Same status should be allowed.' );
$validEntry = ( new TimeEntryValidator ()) -> validate ([ 'work_date' => '2026-09-01' , 'start_time' => '09:00' , 'end_time' => '11:30' ]);
if ( ! $validEntry [ 'valid' ] || $validEntry [ 'hours' ] !== 2.5 || $validEntry [ 'errors' ] !== []) throw new RuntimeException ( 'Expected valid time entry.' );
$invalidEntry = ( new TimeEntryValidator ()) -> validate ([ 'work_date' => 'not-a-date' , 'start_time' => '11:00' , 'end_time' => '10:00' ]);
if ( $invalidEntry [ 'valid' ] || count ( $invalidEntry [ 'errors' ]) !== 2 ) throw new RuntimeException ( 'Expected invalid time entry errors.' );
$nonNumericEntry = ( new TimeEntryValidator ()) -> validate ([ 'work_date' => '2026-09-01' , 'hours' => 'not-a-number' ]);
if ( $nonNumericEntry [ 'valid' ] || ! isset ( $nonNumericEntry [ 'errors' ][ 'hours' ])) throw new RuntimeException ( 'Expected non-numeric hours to be rejected.' );
$aggregator = new TimeAggregator ();
if ( $aggregator -> total ([[ 'hours' => 2.25 ], [ 'hours' => 1.5 ], [ 'hours' => - 4 ]]) !== 3.75 ) throw new RuntimeException ( 'Expected positive time aggregation.' );
2026-09-01 18:58:18 +02:00
if ( $aggregator -> slaTotal ([[ 'hours' => 2 , 'counts_toward_sla' => true ], [ 'hours' => 3 , 'counts_toward_sla' => false ], [ 'hours' => 1 , 'counts_toward_sla' => 1 ]]) !== 3.0 ) throw new RuntimeException ( 'Expected SLA-filtered aggregation.' );
2026-09-01 18:54:47 +02:00
printf ( "Jobcard domain tests: 12 passed \n " );