add notes/remark and refactor round-trip
PHP Tests / php-tests (push) Has been cancelled

This commit is contained in:
Nyan Lin Paing
2026-08-22 21:43:41 +07:00
parent 894352b43f
commit fa908cdcaf
46 changed files with 1679 additions and 182 deletions
@@ -152,3 +152,57 @@ test('a failed gateway refund is persisted as failed, leaves the booking untouch
Event::assertNotDispatched(RefundProcessed::class);
});
/**
* Round trip: payment is combined on the outbound ("primary") leg the
* return leg has no Payment of its own (domain.md §2b).
*/
function confirmedRoundTripWithCombinedPayment(string $outboundPrice, string $returnPrice): array
{
$outbound = Booking::factory()->create(['status' => BookingStatus::Confirmed, 'price' => $outboundPrice]);
$return = Booking::factory()->create([
'status' => BookingStatus::Confirmed,
'price' => $returnPrice,
'is_return_leg' => true,
'linked_booking_id' => $outbound->id,
]);
$outbound->update(['linked_booking_id' => $return->id]);
$combined = bcadd($outboundPrice, $returnPrice, 2);
Payment::factory()->completed()->create([
'booking_id' => $outbound->id,
'gateway' => PaymentMethod::KbzMiniApp,
'amount' => $combined,
'gateway_transaction_id' => 'EVB-ROUNDTRIP-REFUND-1',
]);
return [$outbound->fresh(), $return->fresh()];
}
test('refunding a return leg draws a partial refund against the primary leg\'s combined payment', function () {
[$outbound, $return] = confirmedRoundTripWithCombinedPayment('9000.00', '11000.00');
$refund = app(RefundBookingAction::class)->handle($return, '11000', 'return leg cancelled');
expect($refund->status)->toBe(RefundStatus::Completed)
->and($refund->payment_id)->toBe($outbound->payments()->first()->id)
->and($return->refresh()->status)->toBe(BookingStatus::Cancelled)
->and($outbound->refresh()->status)->toBe(BookingStatus::Confirmed);
});
test('each leg of a round trip can be cancelled/refunded independently without exceeding the combined payment', function () {
[$outbound, $return] = confirmedRoundTripWithCombinedPayment('9000.00', '11000.00');
app(RefundBookingAction::class)->handle($return, '11000', 'return leg cancelled');
$second = app(RefundBookingAction::class)->handle($outbound, '9000', 'outbound leg cancelled too');
expect($second->status)->toBe(RefundStatus::Completed)
->and($outbound->refresh()->status)->toBe(BookingStatus::Cancelled)
->and($return->refresh()->status)->toBe(BookingStatus::Cancelled);
// Cumulative refunds (20000) exactly match the combined payment total —
// a third refund attempt on either leg must now fail.
expect(fn () => app(RefundBookingAction::class)->handle($outbound, '1', 'over the limit'))
->toThrow(RefundNotAllowedException::class);
});