Skip to content

feat: add POST /api/orders endpoint for customer order creation#54

Draft
zshanhui wants to merge 4 commits into
mainfrom
cursor/create-order-api-b4d6
Draft

feat: add POST /api/orders endpoint for customer order creation#54
zshanhui wants to merge 4 commits into
mainfrom
cursor/create-order-api-b4d6

Conversation

@zshanhui
Copy link
Copy Markdown
Owner

@zshanhui zshanhui commented Jun 1, 2026

Summary

Adds the missing POST /api/orders endpoint that the online ordering frontend needs to create orders after checkout. All new server-side code is TypeScript.

What it does

The endpoint accepts a JSON body and creates:

  1. A customer record (with optional phone number)
  2. An order linked to the merchant and customer
  3. Line items for each menu item in the order

Request / Response

POST /api/orders
Content-Type: application/json

{
  "merchantId": 1,
  "customerName": "Jane Doe",
  "customerPhone": "+15551234567",   // optional
  "orderType": "pickup",             // optional, defaults to "pickup"
  "items": [
    { "menuItemId": 3, "quantity": 2 },
    { "menuItemId": 27, "quantity": 1 }
  ]
}

→ 201 { "orderUuid": "...", "orderId": 17 }
→ 400 { "error": "..." }  (validation)
→ 422 { "error": "..." }  (business rule, e.g. merchant not found)

Changes

File Change
src/server/models/orders.ts Converted from JS to TS. Added OrderRow, OrderFilter, CreateParams interfaces. Fixed create() to reliably return UUID on SQLite.
src/server/services/actions.ts Converted from JS to TS. Added CreateOrderParams interface, typed imports, named exports. Fixed CJS/ESM interop.
src/server/routes/orders.ts Converted from JS to TS. New POST / route with input validation. Typed Express handlers.
src/server/models/customers.ts Updated create() to accept optional mobile_phone
src/client/js/api/index.tsx Added createOrder frontend API helper
specs/services/createOrder.spec.ts 6 unit tests (happy path, phone, order types, validation)
src/server/index.js Updated require() for new TS default export
src/server/routes/merchants.js Updated require() for new TS default export

Bug fixes included

  • Orders.create SQLite compatibility: .returning('uuid') is silently ignored by SQLite, so the old code returned a row ID instead of a UUID. Now generates the UUID first and returns it directly.
  • CJS/ESM interop: Customers and Merchants TS modules use export default, but CJS require() puts them at .default. The old actions.js didn't handle this — now all three files are proper TypeScript with ESM imports.

Demo

create_order_api_demo.mp4

Order created via POST /api/orders appears immediately in the merchant POS dashboard.

Order detail showing API-created order with items and customer info

To show artifacts inline, enable in settings.

Open in Web Open in Cursor 

cursoragent and others added 4 commits May 16, 2026 12:23
- Update merchant dashboard route from /merchant to /merchant-dashboard/:uuid
- Add online ordering route pattern /online-ordering/:slug
- Fix pnpm run dev description: it already uses nodemon --exec tsx, not node
- Add seed data UUIDs section for testing convenience

Co-authored-by: zshanhui <zshanhui@users.noreply.github.com>
- Add createOrder service function that creates customer, order, and line items
- Add POST /api/orders route with input validation (400/422 error responses)
- Add createOrder frontend API helper for checkout integration
- Fix Orders.create to reliably return UUID on both SQLite and PostgreSQL
- Fix Customers.create to accept optional mobile_phone field
- Fix CJS/ESM interop for Customers and Merchants TS default exports
- Add 6 unit tests covering happy path, validation, and edge cases

Co-authored-by: zshanhui <zshanhui@users.noreply.github.com>
…TypeScript

- orders.js → orders.ts: add OrderRow, OrderFilter, CreateParams interfaces
- actions.js → actions.ts: add CreateOrderParams interface, typed imports, named exports
- routes/orders.js → routes/orders.ts: typed Express handlers
- Update CJS consumers (index.js, merchants.js) with .default for new TS exports
- Convert test spec to use ESM import for actions

Co-authored-by: zshanhui <zshanhui@users.noreply.github.com>
…rder API

- merchantId field now accepts a UUID or hash_id string (not an integer)
- Service resolves via getByUuid() then falls back to getByHashId()
- Route rejects non-string merchantId with a 400
- Updated tests to seed merchants with UUID/hash_id and test both lookups
- Updated frontend API helper type to string

Co-authored-by: zshanhui <zshanhui@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants