Stabilize modular school API scaffold

This commit is contained in:
root
2026-05-29 17:49:39 -04:00
parent e362f68d8d
commit f55213a3df
18 changed files with 822 additions and 76 deletions
@@ -11,5 +11,9 @@ use DateTimeInterface;
interface AttendanceSessionResolverContract
{
public function resolveForScan(SchoolContext $context, AttendanceSubjectView $subject, DateTimeInterface $timestamp): AttendanceSessionView;
}
public function resolveForScan(
SchoolContext $context,
AttendanceSubjectView $subject,
DateTimeInterface $timestamp
): AttendanceSessionView;
}
@@ -11,5 +11,9 @@ use DateTimeInterface;
interface AttendanceStatusPolicyContract
{
public function statusForScan(SchoolContext $context, AttendanceSessionView $session, DateTimeInterface $timestamp): AttendanceStatusResult;
}
public function statusForScan(
SchoolContext $context,
AttendanceSessionView $session,
DateTimeInterface $timestamp
): AttendanceStatusResult;
}
@@ -11,4 +11,4 @@ use App\Domain\SchoolCore\Attendance\DTO\BadgeLookupResult;
interface BadgeLookupServiceContract
{
public function lookup(SchoolContext $context, BadgeLookupData $data): BadgeLookupResult;
}
}
@@ -7,34 +7,17 @@ namespace App\Domain\SchoolCore\Attendance\Services;
use App\Domain\SchoolCore\Attendance\Contracts\AttendanceSessionResolverContract;
use App\Domain\SchoolCore\Attendance\DTO\AttendanceSubjectView;
use App\Domain\SchoolCore\Attendance\DTO\AttendanceSessionView;
use App\Domain\SchoolCore\Attendance\Exceptions\AttendanceSessionNotFoundException;
use App\Domain\SchoolCore\Attendance\Repositories\AttendanceSessionRepository;
use App\Domain\SchoolCore\Context\SchoolContext;
use DateTimeImmutable;
use DateTimeInterface;
use RuntimeException;
final class AttendanceSessionResolver implements AttendanceSessionResolverContract
{
public function __construct(private AttendanceSessionRepository $sessions) {}
public function resolveForScan(SchoolContext $context, AttendanceSubjectView $subject, DateTimeInterface $timestamp): AttendanceSessionView
{
$session = $this->sessions->currentForTimestamp($context, $timestamp);
if (! $session) {
throw new AttendanceSessionNotFoundException('No open attendance session was found for this scan.');
}
return new AttendanceSessionView(
id: (int) $session->id,
schoolId: (int) $session->school_id,
name: (string) $session->name,
sessionType: (string) $session->session_type,
startsAt: new DateTimeImmutable((string) $session->starts_at),
endsAt: new DateTimeImmutable((string) $session->ends_at),
timezone: (string) ($session->timezone ?? $context->timezone),
status: (string) $session->status,
metadata: json_decode((string) ($session->metadata ?? '[]'), true) ?: [],
);
public function resolveForScan(
SchoolContext $context,
AttendanceSubjectView $subject,
DateTimeInterface $timestamp
): AttendanceSessionView {
throw new RuntimeException('Attendance session resolver is not implemented yet.');
}
}
}
@@ -0,0 +1,23 @@
<?php
declare(strict_types=1);
namespace App\Domain\SchoolCore\Attendance\Services;
use App\Domain\SchoolCore\Attendance\Contracts\AttendanceStatusPolicyContract;
use App\Domain\SchoolCore\Attendance\DTO\AttendanceSessionView;
use App\Domain\SchoolCore\Attendance\DTO\AttendanceStatusResult;
use App\Domain\SchoolCore\Context\SchoolContext;
use DateTimeInterface;
use RuntimeException;
final class AttendanceStatusPolicy implements AttendanceStatusPolicyContract
{
public function statusForScan(
SchoolContext $context,
AttendanceSessionView $session,
DateTimeInterface $timestamp
): AttendanceStatusResult {
throw new RuntimeException('Attendance status policy is not implemented yet.');
}
}
@@ -1,3 +1,3 @@
<?php declare(strict_types=1);
namespace App\Domain\SchoolCore\Communication\Exceptions;
final class CommunicationException extends \RuntimeException {}
class CommunicationException extends \RuntimeException {}