HOCO B2B
DesignScreen specificationsBack-office

Promotions and loyalty

Page specs BO-49 to BO-54: promotions list, promotion editor with targeting, stacking and preview, banners and daily offers, and the V2 packs, loyalty and rewards pages.

Promotions stimulate orders with targeted offers (cahier §4.6). In V1 they are simple:

  • daily offers, scheduled promotions and temporary discounts;
  • on products, categories or brands;
  • targeted by wilaya, segment and volume;
  • with configurable stacking (PRM-01 to PRM-05).

They apply on top of the reseller's customer-type price (Super-gros, Demi-gros or Détail, PRC-02).

Promotions and banners open to everyone are also visible to guests in the reseller app and web, without any price (AUTH-10). Packs and loyalty are V2.

IDScreenSectionTemplateReleaseDesignBuild
BO-49Promotions listPromotionstemplateV1Day 19DSH-09
BO-50Promotion editorPromotionsbespokeV1Day 19DSH-09
BO-51Banners & daily offersPromotionstemplateV1Day 19DSH-09
BO-52PacksPromotionstemplateV2DES-30DSH-21
BO-53Loyalty settings & levelsPromotionstemplateV2DES-30DSH-21
BO-54Rewards & redemptionsPromotionstemplateV2DES-30DSH-21

BO-49 — Promotions list

FieldValue
TemplateList (with a timeline view)
ReleaseV1
Design dayDay 19 — DES-19
Build taskDSH-09
Route/promotions (?view=, ?display=list or timeline)
RequirementsPRM-01 · PRM-03
Permissions requiredpromotions.view · promotions.create (« Nouvelle promotion », « Dupliquer ») · promotions.validate (pause, resume, archive) · promotions.export

Purpose. See every promotion by status and over time, spot overlaps, and pause or archive them.

Who uses it. Commercial admin. Direction, stock and finance read it.

Entry points. Promotions › Promotions, and the « Promo active » badges of BO-27.

Layout.

  • Tabs: « Actives », « Programmées », « Brouillons », « En pause », « Terminées », « Archivées » (PromotionStatus).
ColumnSource fieldSortableDefault visible
Nomname + « Offre du jour » badgeYesYes
Typetype (PromotionType)YesYes
Valeur« −15 % », « −50,00 DA », « Prix promo », « Livraison offerte »NoYes
PortéeSummary (« Marque ACEFAST », « 3 produits »)NoYes
CiblageSummary (« Tous · visiteurs inclus », « Oran, Alger · Demi-gros »)NoYes
Début / FinstartsAt, endsAtYesYes
StatutstatusYesYes
PrioritépriorityYesYes
CumulablestackableYesNo
UtilisationUnits sold under the promotion / cap, orders countYesYes
Remise accordéeΣ discount HT on counted ordersYesNo
  • Filters: q, type, brand, category, wilaya, segment, customerType, from / to (active during), dailyOffer=true, guestVisible=true.
  • Timeline view: one bar per promotion on a calendar, grouped by scope (brand or category). Overlapping bars with the same scope and audience show a warning icon.
  • Row actions: « Modifier », « Dupliquer », « Mettre en pause » / « Reprendre », « Archiver ».

Data. admin.promotions.crud (GET list), admin.promotions.setStatus.

Actions.

  • « Mettre en pause »: « Mettre en pause ACEFAST −15 % ? Elle ne s'appliquera plus aux paniers ; les commandes déjà passées gardent la remise. »
  • « Archiver »: confirmation.
  • Both are audited STATUS_CHANGE and not optimistic.
  • « Dupliquer » opens BO-50 as a draft copy.

Rules.

  • ENDED is set automatically at the end date or when the cap is reached. A promotion cannot be resumed past its end date.
  • « Utilisation » counts only counted (confirmed) orders, with the same basis as BO-04.

Real-time. None. The list refreshes on focus.

States. First use: « Créez votre première promotion ».

Acceptance criteria.

  • The timeline shows an overlap warning for two active promotions with the same brand scope and audience.
  • Pausing removes the promotion from reseller carts at their next re-validation.
  • A promotion whose cap is reached appears under « Terminées ».

BO-50 — Promotion editor

FieldValue
TemplateBespoke (Form skeleton with a live preview)
ReleaseV1
Design dayDay 19 — DES-19
Build taskDSH-09
Route/promotions/new · /promotions/[promotionId]
RequirementsPRM-01 · PRM-02 · PRM-03 · PRM-04 · PRC-02 · AUTH-10
Permissions requiredpromotions.create (new) · promotions.update (edit) · promotions.validate (schedule, activate, pause, archive) · promotions.view (preview)

Purpose. Build one promotion end to end (cahier §4.6):

  • its mechanics;
  • what it applies to (scope);
  • who gets it (targeting by wilaya, segment, customer type and volume);
  • when, and how much (stock cap);
  • how it combines with others (stacking and priority);
  • a preview on a real reseller and a sample cart before it goes live.

Who uses it. Commercial admin.

Entry points. « Nouvelle promotion » and « Modifier » / « Dupliquer » on BO-49.

Layout

The page is a two-column form. The left holds six sections. The right holds a sticky panel with three blocks:

  • Résumé: a sentence generated from the form, « −15 % sur la marque ACEFAST pour les revendeurs Demi-gros et Détail d'Oran et Alger, du 10/11 au 20/11, dans la limite de 2 000 pièces ».
  • Visibilité: guests yes or no.
  • Aperçu: the simulation (below).

The status actions sit in the save bar.

1 · Général

FieldTypeValidationDefaultHelp text
Nom interneTextRequired, 3–80 characters—Not shown to resellers
Libellé revendeurTextRequired, 60 characters maxGenerated from the mechanics« Affiché dans les applications : ex. −15 % sur ACEFAST »
DescriptionTextarea500 characters max—Conditions shown on the promotion page
VisuelImage (BANNER_IMAGE, public, 5 MB max)Optional—Used in the promotions list of the apps
Offre du jourToggleWhen on, the duration must be 48 h or lessOffShows the promotion in the daily-offer carousel with a countdown (PRM-05)
Vente flashToggleWhen on, the duration must be between 2 h and 48 h (FLASH_SALE_DURATION); exclusive with Offre du jourOffLists the promotion on the Ventes flash tab with a countdown and sends flash_sale.started at activation (PRM-07, change request 03, DSH-14). Quick durations: 2 h, 6 h, 24 h, 48 h

2 · Mécanique

FieldTypeValidationNotes
TypeRadio cards (PromotionType)Required—
Remise en % (PERCENT_OFF)Percentage1–90 % (sent in basis points)Applies to the reseller's customer-type price
Remise en montant (AMOUNT_OFF)Money (DA HT per unit)Above 0; warning when it is 50 % or more of the lowest price in scopeNever brings a price below 0
Prix promotionnel (FIXED_PRICE)Three money inputs: Super-gros, Demi-gros, Détail (HT)Each must be below the variant's regular price of that type; scope limited to products or variantsOne promotional price per customer type. Assumption — confirm with HOCO.
Livraison offerte (FREE_DELIVERY)—No valueThe delivery fee becomes 0 when the conditions are met

3 · Portée (PromotionScope)

  • S'applique à: « Tout le catalogue », « Marques », « Catégories » (sub-categories included), « Produits », « Variantes ». The pickers allow multiple values.
  • Exclusions: products or variants.
  • A live count of the variants in scope (« 186 variantes concernées ») with « Voir la liste ».

4 · Ciblage (PromotionAudience, PRM-02)

  • Destinataires: « Tous les revendeurs (et visiteurs) » or « Restreint ».
  • Restreint combines four dimensions:
    • Wilayas (multi-select);
    • Segments;
    • Types de client (CustomerType; Assumption — customer type as a targeting dimension);
    • Revendeurs (search, at most 200). Values within one dimension combine with OR; dimensions combine with AND. Niveau de fidélité is shown disabled and labelled « V2 ».
  • Condition de volume (optional):
    • « Montant minimum du panier » (HT; all items, or only the items in scope);
    • « Quantité minimum » (of the items in scope).
  • Guest visibility (read-only indicator):
    • « Visible par les visiteurs sans compte » is Yes only when Destinataires = « Tous » and there is no condition beyond volume.
    • Guests then see the label, the percentage or « Prix promotionnel », and the eligible products, never a price or an amount.
    • A restricted promotion is invisible to guests and to resellers outside its target.

5 · Calendrier et plafond

FieldTypeValidationDefault
DébutDate and time (Africa/Algiers)Required; for a new promotion, now or laterNow + 1 h
FinDate and timeRequired; after Début—
Stock promotionnelInteger (units, all resellers)Optional, 1 or more—
Limite par revendeurInteger (units per reseller over the period)Optional, 1 or more—

6 · Cumul et priorité (PRM-03)

FieldTypeValidationDefaultHelp text
PrioritéInteger1–100 (1 = la plus prioritaire)50« Ordre d'application lorsque plusieurs promotions concernent un même article »
CumulableToggle—Off« Si désactivé, aucune autre promotion ne s'applique à un article qui en bénéficie »

Below the fields, a « Promotions en concurrence » list shows the active and scheduled promotions overlapping this one on scope, audience and dates, with their priority and stackability.

Preview

  • Inputs:
    • Revendeur: a search, or a quick profile « Type de client + wilaya » without a real reseller, or « Visiteur sans compte ».
    • Panier d'exemple: variants and quantities, with « Ajouter 3 articles de la portée ».
  • « Simuler » calls admin.promotions.preview with the unsaved draft and the sample.
  • Result per line:
    • the regular price for the reseller's customer type;
    • the promotions applied, in order, with amounts;
    • the final unit price and line total HT.
  • Result for the cart: subtotal, discount total, delivery fee, VAT, total TTC (shared Totals).
  • Promotions not applied, with their reason: NOT_TARGETED, OUT_OF_DATES, CAP_REACHED, VOLUME_NOT_MET, NOT_STACKABLE, LOWER_PRIORITY.
  • « Visiteur sans compte » shows what the apps display: the label and eligible products, with every price replaced by « Créez un compte pour voir les prix ».

Actions

ActionEndpointConfirmation (FR)OptimisticAudit
« Enregistrer le brouillon »admin.promotions.crud (POST or PATCH)—NoCREATE / UPDATE
« Programmer » (start in the future)admin.promotions.setStatus (SCHEDULED)« Programmer cette promotion du 10/11 08:00 au 20/11 23:59 ? »NoSTATUS_CHANGE
« Activer maintenant »admin.promotions.setStatus (ACTIVE)« Activer maintenant ? Elle s'appliquera immédiatement aux paniers des revendeurs ciblés. »NoSTATUS_CHANGE
« Mettre en pause » / « Reprendre »admin.promotions.setStatusAs in BO-49NoSTATUS_CHANGE
« Archiver »admin.promotions.setStatus (ARCHIVED)« Archiver la promotion ? »NoSTATUS_CHANGE
« Simuler »admin.promotions.preview———

Activation sends no notification by itself. Announcing a promotion is done with an announcement (BO-57) or a banner (BO-51). The promotional notifications respect the reseller's opt-out (NOT-06).

Rules

  • Application (PRM-04):
    • A promotion applies only within its dates, its cap and its target.
    • The cart engine applies it on the price of the reseller's customer type, and re-validates at checkout.
    • An order keeps the discounts it was submitted with, even if the promotion ends before the order is confirmed (BO-39 shows a warning).
  • Stacking follows the setting promotions.stackingMode (BO-64):
    • BEST_ONLY: on each line, only the eligible promotion with the largest discount applies.
    • PRIORITY: eligible promotions apply in priority order on the already-discounted price. A non-stackable one stops further line promotions.
    • In both modes, FREE_DELIVERY combines with line promotions.
    • A guard caps the combined discount on a line at the setting promotions.maxLineDiscountPercent (default 50 %). Assumption — to confirm.
  • Editing while running:
    • In DRAFT and SCHEDULED, everything is editable.
    • In ACTIVE and PAUSED, only the label, description, visual, end date (not in the past) and cap (not below the units already sold) can change. Mechanics, scope and audience are locked: « Dupliquer » to change them.
  • Guests: a guest-visible promotion is returned by promotions.list and promotions.get to unauthenticated callers, without prices (§1b.6).
  • Stock: a promotion never shows stock quantities to resellers; eligible products show En stock or En rupture only (STK-07).

Real-time. None.

States.

  • Draft banner « Brouillon — non visible ».
  • Locked fields with a lock icon while active.
  • Empty scope: « Aucune variante dans la portée » blocks activation.
  • Preview error: « Simulation indisponible ».

Acceptance criteria

  • A −15 % promotion on ACEFAST for Demi-gros resellers of wilaya 31 applies only to those resellers' carts, during its dates and until its cap (cahier §12 « La remise s'applique uniquement aux produits, dates et cibles autorisés »).
  • The preview for a Demi-gros reseller shows the Demi-gros price, the 15 % discount and the final price equal to what the reseller's cart then shows.
  • A promotion for « Tous » appears for a guest in the reseller app with its label and eligible products and no price. A promotion restricted to a segment does not appear for guests.
  • With PRIORITY mode, a non-stackable priority-1 promotion prevents a stackable priority-10 promotion on the same line, and the preview reports NOT_STACKABLE.
  • Mechanics, scope and audience cannot be changed on an active promotion.

BO-51 — Banners & daily offers

FieldValue
TemplateList (with drawer and phone/web preview)
ReleaseV1
Design dayDay 19 — DES-19
Build taskDSH-09
Route/promotions/banners (?tab=banners or daily)
RequirementsPRM-05 · PRM-02 · AUTH-10
Permissions requiredpromotions.view · promotions.create · promotions.update · promotions.delete

Purpose. Manage the home banners and the daily-offer carousel with countdown of the reseller app and web (reference screens 1 and 7). Banners open to everyone are also shown to guests.

Who uses it. Commercial admin.

Entry points. Promotions › Bannières et offres du jour.

Layout.

  • Tab « Bannières »: a table (thumbnail, Titre, Emplacement, Lien, Ciblage, Visible visiteurs, Début / Fin, Ordre (drag), Actif), and a drawer:
    • Titre: internal, required.
    • Image mobile: required, 1080 × 480 px recommended.
    • Image web: optional, 1600 × 400 px recommended (BANNER_IMAGE, public). Assumption — the sizes are to fix with Akram's design.
    • Emplacement: « Accueil — carrousel ».
    • Lien: product, category, brand, promotion or none.
    • Ciblage: as in BO-50 (« Tous » or restricted). The guest indicator is derived the same way.
    • Début, Fin, Actif.
  • Tab « Offres du jour »: the ordered list of promotions flagged Offre du jour (from BO-50) and active or scheduled in the next 7 days. Each shows its countdown end and carousel order (drag). « Créer une offre du jour » opens BO-50 with the flag on.
  • Preview: a phone frame and a web frame of the reseller home, for a chosen profile (customer type, wilaya, or guest).

Data. admin.banners.crud, admin.promotions.crud (GET with dailyOffer=true), files.createUpload.

Actions. Create, edit and reorder (reorder is optimistic). Delete asks « Supprimer la bannière ? ». All are audited.

Rules.

  • The apps show at most 5 banners, in order, filtered by target and dates (banners.list, guests allowed).
  • A banner linked to a promotion is hidden automatically when that promotion ends or is paused.
  • Guest-visible banners never carry prices in the image. Assumption — this is an editorial rule shown as a hint, and the server cannot check it.

Real-time. None.

States. No banner: the apps show the default HOCO / ACEFAST / BOROFONE banner.

Acceptance criteria.

  • A banner targeted to « Tous » shows on the guest home. One targeted to a segment shows only to its members.
  • Reordering changes the carousel order on the next home load.
  • A daily offer's countdown in the apps ends at the promotion's end time.

BO-52 — Packs

FieldValue
TemplateList (with a pack editor)
ReleaseV2 — designed in DES-30
Design dayDES-30 — V2 designs (during the build phase; no V1 design day)
Build taskDSH-21
Route/promotions/packs
RequirementsPRM-06
Permissions requiredpromotions.view · promotions.create · promotions.update · promotions.delete

V2 — designed in DES-30

Packs ship with V2 (cahier §14.2). The detailed spec will be written with DES-30.

Purpose. Profitable packs: bundles of several references sold at a pack price and added to the cart as a unit (cahier §4.6, §5.5).

Layout (outline).

  • A list: pack, items, pack price per customer type, margin (needs pricing.view), stock (the minimum over items), status.
  • An editor: items and quantities, the three pack prices, targeting and dates as in BO-50, and a visual.

Data. admin.packs.crud.

Acceptance criteria (draft).

  • A pack's availability is En rupture as soon as one item is out of stock.
  • A pack added to a cart reserves each item's quantity at confirmation.

BO-53 — Loyalty settings & levels

FieldValue
TemplateSettings
ReleaseV2 — designed in DES-30
Design dayDES-30 — V2 designs (during the build phase; no V1 design day)
Build taskDSH-21
Route/loyalty/settings
RequirementsLOY-01 · LOY-02 · LOY-03
Permissions requiredloyalty.administer · loyalty.update (manual adjustments)

V2 — designed in DES-30

The loyalty programme is V2. Its thresholds, periods and earning rules must be validated by HOCO (cahier §4.6 « seuils validés par le client »).

Purpose. Configure points earning (per order, credited after delivery or payment), bonuses, expiry, reversal on cancellation or refund, and the levels Bronze, Silver, Gold and VIP with their period and thresholds (cahier §4.4, §4.6).

Layout (outline).

  • Groups: Gain de points, Expiration, Régularisations, Niveaux (a table of LoyaltyLevel with thresholds and period).
  • A per-reseller manual adjustment drawer (reason required).

Data. admin.loyalty.settings, admin.loyalty.adjust.

Acceptance criteria (draft).

  • Cancelling an order reverses its points automatically (cahier §4.6 « Les points annulés ou remboursés doivent être régularisés »).
  • Each manual adjustment appears in the reseller's points history with its reason.

BO-54 — Rewards & redemptions

FieldValue
TemplateList
ReleaseV2 — designed in DES-30
Design dayDES-30 — V2 designs (during the build phase; no V1 design day)
Build taskDSH-21
Route/loyalty/rewards (?tab=rewards or redemptions)
RequirementsLOY-04 · LOY-05
Permissions requiredloyalty.view · loyalty.create · loyalty.update (fulfil redemptions) · loyalty.delete

V2 — designed in DES-30

Rewards ship with the V2 loyalty programme.

Purpose.

  • The rewards catalogue (RewardType: voucher, free delivery, discount, gift, early access) with points cost, stock and validity.
  • The redemptions to fulfil (cahier §4.6, §5.5).

Layout (outline).

  • Récompenses: list and drawer (type, points, stock, dates, level required).
  • Échanges: queue of redemptions (reseller, reward, date, status) with « Marquer comme remis ».

Data. admin.rewards.crud, admin.redemptions.list.

Acceptance criteria (draft).

  • A reward out of stock cannot be redeemed (cahier §5.5).
  • Every redemption appears in the reseller's points history.

On this page