From 969c064f3a3dc49efe1bd170ee9199b3bfa94fb5 Mon Sep 17 00:00:00 2001 From: seb Date: Thu, 8 Oct 2026 21:50:42 +0200 Subject: [PATCH] u --- docs/api/routes-all.md | 4 +-- docs/api/routes.md | 4 +-- docs/api/routes/order/list.md | 30 ++++++++++++++++-- src/api/routes/order.js | 57 ++++++++++++++++++++++++++++++++--- src/db/order.js | 4 +-- 5 files changed, 86 insertions(+), 13 deletions(-) diff --git a/docs/api/routes-all.md b/docs/api/routes-all.md index 5fbff91..881968d 100644 --- a/docs/api/routes-all.md +++ b/docs/api/routes-all.md @@ -436,8 +436,8 @@ _none_ - Params: `id: int, body: { prefix?: str, padding?: int, next?: int }` - Returns: `200 { number: { id: int, type: str, prefix: str, padding: int, next: int } }` #### List orders — `GET /order` -_none_ -- Returns: `200 { orders: { id: int, number: str, type: str, entityId: int|null, date: str, createdAt?: str }[] }` +- Params: `query: offset?: int, limit?: int` +- Returns: `200 { orders: T11[], total: int, offset: int, limit: int }` #### Create order — `POST /order` - Params: `body: { number: str, date: str, lines: T25[], entityId?: int|null }` - Returns: `201 T7` diff --git a/docs/api/routes.md b/docs/api/routes.md index 94c73b2..336225d 100644 --- a/docs/api/routes.md +++ b/docs/api/routes.md @@ -374,8 +374,8 @@ _none_ - Params: `id: int, body: { prefix?: str, padding?: int, next?: int }` - Returns: `200 { number: { id: int, type: str, prefix: str, padding: int, next: int } }` #### List orders — `GET /order` -_none_ -- Returns: `200 { orders: { id: int, number: str, type: str, entityId: int|null, date: str, createdAt?: str }[] }` +- Params: `query: offset?: int, limit?: int` +- Returns: `200 { orders: T10[], total: int, offset: int, limit: int }` #### Create order — `POST /order` - Params: `body: { number: str, date: str, lines: T24[], entityId?: int|null }` - Returns: `201 T7` diff --git a/docs/api/routes/order/list.md b/docs/api/routes/order/list.md index 2c2f55c..2da5859 100644 --- a/docs/api/routes/order/list.md +++ b/docs/api/routes/order/list.md @@ -6,8 +6,16 @@ List orders Lists sales orders (`manifest` rows with `type = 'order'`) for the authenticated user's selected company. +Results are paged, include line items, and provide total unpaged count. +## Query parameters + +| Param | Required | Type | Description | +|-------|----------|------|-------------| +| `offset` | no | integer | Number of orders to skip | +| `limit` | no | integer | Number of orders to return | + ## Response `200` Order list @@ -21,9 +29,25 @@ Order list "type": "order", "entityId": 1, "date": "2026-08-10T00:00:00.000Z", - "createdAt": "2026-08-10T00:00:00.000Z" + "createdAt": "2026-08-10T00:00:00.000Z", + "lines": [ + { + "id": 1, + "sku": "…", + "name": "…", + "pu": 1, + "amount": 1, + "net": 1, + "rebate": 1, + "taxrate": 1, + "comment": "…" + } + ] } - ] + ], + "total": 1, + "offset": 1, + "limit": 1 } ``` @@ -31,7 +55,7 @@ Order list | Status | Description | |--------|-------------| -| 400 | No company selected — `{"error":"…"}` | +| 400 | Invalid offset, invalid limit, or no company selected — `{"error":"…"}` | | 401 | Unauthorized — `{"error":"…"}` | | 403 | Not authorized — `{"error":"…"}` | | 404 | Company not found — `{"error":"…"}` | diff --git a/src/api/routes/order.js b/src/api/routes/order.js index 2282dd0..e4b5fea 100644 --- a/src/api/routes/order.js +++ b/src/api/routes/order.js @@ -18,6 +18,8 @@ function orderErrorStatus(error) { if (error.message === 'Invalid entityId') return 400; if (error.message === 'Invalid order') return 400; if (error.message === 'Invalid lines') return 400; + if (error.message === 'Invalid offset') return 400; + if (error.message === 'Invalid limit') return 400; if (error.message?.includes('parent article') || error.message?.includes('A parent article')) return 400; return 500; } @@ -37,8 +39,25 @@ export function register(app, basePath = '') { * description: | * Lists sales orders (`manifest` rows with `type = 'order'`) * for the authenticated user's selected company. + * Results are paged, include line items, and provide total unpaged count. * security: * - cookieAuth: [] + * parameters: + * - in: query + * name: offset + * schema: + * type: integer + * default: 0 + * minimum: 0 + * description: Number of orders to skip + * - in: query + * name: limit + * schema: + * type: integer + * default: 20 + * minimum: 1 + * maximum: 100 + * description: Number of orders to return * x-markdown: order/list.md * responses: * 200: @@ -47,13 +66,23 @@ export function register(app, basePath = '') { * application/json: * schema: * type: object + * required: [orders, total, offset, limit] * properties: * orders: * type: array * items: - * $ref: '#/components/schemas/OrderSummary' + * $ref: '#/components/schemas/Order' + * total: + * type: integer + * description: Total number of unpaged orders + * offset: + * type: integer + * description: Number of orders skipped + * limit: + * type: integer + * description: Number of orders returned * 400: - * description: No company selected + * description: Invalid offset, invalid limit, or no company selected * content: * application/json: * schema: @@ -161,9 +190,29 @@ export function register(app, basePath = '') { return res.status(400).json({ error: selected.error }); } + const rawOffset = req.query.offset; + const rawLimit = req.query.limit; + + let offset = 0; + let limit = 20; + + if (rawOffset !== undefined) { + offset = parseInt(rawOffset, 10); + if (!Number.isInteger(offset) || offset < 0) { + return res.status(400).json({ error: 'offset must be an integer >= 0' }); + } + } + + if (rawLimit !== undefined) { + limit = parseInt(rawLimit, 10); + if (!Number.isInteger(limit) || limit < 1 || limit > 100) { + return res.status(400).json({ error: 'limit must be an integer between 1 and 100' }); + } + } + try { - const orders = await db.list(req.user.id); - res.status(200).json({ orders }); + const result = await db.list(req.user.id, { offset, limit }); + res.status(200).json(result); } catch (error) { const status = orderErrorStatus(error); if (status === 500) console.error('List orders failed:', error); diff --git a/src/db/order.js b/src/db/order.js index 28c4275..f9fc379 100644 --- a/src/db/order.js +++ b/src/db/order.js @@ -1,8 +1,8 @@ import { getStore } from './store.js'; -export async function list(googleAuthId) { +export async function list(googleAuthId, opts) { const store = await getStore(); - return store.order.list(googleAuthId); + return store.order.list(googleAuthId, opts); } export async function getById(googleAuthId, id) {