Add lesson booking registration flow (offering, questions, policies)
CI / Coding Standards (pull_request) Successful in 1m51s
CI / PHPStan (pull_request) Successful in 2m17s
CI / Tests (PHP 8.1) (pull_request) Successful in 2m24s
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 47s
CI / Build Plugin Zip (pull_request) Has been skipped
CI / Coding Standards (pull_request) Successful in 1m51s
CI / PHPStan (pull_request) Successful in 2m17s
CI / Tests (PHP 8.1) (pull_request) Successful in 2m24s
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 47s
CI / Build Plugin Zip (pull_request) Has been skipped
Implements #3: students register for a private lesson by picking a slot, answering the offering's intake questions, and accepting booking-scoped policies. Payment is a clean seam for #7 (lessons land pending; payment_id null; instructor confirms via PATCH /bookings/{id}/status). - Schema: us_lessons += offering_id, recurrence, series_id, payment_id. - Lesson: new fields + recurrence constants. - BookingRepository::insertSeries() builds a weekly series sharing a series_id; AvailabilityRepository::findUnbookedInGroup() reserves a group. - RegistrationGate (src/Registration/): validate + record intake answers and booking-scoped policy acceptances. Reused by group enrolment (#4). - BookingEndpoint::book(): offering_id, recurrence, answers, accepted_policy_version_ids; single or weekly; records answers/acceptances (type lesson). - GET /policies?scope=booking filter. - Front-end booking.js: slot -> questions + policies -> submit. - Wiring: RegistrationGate built in Plugin, passed via RestRegistrar. - Test-only WP_Error stub in tests/bootstrap.php for gate testing. Refs #3 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -34,19 +34,43 @@ class BookingRepositoryTest extends TestCase
|
||||
Mockery::on(static function (array $data): bool {
|
||||
return $data['slot_id'] === 10
|
||||
&& $data['student_id'] === 5
|
||||
&& $data['offering_id'] === 7
|
||||
&& $data['recurrence'] === Lesson::RECURRENCE_SINGLE
|
||||
&& $data['status'] === Lesson::STATUS_PENDING;
|
||||
}),
|
||||
['%d', '%d', '%d', '%s', '%s', '%s']
|
||||
['%d', '%d', '%d', '%d', '%s', '%d', '%s', '%d', '%s', '%s']
|
||||
);
|
||||
|
||||
$this->db->insert_id = 77;
|
||||
|
||||
$lesson = new Lesson(slotId: 10, studentId: 5, instructorId: 3);
|
||||
$lesson = new Lesson(slotId: 10, studentId: 5, instructorId: 3, offeringId: 7);
|
||||
$result = $this->repo->insert($lesson);
|
||||
|
||||
self::assertSame(77, $result);
|
||||
}
|
||||
|
||||
public function testInsertSeriesSharesSeriesIdAcrossSlots(): void
|
||||
{
|
||||
Functions\when('current_time')->justReturn('2026-04-01 12:00:00');
|
||||
|
||||
$ids = [40, 41, 42];
|
||||
$this->db->shouldReceive('insert')
|
||||
->times(3)
|
||||
->andReturnUsing(function () use (&$ids): void {
|
||||
$this->db->insert_id = array_shift($ids);
|
||||
});
|
||||
|
||||
// The first lesson is back-filled with its own id as the series id.
|
||||
$this->db->shouldReceive('update')
|
||||
->once()
|
||||
->with('wp_us_lessons', ['series_id' => 40], ['id' => 40], ['%d'], ['%d']);
|
||||
|
||||
$template = new Lesson(slotId: 0, studentId: 5, instructorId: 3, offeringId: 7);
|
||||
$result = $this->repo->insertSeries($template, [100, 101, 102]);
|
||||
|
||||
self::assertSame([40, 41, 42], $result);
|
||||
}
|
||||
|
||||
public function testFindByIdReturnsNullWhenNotFound(): void
|
||||
{
|
||||
$this->db->shouldReceive('prepare')->andReturn('SELECT ...');
|
||||
@@ -60,9 +84,13 @@ class BookingRepositoryTest extends TestCase
|
||||
$row = (object) [
|
||||
'id' => '15',
|
||||
'slot_id' => '10',
|
||||
'offering_id' => null,
|
||||
'student_id' => '5',
|
||||
'instructor_id' => '3',
|
||||
'recurrence' => Lesson::RECURRENCE_SINGLE,
|
||||
'series_id' => null,
|
||||
'status' => 'pending',
|
||||
'payment_id' => null,
|
||||
'notes' => null,
|
||||
];
|
||||
|
||||
@@ -109,9 +137,13 @@ class BookingRepositoryTest extends TestCase
|
||||
$row = (object) [
|
||||
'id' => '1',
|
||||
'slot_id' => '2',
|
||||
'offering_id' => null,
|
||||
'student_id' => '5',
|
||||
'instructor_id' => '3',
|
||||
'recurrence' => Lesson::RECURRENCE_SINGLE,
|
||||
'series_id' => null,
|
||||
'status' => 'pending',
|
||||
'payment_id' => null,
|
||||
'notes' => null,
|
||||
];
|
||||
|
||||
|
||||
Reference in New Issue
Block a user