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).
| ID | Requirement | Release | Priority | Source | Apps |
|---|---|---|---|---|---|
FLD-01 | Delegate accounts and profiles; assignment of wilayas, communes and points of sale | V1 | MUST | §4.5 | API · BO · DA |
FLD-02 | Objectives per delegate and period: visits, sign-ups, app installs, orders, revenue | V1 | MUST | §4.5 | API · BO · DA |
FLD-03 | Tour planning: daily, weekly or monthly; ordered stops (imposed or recommended); priorities and time slots | V1 | MUST | §4.5, §6.2 | API · BO |
FLD-04 | Tour lifecycle (planned, to start, in progress, suspended, completed, cancelled); only the assigned delegate starts it | V1 | MUST | §4.5, §6.1, §15.3 | API · DA · BO |
FLD-05 | Delegate home: today's tour, counters, objectives, conversion rate, quick access | V1 | MUST | §6.1 | DA · API |
FLD-06 | Tour programme: list and map show the same visits in the same order; filters, delays, priorities | V1 | MUST | §6.2 | DA · API |
FLD-07 | Map and navigation: position, next destination with ETA and distance, external GPS navigation, arrival confirmation within tolerance | V1 | MUST | §6.3 | DA · API |
FLD-08 | Visit and check-in: time and position at check-in, duration, checklist, note, photos (mandatory by visit type), call; finished visit locked | V1 | MUST | §6.4 | DA · API · BO |
FLD-09 | A visit not carried out requires a reason | V1 | MUST | §4.5, §6.9 | DA · API |
FLD-10 | Structured visit report (person met, interest, products and promotions presented, issues, next action, follow-up date, attachments) that triggers the follow-up | V1 | MUST | §6.8 | DA · API · BO |
FLD-11 | Field reseller sign-up with GPS and façade photo, offline-capable, linked to the creating delegate, pending validation | V1 | MUST | §6.5 | DA · API |
FLD-12 | Tour closing: day summary, comment, objectives and conversion, final report; requires reasons and synced data; definitive unless reopened | V1 | MUST | §6.9 | DA · API · BO |
FLD-13 | Live follow-up in the back-office: delegates on tour, positions, visit progress | V1 | MUST | §4.5, §6.4 | BO · API |
FLD-14 | Back-office analysis of visit reports and validation of new points of sale | V1 | MUST | §4.5 | BO |
FLD-15 | Location policy: consent, frequency, tolerance and retention configurable and transparent | V1 | MUST | §8, §10 | API · DA · BO |
FLD-16 | Visit types and checklist templates configuration | V1 | SHOULD | §6.4, §6.8 | BO · API |
FLD-17 | Recommended visit order (nearest-neighbour heuristic) | V1 | SHOULD | §4.5, §6.2 | API · BO |
FLD-18 | Automatic tour optimisation (routing engine) | V2 | COULD | §14.2 | API · BO |
FLD-19 | Delegate reports history and own performance over periods | V1 | MUST | §6.1, §6.9 | DA · 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.
| Key | Default | Meaning |
|---|---|---|
field.gpsToleranceMeters | 150 (to confirm) | Maximum distance between the check-in fix and the point of sale's stored coordinates. |
field.gpsMaxAccuracyMeters | 100 (to confirm) | A fix whose reported accuracy radius is larger is refused for check-in and sign-up capture, and dropped from pings. |
field.allowOutOfToleranceCheckIn | false | When true, an out-of-tolerance check-in is accepted with a mandatory justification and flagged. |
field.locationIntervalSeconds | 300 (to confirm) | Time trigger for a position sample while a tour is IN_PROGRESS. |
field.locationDistanceMeters | 200 (to confirm) | Distance trigger for a position sample (whichever trigger comes first). |
field.locationRetentionDays | 90 (to confirm) | Retention of LocationPing rows; older rows are purged nightly. |
field.reportRequiredToEndVisit | true | Default "report required" flag of new visit types (FLD-16). |
field.closingRequiresSync | true | The tour can only be closed when the device's queue for it is empty (FLD-12). |
field.reopenMaxDays | 7 | A completed tour can be reopened up to this many days after its date. |
field.visitUnlockHours | 24 | Correction 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.maxStopsPerTour | 30 (proposed) | Maximum number of stops in one tour. |
field.shortVisitFlagSeconds | 120 (proposed) | Finished visits shorter than this are flagged for review (never blocked). |
field.signupFacadePhotoRequired | true (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
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
- A delegate is a
Userof typeDELEGATEholding theDELEGATErole, with exactly oneDelegateProfile: 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). - 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). - 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 answers422 DELEGATE_HAS_NO_ZONE. - 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). - 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.
- Suspending or disabling a delegate (SEC-06) revokes their sessions, lists their
PLANNED/TO_STARTtours 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. - 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.
- Every creation, zone change and status change is written to the
AuditLog; a zone change notifies the delegate (categoryFIELD).
Acceptance criteria
- Given a commercial admin with
field.create, when they create a delegate with phone+213555123456and 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 withoutfield.creategets403 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.listand B'sdelegate.resellers.geton P answers404 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
401and the app shows the suspended-account message (AUTH-02).
Data — User, UserRole, DelegateProfile, DelegateZone, Zone, ZoneArea, Wilaya, Commune, ResellerAssignment, Session, AuditLog.
Interfaces
- Screens: DA-24 Profile hub · DA-25 My zone · BO-16 Delegates list · BO-17 Delegate detail & performance · BO-18 Delegate create / edit
- Endpoints:
delegate.profile·admin.delegates.crud— related:admin.zones.crud,admin.resellers.assign
FLD-02 — Objectives per delegate and period
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
-
An
Objectiveis (delegate,ObjectivePeriodDAY/WEEK/MONTH, period start date,ObjectiveMetric, target). Weeks start on Sunday (working week Sunday–Thursday); months are calendar months. Targets are positive integers;REVENUEis in centimes of DZD. -
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). -
Once the period has ended, an objective is read-only (
409 OBJECTIVE_PERIOD_CLOSED) except for users holdingfield.administer; the change is audited. -
Achievement is computed by the server for the delegate's own activity, with business dates in
Africa/Algiers:Metric Counted Date used VISITSVisits in status DONEon 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 CANCELLEDorREFUSEDsubmission 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 -
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.
-
When no
DAY/VISITSobjective 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) ». -
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/VISITSobjective 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 with400 VALIDATION_FAILED. - Given an order of 125 000,00 DA counted in A's
REVENUEtoday, 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.administerfails with409 OBJECTIVE_PERIOD_CLOSED.
Data — Objective, Visit, Tour, Reseller, Invitation, InvitationEvent, Order, Setting.
Interfaces
- Screens: DA-05 Home · DA-22 Objectives · BO-17 Delegate detail & performance · BO-20 Objectives
- Endpoints:
delegate.objectives·admin.delegates.performance·admin.objectives.crud
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
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
- A
Touris one delegate, one business date and an ordered list of stops (Visitrecords in statusPLANNED); it receives a numberTRN-2026-000045at creation. - 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.
- A delegate has at most one non-cancelled tour per date: a second one answers
409 TOUR_DATE_TAKENwith the existing tour number indetails. - A tour has 1 to
field.maxStopsPerTourstops. Each stop carries: the point of sale (in the delegate's scope at planning time, otherwise403 OUT_OF_SCOPE), aVisitType(default: prospection for prospects, follow-up for active resellers — FLD-16), aVisitPriority(NORMALorHIGH), an optional time slot (start and endHH: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). TourOrderingMode:RECOMMENDED(default) lets the delegate reorder the remaining stops;IMPOSEDforbids 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.- Edit rights by tour status:
PLANNED/TO_START— date, mode, notes and stops;IN_PROGRESS/SUSPENDED— only stops stillPLANNEDmay be added, moved or removed (a removed stop becomesCANCELLED); stops in any other status are immutable (409 VISIT_LOCKED);COMPLETED/CANCELLED— nothing (409 TOUR_NOT_EDITABLE). The date cannot change once the tour isTO_START. - 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.deltaimmediately (§6.2: « Une visite ajoutée ou déplacée doit être synchronisée »). - 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 with422 DUPLICATE_STOP; adding a point of sale assigned to another delegate fails with403 OUT_OF_SCOPE. - Given a tour
IN_PROGRESSwith stop 2DONE, removing stop 2 fails with409 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
IMPOSEDtour,delegate.tours.reorderfails with409 TOUR_ORDER_IMPOSED.
Data — Tour, TourStatusChange, Visit, VisitType, Reseller, DelegateProfile, NumberSequence, OutboxEvent, Notification.
Interfaces
- Screens: DA-07 Tours calendar & history · BO-21 Tour planner · BO-22 Tour editor
- Endpoints:
delegate.tours.list·delegate.tours.reorder·admin.tours.list·admin.tours.create·admin.tours.update·admin.tours.setStops
FLD-04 — Tour lifecycle
| Release | Priority | Source | Apps | Owner tasks |
|---|---|---|---|---|
| V1 | MUST | cahier §4.5, §6.1, §15.3 | API · DA · BO | SRV-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
-
Transitions, actors and guards:
From To Actor Guards (checked in this order) Effects PLANNEDTO_STARTSystem job at 00:05 tour date is today Start button enabled TO_STARTIN_PROGRESSAssigned delegate tour belongs to the caller (another delegate's tour answers 404 NOT_FOUND, ACL-03); status isTO_START(409 TOUR_NOT_STARTABLEfor a completed, cancelled or already started tour); theAfrica/Algiersdate ofoccurredAtis the tour date (409 TOUR_NOT_TODAY); no other tour of the delegate isIN_PROGRESSorSUSPENDED(409 TOUR_ALREADY_IN_PROGRESS); current location consent (FLD-15,409 LOCATION_CONSENT_REQUIRED)start time and position recorded, location sampling starts, tour.startedeventIN_PROGRESSSUSPENDEDAssigned delegate reason from the TOUR_SUSPEND_REASONlist; no visitCHECKED_INorIN_PROGRESS(409 VISIT_IN_PROGRESS)sampling stops SUSPENDEDIN_PROGRESSAssigned delegate tour not closed sampling resumes (only during the tour's business day) IN_PROGRESS,SUSPENDEDCOMPLETEDAssigned delegate closing guards of FLD-12 final report PLANNED,TO_START,IN_PROGRESS,SUSPENDEDCANCELLEDBack-office, field.updatereason (text, 5 to 300 characters) PLANNEDstops becomeCANCELLED; finished visits are kept; delegate notifiedCOMPLETEDIN_PROGRESSBack-office, field.validatewithin field.reopenMaxDays(409 REOPEN_WINDOW_EXPIRED); reasonsee FLD-12 -
The start records
startedAt(the action'soccurredAt) and, when location permission is granted and a fix with accuracy ≤field.gpsMaxAccuracyMetersis obtained within 15 seconds, the start position; otherwise the start proceeds with the reason position unavailable recorded (§6.1: « selon les permissions GPS »). -
Offline, the app treats a
PLANNEDtour dated today as startable (it mirrors the 00:05 job) and queues the start with itsoccurredAt; the server checks the guards against the business day ofoccurredAt. -
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_STARTafter their date) and not closed (IN_PROGRESSorSUSPENDEDafter their date) — see the lifecycles page. A tour stillIN_PROGRESSat 21:00 is moved toSUSPENDED(reasonAUTO_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 ». -
Every transition writes a
TourStatusChange(from, to, actor,occurredAt,receivedAt, reason) and anOutboxEventthat 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 callsdelegate.tours.start, then the answer is404 NOT_FOUNDand the tour staysTO_START. - Given a tour dated tomorrow (
PLANNED), when A tries to start it, then the answer is409 TOUR_NOT_TODAYand 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 is409 TOUR_ALREADY_IN_PROGRESSand the app opens the closing of yesterday's tour. - Given A starts the tour with location permission denied, then the tour becomes
IN_PROGRESSwith start time recorded and no position, and BO-23 shows « Position de démarrage indisponible ». - Given a
TO_STARTtour never started, at 00:05 the next day it staysTO_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
- Screens: DA-06 Tour programme · BO-23 Tour live detail
- Endpoints:
delegate.tours.start·delegate.tours.suspend·delegate.tours.resume·admin.tours.cancel
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
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
- 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 (
VisitStatuslabel, En retard derived per FLD-06); quick-access tiles Tournée, Prospects, Rapports, Messages (unread badge); widgets Objectif du jour and Taux de conversion. - One tour action button, by status of today's tour:
TO_START(orPLANNEDdated 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). - 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.homerefreshes the server-side figures (objectives, conversion, unread counts) at app foreground and at most every 5 minutes. - 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 reachedACCOUNT_CREATEDor 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. - Objectif du jour uses the
DAY/VISITSobjective, or the number of stops of today's tour when none exists (FLD-02 rule 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_STARTwith 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
- Screens: DA-05 Home
- Endpoints:
delegate.home
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)
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
- 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. - 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. - En retard is derived on the device: a
PLANNEDstop of aTO_STARTorIN_PROGRESStour whose slot end has passed (Africa/Algiers); stops without a slot are never late (lifecycles).HIGHpriority stops carry the Prioritaire marker. - 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.
- Reorder (drag) is offered only on
RECOMMENDEDtours and only amongPLANNEDstops; it is saved throughdelegate.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. - 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
IMPOSEDtours too (outside the imposed sequence). A point of sale already on the tour cannot be added again (422 DUPLICATE_STOP). - 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
PLANNEDat 11:01, it shows En retard and the counter increases by 1. - Given an
IMPOSEDtour, no drag handle is shown and the API refuses a reorder with409 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
- Screens: DA-06 Tour programme
- Endpoints:
delegate.tours.today·delegate.tours.get·delegate.tours.reorder·delegate.tours.addVisit·admin.tours.setStops
FLD-07 — Map, navigation and arrival
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
- 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).
- Next destination = the first unresolved stop in tour order (the delegate can select another one on
RECOMMENDEDtours). 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 »). - « 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.
- « 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.
- 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.
- 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
- Screens: DA-08 Map & navigation · DA-28 System states
- Endpoints:
delegate.visits.arrive
FLD-08 — Visit and check-in
| Release | Priority | Source | Apps | Owner tasks |
|---|---|---|---|---|
| V1 | MUST | cahier §6.4 | DA · API · BO | SRV-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.
- Scope — the visit belongs to a tour of the caller, else
404 NOT_FOUND(ACL-03: only the assigned delegate acts on a tour). - Tour — the tour is
IN_PROGRESS; otherwise409 TOUR_NOT_IN_PROGRESS(PLANNED,TO_START,SUSPENDED),409 TOUR_CLOSED(COMPLETED) or409 TOUR_CANCELLED. - Visit — the visit is
PLANNED, orNOT_DONEwhile the same tour is stillIN_PROGRESS(the delegate came back later) (DONE→409 VISIT_LOCKED;CANCELLED→409 VISIT_CANCELLED; other →409 VISIT_INVALID_TRANSITION); on anIMPOSEDtour it is the lowest-position unresolved planned stop, ad-hoc visits excepted (409 VISIT_OUT_OF_ORDER); no other visit of the delegate isCHECKED_INorIN_PROGRESS(409 VISIT_IN_PROGRESS). - Time —
occurredAtpasses the plausibility rule of SYN-05 (422 OCCURRED_AT_OUT_OF_RANGE). - 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 answer400 VALIDATION_FAILED(LOCATION_OUT_OF_BOUNDS). - Freshness — the fix is at most 2 minutes older than the action's
occurredAt, else400 VALIDATION_FAILEDwith field codeLOCATION_STALE(the app takes a fresh fix). - Mock — a fix the OS flags as mocked answers
422 GPS_MOCK_LOCATION. - Accuracy gate —
accuracy≤field.gpsMaxAccuracyMeters, else422 GPS_ACCURACY_TOO_LOW(details:accuracyMeters,maxAccuracyMeters). The app keeps listening for up to 30 seconds for a better fix before giving this verdict. - Reference point — the point of sale's stored coordinates. If it has none, the check-in is accepted with
toleranceStatus = NO_REFERENCEand 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). - 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. - Out of tolerance — with
field.allowOutOfToleranceCheckIn = false:422 GPS_OUT_OF_TOLERANCE(details:distanceMeters,toleranceMeters,accuracyMeters), the visit staysPLANNEDand 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). Withtrue:outOfToleranceReason(10 to 300 characters) is required (422 OUT_OF_TOLERANCE_REASON_REQUIRED); the check-in is accepted withtoleranceStatus = OUT_OF_TOLERANCE, the visit is flagged Hors tolérance in BO-24 and the commercial admins receive aFIELDnotification. - 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. - 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; eventvisit.checked_into the back-office stream.
Rules (visit flow after check-in)
- « Commencer la visite » moves
CHECKED_IN→IN_PROGRESSand recordsstartedAt; « Terminer la visite » movesIN_PROGRESS→DONE. Duration =endedAt − startedAt, shown live (« Durée de la visite 00:12 »). Other transitions answer409 VISIT_INVALID_TRANSITION; timestamps must be ordered (check-in ≤ start ≤ end, else422 OCCURRED_AT_INCONSISTENT). - Checklist: the items of the visit type's
ChecklistTemplate, copied toVisitChecklistItemat check-in, each checked or not; saved as a whole (delegate.visits.checklist), any number of times before the end. - Quick note: 0 to 300 characters (counter 0/300), saved with
delegate.visits.note. - 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. - Call: the phone icon opens the dialer on the point of sale's phone (
tel:) and logs a call attempt (Interactionof typeCALL) on the point of sale's timeline. - End guards: when the frozen requirements are not met the server answers
422 VISIT_REQUIREMENTS_NOT_METwithdetails.missinglisting, in this order,PHOTO_REQUIRED(withrequiredandprovided),REPORT_REQUIRED(FLD-10) andCHECKLIST_INCOMPLETE(the unchecked required items). The app shows the same blocking reasons before sending. - Lock: at
DONEthe visit is locked; any later mutation answers409 VISIT_LOCKED(§6.4 « Une visite terminée ne peut être modifiée sans permission »). A user withfield.validatecan unlock it with a reason (admin.visits.unlock): the delegate may then edit checklist, note, photos and report forfield.visitUnlockHours; the visit re-locks at the next Terminer or when the window ends. Unlock and every corrected field are audited. - Finished visits shorter than
field.shortVisitFlagSecondsare flagged Visite courte in the back-office, never blocked. - On
DONE: eventvisit.completed, aVISITinteraction on the point of sale's timeline (CRM-07), home counters updated. - 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_INwithdistanceMeters = 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_TOLERANCEwithdistanceMeters = 158,toleranceMeters = 150; visit stillPLANNED; 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_METwithmissing=PHOTO_REQUIRED,REPORT_REQUIRED; with the photo but no report →missing=REPORT_REQUIRED; with both →DONE, thendelegate.visits.note→409 VISIT_LOCKED. - On an
IMPOSEDtour, checking in at stop 3 while stop 2 is stillPLANNED→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
- Screens: DA-10 Visit & check-in · BO-24 Visits list · BO-25 Visit detail
- Endpoints:
delegate.visits.get·delegate.visits.arrive·delegate.visits.start·delegate.visits.checklist·delegate.visits.note·delegate.visits.addPhoto·delegate.visits.end·admin.visits.list·admin.visits.get·admin.visits.unlock
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
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
- Allowed from
PLANNED,CHECKED_IN(arrived but the visit could not happen) orIN_PROGRESS(visit interrupted) — lifecycles; aDONEvisit answers409 VISIT_LOCKED. - A reason code from the
VISIT_NOT_DONE_REASONreference 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). - The current position is attached when available (not required, no tolerance check) so the back-office can see where the decision was taken.
- Reporté à la demande du client proposes a follow-up date and creates a
VISITfollow-up task (CRM-08) when the delegate confirms it. - A
NOT_DONEvisit can still be checked in later while the same tour isIN_PROGRESS(the delegate came back); the reason stays in its history. Once the tour is closed it is final. Works offline (queued withoccurredAt). - Unvisited stops can also receive their reasons in bulk at closing (FLD-12); the same list and rules apply.
- 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_INand the not-done reason stays in its history; marking aDONEvisit 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
- Screens: DA-11 Visit not done — reason · BO-24 Visits list
- Endpoints:
delegate.visits.notDone·admin.visits.list
FLD-10 — Structured visit report and follow-up
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
-
Fields (reference screen Rapport de visite):
Field Rule Person met — name required, 2 to 80 characters Person met — role from the PERSON_ROLElist (e.g. Gérant, Propriétaire, Vendeur)Interest level required, InterestLevel(LOW/MEDIUM/HIGH)Products presented optional, multi-select of products or categories Promotions presented toggle; when on, at least one active promotion selected Issues reported optional, multi-select from VISIT_ISSUE_TAG(e.g. Rupture de chargeurs, Demande écouteurs)Next action required, NextActionFollow-up date required when next action is not NONE; between the visit's business day and +90 days (422 FOLLOW_UP_DATE_OUT_OF_RANGE)Comments optional, ≤ 1 000 characters Attachments optional, up to 5 files (images as VISIT_PHOTO, PDF asSTORE_DOCUMENT) -
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 »). -
The report has a client-generated id;
delegate.visits.reportis an upsert (saving twice updates the sameVisitReport). It can be saved while the visit isCHECKED_INorIN_PROGRESS, and afterDONEonly during an unlock window. « Enregistrer » saves; « Terminer la visite » saves then ends. -
Follow-up creation: when next action is not
NONE, the server creates exactly oneCrmTasklinked to the report — type mappedPHONE_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:00Africa/Algierson the follow-up date; statusOPEN. Updating the report updates that task (never a second one); setting next action toNONEcancels it if stillOPEN; a task alreadyDONEis left untouched and a new one is created only if the next action changes. -
The report emits
visit.report_saved, used by the CRM lifecycle automation (CRM-04) — for example a pending follow-up sets À relancer. -
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
OPENtask of typeCALLdue 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
- Screens: DA-12 Visit report · BO-25 Visit detail
- Endpoints:
delegate.visits.report·delegate.visits.end·admin.visits.get
FLD-11 — Field sign-up of a point of sale
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
- 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 whilefield.signupFacadePhotoRequiredis on), initial status Prospect (NEW_PROSPECT) or Intéressé (INTERESTED). Compte créé and Revendeur actif are reached automatically, never chosen (CRM-04). - Communes offered are those of the delegate's zones; a commune outside them answers
403 OUT_OF_SCOPE(ACL-03). - 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 ». - Duplicate check: online, the app calls
delegate.resellers.checkPhonewhen 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 fromsync.batchasREJECTEDwithPHONE_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). - 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 ». - Created with source
DELEGATE_APP, creating delegate, assigned delegate = creator, validation statusPENDING; 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 aResellerPhotoof kindFACADE. - 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 56already 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 (
REPLAYEDon the second). - A queued creation whose phone was registered meanwhile returns
REJECTED/PHONE_ALREADY_EXISTSand 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 answers409 PHONE_ALREADY_EXISTS.
Data — Reseller, ResellerPhoto, ResellerAssignment, ResellerStatusChange, File, Commune, DelegateZone, NumberSequence.
Interfaces
- Screens: DA-14 New reseller
- Endpoints:
delegate.resellers.create— related:delegate.resellers.checkPhone,delegate.resellers.addPhoto
FLD-12 — Tour closing and final report
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
- Day summary (reference screen Clôture de tournée), returned by
delegate.tours.closingPreviewand 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. - 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 abovefield.gpsMaxAccuracyMetersor implying more than 150 km/h from the previous kept point are skipped; one decimal. It is an estimate (straight lines between samples). - Closing guards, checked in this order by
delegate.tours.close:- the tour belongs to the caller (
404 NOT_FOUND); - tour is
IN_PROGRESSorSUSPENDED(409 TOUR_CLOSEDifCOMPLETED,409 TOUR_CANCELLED,409 TOUR_NOT_IN_PROGRESSif not started); - otherwise
409 TOUR_CLOSING_BLOCKEDwithdetails.blockingItems, each item carrying a code and the visit ids concerned:VISIT_IN_PROGRESS(a visit stillCHECKED_INorIN_PROGRESS);NOT_DONE_REASON_REQUIRED(a stop stillPLANNEDwithout a reason, neither recorded nor in the request'snotDonelist — FLD-09 rules apply);UNSYNCED_DATA(withfield.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).
- the tour belongs to the caller (
- 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).
- Effects: tour →
COMPLETED, closing time and position recorded, summary frozen as the final report, location sampling stopped, eventtour.closedto 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é ». - Definitive: after
COMPLETED, every visit or tour mutation answers409 TOUR_CLOSED. - Reopening (
admin.tours.reopen,field.validate, reason required, withinfield.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 byTOUR_CLOSEDcan 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, 2PLANNED— closing without reasons →409 TOUR_CLOSING_BLOCKEDwith aNOT_DONE_REASON_REQUIREDitem listing the 2 visits; with Magasin fermé for both innotDone→COMPLETEDand BO-23 shows 8/10 visits and the reasons. - A visit still
IN_PROGRESS→409 TOUR_CLOSING_BLOCKEDwith aVISIT_IN_PROGRESSitem. - Two photos still uploading → the app disables « Terminer la tournée »; the API answers
409 TOUR_CLOSING_BLOCKEDwith anUNSYNCED_DATAitem 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
- Screens: DA-20 Tour closing & results · BO-23 Tour live detail
- Endpoints:
delegate.tours.closingPreview·delegate.tours.close·admin.tours.reopen
FLD-13 — Live follow-up in the back-office
| Release | Priority | Source | Apps | Owner tasks |
|---|---|---|---|---|
| V1 | MUST | cahier §4.5, §6.4 | BO · API | SRV-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
- BO-06 live map: one marker per delegate whose tour is
IN_PROGRESSorSUSPENDED, 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. - 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. - 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). - 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 thanfield.locationRetentionDaysreturn an empty trail marked as purged. - 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.trackreturns an empty trail flagged as purged while check-ins and the summary remain. - A user without
field.viewgets403 PERMISSION_DENIEDonadmin.live.delegatesand receives no field events on the stream.
Data — LocationPing, Tour, Visit, DelegateProfile, OutboxEvent.
Interfaces
- Screens: BO-06 Field dashboard & live map · BO-23 Tour live detail
- Endpoints:
sync.locationPings·admin.tours.get·admin.tours.track·admin.live.delegates·admin.events.stream
FLD-14 — Report analysis and validation of new points of sale
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
- 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.
- 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 statusPENDINGand 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). - Approve →
APPROVED; reject →REJECTEDwith 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'sSIGNUPSobjective. - 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 with400 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
SIGNUPSachievement.
Data — VisitReport, Visit, Reseller, ResellerPhoto, ReferenceItem, Notification, AuditLog.
Interfaces
- Screens: BO-13 Account validation queue · BO-25 Visit detail
- Endpoints:
admin.tours.get— related:admin.visits.list,admin.resellers.validation.list,admin.resellers.validate
FLD-15 — Location policy: consent, frequency, tolerance, retention
| Release | Priority | Source | Apps | Owner tasks |
|---|---|---|---|---|
| V1 | MUST | cahier §8, §10 | API · DA · BO | SRV-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
-
What is collected and when:
Moment Data Condition Tour start and closing one position if permission granted Check-in one position (required) FLD-08 Field sign-up the store's position FLD-11 Visit photo capture position if available Position samples ( LocationPing)lat, lng, accuracy, speed, occurredAtonly while the delegate's tour of the current business day is IN_PROGRESSNothing is collected while the tour is
SUSPENDED, after closing, after midnight, or when no tour is in progress. -
Sampling: a sample is taken when
field.locationIntervalSecondshave elapsed orfield.locationDistanceMetershave been travelled since the last sample, whichever comes first; samples with accuracy abovefield.gpsMaxAccuracyMetersare 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, theoccurredAtlimit). -
The server discards (without error, counted in the response) samples whose
occurredAtfalls outside anIN_PROGRESSperiod of the tour, so a late batch never creates positions outside the policy. -
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).
-
Consent (DA-04): at first sign-in and whenever
field.locationPolicyVersionchanges, 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 answers409 LOCATION_CONSENT_REQUIRED; the other features stay available. -
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.
-
Transparency: DA-26 shows whether sampling is active, the last sample time, the current frequency, tolerance and retention values, and the full notice.
-
Retention:
LocationPingrows older thanfield.locationRetentionDaysare 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). -
Changes to the policy settings are audited; changing frequency or tolerance takes effect on devices at their next
appConfig.getorsync.delta. -
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 (version2026-11), the start succeeds and the consent time and version are visible on BO-17. - During an
IN_PROGRESStour 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
- Screens: DA-04 Permissions & location consent · DA-26 Settings
- Endpoints:
sync.locationPings·admin.tours.track
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
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
- A
VisitTypehas: code (immutable), label (fr, optional ar/en), minimum photos (0 to 10), report required (yes/no), optional report fields shown (products, promotions, issues, attachments), aChecklistTemplate(optional), active flag. - A
ChecklistTemplatehas 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. - 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).
- 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.
- 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 throughsync.delta.
Acceptance criteria
- Changing Prospection to 2 photos: a visit already
CHECKED_INstill 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
- Screens: BO-26 Visit types & checklist templates
- Endpoints:
admin.visitTypes.crud·admin.checklists.crud
Notes / open points — Seed visit types and checklists are proposals to validate with HOCO's sales management.
FLD-17 — Recommended visit order
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
- Start point: the delegate's configured start point; otherwise the first stop in the current order.
- Algorithm: repeatedly pick the closest unplaced stop (Haversine distance) from the last placed point; ties broken by
HIGHpriority 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). - 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.setStopsand sets the tour's ordering mode toRECOMMENDEDunless the planner keepsIMPOSED. - In the delegate app, « Réordonner au plus proche » runs the same algorithm on the device from the current position over the remaining
PLANNEDstops (RECOMMENDEDtours only) and saves the order throughdelegate.tours.reorder. - 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
IMPOSEDtour the delegate app does not offer the action.
Data — Tour, Visit, Reseller, DelegateProfile.
Interfaces
- Screens: DA-06 Tour programme · BO-22 Tour editor
- Endpoints:
admin.tours.recommendOrder
FLD-18 — Automatic tour optimisation (V2)
Statement — The system should compute optimised tour orders with a routing engine that uses road distances, travel times and the stops' time slots.
Rules
- 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.
- 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.
- 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
Statement — The system shall let each delegate consult their own past tours, visit reports and tour reports, and their performance over selectable periods.
Rules
- 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).
- 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.
- History: tours calendar with status and summary (DA-07); visit reports searchable by point of sale and date; tour final reports (DA-21).
- Scope: a delegate only sees their own data (
delegatescope); the same figures appear for the back-office on BO-17. - 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.reportsonly returns A's.
Data — Tour, Visit, VisitReport, Objective, Order, Invitation, Reseller.
Interfaces
- Screens: DA-07 Tours calendar & history · DA-21 Reports & performance
- Endpoints:
delegate.performance·delegate.reports·delegate.tours.list
Loyalty programme
Requirements LOY-01 to LOY-07 (V2): points earning, expiry and reversal, Bronze to VIP levels, rewards and redemption, the traceable points history, missions and challenges, and the Top 3 resellers of the month.
Invitations & activation
Requirements IVT-01 to IVT-04: invitation code, link and QR code, sharing, the activation funnel and attribution of the sign-up to the inviting delegate.