Merit / E-Commerce Solution / Rewards
How a digital gift card gets into the catalogue, how a discount is set for one product and one tenant, and what happens to the money between the order and the settlement report.
Sections 1, 2 and 5 come from the recorded session, so they carry what people actually said. Sections 3 and 4, the runtime, come from the whiteboard plus Brian's walkthrough of it. The session never discussed the wallet, OMS, fulfilment or settlement, so treat the runtime half as a reading of the board that needs Marthino to confirm it.
This is the configuration path. Nothing moves money here. It answers two separate questions: what is this product, and what does it cost this particular tenant.
Read it left to right. Two independent inputs meet in the middle. PIM holds the product. LiveOps holds the price rule. The Rewards Portal joins the two at display time, so the same gift card can appear at a different price in two different tenant portals.
The counterpart of the Seller Portal, but for gift card vendors. The vendor owns its own product data and enters it here. Gift cards first, offers later.
Single source of truth for what a product is. It publishes product.created and product.updated so downstream systems stay in sync.
Where discount, markup and transaction fee are configured. The key is the pair, one product and one tenant, not the product alone.
The board shows the Digital Seller Portal writing config into LiveOps directly. A vendor must not set the tenant discount, because that is Merit's margin against Merit's client. The vendor supplies its cost to Merit. Merit commercial sets the tenant rate. Two different writers, and today they share one box.
This is the single hardest thing to hold in your head, and it is why a flat revenue share was rejected in the session.
A tenant gets access to a subset of the global catalogue. Inside that subset, each product carries a discount that belongs to that tenant alone. The same gift card sits at a different rate for Jahez than it does for Al Fursan, because the contracts differ and the volumes differ.
| Gift card | Tenant A, high volume | Tenant B, new | Tenant C |
|---|---|---|---|
| Brand X, SAR 100 | 5.0% | 2.0% | no access |
| Brand Y, SAR 50 | 3.0% | 2.0% | 2.5% |
| Brand Z, SAR 200 | 1.0% | no access | 1.0% |
Every cell is a separate configuration row. A blank cell is catalogue entitlement, which is a different control from price. Two controls, one screen.
Brand discount from the supplier already ranges from 1% to 5%. A single Merit-wide share would pay out more than the margin on the 1% brands and leave money on the table on the 5% brands. This was decided in the session on 25 August and it is the reason the granular table above exists.
The ladder implies a job that measures tenant volume on a cycle and moves the rate. That job has no owner, no cycle and no threshold definition. Until it exists, every promotion is a manual edit in LiveOps that someone has to remember to make.
Swimlane. Time runs left to right. Each row is the system that does the work.
The important beat is step 6. Funds are held, not taken. Nothing is charged to the tenant until the card actually exists. That is what makes the settlement step in part two necessary at all.
The second half is where the discount is actually applied to money. Same swimlane grammar, different cast.
The Settlement Service does not decide anything about the order. It reads the completed state from OMS, reads the rate from LiveOps, does the arithmetic, and tells the Wallet what to take. Three reads and one write.
Two drafts overlap with it and neither is built. The OMS Payment Settlement Integration covers escrow and payout batches. The Pricing Commission Engine covers rate resolution and the pricing ledger. Whether the rewards settlement path is a third service or a mode of one of those two is an unmade decision, and it is the largest single risk in this design.
The session settled this. Gift cards and merchandise are priced by different mechanics, so one engine cannot serve both without a mode switch.
The card has a base value. Merit takes a discount off it or adds a markup. The rate is set for each product and tenant pair, and it moves with volume. Configured in LiveOps, applied at settlement.
Typical range: 1% to 5%, driven by what the supplier gives Merit on that brand.
No per-product discount. The tenant contract carries a share of profit across the whole basket. Simpler to administer, and it is the right shape for enterprise deals.
Marthino's diagram does not cover this path. It is a gift card diagram.
Two ways exist to share a gift card: share the discount, or share a percentage of the money. The revenue share version was described in the room like this. Merit gets 3% from the brand, is transparent about it, and splits that 3% with the tenant on an agreed ratio, 80/20 or 40/60. That is workable for one deal.
What was rejected is doing it globally, across the whole catalogue, because brands give 1%, 2%, 3% and 5% and an averaged single rate pays out wrong at both ends. Revenue share stays a fair shape for enterprise deals. The rewards portal needs the granular table instead.
The question was raised that the same product-and-tenant discount logic should also apply in the new e-commerce architecture, using three different bank clients as the example. The answer given was that e-commerce will share gross margin instead, and the discussion moved on. So whether this logic gets built once or twice is still open, and it is the reason question 1 below matters.
The tenant rate cannot be set without knowing what the supplier gives Merit, otherwise the deal can go negative without anyone noticing. The Online Catalogue holds this today, by hand, with a Finance double check before anything goes live. The rule in use is one conditional:
So there are two chained margins, supplier to Merit and Merit to tenant, and the tenant-facing rate in LiveOps is only safe while it stays inside the supplier-facing one. That guard is a manual check today.
Four deltas. Two are things Brian said out loud that the board does not draw. Two are lines on the board that nobody explained.
| # | On the board | Here, and why |
|---|---|---|
| 1 | Settlement is triggered by the fulfilment channel, arrow labelled If Fulfilled = True from MGC to Settlement Service | Here it is triggered by OMS after the order reaches FULFILLED, which is how Brian described it. The two are not the same design. Triggering from the channel skips the order state, so a bulk order with one failed item would settle anyway. Needs Marthino to confirm which one is intended. |
| 2 | No return arrow from the Fulfilment Service to OMS | Added here as step 8 to 9. Without it, OMS never learns the order is complete and cannot be the trigger in delta 1. |
| 3 | A line from LiveOps to Wallet | Not drawn here, because nothing in the walkthrough explains it. If the Wallet reads the rate directly, then two systems compute the same number and they will disagree. See question 7. |
| 4 | A line from the Rewards Portal to Wallet | Not drawn here. Most likely a balance display at checkout, which is reasonable, but it is a read the board does not label. See question 8. |
The catalogue path, the config path, the order path through OMS to the Fulfilment Service, the wallet check and hold, and the fulfilment channel are all drawn the same way here as on the board.
Twelve things. Ordered by how much they hurt. The first four can lose money quietly, which is worse than failing loudly.
| # | Gap | Why it matters, and what to do |
|---|---|---|
| 1 | Rate is read at settlement, not at order | If someone edits the discount in LiveOps between the order and the settlement, the tenant is charged a rate they never saw at checkout. Fix: write a price snapshot on the order at creation, and settle from the snapshot. This is step 3 in part one. |
| 2 | No hold release path | The diagram only draws the happy path. If MGC fails to allocate, the hold sits on the tenant wallet forever. Every hold needs a time to live and an explicit void on failure. |
| 3 | No insufficient balance branch | What does the customer see, does the order fail or queue, and who is told. Undefined. |
| 4 | No margin guard at config time | Nothing stops a tenant rate being set above the supplier margin on that brand. That is a loss per transaction and it will not surface until reconciliation. |
| 5 | Refund and cancellation are absent | A gift card is delivered and then disputed. Reverse the capture, reverse the settlement line, and mark the card. None of this is drawn. |
| 6 | Partial fulfilment on bulk orders | MGC takes 5 items per call at 1 order per second. A 200 card order is many calls, some of which fail. One hold against a partly fulfilled order needs a defined capture rule. |
| 7 | Transaction fee appears once and never again | The board lists it beside discount and markup, then it does not enter the settlement arithmetic. Is it charged per order or per item, and does it sit inside or outside the discount. |
| 8 | Volume tier promotion has no owner | The 2 to 3 to 5 percent ladder implies a periodic job. No cycle, no threshold, no owner. Today it is a manual edit someone must remember. |
| 9 | No effective dating or audit on the config | Rate changes need a start date, an end date and a record of who changed what. Finance will ask which rate was live on a given day, and there is no answer. |
| 10 | Idempotency is not shown | A retried order must not hold funds twice. The Fulfilment Service already takes an idempotency key. The Wallet path does not say it does. |
| 11 | VAT, FX and rounding | Multi market means more than one currency and a tax treatment per market. The net amount cannot be computed without them. |
| 12 | Global Catalog retirement has no date | The board marks it "we will leave this eventually". Until it goes, supplier cost lives in one system and tenant price lives in another, which is exactly how the two margins drift apart. |
Discount is keyed on the product and tenant pair, not the product alone. Merchandise is client level profit share, not per product. A single flat revenue share across the whole catalogue does not work. Tenant discount data is specific to the brand and the tenant, so it stays in the rewards portal domain. All four from the session on 25 August 2026.
Eight. Each one blocks something concrete. The first two are the ones that change the build.
| # | Question | Blocks |
|---|---|---|
| 1 | Is the Settlement Service a new service, or a mode of the OMS settlement engine, or the Pricing Commission Engine. | Ownership, sequencing, and which backlog it lands in |
| 2 | Do we snapshot the rate on the order at creation. Yes or no. | The whole settlement design. Answer this first |
| 3 | Who is allowed to write the tenant rate in LiveOps: Merit commercial only, or the vendor too. | Permissions, and whether vendor and tenant config split into two screens |
| 4 | Hold time to live, and the void rule on fulfilment failure. | Wallet build, which is not started |
| 5 | Transaction fee: per order or per item, inside or outside the discount. | The net amount formula |
| 6 | Is merchandise in scope for this flow at all, or does it stay on client level profit share. | Scope of the first build |
| 7 | What is the LiveOps to Wallet line on the board for. | Whether the Wallet computes the net amount or is only told it |
| 8 | What is the Rewards Portal to Wallet line for. Balance display at checkout, or something else. | Checkout behaviour when the tenant balance is low |