Merit Incentives · AlFursan Store · 29 July 2026 · revised 3 August 2026

Promo Codes: technical response and plan

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.

Responds to

Abdulelah Alhamdan

Clarification list of 26 July 2026 on the Promo Code BRD v0.1.

Source document

Promo Code BRD v0.1

Issued 20 July 2026 from the requirements workshop of the same date.

Scope of this page

All fourteen points

Seven technical points and seven commercial points, each on its own tab.


How to use this page

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.

Revision history

DateVersionWhat changed
29 July 2026v1.0First issue. Answers to the fourteen clarification points of 26 July 2026.
2 August 2026v1.1Worked calculation examples corrected and the commercial tab completed.
3 August 2026v2.0Tier 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 2026v2.1Point 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.

Answer status at a glance

PointSubjectWhere this leaves it
1Member data for tier discountsClosed 3 August 2026. No member data is stored at all, so there is nothing to protect and no approval to wait for
2Stored tier versus live lookupDecided 3 August 2026. Live lookup against the AlFursan Accenture API at validation time
3Capability confirmationAnswered in full, including one capability we will not overstate
4Calculation examplesAnswered with a working calculator. Partial return needs your rule
5Restoration after cancellationAnswered in full. No open items
6Reporting fields and sampleAnswered in full. Field list open to additions
7Designing Phase 1 and 2 togetherAgreed. Shown as what is built once and released twice
C1 to C7The seven commercial pointsAll 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

What member data Merit holds: none

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.

What is exchanged at validation time

FieldWhat it holdsExampleStored by Merit
AlFursan member IDThe 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 onaf_9c1e...No
tierThe tier value returned by the AlFursan Accenture API, held in process memory for the life of the single validation callGOLDNo
Nothing elseThere is no third field, because there is no record. No table, no cache entry, no refresh timestamp, and no batch filen/aNo
Not stored

Tier value

Used in memory to price one basket, then gone.

Not stored

Name, email, phone, balance

Never requested, never received, never held.

Not synced

Any AlFursan dataset

No batch, no feed, no mirror of the membership base.

Why the member ID is the anchor, and not email or phone

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.

Why no batch process is possible, independently of the privacy question

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.

Where tier data sits and what crosses the boundary The member tier stays inside AlFursan systems. At the moment a promo code is validated, Merit calls the AlFursan tier API operated by Accenture, receives the tier value, evaluates the discount in memory, and discards the value when the response is returned. Merit writes nothing to storage and there is no scheduled sync in either direction. ALFURSAN SYSTEMS MERIT Tier API, Accenture tier stays with AlFursan LIVE RESPONSE TIER VALUE ONLY Tier lookup call synchronous, timeout guarded In memory evaluation tier used to price the basket no store, no cache, no sync Promo validation at checkout DISCOUNT ONLY LIVE LOOKUP AT VALIDATION
Figure 1. The dashed path is the outbound lookup, raised only when a code is validated. The tier value comes back, prices that one basket, and is discarded with the request. Nothing is written on the Merit side and nothing is sent back to AlFursan.

Lifecycle of a tier value, which lasts one request

Step 1 · on code entry

The member applies a code 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.

Step 2 · only if tier matters

Merit calls the AlFursan tier API

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.

Step 3 · in memory

The tier prices the basket, and never leaves the request

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.

Step 4 · on failure

If the tier API does not 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.

Step 5 · retention

Nothing to retain, nothing to delete

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.


Controls

ControlPosition
Encryption in transitTLS on every call between Merit and the AlFursan tier API. This is the only place tier data exists in the Merit path
Encryption at restNot applicable. There is no tier data at rest on the Merit side to encrypt
Access controlService 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 logMerit 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
SegregationThe 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
DeletionNot 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

Storing the tier against a live API lookup: decided

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.

1

Member applies the code at checkout

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.

0 ms
2

Merit calls the AlFursan tier API

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.

+150 to 400 ms
3

Rules are evaluated and the discount returns

The tier value prices the basket in memory and is discarded with the response. Nothing is written on the Merit side.

~200 to 450 ms
!

If AlFursan systems are unavailable

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.

base tier applied
DimensionStored tier, withdrawnLive lookup, decided
Checkout latencyNegligible, a local readOne external round trip per validation attempt
AvailabilityUnaffected by AlFursan system availabilityCampaign is only as available as the tier API
Data held at MeritAnonymous reference plus tier valueNone held
FreshnessAs fresh as the refresh cadence, with a live lookup fallback when a record is staleAlways current. An upgrade applies to the very next basket, with no propagation delay
Load on AlFursan systemsOne scheduled batch per dayOne call per validation attempt, including failed attempts and retries
CostStorage cost is negligible at this volumeNo storage cost, higher integration and support cost
Operational dependencyRefresh job must be monitoredLive API must hold a checkout grade SLA, including during campaign peaks
Failure modeA member sees yesterday's tier for up to one refresh cycleA 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.

What this costs at campaign creation time, stated plainly

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

Capability confirmation

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.

Phase 1 in the first release Phase 2 in the second release Phase 3 in the third release Phase N proposed not phased in the BRD, Merit recommends where it belongs Your decision blocked on an AlFursan answer Limited partial by nature of the channel
CapabilityStatusNote
Percentage and fixed value discountsPhase 1Both, set per campaign
Discount on miles, cash, or both componentsPhase 1Applied to the basket value, then split across the payment components in the same proportion as the member's chosen split
Minimum basket valuePhase 2 proposedRides on campaign scoping. Its absence is why Merit proposes percentage codes only in Phase 1
Maximum discount per orderPhase 2 proposedRides 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 exclusionPhase 2Non eligible items in the same basket are charged at full price
Gift card exclusionPhase 1 proposed Phase 2 proposedA single store wide flag in Phase 1, then exclusion by category once scoping arrives
Prevention of promo code stackingPhase 1 proposed Phase 2Structural, 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 discountPhase 1 proposedThe product level discount already exists in the store today, so the collision is live from the first campaign
Campaign level redemption limit and budget limitPhase 1Both a redemption count cap and a discount value cap. The campaign stops automatically when either is reached
Usage limit per memberPhase 1Enforced server side against the AlFursan member identity. This is the strongest limit available and it cannot be bypassed from the browser
Usage limit per accountPhase 1Same mechanism as per member
Usage limit per householdYour decision Phase 2 proposedOpen 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 addressLimited Phase 2 proposedDeliverable as a velocity control, with a caveat below. An IP address is personal data, so it waits for the compliance position
Usage limit per deviceLimited Phase 2 proposedBest effort signal only on a web storefront, explained below, and a persistent device identifier needs a consent position first
Immediate suspension on misuse or fraudPhase 1 proposedOperational safety for the first public code. Nothing to build in Phase 2 or 3

Where Merit proposes each of these belongs

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.

Phase 1, four rows, none of which need data Merit does not already hold

SettingMerit proposesWhy it cannot wait
Code stackingOne 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 combineStructural. 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 discountNot combined by default, taking the deeper of the two, configurable per campaignSection 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 wideA single blanket exclusion covering every campaignOne flag, and without it the first public code discounts stored value. Exclusion by category follows in Phase 2 with scoping
Immediate suspensionAvailable to Merit and AlFursan from the admin console, effective within secondsOperational safety for the first public code. There is no later version of it to build

Phase 2, everything that needs scoping or data Merit does not hold today

SettingWhat it depends onSensitive data
Minimum basket valueCampaign scoping, which arrives in Phase 2None
Maximum discount per orderSame scoping workNone
Gift card exclusion by categoryProduct and category scoping, Phase 2None
Household and family limitAlFursan defining a household, then supplying the relationship between accountsYes. 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 thresholdsRetaining IP addresses against redemption attempts for a defined windowYes. An IP address is personal data. It needs a retention period and a lawful basis before it is stored, not after
Payment card limitsRetaining a card reference against redemption historyYes. Payment data carries its own handling requirements independent of the promo feature
Device fingerprint for anomaly reportingCollecting and retaining a browser derived identifierYes. 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, and why none of the rows above belong in it

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 controlWhy it only exists once codes are individual
Member bound validationA voucher issued to one member has to be refused for everyone else. A public code has nobody to bind to
Code entropy and guess protectionBulk 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 issueA 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 rateInfluencer 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 codeWithdrawing 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.


Device and IP limits: what a web storefront can honestly do

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.

The layered control plan

Layer 1 · primary defence · strong · phase 1

Member identity limits, enforced server side

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.

Layer 2 · ceiling · strong · phase 1

Campaign redemption cap and budget cap

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.

Layer 3 · velocity · moderate · phase 2

IP address velocity limits

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.

Layer 4 · signal · moderate · phase 2

Payment instrument limits

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.

Layer 5 · signal only · weak · phase 2

Device fingerprint

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.

Layer 6 · response · strong · phase 1

Anomaly reporting and one click suspension

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.

The same six layers, read as an attacker would

ControlWhat it costs an abuser to defeatFalse positives on genuine membersVerdict
Member and account limitCreating a second genuine AlFursan membershipNonePrimary defence
Campaign redemption and budget capCannot be defeated. It bounds the total regardless of methodNone until the cap is reachedBounds the loss
Payment card limitA second payment cardShared family cardsUseful on the cash component only
IP velocity thresholdA mobile hotspot or a VPNHigh if set tight, because carrier and office networks share addressesVelocity alerting, not a hard gate
Device fingerprintA private browsing windowModerate, since families share devicesReporting signal only
Anomaly review and suspensionNothing, it is a response rather than a barrierNoneCatches 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

Worked calculation examples

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.

Percent off the product value
Illustrative. Replace with AlFursan's rate
Illustrative
60%

Example A. Miles only order

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.

LineWithout codeWith code

Example B. Miles and Cash order

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.

LineWithout codeWith 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.


Cancellation and returns

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.

ScenarioRefunded to memberMiles reversedRedemptionMember allowance

Partial return, the two candidate rules

The member keeps part of the basket and returns the rest. The share returned is set here.

40%
Affects the two rule columns below only. The order tables higher up the page are unchanged by it.
LineRule A, discount recalculatedRule B, discount kept whole
Rule A

Discount recalculated on what the member keeps

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.

Rule B

Discount kept whole against the retained items

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

How usage, member limits, and campaign budget are restored

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.

Day 0

Code redeemed, redemption is provisional

The discount is given. The member's usage allowance is consumed. The campaign's remaining redemption count and remaining budget both go down.

Day 0 to 30 · if reversed

Cancellation or return inside the window

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.

Day 30

Redemption becomes confirmed

The order has settled and the miles have been credited. The result stands and is not reversed by anything that happens afterwards.

After day 30

A return outside the window

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 restoredOn reversal inside 30 daysOn reversal after 30 days
Member usage allowanceReturned in fullNot returned
Campaign redemption countReturned to the poolNot returned
Campaign budgetReturned to the poolNot returned
BillingNever billed, since only confirmed redemptions are billableAppears as a credit line on the next statement
Miles earned by the memberReversed with the orderPer 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

Reporting fields and a sample report

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.

FieldDefinitionRequested by
Redemptions, provisionalCodes applied to an order, including orders still inside the 30 day windowAlFursan
Redemptions, confirmedRedemptions on orders that have passed 30 days with no reversal. This is the billable numberMerit
Unique membersDistinct members who redeemedAlFursan
New versus existingSplit on the agreed definition of a new customer, BRD open point 6AlFursan
TierRedemptions and value by member tier. Phase 2 onwardAlFursan
Basket valueOrder value before discount, excluding VAT and deliveryAlFursan
Discount valueTotal discount given. This is the AlFursan funded amountAlFursan
Net valueBasket value after discountAlFursan
Miles redeemedMiles used to pay for the orderAlFursan
Cash collectedCash component collected on Miles and Cash ordersAlFursan
Miles earnedMiles credited to members on the amount actually paidMerit
Miles foregoneDifference between what members would have earned at full basket value and what they earned after discount. A member impact metric, never an accounting entryMerit
Cancellations and returnsCounts and value, split full and partialAlFursan
Reversal rateReversed redemptions as a share of provisional redemptions, per campaign and per codeAlFursan
Category performanceRedemptions and discount value by category. Phase 2 onwardAlFursan
Order level traceabilityEvery line traces to an individual order ID, downloadableAlFursan

Sample campaign report

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.

Campaign

SND26

10 percent store wide, 20 to 25 September 2026

Status

Closed, settling

Report generated 30 September, so late orders are still provisional

Budget

Illustrative

Cap of 5,000 redemptions and 250,000 SAR of discount

MetricProvisionalConfirmed
Redemptions3,4122,180
Unique members3,3012,144
New customers1,240790
Existing customers2,0611,354
Basket value before discount, SAR2,730,0001,744,000
Discount value, SAR273,000174,400
Net value, SAR2,457,0001,569,600
Miles redeemed41,800,00026,700,000
Cash collected, SAR612,000391,000
Miles earned by members2,457,0001,569,600
Miles foregone273,000174,400
Cancellations and returns168-
Reversal rate4.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

Phase 1 and Phase 2 designed together, released separately

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.

ComponentDesigned and built in Phase 1Switched on in Phase 2
Campaign configuration modelCarries fields for category scope and tier scope from the start, unused in Phase 1Category and tier scoping become editable in the admin console
Rules evaluationBuilt as a rule set over the basket rather than a single store wide checkItem level eligibility rules are added to the same evaluation
Discount applicationApplied per eligible line, with every line eligible in Phase 1Non eligible lines are excluded without changing how the discount is applied
Reporting schemaTier and category dimensions exist in the schema and report as emptyDimensions populate. Phase 1 campaign history stays queryable in the same report
ReconciliationComplete in Phase 1, per BRD section 4.1Unchanged. Phase 2 adds no new billing logic
Tier resolutionNot built. Phase 1 has no tier logic and makes no call to AlFursanA live call to the AlFursan Accenture tier API at validation time, per point 1. No tier store is built in either phase
Stacking ruleOne code per order, enforced in the rules evaluation from the first campaignA per campaign toggle exposes that same rule in the admin console, off by default

What is actually in each release

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 codesSource
Code entry at checkout, discount applied to the full basket in miles or cashBRD
Percentage discounts. Merit now recommends fixed amount codes wait for Phase 2, since the minimum basket that protects them moved thereBRD, amended
Campaign start and end dateBRD
Total redemption cap and campaign budget capBRD
Per member and per account usage limits, including a limit per rolling periodBRD
New customer only restriction, meaning members with no prior purchase on the storeBRD
Basic redemption report per code, split new against existingBRD
Automated reconciliation and the billing statementBRD
One code per order, no stacking, not configurable in this releaseAdded
Code against the existing product level discount, not combined by defaultAdded
Store wide gift card exclusionAdded
Immediate suspension of a live codeAdded
Phase 2, segmented promo codesSource
Product, category, and brand scoping, so a code applies only to eligible itemsBRD
Tier based discount, one code returning a different percentage per tierBRD
Reporting by tier, by category, and by customer stateBRD
Tier and customer state combined on one campaign, for example Gold members on their first purchaseBRD
Live tier resolution against the AlFursan Accenture API at validation time, with nothing stored on the Merit sideBRD, revised 3 August 2026
Basic promo code stacking toggle, set per campaign, off by default so a campaign has to opt inAdded 3 August 2026
Minimum basket value, and with it fixed amount discount codesAdded
Maximum discount per orderAdded
Gift card exclusion by category rather than store wideAdded
Household and family account limits, once AlFursan defines a householdAdded, needs your data
IP velocity thresholdsAdded, personal data
Payment card limits on the cash componentAdded, payment data
Device signal for anomaly reportingAdded, 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 codesSource
Bulk generation of unique codes, one per influencer or one per member in a segmentBRD
Codes bound to a specific member, unusable by anyone elseBRD
Validity counted from the date of issue, for example 30 days from the day the email is sentBRD
Attribution reporting per code, with new customers reported separately so influencer performance is judged on acquisitionBRD
Rapid manual issuance of a single bespoke code for a partner or guestBRD
Code entropy and guess protection, with attempt rate limiting at checkoutAdded
Revocation of one issued code without stopping the campaignAdded
Reversal rate per influencer code, so a code producing returns is visibleAdded

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

The commercial questions, answered in order

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.

C1. How promo code discounts affect the existing revenue share model

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.

C2. Is the revenue share calculated before or after the promo code discount

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 discountShare calculated before the discountShare calculated after the discount
Value the store sold1,000 SAR1,000 SAR
Collected from the member800 SAR800 SAR
Reimbursed by AlFursan200 SAR200 SAR
Base the revenue share is applied to1,000 SAR800 SAR
Effect on Merit against the same order at full priceNoneMerit earns less because AlFursan ran a campaign
Effect on the no ceiling position in C6Holds, since campaign depth costs Merit nothingBreaks, 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.

C3. Funding, invoicing, settlement, and reconciliation

ElementMerit's position
FundingNo upfront deposit and no prefunded campaign wallet. The discount accrues as a receivable against AlFursan as redemptions confirm
What is billableConfirmed 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
StatementAutomated, 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
SettlementNetted against the existing AlFursan Store settlement rather than invoiced as a separate stream, so there is one payment flow and not two
Payment termsThe same terms as the existing AlFursan Store commercial agreement. Merit commercial confirms the exact wording by 3 August

C4. How cancelled and returned orders appear, and whether credits are automatic

CaseWhat appears on the statementAutomatic
Reversal inside the 30 day windowNothing. It was never billed, because only confirmed redemptions are billable, so there is no charge to creditYes
Reversal after the redemption confirmed and was billedA credit line on the next statement, itemised to the original order IDYes, no claim and no manual request
Partial returnA credit for the returned portion, calculated under whichever partial return rule AlFursan selects on the calculations tabYes, 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.

C5. Billing frequency, and when a redemption becomes final and chargeable

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:

20 Sep

Campaign opens

Redemptions start accumulating as provisional.

25 Sep

Campaign closes

No further redemptions. Nothing is billable yet, because no order has passed its 30 day window.

30 Sep

September statement

Carries no confirmed redemptions from this campaign. The campaign appears with its provisional figures for visibility only.

20 to 25 Oct

Orders confirm in the order they were placed

Each order confirms 30 days after it was accepted, so the campaign settles across the same six day spread over which it ran.

31 Oct

October statement

Carries the confirmed redemptions and the credit lines for anything reversed. This is the invoice that matters.

25 Oct onward

Final cost known

Only at this point can the campaign be judged on confirmed numbers. Anything reported before this is provisional and will move.

C6. Does Merit apply limits on discount depth, budget, categories, or frequency

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.

C7. No campaign activated, amended, extended, or stopped without written approval

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.

Who controls what, across C6 and C7

ActionAlFursanMeritApproval needed
Set the discount depth and the campaign budgetDecidesExecutesNone from Merit
Choose eligible categories and campaign frequencyDecidesExecutesNone from Merit
Activate, amend, or extend a campaignApproves in writingExecutesAlFursan, always
Stop a campaign under normal conditionsApproves in writingExecutesAlFursan, always
Include gift cards in a campaignRequests in writingEnablesAlFursan request, since the default is excluded
Suspend a live code on active fraud or a critical faultNotified at the moment it happensActs immediatelyNone, this is the one exception
Restart a suspended campaignApproves in writingExecutesAlFursan, 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

Four decisions still open, and three now closed

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.

Closed at the Marketplace sprint backlog review, 3 August 2026

Was openResolutionDate closed
Point 2. Stored tier against a live API lookupLive 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 data3 August 2026
Point 1. Merit security and compliance position on the tier storeClosed 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 answer3 August 2026
Scope. Whether campaign level promo code stacking belongs in the AlFursan release or the promo engine roadmapA 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 scope3 August 2026

Still open, and needing an answer from AlFursan

BRD pointQuestionMerit recommendationBlocks
1Household 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 purchasedApply per individual member. It matches how the limit is enforced technically and it is the fairer outcome for membersPhase 1 spec
6Definition 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 dateStart with new to the store. It needs no data exchange and it can be enforced from day onePhase 1 spec
7Does the first purchase discount apply strictly to new customers, or to any member on their first use of that particular codeStrictly to new customers where the campaign is an acquisition campaign, since otherwise the acquisition budget discounts existing buyersPhase 1 spec
8Acknowledgement that miles are earned on the amount actually paid after the discount, with miles foregone reported separatelyAcknowledgement only. This was decided in the workshop of 20 JulyPhase 1 build
9Partial return treatment, rule A or rule B on the calculations tabRule A, discount recalculated on the retained itemsPhase 2

What Merit delivers next

ItemOwnerWhen
Written security and compliance position on the tier store. Closed 3 August 2026, no longer required because nothing is storedMerit security and complianceClosed
Latency and availability commitment on the AlFursan tier API, plus written confirmation of the fallback behaviourAlFursan and AccentureBefore the Phase 2 build starts
Answers to the seven commercial pointsThamer Bamieh, Merit3 August 2026
Phase 1 specification and sprint plan, once the three blocking points are answeredBrian Arfi Faridhi, MeritPhase 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.

0 of 7 points reviewed

Review summary