Files
unsupervised-scheduler/src/GroupClass/Enrollment.php
T
thatguygriff 9cb5207dcd
CI / Tests (PHP 8.1) (pull_request) Successful in 45s
CI / Coding Standards (pull_request) Successful in 50s
CI / PHPStan (pull_request) Successful in 1m4s
CI / No Debug Code (pull_request) Successful in 2s
CI / Tests (PHP 8.2) (pull_request) Successful in 42s
CI / Tests (PHP 8.3) (pull_request) Successful in 42s
CI / Build Plugin Zip (pull_request) Has been skipped
Add group-class enrolment (year commitment, capacity, registration gate)
Implements #4: students enrol in a group_class offering via the same
registration gate as private lessons (intake questions + booking-scoped
policy acceptance). Enrolment is capacity-enforced and prevents duplicates.

- Schema: us_group_enrollments table.
- Enrollment value object + EnrollmentRepository (countActiveForOffering,
  hasActiveEnrollment, per-student/instructor/all-active queries, status).
- EnrollmentEndpoint: GET /enrollments (scoped) and POST /enrollments
  (validates group_class, capacity, no-duplicate; reuses RegistrationGate;
  records answers/acceptances type enrollment).
- GroupClassController + admin page (view_all_lessons): all active enrolments.
- Front-end: [us_group_classes] shortcode (GroupClassPage) + group-classes.js
  enrol flow (list classes -> questions + policies -> POST /enrollments).
- Wiring in Plugin, RestRegistrar, AdminMenu, ShortcodeRegistrar.

Payment is the deferred seam (#7): enrolment lands active, payment_id null.
JS left untested for parity with the repo's no-build vanilla-JS posture.

Tests: tests/Unit/GroupClass/ (Enrollment, EnrollmentRepository).
composer test (121), cs, and PHPStan level 6 all pass.

Refs #4

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-07 11:43:33 -03:00

55 lines
1.4 KiB
PHP

<?php
declare(strict_types=1);
namespace Unsupervised\Schedular\GroupClass;
class Enrollment {
public const STATUS_ACTIVE = 'active';
public const STATUS_CANCELLED = 'cancelled';
public const STATUS_COMPLETED = 'completed';
/**
* All valid enrolment statuses.
*
* @var list<string>
*/
public const VALID_STATUSES = [ self::STATUS_ACTIVE, self::STATUS_CANCELLED, self::STATUS_COMPLETED ];
public function __construct(
public readonly int $offeringId,
public readonly int $studentId,
public readonly int $instructorId,
public readonly string $status = self::STATUS_ACTIVE,
public readonly ?int $paymentId = null,
public readonly ?int $id = null,
) {}
public static function fromRow( object $row ): self {
return new self(
offeringId: (int) $row->offering_id,
studentId: (int) $row->student_id,
instructorId: (int) $row->instructor_id,
status: $row->status,
paymentId: null !== $row->payment_id ? (int) $row->payment_id : null,
id: (int) $row->id,
);
}
/**
* Returns a plain array representation of the enrolment.
*
* @return array<string, mixed>
*/
public function toArray(): array {
return [
'id' => $this->id,
'offering_id' => $this->offeringId,
'student_id' => $this->studentId,
'instructor_id' => $this->instructorId,
'status' => $this->status,
'payment_id' => $this->paymentId,
];
}
}