Platform

The platform underneath the pitch.

Operations decisions live on the server. Tenancy is enforced on every route and query. Rules are deterministic. Audit is immutable. This page is the spec.

How it runs in the wild

Built for mall operations. Not for a slide.

The questions a coupon platform has to answer before it ships into a vendor location. POS surface, dropped connectivity, double-scans, refunds, onboarding, validation.

POS-agnostic capture

Redemptions capture on any browser. A store operator opens the redeem console on their phone or a POS-attached tablet and scans the coupon. No deep POS integration required to start. Tighter integrations roll out in Phase 2 against signed merchant commitments.

Offline-tolerant scanning

Codes stay scannable when connectivity drops. The capture queues locally and certifies once the connection returns. No redemptions lost between the till and the cloud.

Idempotent against double-scans

Every redemption write claims a transactional lock keyed by the redemption code. A double-scan returns the original capture, not a second fee. The rules engine emits { allowed, reasonCode, message } so disputes have a paper trail.

Returns and voids, handled honestly

Phase 1 captures certified records. Refunds reconcile at invoice review by Finance. Phase 2 adds an explicit void workflow with audit-tracked reversal. We do not silently rewrite history.

Onboarded by invitation

Every user joins via a signed invitation token. Vendor admins are scoped to their brand at creation. Property admins to their mall. Excellerate Super Admins to the platform. No accidental cross-tenant exposure ever.

Server-side rules engine

Time window, redemption cap, eligibility segment, vendor-location match. All run server-side on every scan against a deterministic rules engine. The UI never decides anything that touches money.

Tenancy

Nine levels. Every redemption traces up the tree.

Permissions enforce at every level, server-side, on every route and query. A vendor admin cannot see a competitor. A property admin cannot reach into another mall.

  1. 01
    Platform

    Coupex software, RBAC, audit, finance rules.

  2. 02
    ClientAccount

    Excellerate, with configurable currency and timezone.

  3. 03
    PropertyGroup

    Portfolio cluster across regions or formats.

  4. 04
    Property

    Single mall, scoped to its admins and operators.

  5. 05
    VendorLocation

    Vendor brand at a specific property store.

  6. 06
    Campaign

    Approved window of activity with rules and segments.

  7. 07
    Coupon

    Discount design with limits, eligibility, and artwork.

  8. 08
    CouponInstance

    Unique issued code, QR, or barcode for one shopper.

  9. 09
    Redemption

    Captured event with fee, certified by finance.

Hard rules

Decisions on the server. Records that hold up.

RBAC enforces on every route and query. Validation, fee calc, and approval state never run in the UI. Idempotent redemption writes prevent double-counting under race conditions.

ZAR with space separators

Money formats as R1 000 with a non-breaking space, matching SA convention across the dashboard and the invoice draft.

Africa/Johannesburg timestamps

Every redemption captures in SAST. Reports default to SAST. No timezone guesswork when a dispute lands.

POPIA-aware customer data

Consent state and source persist on every customer record. Reading a customer detail row writes a customer_detail_viewed entry to the audit log.

Decimal money, never floats

Money stored as Decimal(14, 2), percentages as Decimal(7, 4). Resolved fee rule IDs and resolved percentages persist on every fee calculation.

Demo data is labelled

Seeded data is clearly demo data. No mock figures get presented as production activity. Imports surface failure CSVs rather than failing silently.

Audit across every write

Approvals, redemption certifications, invoice generation, customer access, sign-in events. Every write is captured with actor, action, and timestamp.

Architecture

A short tour of the request path.

Browser to proxy to auth to services to rules to Prisma to Postgres. Every step adds checks. Every material write spawns an audit row in the same transaction.

Request flow

  1. 01

    Browser

    Next.js client components. No business logic. Forms, navigation, presentation.

  2. 02

    Proxy + Auth.js

    Edge-runtime proxy gates /app routes. Invitation-only sign-in. RBAC carried on every request.

  3. 03

    Service layer

    Server actions and services. RBAC checks first. DTOs serialise Decimal as ZAR strings.

  4. 04

    Rules engine

    Pure functions. Resolves fee precedence, validates redemptions, evaluates approval gates.

  5. 05

    Prisma + Postgres

    Migrations, transactional writes, idempotent redemption locks, Decimal money.

  6. 06

    Audit log

    Every material write captures actor, action, entity, timestamp. Immutable.

Side-channel writes

Every approval, redemption certification, invoice draft, customer detail read, sign-in event, and permission denial branches off the main flow into the audit log table. The write commits in the same transaction as the action it records. No silent failures, no orphan events.

The same pattern carries fee calculations. The resolved fee rule and resolved percentages persist with every Redemption row, so historical fees stay correct even when the rule table changes.

customer_detail_viewed

POPIA-tracked read

redemption_certified

Finance action

campaign_approved

Approval action

permission_denied

Cross-tenant attempt blocked

POPIA posture

Customer data is treated as the operator's responsibility.

Consent persisted. Detail reads logged. Audit immutable. The platform makes it harder, not easier, to lose track of who saw what.

Consent persisted on every customer record

Every Customer row tracks consentStatus and source. Updates to either field are themselves audited.

Customer detail reads are logged

Any operator opening a customer detail page emits a customer_detail_viewed entry. The actor, target customer, and timestamp persist. This is POPIA compliance, not an analytics nicety.

Audit immutability is structural

AuditLog rows never update. They only append. Approvals, redemption certifications, invoice generation, sign-in events, and permission denials all flow through the same table.

Run it for yourself.

Seeded properties, vendors, campaigns, certified redemptions, AI recommendations, audit log entries. Everything wired to the same RBAC the production rollout will carry.