Let students cancel their own lessons from the booking page
CI / No Debug Code (push) Successful in 3s
CI / Coding Standards (push) Successful in 46s
CI / Tests (PHP 8.1) (push) Successful in 45s
CI / Tests (PHP 8.2) (push) Successful in 45s
CI / PHPStan (push) Successful in 1m11s
CI / Tests (PHP 8.3) (push) Successful in 1m0s
CI / Build Plugin Zip (push) Successful in 1m10s
CI / No Debug Code (push) Successful in 3s
CI / Coding Standards (push) Successful in 46s
CI / Tests (PHP 8.1) (push) Successful in 45s
CI / Tests (PHP 8.2) (push) Successful in 45s
CI / PHPStan (push) Successful in 1m11s
CI / Tests (PHP 8.3) (push) Successful in 1m0s
CI / Build Plugin Zip (push) Successful in 1m10s
Adds POST /bookings/{id}/cancel (owner-only, idempotent): marks the lesson
cancelled, releases the availability slot for rebooking, and voids a
still-pending payment so it leaves the admin confirmation queue. Paid
payments are untouched — refunds stay a manual admin decision.
The instructor PATCH /bookings/{id}/status path now does the same slot
release and payment voiding on cancellation (previously cancelled lessons
left their slot permanently booked), and reinstating a cancelled lesson
re-claims the slot, rejecting with 409 if the freed time was rebooked.
The "Your upcoming lessons" panel gets a Cancel button with a confirm
prompt; on success both the lesson list and the slot calendar refresh.
Co-Authored-By: Claude Fable 5 <[email protected]>
This commit is contained in:
@@ -65,6 +65,30 @@ class PaymentServiceTest extends TestCase
|
||||
self::assertNull($this->service->createForRegistration(Payment::REG_LESSON, 12, 5, 3, 0.0, 'CAD'));
|
||||
}
|
||||
|
||||
public function testVoidPendingMarksPendingPaymentFailed(): void
|
||||
{
|
||||
$this->payments->shouldReceive('findById')->with(50)->andReturn($this->payment(Payment::METHOD_ETRANSFER, Payment::STATUS_PENDING, 50));
|
||||
$this->payments->shouldReceive('updateStatus')->once()->with(50, Payment::STATUS_FAILED)->andReturn(true);
|
||||
|
||||
$this->service->voidPending(50);
|
||||
}
|
||||
|
||||
public function testVoidPendingLeavesPaidPaymentAlone(): void
|
||||
{
|
||||
// Refunds are manual: cancelling a paid lesson must not touch the ledger.
|
||||
$this->payments->shouldReceive('findById')->with(50)->andReturn($this->payment(Payment::METHOD_CARD, Payment::STATUS_PAID, 50));
|
||||
$this->payments->shouldNotReceive('updateStatus');
|
||||
|
||||
$this->service->voidPending(50);
|
||||
}
|
||||
|
||||
public function testVoidPendingIgnoresNullPaymentId(): void
|
||||
{
|
||||
$this->payments->shouldNotReceive('findById');
|
||||
|
||||
$this->service->voidPending(null);
|
||||
}
|
||||
|
||||
public function testEtransferStaysPending(): void
|
||||
{
|
||||
$this->resolver->shouldReceive('resolve')->with(5)->andReturn(Payment::METHOD_ETRANSFER);
|
||||
|
||||
Reference in New Issue
Block a user