Skip to content

How it works

One order, end to end — from browsing the store to the accounts team closing it.

Every BabyMart order has two halves. First the customer shops and pays on the storefront or the mobile app. Then employees move the order through fulfilment in the admin dashboard, one role at a time, until it is completed. The API is the single source of truth for both halves.

  1. 1BrowseShop, search, filters
  2. 2Add to cartSaved on the server
  3. 3CheckoutPick an address
  4. 4Place orderOrder is created
  5. 5PayStripe, SSLCommerz or COD
  6. 6TrackMy orders
What the customer does. Each step calls the API.
  1. Browse. The customer finds products on /shop, by text search, or by uploading a photo (search by image). Signed-in customers can save a wishlist and compare up to four products.
  2. Add to cart. The cart lives on the API (/api/cart), so it follows the customer between devices. Adding to the cart requires signing in.
  3. Checkout. The customer chooses a saved address and a payment method.
  4. Place order. The storefront calls POST /api/orders. The API prices the order itself from the database — tax from TAX_RATE, free delivery above FREE_DELIVERY_THRESHOLD, otherwise a flat shipping fee — so a tampered cart cannot change the total.
  5. Pay. With Stripe the customer is sent to a Stripe Checkout page; with SSLCommerz to the SSLCommerz gateway; with cash on delivery the order is simply left unpaid until the courier collects the money.
  6. Track. The order appears under /user/orders with its live status.

The browser is never trusted to say “I paid”. Stripe tells the system directly with a signed webhook, and the API checks the payment with Stripe before it marks the order paid.

sequenceDiagram
  participant S as Storefront
  participant A as API
  participant P as Stripe
  S->>A: POST /api/orders
  A-->>S: order, status pending
  S->>P: Checkout Session for order.total
  P-->>S: customer pays on Stripe
  P->>S: webhook checkout.session.completed
  S->>A: PUT /api/orders/:id/webhook-status
  A->>P: retrieve session and verify
  A-->>S: paymentStatus paid

The full flow, SSLCommerz and the mobile PaymentSheet are on Payments.

Once an order exists, employees take it from pending to completed. Each step is an endpoint under /api/orders/workflow, and each is guarded by an employee role.

  1. 1Confirmcall_center
  2. 2Assign packerincharge
  3. 3Packpacker
  4. 4Assign courierincharge
  5. 5Deliverdeliveryman
  6. 6Completeaccounts
Who moves the order, in order.
Step Role Endpoint Status after
Confirm the address call_center PUT /api/orders/workflow/:id/confirm-address address_confirmed
Confirm the order call_center PUT /api/orders/workflow/:id/confirm-order confirmed
Assign a packer incharge PUT /api/orders/workflow/:id/assign-packer processing
Pack packer PUT /api/orders/workflow/:id/pack packed
Assign a deliveryman incharge PUT /api/orders/workflow/:id/assign-deliveryman packed
Start delivery deliveryman PUT /api/orders/workflow/:id/start-delivery delivering
Collect cash (COD only) deliveryman PUT /api/orders/workflow/:id/collect-cod delivering, payment paid
Mark delivered deliveryman PUT /api/orders/workflow/:id/deliver delivered
Complete accounts PUT /api/orders/workflow/:id/complete completed

An incharge can do every employee step, and an admin can do everything. Cash a deliveryman collects is tracked as a cash collection and handed to the accounts team, who confirm they received it.

stateDiagram-v2
  [*] --> pending
  pending --> address_confirmed: call_center
  address_confirmed --> confirmed: call_center
  pending --> confirmed: call_center
  confirmed --> processing: incharge assigns packer
  processing --> packed: packer
  confirmed --> packed: packer
  packed --> delivering: deliveryman starts
  delivering --> delivered: deliveryman
  delivered --> completed: accounts
  pending --> cancelled: customer or staff
  confirmed --> cancelled: staff
  completed --> [*]
  cancelled --> [*]

A customer can cancel only their own order, and only while it is pending and unpaid. Staff can cancel later too. Payment has its own field, paymentStatus: pending, paid, failed, refunded or cod_collected. Completing an order always sets it to paid.

  • apps/api/controllers/orderWorkflowController.ts — every workflow step and its status checks.
  • apps/api/routes/orderWorkflowRoutes.ts — which role guards each step.
  • apps/api/src/modules/orders/orderPricing.ts — server-side totals.
  • apps/web/components/pages/CheckoutPage.tsx — the storefront checkout.