Promotions
Screen specifications RA-24 and RA-25 of the reseller app — daily offers with countdown, the list of promotions targeting the reseller, and a promotion's conditions and eligible products.
Cahier §4.6 and §5.5: daily offers, scheduled promotions and temporary discounts on products, categories or brands, targeted by wilaya, segment, level, brand or volume; « Une promotion doit respecter ses dates, son stock et sa cible ». V1 has simple promotions only (PRM-01); packs and loyalty are V2 (RA-37 to RA-39). Designed on day 10, built in MRA-06. Promotions apply automatically in the cart — there is no code to type.
| ID | Screen | UI title | Section | Release | Design | Build |
|---|---|---|---|---|---|---|
RA-24 | Promotions & daily offers | Promotions | Promotions | V1 | Day 10 | MRA-06 |
RA-25 | Promotion detail | Détail de l'offre | Promotions | V1 | Day 10 | MRA-06 |
Guests. Guests see promotions and banners — label, percentage badge, dates, conditions and eligible products — but no price and no amount (PriceLock); « −30 % » badges stay. promotions.list, promotions.get and banners.list accept calls without a session (auth: optional) and then return untargeted, public promotions only.

RA-24 — Promotions & daily offers
| Field | Value |
|---|---|
| Screen | Promotions & daily offers · Promotions |
| French title | Promotions |
| Release | V1 |
| Design day | Day 10 — DES-10 |
| Build task | MRA-06 |
| Requirements | PRM-01 · PRM-05 · PRM-07 |
| Reference screen | reseller-06-promotions-loyalty |
Purpose — Show today's offers and every promotion currently available to the reseller, so they can act before it ends (PRM-01, PRM-05).
Entry points & exits — Promotions quick tile and the daily offer on RA-09; notifications daily_offer.published and promotion.started; /promotions. Exits to RA-25, RA-14 (product of a daily offer), RA-12 on the Promotions tab (« Voir tous les produits en promotion »), WhatsApp.
Layout
AppBar« Promotions » with back and a search icon (→ RA-10).- « Offres du jour » with « Voir tout »:
Carouselof daily offers as on the reference — label « OFFRE FLASH » or « OFFRE DU JOUR », title (« Jusqu'à −30 % »), subtitle (« sur une sélection de produits HOCO »), image, discount badge,Countdown« Se termine dans 12 h 45 min 30 s », dots. - Filter chips: « Toutes », « Se termine bientôt » (under 48 h), « HOCO », « ACEFAST », « BOROFONE ».
- « Toutes les promotions »: list of promotion cards — image or brand logo, title, type label (Remise en %, Remise en montant, Prix promotionnel, Livraison offerte), scope line (« Sur les chargeurs HOCO », « Sur toute la marque ACEFAST »), validity « Jusqu'au 30 nov. », and « Quantité limitée » when a stock cap applies (never the remaining number).
- Text link « Voir tous les produits en promotion » → RA-12, tab Promotions.
WhatsAppButton(floating). Packs and loyalty sections of the reference come in V2.
Data
| Shown | Source |
|---|---|
| Daily offers and promotions | promotions.list → items[].id, title, subtitle, type (PromotionType), badgeLabel, imageUrl, scopeLabel, brandId, startsAt, endsAt, isDailyOffer, hasStockCap |
| Carousel extra slides | banners.list ?placement=PROMOTIONS → items[].imageUrl, title, route |
| Server clock | appConfig.get → serverTime (countdowns) |
Actions — Card or slide → RA-25 (a daily offer on a single product may open RA-14 directly). Chips filter locally. Pull-to-refresh. A countdown reaching zero turns its card into « Offre terminée » and the card disappears at the next refresh.
Rules
- Only active promotions targeting the reseller are returned — dates, stock cap and target are applied server-side (PRM-02, PRM-04); scheduled promotions are not shown in V1.
- Discounts are computed on the reseller's customer-type price; stacking follows the configured rules (PRM-03).
- A promotion's remaining stock cap is never shown as a number (consistent with STK-07): « Quantité limitée ».
States — Loading: carousel and card skeletons. Empty: « Aucune promotion en cours — revenez demain pour les offres du jour. » with « Voir le catalogue ». Error: ErrorState. Offline: cached list with the offline banner; countdowns keep running on cached endsAt. Guest: same screen, amounts locked.
Copy — « Promotions » · « Offres du jour » · « OFFRE FLASH » · « Se termine dans {remaining} » · « Toutes » · « Se termine bientôt » · « Toutes les promotions » · « Jusqu'au {date} » · « Quantité limitée » · « Offre terminée » · « Voir tous les produits en promotion » · « Aucune promotion en cours — revenez demain pour les offres du jour. »
Analytics — promotions_viewed with count, userKind; promotion_clicked with promotionId, position, isDailyOffer.
Tabs and flash sales (change request 03) — PRM-07, designed in DES-23, built in MRA-11.
- Under the app bar,
TabBarwith « Promotions » and « Ventes flash ». V2 adds « Offres exclusives » (PRM-08). A tab without content is hidden. The screen opens on « Ventes flash » when a flash sale is active, else on « Promotions »; the routes are/promotions?tab=promotionsand/promotions?tab=flash. - Promotions holds today's layout (daily offers and normal promotions that last several days or until the stock runs out).
- Ventes flash lists the
isFlashSaleoffers sorted by end time. Each card is aFlashSaleCard(DES-23): image, label « VENTE FLASH », discount badge, title, and a countdown that is prominent under 24 h (« Plus que 05:12:45 », ticking every second, fromserverTime) and a date line from 24 h (« Se termine dans 2 jours »). The primary button « Commander maintenant » opens RA-25 or the single product on RA-14. At zero the card turns « Offre terminée » and greys out. - The push
flash_sale.startedopens RA-25 of that sale; the chip « Se termine bientôt » stays on the Promotions tab.
Acceptance criteria
- A promotion targeted at another wilaya or segment is not listed (cahier §12 Promotion scenario).
- A countdown reaches zero at the promotion's
endsAt(server time), not the phone's clock. - No remaining-quantity number appears.
RA-25 — Promotion detail
| Field | Value |
|---|---|
| Screen | Promotion detail · Promotions |
| French title | Détail de l'offre |
| Release | V1 |
| Design day | Day 10 — DES-10 |
| Build task | MRA-06 |
| Requirements | PRM-01 · PRM-04 |
| Reference screen | None — follow the design system |
Purpose — Explain a promotion — what, on which products, until when, under which conditions — and let the reseller add eligible products to the cart (PRM-01, PRM-04).
Entry points & exits — Cards and slides of RA-24, the daily offer of RA-09, the promotion link on RA-14, notifications daily_offer.published and promotion.started, /promotions/{promotionId}. Exits to RA-14, RA-17 (snackbar), RA-41 (guest lock).
Layout
- Hero image with back and share; badge « −30 % ».
- Title, scope line, validity « Du 10 au 30 nov. 2026 » or a
Countdownunder 24 h. - « Conditions » list, built from the promotion fields:
- « Remise de 30 % sur une sélection de produits HOCO » (type and value);
- « Valable du 10 nov. au 30 nov. 2026 »;
- « Dans la limite des stocks alloués à l'offre » (when a stock cap exists);
- « Minimum 5 pièces par article » (when a minimum quantity applies);
- « Non cumulable avec d'autres offres » (stacking rule);
- « Appliquée automatiquement dans votre panier ».
- « Produits concernés »: grid of
ProductCardwith the promotional price and the struck-through base price (or the lock), cart icons, infinite scroll. - For Livraison offerte: no grid — « Livraison offerte sur toute commande à partir de 20 000,00 DA » and « Voir le catalogue ».
Data
| Shown | Source |
|---|---|
| Promotion | promotions.get → title, type, value, badgeLabel, scopeLabel, imageUrl, startsAt, endsAt, hasStockCap, minQty, stackable, minOrderAmount (free delivery) |
| Eligible products | catalog.products.list ?promotionId=&cursor= → items[] (ProductCard with promotion.price) |
Actions — Product card → RA-14; quick add as on the catalog; share → « Offre HOCO : −30 % sur une sélection de produits HOCO jusqu'au 30 nov. » with the link /promotions/{promotionId} (no price).
Rules — The promotion applies to the eligible products only, within its dates, stock cap and target (PRM-04); the cart shows it on each line (RA-17) and its amount in the summary. An ended, paused or untargeted promotion is not served.
States — 404 NOT_FOUND (ended, paused or not targeted): « Cette offre est terminée » with « Voir les promotions en cours » → RA-24. No eligible product left: « Tous les produits de cette offre sont en rupture. » Offline: cached detail. Guest: amounts locked; conditions visible.
Copy — « Conditions » · « Remise de {value} sur {scope} » · « Valable du {start} au {end} » · « Dans la limite des stocks alloués à l'offre » · « Minimum {minQty} pièces par article » · « Non cumulable avec d'autres offres » · « Appliquée automatiquement dans votre panier » · « Produits concernés » · « Cette offre est terminée ».
Analytics — promotion_viewed with promotionId, type, userKind; add_to_cart with source: "promotion", promotionId.
Acceptance criteria
- A product added from this screen shows the promotional price in the cart, and the cart total applies the promotion correctly (cahier §5.5).
- After
endsAt, the deep link shows « Cette offre est terminée ». - Conditions shown match those entered in the promotion editor (BO-50).
Orders
Screen specifications RA-21 to RA-23 of the reseller app — orders with counters and live progress, order detail with tracking, documents, cancel, reorder, returns and after-sales entry points, and the confirmation of assisted orders.
Finance
Screen specifications RA-29 to RA-31 of the reseller app — balance and credit, invoices and credit notes with PDFs, payments and the declaration of a transfer, CCP or BaridiMob payment with proof.