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
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>
55 lines
1.4 KiB
PHP
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,
|
|
];
|
|
}
|
|
}
|