Appearance
Booking statuses
Page summary: Understand what state a booking is really in.
Use this when: Use this when building, testing, supporting, reporting on, or changing booking behaviour.
- A booking has five independent status models.
- “Confirmed” answers whether the trip is going ahead, not whether money arrived.
- Start with the status model; use the exact rules only when you need transition behaviour or edge cases.
A booking has five statuses, not one
They move independently. None controls the others.
| Status | Answers |
|---|---|
| Booking | Is the trip happening? |
| Item | Is each line accepted? |
| Payment | Has money arrived? |
| Invoice | Where is the bill? |
| Cancellation | Has someone asked to cancel, and was it agreed? |
So all of these are normal: confirmed and unpaid · cancelled and fully paid · paid while the invoice still says draft · confirmed with one line rejected · confirmed with a cancellation request waiting.
When someone says "the booking looks wrong", ask which of the five they are looking at. Different screens show different ones.
Evidence and test details
- Code
ems-backend/internal/shared/entities/booking.entity.go:33-38 - Checked Confirmed in code, 5 Aug 2026
Booking status
Is the trip happening.
| Shown as | Stored as | Means |
|---|---|---|
| Requested | requested | Guest asked. Vendor has not answered. |
| Pending customer confirmation | pending_customer_confirmation | Vendor proposed a change. Waiting on the guest. |
| Confirmed | confirmed | Going ahead. |
| Partially confirmed | partially_confirmed | Valid, but nothing sets it and nothing shows it. See A status nothing can display. |
| Rejected | rejected | Vendor turned it down. |
| In progress | in_progress | Happening now. |
| Done | done | Finished. |
| No show | no_show | Guest did not turn up. |
| Cancelled | cancelled | Called off. |
| Archived | archived | Filed away. Nothing can change afterwards. |
There is no "paid", "refunded" or "expired" booking status. Those belong to payment.
How a booking gets its first status
Guest books directly → requested. The vendor then reviews each line. Any line approved makes it confirmed. A line proposed for change makes it pending customer confirmation. All lines rejected makes it rejected.
Partner books → confirmed straight away, no vendor review.
Vendor books from the dashboard → confirmed, all checks skipped. See Vendor bookings skip every check.
Evidence and test details
- Code
ems-apis/constants/booking_status.go:5-29·ems-backend/internal/booking/usecases/booking_create.usecase.go:43·ems-backend/internal/booking/repositories/impl/booking.adapter.go:109-153·ems-backend/internal/booking/usecases/booking_reseller.usecase.go:229 - Checked Confirmed in code, 5 Aug 2026
What can change to what
| From | Can become |
|---|---|
| Confirmed | In progress, Done, No show, Cancelled, Archived |
| In progress | Confirmed, Done |
| No show | Confirmed |
| Cancelled | Confirmed, No show, Archived — but should not |
| Done | Confirmed, In progress |
| Archived | nothing |
| Requested, Rejected | nothing happens, and no error |
Anything else is refused with "Cannot revert back".
Evidence and test details
- Code
ems-backend/internal/booking/usecases/booking_internal.usecase.go:531-600 - Checked Confirmed in dev for Done → Confirmed and Done → In progress, booking
BO10GI1LMR7, 5 Aug 2026. Rest confirmed in code.
Item status
One line per thing booked. Each is accepted or refused on its own, and the lines decide the booking status — not the other way round.
Six values: requested · pending customer confirmation · rejected · confirmed · cancelled · no show.
A two-item booking with one item rejected still shows as confirmed. The guest is coming, for less than they asked for.
Evidence and test details
- Code
ems-apis/constants/booking_item_status.go:11-18 - Checked Confirmed in code, 5 Aug 2026
Payment status
Whether money arrived. Independent of whether the trip is happening.
Ten values: waiting payment · unpaid · due · overdue · processing · partially paid · paid · failed · partially refunded · refunded.
Every booking starts at waiting payment.
Evidence and test details
- Code
ems-apis/constants/payment_status.go:8-19·ems-backend/internal/booking/usecases/booking_create.usecase.go:47 - Checked Confirmed in code, 5 Aug 2026
Invoice status
Where the bill got to. Separate from whether money arrived.
Seven values: draft · invoice sent · partially paid · paid · partially refunded · fully refunded · voided.
Payment and invoice status share several words and can hold different values at once. The booking list shows the invoice one.
Evidence and test details
- Code
ems-apis/constants/invoice_status.go:5-13 - Checked Confirmed in dev — booking list badge is labelled "Invoice Status", 5 Aug 2026
Cancellation status
A cancellation is its own record. It exists from the moment someone asks, which is not the same as the booking being cancelled.
Two values: requested and confirmed. It can cover some lines or all of them, so there are four real situations:
| Partial | Full | |
|---|---|---|
| Requested | Asked to cancel part. Not agreed. | Asked to cancel all. Not agreed. |
| Confirmed | Part cancelled, rest stands. | All cancelled. |
Each cancelled line has its own refund amount, and the agreed amount can differ from the amount asked for.
A confirmed partial cancellation leaves the booking status at confirmed. That is correct.
Evidence and test details
- Code
ems-apis/constants/cancellation_status.go·ems-backend/internal/shared/entities/booking.entity.go:719-743 - Checked Confirmed in code, 5 Aug 2026
What each screen explains
The dashboard has a built-in status guide, reached from "Show status guide" on the booking list.
| Guide tab | Explains | Silent about |
|---|---|---|
| Booking | Confirmed, In progress, Cancelled, Done | Requested, Pending, Rejected, No show, Archived, Partially confirmed |
| Invoice | Invoice sent, Partially paid, Paid, Partially refunded, Fully refunded | Draft, Voided |
| Payment | Not paid, Processing, Paid, Partially refunded, Overdue, Due, Failed | Waiting payment, Partially paid, Refunded, Unpaid |
A vendor can see a status the guide does not explain — including waiting payment, which every booking starts at.
Evidence and test details
- Code
VMS-Frontend/apps/main/src/microapps/booking/components/BookingList/BookingListStatusGuidePopup/BookingListStatusGuidePopup.viewModel.tsx:16-40 - Checked Confirmed in dev, 5 Aug 2026
Rules
Archived is final BST-001
What happens today: Nothing can be changed once a booking is archived. The attempt is refused.
Applies to: Everyone.
Expected behaviour: Not established.
Status: No stated intent.
Evidence and test details
- Code
ems-backend/internal/booking/usecases/booking_internal.usecase.go:593-594 - Checked Confirmed in code, 5 Aug 2026
A cancelled booking cannot safely be reopened BST-002
What happens today: The API allows a cancelled booking back to confirmed, no show or archived. The dashboard blocks it — the status control is switched off entirely for cancelled bookings.
Why it matters: Cancelling releases the seats, stops the unpaid payment schedule and removes any promotion. Coming back to confirmed restores none of it.
Expected behaviour: A cancelled booking stays cancelled.
Status: Product and code do not match. Only the screen prevents it.
Evidence and test details
- Code
ems-backend/internal/booking/usecases/booking_internal.usecase.go:575-582· dashboardVMS-Frontend/apps/main/src/microapps/booking/components/BookingStatusDropdown/BookingStatusDropdown.viewModel.tsx:87-91, 127-136 - Checked Confirmed in code, 5 Aug 2026
- Test Call the status-change API on a cancelled booking, asking for confirmed. It should be refused.
- Follow-up Open decisions
A finished booking can be reopened BST-003
What happens today: A booking marked done can go back to confirmed or in progress.
Why it matters: The completion time is written when the booking becomes done and never cleared, so a reopened booking carries a completion time while not being complete. Reports read that field.
Expected behaviour: Exactly this. Confirmed by product.
Status: Matches, with a side effect worth knowing.
Evidence and test details
- Code
ems-backend/internal/booking/usecases/booking_internal.usecase.go:583-589 - Checked Confirmed in dev — booking
BO10GI1LMR7, the dropdown offered Confirmed and In Progress, 5 Aug 2026
Some status changes do nothing, and say they worked BST-004
What happens today: Changing the status of a booking at requested or rejected returns success and changes nothing. No error. Any follow-on action runs against the old status.
Why it matters: The automatic cancellation job uses this route. A booking still at requested would fail to cancel and record that it succeeded.
Expected behaviour: Not established — either refuse with an error, or allow it. Silent success is wrong either way.
Status: No stated intent. Not yet reproduced.
Evidence and test details
- Code
ems-backend/internal/booking/usecases/booking_internal.usecase.go:540-597 - Checked Confirmed in code, 5 Aug 2026. Not reproduced in dev.
- Test Take a booking at requested. Call the status-change API asking for cancelled. Check the response, then re-read the booking.
- Follow-up Open decisions
Propose-changes always moves the booking to pending BST-005
What happens today: Proposing a change to a line moves the booking to pending customer confirmation. There is a switch for it, and it is on in dev, staging and production.
Expected behaviour: This. The older path is unreachable anywhere.
Status: Matches.
Evidence and test details
- Code
ems-backend/internal/booking/repositories/impl/booking.adapter.go:122-128 - Checked Confirmed in code; setting read from all three environment configuration files, 5 Aug 2026
What cancelling actually does BST-006
What happens today: Three things together: unpaid payment schedules are stopped; any promotion is removed and its coupon released; a cancellation notification is triggered.
Exception: If the caller says what to do with each payment, that is used instead of stopping everything.
Expected behaviour: Not established.
Status: No stated intent.
Evidence and test details
- Code
ems-backend/internal/booking/usecases/booking_internal.usecase.go:471-483, 506-514, 602-616 - Checked Confirmed in code, 5 Aug 2026
Part-paid bookings are never cancelled automatically BST-007
What happens today: The automatic cancellation job stops if any part of the booking has been paid. A person can still cancel it by hand.
Why it matters: A deposit that never becomes a full payment holds its seat indefinitely.
Expected behaviour: Not established.
Status: No stated intent. Product has parked it with a recommendation.
Evidence and test details
- Code
ems-backend/internal/booking/usecases/booking_internal.usecase.go:415-428 - Checked Confirmed in code, 5 Aug 2026
- Follow-up Open decisions
Timestamps are written once and never cleared BST-008
What happens today: Requested time at creation, confirmed time on confirmation, completed time on done. None is cleared when the booking leaves that status.
Why it matters: Reopening a finished booking is allowed, so a booking can be confirmed while carrying a completion time.
Expected behaviour: Not established.
Status: No stated intent.
Evidence and test details
- Code
ems-backend/internal/booking/usecases/booking_create.usecase.go:44·ems-backend/internal/booking/repositories/impl/booking.adapter.go:131-133·ems-backend/internal/booking/usecases/booking_internal.usecase.go:485-488 - Checked Confirmed in code, 5 Aug 2026
Rejected bookings get a confirmation time BST-009
What happens today: Rejecting a booking sets the confirmed-at field to the moment of rejection.
Why it matters: Any report counting confirmations by that field counts rejections too.
Expected behaviour: Not established. Either the field is reused to mean "when this was decided", or it is a slip.
Status: No stated intent. Product has parked it with a recommendation.
Evidence and test details
- Code
ems-backend/internal/booking/repositories/impl/booking.adapter.go:140-144 - Checked Confirmed in code, 5 Aug 2026
- Follow-up Open decisions
Only instant-confirm experiences reach partners BST-010
What happens today: Partner bookings confirm without asking the vendor. Product says that is safe because experiences needing approval are never offered to partners.
Expected behaviour: This.
Status: The confirming half matches. The filtering half has not been found in the code.
Evidence and test details
- Code
ems-backend/internal/booking/usecases/booking_reseller.usecase.go:229 - Checked Confirmed in code for the confirm step; intent stated by product, 5 Aug 2026
- Follow-up Open decisions
The dashboard keeps its own copy of the transition rules BST-011
What happens today: The dashboard has its own list of which status can follow which, separate from the service's, and they disagree. The service allows archiving from confirmed and cancelled; the dashboard never offers it. The dashboard lists options for a cancelled booking then switches the button off.
Exception: For Get Your Guide bookings the dashboard switches the control off entirely.
Why it matters: What you can do depends on whether you use the screen or the API. The screen is currently the only thing preventing reopening a cancelled booking.
Expected behaviour: One list, in one place.
Status: Two copies, already drifted.
Evidence and test details
- Code
ems-backend/internal/booking/usecases/booking_internal.usecase.go:540-597againstVMS-Frontend/apps/main/src/microapps/booking/components/BookingStatusDropdown/BookingStatusDropdown.viewModel.tsx:68-98, 119-143 - Checked Confirmed in code, 5 Aug 2026
The dashboard expects payment values the service never sends BST-012
What happens today: The service sends a full refund as refunded; the dashboard expects fully_refunded. The dashboard also handles four values that do not exist — pending_payment, not_paid, invoice_sent, voided — and does not handle unpaid, which does exist.
Why it matters: An unrecognised value gets no label and no colour, because both are looked up from the value itself.
Expected behaviour: One agreed list.
Status: Mismatch.
Evidence and test details
- Code
ems-apis/constants/payment_status.go:8-19againstVMS-Frontend/packages/utils/enums/PaymentStatus.ts:13-27 - Checked Confirmed in code, 5 Aug 2026. Not yet seen on screen — needs a fully refunded booking in dev.
- Test Find or make a fully refunded booking in dev. Look at the payment status badge on the booking list.
A status nothing can display BST-013
What happens today: partially_confirmed is defined in the service and accepted as valid. Nothing sets it, and the dashboard has never heard of it — no label, no colour, no list of allowed next statuses.
Why it matters: It is accepted as valid, so anything setting a status through the API can put a booking into a state the dashboard cannot render.
Expected behaviour: Not established. Finish it or remove it.
Status: No stated intent.
Evidence and test details
- Code
ems-apis/constants/booking_status.go:10, 23; absent fromVMS-Frontend/packages/utils/enums/BookingStatus.tsand from the dashboard's transition list - Checked Confirmed in code, 5 Aug 2026
A payment status that fails its own validity check BST-014
What happens today: unpaid is defined, but left out of the service's own list of valid payment statuses. Any validity check rejects it.
Expected behaviour: Not established. Almost certainly a slip.
Status: No stated intent.
Evidence and test details
- Code
ems-apis/constants/payment_status.go:17defined; absent from the check at lines 21-31 - Checked Confirmed in code, 5 Aug 2026
A refunded invoice document says "Unpaid" BST-015
What happens today: The invoice PDF works out its own status word, separately from the badge on screen. Only four statuses have a word of their own; draft, partially refunded and fully refunded all fall through to "Unpaid". The PDF is rebuilt whenever the invoice changed since the file was last written — and a refund changes the invoice.
Why it matters: The PDF is what goes to the customer and what finance reconciles against. The badge on screen is correct; the document is not.
Expected behaviour: Every status has its own word.
Status: Mismatch, not yet seen on a real document.
Evidence and test details
- Code
ems-apis/constants/invoice_status.go:15-28, used atems-backend/internal/payment/usecase/invoice.usecase.go:719; rebuild-on-download at:454-458 - Checked Confirmed in code, 5 Aug 2026. No refunded invoice PDF opened yet.
- Test Find a fully refunded booking in dev, download its invoice, read the status word on the document.
The status guide explains a payment status that does not exist BST-016
What happens today: The dashboard's status guide describes "Not Paid". The service has no such status — it has unpaid and waiting_payment, and the guide describes neither.
Why it matters: A vendor looking up the status in front of them will not find it, and will find one they never see. Every booking starts at waiting payment.
Expected behaviour: The guide describes the statuses the service actually sends.
Status: Mismatch.
Evidence and test details
- Code
ems-apis/constants/payment_status.go:8-19 - Checked Confirmed in dev — status guide, Payment Status tab, 5 Aug 2026
Not established yet
| Gap | Why it matters | Who can settle it |
|---|---|---|
| Which notification each status change sends | Needed to answer "why didn't the guest get an email" | engineering |
| What each status change does to available seats | Blocks the availability page | engineering |
| Which words each screen, email and export shows | Guests, vendors and partners may see different words for the same thing | product |
| Whether some status changes do nothing, and say they worked (BST-004), the dashboard expects payment values the service never sends (BST-012) and a refunded invoice document says "Unpaid" (BST-015) show up in the running product | Three are code readings only | engineering, in dev |