Files
backend_fiesta/MOBILE_ORDER_VERIFICATION.md
Suriya d3a7466f4c Sync stock status on restock and expose live stock on getproductbyvariant
Two gaps found while auditing the order/stock flow:

- Receiving stock via an approved stock request only updated
  products.productstatus (a global per-product flag). A location
  flagged outofstock by CreateOrder never got reactivated, since
  nothing touched productlocations.status on the way back in.
  CreateProductStock now reactivates the specific
  (tenant, location, product) row to "available" for every "in"
  entry, the counterpart to how it gets flagged out.

- getproductbyvariant returned no stock info at all, so the app could
  only find out a product was unavailable from the 409 at order time.
  It now accepts an optional locationid and, when passed, returns
  live productstock (same SUM(in)-SUM(out) formula the order check
  uses) and locationstatus per product. Omitting locationid keeps the
  old response shape.

Added MOBILE_ORDER_VERIFICATION.md as a handoff doc for the mobile
team covering the expected request/response shapes and how to verify
their integration.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-21 18:01:39 +05:30

4.9 KiB

Order Creation — Mobile Developer Verification Guide

Why this exists

We found that orders placed through the app were being saved with zero line items — the order header (tenant, location, customer) saved fine, but the items array was silently getting dropped somewhere between the app and the database. Because the stock check only runs over whatever's in items, an order with no items also skipped stock validation entirely.

The backend now tolerates a few different request shapes and has a stock check in place, but the app's actual request needs to be verified against what's below to confirm it lines up.

Endpoint

POST https://fiesta.nearle.app/live/api/v1/mob/orders/createorder
Content-Type: application/json

Request shape — items MUST be inside orders, not a sibling of it

Correct:

{
  "orders": {
    "tenantid": 1135,
    "locationid": 1166,
    "customerid": 42,
    "items": [
      { "productid": 7060, "orderqty": 2, "price": 45.0 }
    ]
  }
}

Also accepted (flat, no wrapper):

{
  "tenantid": 1135,
  "locationid": 1166,
  "customerid": 42,
  "items": [
    { "productid": 7060, "orderqty": 2, "price": 45.0 }
  ]
}

This shape used to silently lose the items — avoid it:

{
  "orders": { "tenantid": 1135, "locationid": 1166 },
  "items": [ { "productid": 7060, "orderqty": 2 } ]
}

items as a sibling of orders (not nested inside it) is now handled as a fallback server-side too, but don't rely on the fallback — put items inside orders to match the primary/documented shape.

Required fields per item

field type required notes
productid int yes must be a real product for the tenant
orderqty number yes quantity being ordered
price number recommended unit price at time of order
locationid int no defaults to the order's own locationid if omitted

Expected responses — verify your app handles all of these

Scenario HTTP code Body (key fields)
Order succeeds 200 "status": true, "details": { "orderheaderid": ..., "items": [...] }
No tenantid at all 409 "status": false, "message": "Tenant ID is required"
items missing/empty 400 "status": false, "message": "Order must contain at least one item"
Requested qty > available stock 409 "status": false, "message": "insufficient stock for product '<name>': requested X, available Y"

Important: a 409 with "insufficient stock" is not a network/server error — it's the correct, expected response when a customer tries to order more than what's in stock at that store. The app should catch this specifically (check the message text, or treat any 409 from this endpoint as a stock problem) and show the customer a clear "not enough stock" message rather than a generic error screen.

How to verify end-to-end yourselves

  1. Pick a real tenantid + locationid + productid combo you know has stock (ask backend/ops for current numbers, or check via the merchant web app's inventory view).
  2. Place a normal order for 1 unit through the app. Confirm it returns 200 and the response's details.items array is non-empty.
  3. Place an order for a quantity larger than what's currently in stock for that product/location. Confirm you get a 409 with an "insufficient stock" message, and that the app surfaces this to the user instead of silently failing or showing a generic error.
  4. Cancel a successful order and confirm a follow-up stock check reflects the restored quantity (ask backend to check, or place the same over-quantity order again afterward — it should now succeed if cancellation restored enough stock).

Checking stock before the customer even taps "order"

GET /live/api/v1/mob/products/getproductbyvariant now accepts an optional locationid query param:

GET /live/api/v1/mob/products/getproductbyvariant?tenantid=1135&variantid=44&locationid=1166

When locationid is passed, each returned product now carries two extra live fields:

field meaning
productstock live available quantity at that store — same SUM(in)-SUM(out) formula the order stock check uses
locationstatus that store's status for this product, e.g. "outofstock" or "available"/"Active"

If locationid is omitted, both fields come back empty/zero — this is the old behavior preserved for backward compatibility, not new stock data. Start passing locationid (the store the customer is browsing) to get real numbers, and use it to show "out of stock" / gray out the add-to-cart button before the customer tries to order, instead of only finding out from the 409 response above.