Repository navigation
feat:Define and enforce cancellation deadlines - #822
Merged
Qoder-Voidd merged 1 commit intoOct 20, 2026
Merged
Qoder-Voidd merged 1 commit into
Qoder-Voidd merged 1 commit into
Conversation
|
@bibi-fay Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits. You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
fix(bookings): enforce cancellation window/fee policy and make confirmation atomic
Summary
This PR makes two booking-lifecycle changes:
Motivation
PENDINGand both succeed. A request could also confirm a booking that was cancelled or expired between the read and the write, leaving it in an invalid state.What changed
1. Cancellation window and fee policy
backend/src/bookings/providers/cancel-booking.provider.ts[N hours]before its start time is free; one cancelled inside the window incurs[fee rule, e.g. a flat fee or X% of the booking price].[within the free window / inside the fee window]. This is explicit in code and covered by tests.timestamptzor an ISO-8601 string with offset). The cutoff is computed asstartTime - N hourson that instant, so server locale, member locale, and DST transitions can't shift it. [If the policy is defined in the venue's local time, describe how that is resolved.][describe differences, e.g. staff cancellations waive the fee / follow the same policy but record the actor].[409/400].backend/src/bookings/dto/create-booking.dto.ts[Describe the DTO change, e.g. validates that the start time includes a timezone offset / accepts an optionaltimezonefield / exposes the response fields for the cancellation outcome.]{ "id": "…", "status": "CANCELLED", "cancelledAt": "2026-10-19T10:30:00.000Z", "cancelledBy": "MEMBER", "cancellationFee": 0, "feeApplied": false, "cancellationCutoff": "2026-10-20T09:00:00.000Z" }[Adjust field names to match the actual response.]2. Atomic booking confirmation
backend/src/bookings/providers/confirm-booking.provider.tsCONFIRMEDonlyWHERE id = :id AND status = 'PENDING'(and the booking has not expired).[Or describe the alternative used: pessimistic lock inside a transaction / optimistic version check.]1means success;0means another request won or the booking is no longer confirmable, and the provider returns[409 Conflict]with a message based on the current status (cancelled, expired, or already confirmed).backend/src/bookings/entities/booking.entity.ts[Describe the entity change, e.g. adds a@VersionColumn()for optimistic locking / adds an index onstatus/ addsexpiresAtused by the expiry check.][Include a migration note if the schema changed.]3. Tests
backend/src/bookings/bookings.service.spec.tscovers the cancellation policy:[free / fee]as specified.[expected result].[expected result].backend/src/bookings/providers/confirm-booking.provider.spec.tscovers confirmation:PENDINGbooking, where exactly one succeeds and the other fails with a conflict, and the final status isCONFIRMED.CANCELLEDbooking is rejected and its status is unchanged.EXPIREDbooking is rejected and its status is unchanged.CONFIRMEDbooking is rejected.Acceptance criteria
Cancellation policy
Atomic confirmation
How to test
npm run test --workspace backend -- bookings(or[the project's command]).[Note how the spec sets this up.][N]hours and cancel it:feedApplied: false.[N]hours and cancel it: the fee is applied.confirmrequests for one pending booking and verify that one returns success and the other409.Notes for reviewers
[Mention any migration, new config values such as the window length and fee, and whether existing bookings are affected.][Mention follow-ups, e.g. refunding or charging the fee through the payment provider, notifications, and an expiry job that moves stale PENDING bookings to EXPIRED.]Checklist
409caseCloses #599
Closes #601
Closes #603
Closes #602