Merit · E-Commerce Solutions · Product

Three things happen, not one

The single flow diagram collapsed three different events into one line, which is why the Odoo question and the Finance scope question keep coming back. A rate change, an order, and a redemption are separate lifecycles with separate triggers. Each one is drawn below with the phase that owns every step.

Status · agreed with Tahsin Ali, 5 August 2026

Tahsin has reviewed and agreed the A, B and C split. He has also made one scope call: Track C enters the project as its final phase, on the basis that it is revenue realisation, which only happens after the order is placed and the card is issued. That is recorded below as OC P6. Track C is therefore no longer an unowned gap; it is agreed scope, sequenced last, and not yet specified. This version goes to Finance for buy-in.

The sentence the whole page exists to make obvious

A rate change moves no money. Merit earns when the order is done. But the card is only activated when the customer redeems it, so Merit only incurs the cost if the customer redeems. Earning and expense are two different events, on two different clocks, and only the earning side is currently written to a ledger.

Live today In build or in sign-off Later phase, no dates Agreed scope, not yet specified Outside this workstream

Track A · A price or discount changes

Track A · the catalogue lifecycle

Trigger: a supplier moves their rate, or an account manager changes a client discount. Nothing is sold, nothing is booked, no customer is involved.

Rate change api portal csv OC P3 · manual today Approval queue pending to approved OC P3 · alarm Margin guard block at or over OC P2d Master Catalogue approved only OC P1 · live Client catalogues auto propagate OC P2a MGC sync activation OC P2a · ops Client notified 30 day notice OC P4d

Three intake channels land in one approval queue, and no channel bypasses it. The margin guard is the system check that blocks any fixed client discount sitting at or above the live supplier margin, which is the supplier-switch loss the whole project was started to stop. Only an approved rate is written to the Master Catalogue, and only then does it fan out to client catalogues and sync to MGC for activation. Today the intake is still manual entry by Ops and Partnership, which is the known hole that OC P3 closes.

What this track does not do

It sets the price that will apply. It does not calculate revenue, touch a ledger, or produce anything Finance can report on. Every number here is a rate waiting to be used, not an amount earned. This is the distinction that keeps getting lost when Phase 2 is discussed with Finance in the room.

Track B · An order is placed

Track B · the transaction lifecycle

Trigger: a customer or client buys, on the B2C app, Saudia, or a rewards portal. This is the only track where revenue is calculated.

Order placed b2c saudia portal outside OC Price read live client cat OC P2a Revenue computed vat fx fees share OC P2 · sign-off Data Lake order record reporting layer Txn ledger earning booked OC P4a Share resolved four level cascade OC P4b SOA per client feeds odoo OC P4c

The order is priced from whatever Track A last made live. The per-transaction calculation then runs in the order set out in section 2.1 of the sign-off document: card value times the applicable discount or markup, VAT on the margin only and in-country only, activation and handling fees, then FX at the transaction-date spot rate plus three percent. The order record lands in the Data Lake and the ledger books the earning against an immutable snapshot of the rate that was actually applied. Note what is absent: no card is activated and no supplier is paid anywhere in this track. Everything from the ledger rightwards is OC P4, which currently sits behind OC P3 and has no dates against it.

Where the 31 August pressure actually lands

Reading left to right, the first four steps exist today in some form. The last three, ledger, revenue share resolution and SOA, are all OC P4. That is the part Odoo consumes, it is what Finance has been asking for since June, and it sits behind a phase that delivers Finance nothing. The re-sequencing question is whether 4a and 4c move ahead of P3, and under ground rule 6 that needs a written change to the plan rather than a decision in a call.

Track C · The customer redeems, and only now does it cost anything OC P6

Track C · the redemption lifecycle

Trigger: the customer clicks their delivery link, days or months after the order. This is where the card is activated, and therefore where the supplier cost is actually incurred. Owned by the Merit Fulfilment Service, not by this workstream.

Delivery link no code yet Fulfilment Svc Customer claims code generated Fulfilment Svc Card activated drawn from supplier Fulfilment Svc Supplier cost expense incurred OC P6 · in scope Spend and burn part or full Fulfilment Svc Expiry unclaimed cost never incurred OC P6 · in scope

This is lazy fulfilment: at order time the customer receives a link, not a card. No code exists behind it and no supplier has been drawn against. Only when the customer claims does the code get generated, the card get activated, and the cost land on Merit. The redemption states after that are derived from balance read live from MGC, never set directly. The last box is a branch rather than a step: if the customer never claims, steps two through five never happen, the cost is never incurred, and Merit keeps the revenue it already booked.

The consequence, and what OC P6 has to close

Revenue is booked at order. Cost is incurred at redemption, or never. That is a genuine timing mismatch, not a modelling nicety, and the OC ledger writes only once, at order time, and is never revisited. So the Statement of Account that Odoo consumes carries revenue with no matching cost, and unclaimed cards are pure unrecorded breakage.

Two things make this harder to close than it looks. Redemption is currently tracked for MyList cards only, so the majority of third-party cards have no lifecycle record at all once they leave MGC. And the one place this has been thought about, open question 6 of the Merit Fulfilment Service PRD, proposes emitting two distinct events and letting the Ledger consume the second for liability, precisely because lazy fulfilment means no code exists until the customer claims. That is the right shape of answer, it is owned by Marthino Tri Yuda in a different workstream, and its status is still Proposed. OC P6 should consume that event rather than build a second one, which makes the Fulfilment Service a hard dependency of this phase and is the first thing to settle when P6 is specified.


The two clocks, connected

Tracks B and C are separate flows, but they are the same order item. This is where they meet, and where they fail to.

Figure D · earning and expense on the same order

EARNING · recognised when the order is done outside OC Order placed order confirmed OC P2 Revenue computed vat fx fees share OC P4a Ledger entry earning only OC P4c SOA per client revenue no cost Odoo project Odoo posts it 31 aug go live same order item OC P6 builds this link EXPENSE · incurred only if the customer redeems Delivery link no code yet Fulfilment Svc Customer claims code generated Fulfilment Svc Card activated drawn from supplier Fulfilment Svc Supplier cost expense incurred OC P6 Never claimed no cost ever OC P6 · breakage
Earning path, live or specified Earning path, later phase OC P6, agreed scope, not yet built Outside this workstream

Read down the left bracket: one order produces both bands. The top band completes in seconds and books the earning. The bottom band may complete tomorrow, may complete in six months, or may never complete at all, and the branch that never completes is the last box on the right. The red dashed line is the missing piece: there is no route from the supplier cost back into the ledger that produces the Statement of Account, so the SOA reports revenue without the cost that belongs against it.

What this changes about the 31 August question

Until now the Odoo conversation has been about whether the automation connects to Odoo and when. This reframes it. Even with the connection built and OC P4a and P4c delivered on time, the Statement of Account Odoo consumes is only half the transaction, because the matching cost arrives in OC P6 and P6 is sequenced last.

That is a deliberate choice, not an oversight, and it is defensible: revenue realisation genuinely does follow the order. But it should be said out loud to Finance rather than discovered at month-end. Between the Odoo go-live and OC P6, the SOA carries revenue without its matching cost, and that interim has to be handled manually or accepted explicitly.


Which phase takes care of what

The same five phases, read by track instead of by sequence.

PhaseWhat it is Track A, rate changeTrack B, orderTrack C, redemption
P1 Visibility Foundation
Complete, in production
Master Catalogue exists as a record, with bulk download and upload of supplier discounts, RBAC-gated to Finance and Super Admin Nothing Nothing
P2 Master to Client Sync and Revenue Models
Blocked on Rajaa's sign-off
2a propagation to client catalogues and MGC. 2b client discount recomputed when supplier discount moves. 2c manual entry in the interim. 2d margin guard The revenue calculation itself: discount or markup, VAT on margin, fees, FX. This is section 2.1 of the sign-off doc and the whole of what P2 gives Finance Nothing
P3 Supplier Rate Submission and Approval
Not started
Replaces manual entry with supplier self-submission through API, portal or CSV into one approval queue, with a written reason and full audit trail Nothing directly, but it is what stops a wrong rate reaching the order in the first place Nothing
P4 Ledger, SOA, Multi-Level Revenue
No dates, behind P3
4d account manager catalogue generation and the 30 day client notification on approved changes 4a per-transaction ledger with immutable rate snapshot. 4b four-level revenue share cascade. 4c auto-generated SOA per client, date ranges, reporting currency. This is the whole of Finance's ask Nothing
P5 Supplier Routing and Golden Catalogue
Needs the P4 ledger live
Automatic supplier selection on fulfilment rate and margin history, one SKU to one golden record Changes which supplier the order is routed to, using P4 ledger history Nothing
P6 Revenue Realisation
New, agreed 5 Aug, sequenced last
Nothing Writes the cost event back against the order so the SOA carries revenue and its matching expense, not revenue alone Consumes the redemption event from the Merit Fulfilment Service, books the supplier cost at activation, and defines the treatment for unclaimed breakage. Not yet specified

Reading the table

The right-hand column was empty for all five original phases: none of them touched what happens after the customer receives the link, which is also where the entire cost side of the transaction lives. Adding P6 closes that as an ownership question. It does not close it as a delivery question, because P6 sits last and has no dates.

What P6 has to answer, and who answers it

The scope call is made. These three are what turn it into something buildable, and two of them are Finance calls rather than product ones.

Until the first two are answered, P6 cannot be sized, and the interim between the Odoo go-live and P6 shipping has to be handled manually or accepted explicitly.