Add group-class withdrawal deadline and kind-aware offering form
CI / Tests (PHP 8.1) (pull_request) Successful in 44s
CI / Tests (PHP 8.2) (pull_request) Successful in 59s
CI / No Debug Code (pull_request) Successful in 3s
CI / Coding Standards (pull_request) Successful in 2m53s
CI / PHPStan (pull_request) Successful in 2m55s
CI / Tests (PHP 8.3) (pull_request) Successful in 2m41s
CI / Build Plugin Zip (pull_request) Skipped
CI / Tests (PHP 8.1) (pull_request) Successful in 44s
CI / Tests (PHP 8.2) (pull_request) Successful in 59s
CI / No Debug Code (pull_request) Successful in 3s
CI / Coding Standards (pull_request) Successful in 2m53s
CI / PHPStan (pull_request) Successful in 2m55s
CI / Tests (PHP 8.3) (pull_request) Successful in 2m41s
CI / Build Plugin Zip (pull_request) Skipped
Group classes now carry an optional per-class withdrawal deadline. Up to
that day a student may withdraw themselves from the class; the withdrawal
frees the seat and voids any pending payment but never issues an account
credit. After the deadline self-withdrawal closes and a studio admin must
withdraw the student by hand (the admin path is never subject to the
deadline). A blank deadline keeps self-withdrawal open indefinitely.
Also make the Add/Edit Offering form show only the fields relevant to the
selected kind: group settings for group classes, weekly reservation for
private lessons. Progressive enhancement — without JS every field renders.
- New nullable us_offerings.withdrawal_deadline column; Offering model gains
$withdrawalDeadline + isWithdrawalOpen().
- New student endpoint POST /enrollments/{id}/withdraw, gated by the deadline
(403 withdrawal_closed), ownership-checked, idempotent.
- Front-end group-class page shows a Withdraw button while open.
- No USC_VERSION bump: 1.2.0 is unreleased and accumulates schema changes
under its section, matching the scheduled-billing and credit features.
Tests: composer test (596), composer lint, composer cs all pass.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
@@ -69,6 +69,7 @@ class Offering {
|
||||
public readonly ?string $termEnd = null,
|
||||
public readonly ?string $classTime = null,
|
||||
public readonly ?string $enrollmentDeadline = null,
|
||||
public readonly ?string $withdrawalDeadline = null,
|
||||
public readonly ?string $scheduleNote = null,
|
||||
public readonly ?string $etransferEmail = null,
|
||||
public readonly ?int $cancellationCutoffHours = null,
|
||||
@@ -114,6 +115,19 @@ class Offering {
|
||||
return null === $deadline || $today <= $deadline;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether a student may still withdraw themselves from this group class on
|
||||
* `$today` (a `Y-m-d` date). Withdrawal stays open through the end of the
|
||||
* deadline day. Unlike the enrolment deadline there is no implicit default: a
|
||||
* class with no withdrawal deadline set stays open to withdrawal for its whole
|
||||
* life, so the instructor must set a date to lock students in. A withdrawal
|
||||
* made while open never issues an account credit — it only frees the seat and
|
||||
* voids any still-pending payment.
|
||||
*/
|
||||
public function isWithdrawalOpen( string $today ): bool {
|
||||
return null === $this->withdrawalDeadline || $today <= $this->withdrawalDeadline;
|
||||
}
|
||||
|
||||
/**
|
||||
* Normalise a submitted term date to canonical `Y-m-d`, or null when it is
|
||||
* not a real calendar date. Round-trips through DateTimeImmutable so
|
||||
@@ -214,6 +228,7 @@ class Offering {
|
||||
termEnd: Val::stringOrNull( $row->term_end ),
|
||||
classTime: Val::stringOrNull( $row->class_time ?? null ),
|
||||
enrollmentDeadline: Val::stringOrNull( $row->enrollment_deadline ?? null ),
|
||||
withdrawalDeadline: Val::stringOrNull( $row->withdrawal_deadline ?? null ),
|
||||
scheduleNote: Val::stringOrNull( $row->schedule_note ),
|
||||
etransferEmail: Val::stringOrNull( $row->etransfer_email ),
|
||||
cancellationCutoffHours: Val::intOrNull( $row->cancellation_cutoff_hours ),
|
||||
@@ -249,6 +264,7 @@ class Offering {
|
||||
'term_end' => $this->termEnd,
|
||||
'class_time' => $this->classTime,
|
||||
'enrollment_deadline' => $this->enrollmentDeadline,
|
||||
'withdrawal_deadline' => $this->withdrawalDeadline,
|
||||
'schedule_note' => $this->scheduleNote,
|
||||
'cancellation_cutoff_hours' => $this->cancellationCutoffHours,
|
||||
'access_mode' => $this->accessMode,
|
||||
|
||||
Reference in New Issue
Block a user