VIP CRM and Allergy History Sharing: How Bangkok Entertainment Rooms Keep Corporate Accounts When the GM Is Off

VIP CRM and Allergy History Sharing: How Bangkok Entertainment Rooms Keep Corporate Accounts When the GM Is Off
BLUF: Decide the source of truth before the next GM rest day
Corporate accounts in Sukhumvit and Thong Lo do not leave because a sommelier named the wrong vintage. They leave because a companion allergy captured on a secretary LINE never reaches the kitchen ticket, and because the principal diner sits as a stranger on the night the GM is off. Bangkok entertainment bookings run on LINE Official Account, not landline CTI. Buy a 200ms caller popup after you bind allergy severity, seat preference, and bottle-keep remainder to the reservation event. Foreign CRMs are strong at guest notes. They fail in Thai rooms when the note stays English-only, WhatsApp or per-cover metering sits on a different rail from LINE, and health data is collected on the same checkbox as marketing. A 32-seat room with 22 VIP accounts loses about 255,000 THB a year per departed account. GM dependence plus kitchen unread tickets puts 400,000 to 750,000 THB a year off the invoice. The fix is not better greeting scripts. It is booker versus principal separation, allergy severity codes, kitchen read receipts, and explicit PDPA consent on one ledger.
1. Count the loss as account annual revenue, not as a missed preference
A 32-seat Japanese, yakiniku, or kaiseki room on Phrom Phong Soi 39 or Thong Lo Soi 13 (12 at the counter, 16 at tables, one private room) makes Friday dinner on corporate entertainment, not walk-in. A Japanese trading house, bank, or manufacturer sits with a Thai conglomerate host. The booking arrives from a secretary. The principal diner arrives on a different mobile number. The same host returns on Tuesday with a different companion, on the GM’s rest day. If the tools on the floor are “the GM’s head” and a LINE bubble from three months ago, the loss is not a dish. It is an account.
Four layers produce that loss.
- Allergy transmission gap. “Companion: prawn allergy” sits in the booking chat. The ticket prints “ebi NG” as free text. Stock, shared fryer oil, garnish prawn, and nam pla never get a yes/no. Thai seasoning sits on fish sauce (น้ำปลา) and shrimp paste. A verbal “no seafood” after seating cannot re-cook the plate. Even without a medical incident, the host moves the next dinner. One account’s annual revenue disappears.
- Recognition failure on GM rest days. Preferred private room, kamiza seat, dry white after the toast, and keep-bottle remainder live in one person’s memory. Add Tuesday offs and annual leave, and roughly 30% of VIP covers land on a night that is “the usual restaurant, except it is not.”
- Secretary versus principal mix-up. The LINE Official Account counterpart is the secretary’s personal account. Search by the diner’s number and the card is empty. Search by the secretary and a different body sits down. Place cards and allergies swap.
- Dead bottle keep. Paper tags and bar-shelf photos live on a personal phone. No drink-down reminder fires. Opened product is discarded at 90 days, and the reason to return dies with it.
Place the math as follows. 22 corporate VIP accounts, average party 4.2, check 4,600 THB, 1.1 visits per month.
- Annual revenue per account: 1.1 × 12 × 4.2 × 4,600 = 255,024 THB
- VIP dinner book: 22 × 255,024 = ~5.61 million THB (often ~40% of dinner sales)
- One departed account in a GM-dependent year: 255,024 THB
- Near-miss comps and re-fires: 3 × 8,000 = 24,000 THB
- Missed drink-down visits: 1 party × 15,000 × 12 = 180,000 THB
- Peak labor spent scrolling LINE: Fri–Sat 45 min × 2 hosts × 90 THB/hour × 8 nights, plus 20 min × 2 hosts × 20 weeknights, annualized ≈ 27,000 THB/year
The expected annual hole is about 480,000 THB. A two-account year clears 730,000 THB. Labor is the small line. The body is account revenue plus keep-driven return visits. A “hospitality impression” KPI does not support a buy decision. Put departed-account revenue and unread kitchen allergy tickets first.
Thai F&B has no in-room allergen disclosure statute comparable to packaged-food labeling. Ministry of Public Health Notification No. 450 B.E. 2567 (2024) tightened the packaged list (gluten cereals, crustacea, egg, fish, peanut, soy, milk, tree nut, sulphites, plus shellfish and squid as secondary or contaminant items). That list still does not force a private-room ticket. Entertainment-room safety records are therefore an operating asset for account retention, not a label the law already writes for you. Rooms that never ask treat near-misses as comps. Rooms that ask but never code the answer repeat the same near-miss next month.
2. Floor notes, Reddit, and X describe the same break
Internal shift notes and public threads point at one structure.
On the floor. Friday 18:50, the secretary LINE reads “four tonight, one nut, private room.” The host writes the slot in the book and leaves the detail in chat. 19:10, the principal presents a company card. The search key is still the secretary, so the dossier is empty. The kitchen hears “nut NG.” The pastry cook pulls almond powder from the dessert and leaves nut oil in the sauce. The GM is off. The keep-bottle shelf number lives in the GM’s notes app.
On the line (public boards). r/KitchenConfidential repeats fatigue with tickets that print “allergy” on every row. Anaphylaxis, coriander aversion, and “not too spicy” share one label, and the line treats the warning as background noise. Walking from the floor into the kitchen to confirm the chef saw a red band is not available at Friday 19:00. Servers who dump every verbal preference into the POS as an allergy get the same thread’s pushback. r/Serverlife’s stock story is “regulars live in the GM’s head,” so a regular is treated as a stranger on the GM’s day off. r/restaurateur notes that SevenRooms or OpenTable guest notes can stop on the server screen and never hit expo or the kitchen ticket. Having a note and having the chef read it before fire are different jobs.
On the diner and traveler side. r/Bangkok and r/ThailandTourism produce “I sent the allergy on LINE and it never arrived” and “the booking name and the arrival name differed, so they asked again at the table.” r/JapaneseFood treats dashi left on a “no crustacean” plate as a trust failure, not a taste miss. On X, Tokyo-side expats in Bangkok say they specify the room that remembers a companion restriction after one telling, not merely the room that can hold a private table.
Guests are not rejecting a CRM brand. They are rejecting (a) content written on the booking channel that vanishes at seating, (b) preference and severe allergy looking identical, (c) a secretary booking that treats the diner as a stranger, and (d) a keep remainder the guest has to remember first.
The booking event in Bangkok entertainment is not the landline CTI Japanese izakaya operators still assume. Close to 90% of reservations arrive on LINE, Google, or walk-in. A sub-second inbound popup bought first hits the secretary’s mobile and leaves principal and companion allergies inside the thread.
3. Feature comparison: five ways to “do VIP CRM”
“Put in a VIP CRM” is a slogan. Implementation decides Friday 19:00 kitchen reach and account retention. FX used here: 1 USD = 34 THB. Public list and circulating single-venue bands as of August 2026. Thai contracts for foreign engines are quote-driven.
| Dimension | LINE chat + GM memory | Paper cards / spreadsheet | Foreign CRM (SevenRooms / OpenTable GuestCenter) | SEA public SaaS (Eat App and peers) | Rezabo store ledger CRM |
|---|---|---|---|---|---|
| Guest source of truth | GM head and chat history. Search is human memory | A name row. Concurrent edits overwrite | Engine guest profile. Auto VIP tags are strong | Guest notes and tags. Searchable CRM is often +USD 39/month on lower plans | Tenant dossier. Allergy and booker bind to reservation ID |
| Booker (secretary) vs principal | Treated as one thread | Extra columns do not join the booking screen | Separate profiles possible. Thai LINE user IDs are a different key | Phone-number key. LINE user ID is a separate build | Booker, principal, companions as roles on one reservation |
| Allergy grain | Free text “ebi NG” | Cell string. No severity | Notes and tags. Forced kitchen print is contract- and config-dependent | Notes persist. Kitchen chit printer is a USD 179 one-off | Severe / removable / preference codes required. Free text is supplement only |
| Kitchen reach | Verbal. Drops at peak | Print with no read receipt | Stops on the server screen. English UI remains | Expo print depends on install wiring | Ticket print + screen alert + pre-fire read on one event |
| Bottle keep | Paper tag + personal phone photos | Shelf column. No expiry ping | Asset tracking is overkill or absent. Photos sit in another tool | Not published as a standard feature | Remainder photo, shelf, open date, expiry hang off the dossier |
| Published price band | Software 0. Thai LINE OA: Free 300 msgs/month, Basic 1,280 THB (15,000), Pro 1,780 THB (35,000) | Software 0. Rebuild and account loss are the body | SevenRooms unpublished list. Street single-venue ~USD 250–600/month (8,500–20,400 THB). DoorDash-owned since June 2025. OpenTable Basic USD 149 + USD 1.50/cover, Core USD 299 + USD 1, Pro USD 499 + USD 1. Guest CRM sits in the Pro band | Annual: Starter USD 48/month (300-cover cap, 100 WhatsApp), Essential USD 111 (unlimited, 250 WhatsApp), Pro USD 209 (500). Monthly 69 / 139 / 272. Searchable CRM +USD 39 on lower plans. Network often USD 2/cover | Ledger 1,900 THB/month, unlimited reservations. LINE OA and rails billed separately |
| Metering trap | Message caps. Thai Free and Japan-region Light cannot buy overage. Thai Basic overage 0.10 THB/msg, Pro 0.06 | None. Person-dependence instead | Busy months inflate cover fees. Guest data stays in the engine. Confirm parent-company region in the contract | Starter stops at 300 covers. Conversation overage is a bundle from ~USD 100 or a jump to Pro | No per-reservation meter. VIP volume does not move the ledger line |
| Thai PDPA (health) | Sits in chat. No explicit-consent log | Paper walk-out is the leak path | Region and cross-border clauses need contract review. US parent processing can remain | USD-denominated cloud. Consent copy is the shop’s job | Booking-time checkbox stored on the dossier. Export locked to GM+ |
| Offline | Chat remains. Search does not | Paper works. Same-day updates do not | Cloud-assumed | Cloud-assumed | Tonight’s VIP cards cached on device. Commit is server-authoritative |
Read the table as operating risk, not sticker price. LINE and paper look free and bill the account. SevenRooms-class products sell guest profiles and zero cover fees. They break in a 32-seat Bangkok room because DoorDash or Deliveroo reservation marketplaces are not the demand side, floor language is Thai and Japanese, and booking completion lives in LINE. After the June 2025 DoorDash acquisition (deal closed 13 June 2025), SevenRooms published that restaurants still own first-party guest data, and that DoorDash insights are additive. Ownership language is not the same as processing location. Put the parent’s analytics and support region in the DPA before health flags sit on a Singapore or US cluster. OpenTable’s published network is USD 1.00 to 1.50 per cover. Entertainment demand does not arrive from the OpenTable app. Paying the network fee does not retire the secretary LINE as source of truth. Deep GuestCenter CRM sits on Pro (USD 499/month). Buying Core notes and calling that “VIP CRM” is a quote misread.
Eat App has no cover meter on Essential and Pro, and real SEA installs. Constraints are WhatsApp conversation caps, Starter’s 300-cover stop, searchable guest DB as a USD 39 add-on on lower plans, kitchen paper as a USD 179 chit-printer one-off, and LINE remaining a parallel rail. Rezabo’s 1,900 THB is the ledger. Official LINE message plans and kitchen printer consumables are separate lines. The value is secretary booking, allergy code, and tonight’s read receipt on one reservation ID, with software OPEX that does not scale with VIP volume.
4. Rate limits and infrastructure ceilings that belong in the quote pack
Sales decks say “real-time sync” and “open API.” Published and field constraints disagree. Freeze these rows before legal signs. LINE figures are from the Messaging API reference (broadcast, narrowcast, and insight families). Eat App conversation caps are from the August 2026 public pricing page.
| Constraint | LINE OA + chat as CRM | Foreign CRM (SevenRooms / OpenTable) | Eat App (public SaaS) | Rezabo ledger + LINE completion |
|---|---|---|---|---|
| Hard stop that the floor feels | Thai Free: 300 msgs/month, no overage. Japan Light: 5,000, no overage. Notices die when the pool is empty | Cover fee inflates with seated network volume. CRM extract and API scope are contractual | Starter hard-stops at 300 covers. Essential WhatsApp 250 conversations. Pro 500. Overage is a bundle from ~USD 100 or a plan jump | Ledger is unlimited. LINE OA quota remains a separate stop |
| Message / request rate | Broadcast, narrowcast, delivery stats, friend counts, rich-menu insight, webhook test: 60 requests/hour. Multicast: 200 req/s. Most other endpoints including push: 2,000 req/s. HTTP 429 on excess | Engine APIs are quote-scoped. Naive multi-site pollers that refresh every table every 5 seconds 429 first. Handle Retry-After. Do not retry create |
WhatsApp conversation window is the meter, not HTTP RPS. A confirmation plus a keep-expiry plus a survey can consume three conversations for one party | Webhook ingest is burst-controlled. Retries must be idempotent on reservation_id |
| Allergy update path | Free-text chat. No idempotency. Friday peak drops parses | Guest-note PATCH. Kitchen print is a different SKU | Guest note on the profile. Chit print is a USD 179 one-off. Read receipt is not standard | Postback or LIFF writes a coded flag onto the reservation. Duplicate webhookEventId is a no-op |
| Identity join | LINE userId without phone unless the user shares it. Secretary ID ≠ principal body |
Phone / email / card. Thai LINE ID is a custom field at best | Phone-centric. LINE is a parallel rail | Capture userId + E.164 + role on the same LIFF submit |
| Webhook semantics | Reply tokens expire. Rich-menu URI taps carry no replyToken. Push counts against the OA cap |
Create / change / cancel can arrive twice for one external ID | Vendor webhooks if contracted. Dual-write with LINE is the shop’s problem | Paid / confirmed / allergy_updated / chef_read retry; same ID consumes one seat and one ticket |
| Kitchen gate | Verbal. No read | Server screen. Expo wiring is config | Unwired notes stop on the host. Wired chits still have no chef-read original | Ticket + KDS/iPad tap. Unread cannot pass expo |
| Data residency / PDPA | Chat history is a LINE-side store. No shop consent log | Confirm region of PII. US parent processing can remain after a Singapore label | USD cloud. Shop writes consent copy | Thai tenant. Shop is controller for phone, allergy, visit history |
Three traps sit inside that matrix.
Broadcast is not a CRM channel. LINE’s 60 requests/hour ceiling on broadcast, narrowcast, and insight endpoints is generous for a Friday keep-expiry segment and fatal for a “message all friends, then poll stats on the host iPad” loop. Keep notices belong on a 14-day-to-expiry holder list. Polling OA statistics from the CRM screen steals the same hourly budget.
A conversation cap is not a message cap. Eat App Essential’s 250 WhatsApp conversations look large until confirmation, reminder, and a post-dining survey each open a window. Entertainment secretaries already live on LINE. Under-consuming WhatsApp while LINE remains the completion rail is how the cheaper SaaS still leaves a dual original.
Idempotency is a seating rule, not an engineering preference. A webhook retry that re-applies “companion: severe crustacean” is harmless. A retry that re-creates the reservation is a double book. A retry that re-prints the ticket is how the line learns to ignore red bands. Key on reservation_id plus webhookEventId.
5. Make the source of truth a role-tagged reservation, not a person master
Cleaning a name master first collides in Japanese rooms where Sato and Suzuki sit three deep. The original is the reservation event. One booking must hold three or more roles. The secretary is a channel, not the subject. Writing the principal’s health data onto the channel profile deletes the allergy the day the secretary rotates.
Roles. Booker (secretary / organizer), principal, companion, payer (corporate AP). Phone, LINE user ID, company, and tax invoice party sit per role. Never write the principal’s allergy on the booker. Shops that do lose the allergy on every assistant change.
Allergy codes (do not treat free text as truth).
- Severe (trace not allowed). Shared fryer, stock, sauce, garnish, and katsuobushi dust are in scope. Ticket is a red band. Service status cannot advance without a chef read before fire.
- Removable. Solid exclusion is enough. Stock and oil yes/no are mandatory questions.
- Preference. Coriander, heat, sweetness, raw. Do not share the severe warning color. Shared color produces the r/KitchenConfidential warning-fatigue pattern.
- Unanswered. Walk-in may confirm unanswered. Private rooms and courses force a choice on the booking screen. Blank is not “no issue.”
Item set: start from the Thai packaged list under Notification No. 450 B.E. 2567 (gluten cereals, crustacea, egg, fish, peanut, soy, milk, tree nut, sulphites, plus shellfish and squid as secondary or contaminant items), then add coriander, alcohol, and pork from the actual menu. Split prawn, crab, and mollusc. Flag fish stock and fish sauce separately. “Seafood NG” is not operable. Mollusc and crustacean are medically and labeling-wise distinct; one cell pushes the kitchen into over-exclusion or over-service. Sulphites matter on wine-heavy entertainment checks. Do not hide them inside “alcohol NG.”
The Thai PDPC’s 2026 tourism-sector draft guidance tells operators to minimize collection of the reason for an allergy or religious rule, and to take a dietary or accessibility choice instead. On a booking screen that means crustacean: severe / removable / preference / unanswered, with symptom free text (breathing, for example) collected only on severe, encrypted, and purpose-limited to safe service. A dossier that stores a medical short story loses both access requests and purpose-limitation reviews.
Seating protocol. When the host opens the reservation, principal name, roles, allergy codes, seat preference (private / kamiza / no-smoke / no-counter), and last keep SKU share one screen. The kitchen receives codes, not dish prose, and logs a read tap. Unread tickets cannot pass expo. Verbal “I just told them” is not the original. Floor walking into the kitchen is the failure Reddit already documented.
Sixty seconds at checkout. Vintage drunk, plate left, seat rating, and next-budget range (only what the organizer said) append to the reservation. Do not write a novel. The next secretary booking reads the same fields. Granularity that survives the GM’s Tuesday lives in that minute.
Bottle keep. Open date, shelf, remainder photo, expiry (default 90 days after open, overridable), and drink-down send date. Photos do not live on a personal Drive. LINE the holder 14 days before expiry. That message counts against the OA cap, so segment keep holders only. Do not mix them into Friday broadcast.
6. Pricing pitfalls and year-1 TCO
Paper and LINE look cheapest on a price list. Add departed accounts, meters, and dual sources of truth, and the ranking reverses.
Assumptions: Sukhumvit 32 seats, 22 VIP accounts, 255,024 THB per account, 480,000 THB expected loss under person-dependent ops. Thai-region LINE OA Pro (1,780 THB/month, 35,000 messages) is a separate line. Eat App Essential is the annual public list (USD 111/month), not the monthly USD 139 list.
| Annual cost item | LINE + GM memory | Foreign CRM (SevenRooms street / OpenTable Core–Pro) | SEA public SaaS (Eat App Essential annual) | Rezabo flat ledger |
|---|---|---|---|---|
| Software / book | 0 (OA messages extra) | SevenRooms USD 400 × 12 = USD 4,800 (~163,000 THB) plus onboarding. OpenTable Core USD 299 × 12 ≈ 122,000 THB. CRM-as-spine Pro USD 499 × 12 ≈ 204,000 THB | USD 111 × 12 = USD 1,332 (~45,300 THB). Monthly USD 139 ≈ 56,700. Searchable CRM +USD 39 ≈ 15,900 extra | 3,500 × 12 = 42,000 THB |
| Meters and caps | Thai Pro overage 0.06 THB/msg. Free 300 and Japan Light 5,000 cannot buy extra; notices stop | Network USD 1.00–1.50/cover. Rooms whose demand is not on that network still pay the base | WhatsApp 250. Overage is a bundle from USD 100 or a jump to Pro (USD 209 annual / USD 272 monthly). Drop to Starter and the book stops at 300 covers. Network USD 2/cover | Unlimited reservations. No seat-count multiplier |
| Kitchen wiring | Verbal. No read | Ticket print is contract/config. English UI training remains | Chit printer USD 179 (~6,100 THB) plus consumables. Unwired, notes stop on the server screen | Ticket print and read tap on the same reservation ID |
| Residual dual-source loss | The body (~480,000) | If LINE remains, notes and chat split; 200,000+ often remains | Same if LINE stays the completion rail | Compresses when LINE intake and dossier share the reservation |
| Labor (search and verbal relay) | ~27,000 plus peak misses | English UI training may remain | English / WhatsApp-centric training | Exception overrides only |
| PDPA | No consent log. Hard to explain a leak | Cross-border and DPA in contract. Paper copies on the floor recreate dual control | Shop writes its own consent | Booking consent and export ACL as standard |
| Year-1 TCO shape | Software 0 + OA + 480,000 leakage | Ledger 122,000–204,000 + setup + LINE residual | Ledger 45,000–80,000 + CRM add-on + conversation overage + LINE residual | Ledger 42,000 + OA (Pro ≈ 21,360) + remaining unregistered accounts |
Six procurement mistakes repeat.
- “Cost zero” on paper and LINE does not appear on an invoice. 255,024 THB is account abandonment. Advertising and food-cost cuts do not recover it.
- SevenRooms zero cover fee is a story for markets that can centralize guest data and first-party bookings in the engine. If LINE chat remains booking completion in Bangkok, the hole stays open next to a high monthly. Unpublished quotes are themselves a cost structure: onboarding, POS connectors, Voice AI, and marketplace modules accumulate after the demo.
- OpenTable Core at USD 299 is recovered where network demand exists. Japanese entertainment organizers do not open that app. Using GuestCenter notes alone mismatches both the cover-fee contract and the product center of gravity. If CRM is the spine, put Pro’s ~204,000 THB/year in the denominator.
- Eat App Essential at USD 111 annualized looks cheap. Rooms whose confirmation finishes on LINE under-consume the WhatsApp quota and fall back to chat as truth. Searchable CRM adds ~15,900 THB/year. Kitchen paper adds ~6,100 THB in year 1. POS spend history is another USD 59/month if you want check-level VIP tags.
- Official LINE message volume is a stop condition, not a CRM feature. Keep-expiry notices plus confirmation cards in the same month can exhaust the pool, and Friday confirmation cards stop. Thai Free: 300, no overage. Basic overage: 0.10 THB. Pro overage: 0.06 THB. Japan-region Light: 5,000, no overage. Even on Thai Pro, check remaining quota at Friday noon as house rule.
- Network USD 2/cover (Eat App) or USD 1.00–1.50 (OpenTable) is a fee paid to a channel that is not the entertainment demand spine. A contract that inflates as VIP volume grows points the objective function the wrong way.
Do not over-claim Rezabo’s number. 1,900 THB/month is an unlimited reservation ledger and dossier. LINE OA plan fees, kitchen printers, Wongnai POS or Ocha settlement links, and counsel-drafted PDPA copy are extra lines. The value is software that does not meter VIP volume, and allergy codes that survive from secretary booking to kitchen read on one ID. It is not a demand-generation product.
On a three-year view the gap widens.
| 3-year cash shape (same 32-seat room) | Person-dependent LINE + GM | Foreign CRM spine, LINE residual remains | Eat App Essential annual + CRM add-on + LINE residual | Rezabo ledger + Thai OA Pro |
|---|---|---|---|---|
| Software + rails | OA Pro ~64,000 | 366,000–612,000 + residual dual-source | ~136,000–240,000 + residual dual-source | Ledger 126,000 + OA ~64,000 = ~190,000 |
| Account leakage if ops do not change | ~1.44 million (480,000 × 3) | Often ~600,000+ if notes never reach fire | Often ~600,000+ if LINE stays original | Target is compression toward 0–1 account over the period |
| What actually moves the number | GM rest-day misses | DPA + kitchen wire + retiring LINE as original | Conversation cap + chit printer + retiring LINE | Role model + coded ticket + chef read |
Even if year-1 migration (re-interview 22 accounts and recapture consent) is costed at 200,000 THB of labor, the recovery target is account revenue, not the software line.
7. API and infrastructure constraints to kill before go-live
Phone normalization. 0812345678, 812345678, +66812345678, 66812345678, and hyphenated forms fold to one E.164. Without that fold, CTI and CRM search miss secretaries. Withheld and company switchboard numbers store as “no number” against the booker role. Never bind a switchboard to the principal.
LINE user ID and phone join. Messaging API does not return a phone unless the user shares it. Capture phone, allergy code, and explicit PDPA consent on the same LIFF form, and persist userId plus E.164 on the reservation ID together. Parsing free text from chat into a dossier fails at Friday peak. A rich-menu URI tap does not carry a replyToken. Confirmation cards and keep-expiry notices are Push, and they count against the cap. Allergy updates must be idempotent against webhook retries. Do not double-write the same reservation ID.
type AllergySeverity = "severe" | "removable" | "preference" | "unanswered";
type GuestRole = "booker" | "principal" | "companion" | "payer";
type DietaryFlag =
| "crustacean_prawn"
| "crustacean_crab"
| "mollusc_squid"
| "mollusc_shellfish"
| "fish_stock"
| "fish_sauce"
| "tree_nut"
| "peanut"
| "sesame"
| "sulphite"
| "coriander"
| "pork"
| "alcohol";
export type ReservationParty = {
role: GuestRole;
displayName?: string; // companions may be unnamed
e164?: string;
lineUserId?: string;
company?: string;
allergies: Array<{
flag: DietaryFlag;
severity: AllergySeverity;
stockOk?: boolean;
sharedOilOk?: boolean;
garnishOk?: boolean;
encryptedSymptomCipher?: string; // severe only
}>;
};
export type VipReservation = {
id: string;
serviceAtIct: string; // store ICT; never device Buddhist year
parties: ReservationParty[]; // require principal + booker
pdpaHealthConsentAt?: string;
marketingConsentAt?: string; // separate checkbox
keepBottleSku?: string;
kitchenTicketId?: string;
chefReadAt?: string;
};
const appliedEvents = new Set<string>();
export function applyAllergyWebhook(eventId: string, reservationId: string): "applied" | "duplicate" {
const key = `${reservationId}:${eventId}`;
if (appliedEvents.has(key)) return "duplicate";
appliedEvents.add(key);
return "applied";
}
export function normalizeThPhone(raw: string): string {
const digits = raw.replace(/\D/g, "");
if (digits.startsWith("66") && digits.length === 11) return `+${digits}`;
if (digits.startsWith("0") && digits.length === 10) return `+66${digits.slice(1)}`;
if (digits.startsWith("81")) return `+${digits}`;
throw new Error(`unjoinable phone: ${raw}`);
}
A single customer_id schema deletes allergies when the secretary rotates. Companions must accept a code with no name. If the name is required, the night the organizer can only say “one more, nut, no name” confirms blank.
LINE-style webhook (abbreviated). Deduplicate on webhookEventId plus reservationId:
{
"destination": "UxxxxxxxxLINEOA",
"events": [
{
"type": "postback",
"replyToken": "unused_for_push",
"source": { "type": "user", "userId": "UsecretaryLineId" },
"postback": {
"data": "allergy_update&rsv=rsv_bkk_20260821_1930_pr1&role=companion&flag=crustacean_prawn&sev=severe"
},
"webhookEventId": "01JABCDEF1234567890",
"timestamp": 1755775800000
}
]
}
Kitchen ticket and read receipt. An 80mm printer must emit Thai, Japanese, and English on one chit. Missing glyphs make the severe code unreadable. Printers cannot take a read. KDS or floor iPad tap is the original. Double-tap on the same ticket_id is idempotent. POS item master holds allergen bits; a severe code intersected with a bit blocks fire. Wongnai POS and Ocha close-check event names differ by product. Match fields in week one. Substring match on dish name misses garnish prawn and prawn stock. Use bitwise intersect.
BEGIN;
INSERT INTO kitchen_reads (ticket_id, reservation_id, chef_staff_id, read_at)
VALUES ('tkt_20260821_1930_pr1', 'rsv_bkk_20260821_1930_pr1', 'stf_chef_01', now())
ON CONFLICT (ticket_id) DO NOTHING;
UPDATE reservations r
SET chef_read_at = now(),
service_gate = 'cleared_to_fire'
WHERE r.id = 'rsv_bkk_20260821_1930_pr1'
AND r.service_gate = 'blocked_allergy'
AND EXISTS (
SELECT 1 FROM kitchen_reads k
WHERE k.ticket_id = 'tkt_20260821_1930_pr1'
AND k.reservation_id = r.id
);
/* Block fire when a severe flag intersects a menu item bit */
SELECT mi.sku, mi.name_th
FROM reservation_allergies ra
JOIN menu_item_allergens mi
ON (mi.allergen_bits & ra.flag_bit) <> 0
WHERE ra.reservation_id = 'rsv_bkk_20260821_1930_pr1'
AND ra.severity = 'severe'
AND ra.stock_ok IS NOT TRUE;
COMMIT;
Issue the party graph from the booking service, not from a host chat macro. The host iPad and the LINE LIFF must mutate the same object.
mutation UpsertReservationParty($input: UpsertPartyInput!) {
upsertReservationParty(input: $input) {
reservationId
parties { role displayName e164 lineUserId }
allergyCodes { flag severity stockOk sharedOilOk }
pdpaHealthConsentAt
kitchenTicketId
chefReadAt
}
}
query TonightVipCard($reservationId: ID!) {
reservation(id: $reservationId) {
serviceAtIct
tableId
parties { role displayName }
allergyCodes { flag severity }
keepBottle { sku shelf remainderPhotoUrl expiresOn }
serviceGate
}
}
Encryption versus Friday search. AES-256 on the phone field with no index forces full-table decrypt on inbound lookup. HMAC index for search, encrypted detail for storage. Allergy codes are enumerable plaintext. Encrypt symptom free text only. A security questionnaire that encrypts everything does not coexist with Friday 19:00 search.
PDPA and cross-border. Health data is sensitive personal information under PDPA B.E. 2562 (in force June 2022). Purpose (safe service) on the booking screen in Thai, English, and Japanese, separated from marketing. Withdrawal on the same screen. Data-subject access and deletion in 30 days is the practical clock. Deleting the dossier does not delete that night’s kitchen paper. Retention and shredder rules belong in house policy. If the cloud region is Singapore or Tokyo, write the transfer basis into the contract and the privacy notice before the consent checkbox. Floor tablets on guest Wi-Fi drop on captive portal and freeze tonight’s card. Split to a shop SSID or a 4G router.
Clock and Buddhist calendar. An iPad left on year 2569, or a timezone left on Tokyo, shifts keep expiry and service date. Expiry math uses server time only (ICT, UTC+7). Offline, cache tonight’s VIP cards. Do not leave a full CSV on device. On reconnect, the server is the original.
8. Operational traps that keep accounts leaving on GM rest days
Worked miss, Friday 19:10, private room P1:
- 14:20. Secretary LINE: four pax, 19:30, “one nut.” Host writes the slot. Detail stays in chat.
- 18:55. Host searches the principal’s +66 number. Empty card. Searches the secretary. Wrong body, last visit’s kamiza note, no nut flag.
- 19:10. Ticket prints “nut NG.” Pastry removes almond powder, leaves nut oil. Chef never taps read. GM is off. Keep bottle of Hibiki sits on shelf B3 in the GM’s camera roll.
- 21:40. Comp dessert. Organizer smiles. Next month the account books elsewhere.
The SOP is not “tell the kitchen louder.” The SOP is “P1 cannot fire until the reservation ID carries a coded flag and a chef read.”
Contract and floor landmines
- Preference and severe on the same red label. Coriander dislike and anaphylaxis sharing a print trains the line to ignore warnings. Split color and the process gate.
- Stopping at free text “ebi NG.” A record without stock, shared oil, garnish, and fish-sauce yes/no was not transmitted. An uncoded CRM has the same hole as paper.
- Collapsing mollusc into crustacean. Notification No. 450 lists squid and shellfish separately from crab and prawn. One “seafood” cell is how dashi and nam pla survive a “no shrimp” plate.
- Saving the secretary LINE ID as the principal. Arrival search misses. Split booker and principal by role. Companion allergies live on the reservation, not the booker card.
- Health data on the same checkbox as marketing. PDPA sensitive (health) needs separate explicit consent. Mailing a new menu “because they have an allergy” is purpose creep. The 2026 tourism draft says take the restriction choice, not the reason.
- Pasting the VIP roster into a staff LINE group. The list survives resignation. Same path as walking out with paper. Views are ACL screens plus audit log.
- Auto-merging Japanese surnames. Collapsing every Sato copies one body’s allergy onto another. Merge only on phone or LINE user ID match, plus GM approval.
- Going live on a foreign CRM guest note with no kitchen wire. A note is not an incident control. Confirm code, language, and read on live paper in week one. Eat App’s chit printer is a USD 179 extra line.
- Cover meters or conversation caps through an entertainment month. OpenTable USD 1.00–1.50/cover, Eat App Starter’s 300-cover stop, WhatsApp 100–250 caps either inflate the bill or freeze intake on a busy month. A CRM invoice that scales with VIP volume fights this article’s objective function.
- Reading a lower-plan “note” as the CRM body. Eat App searchable guest DB is +USD 39 on lower plans. OpenTable’s deep CRM sits on Pro (USD 499). Do not treat the first quote line as “VIP ready.”
- Buying CTI first. Bangkok entertainment booking is LINE. Withheld CLI, company switchboard, secretary mobile, and principal mobile mix. CTI without E.164 fold and roles only hits the secretary faster.
- Mixing budget and allergy in the check memo. “3,000 THB/head tonight, no prawn” in one field makes the floor speak the budget and widens health-data access. Split fields.
- Skipping parent-company and transfer clauses. SevenRooms has been DoorDash-owned since June 2025. A Singapore region label can still leave support and analytics with a US parent. Fix transfer basis and DPA before the booking-screen checkbox.
- Broadcasting keep-expiry to all OA friends. Hits the 60 requests/hour insight/broadcast family and the monthly message pool. Segment to holders inside 14 days of expiry.
- Leaving paper as “the real book” after go-live. Dual originals recreate Friday 18:50. Kill the notebook in week three or the software line is pure cost.
9. Roll out on the top 20 accounts in three weeks
- Week 1. Scope the top 20 accounts by revenue. Re-split booker / principal / companion from existing reservations. Refuse to persist allergy outside severe / removable / preference / unanswered. Put explicit PDPA consent on private-room and course booking screens. Paper-notebook transcription is GM-gated and stores the source (verbal / LINE / card). Do not treat old chat screenshots as consent. Write a fresh choice onto the new reservation.
- Week 2. Red-band kitchen tickets and read taps go live. Friday: ten covers, code-versus-plate check before fire. Drop verbal relay to backup. Ban hosts from leaving the host screen to hunt allergies in LINE. Every blocked SKU has one pre-agreed substitute. Inventing a plate in the moment is how near-misses incubate.
- Week 3. Move keep photos and expiry onto the dossier. Personal-phone albums leave the source of truth. Pin the 60-second checkout append before the check closes. On a GM rest night, test that a host can open the dossier by principal name. Audit CSV export and merge approvals. Write “check OA remaining quota at Friday noon” into house rules.
Do not force answers on every weekday lunch walk-in. Unanswered volume rises and the code becomes theater. Run 90 days, get transmission near-misses to zero, then expand to weekday banquets and new corporates. Leaving the paper notebook as “the real one” adds cost only.
10. Questions owners ask before they turn it on
Q1. Will asking for allergies drop completion? On private rooms and courses, rarely. Completion drops when every seat requires a long free-text essay. Four-value choice, with detail only on severe. Do not collect the medical reason.
Q2. May we serve if they arrive unanswered? Walk-in: verbal confirm at seat, code it there. Private-room courses unanswered at booking: re-collect on the reminder. Never auto-convert unanswered to “no issue.”
Q3. Companion added same day, “nut, no name.” Attach a severe code to an unnamed companion slot and send stock/oil questions to the principal. Stop the plate, then ask. Do not wait on a name change to fire.
Q4. If a PDPA deletion request arrives, do we shred that night’s kitchen safety record? Split statutory reservation and tax retention from out-of-purpose health retention. Marketing lists and long-lived free text go first. Confirm that night’s service record with counsel and write it into house policy. A single “delete all” button is unsafe.
Q5. Do we need landline caller popup? After E.164 fold, yes if you have a PBX. LINE role tagging is first. A hit on inbound CLI still does not surface companion allergies.
Q6. Will keep-expiry LINE get us blocked? Segment to holders. Do not mix into all-friends broadcast. Check remaining quota before Fri–Sat. Thai Free 300 and Japan Light 5,000 cannot buy overage. Broadcast/narrowcast sit at 60 requests/hour; do not poll insight endpoints from the host screen.
Q7. May we keep a foreign engine dossier in parallel? Dual originals leak first. If the demand engine stays, one write path for allergy codes. Do not hand-key guest notes into both.
Q8. Do accounts walk when staff resign? Restrict CSV and bulk photo download to GM+, with audit. Ban personal LINE forwards and paper copies in house rules. A ban is not enough. Copy-resistant ACL is the control.
Q9. If the foreign CRM has guest notes, can kitchen wiring wait? No. A note is a server-screen memo, not a pre-fire read. In week one, watch live paper for code, language, and read. A product that cannot print those three is a front-of-house notepad, not a VIP CRM.
Q10. Is “seafood NG” enough if the guest said it that way? No. Translate at capture into crustacean (prawn/crab), mollusc (squid/shellfish), fish stock, and fish sauce, each with a severity. The guest’s phrase is a clue. The ticket is a code.
11. Metrics that prove the GM rest day is survivable
| Metric | GM memory / LINE chat | Role dossier + kitchen read | Why it matters |
|---|---|---|---|
| Chef read rate on allergy tickets | Unmeasurable (verbal) | 100% on private rooms and courses is normal | Whether transmission happened |
| Severe/preference label mix count | High (everything “NG”) | Weekly zero | Leading indicator of warning fatigue |
| Principal dossier opens at seating on secretary bookings | Low | Above 90% | Role split actually works |
| VIP greeting misses on GM rest days (name, seat, keep) | Unlogged | Monthly decline is normal | Remaining person-dependence |
| Accounts lost per year | 1 to 2 is plausible | 0 to 1 | Unit is 255,024 THB |
| Keep expiry discards | Shelf count only | Noticed ratio and bottles dumped | Return-visit motive |
| Times hosts leave the screen to hunt LINE for an allergy (Fri–Sat) | 8 to 15 a night | Zero is normal | Source of truth moved |
| CSV export and merge approvals | Unlogged | Zero outside GM | PDPA and walk-out |
| Official LINE remaining quota (Friday noon) | Unchecked | Enough left for Fri–Sat | Prevents confirmation-card stop |
Closing
The night a Bangkok entertainment room loses a VIP is not a service-skill failure. The booking arrives on a secretary LINE. Principal and companions sit down as different bodies. The kitchen drops free-text “NG” at peak. The loss is not a monthly software line. It is 255,000 THB units of account revenue, plus the return visits a keep bottle creates. The stop condition is a role-tagged reservation as source of truth, severity-coded allergies, a kitchen read as a gate, and health consent split from marketing.
Paper and chat look free. Foreign CRMs and SEA SaaS sell guest notes and zero cover fees. What works at Friday 19:00 in an independent Thai room is codes that reach the kitchen the moment a LINE booking confirms, on a flat ledger that does not meter volume. Ledger cost sits near 42,000 THB a year. One defended account is 255,000. Expected leakage under person-dependent ops is 400,000 to 750,000. The spread is not CTI milliseconds. It is whether a host on the GM’s Tuesday can see a companion’s stock yes/no on a screen.
When you take quotes, freeze five rows, not the monthly headline: (1) lines that grow when reservations or covers grow, (2) WhatsApp or LINE message caps, including LINE’s 60 requests/hour on broadcast and insight, (3) whether kitchen tickets and reads are standard or a separate build, (4) whether booker and principal are different keys, (5) whether health consent and cross-border transfer sit in the contract. Having a guest note and having a chef read before fire are different products. Searchable CRM as an add-on, OpenTable’s deep CRM on Pro, and SevenRooms guest data that may enter a US parent’s processing scope belong on the same table.
To match role model and allergy-code screens to your private-room count and corporate roster, talk to the local team from the button below.
Bangkok Restaurant No-Show Prevention Checklist (15 Rules)
An operational field guide for dining venues in Thailand: sync kitchen prep strictly with dynamic PromptPay QR deposits and automated LINE reminders to eliminate food waste.
- Strict synchronization of Friday 16:00 kitchen prep with paid bookings only
- Dynamic QR verification replacing static slip matching and slip forgery
- High-retention refund deadline rules and seamless tourist card routing
Delivered instantly via LINE Official Account (Instant 3-sec access)