HOCO B2B
SRSRequirements

Field operations (delegates, tours, visits)

Requirements FLD-01 to FLD-19: delegates, objectives, tour planning and lifecycle, GPS check-in, visits, reports, field sign-up, tour closing and the location policy.

This area covers the work of the délégué commercial (sales delegate) in the field and its supervision from the back-office: delegate profiles and zones, objectives, the tournée (tour) from planning to closing, visits with GPS check-in, checklists, photos and structured reports, field sign-up of new points of sale, live follow-up, and the rules for collecting positions. Sources: cahier §4.5 (back-office side), §6 to §6.9 (delegate app), §7.3 (offline), §8 (GPS rules), §10 (consent) and §12 (acceptance scenarios Tournée, GPS, Prospect, Rapport). Apps: the delegate app (DA, offline-first), the back-office (BO) and the API. Server module: field (with geo for distances and zones, crm for points of sale and follow-ups, files for photos and sync for offline replay — see Synchronisation & offline).

IDRequirementReleasePrioritySourceApps
FLD-01Delegate accounts and profiles; assignment of wilayas, communes and points of saleV1MUST§4.5API · BO · DA
FLD-02Objectives per delegate and period: visits, sign-ups, app installs, orders, revenueV1MUST§4.5API · BO · DA
FLD-03Tour planning: daily, weekly or monthly; ordered stops (imposed or recommended); priorities and time slotsV1MUST§4.5, §6.2API · BO
FLD-04Tour lifecycle (planned, to start, in progress, suspended, completed, cancelled); only the assigned delegate starts itV1MUST§4.5, §6.1, §15.3API · DA · BO
FLD-05Delegate home: today's tour, counters, objectives, conversion rate, quick accessV1MUST§6.1DA · API
FLD-06Tour programme: list and map show the same visits in the same order; filters, delays, prioritiesV1MUST§6.2DA · API
FLD-07Map and navigation: position, next destination with ETA and distance, external GPS navigation, arrival confirmation within toleranceV1MUST§6.3DA · API
FLD-08Visit and check-in: time and position at check-in, duration, checklist, note, photos (mandatory by visit type), call; finished visit lockedV1MUST§6.4DA · API · BO
FLD-09A visit not carried out requires a reasonV1MUST§4.5, §6.9DA · API
FLD-10Structured visit report (person met, interest, products and promotions presented, issues, next action, follow-up date, attachments) that triggers the follow-upV1MUST§6.8DA · API · BO
FLD-11Field reseller sign-up with GPS and façade photo, offline-capable, linked to the creating delegate, pending validationV1MUST§6.5DA · API
FLD-12Tour closing: day summary, comment, objectives and conversion, final report; requires reasons and synced data; definitive unless reopenedV1MUST§6.9DA · API · BO
FLD-13Live follow-up in the back-office: delegates on tour, positions, visit progressV1MUST§4.5, §6.4BO · API
FLD-14Back-office analysis of visit reports and validation of new points of saleV1MUST§4.5BO
FLD-15Location policy: consent, frequency, tolerance and retention configurable and transparentV1MUST§8, §10API · DA · BO
FLD-16Visit types and checklist templates configurationV1SHOULD§6.4, §6.8BO · API
FLD-17Recommended visit order (nearest-neighbour heuristic)V1SHOULD§4.5, §6.2API · BO
FLD-18Automatic tour optimisation (routing engine)V2COULD§14.2API · BO
FLD-19Delegate reports history and own performance over periodsV1MUST§6.1, §6.9DA · API

Field settings used on this page

Every tunable value below is a Setting edited in BO-64 by a user holding settings.administer (ADM-03). The delegate app receives them through appConfig.get and sync.delta and applies the same values offline. Defaults marked "to confirm" are open in the decision register — GPS tolerance (D-06), sampling (D-07, D-24) and retention (D-11) are listed by the cahier as decisions still to validate (§15). Position format, validation and the distance function are those of GEO-03.

KeyDefaultMeaning
field.gpsToleranceMeters150 (to confirm)Maximum distance between the check-in fix and the point of sale's stored coordinates.
field.gpsMaxAccuracyMeters100 (to confirm)A fix whose reported accuracy radius is larger is refused for check-in and sign-up capture, and dropped from pings.
field.allowOutOfToleranceCheckInfalseWhen true, an out-of-tolerance check-in is accepted with a mandatory justification and flagged.
field.locationIntervalSeconds300 (to confirm)Time trigger for a position sample while a tour is IN_PROGRESS.
field.locationDistanceMeters200 (to confirm)Distance trigger for a position sample (whichever trigger comes first).
field.locationRetentionDays90 (to confirm)Retention of LocationPing rows; older rows are purged nightly.
field.reportRequiredToEndVisittrueDefault "report required" flag of new visit types (FLD-16).
field.closingRequiresSynctrueThe tour can only be closed when the device's queue for it is empty (FLD-12).
field.reopenMaxDays7A completed tour can be reopened up to this many days after its date.
field.visitUnlockHours24Correction window opened by an authorised unlock of a finished visit.
field.locationPolicyVersion"2026-11" (proposed)Version of the location notice; a new version requires a new consent.
field.maxStopsPerTour30 (proposed)Maximum number of stops in one tour.
field.shortVisitFlagSeconds120 (proposed)Finished visits shorter than this are flagged for review (never blocked).
field.signupFacadePhotoRequiredtrue (proposed)A façade photo is mandatory for a field sign-up.

Keys marked "proposed" are additions to the settings catalogue; the others are already listed there with their allowed ranges.

Business days, "today" and every daily job use Africa/Algiers. Distances are great-circle distances computed with the Haversine formula (mean Earth radius 6 371 008.8 m) and rounded to the metre (GEO-03).

FLD-01 — Delegate accounts, zones and points of sale

ReleasePrioritySourceAppsOwner tasks
V1MUSTcahier §4.5API · BO · DASRV-21, DSH-08, MDA-01

Statement — The system shall let authorised back-office users create and maintain delegate accounts and profiles, and assign to each delegate the zones (wilayas and communes) and the points of sale they cover.

Rules

  1. A delegate is a User of type DELEGATE holding the DELEGATE role, with exactly one DelegateProfile: first name, last name, mobile phone (E.164, unique among users, used to sign in), optional email and avatar, a short unique delegate code shown in lists (e.g. DEL-012), an optional start point (latitude/longitude used by FLD-17) and an optional manager (staff user).
  2. Creation and edition happen in BO-18 with field.create / field.update. Creating a delegate creates the account in the same transaction and sends the temporary password by SMS; the first sign-in forces a password change (ADM-01).
  3. Zones are attached through DelegateZone (one or more zones; a zone groups wilayas and communes — GEO-02). A delegate without a zone can sign in but cannot receive a tour: planning answers 422 DELEGATE_HAS_NO_ZONE.
  4. Points of sale are attached through ResellerAssignment (CRM-05); a point of sale has at most one assigned delegate at a time. The delegate's data scope is: points of sale assigned to them, plus unassigned points of sale whose commune belongs to one of their zones (ACL-03).
  5. Changing a delegate's zones never reassigns points of sale silently: the back-office lists the assigned points of sale now outside the delegate's zones and offers a bulk reassignment; until it is done the assignment keeps them in scope.
  6. Suspending or disabling a delegate (SEC-06) revokes their sessions, lists their PLANNED / TO_START tours with a prompt to cancel them, and lists their assigned points of sale for reassignment. History (tours, visits, reports, attributions) is kept; a delegate code is never reused.
  7. In the delegate app, DA-24 and DA-25 show the profile, status, zones, wilayas and communes covered, and the number of points of sale per commune. Only the avatar and the language are editable by the delegate.
  8. Every creation, zone change and status change is written to the AuditLog; a zone change notifies the delegate (category FIELD).

Acceptance criteria

  • Given a commercial admin with field.create, when they create a delegate with phone +213555123456 and zone Oran Centre, then the delegate receives an SMS, can sign in, must change the password, and DA-25 lists the wilayas and communes of Oran Centre.
  • Creating another user with the same normalised phone fails with 409 USER_PHONE_TAKEN; a user without field.create gets 403 PERMISSION_DENIED.
  • Given point of sale P assigned to delegate A and delegate B whose zone covers P's commune, then P is absent from B's delegate.resellers.list and B's delegate.resellers.get on P answers 404 NOT_FOUND (out-of-scope records are not revealed).
  • Planning a tour for a delegate without zone fails with 422 DELEGATE_HAS_NO_ZONE.
  • Suspending a delegate who has two planned tours shows both tours in the confirmation dialog; the delegate's next API call answers 401 and the app shows the suspended-account message (AUTH-02).

Data — User, UserRole, DelegateProfile, DelegateZone, Zone, ZoneArea, Wilaya, Commune, ResellerAssignment, Session, AuditLog.

Interfaces

FLD-02 — Objectives per delegate and period

ReleasePrioritySourceAppsOwner tasks
V1MUSTcahier §4.5API · BO · DASRV-21, DSH-08, MDA-01

Statement — The system shall let the back-office set numeric objectives per delegate and period for visits, sign-ups, app installs, first orders, orders and revenue, and shall compute and display their achievement to the delegate and to the back-office.

Rules

  1. An Objective is (delegate, ObjectivePeriod DAY / WEEK / MONTH, period start date, ObjectiveMetric, target). Weeks start on Sunday (working week Sunday–Thursday); months are calendar months. Targets are positive integers; REVENUE is in centimes of DZD.

  2. The tuple (delegate, metric, period, period start) is unique: a second one answers 409 OBJECTIVE_ALREADY_EXISTS. Objectives can be created in bulk for several delegates from BO-20 (field.create).

  3. Once the period has ended, an objective is read-only (409 OBJECTIVE_PERIOD_CLOSED) except for users holding field.administer; the change is audited.

  4. Achievement is computed by the server for the delegate's own activity, with business dates in Africa/Algiers:

    MetricCountedDate used
    VISITSVisits in status DONE on the delegate's toursvisit end
    SIGNUPSPoints of sale created by the delegate in the field (source DELEGATE_APP) and not rejected at validationcreation
    APP_INSTALLSThe delegate's invitations that reached step APP_INSTALLED (IVT-03), excluding flagged installsstep time
    FIRST_ORDERSOrders flagged as first order and attributed to the delegate (ORD-09), not CANCELLED or REFUSEDsubmission
    ORDERSOrders of points of sale assigned to the delegate at submission time, in any status except DRAFT, REFUSED, CANCELLED, RETURNEDsubmission
    REVENUESum of the totals (TTC, after discounts, without delivery fee) of the orders counted in ORDERSsubmission
  5. Achievement % = achieved ÷ target × 100, rounded down; values above 100 % are shown as they are. Counters are recomputed whenever a counted order changes status, so a cancelled order leaves the revenue of its day.

  6. When no DAY / VISITS objective exists for today, the delegate home uses the number of stops of today's tour as the daily visit target and labels it « Objectif du jour (tournée) ».

  7. A delegate sees only their own objectives (DA-22); the back-office sees all of them in BO-17 and BO-20.

Acceptance criteria

  • Given a WEEK / VISITS objective of 50 for delegate A starting Sunday, when A finishes 3 visits on Monday, then DA-22 shows 3 / 50 (6 %) and BO-17 shows the same figure.
  • Creating the same delegate, metric, period and start twice fails with 409 OBJECTIVE_ALREADY_EXISTS; a target of 0 fails with 400 VALIDATION_FAILED.
  • Given an order of 125 000,00 DA counted in A's REVENUE today, when the back-office cancels it, then today's revenue achievement drops by 12 500 000 centimes at the next refresh.
  • Editing last month's objective without field.administer fails with 409 OBJECTIVE_PERIOD_CLOSED.

Data — Objective, Visit, Tour, Reseller, Invitation, InvitationEvent, Order, Setting.

Interfaces

Notes / open points — The exact definition of REVENUE (submitted vs validated orders, TTC vs HT) is a proposal to confirm in the decision register; the reference screens show « Chiffre d'affaires généré » without a definition.

FLD-03 — Tour planning

ReleasePrioritySourceAppsOwner tasks
V1MUSTcahier §4.5, §6.2API · BOSRV-21, DSH-08, MDA-02, DES-19

Statement — The system shall let the back-office plan tours per delegate for a day, a week or a month, each tour being an ordered list of stops with an ordering mode (imposed or recommended), priorities and optional time slots, and shall synchronise every change to the delegate.

Rules

  1. A Tour is one delegate, one business date and an ordered list of stops (Visit records in status PLANNED); it receives a number TRN-2026-000045 at creation.
  2. Daily planning creates one tour. Weekly and monthly planning create a series: a weekday pattern (e.g. Sunday and Tuesday) over a date range of at most 3 months; one independent tour is created per matching working day (Sunday–Thursday, public holidays skipped unless explicitly kept). Editing one tour of a series never changes the others.
  3. A delegate has at most one non-cancelled tour per date: a second one answers 409 TOUR_DATE_TAKEN with the existing tour number in details.
  4. A tour has 1 to field.maxStopsPerTour stops. Each stop carries: the point of sale (in the delegate's scope at planning time, otherwise 403 OUT_OF_SCOPE), a VisitType (default: prospection for prospects, follow-up for active resellers — FLD-16), a VisitPriority (NORMAL or HIGH), an optional time slot (start and end HH:mm, end after start, between 06:00 and 21:00) and an optional note (≤ 300 characters). A point of sale appears at most once per tour (422 DUPLICATE_STOP).
  5. TourOrderingMode: RECOMMENDED (default) lets the delegate reorder the remaining stops; IMPOSED forbids reordering (409 TOUR_ORDER_IMPOSED) and, at check-in, requires the first unresolved stop of the sequence (FLD-08 rule 3). Positions are contiguous from 1.
  6. Edit rights by tour status: PLANNED / TO_START — date, mode, notes and stops; IN_PROGRESS / SUSPENDED — only stops still PLANNED may be added, moved or removed (a removed stop becomes CANCELLED); stops in any other status are immutable (409 VISIT_LOCKED); COMPLETED / CANCELLED — nothing (409 TOUR_NOT_EDITABLE). The date cannot change once the tour is TO_START.
  7. Every change increments the tour's version, is recorded in the tour history, and triggers a push to the delegate (« Votre tournée du 22/05 a été modifiée ») plus a silent sync hint so the device pulls sync.delta immediately (§6.2: « Une visite ajoutée ou déplacée doit être synchronisée »).
  8. The planner calendar (BO-21) shows, per delegate and day, the tour status, the number of stops and the days without a tour; the editor (BO-22) shows the stops on a map in their order with the straight-line total distance.

Acceptance criteria

  • Given delegate A with zone Oran Centre, when an admin plans a weekly series "Sunday and Tuesday" over 4 weeks, then 8 tours are created (minus holidays), each with its own TRN-… number, visible in A's calendar (DA-07) after the next sync.
  • Planning a second tour for A on the same date fails with 409 TOUR_DATE_TAKEN; adding the same point of sale twice fails with 422 DUPLICATE_STOP; adding a point of sale assigned to another delegate fails with 403 OUT_OF_SCOPE.
  • Given a tour IN_PROGRESS with stop 2 DONE, removing stop 2 fails with 409 VISIT_LOCKED; moving stop 5 (PLANNED) to position 3 succeeds and the delegate's list and map show the new order within 1 minute when the device is online.
  • On an IMPOSED tour, delegate.tours.reorder fails with 409 TOUR_ORDER_IMPOSED.

Data — Tour, TourStatusChange, Visit, VisitType, Reseller, DelegateProfile, NumberSequence, OutboxEvent, Notification.

Interfaces

FLD-04 — Tour lifecycle

ReleasePrioritySourceAppsOwner tasks
V1MUSTcahier §4.5, §6.1, §15.3API · DA · BOSRV-21, DSH-08, MDA-02

Statement — The system shall manage each tour through the statuses PLANNED, TO_START, IN_PROGRESS, SUSPENDED, COMPLETED and CANCELLED with the transitions below, and only the assigned delegate shall be able to start, suspend, resume and close it.

Rules

  1. Transitions, actors and guards:

    FromToActorGuards (checked in this order)Effects
    PLANNEDTO_STARTSystem job at 00:05tour date is todayStart button enabled
    TO_STARTIN_PROGRESSAssigned delegatetour belongs to the caller (another delegate's tour answers 404 NOT_FOUND, ACL-03); status is TO_START (409 TOUR_NOT_STARTABLE for a completed, cancelled or already started tour); the Africa/Algiers date of occurredAt is the tour date (409 TOUR_NOT_TODAY); no other tour of the delegate is IN_PROGRESS or SUSPENDED (409 TOUR_ALREADY_IN_PROGRESS); current location consent (FLD-15, 409 LOCATION_CONSENT_REQUIRED)start time and position recorded, location sampling starts, tour.started event
    IN_PROGRESSSUSPENDEDAssigned delegatereason from the TOUR_SUSPEND_REASON list; no visit CHECKED_IN or IN_PROGRESS (409 VISIT_IN_PROGRESS)sampling stops
    SUSPENDEDIN_PROGRESSAssigned delegatetour not closedsampling resumes (only during the tour's business day)
    IN_PROGRESS, SUSPENDEDCOMPLETEDAssigned delegateclosing guards of FLD-12final report
    PLANNED, TO_START, IN_PROGRESS, SUSPENDEDCANCELLEDBack-office, field.updatereason (text, 5 to 300 characters)PLANNED stops become CANCELLED; finished visits are kept; delegate notified
    COMPLETEDIN_PROGRESSBack-office, field.validatewithin field.reopenMaxDays (409 REOPEN_WINDOW_EXPIRED); reasonsee FLD-12
  2. The start records startedAt (the action's occurredAt) and, when location permission is granted and a fix with accuracy ≤ field.gpsMaxAccuracyMeters is obtained within 15 seconds, the start position; otherwise the start proceeds with the reason position unavailable recorded (§6.1: « selon les permissions GPS »).

  3. Offline, the app treats a PLANNED tour dated today as startable (it mirrors the 00:05 job) and queues the start with its occurredAt; the server checks the guards against the business day of occurredAt.

  4. Nothing is closed or cancelled automatically, because closing needs the delegate's report: the 00:05 job lists to the commercial admins the tours not started (still TO_START after their date) and not closed (IN_PROGRESS or SUSPENDED after their date) — see the lifecycles page. A tour still IN_PROGRESS at 21:00 is moved to SUSPENDED (reason AUTO_END_OF_DAY) so location sampling never runs overnight (field.autoSuspendOpenTours, proposal). The next morning the delegate must close it before starting the new tour (TOUR_ALREADY_IN_PROGRESS); the app offers « Clôturer la tournée d'hier ».

  5. Every transition writes a TourStatusChange (from, to, actor, occurredAt, receivedAt, reason) and an OutboxEvent that feeds the real-time stream (SYN-07) and the notifications.

Acceptance criteria

  • Given a tour of delegate A dated today in TO_START, when delegate B calls delegate.tours.start, then the answer is 404 NOT_FOUND and the tour stays TO_START.
  • Given a tour dated tomorrow (PLANNED), when A tries to start it, then the answer is 409 TOUR_NOT_TODAY and the start button is not shown on DA-05.
  • Given yesterday's tour still IN_PROGRESS, when A starts today's tour, then the answer is 409 TOUR_ALREADY_IN_PROGRESS and the app opens the closing of yesterday's tour.
  • Given A starts the tour with location permission denied, then the tour becomes IN_PROGRESS with start time recorded and no position, and BO-23 shows « Position de démarrage indisponible ».
  • Given a TO_START tour never started, at 00:05 the next day it stays TO_START, is listed to the commercial admins as non démarrée, and its stops count as planned-but-not-done in tour performance until the back-office cancels it.
  • Every transition appears in the tour history of BO-23 with actor and time.

Data — Tour, TourStatusChange, Visit, LocationPing, ReferenceItem (TOUR_SUSPEND_REASON), OutboxEvent, AuditLog.

Interfaces

Notes / open points — The automatic suspension at 21:00 is a proposal of the jobs page; without it, sampling would run until the delegate closes or suspends the tour.

FLD-05 — Delegate home

ReleasePrioritySourceAppsOwner tasks
V1MUSTcahier §6.1DA · APISRV-21, MDA-01, DES-11

Statement — The system shall give the delegate a home screen summarising today's tour, the day's counters, objective progress and conversion rate, with the tour action that matches the tour status and quick access to the main modules, and shall keep it current after every visit, online or offline.

Rules

  1. Content (reference screen Accueil délégué): greeting with first name, zone name, notification bell with unread count; counters Visites prévues, Visites réalisées, Nouveaux prospects (field sign-ups of the day); Ma tournée du jour — the stops in order with name, commune, slot start and status pill (VisitStatus label, En retard derived per FLD-06); quick-access tiles Tournée, Prospects, Rapports, Messages (unread badge); widgets Objectif du jour and Taux de conversion.
  2. One tour action button, by status of today's tour: TO_START (or PLANNED dated today while offline) → « Commencer la tournée »; IN_PROGRESS → « Continuer la tournée »; SUSPENDED → « Reprendre la tournée »; all stops resolved → « Clôturer la tournée »; COMPLETED → « Voir le bilan ». No tour today → empty state « Aucune tournée planifiée aujourd'hui » with access to prospects. The start button exists only for a tour planned for today (§6.1).
  3. Counters and widgets are computed on the device from the local database and refreshed after every visit action, so they move even offline (§6.1 « Les compteurs se mettent à jour après chaque visite »); when online, delegate.home refreshes the server-side figures (objectives, conversion, unread counts) at app foreground and at most every 5 minutes.
  4. Taux de conversion (day, week or month) = converted prospects ÷ prospects visited × 100, rounded down, shown as « 2 / 8 prospects ». A prospect visited is a distinct point of sale whose status was a prospect status (NEW_PROSPECT, TO_CONTACT, INTERESTED, TO_FOLLOW_UP, NOT_INTERESTED, APP_INSTALLED) when the delegate finished a visit to it in the period; it is converted when it reached ACCOUNT_CREATED or a later status (FIRST_ORDER, ACTIVE) by the end of the period. The same formula is used on DA-20, DA-21 and in the back-office.
  5. Objectif du jour uses the DAY / VISITS objective, or the number of stops of today's tour when none exists (FLD-02 rule 6).
  6. The home loads from the local database in under 1 second after a cold start that already passed the splash screen; server refresh never blocks the display.

Acceptance criteria

  • Given today's tour TO_START with 12 stops, the home shows 12 planned, 0 done and « Commencer la tournée »; given a tour dated tomorrow only, no start button is shown.
  • Given the phone in airplane mode, when the delegate finishes visit 3, then Visites réalisées goes from 2 to 3 and the objective bar updates without network.
  • Given 8 prospects visited today of which 2 created their account, the widget shows « 25 % — 2 / 8 prospects », and BO-17 shows 25 % for the same delegate and day.
  • Given an unread announcement, the Messages tile shows a badge that disappears once it is read on DA-23.

Data — Tour, Visit, Objective, Reseller, ResellerStatusChange, Notification, Announcement, AnnouncementRead.

Interfaces

Notes / open points — The reference screens label the conversion denominator prospects on the home and visites on the closing screen; this page uses one formula (prospects) for both — Akram aligns the closing label, the formula itself goes to the decision register.

FLD-06 — Tour programme (list and map)

ReleasePrioritySourceAppsOwner tasks
V1MUSTcahier §6.2DA · APISRV-21, MDA-02, DES-12

Statement — The system shall show the delegate the stops of a tour as a list and on a map that always contain the same visits in the same order, with filters, delays, priorities and distances, and shall let the delegate reorder (when allowed) and add unplanned visits.

Rules

  1. List and map read the same local records sorted by position; pin numbers equal list numbers; a filter applied to one applies to the other (§6.2 acceptance criterion). Removed stops (CANCELLED) disappear from both.
  2. Header counters: Visites prévues, Visites réalisées, En retard. Tabs: À visiter (PLANNED, CHECKED_IN, IN_PROGRESS), Visitées (DONE, NOT_DONE), Prospects (stops whose point of sale has a prospect status). Filters: status, priority, morning or afternoon slot, commune.
  3. En retard is derived on the device: a PLANNED stop of a TO_START or IN_PROGRESS tour whose slot end has passed (Africa/Algiers); stops without a slot are never late (lifecycles). HIGH priority stops carry the Prioritaire marker.
  4. Each row shows name, commune, slot start, and the straight-line distance from the current position (from the previous stop when no fix is available); the action is « Visiter » for an unresolved stop and « Voir » for a resolved one.
  5. Reorder (drag) is offered only on RECOMMENDED tours and only among PLANNED stops; it is saved through delegate.tours.reorder (offline: queued) and resolved positions keep their place. « Réordonner au plus proche » applies the FLD-17 heuristic from the current position on the device.
  6. Ad-hoc visit: the delegate picks a point of sale in scope or creates one (FLD-11); the visit gets a client-generated id, is appended at the end with the flag Non planifiée, and uses the default visit type. Allowed on IMPOSED tours too (outside the imposed sequence). A point of sale already on the tour cannot be added again (422 DUPLICATE_STOP).
  7. Changes made by the back-office arrive through the silent sync hint and sync.delta; the app shows a banner « Tournée mise à jour par l'administration » and re-sorts list and map together.

Acceptance criteria

  • Given a tour of 6 stops, list and map show pins 1–6 matching rows 1–6; after filtering Prioritaire, both show the same 2 stops.
  • Given stop 3 with slot 10:30–11:00 still PLANNED at 11:01, it shows En retard and the counter increases by 1.
  • Given an IMPOSED tour, no drag handle is shown and the API refuses a reorder with 409 TOUR_ORDER_IMPOSED; an ad-hoc visit is still accepted and appended with Non planifiée.
  • Given the back-office moves stop 5 to position 2 while the delegate is online, the list and the map both show it second within 1 minute.

Data — Tour, Visit, VisitType, Reseller, Setting.

Interfaces

FLD-07 — Map, navigation and arrival

ReleasePrioritySourceAppsOwner tasks
V1MUSTcahier §6.3DA · APISRV-21, MOB-10, MDA-03, MOB-13, DES-12

Statement — The system shall show the delegate's position and the next destination with ETA and distance, open an external navigation app on request, and record the arrival (check-in) only when the GPS tolerance rules of FLD-08 are met.

Rules

  1. The map (DA-08) shows the current position, the remaining stops as numbered pins in tour order and the route polyline from the maps provider (INT-01).
  2. Next destination = the first unresolved stop in tour order (the delegate can select another one on RECOMMENDED tours). The card shows name, commune, ETA and road distance from the provider's routing; requests are made only for the next destination, at most every 2 minutes or every 500 m moved. Without network or provider answer, the card shows the straight-line distance and hides the ETA (« ETA indisponible hors ligne »).
  3. « Démarrer GPS » opens the external navigation app (Google Maps, or the system chooser) with the point of sale's coordinates as destination; the HOCO app does not provide turn-by-turn guidance. A stop without coordinates opens the navigation app with its address text.
  4. « Arrivé » triggers the check-in algorithm of FLD-08; the button shows the live distance (« Vous êtes à 320 m — tolérance 150 m ») computed on the device with the same formula and settings as the server.
  5. System states (DA-28): location services off → « Activez la localisation » with a shortcut to settings; permission denied → explanation and link to app settings; accuracy too low → « Précision insuffisante (± 180 m) — attendez quelques secondes »; out of tolerance → distance and tolerance with « Réessayer »; offline → map tiles from cache when available, pins and list always available.
  6. Position is used only for the purposes of the location policy (FLD-15); the map screen does not create position samples by itself.

Acceptance criteria

  • Given the next stop 4,2 km away by road and network available, the card shows the provider's ETA and 4,2 km; in airplane mode it shows the straight-line distance and « ETA indisponible hors ligne ».
  • Tapping « Démarrer GPS » opens the external navigation app with the stop as destination and returns to the HOCO app on back.
  • Given the delegate at 320 m with tolerance 150 m and field.allowOutOfToleranceCheckIn = false, « Arrivé » is disabled and shows the distance; at 90 m with accuracy ± 25 m it records the check-in and opens the visit.
  • Given location services off, the map shows the Activez la localisation state and « Arrivé » is unavailable.

Data — Visit, Reseller (coordinates), Tour, Setting.

Interfaces

FLD-08 — Visit and check-in

ReleasePrioritySourceAppsOwner tasks
V1MUSTcahier §6.4DA · API · BOSRV-21, DSH-08, MOB-11, MDA-05, DES-13

Statement — The system shall record for each visit the check-in time and position (validated against the point of sale's coordinates), the start and end times and duration, the checklist, a note, photos (mandatory when the visit type requires them) and call attempts, and shall lock the visit once finished unless an authorised user unlocks it.

Check-in algorithm — the server applies these steps in this order to delegate.visits.arrive (body: the position, occurredAt, optional outOfToleranceReason); the app applies steps 6 to 10 locally before sending, with the same settings, so the delegate gets the verdict even offline.

  1. Scope — the visit belongs to a tour of the caller, else 404 NOT_FOUND (ACL-03: only the assigned delegate acts on a tour).
  2. Tour — the tour is IN_PROGRESS; otherwise 409 TOUR_NOT_IN_PROGRESS (PLANNED, TO_START, SUSPENDED), 409 TOUR_CLOSED (COMPLETED) or 409 TOUR_CANCELLED.
  3. Visit — the visit is PLANNED, or NOT_DONE while the same tour is still IN_PROGRESS (the delegate came back later) (DONE → 409 VISIT_LOCKED; CANCELLED → 409 VISIT_CANCELLED; other → 409 VISIT_INVALID_TRANSITION); on an IMPOSED tour it is the lowest-position unresolved planned stop, ad-hoc visits excepted (409 VISIT_OUT_OF_ORDER); no other visit of the delegate is CHECKED_IN or IN_PROGRESS (409 VISIT_IN_PROGRESS).
  4. Time — occurredAt passes the plausibility rule of SYN-05 (422 OCCURRED_AT_OUT_OF_RANGE).
  5. Position present — a position in the GEO-03 format (lat, lng, accuracy, capturedAt, isMocked) is required (422 LOCATION_REQUIRED): unlike the tour start, a check-in cannot be recorded without a fix (§12 scenario GPS). Coordinates outside Algeria answer 400 VALIDATION_FAILED (LOCATION_OUT_OF_BOUNDS).
  6. Freshness — the fix is at most 2 minutes older than the action's occurredAt, else 400 VALIDATION_FAILED with field code LOCATION_STALE (the app takes a fresh fix).
  7. Mock — a fix the OS flags as mocked answers 422 GPS_MOCK_LOCATION.
  8. Accuracy gate — accuracy ≤ field.gpsMaxAccuracyMeters, else 422 GPS_ACCURACY_TOO_LOW (details: accuracyMeters, maxAccuracyMeters). The app keeps listening for up to 30 seconds for a better fix before giving this verdict.
  9. Reference point — the point of sale's stored coordinates. If it has none, the check-in is accepted with toleranceStatus = NO_REFERENCE and the fix is stored as a candidate position for back-office validation (badge « Position à valider » on BO-25 and BO-13); later check-ins are compared with the candidate until a back-office user validates or corrects it (audited).
  10. Distance and tolerance — distanceMeters = Haversine distance between the fix and the stored coordinates, rounded to the metre (GEO-03 rule 4). distanceMeters ≤ field.gpsToleranceMeters → WITHIN_TOLERANCE. The accuracy radius is not added to the tolerance: accuracy and distance are two separate gates.
  11. Out of tolerance — with field.allowOutOfToleranceCheckIn = false: 422 GPS_OUT_OF_TOLERANCE (details: distanceMeters, toleranceMeters, accuracyMeters), the visit stays PLANNED and the refused attempt is counted on the visit (count and last refused distance, visible on BO-25). The out-of-tolerance state offers « Signaler une position erronée », which creates a follow-up task for the commercial admins to correct the store's pin (D-06 option 1). With true: outOfToleranceReason (10 to 300 characters) is required (422 OUT_OF_TOLERANCE_REASON_REQUIRED); the check-in is accepted with toleranceStatus = OUT_OF_TOLERANCE, the visit is flagged Hors tolérance in BO-24 and the commercial admins receive a FIELD notification.
  12. Offline replay — a check-in queued offline is re-evaluated at replay with the fix it carries (never with a later position). If the server verdict differs from the device's (point of sale moved, setting changed meanwhile), the server applies the check-in, stores both verdicts and flags the visit Écart de tolérance for review instead of rejecting work already done in the field. A stale or mocked fix is still refused (REJECTED), because the device applies the same checks before queueing.
  13. Effects — visit → CHECKED_IN; stored: check-in time (= occurredAt), receivedAt, position, accuracy, distance, toleranceStatus; the requirement snapshot of the visit type (photos, report, checklist) is frozen on the visit so later configuration changes do not invalidate field work; event visit.checked_in to the back-office stream.

Rules (visit flow after check-in)

  1. « Commencer la visite » moves CHECKED_IN → IN_PROGRESS and records startedAt; « Terminer la visite » moves IN_PROGRESS → DONE. Duration = endedAt − startedAt, shown live (« Durée de la visite 00:12 »). Other transitions answer 409 VISIT_INVALID_TRANSITION; timestamps must be ordered (check-in ≤ start ≤ end, else 422 OCCURRED_AT_INCONSISTENT).
  2. Checklist: the items of the visit type's ChecklistTemplate, copied to VisitChecklistItem at check-in, each checked or not; saved as a whole (delegate.visits.checklist), any number of times before the end.
  3. Quick note: 0 to 300 characters (counter 0/300), saved with delegate.visits.note.
  4. Photos: taken with the camera or picked from the gallery, compressed on the device (long edge ≤ 1 600 px, JPEG), EXIF removed, uploaded with purpose VISIT_PHOTO (≤ 5 MB) and attached with their capture time and position (delegate.visits.addPhoto); at most 10 per visit. Offline, photos wait in the upload queue and are attached in order before the end action is replayed.
  5. Call: the phone icon opens the dialer on the point of sale's phone (tel:) and logs a call attempt (Interaction of type CALL) on the point of sale's timeline.
  6. End guards: when the frozen requirements are not met the server answers 422 VISIT_REQUIREMENTS_NOT_MET with details.missing listing, in this order, PHOTO_REQUIRED (with required and provided), REPORT_REQUIRED (FLD-10) and CHECKLIST_INCOMPLETE (the unchecked required items). The app shows the same blocking reasons before sending.
  7. Lock: at DONE the visit is locked; any later mutation answers 409 VISIT_LOCKED (§6.4 « Une visite terminée ne peut être modifiée sans permission »). A user with field.validate can unlock it with a reason (admin.visits.unlock): the delegate may then edit checklist, note, photos and report for field.visitUnlockHours; the visit re-locks at the next Terminer or when the window ends. Unlock and every corrected field are audited.
  8. Finished visits shorter than field.shortVisitFlagSeconds are flagged Visite courte in the back-office, never blocked.
  9. On DONE: event visit.completed, a VISIT interaction on the point of sale's timeline (CRM-07), home counters updated.
  10. Back-office: BO-24 lists visits with filters (status, delegate, date, tolerance status, flags); BO-25 shows the check-in on a map (fix, accuracy circle, stored position, distance), times, duration, checklist, note, photos, report and full history (§6.4 « La visite apparaît en temps réel dans le back-office et conserve son historique complet »).

Acceptance criteria

  • Given a point of sale at 35.6969, -0.6331 and a fix at 90 m with accuracy ± 25 m taken 10 s ago, when the delegate taps « Arrivé », then the visit becomes CHECKED_IN with distanceMeters = 90, WITHIN_TOLERANCE, and appears on BO-23 within 5 seconds (online).
  • Same point of sale, fix at (35.6980, -0.6320) — 158 m, the GEO-03 test vector —, field.allowOutOfToleranceCheckIn = false → 422 GPS_OUT_OF_TOLERANCE with distanceMeters = 158, toleranceMeters = 150; visit still PLANNED; BO-25 shows 1 refused attempt.
  • Same with the setting on and no reason → 422 OUT_OF_TOLERANCE_REASON_REQUIRED; with reason « Magasin déménagé en face » → accepted, flagged Hors tolérance, commercial admins notified.
  • Fix with accuracy ± 180 m → 422 GPS_ACCURACY_TOO_LOW; fix taken 3 minutes before the action → 400 VALIDATION_FAILED / LOCATION_STALE; mocked fix → 422 GPS_MOCK_LOCATION; no position → 422 LOCATION_REQUIRED.
  • Point of sale without coordinates → check-in accepted with NO_REFERENCE, and the fix appears on BO-25 as the candidate position to validate.
  • Visit type requiring 1 photo and a report: Terminer with no photo → 422 VISIT_REQUIREMENTS_NOT_MET with missing = PHOTO_REQUIRED, REPORT_REQUIRED; with the photo but no report → missing = REPORT_REQUIRED; with both → DONE, then delegate.visits.note → 409 VISIT_LOCKED.
  • On an IMPOSED tour, checking in at stop 3 while stop 2 is still PLANNED → 409 VISIT_OUT_OF_ORDER.
  • A visit done fully offline (check-in, checklist, 2 photos, report, end) is replayed after reconnection in order and BO-25 shows the original device times (occurredAt) and the reception times.

Data — Visit, VisitType, ChecklistTemplate, VisitChecklistItem, VisitPhoto, VisitReport, File, Reseller, Interaction, Tour, AuditLog, OutboxEvent, Setting.

Interfaces

Notes / open points — Tolerance (150 m), accuracy (100 m) and whether out-of-tolerance check-ins are allowed with a justification are D-06 (default: refused). The mock code follows the register and the lifecycles page (GPS_MOCK_LOCATION); GEO-03 still writes GPS_MOCK_LOCATION and must be aligned.

FLD-09 — Visit not carried out requires a reason

ReleasePrioritySourceAppsOwner tasks
V1MUSTcahier §4.5, §6.9DA · APISRV-21, DSH-08, MDA-05, DES-13

Statement — The system shall let the delegate mark a planned visit as not carried out only with a reason from the configured list, and shall make that reason visible to the back-office.

Rules

  1. Allowed from PLANNED, CHECKED_IN (arrived but the visit could not happen) or IN_PROGRESS (visit interrupted) — lifecycles; a DONE visit answers 409 VISIT_LOCKED.
  2. A reason code from the VISIT_NOT_DONE_REASON reference list is mandatory (422 NOT_DONE_REASON_REQUIRED). Proposed seed: Magasin fermé, Responsable absent, Refus de recevoir, Manque de temps, Adresse introuvable, Reporté à la demande du client, Autre. Items flagged "comment required" (at least Autre) need a comment of 5 to 300 characters (422 NOT_DONE_COMMENT_REQUIRED).
  3. The current position is attached when available (not required, no tolerance check) so the back-office can see where the decision was taken.
  4. Reporté à la demande du client proposes a follow-up date and creates a VISIT follow-up task (CRM-08) when the delegate confirms it.
  5. A NOT_DONE visit can still be checked in later while the same tour is IN_PROGRESS (the delegate came back); the reason stays in its history. Once the tour is closed it is final. Works offline (queued with occurredAt).
  6. Unvisited stops can also receive their reasons in bulk at closing (FLD-12); the same list and rules apply.
  7. Back-office: BO-24 filters by not-done reason and shows the reason breakdown per delegate and period; not-done visits count as planned-not-done in tour performance.

Acceptance criteria

  • Marking a visit not done without reason → 422 NOT_DONE_REASON_REQUIRED; with Autre and no comment → 422 NOT_DONE_COMMENT_REQUIRED; with Magasin fermé → NOT_DONE, reason shown on BO-24 and BO-25.
  • Given a visit marked Magasin fermé at 10:05, when the delegate comes back at 16:00 during the same tour and checks in, the visit becomes CHECKED_IN and the not-done reason stays in its history; marking a DONE visit not done → 409 VISIT_LOCKED.
  • A not-done visit recorded offline at 10:05 shows 10:05 as decision time in the back-office after synchronisation.

Data — Visit, ReferenceItem (VISIT_NOT_DONE_REASON), CrmTask.

Interfaces

FLD-10 — Structured visit report and follow-up

ReleasePrioritySourceAppsOwner tasks
V1MUSTcahier §6.8DA · API · BOSRV-21, DSH-08, MDA-06, DES-13

Statement — The system shall capture a structured report for a visit (person met, interest, products and promotions presented, issues, next action, follow-up date, comments, attachments), shall make it visible on the point of sale's record, and shall create or update the follow-up task the report plans.

Rules

  1. Fields (reference screen Rapport de visite):

    FieldRule
    Person met — namerequired, 2 to 80 characters
    Person met — rolefrom the PERSON_ROLE list (e.g. Gérant, Propriétaire, Vendeur)
    Interest levelrequired, InterestLevel (LOW / MEDIUM / HIGH)
    Products presentedoptional, multi-select of products or categories
    Promotions presentedtoggle; when on, at least one active promotion selected
    Issues reportedoptional, multi-select from VISIT_ISSUE_TAG (e.g. Rupture de chargeurs, Demande écouteurs)
    Next actionrequired, NextAction
    Follow-up daterequired when next action is not NONE; between the visit's business day and +90 days (422 FOLLOW_UP_DATE_OUT_OF_RANGE)
    Commentsoptional, ≤ 1 000 characters
    Attachmentsoptional, up to 5 files (images as VISIT_PHOTO, PDF as STORE_DOCUMENT)
  2. The visit type decides whether the report is mandatory before Terminer (FLD-08, REPORT_REQUIRED) and which optional fields are shown (FLD-16); required fields above stay required whenever a report is saved (§6.8 « Les champs affichés peuvent dépendre du type de visite »).

  3. The report has a client-generated id; delegate.visits.report is an upsert (saving twice updates the same VisitReport). It can be saved while the visit is CHECKED_IN or IN_PROGRESS, and after DONE only during an unlock window. « Enregistrer » saves; « Terminer la visite » saves then ends.

  4. Follow-up creation: when next action is not NONE, the server creates exactly one CrmTask linked to the report — type mapped PHONE_FOLLOW_UP→CALL, NEW_VISIT→VISIT, SEND_CATALOG→SEND_CATALOG, WHATSAPP_MESSAGE→WHATSAPP; assignee: the point of sale's assigned delegate (the author by default); due at 09:00 Africa/Algiers on the follow-up date; status OPEN. Updating the report updates that task (never a second one); setting next action to NONE cancels it if still OPEN; a task already DONE is left untouched and a new one is created only if the next action changes.

  5. The report emits visit.report_saved, used by the CRM lifecycle automation (CRM-04) — for example a pending follow-up sets À relancer.

  6. The report is visible on the point of sale's sheet (DA-09), in the reseller 360° (BO-11) and on BO-25; the follow-up appears in DA-19 and BO-14 and its reminder is sent on the due date (notification matrix).

Acceptance criteria

  • Given a report with next action Relance téléphonique and follow-up date 29/05, then one OPEN task of type CALL due 29/05 09:00 is assigned to the delegate and listed on DA-19 (§12 scenario Rapport).
  • Saving the report again with date 30/05 moves the same task (task count unchanged); switching next action to Aucune cancels it.
  • Next action set without date → 422 FOLLOW_UP_DATE_REQUIRED; date 120 days ahead → 422 FOLLOW_UP_DATE_OUT_OF_RANGE; missing interest level → 400 VALIDATION_FAILED.
  • A report saved offline appears on BO-11 after synchronisation with its original time.

Data — VisitReport, Visit, VisitType, CrmTask, Interaction, Product, Promotion, ReferenceItem (PERSON_ROLE, VISIT_ISSUE_TAG), File.

Interfaces

FLD-11 — Field sign-up of a point of sale

ReleasePrioritySourceAppsOwner tasks
V1MUSTcahier §6.5DA · APISRV-21, MDA-07, DES-14

Statement — The system shall let a delegate create a prospect or reseller record in the field, with GPS position and façade photo, even without network, linked to the creating delegate and pending back-office validation, without creating duplicates.

Rules

  1. Fields (reference screen Nouveau revendeur): store name*, owner name*, phone* (normalised to E.164), WhatsApp, wilaya*, commune*, address*, business type* (BUSINESS_TYPE), potential* (Potential), GPS position*, façade photo (required while field.signupFacadePhotoRequired is on), initial status Prospect (NEW_PROSPECT) or Intéressé (INTERESTED). Compte créé and Revendeur actif are reached automatically, never chosen (CRM-04).
  2. Communes offered are those of the delegate's zones; a commune outside them answers 403 OUT_OF_SCOPE (ACL-03).
  3. GPS capture: a fix with accuracy ≤ field.gpsMaxAccuracyMeters, not mocked, in the GEO-03 format; shown as « Position capturée 35.6969° N, 0.6331° E ».
  4. Duplicate check: online, the app calls delegate.resellers.checkPhone when the phone field loses focus and blocks with « Ce numéro est déjà enregistré »; offline, the record is queued and the server checks at replay. A duplicate at replay comes back from sync.batch as REJECTED with PHONE_ALREADY_EXISTS (CRM-03, SYN-05): no record is created; the sync centre keeps the form so the delegate can correct the phone or discard it; when the existing record is outside the delegate's scope no detail about it is revealed (CRM-03).
  5. The record uses a client-generated UUIDv7 id (idempotent upsert) and gets its REV-… number from the server; until then the app shows « Numéro attribué à la synchronisation ».
  6. Created with source DELEGATE_APP, creating delegate, assigned delegate = creator, validation status PENDING; it appears in the CRM with source, delegate and position (§6.5 acceptance criterion) and in the validation queue (FLD-14). The façade photo is stored as a ResellerPhoto of kind FACADE.
  7. If created during a visit flow (ad-hoc stop), the new point of sale is attached to the current tour as an ad-hoc visit.

Acceptance criteria

  • Given network available and the phone 0555 12 34 56 already registered, the form blocks at the phone field and nothing is created.
  • Given airplane mode, when the delegate saves a complete form, then the record appears in the local prospects list with a pending icon; after reconnection it appears in BO-09 with source Application délégué, the delegate's name and the position, and in the BO-13 queue as PENDING (§12 scenario Prospect: no duplicate).
  • The same queued creation replayed twice creates one record (REPLAYED on the second).
  • A queued creation whose phone was registered meanwhile returns REJECTED / PHONE_ALREADY_EXISTS and is shown in the sync centre with the correction options.
  • Saving without façade photo (setting on) or with a fix of ± 150 m is refused on the device and by the server (422 PHOTO_REQUIRED, 422 GPS_ACCURACY_TOO_LOW); a phone already registered online answers 409 PHONE_ALREADY_EXISTS.

Data — Reseller, ResellerPhoto, ResellerAssignment, ResellerStatusChange, File, Commune, DelegateZone, NumberSequence.

Interfaces

FLD-12 — Tour closing and final report

ReleasePrioritySourceAppsOwner tasks
V1MUSTcahier §6.9DA · API · BOSRV-21, DSH-08, MDA-10, DES-14

Statement — The system shall let the assigned delegate close a tour only when every stop is resolved (visited, or not done with a reason) and all field data is synchronised, shall then produce the final day report for the back-office, and shall make the closing definitive unless an authorised user reopens the tour.

Rules

  1. Day summary (reference screen Clôture de tournée), returned by delegate.tours.closingPreview and frozen at closing: visits done / planned, new points of sale, app installs, first orders, orders, revenue (definitions of FLD-02 restricted to the tour's business day), kilometres, conversion rate (FLD-05 rule 4), objective achievement, not-done visits with reasons.
  2. Kilometres = path length of GEO-03 rule 6 over the tour's retained points (start position, location pings, check-ins, closing position) ordered by occurredAt: points with accuracy above field.gpsMaxAccuracyMeters or implying more than 150 km/h from the previous kept point are skipped; one decimal. It is an estimate (straight lines between samples).
  3. Closing guards, checked in this order by delegate.tours.close:
    1. the tour belongs to the caller (404 NOT_FOUND);
    2. tour is IN_PROGRESS or SUSPENDED (409 TOUR_CLOSED if COMPLETED, 409 TOUR_CANCELLED, 409 TOUR_NOT_IN_PROGRESS if not started);
    3. otherwise 409 TOUR_CLOSING_BLOCKED with details.blockingItems, each item carrying a code and the visit ids concerned: VISIT_IN_PROGRESS (a visit still CHECKED_IN or IN_PROGRESS); NOT_DONE_REASON_REQUIRED (a stop still PLANNED without a reason, neither recorded nor in the request's notDone list — FLD-09 rules apply); UNSYNCED_DATA (with field.closingRequiresSync: the device's pending-item count for the tour, sent in the request, is not 0, or a photo or attachment referenced by the tour's visits is not fully uploaded).
  4. Closing needs connectivity: the button is disabled offline (« Connexion requise pour clôturer ») and while the sync centre holds items for the tour (« 3 éléments en attente de synchronisation »). The end-of-day comment is optional (≤ 1 000 characters).
  5. Effects: tour → COMPLETED, closing time and position recorded, summary frozen as the final report, location sampling stopped, event tour.closed to the back-office stream, final report visible on BO-23; daily aggregates recomputed (§6.9 acceptance criterion « Le back-office reçoit le bilan complet et les indicateurs sont recalculés »). The app shows « Rapport envoyé ».
  6. Definitive: after COMPLETED, every visit or tour mutation answers 409 TOUR_CLOSED.
  7. Reopening (admin.tours.reopen, field.validate, reason required, within field.reopenMaxDays — 409 REOPEN_WINDOW_EXPIRED): tour → IN_PROGRESS, the delegate is notified, corrections become possible (missing reasons, report during an unlock window, pending items blocked by TOUR_CLOSED can be retried), location sampling does not restart for a past day, and the delegate must close again; the new summary replaces the previous one, both kept in history.

Acceptance criteria

  • Given 10 stops — 8 DONE, 2 PLANNED — closing without reasons → 409 TOUR_CLOSING_BLOCKED with a NOT_DONE_REASON_REQUIRED item listing the 2 visits; with Magasin fermé for both in notDone → COMPLETED and BO-23 shows 8/10 visits and the reasons.
  • A visit still IN_PROGRESS → 409 TOUR_CLOSING_BLOCKED with a VISIT_IN_PROGRESS item.
  • Two photos still uploading → the app disables « Terminer la tournée »; the API answers 409 TOUR_CLOSING_BLOCKED with an UNSYNCED_DATA item if called.
  • After closing, adding a note to a visit of the tour → 409 TOUR_CLOSED; after an authorised reopening the note is accepted and a second closing is required (§12 scenario Tournée).
  • Reopening a tour closed 10 days ago → 409 REOPEN_WINDOW_EXPIRED.

Data — Tour, TourStatusChange, Visit, VisitPhoto, LocationPing, Objective, Order, Invitation, Reseller, ReferenceItem, OutboxEvent, AuditLog.

Interfaces

FLD-13 — Live follow-up in the back-office

ReleasePrioritySourceAppsOwner tasks
V1MUSTcahier §4.5, §6.4BO · APISRV-21, SRV-26, DSH-08, MDA-12, DES-19

Statement — The system shall show authorised back-office users, live, which delegates are on tour, their last known position and trail, and the progress of their visits.

Rules

  1. BO-06 live map: one marker per delegate whose tour is IN_PROGRESS or SUSPENDED, at the last accepted position, with name, tour progress (done / planned), current visit and position age. A marker turns grey when the position is older than 3 × field.locationIntervalSeconds (15 minutes by default) and shows « Suspendue » for a suspended tour.
  2. BO-23 tour detail: trail polyline from the location pings (admin.tours.track), check-in markers coloured by tolerance status with distance, visit timeline (planned slot vs actual times), photos and reports as they arrive.
  3. Live updates use the back-office SSE stream (SYN-07): tour.started, visit.checked_in, visit.completed, tour.closed, delegate.position (throttled to one event per delegate per 60 seconds).
  4. Access: field.view; the Direction role sees it read-only. Positions are shown only within the location policy (FLD-15): nothing is collected or displayed outside an active tour, and trails older than field.locationRetentionDays return an empty trail marked as purged.
  5. Latency target: an online check-in or position appears on the live map within 5 seconds (p95) of being received by the server.

Acceptance criteria

  • Given delegate A starts a tour, A's marker appears on BO-06 within 5 seconds; after A's check-in at stop 1, BO-23 shows the check-in with distance and tolerance badge without reloading.
  • Given A's last ping 20 minutes ago, the marker is grey with « il y a 20 min ».
  • Given a tour from 4 months ago, admin.tours.track returns an empty trail flagged as purged while check-ins and the summary remain.
  • A user without field.view gets 403 PERMISSION_DENIED on admin.live.delegates and receives no field events on the stream.

Data — LocationPing, Tour, Visit, DelegateProfile, OutboxEvent.

Interfaces

FLD-14 — Report analysis and validation of new points of sale

ReleasePrioritySourceAppsOwner tasks
V1MUSTcahier §4.5BOSRV-21, DSH-08

Statement — The system shall let back-office users analyse visit reports across delegates and periods, and validate or reject the points of sale created in the field.

Rules

  1. Report analysis on BO-24 / BO-25: filters by delegate, zone, period, visit type, interest level, issue tag, next action and flags (Hors tolérance, Écart de tolérance, Visite courte); aggregates for the filtered set: visits by interest level, top 10 issue tags, next actions planned and follow-ups overdue. Rows open the visit detail; exports follow ANA-05.
  2. Validation of new points of sale happens in the account validation queue (BO-13, crm.validate, CRM-09; who validates is D-30): field-created records arrive with validation status PENDING and show the façade photo, the captured position on a map with the commune, the creating delegate, the first visit report if any, and duplicate hints (same phone digits, similar store name within 100 m).
  3. Approve → APPROVED; reject → REJECTED with a mandatory reason; the creating delegate is notified in both cases (FIELD). A rejected record stays in the CRM (history) and is excluded from the delegate's SIGNUPS objective.
  4. Validating the point of sale is distinct from activating a reseller account: a field-created prospect may be approved long before its owner signs up (AUTH-05).

Acceptance criteria

  • Given 3 field sign-ups yesterday, they appear in BO-13 with photo, map and delegate; approving one notifies the delegate and sets APPROVED; rejecting one without reason fails with 400 VALIDATION_FAILED.
  • Filtering BO-24 on issue tag Rupture de chargeurs over the last month shows the matching visits and the tag count matches the aggregate.
  • A rejected sign-up no longer counts in the delegate's SIGNUPS achievement.

Data — VisitReport, Visit, Reseller, ResellerPhoto, ReferenceItem, Notification, AuditLog.

Interfaces

FLD-15 — Location policy: consent, frequency, tolerance, retention

ReleasePrioritySourceAppsOwner tasks
V1MUSTcahier §8, §10API · DA · BOSRV-21, MOB-10, MDA-11, MDA-12, MOB-13

Statement — The system shall collect delegates' positions only within a configurable, transparent policy — explicit consent, collection limited to active tours, configurable frequency, tolerance and retention — and shall make that policy visible to the delegate at any time.

Rules

  1. What is collected and when:

    MomentDataCondition
    Tour start and closingone positionif permission granted
    Check-inone position (required)FLD-08
    Field sign-upthe store's positionFLD-11
    Visit photocapture positionif available
    Position samples (LocationPing)lat, lng, accuracy, speed, occurredAtonly while the delegate's tour of the current business day is IN_PROGRESS

    Nothing is collected while the tour is SUSPENDED, after closing, after midnight, or when no tour is in progress.

  2. Sampling: a sample is taken when field.locationIntervalSeconds have elapsed or field.locationDistanceMeters have been travelled since the last sample, whichever comes first; samples with accuracy above field.gpsMaxAccuracyMeters are dropped on the device. Samples are uploaded in batches (sync.locationPings, up to 200 per call) every 10 samples or 15 minutes, and kept on the device while offline (up to 72 hours, the occurredAt limit).

  3. The server discards (without error, counted in the response) samples whose occurredAt falls outside an IN_PROGRESS period of the tour, so a late batch never creates positions outside the policy.

  4. Android: sampling runs in a foreground service of type location started with the tour, with a persistent notification « HOCO Délégué — localisation active pendant la tournée »; the app asks for location permission "while using the app" and does not request background location in V1 (D-24 option 1; Play declaration in MOB-14).

  5. Consent (DA-04): at first sign-in and whenever field.locationPolicyVersion changes, the app shows the notice (what, when, how often, who sees it — commercial admins and Direction —, retention, contact for questions) and records acceptance with version and time on the delegate's profile (SEC-07). Without a current consent, starting a tour answers 409 LOCATION_CONSENT_REQUIRED; the other features stay available.

  6. Withdrawal: in DA-26 the delegate can withdraw consent; sampling stops at once, tours can no longer be started, and the delegate's profile shows « Consentement retiré » in the back-office.

  7. Transparency: DA-26 shows whether sampling is active, the last sample time, the current frequency, tolerance and retention values, and the full notice.

  8. Retention: LocationPing rows older than field.locationRetentionDays are deleted by the nightly job (02:00); tour summaries (kilometres) and visit check-in positions are business records kept with the visit (retention per SEC-08).

  9. Changes to the policy settings are audited; changing frequency or tolerance takes effect on devices at their next appConfig.get or sync.delta.

  10. Battery target: sampling adds at most 4 % battery per hour on the reference mid-range phone over a 6-hour tour (measured in MOB-13).

Acceptance criteria

  • Given a delegate without consent, starting a tour → 409 LOCATION_CONSENT_REQUIRED; after accepting the notice (version 2026-11), the start succeeds and the consent time and version are visible on BO-17.
  • During an IN_PROGRESS tour with a stationary phone, one sample is recorded about every 5 minutes; driving 1 km in 2 minutes records about 5 samples (200 m trigger).
  • After suspending the tour, no sample is recorded; a batch containing samples taken during the suspension is accepted with those samples counted as discarded.
  • Given the setting changed to 600 s, the device samples every 10 minutes after its next configuration refresh.
  • Pings older than 90 days are absent the day after they expire; the related tour still shows its kilometres.

Data — LocationPing, DelegateProfile (consent version and time), Tour, Setting, AuditLog.

Interfaces

Notes / open points — Frequency and visibility are D-07, the Android mechanism D-24, retention D-11. How consent is transmitted to the server is not yet an operation of endpoints.json (proposal: a field of me.update).

FLD-16 — Visit types and checklist templates

ReleasePrioritySourceAppsOwner tasks
V1SHOULDcahier §6.4, §6.8BO · APISRV-21, DSH-08

Statement — The system shall let administrators configure visit types — their photo, report and checklist requirements and the report fields shown — and the checklist templates they use.

Rules

  1. A VisitType has: code (immutable), label (fr, optional ar/en), minimum photos (0 to 10), report required (yes/no), optional report fields shown (products, promotions, issues, attachments), a ChecklistTemplate (optional), active flag.
  2. A ChecklistTemplate has 1 to 15 ordered items, each with a label (≤ 80 characters) and a required flag. Proposed seed from the reference screen: Présenter les accessoires HOCO, Montrer les nouveautés HOCO, Aider à choisir les accessoires, Parler des promotions en cours, Aider à la 1ère commande HOCO.
  3. Proposed seed of visit types: Prospection (1 photo, report required), Suivi revendeur (0 photo, report required), Merchandising / présentoir (2 photos, report optional), Aide à la première commande (0 photo, report required).
  4. Editing a type or template never changes visits already checked in: their requirements and checklist items were frozen at check-in (FLD-08 step 13). Planned visits pick up the new configuration.
  5. Types and templates in use are deactivated, never deleted; inactive types cannot be chosen for new stops. Permission field.administer; changes audited; devices receive them through sync.delta.

Acceptance criteria

  • Changing Prospection to 2 photos: a visit already CHECKED_IN still ends with 1 photo; a visit checked in afterwards requires 2 (422 VISIT_REQUIREMENTS_NOT_MET, PHOTO_REQUIRED, with 1).
  • Deleting a type used by past visits is refused; deactivating it removes it from the stop editor.
  • A template with 16 items → 400 VALIDATION_FAILED.

Data — VisitType, ChecklistTemplate, VisitChecklistItem, Visit, AuditLog.

Interfaces

Notes / open points — Seed visit types and checklists are proposals to validate with HOCO's sales management.

FLD-17 — Recommended visit order

ReleasePrioritySourceAppsOwner tasks
V1SHOULDcahier §4.5, §6.2API · BOSRV-21, DSH-08

Statement — The system shall propose a visiting order for a tour's stops using a nearest-neighbour heuristic from the start point, which the planner can apply or ignore.

Rules

  1. Start point: the delegate's configured start point; otherwise the first stop in the current order.
  2. Algorithm: repeatedly pick the closest unplaced stop (Haversine distance) from the last placed point; ties broken by HIGH priority first, then store name. Stops without coordinates keep their relative order at the end and are flagged Position manquante. Time slots are not considered in V1 (routing with time windows is FLD-18).
  3. In the back-office the result is a proposal: BO-22 shows the current and proposed order with the straight-line total distance of each; Appliquer saves it through admin.tours.setStops and sets the tour's ordering mode to RECOMMENDED unless the planner keeps IMPOSED.
  4. In the delegate app, « Réordonner au plus proche » runs the same algorithm on the device from the current position over the remaining PLANNED stops (RECOMMENDED tours only) and saves the order through delegate.tours.reorder.
  5. The computation answers in under 500 ms for 30 stops.

Acceptance criteria

  • Given 5 stops on a line A–B–C–D–E entered in the order E, A, D, B, C and a start point near A, the proposal is A, B, C, D, E and its total distance is lower than or equal to the current one.
  • A stop without coordinates is placed last with Position manquante.
  • On an IMPOSED tour the delegate app does not offer the action.

Data — Tour, Visit, Reseller, DelegateProfile.

Interfaces

FLD-18 — Automatic tour optimisation (V2)

ReleasePrioritySourceAppsOwner tasks
V2COULDcahier §14.2API · BOSRV-37, MDA-20

Statement — The system should compute optimised tour orders with a routing engine that uses road distances, travel times and the stops' time slots.

Rules

  1. Inputs: stops with coordinates, time slots, estimated visit duration per visit type, start point, working hours; output: ordered stops with estimated arrival times and total road distance and duration.
  2. The engine is an external routing service or library chosen in V2 (cost and quotas validated by HOCO as for INT-07); V1's nearest-neighbour (FLD-17) remains the fallback when the engine is unavailable.
  3. The delegate app shows the optimised route and estimated times (MDA-20).

Acceptance criteria

  • For a reference set of 20 stops, the optimised order's road distance is at least 10 % shorter than the nearest-neighbour order, and every stop with a slot is reached within its slot when feasible.

Data — Tour, Visit, VisitType.

Interfaces — None in V1.

FLD-19 — Delegate reports history and performance

ReleasePrioritySourceAppsOwner tasks
V1MUSTcahier §6.1, §6.9DA · APISRV-21, MDA-02, MDA-10

Statement — The system shall let each delegate consult their own past tours, visit reports and tour reports, and their performance over selectable periods.

Rules

  1. Periods: today, this week, this month, last month, custom range of at most 92 days; history is available for the last 12 months in the app (older data in the back-office).
  2. Metrics (definitions of FLD-02 and FLD-05): visits done / planned, not-done rate with reasons, field sign-ups, app installs, accounts created, first orders, orders, revenue, kilometres, conversion rate, average visit duration, and achievement of each objective of the period.
  3. History: tours calendar with status and summary (DA-07); visit reports searchable by point of sale and date; tour final reports (DA-21).
  4. Scope: a delegate only sees their own data (delegate scope); the same figures appear for the back-office on BO-17.
  5. Offline: the last loaded figures stay visible with « Mis à jour il y a 2 h »; today's figures are computed locally as on the home.

Acceptance criteria

  • Selecting Ce mois-ci shows the same visits, sign-ups and revenue as BO-17 for that delegate and month.
  • A custom range of 120 days → 400 VALIDATION_FAILED (maximum 92 days).
  • Delegate A cannot obtain delegate B's reports: delegate.reports only returns A's.

Data — Tour, Visit, VisitReport, Objective, Order, Invitation, Reseller.

Interfaces

On this page