Promotion Platform — Design Document

Status: Draft for review · v2 Author: Rayon Hunte Created: 2026-07-01 · Revised: 2026-07-06 Supersedes: Digital_Promotion_Station_Proposal.docx and the v1 receipt-QR design (§16) Companions: How It Works (business walkthrough) · live demo

1.Summary

The Promotion Platform modernizes CAMEX Restaurants' promotional draws without changing how customers order and without changing the receipt. After purchasing, the customer scans a static QR code displayed in the store, which opens the promotion web app with the store's location already set. They enter the order number printed on their receipt; the system validates that the order was really placed at that location on that day and hasn't been claimed; the customer identifies with their phone number (returning customers are recognised); and they select from the promotions their purchase qualifies for. Each purchase can be claimed exactly once.

This is an extension of the existing camex-oms platform, reusing its backend services rather than integrating with a foreign POS.

2.Business objectives

3.Context and constraints

Sample receipts reviewed: Mario's Pizza and Church's Chicken (CAMEX Restaurants, Guyana; GYD currency, +592 numbers).

4.Scope decisions (agreed)

DecisionChoiceRationale
PlatformExtension of camex-oms; reuse existing backendBackend is owned; no foreign POS integration
QR codeStatic, displayed in-store (poster/sticker per location)Receipt cannot be modified; QR identifies the location
Scan timeCaptured server-side at scanNever trusted from the customer's device or receipt
Order validationLocation + date + order number looked up live in camex-omsThe composite key that works with an unmodified receipt
Receipt date entryOptional customer input, business-configurableOff = same-day receipts only; on = older receipts accepted
IdentityPhone-first lookup, before promotions are shownReturning customers skip the form; builds the customer DB
New-customer dataFirst name, last name, street address, town/cityOne-time capture
Promotion eligibilityRules on order amount and items (for now)Future: business-defined rules on any order detail
Entries per purchase1 entry per promotion per purchase, business-definedAllowance is a business decision
Phone verificationNone for pilot; SMS OTP is the Phase-2 upgradeFastest, no SMS cost; upgrade path preserved
ConfigurationDev team configures for pilot; business self-service laterAdmin screens are a platform goal, not a pilot deliverable

5.Architecture overview

Four logical pieces on top of the existing camex-oms backend:

  1. In-store QR codes — one static code per location, printed on posters/stickers. Encodes the promotion-app URL with the location identity. No per-order data.
  2. Promotion web app — mobile-first web page opened by the QR. Runs equally on a customer's phone (primary) or an optional in-store kiosk tablet (same app).
  3. Promotion Service — validates orders against camex-oms, looks up/creates customers, evaluates promotion eligibility, enforces the single-claim rule, records entries.
  4. camex-oms order lookup — the authoritative source for "did this order happen here, on this day, and what was on it."
Customer purchases (nothing changes at POS; receipt unchanged)
        │
Customer scans the in-store QR  ──▶  app opens; location set by QR;
        │                            scan time stamped server-side
        ▼
Customer enters order number (CHK)          [+ receipt date, if business allows]
        │
        ▼
Promotion Service validates against camex-oms
  1. order exists at THIS location on THAT day
  2. totals/items pulled from backend records (never typed)
  3. purchase not already claimed
        │
        ▼
Customer enters phone number ──▶ lookup
  ├─ returning customer → recognised, details on file, no form
  └─ new customer       → first name, last name, street, town/city (one time)
        │
        ▼
Eligible promotions listed (rules on amount/items; ineligible shown greyed with reason)
        │
Customer selects draws ──▶ entries recorded (1 per promotion per purchase)
        │
        ▼
Purchase marked CLAIMED (atomic; permanent; single-use)

6.Order validation design

Composite key: location + date + order number.

The Promotion Service queries camex-oms for an order matching all three. On a match it pulls the authoritative order data (total, items, time) from the backend — nothing about the purchase is trusted from user input.

Why not the check number alone: check numbers are per-store and recycle over time. Scoping by location (from the QR) and day makes the key practically unique. Residual ambiguity (the same store issuing the same check number twice on the same day) is considered negligible but should be confirmed against real OMS data during integration.
Production behaviour: failure responses are generic ("we couldn't match that order") — they must not reveal whether an order exists at another store or on another date. The demo shows detailed reasons for teaching purposes only, and labels them as demo-only.

7.Identity: phone-first, before promotions

The customer identifies before any promotions are shown:

  1. Enter phone number.
  2. Backend lookup:
    • Known customer → their stored details are returned; they're greeted by name and go straight to the promotions list.
    • New customer → one-time form: first name, last name, street address, town/city. Saved on their first successful claim; never asked again.

The entered phone number is not verified in the pilot (§14). Manual entry also acts as friction against bulk/automated abuse.

8.Promotions and eligibility

9.Claims and integrity

Three layers, each with a distinct job:

Trade-off vs the v1 design: v1's signed receipt-QR made forgery cryptographically hard. Because the receipt can't be modified, v2 accepts guessability as a residual risk and manages it with the controls above plus the single-claim rule (a guessed number only ever pays out once, and only for a real purchase).

10.Surfaces

11.Configuration ownership

Pilot: all settings designed and configured by the development team from business direction. Platform goal: business self-service through a promotion-platform admin screen.
SettingControls
Promotions & prizesWhich draws run, names, prizes, start/end dates
Eligibility rulesMin spend, required items — later any order detail
Entries per purchaseAllowance per promotion per purchase
Receipt date entrySame-day only vs older receipts accepted
Participating storesWhich locations display QRs and accept entries

12.Data captured

Each claim records: location, order number, receipt date, promotion entries (with reference numbers), and the customer (first name, last name, phone, street, town/city). Customers are stored once and recognised on every later claim. Byproduct: a clean identity-plus-real-purchase dataset — the foundation for loyalty, coupons, surveys, and direct marketing with no extra collection work.

13.Backend integration — open questions

To resolve against the camex-oms codebase before implementation:

  1. Order lookup — an endpoint (or query) by store + business day + check number, returning total, items, order type, and timestamps. Confirm check-number uniqueness within a store-day.
  2. Customer store — where promotion customers live (new collection/table vs existing customer records), keyed on normalized phone.
  3. Claims + entries storage — new tables/collections with a unique constraint on the claim key; kept separate from order records.
  4. Rate limiting — per phone/session/IP throttling for order-number attempts.
  5. Location identity in the QR — stable store IDs to encode in each poster URL.

14.Future upgrade: phone verification (Phase 2+)

SIM-based verification (Google Phone Number Hint / SMS Retriever / carrier "verify with SIM") only works on the customer's own device with their SIM present, so it can't serve a kiosk. The device-agnostic equivalent is SMS OTP: enter a number, receive a code, type it back — proving SIM possession from any surface. Deferred from the pilot for cost and friction; documented as the intended verification path.

15.Phasing

16.Revision history

17.Non-goals (for the pilot)