# 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:** ```json { "orders": { "tenantid": 1135, "locationid": 1166, "customerid": 42, "items": [ { "productid": 7060, "orderqty": 2, "price": 45.0 } ] } } ``` **Also accepted (flat, no wrapper):** ```json { "tenantid": 1135, "locationid": 1166, "customerid": 42, "items": [ { "productid": 7060, "orderqty": 2, "price": 45.0 } ] } ``` **This shape used to silently lose the items — avoid it:** ```json { "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 '': 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.