Aller au contenu principal

UC-03 — Achat / vente

Acteur : Vendeur / Caissier But : Vendre des produits et débiter une carte

Trigger​

Un porteur souhaite acheter des produits à la buvette.

Préconditions​

  • Le vendeur possède la permission product.sell
  • La carte est active avec un solde suffisant
  • Les produits sont en stock

Postconditions​

  • Le solde de la carte est débité du total
  • Le stock est décrémenté atomiquement
  • Une transaction debit_purchase est enregistrée

Endpoints​

1. Consulter le catalogue​

GET /api/v1/products

2. Effectuer l'achat​

POST /api/v1/transactions/purchase
Content-Type: application/json
Idempotency-Key: <uuid-v4>

{
"card_id": "uuid-carte",
"items": [
{ "product_id": "uuid-produit-1", "quantity": 2, "unit_price_cents": 500 },
{ "product_id": "uuid-produit-2", "quantity": 1, "unit_price_cents": 500 }
],
"point_of_sale_id": "uuid-pos",
"site_id": "uuid-site"
}
unit_price_cents obligatoire

Chaque article doit fournir product_id, quantity et unit_price_cents.

Flow​

sequenceDiagram
participant Porteur
participant Vendeur
participant POS
participant API
participant DB

Porteur->>Vendeur: "2 cafés et 1 croissant"
Vendeur->>POS: Scanner produits
POS->>API: GET /products
API-->>POS: [produits, prix, stocks]
POS->>Vendeur: Total : 1500 F

Vendeur->>POS: Carte + valider
POS->>API: POST /transactions/purchase
API->>DB: BEGIN
API->>DB: Vérifie solde + stock
API->>DB: Décrémente stock + INSERT transaction
API->>DB: UPDATE cards.balance_cents
API->>DB: COMMIT
API-->>POS: {transaction, new_balance_cents}
POS->>Vendeur: "Vente réussie ✓"

Exemple de réponse​

{
"transaction": {
"id": "uuid",
"card_id": "uuid",
"type": "debit_purchase",
"amount_cents": 1500,
"balance_before_cents": 5000,
"balance_after_cents": 3500,
"amount_formatted": "1 500 FCFA",
"balance_after_formatted": "3 500 FCFA",
"currency": "XOF",
"created_at": "2025-06-01T11:00:00Z"
},
"new_balance_cents": 3500,
"new_balance": 3500,
"new_balance_formatted": "3 500 FCFA",
"currency": "XOF"
}

Les articles achetés sont visibles dans GET /transactions (champ purchase_items).

Permissions​

PermissionDescription
product.sellEffectuer une vente

Erreurs​

error_codeDescription
ValidationSolde ou stock insuffisant
NotFoundCarte ou produit introuvable
ConflictConflit d'idempotence

Voir Transaction — Achat.