Coupons, and the review that follows the meal
Two halves of the same idea: a promotion should only appear where it can be used, and a rating should appear where it can be read. Before this round a coupon was one undifferentiated thing โ visible in the booking form and at food checkout whether or not it made sense there โ and a review, once written, had no public home at all.
What an offer now carries
| Field | What it means | What the customer sees |
|---|---|---|
| Where it can be used | At the table, On online orders, or Both |
Only the coupons opened for the flow they are in |
| Coupon code | The code you wrote in the offer form | The code shown on the booking, and in their order summary |
| Value | Percentage or flat rupees, with the minimum bill | 15% off, not "a % special offer" |
| Days and window | Which weekdays, and the lunch/dinner window | Greyed out with the reason, when today is not one of them |
Offers created before this option existed are Both, so nothing you published earlier quietly
stopped working.
At the table means the coupon is offered while someone books a table. On online orders means
it is offered at food checkout. A coupon is never silently re-labelled to fit the other flow: if
an owner tries to use an online-only coupon for a table booking the booking is refused with a
reason, and the same happens in reverse.
Coupons live on their own page
A customer does not compare five promotions in the middle of booking a table, and a coupon that expired
last month should not be shown greyed out at all โ that is a promise the restaurant already took back. So
the list lives on /restaurants/<your-slug>/coupons, with a tab for the table and a tab for online
orders, and the booking form and checkout each carry one line instead: what is applied, what it is worth,
and Change / โ. If nothing can be used here right now, no line appears.
Only coupons that can be used today are listed anywhere on that page โ active, inside validFromโ
validUntil, valid on this weekday, inside the time window for a table, and over the minimum bill for an
order. A coupon you closed, or one that runs only at weekends, simply is not offered. The page says so
plainly when nothing is open, so the empty state reads as "nothing running today", not as a bug.
The restaurant page header also carries a "N coupons on" chip that opens that page, in both discovery modes. Apply & book a table / Apply & order pins the coupon by id and drops the customer into the right flow with it already chosen.
How the "best" coupon is chosen for a customer
Both pickers preselect a coupon so the customer does not have to compare promotions by hand. The rule is deliberately simple and is the same in both flows:
- Keep this restaurant's coupons that are
isActive, apply to this purpose (Bothcounts), fall insidevalidFromโvalidUntil(both days inclusive), cover the weekday, honour the time window (only for a table booking โ a delivery order at 22:00 is not bound by your lunch hours), and clear the minimum bill if one is known. - Work out what each one saves in rupees on the bill in front of them:
percentage โ bill ร min(value, 100) รท 100,flat โ value, capped at the bill. - Pick the largest saving. A tie goes to the coupon with the lower minimum bill, then the title.
If the customer applies a coupon from the coupons page, that choice wins โ the preselection only fills the gap when nobody has chosen. A pinned coupon that stopped being usable in the meantime is not swapped for another one silently: the flow says "no coupon applied" and lets the customer pick again.
For an online order the bill is the cart total, so the saving quoted is the saving on that order. For a table booking there is no bill yet, so a benchmark bill of โน1,000 is used to compare them, and the wording says exactly that ("worth โนX on a โน1,000 bill"). It is a nudge, never a promise: the real discount is computed later from the real bill.
20% off on a โน600 bill saves โน120; โน150 off saves โน150. The flat coupon is preselected even
though its headline number is smaller โ that is the point of ranking by rupees.
What the platform does with it
The browser sends the coupon's id and nothing else. When the order or booking is written, the server re-reads your offer row and recomputes the discount from your values, then:
- online order:
total = item total + delivery fee โ coupon, floored at zero. A coupon never discounts the delivery fee, because the rider is paid the same either way. The coupon and what it saved are stored on the order, and named in the notification you receive. - table booking: the coupon id, its percentage and type are snapshotted onto the booking, so the discount you apply at the desk and the discount the customer sees are the same arithmetic. The bill is settled by you at the table, not by the platform.
If a coupon stops being valid between the cart and the pay button, the order is refused with the reason rather than quietly placed at a different price. The checkout then drops the coupon, tells the customer, and lets them pay on the honest amount. Refusing beats honouring a promotion you have already switched off, and beats charging a customer for something they were promised.
The bill you enter is the bill they confirm
When you mark a table booking done and record a bill, the customer's confirmation box now opens
with your figure already in it โ labelled as what the restaurant recorded, with your offer
amount shown against it. Everything else works as before: they still type their own amount, and
your number and theirs are stored separately (billAmount/finalAmount versus
customerBillAmount/customerFinalAmount).
Deliberately, the customer's box is a prefill, not a lock. If your figure and theirs differ, the difference stays visible to both of you and the mismatch chip on the bookings list still appears, instead of one side overwriting the other. A silent auto-agreement would hide the exact case where a human needs to look.
Reviews
A completed booking now asks for one. The ask appears in My Bookings on a booking whose status is
COMPLETED and which has no review yet โ after the meal, not before the table is confirmed โ and
the row itself reads "Review & details" in that case. One rating per booking: the review is keyed to
the reservation, so a visit cannot be rated twice, and once it exists the form is replaced by
"You rated this visit 4/5".
Guests on a shared link are not asked. A review belongs to an account, and a link can be opened by anyone with the URL, so a review from it could not be trusted.
Where they show
On the restaurant's own page, below the menu and the booking form, in both discovery modes โ that is where a diner decides, so that is where the opinions live:
- the average and the count, computed over every visible review (not over the twelve shown);
- the twelve most recent reviews, each with the diner's initials, stars, date and words;
- Show more reviews, which pages through
/api/restaurant/:id/reviews.
There is no separate "reviews" page to build. A restaurant with no reviews says so plainly, so the absence reads as "new", not as "broken".
The switch you do have
Reviews carry isVisible. Hiding one keeps it out of the average, the count and the page โ it is not
deleted, so a review written in error can be shown again later.
Ready to grow your restaurant?
Join 50+ restaurants on MyCityDeal and start receiving bookings today.