Merit Incentives · AlFursan Store · 29 July 2026 · revised 3 August 2026
A response to the fourteen clarification points raised on 26 July 2026, structured so each answer can be accepted or challenged on its own. Revised after the Marketplace sprint backlog review of 3 August 2026, which settled the tier architecture.
Clarification list of 26 July 2026 on the Promo Code BRD v0.1.
Issued 20 July 2026 from the requirements workshop of the same date.
Seven technical points and seven commercial points, each on its own tab.
Each of the seven technical points has its own tab, and the seven commercial points share one. At the bottom of every tab there is a review block with two buttons and a notes field. Mark an answer Accepted when it can go into the specification as written, or Needs discussion when it cannot, and add the reason in the notes field.
Your marks are saved in this browser only. Nothing is transmitted anywhere and this page makes no network requests. When you are finished, use Export review in the bar at the bottom to produce a plain text summary you can paste into an email reply.
On the numbers in this document
The worked examples in point 4 use an illustrative miles conversion rate and earn rate, because Merit does not hold AlFursan's commercial rate card. Both are editable inputs on that tab. Replace them with your figures and every number on the page recalculates. The arithmetic is the thing to review, not the rate.
| Date | Version | What changed |
|---|---|---|
| 29 July 2026 | v1.0 | First issue. Answers to the fourteen clarification points of 26 July 2026. |
| 2 August 2026 | v1.1 | Worked calculation examples corrected and the commercial tab completed. |
| 3 August 2026 | v2.0 | Tier architecture settled at the Marketplace sprint backlog review. Point 1 and point 2 rewritten: Merit resolves the member tier by a live call to the AlFursan Accenture API at the moment a code is validated, and stores no tier value, no member reference for tier purposes, and no personal data of any kind. The stored tier proposal, the daily refresh job, and the Merit tier store are withdrawn. The security and compliance approval that the stored design required is closed as no longer applicable, because nothing is stored. Phase 2 gains a basic per campaign promo code stacking toggle, off by default. Phase 1 is approved for the next sprint against the Saudi National Day date. |
| 3 August 2026 | v2.1 | Point 1 and point 2 extended with three things settled in the same discussion but missing from v2.0. The AlFursan member ID is named as the anchor attribute linking the two systems, with the reason email and phone are not used in that role. The case against batch processing is stated on its own terms, independently of privacy: Merit knows only the members who have signed in to the store, so a batch either covers a partial base or requires the full membership list. The cost of the decision at campaign creation time is stated plainly: the creation screen cannot size an audience, and audience sizing becomes a separate conversation rather than a dependency of Phase 2. |
| Point | Subject | Where this leaves it |
|---|---|---|
| 1 | Member data for tier discounts | Closed 3 August 2026. No member data is stored at all, so there is nothing to protect and no approval to wait for |
| 2 | Stored tier versus live lookup | Decided 3 August 2026. Live lookup against the AlFursan Accenture API at validation time |
| 3 | Capability confirmation | Answered in full, including one capability we will not overstate |
| 4 | Calculation examples | Answered with a working calculator. Partial return needs your rule |
| 5 | Restoration after cancellation | Answered in full. No open items |
| 6 | Reporting fields and sample | Answered in full. Field list open to additions |
| 7 | Designing Phase 1 and 2 together | Agreed. Shown as what is built once and released twice |
| C1 to C7 | The seven commercial points | All answered on the Commercial tab. Three rest on the signed agreement and are confirmed in writing by 3 August |
What Merit needs back
Four decisions from the BRD are still open and three of them block the Phase 1 specification. They are listed on the last tab with the recommendation for each, so they can be settled in the same pass as this review. The tier architecture question that used to sit alongside them was settled on 3 August 2026 and is recorded as resolved on that same tab.
Point 1
Phase 2 tier discounts need Merit to know which tier a member holds at the moment they apply a code. Settled on 3 August 2026: Merit asks AlFursan for that tier at the moment of validation and keeps nothing.
Short answer
Nothing is stored. When a member applies a code, Merit calls the AlFursan tier API operated by Accenture, uses the tier value it receives to price that one basket, and discards it when the response is sent. There is no tier store, no cache, and no data sync in either direction.
The earlier version of this page proposed a small Merit side tier store holding an anonymous reference and a tier value. That proposal is withdrawn. Merit holds no AlFursan member data of any kind, at any point, which removes the question this page was originally written to answer.
| Field | What it holds | Example | Stored by Merit |
|---|---|---|---|
| AlFursan member ID | The anchor attribute that links a user consistently across AlFursan systems and Merit systems. It is already present on the store session and is sent in the outbound lookup request. It is not written anywhere for tier purposes. Merit may hold its own internal identifiers, but the AlFursan member ID is what the two sides agree on | af_9c1e... | No |
| tier | The tier value returned by the AlFursan Accenture API, held in process memory for the life of the single validation call | GOLD | No |
| Nothing else | There is no third field, because there is no record. No table, no cache entry, no refresh timestamp, and no batch file | n/a | No |
Used in memory to price one basket, then gone.
Never requested, never received, never held.
No batch, no feed, no mirror of the membership base.
Both sides need one attribute they can agree on to refer to the same person over time. Email and phone number are both prone to change across a membership lifetime, so neither is safe as the link between the two systems. The AlFursan member ID is created once when the profile is created on the AlFursan side and stays constant for the life of that user, which is why it is the attribute the lookup is keyed on.
Even setting the data protection argument aside, a scheduled batch cannot answer the question a campaign needs to ask. Merit only becomes aware that a member exists when that member signs in to the store. If the programme holds a million members and a fraction of them have ever signed in to the Merit marketplace, Merit knows only that fraction. It does not know the size of the wider programme, and it does not know who the remaining members are.
That leaves a batch with two options and neither works. Processing only the members Merit already knows about produces a partial answer that silently excludes most of the programme. Processing the full membership base would require AlFursan to hand over the entire member list, which is the opposite of the direction this design took. The live lookup avoids the choice entirely: the question is only ever asked about one member, at the moment that member is standing at checkout.
Nothing has been requested from AlFursan yet. Merit first checks the campaign rules it holds itself, so a code that is expired, suspended, or out of budget is rejected without touching your API at all.
The call is raised only for a campaign that is actually tier differentiated. A Phase 1 store wide code never calls it, and neither does a Phase 2 campaign that scopes by category alone. This keeps the load on the Accenture API proportional to the campaigns that need it.
The returned value is used to select the discount percentage for that basket. It is not written to a database, a cache, a queue, or a log line. Upgrades and downgrades therefore need no propagation mechanism at all: the next validation asks again and gets the current answer.
Merit applies the campaign's base tier discount rather than rejecting the code in front of the member, and flags the affected orders in the campaign report so AlFursan can see exactly which redemptions were priced on the fallback. Merit asks AlFursan for a documented latency and availability commitment on the tier API, since the campaign now depends on it.
The value is discarded when the response is returned. There is no retention period to agree, no deletion schedule to run, and no data subject deletion request that Merit can be asked to service, because Merit holds nothing to delete.
| Control | Position |
|---|---|
| Encryption in transit | TLS on every call between Merit and the AlFursan tier API. This is the only place tier data exists in the Merit path |
| Encryption at rest | Not applicable. There is no tier data at rest on the Merit side to encrypt |
| Access control | Service level credentials for the promo validation service calling the tier API. No standing human access, because there is no store for a human to read |
| Audit log | Merit logs that a tier lookup was made for a given validation attempt, with timestamp and outcome. The tier value itself is not written into the log |
| Segregation | The tier value is used only to price the basket in the request that fetched it. It is never combined with any other Merit dataset, because it never outlives the request |
| Deletion | Not applicable. Nothing is retained, so there is nothing to delete on a schedule or on request |
Settled on 3 August 2026: the security and compliance approval is closed
The earlier version of this page said that Merit security and compliance would issue a written position on encryption standard, retention period, audit retention, and the derivation of the member reference. All four of those questions existed only because the design stored a record. The design no longer stores anything, so the approval is no longer required and is closed as not applicable rather than pending.
What replaces it is narrower and sits on the integration rather than on data: a latency and availability commitment on the AlFursan tier API, and the agreed fallback behaviour in step 4 above. Neither blocks Phase 1, which has no tier logic, and neither blocks the Phase 2 build.
Point 2
Both approaches work and they fail in different ways. The comparison below is kept as the record of the analysis. The decision, taken on 3 August 2026, is the live lookup.
Short answer, revised 3 August 2026
Live lookup. Merit calls the AlFursan Accenture tier API at the moment a code is validated and stores nothing. The stored tier design in the left hand column below, together with its daily refresh and its staleness guard, is withdrawn.
Why the decision went the other way from the original recommendation
This page originally recommended the stored tier, on latency and availability grounds. The review of 3 August 2026 weighed those against the cost of holding AlFursan member data at all, and the data position won: a design that stores nothing removes the security approval, the retention question, the deletion channel, and the derivation of the member reference in one move. The latency and availability cost is real and is accepted, managed through the timeout guard and the agreed fallback in point 1, step 4.
Checkout calls the Merit promo validation service with the basket and the code. Merit checks its own campaign rules first, so expired, suspended, and out of budget codes are rejected before any external call is made.
An external round trip inside the checkout path, raised only for campaigns that are actually tier differentiated. The call is timeout guarded so a slow API cannot hold the checkout open.
The tier value prices the basket in memory and is discarded with the response. Nothing is written on the Merit side.
Merit applies the campaign's base tier discount rather than rejecting the code in front of the member, and flags the affected orders in the campaign report. This is the agreed behaviour, and it is why Merit asks for a documented latency and availability commitment on the tier API.
| Dimension | Stored tier, withdrawn | Live lookup, decided |
|---|---|---|
| Checkout latency | Negligible, a local read | One external round trip per validation attempt |
| Availability | Unaffected by AlFursan system availability | Campaign is only as available as the tier API |
| Data held at Merit | Anonymous reference plus tier value | None held |
| Freshness | As fresh as the refresh cadence, with a live lookup fallback when a record is stale | Always current. An upgrade applies to the very next basket, with no propagation delay |
| Load on AlFursan systems | One scheduled batch per day | One call per validation attempt, including failed attempts and retries |
| Cost | Storage cost is negligible at this volume | No storage cost, higher integration and support cost |
| Operational dependency | Refresh job must be monitored | Live API must hold a checkout grade SLA, including during campaign peaks |
| Failure mode | A member sees yesterday's tier for up to one refresh cycle | A member sees no discount, or the wrong one, during an outage |
Decision, 3 August 2026
Live lookup against the AlFursan Accenture tier API at validation time. Merit stores no tier value, no member tier history, and no AlFursan member data of any kind. There is no cache and no sync job anywhere in the design.
Merit asks for two things on the back of it: a documented latency and availability commitment on the tier API, and confirmation of the agreed behaviour when the API does not answer, which is to fall back to the campaign's base tier discount and flag the affected orders in the campaign report rather than reject the code in front of the member.
The stored tier design above is retained on this page only as the record of what was compared. It is not being built.
Promo codes are not only a redemption feature. They are also a creation feature, and the two halves are affected differently by this decision. Redemption is unaffected and arguably improved, because the tier read is always current. Creation loses something real, and it is worth naming rather than discovering later.
Because Merit holds no copy of the membership base, the campaign creation screen cannot size an audience. An operator building a Gold tier campaign cannot be shown how many Gold members exist, what share of the base they represent, or how many members a given set of restrictions would reach. Only AlFursan holds the data needed to answer that, so any such number would have to come from AlFursan rather than from the Merit screen.
The accepted approach is therefore the simpler one: at creation, the operator defines the code and its restrictions and limitations without any member data in front of them. At redemption, Merit calls the AlFursan system, checks the member against the campaign's parameters, and receives an eligible or not eligible answer. Audience sizing, if AlFursan wants it, is a separate conversation and a separate piece of work, not a dependency of Phase 2.
This decision affects Phase 2 only. Phase 1 has no tier logic and was never waiting on it.
Point 3
Every capability you listed, with an honest status against each. One of them Merit will not claim in full, and the reason is on this page.
Short answer
Everything on your list is deliverable except tight device level control, which no web storefront can honestly promise. Four settings sit in Phase 1, and everything touching personal or payment data waits for Phase 2.
| Capability | Status | Note |
|---|---|---|
| Percentage and fixed value discounts | Phase 1 | Both, set per campaign |
| Discount on miles, cash, or both components | Phase 1 | Applied to the basket value, then split across the payment components in the same proportion as the member's chosen split |
| Minimum basket value | Phase 2 proposed | Rides on campaign scoping. Its absence is why Merit proposes percentage codes only in Phase 1 |
| Maximum discount per order | Phase 2 proposed | Rides on the same scoping work. Phase 1 relies on the campaign budget cap alone, so set that cap low on the first campaign |
| Product, category, and brand inclusion or exclusion | Phase 2 | Non eligible items in the same basket are charged at full price |
| Gift card exclusion | Phase 1 proposed Phase 2 proposed | A single store wide flag in Phase 1, then exclusion by category once scoping arrives |
| Prevention of promo code stacking | Phase 1 proposed Phase 2 | Structural, so the one code per order rule holds from the first code that exists. Added 3 August 2026: Phase 2 adds a per campaign toggle that lets a named campaign opt in to stacking. Off by default |
| Prevention of combining a code with an existing discount | Phase 1 proposed | The product level discount already exists in the store today, so the collision is live from the first campaign |
| Campaign level redemption limit and budget limit | Phase 1 | Both a redemption count cap and a discount value cap. The campaign stops automatically when either is reached |
| Usage limit per member | Phase 1 | Enforced server side against the AlFursan member identity. This is the strongest limit available and it cannot be bypassed from the browser |
| Usage limit per account | Phase 1 | Same mechanism as per member |
| Usage limit per household | Your decision Phase 2 proposed | Open point 1 of the BRD, and it needs AlFursan to supply the relationship between accounts. That is member data Merit would have to hold, which the tier design deliberately avoids, so it needs its own compliance position before it can be built |
| Usage limit per IP address | Limited Phase 2 proposed | Deliverable as a velocity control, with a caveat below. An IP address is personal data, so it waits for the compliance position |
| Usage limit per device | Limited Phase 2 proposed | Best effort signal only on a web storefront, explained below, and a persistent device identifier needs a consent position first |
| Immediate suspension on misuse or fraud | Phase 1 proposed | Operational safety for the first public code. Nothing to build in Phase 2 or 3 |
These were in your list but not in the BRD's three phase plan, so there was nothing to point at when you asked which release they arrive in. Each one is attached below to the requirement or the data it depends on, and it inherits that dependency's phase.
The governing rule is that anything needing data Merit does not hold today sits in Phase 2, behind its own security and compliance position. That covers the household rule, IP addresses, payment card references, and device signals. It would be wrong to ship those in Phase 1 and settle the data question afterwards. Tier is no longer on that list: as of 3 August 2026 the tier is read live from AlFursan and never stored, so it carries no data question of its own.
| Setting | Merit proposes | Why it cannot wait |
|---|---|---|
| Code stacking | One code per order in Phase 1, not configurable. Phase 2 adds a per campaign toggle, off by default, so a campaign has to opt in before two codes can combine | Structural. Retrofitting the rule itself later invalidates every campaign report issued before the change, so Phase 1 sets the default and Phase 2 only exposes the switch |
| Code plus an existing product discount | Not combined by default, taking the deeper of the two, configurable per campaign | Section 2 of the BRD records that a product level discount is the store's only promotional tool today, so the collision is live on the first campaign |
| Gift card exclusion, store wide | A single blanket exclusion covering every campaign | One flag, and without it the first public code discounts stored value. Exclusion by category follows in Phase 2 with scoping |
| Immediate suspension | Available to Merit and AlFursan from the admin console, effective within seconds | Operational safety for the first public code. There is no later version of it to build |
| Setting | What it depends on | Sensitive data |
|---|---|---|
| Minimum basket value | Campaign scoping, which arrives in Phase 2 | None |
| Maximum discount per order | Same scoping work | None |
| Gift card exclusion by category | Product and category scoping, Phase 2 | None |
| Household and family limit | AlFursan defining a household, then supplying the relationship between accounts | Yes. Relationships between members are more revealing than a tier value, and unlike the tier they would have to be stored, so this needs a compliance position of its own |
| IP velocity thresholds | Retaining IP addresses against redemption attempts for a defined window | Yes. An IP address is personal data. It needs a retention period and a lawful basis before it is stored, not after |
| Payment card limits | Retaining a card reference against redemption history | Yes. Payment data carries its own handling requirements independent of the promo feature |
| Device fingerprint for anomaly reporting | Collecting and retaining a browser derived identifier | Yes. A persistent device identifier is a tracking identifier and needs a consent position first |
What this costs Phase 1, stated plainly
Moving those rows to Phase 2 leaves Phase 1 with two abuse controls rather than six: the per member limit and the campaign redemption and budget cap. The layered plan below already names those as the primary defence, so this is not a hole so much as a thinner first release, but two consequences follow and both are real.
Phase 1 should run percentage codes rather than fixed amount codes. Without a minimum basket value, a fixed 50 SAR off can be spent on a 60 SAR basket. A percentage code has no equivalent exposure, and Saudi National Day is a percentage campaign, so Phase 1 loses nothing it needs.
Phase 1 campaigns need a firmer budget cap than they otherwise would. With no per order ceiling, one high value electronics basket consumes a visible share of a campaign. Merit recommends setting the Phase 1 campaign budget deliberately low on the first campaign and raising it once real redemption data exists.
Phase 3 in the BRD is vouchers and influencer codes, where a code stops being public and becomes individual. Nothing in your list lands there, because every item above is about controlling a public code. Phase 3 has its own control requirements though, and they do not exist in Phases 1 and 2 at all:
| Phase 3 control | Why it only exists once codes are individual |
|---|---|
| Member bound validation | A voucher issued to one member has to be refused for everyone else. A public code has nobody to bind to |
| Code entropy and guess protection | Bulk generated codes must be long and random enough that they cannot be guessed, with attempt rate limiting at checkout. A single published code like SND is meant to be known, so neither applies |
| Validity from date of issue | A voucher expires a set number of days after it is sent to that member, so every code carries its own clock rather than the campaign's |
| Per code attribution and reversal rate | Influencer performance is judged per code, including the share of redemptions that later came back. There is nothing to attribute when everyone shares one code |
| Revocation of a single issued code | Withdrawing one influencer's code without stopping the campaign. Phase 1 suspension is all or nothing by design |
How to close this section
Mark this point accepted if the three phase placements above are right. The row most worth arguing about is the maximum discount per order, since moving it to Phase 2 is what forces the tighter Phase 1 budget cap. If you would rather have it in Phase 1, say so and Merit will move it back, because it needs no data from AlFursan to build.
The AlFursan Store runs in a web browser, where anyone can open a private window and present as a new device. That puts a ceiling on how tight device level control can be, and the plan below is built around that ceiling rather than around a claim Merit cannot keep.
Merit could implement device fingerprinting and report it as a supported control. It would not be accurate. A member using a private browsing window, a second browser, a different phone, or a cleared browser store presents as a new device every time. Any promo protection built on device identity as its primary defence is protection on paper.
This is not specific to Merit. It is why marketplaces that need genuinely tight promotional control run those campaigns inside a mobile application, where the install itself is the device identity and cannot be reset by clearing browsing data. It is also why some marketplaces deliberately offer app only promo codes. What makes those codes controllable is the channel they run in, and on a web storefront that channel is not available.
What Merit will do is get the maximum that is achievable in the current environment, and be precise about what each layer actually buys. The design below assumes device identity is unreliable and puts the real defence where it holds.
A code is redeemed by an authenticated AlFursan member, so every limit is counted against the member identity in Merit's usage ledger. Once per member, once per member per 30 days, first purchase only, all of it is enforced on the server.
What defeats it: only a member creating multiple genuine AlFursan memberships. That is a membership control on your side rather than a store control on ours, and it is the single most effective thing that can be done about promo abuse.
Every campaign carries a maximum number of redemptions and a maximum total discount value. When either is hit, the code stops working. This is what bounds the damage of any abuse pattern nobody anticipated, and it is the reason a campaign can never cost more than the number you set when you created it.
Merit can cap redemptions from a single IP address within a time window. This catches the crude case of many redemptions driven from one machine in a short period.
The caveat that matters: mobile carriers and corporate networks put large numbers of unrelated people behind one address. A hard limit of one redemption per IP would reject genuine members who did nothing wrong, and on a national campaign that produces complaints rather than protection. Merit therefore proposes IP as a velocity threshold set high enough to be safe, for example a burst of redemptions from one address in a few minutes, rather than a per member style limit. The threshold is configurable per campaign and Merit will propose a starting value with the specification.
For the cash component of a Miles and Cash order, redemptions can be limited per payment card. A card is harder to duplicate than a browser session, which makes this a materially better signal than device fingerprinting for the same purpose.
Limit: it does nothing on a Miles only order, because no card is presented.
Merit will collect a browser level device signal and use it for detection and reporting, not as a gate. If one device signal appears across many member accounts on a campaign, that pattern surfaces in the anomaly report and a human decides what to do about it.
Merit will not present this as a device limit, because a private window defeats it and a control that can be defeated by a keyboard shortcut should not be described as a control.
Campaign monitoring surfaces unusual redemption velocity, unusual concentration on one device signal or IP range, and unusual reversal rates. A live code can be suspended immediately, and Merit notifies AlFursan at the same time it acts.
| Control | What it costs an abuser to defeat | False positives on genuine members | Verdict |
|---|---|---|---|
| Member and account limit | Creating a second genuine AlFursan membership | None | Primary defence |
| Campaign redemption and budget cap | Cannot be defeated. It bounds the total regardless of method | None until the cap is reached | Bounds the loss |
| Payment card limit | A second payment card | Shared family cards | Useful on the cash component only |
| IP velocity threshold | A mobile hotspot or a VPN | High if set tight, because carrier and office networks share addresses | Velocity alerting, not a hard gate |
| Device fingerprint | A private browsing window | Moderate, since families share devices | Reporting signal only |
| Anomaly review and suspension | Nothing, it is a response rather than a barrier | None | Catches what the rules did not anticipate |
The recommendation that follows from this
Where a campaign carries high abuse risk, either because the discount is deep or the code is public, the protection should come from layers 1 and 2 rather than from device controls. In practice that means tighter per member limits, a firm campaign budget cap, and a first purchase restriction where the campaign is an acquisition campaign.
That matters more now than it did, because layers 3, 4 and 5 all sit in Phase 2 behind the compliance position. Phase 1 runs on layers 1, 2 and 6, which are the three that do not need any new data and, on the table above, the three that are hardest to defeat anyway.
If AlFursan later launches a mobile application, app only codes become possible and the device question changes completely. On a web storefront, this plan is the honest ceiling.
Point 4
Change any input and every table below recalculates. The defaults are illustrative, so replace the conversion rate and the earn rate with AlFursan's real figures.
Short answer
The discount applies to the product value before VAT, VAT is recalculated on the discounted value, delivery is never discounted, and miles are earned on what the member actually pays. Change any input below to check it against a real basket.
The member pays the entire order in miles. The discount reduces the product value, VAT is calculated on the discounted product value, and the delivery fee is not discounted.
| Line | Without code | With code |
|---|
Same basket, paid partly in miles and partly in cash on the split set above. The discount is applied to the basket first, then the payable amount is split in the member's chosen proportion, so the discount benefits both components rather than only one.
| Line | Without code | With code |
|---|
Proposed treatment, for confirmation
The discount applies to the product value before VAT, VAT is then calculated on the discounted product value, and the delivery fee is never discounted unless the campaign explicitly includes free delivery. Miles are earned on the amount the member actually pays after the discount, which is section 4.2 of the BRD. Merit is confirming the VAT treatment with finance and will state the final position with the specification.
All three cases below use example A. Full cancellation and full return behave identically. Partial return is the case with no rule yet, so both candidate rules are shown side by side and AlFursan chooses one.
| Scenario | Refunded to member | Miles reversed | Redemption | Member allowance |
|---|
The member keeps part of the basket and returns the rest. The share returned is set here.
| Line | Rule A, discount recalculated | Rule B, discount kept whole |
|---|
The discount is re-applied to the retained items only, and the difference is deducted from the refund. Consistent with the campaign intent, and the member never keeps a discount on goods they returned. Slightly harder to explain on a refund statement.
The returned items are refunded at their full value and the entire discount stays applied to what the member kept. Simplest to explain on a refund statement. It also means a member can return most of a basket and keep a discount earned on the whole basket, which the effective rate row above makes visible.
Merit recommendation
Rule A, because Rule B lets a member meet a minimum basket threshold, take the discount, and return the items that got them over the threshold. This is BRD open point 9 and the decision sits with AlFursan.
Point 5
Every redemption is counted twice, once when it happens and once when it settles. Nothing is final until the 30 day miles window closes.
Short answer
Inside 30 days, a reversal returns the member's allowance and puts the redemption and its budget back into the campaign. After 30 days the result stands, and anything already billed is credited on the next statement.
The discount is given. The member's usage allowance is consumed. The campaign's remaining redemption count and remaining budget both go down.
The redemption is cancelled. The member's usage allowance is returned, so a member whose order was cancelled is not punished by losing their one use of a campaign. The campaign's remaining redemption count and remaining budget both go back up, so the returned budget can be spent by another member.
The order has settled and the miles have been credited. The result stands and is not reversed by anything that happens afterwards.
Handled under the standard returns policy. The campaign result is not restated, because a campaign that has closed and been billed does not reopen. These cases appear in the reversal rate for visibility rather than as an adjustment.
| What is restored | On reversal inside 30 days | On reversal after 30 days |
|---|---|---|
| Member usage allowance | Returned in full | Not returned |
| Campaign redemption count | Returned to the pool | Not returned |
| Campaign budget | Returned to the pool | Not returned |
| Billing | Never billed, since only confirmed redemptions are billable | Appears as a credit line on the next statement |
| Miles earned by the member | Reversed with the order | Per the standard returns policy |
Consequence for campaign reporting
A campaign cannot be declared successful on the day it ends, because its last orders are still inside their window. Every campaign report shows provisional and confirmed figures side by side and never presents one number without stating which it is.
Point 6
Every field you asked for is included. Merit has added the fields that come out of the miles model, because a promo report on a loyalty store that ignores miles impact is incomplete.
Short answer
Every field you listed is included, plus miles earned and miles foregone. Provisional and confirmed figures always appear side by side, so no number is ever shown without saying which one it is.
| Field | Definition | Requested by |
|---|---|---|
| Redemptions, provisional | Codes applied to an order, including orders still inside the 30 day window | AlFursan |
| Redemptions, confirmed | Redemptions on orders that have passed 30 days with no reversal. This is the billable number | Merit |
| Unique members | Distinct members who redeemed | AlFursan |
| New versus existing | Split on the agreed definition of a new customer, BRD open point 6 | AlFursan |
| Tier | Redemptions and value by member tier. Phase 2 onward | AlFursan |
| Basket value | Order value before discount, excluding VAT and delivery | AlFursan |
| Discount value | Total discount given. This is the AlFursan funded amount | AlFursan |
| Net value | Basket value after discount | AlFursan |
| Miles redeemed | Miles used to pay for the order | AlFursan |
| Cash collected | Cash component collected on Miles and Cash orders | AlFursan |
| Miles earned | Miles credited to members on the amount actually paid | Merit |
| Miles foregone | Difference between what members would have earned at full basket value and what they earned after discount. A member impact metric, never an accounting entry | Merit |
| Cancellations and returns | Counts and value, split full and partial | AlFursan |
| Reversal rate | Reversed redemptions as a share of provisional redemptions, per campaign and per code | AlFursan |
| Category performance | Redemptions and discount value by category. Phase 2 onward | AlFursan |
| Order level traceability | Every line traces to an individual order ID, downloadable | AlFursan |
Illustrative figures for a hypothetical Saudi National Day campaign, shown to demonstrate the shape of the report rather than any forecast. Nothing on this page is a projection.
10 percent store wide, 20 to 25 September 2026
Report generated 30 September, so late orders are still provisional
Cap of 5,000 redemptions and 250,000 SAR of discount
| Metric | Provisional | Confirmed |
|---|---|---|
| Redemptions | 3,412 | 2,180 |
| Unique members | 3,301 | 2,144 |
| New customers | 1,240 | 790 |
| Existing customers | 2,061 | 1,354 |
| Basket value before discount, SAR | 2,730,000 | 1,744,000 |
| Discount value, SAR | 273,000 | 174,400 |
| Net value, SAR | 2,457,000 | 1,569,600 |
| Miles redeemed | 41,800,000 | 26,700,000 |
| Cash collected, SAR | 612,000 | 391,000 |
| Miles earned by members | 2,457,000 | 1,569,600 |
| Miles foregone | 273,000 | 174,400 |
| Cancellations and returns | 168 | - |
| Reversal rate | 4.9% | - |
How to read a report like this one
The provisional column is larger than the confirmed column purely because the campaign closed five days before the report was generated, so most of its orders are still inside the 30 day window. Judging this campaign on either column alone would be wrong. The number that gets billed is the confirmed one.
The field list is open. If a field is missing that AlFursan marketing or finance needs, add it in the notes below and Merit will include it in the specification rather than treat it as a change later.
Point 7
Agreed, and this is how Merit intended to build it. Here is what that means concretely.
Short answer
Yes. The two phases are designed as one system and released separately, so Phase 1 can run a campaign on its own. Phase 1 was approved on 3 August 2026 for the next sprint, against the Saudi National Day date, which is fixed and external.
The parts that would otherwise cause rework in Phase 2 are built during Phase 1, whether or not Phase 1 has a use for them.
| Component | Designed and built in Phase 1 | Switched on in Phase 2 |
|---|---|---|
| Campaign configuration model | Carries fields for category scope and tier scope from the start, unused in Phase 1 | Category and tier scoping become editable in the admin console |
| Rules evaluation | Built as a rule set over the basket rather than a single store wide check | Item level eligibility rules are added to the same evaluation |
| Discount application | Applied per eligible line, with every line eligible in Phase 1 | Non eligible lines are excluded without changing how the discount is applied |
| Reporting schema | Tier and category dimensions exist in the schema and report as empty | Dimensions populate. Phase 1 campaign history stays queryable in the same report |
| Reconciliation | Complete in Phase 1, per BRD section 4.1 | Unchanged. Phase 2 adds no new billing logic |
| Tier resolution | Not built. Phase 1 has no tier logic and makes no call to AlFursan | A live call to the AlFursan Accenture tier API at validation time, per point 1. No tier store is built in either phase |
| Stacking rule | One code per order, enforced in the rules evaluation from the first campaign | A per campaign toggle exposes that same rule in the admin console, off by default |
The BRD set the three phases on 20 July. The clarifications you raised have moved some things between them, so this is the current contents of each release in one place. Rows marked as added are ones that were not in the BRD and arrived through your list.
| Phase 1, generic promo codes | Source |
|---|---|
| Code entry at checkout, discount applied to the full basket in miles or cash | BRD |
| Percentage discounts. Merit now recommends fixed amount codes wait for Phase 2, since the minimum basket that protects them moved there | BRD, amended |
| Campaign start and end date | BRD |
| Total redemption cap and campaign budget cap | BRD |
| Per member and per account usage limits, including a limit per rolling period | BRD |
| New customer only restriction, meaning members with no prior purchase on the store | BRD |
| Basic redemption report per code, split new against existing | BRD |
| Automated reconciliation and the billing statement | BRD |
| One code per order, no stacking, not configurable in this release | Added |
| Code against the existing product level discount, not combined by default | Added |
| Store wide gift card exclusion | Added |
| Immediate suspension of a live code | Added |
| Phase 2, segmented promo codes | Source |
|---|---|
| Product, category, and brand scoping, so a code applies only to eligible items | BRD |
| Tier based discount, one code returning a different percentage per tier | BRD |
| Reporting by tier, by category, and by customer state | BRD |
| Tier and customer state combined on one campaign, for example Gold members on their first purchase | BRD |
| Live tier resolution against the AlFursan Accenture API at validation time, with nothing stored on the Merit side | BRD, revised 3 August 2026 |
| Basic promo code stacking toggle, set per campaign, off by default so a campaign has to opt in | Added 3 August 2026 |
| Minimum basket value, and with it fixed amount discount codes | Added |
| Maximum discount per order | Added |
| Gift card exclusion by category rather than store wide | Added |
| Household and family account limits, once AlFursan defines a household | Added, needs your data |
| IP velocity thresholds | Added, personal data |
| Payment card limits on the cash component | Added, payment data |
| Device signal for anomaly reporting | Added, needs a consent position |
What the Phase 2 stacking toggle is, and what it is not
It is a single per campaign switch. Off by default, and a campaign has to opt in before a second code can combine with it. That is the whole of it, and it is small because the one code per order rule is already structural in Phase 1: Phase 2 exposes the rule rather than rebuilding it.
It is not the full stacking framework. Stacking groups, priority and precedence between overlapping codes, exclusivity sets, and A/B testing of stacking rules are a separate and much larger piece of work. They stay deferred to the 2027 promo engine document, PRD_Promo_Engine_V2_Stacking_AB.md, and nothing in that document is in scope for the AlFursan Phase 2 release.
| Phase 3, vouchers and influencer codes | Source |
|---|---|
| Bulk generation of unique codes, one per influencer or one per member in a segment | BRD |
| Codes bound to a specific member, unusable by anyone else | BRD |
| Validity counted from the date of issue, for example 30 days from the day the email is sent | BRD |
| Attribution reporting per code, with new customers reported separately so influencer performance is judged on acquisition | BRD |
| Rapid manual issuance of a single bespoke code for a partner or guest | BRD |
| Code entropy and guess protection, with attempt rate limiting at checkout | Added |
| Revocation of one issued code without stopping the campaign | Added |
| Reversal rate per influencer code, so a code producing returns is visible | Added |
The difference between Phase 3 and everything before it
Phases 1 and 2 are about one code that everybody uses. Phase 3 is about many codes, each belonging to one person or one influencer. That is why its controls have no earlier equivalent. There is nobody to bind a public code to, nothing to guess when the code is printed in a campaign email, and nothing to attribute when every redemption came through the same code.
It is also the phase that makes influencer marketing measurable, which was the fifth use case in section 3 of the BRD and the one with no interim workaround. Until Phase 3 exists, AlFursan can run a campaign and see what it produced in total, but cannot tell which influencer or which channel produced it, so spend cannot be reallocated on evidence.
Why the sequencing does not change
Designing the two phases together removes rework. It does not merge the releases. Phase 1 still ships on its own so AlFursan can run a store wide campaign, for example Saudi National Day, which is the fixed external date Phase 1 was approved against on 3 August 2026. Phase 2 carries the tier integration and the category scoping, and merging the two would put a store wide campaign behind an integration it has no dependency on.
Phase 3, vouchers and influencer codes, is designed against the same campaign model. The per code attribution reporting it needs is the same reporting schema described in point 6, extended with a code dimension.
Commercial points 1 to 7
Two of these were settled in the workshop of 20 July and are restated here. The other five are Merit's position, and the ones that touch the signed agreement are marked so you can see exactly what rests on it.
Short answer
The revenue share model itself does not change. Merit's position is that the share is calculated on the basket value before the discount, since AlFursan reimburses the discount in full. Three of the seven points rest on the signed agreement and are confirmed in writing by 3 August.
The revenue share model does not change. No new share, no new rate, and no change to what is shareable.
The only thing that changes is that a discounted order carries two values instead of one. There is the basket value before the discount, which is what the store sold, and the amount the member paid, which is what was collected at the till. Point C2 decides which of those the share is calculated on, and that is the whole of the commercial question here.
Merit's position is before the discount, on the full basket value.
Section 4.1 of the BRD, agreed on 20 July, is that AlFursan absorbs the discount in full and Merit subsidises no part of it. AlFursan reimburses the discount, so the order is economically a full price order and the share is calculated on the value the store actually sold.
The alternative would mean Merit earning less on a discounted order than on the same order at full price, which is Merit co-funding an AlFursan campaign. That also matters for point C6. Merit can only credibly say it applies no ceiling on how deep a campaign goes if campaign depth does not cost Merit anything, and calculating the share on the pre discount value is what makes that true.
| On a 1,000 SAR basket with a 200 SAR AlFursan funded discount | Share calculated before the discount | Share calculated after the discount |
|---|---|---|
| Value the store sold | 1,000 SAR | 1,000 SAR |
| Collected from the member | 800 SAR | 800 SAR |
| Reimbursed by AlFursan | 200 SAR | 200 SAR |
| Base the revenue share is applied to | 1,000 SAR | 800 SAR |
| Effect on Merit against the same order at full price | None | Merit earns less because AlFursan ran a campaign |
| Effect on the no ceiling position in C6 | Holds, since campaign depth costs Merit nothing | Breaks, since every extra point of discount costs Merit |
Rests on the signed agreement
This is the one point on this tab with money attached to it. Merit commercial is confirming it against the signed revenue share terms and will state the final position in writing by 3 August. If the agreement already fixes the basis on collected value, Merit will say so plainly rather than argue from the BRD.
| Element | Merit's position |
|---|---|
| Funding | No upfront deposit and no prefunded campaign wallet. The discount accrues as a receivable against AlFursan as redemptions confirm |
| What is billable | Confirmed redemptions only, meaning orders that passed the 30 day window with no cancellation or return. Provisional redemptions appear on the statement for visibility and are not charged |
| Statement | Automated, itemised by campaign, every line traceable to an order ID and downloadable. Built into Phase 1 rather than added later. Re-running a closed period returns identical figures |
| Settlement | Netted against the existing AlFursan Store settlement rather than invoiced as a separate stream, so there is one payment flow and not two |
| Payment terms | The same terms as the existing AlFursan Store commercial agreement. Merit commercial confirms the exact wording by 3 August |
| Case | What appears on the statement | Automatic |
|---|---|---|
| Reversal inside the 30 day window | Nothing. It was never billed, because only confirmed redemptions are billable, so there is no charge to credit | Yes |
| Reversal after the redemption confirmed and was billed | A credit line on the next statement, itemised to the original order ID | Yes, no claim and no manual request |
| Partial return | A credit for the returned portion, calculated under whichever partial return rule AlFursan selects on the calculations tab | Yes, once the rule is chosen |
There is no reconciliation meeting in this process and no period where AlFursan has to assemble a claim. If a reversal happened, it appears.
Frequency. Monthly, aligned to the existing AlFursan Store billing cycle. Merit commercial confirms this matches the current cycle by 3 August.
When a redemption becomes chargeable. When it confirms, meaning 30 days after the order is accepted with no cancellation or return.
The consequence worth stating now rather than discovering on an invoice. A campaign is billed across two statements, and its final cost is only known 30 days after it ends. Traced through a September campaign:
Redemptions start accumulating as provisional.
No further redemptions. Nothing is billable yet, because no order has passed its 30 day window.
Carries no confirmed redemptions from this campaign. The campaign appears with its provisional figures for visibility only.
Each order confirms 30 days after it was accepted, so the campaign settles across the same six day spread over which it ran.
Carries the confirmed redemptions and the credit lines for anything reversed. This is the invoice that matters.
Only at this point can the campaign be judged on confirmed numbers. Anything reported before this is provisional and will move.
No ceiling. Because AlFursan funds the discount in full, AlFursan sets the ceiling. Merit applies no limit on discount percentage, campaign budget, eligible categories, or campaign frequency. Whether a 30 percent Saudi National Day offer is worth running is entirely an AlFursan judgement. This restates BRD section 4.1.
There are two exceptions and neither is commercial.
Gift cards are excluded from campaigns by default. A gift card is a stored value instrument, so discounting one converts a promotion into a currency arbitrage. Merit will lift the exclusion on a named campaign at AlFursan's written request.
Merit can suspend a live code immediately where there is active abuse or a critical technical fault, with notification to AlFursan at the moment it acts. This is an availability control and it is covered in C7.
Confirmed. Merit will not activate, amend, extend, or stop a campaign without written approval from the AlFursan Store team.
The single exception is the immediate suspension described in C6, where waiting for approval would mean letting active fraud or a broken campaign continue running. In that case Merit notifies AlFursan at the moment it acts rather than afterwards, and a suspended campaign is only restarted with AlFursan's written approval.
| Action | AlFursan | Merit | Approval needed |
|---|---|---|---|
| Set the discount depth and the campaign budget | Decides | Executes | None from Merit |
| Choose eligible categories and campaign frequency | Decides | Executes | None from Merit |
| Activate, amend, or extend a campaign | Approves in writing | Executes | AlFursan, always |
| Stop a campaign under normal conditions | Approves in writing | Executes | AlFursan, always |
| Include gift cards in a campaign | Requests in writing | Enables | AlFursan request, since the default is excluded |
| Suspend a live code on active fraud or a critical fault | Notified at the moment it happens | Acts immediately | None, this is the one exception |
| Restart a suspended campaign | Approves in writing | Executes | AlFursan, always |
What is still moving on this tab
Three items are with Merit commercial for written confirmation by 3 August: the revenue share basis in C2, the settlement netting and payment terms in C3, and the billing cycle in C5. Everything else on this tab is BRD sections 4.1 and 4.3 restated and is not expected to change.
Back to AlFursan
Three of the open items block the Phase 1 specification and have been open since the BRD was issued on 20 July. Each carries a Merit recommendation, so the fastest path is to accept or reject the recommendation. The closed items are recorded below them rather than removed, so the trail stays readable.
| Was open | Resolution | Date closed |
|---|---|---|
| Point 2. Stored tier against a live API lookup | Live lookup. Merit resolves the member tier by calling the AlFursan Accenture API at the moment a code is validated. No tier value, no member reference for tier purposes, and no personal data is stored on the Merit side. There is no cache and no data sync in either direction. This replaces the earlier proposal to sync and store member data | 3 August 2026 |
| Point 1. Merit security and compliance position on the tier store | Closed as no longer applicable. The approval existed to cover persisting a tier value against an anonymous member reference. Nothing is persisted, so there is nothing to approve. What remains is an integration commitment, not a data approval: latency and availability on the tier API, plus the agreed fallback to the campaign's base tier discount when the API does not answer | 3 August 2026 |
| Scope. Whether campaign level promo code stacking belongs in the AlFursan release or the promo engine roadmap | A basic per campaign stacking toggle is pulled into AlFursan Phase 2, off by default, with campaigns opting in. The full stacking groups and A/B testing framework stays deferred to the 2027 document PRD_Promo_Engine_V2_Stacking_AB.md and is not in AlFursan scope | 3 August 2026 |
| BRD point | Question | Merit recommendation | Blocks |
|---|---|---|---|
| 1 | Household and family accounts. Does a per member limit apply once to the household or once to each family member, and does a family member count as new when the household has already purchased | Apply per individual member. It matches how the limit is enforced technically and it is the fairer outcome for members | Phase 1 spec |
| 6 | Definition of a new customer. New to the AlFursan Store, which Merit can enforce today, or new to the AlFursan programme, which needs AlFursan to supply the membership join date | Start with new to the store. It needs no data exchange and it can be enforced from day one | Phase 1 spec |
| 7 | Does the first purchase discount apply strictly to new customers, or to any member on their first use of that particular code | Strictly to new customers where the campaign is an acquisition campaign, since otherwise the acquisition budget discounts existing buyers | Phase 1 spec |
| 8 | Acknowledgement that miles are earned on the amount actually paid after the discount, with miles foregone reported separately | Acknowledgement only. This was decided in the workshop of 20 July | Phase 1 build |
| 9 | Partial return treatment, rule A or rule B on the calculations tab | Rule A, discount recalculated on the retained items | Phase 2 |
| Item | Owner | When |
|---|---|---|
| Merit security and compliance | Closed | |
| Latency and availability commitment on the AlFursan tier API, plus written confirmation of the fallback behaviour | AlFursan and Accenture | Before the Phase 2 build starts |
| Answers to the seven commercial points | Thamer Bamieh, Merit | 3 August 2026 |
| Phase 1 specification and sprint plan, once the three blocking points are answered | Brian Arfi Faridhi, Merit | Phase 1 approved for the next sprint on 3 August 2026 |
Export your review
Use the Export review button in the bar below to produce a text summary of every mark and note you made on this page. It is plain text and can be pasted straight into a reply.