HOCO B2B
DesignScreen specificationsBack-office

Support and reports

Page specs BO-55 to BO-60: tickets and after-sales claims, ticket detail with SAV resolution, announcements, notification templates and rules, the reports library and the export centre.

Support handles reseller tickets, including after-sales claims (SAV, ticket type AFTER_SALES). Claims are resolved in V1 by replacement, return, credit note, repair or rejection (SUP-02, SUP-04). Communication covers announcements and the notification matrix. Reports and exports give the essential indicators of cahier §4 and §1.4 in PDF, Excel and CSV (cahier §9).

IDScreenSectionTemplateReleaseDesignBuild
BO-55Tickets listSupporttemplateV1Day 19DSH-10
BO-56Ticket detailSupporttemplateV1Day 19DSH-10
IDScreenSectionTemplateReleaseDesignBuild
BO-57AnnouncementsCommunicationtemplateV1Day 19DSH-10
BO-58Notification templates & rulesCommunicationtemplateV1Day 19DSH-10
IDScreenSectionTemplateReleaseDesignBuild
BO-59Reports libraryReportsbespokeV1Day 19DSH-11
BO-60Export centreReportstemplateV1Day 19DSH-11

BO-55 — Tickets list

FieldValue
TemplateList
ReleaseV1
Design dayDay 19 — DES-19
Build taskDSH-10
Route/support/tickets (?view=)
RequirementsSUP-02 · SUP-04 · SUP-01
Permissions requiredsupport.view · support.update (assign, status, priority in bulk)

Purpose. The support queue: reseller tickets and after-sales claims, to assign, prioritise and answer in time.

Who uses it. Commercial admin, finance (billing tickets), delivery manager (delivery tickets), super admin.

Entry points. Support › Tickets et SAV (badge = unassigned open tickets), BO-11 Tickets et SAV, and BO-69 « Réclamations SAV ».

Layout.

  • Tabs: « Non assignés », « Mes tickets », « SAV » (AFTER_SALES), « Ouverts » (OPEN, IN_PROGRESS), « En attente du revendeur » (WAITING_RESELLER), « Résolus », « Rejetés », « Fermés », « Tous ».
ColumnSource fieldSortableDefault visible
N°number (TKT-2026-000045)YesYes
SujetsubjectNoYes
Typetype (TicketType; SAV badge)YesYes
RevendeurStore name + wilayaYesYes
Commandeorder.numberYesYes
Problème (SAV)AfterSalesIssue of the claimed itemsNoYes on « SAV »
Statutstatus (TicketStatus; staff label « En attente du revendeur » for WAITING_RESELLER)YesYes
Priorité« Basse », « Normale », « Haute », « Urgente » (Assumption: no enum yet)YesYes
Assigné àassignee.displayNameYesYes
Dernier messageTime and author side (reseller / HOCO)YesYes
AttenteTime since the last reseller message without a reply (amber after 4 h, red after 24 h; Assumption: SLA to confirm)YesYes
RésolutionAfterSalesResolutionYesNo
Créé lecreatedAtYesNo
  • Filters: q, type, status, priority, assignee (incl. none), reseller, wilaya, from / to, issue.
  • Default sort: Attente descending.
  • Bulk actions (admin.tickets.update per ticket): « Assigner », « Changer la priorité », « Fermer » (resolved only).

Data. admin.tickets.list, admin.tickets.update, admin.users.list (assignee picker).

Actions. Bulk assignment is not optimistic. It is audited UPDATE per ticket and notifies the assignee (in-app).

Rules.

  • A ticket created by a reseller starts OPEN and unassigned. Its first reply moves it to IN_PROGRESS.
  • Tickets are never deleted.
  • After-sales claims carry the order and the claimed lines.

Real-time. The admin stream has no ticket event in V1. The list and badge poll every 60 s while visible (see contract notes).

States. « Aucun ticket non assigné » is a positive empty state.

Acceptance criteria.

  • A ticket opened in the reseller app appears in « Non assignés » within 60 s.
  • The « SAV » tab lists exactly the AFTER_SALES tickets.
  • Bulk assignment notifies each assignee once.

BO-56 — Ticket detail

FieldValue
TemplateDetail (conversation with a side panel)
ReleaseV1
Design dayDay 19 — DES-19
Build taskDSH-10 (SAV workflow: DSH-13)
Route/support/tickets/[ticketId]
RequirementsSUP-02 · SUP-04 · ORD-13 · FIN-08
Permissions requiredsupport.view · support.update (reply, internal note, assign, status, priority) · support.validate (resolve an after-sales claim) · finance.view (credit-note amounts)

Purpose. Answer a reseller, keep internal notes, and, for an after-sales claim, take it from diagnosis to resolution. The resolution is one of Remplacement (a free replacement order), Retour (creates a return), Avoir (credit note), Réparation, or Refusée with a reason (§1b.9).

Who uses it. Commercial admin (claims), finance (billing), delivery manager (delivery issues).

Entry points. BO-55, BO-69 « Réclamations SAV », BO-39 Retours et SAV, BO-11, and notifications.

Layout.

  • Header: TKT number, subject, TicketType and TicketStatus pills, priority, assignee, reseller (link to BO-11, with phone and WhatsApp), related order (link to BO-39).
  • Main, the conversation:
    • Public messages, aligned by author.
    • Internal notes, on a yellow background with « Note interne — invisible pour le revendeur ».
    • Attachments (TICKET_ATTACHMENT, 10 MB max, signed URLs).
    • Composer with the toggle « Réponse au revendeur » / « Note interne », attachments, and « Envoyer ».
  • Side panel:
    • Fields Statut, Priorité, Assigné à, Type (editable with support.update).
    • Reseller summary.
    • History.
  • After-sales claim panel (type AFTER_SALES), at the top of the main column:
    • Claimed items (TicketItem): product and variant, ordered quantity, claimed quantity, issue (AfterSalesIssue), photos.
    • Warranty status, computed from the delivery date and the product's warranty: « Sous garantie jusqu'au 03/05/2027 » or « Hors garantie depuis le 03/11/2026 ».
    • Order context: delivery date, invoice, previous claims on the same order.
    • The primary action « Résoudre la réclamation » (with support.validate).

After-sales resolution

« Résoudre la réclamation » opens a dialog. The chosen resolution is sent with admin.tickets.resolve.

ResolutionInputsEffectConfirmation (FR)
Remplacement (REPLACEMENT)Quantities to replace per claimed line (≤ claimed); delivery address (reseller's default); noteCreates a free replacement order (CMD-…, lines at 0 DA, channel BACK_OFFICE) linked to the ticket. Like every order, it waits in BO-41 for confirmation, then follows preparation and shipping (ORD-14).« Créer une commande de remplacement gratuite de 2 articles pour Boutique Nour ? Elle devra être confirmée comme toute commande. »
Retour (RETURN)Quantities to return per lineCreates a return RET-… (APPROVED) in BO-69. Its reception restocks automatically (defective items flagged not to restock) and issues the credit note.« Créer un retour de 2 articles ? Le revendeur sera informé des modalités de retour. »
Avoir (CREDIT_NOTE)Amount (default: Σ claimed quantities × unit price TTC paid; can be lowered, not raised); commentIssues a credit note without physical return (FIN-08), visible in BO-44 « Avoirs »« Émettre un avoir de 8 750,00 DA TTC pour Boutique Nour ? »
Réparation (REPAIR)Note (required): what is repaired, expected return dateRecords the repair under warranty; the ticket becomes RESOLVED« Enregistrer la réparation sous garantie ? »
Refusée (REJECTED)Reason (required, shown to the reseller; chips: « Hors garantie », « Dommage dû à une mauvaise utilisation », « Article non fourni par HOCO »)The ticket becomes REJECTED« Refuser la réclamation ? Le motif sera communiqué au revendeur. »

Effects shared by all resolutions:

  • The ticket records the resolution, its author and the created record (order, return or credit note), linked in the claim panel.
  • An automatic public message summarises the decision for the reseller: « Votre réclamation est résolue : remplacement par la commande CMD-…-201 ».
  • The reseller is notified by push and in-app, live while their app is open (ticket.replied, return.status_changed on events.stream).
  • The resolution is audited (VALIDATE, or REJECT for a refusal).

Data. admin.tickets.get, admin.tickets.reply, admin.tickets.update, admin.tickets.resolve, files.createUpload, files.downloadUrl, admin.orders.get (order context).

Actions.

ActionEndpointBehaviourAuditNotifies
« Envoyer » (reply)admin.tickets.reply (public)Status becomes WAITING_RESELLER unless another status is chosen in the composerCREATE (message)Reseller (push, in-app, live)
« Envoyer » (internal note)admin.tickets.reply (internal: true)Visible to staff onlyCREATEMentioned staff (in-app)
Change status, priority or assigneeadmin.tickets.updateOptimistic for priority; not for statusUPDATE / STATUS_CHANGEAssignee; reseller on RESOLVED / CLOSED
« Résoudre la réclamation »admin.tickets.resolveSee the resolution tableVALIDATE / REJECTReseller

Rules.

  • Internal notes are never returned by reseller operations (tickets.get returns public messages only).
  • One resolution per claim. A claim can be reopened to resolve again only by moving it back to IN_PROGRESS; the first resolution and its records are kept.
  • Claimed quantities are capped by the delivered quantities of the order, minus previous claims and returns on the same lines.
  • Replacement orders are never confirmed automatically. They appear in BO-41 with the badge « Remplacement SAV ».
  • Out of warranty: a claim may still be resolved; the dialog shows « Hors garantie » as a warning.

Real-time. None in the admin stream. The conversation polls every 30 s while open (see contract notes).

States.

  • Reseller attachments still uploading.
  • A closed ticket is read-only with « Rouvrir ».
  • The claim panel shows « Article déjà réclamé (TKT-…) » on a line claimed before.

Acceptance criteria.

  • A claim on 2 faulty units resolved as Remplacement creates a 0 DA order of 2 units, linked to the ticket. That order waits in BO-41 until confirmed.
  • Retour creates a return in BO-69. Its reception re-enters the non-defective quantities in stock and issues a credit note, with no manual stock action.
  • Avoir cannot exceed the amount paid for the claimed quantities.
  • Refusée requires a reason, which the reseller sees in their app.
  • Internal notes never appear in the reseller app.

BO-57 — Announcements

FieldValue
TemplateList (with a composer drawer)
ReleaseV1
Design dayDay 19 — DES-19
Build taskDSH-10
Route/communication/announcements
RequirementsNOT-07 · NOT-06
Permissions requiredcommunication.view · communication.create · communication.update · communication.delete (drafts) · communication.validate (send)

Purpose. Send messages from the back-office to delegates or resellers by target: the « Messages » of the delegate app (cahier §6.1) and announcements in the reseller app.

Who uses it. Commercial admin.

Entry points. Support › Annonces.

Layout.

  • Table: Titre, Public (delegates / resellers), Ciblage summary, Canaux, État (« Brouillon », « Programmée », « Envoyée »), Envoyée le, Lus (« 812 / 1 245 · 65 % »).
  • Composer drawer:
    • Titre: required, 80 characters max.
    • Message: required, plain text with links, 1 000 characters max.
    • Public: « Délégués » or « Revendeurs ».
    • Ciblage:
      • delegates: all, zones, or specific delegates;
      • resellers: all, wilayas, segments, customer types, or specific resellers.
    • Notification push: toggle, on by default.
    • Envoi: « Maintenant » or a date and time.
    • The audience count is shown live: « 1 245 destinataires ».
  • Preview in a phone frame.

Commercial push and new catalogue (change request 03). NOT-16, NOT-11, DSH-14.

  • The composer gets a Type selector (AnnouncementKind): « Message » (as above), « Push commercial », « Nouveau catalogue ». The last two are for resellers only.
  • Push commercial: target picker (product, promotion, category or brand), title ≤ 40 characters and message ≤ 120, action label (default « Commander maintenant »), and an extra audience criterion « Acheteurs de la catégorie … sur les N derniers jours ». Before sending, the count reads « 1 245 destinataires · 1 010 en push · 235 dans la boîte seulement (plafond atteint) ».
  • Nouveau catalogue: PDF upload (CATALOG_PDF), cover image, optional category or brand to open, action « Voir le catalogue ».
  • Both kinds are category PROMOTIONAL, group Promotions or Nouveautés, and count in the caps (NOT-17). A Message can be given a group, Urgent when the « Urgent » box is ticked.

Data. admin.announcements.crud, admin.announcements.send.

Actions. « Envoyer » (communication.validate): « Envoyer cette annonce à 1 245 revendeurs ? Une notification push sera envoyée. ». Not optimistic, audited CREATE / STATUS_CHANGE. A sent announcement cannot be edited.

Rules.

  • Announcements belong to the ANNOUNCEMENT category.
    • The inbox always receives them.
    • Push respects the recipient's preference (NOT-06).
  • Read counts come from AnnouncementRead.

Real-time. None.

States. A scheduled announcement shows its countdown. A send failure lists the failed deliveries (link to BO-58 Journal).

Acceptance criteria.

  • An announcement to the delegates of one zone reaches only them: their app inbox shows it, and nobody else's does.
  • The read rate updates as recipients open it.
  • A sent announcement is read-only.

BO-58 — Notification templates & rules

FieldValue
TemplateSettings
ReleaseV1
Design dayDay 19 — DES-19
Build taskDSH-10
Route/communication/notifications (?tab=rules, templates or log)
RequirementsNOT-04 · NOT-05 · ORD-15
Permissions requiredcommunication.administer (rules, templates) · communication.view (log)

Purpose.

  • Configure which event goes through which channel to whom (cahier §8 « Push, in-app, WhatsApp, SMS ou email selon le type d'événement »).
  • Edit the localised templates.
  • Check the delivery log.

Who uses it. Super admin, commercial admin.

Entry points. Support › Notifications.

Layout.

  • Tab « Règles »: a matrix with one row per event and columns IN_APP, PUSH, SMS, EMAIL, WHATSAPP (V1: share links only) per recipient (reseller, delegate, assigned staff, role).
    • Example events: order received, order confirmed, order on hold, order refused, order modified, order shipped, order delivered, assisted order to confirm, account validated or rejected, task assigned, ticket reply, claim resolved, return decided or received, payment confirmed or rejected, credit note issued.
    • Locked cells (lock icon): transactional and security channels that cannot be disabled. For example, every order status change notifies the reseller by push and in-app (ORD-15).
  • Tab « Modèles »: per event × channel × locale (FR; AR and EN prepared).
    • Titre (push), Objet (email) and Message.
    • Variables listed on the right and inserted as {{order.number}}, {{reseller.storeName}}, {{order.totalTtc}}.
    • A preview with sample data.
    • For SMS, a segment counter (160 GSM-7 / 70 UCS-2 characters per segment).
  • Tab « Journal »: date, event, channel, recipient, status (sent / failed), error message. Filters channel, status, from / to, recipient.

Smart notifications (change request 03). NOT-10, NOT-17, DSH-14.

  • Règles adds the smart events of the matrix, each with its group, its priority rank and an on/off switch per event.
  • Modèles adds the Bouton d'action field (label per locale, required for reseller events) next to Titre, and shows the group.
  • A new tab, « Notifications intelligentes », holds the settings: caps per day and per week, back-in-stock look-back (90 days), minimum out-of-stock time (24 h), abandoned-cart delay (2 h), price-drop minimum (5 %), reorder grace (1 day), and the times of the digest jobs. Every change is audited UPDATE.

Data. admin.notifications.rules, admin.notifications.templates, admin.notifications.log.

Actions.

  • Save the rules (one PUT of the matrix): « Enregistrer les règles ? Les prochains envois suivront cette configuration. ».
  • Save a template, per template.
  • Both are audited UPDATE.

Rules.

  • A template with an unknown variable cannot be saved.
  • Transactional notifications (category TRANSACTIONAL) and security ones cannot be switched off for the reseller (NotificationCategory).
  • The notifications matrix holds the seeded configuration.

Real-time. None.

States. The log is empty until the first sends. A failed SMS shows the provider error.

Acceptance criteria.

  • Disabling SMS for « commande expédiée » stops SMS for that event while push and in-app continue.
  • Cells for order status changes to the reseller cannot be disabled.
  • A template using {{order.unknown}} is refused with the variable named.

BO-59 — Reports library

FieldValue
TemplateBespoke (Dashboard skeleton: catalogue + report runner)
ReleaseV1
Design dayDay 19 — DES-19
Build taskDSH-11
Route/reports · /reports/[reportKey] (filters in the URL)
RequirementsANA-03 · ANA-04 · ANA-05 · ORD-09
Permissions requiredreports.view (each report also needs its module's view permission) · reports.export (export)

Purpose. The essential reports (cahier §4 « Indicateurs et rapports »):

  • revenue by period, zone, delegate, reseller, brand and product;
  • prospect conversion and first orders;
  • stock-outs and slow movers;
  • pending, late, cancelled and returned orders.

It also carries the success KPIs of cahier §1.4 (ANA-04).

Who uses it. Direction, commercial admin, finance, stock.

Entry points. Rapports › Rapports, and drill-downs from the dashboards (BO-04, BO-05).

Layout.

  • Catalogue: cards grouped by theme. Each card shows the title, a one-line definition and « Ouvrir ». Only the reports the user may run are listed (admin.reports.list).
  • Runner:
    • The filter bar (each report declares its filters: period, wilaya, commune, delegate, reseller, customer type, brand, category, product, channel), synced to the URL.
    • Regrouper par (when the report allows it), « Exécuter », « Exporter ».
    • A summary strip with the totals.
    • A chart and a paginated table, with a totals row.
    • « Définition » expands the exact formula.
Report (reportKey)GroupsDefinitionNeeds
CA par période (sales-by-period)Day / week / monthΣ net HT of counted orders by validation date (BO-04 basis)orders.view
CA par zone (sales-by-zone)Zone, wilaya, communeSame, by delivery addressorders.view
CA par délégué (sales-by-delegate)DelegateSame, by attributed delegateorders.view + field.view
CA par revendeur (sales-by-reseller)Reseller (+ customer type)Same; with order count, average basket, last orderorders.view + crm.view
CA par marque / par produit (sales-by-brand, sales-by-product)Brand, category, product, variantLine net HT and quantitiesorders.view
CA par type de client (sales-by-customer-type)CustomerTypeSame; share of revenue per typeorders.view
Conversion terrain (field-conversion)Delegate, zone, month of creationProspects created → accounts created → first orders (cohort)field.view + crm.view
Premières commandes (first-orders)Delegate, channelFirst orders with the reseller and source delegate (ORD-09)orders.view
Ruptures (stock-outs)Variant, brandVariants out of stock, days out of stock in the period, 30-day sales lost estimatestock.view
Faible rotation (slow-movers)VariantPhysical stock above 0 and no shipment for N days (default 60)stock.view
Commandes en attente de confirmation (orders-to-confirm)Channel, dayOrders SUBMITTED / PENDING with age, and confirmation delays (median, 90th percentile)orders.view
Commandes en retard (orders-late)Status, wilayaConfirmed orders not shipped within 48 h (setting)orders.view
Annulations et refus (orders-cancelled)Reason, channelCancelled and refused orders with their reasonsorders.view
Retours et SAV (returns)Reason, product, resolutionReturns and claims, quantities, credit notesorders.view + support.view
KPI de succès (success-kpis)MonthAdoption (accounts activated ÷ invited, active users), field conversion, digitalisation (share of orders via app and web), tour performance (visits done ÷ planned), loyalty (order frequency; levels in V2), operational quality (cancellations, refusals, late orders, returns) — cahier §1.4reports.view + the modules involved

Data. admin.reports.list, admin.reports.run (filters, page, pageSize → rows and totals), admin.exports.create.

Actions. « Exporter » (PDF with filters and chart, XLSX or CSV of all rows) creates an async export and shows the toast with the link to BO-60. It is audited EXPORT.

Rules.

  • One set of definitions: the same as the dashboards (BO-04). A report total with the same filters equals the card.
  • Permission-filtered at row level (financial reports need finance.view). Purchase-price margins appear only with pricing.view.
  • Time zone: periods are business days in Africa/Algiers.

Real-time. None. Reports run on demand.

States.

  • Long reports: when the response takes over 3 s, a skeleton with « Calcul en cours… » shows.
  • No data: « Aucune donnée pour ces filtres ».
  • Not permitted (from an old link): « Accès refusé ».

Acceptance criteria.

  • CA par période by month for this year equals CA de l'année on BO-04 with the same filters.
  • Conversion terrain per delegate equals the delegate's figures in BO-17 for the same period.
  • The export of a report contains the same rows and totals as the screen.
  • A stock manager without orders.view does not see the revenue reports in the catalogue.

BO-60 — Export centre

FieldValue
TemplateList
ReleaseV1
Design dayDay 19 — DES-19
Build taskDSH-11
Route/exports
RequirementsANA-05 · AUD-01
Permissions requiredreports.export

Purpose. Collect every export the user requested (lists and reports, PDF / XLSX / CSV, cahier §9) and download it once ready.

Who uses it. Every role that exports.

Entry points. Rapports › Exports (badge = running exports), and the export toasts.

Layout.

ColumnSource fieldSortableDefault visible
ExportSource (« Commandes », « CA par zone ») + filters summaryNoYes
FormatExportFormatYesYes
Demandé lecreatedAtYes (default descending)Yes
StatutJobStatusYesYes
LignesrowCountYesYes
TaillesizeYesNo
Expire leexpiresAtYesYes

Row actions: « Télécharger » (when SUCCEEDED), « Relancer » (same parameters), « Voir les filtres ».

Data. admin.exports.list, admin.exports.get (signed download URL, valid 5 minutes), admin.exports.create.

Actions. « Télécharger » fetches a fresh signed URL and starts the download. « Relancer » creates a new job. The audit is written at creation (EXPORT, with source and filters).

Rules.

  • Users see only their own exports.
  • Files (GENERATED_DOCUMENT, private) expire after 7 days. Assumption — the retention is to confirm. They then show EXPIRED.
  • An export contains only what the user was allowed to see when it was requested.

Real-time. No export event. While any job is QUEUED or RUNNING, the page and the badge poll every 5 s. Completion shows the toast « Export prêt — Télécharger ».

States. « Aucun export » appears on first use. A FAILED job shows its error with « Relancer ».

Acceptance criteria.

  • An export requested from BO-38 appears here at once as QUEUED, then SUCCEEDED with its row count, and downloads through a short-lived URL.
  • Another user's exports are never listed.
  • After expiry, the download is no longer possible and « Relancer » is offered.

On this page