Aller au contenu principal

Sites et points de vente

Base URL : /api/v1/admin/org

Gestion des sites (établissements physiques), des points de vente (POS) et des sessions de caisse.


Sites​

GET /admin/org/sites​

Liste paginée des sites.

Permissions : site.read

ParamTypeDéfaut
limitinteger20
offsetinteger0

Réponse (200) :

{
"items": [
{
"id": "uuid",
"name": "Buvette Principale",
"code": "BP",
"address": "Bloc A, Rez-de-chaussée",
"city": "Lomé",
"country": "TG",
"contact_phone": "+22890123456",
"contact_email": null,
"opening_hours": {
"monday": { "open": "07:00", "close": "18:00", "closed": false }
},
"timezone": "Africa/Lome",
"is_active": true,
"settings": {},
"notification_config": null,
"created_at": "2025-01-15T10:00:00Z",
"updated_at": "2025-06-01T14:30:00Z"
}
],
"total": 2
}

GET /admin/org/sites/{id}​

Détail d'un site. Permissions : site.read Réponse : objet Site brut.

POST /admin/org/sites​

Crée un site. L'opening_hours et le timezone sont recopiés de l'organisation (business_hours).

Permissions : site.create

ChampTypeRequisDescription
namestringOuiNom du site (non vide)
codestringNonCode
addressstringNonAdresse
citystringNonVille
countrystringNonPays (défaut "TG")
contact_phonestringNonTéléphone
contact_emailstringNonEmail

Réponse (201) : { "message": "Site créé", "site": {...} }

PUT /admin/org/sites/{id}​

Met à jour un site (mêmes champs que la création ; country n'est pas réécrit).

Permissions : site.update Réponse (200) : { "message": "Site mis à jour", "site": {...} }

DELETE /admin/org/sites/{id}​

Permissions : site.delete Réponse (200) : { "message": "Site supprimé" }


Points de vente (POS)​

Structure​

ChampTypeDescription
iduuidIdentifiant
site_iduuidSite de rattachement
namestringNom
codestring?Code
kindstring"Fixed" ou "Mobile"
opening_hoursobjectHoraires par jour (noms de jours anglais)
is_currently_openbooleanOuvert actuellement
created_at / updated_atdatetimeHorodatage
Casse de kind

kind est sérialisé en PascalCase : "Fixed" ou "Mobile" (pas "fixed"/"kiosk").

GET /admin/org/points-of-sale​

Permissions : pos.read

ParamTypeDéfautDescription
site_iduuid—Si fourni, retourne tous les POS du site (pagination ignorée)
limitinteger20
offsetinteger0

Réponse (200) : { "items": [PointOfSale], "total": n }

GET /admin/org/points-of-sale/{id}​

Permissions : pos.read — Réponse : objet PointOfSale brut.

POST /admin/org/points-of-sale​

Permissions : pos.create

{
"site_id": "uuid",
"name": "Terminal Bar",
"code": "TB01",
"kind": "Fixed",
"opening_hours": {}
}

Champs requis : site_id, name, kind.

Réponse (201) : { "message": "Point de vente créé", "pos": {...} }

PUT /admin/org/points-of-sale/{id}​

Permissions : pos.update

{ "name": "Terminal Bar - Rénové", "kind": "Fixed" }

Réponse (200) : { "message": "Point de vente mis à jour", "pos": {...} }

DELETE /admin/org/points-of-sale/{id}​

Permissions : pos.delete Réponse (200) : { "message": "Point de vente supprimé" }

POST /admin/org/points-of-sale/{id}/toggle-open​

Bascule l'état ouvert/fermé du point de vente.

Permissions : pos.update Réponse (200) : { "message": "Statut modifié" }


Sessions de caisse (Registers)​

Structure Register​

ChampTypeDescription
iduuidIdentifiant
pos_iduuidPoint de vente (sérialisé pos_id)
statusstring"open" ou "closed"
opened_atdatetimeOuverture
closed_atdatetime?Fermeture
opening_balance_centsintegerFonds de caisse initial
closing_balance_centsinteger?Solde compté
expected_cash_centsinteger?Espèces attendues (calcul système)
actual_cash_centsinteger?Espèces comptées
discrepancy_centsinteger?Écart (actual − expected)
opened_by / closed_byuuid?Opérateurs
notesstring?Notes

GET /admin/org/points-of-sale/{pos_id}/registers​

Liste des sessions d'un POS.

Permissions : register.read

ParamTypeDéfaut
statusstring—
limitinteger20
offsetinteger0

Réponse (200) : { "items": [Register], "total": n }

POST /admin/org/points-of-sale/{pos_id}/registers/open​

Ouvre une session de caisse.

Permissions : register.open

{ "opening_balance_cents": 5000, "notes": "Ouverture matinale" }

opening_balance_cents est requis. Rejette si une caisse est déjà ouverte sur ce POS.

Réponse (201) : { "message": "Caisse ouverte", "register": {...} } (avec opening_balance, opening_balance_formatted, currency).

GET /admin/org/registers/{id}​

Détail d'une session de caisse (arrêté de caisse).

Permissions : register.read

Réponse (200) :

{
"register": {
"id": "uuid",
"pos_id": "uuid",
"point_of_sale_name": "Terminal Bar",
"status": "closed",
"opened_at": "2025-07-15T06:00:00Z",
"closed_at": "2025-07-15T18:00:00Z",
"opening_balance_cents": 5000,
"opening_balance": 5000,
"opening_balance_formatted": "5 000 FCFA",
"closing_balance_cents": 45000,
"expected_cash_cents": 45200,
"actual_cash_cents": 45000,
"discrepancy_cents": -200,
"notes": "Fermeture soir",
"currency": "XOF"
}
}

Les champs monétaires optionnels (closing_balance, expected_cash, actual_cash, discrepancy) n'apparaissent que lorsqu'ils sont définis.

POST /admin/org/registers/{id}/close​

Ferme une session de caisse.

Permissions : register.close

{
"actual_cash_cents": 45000,
"expected_cash_cents": 45200,
"notes": "Fermeture soir"
}
ChampTypeRequisDescription
actual_cash_centsintegerOuiEspèces comptées
expected_cash_centsintegerOuiEspèces attendues
notesstringNonNotes

Réponse (200) : { "message": "Caisse fermée", "register": {...} }

remarque

Il n'existe pas d'endpoint de liste globale /registers ni de /registers/{id}/cash-movement. Les sessions se consultent via le POS (/points-of-sale/{pos_id}/registers) ou par identifiant (/registers/{id}).


Permissions​

PermissionDescription
site.read / site.create / site.update / site.deleteCRUD site
pos.read / pos.create / pos.update / pos.deleteCRUD point de vente
register.read / register.open / register.closeSessions de caisse
site.manageSuper-permission couvrant pos.* et register.*