From 529b142341e7aee34f39e05601993266959341bd Mon Sep 17 00:00:00 2001 From: seb Date: Thu, 15 Oct 2026 10:50:03 +0200 Subject: [PATCH] u --- docs/api/routes-all.md | 32 ++++++++++++++++---------------- docs/api/routes.md | 32 ++++++++++++++++---------------- docs/api/routes/order/create.md | 2 ++ docs/api/routes/order/get.md | 1 + docs/api/routes/order/list.md | 1 + docs/api/routes/order/update.md | 2 ++ docs/api/routes/quote/create.md | 2 ++ docs/api/routes/quote/get.md | 1 + docs/api/routes/quote/list.md | 1 + docs/api/routes/quote/update.md | 2 ++ src/api/openapi.js | 8 ++++++++ src/api/routes/order.js | 16 +++++++++++++++- src/api/routes/quote.js | 16 +++++++++++++++- 13 files changed, 82 insertions(+), 34 deletions(-) diff --git a/docs/api/routes-all.md b/docs/api/routes-all.md index ff3adb0..31e7868 100644 --- a/docs/api/routes-all.md +++ b/docs/api/routes-all.md @@ -10,14 +10,14 @@ Params: path values first, then `query:` and `body:` (`body?` = optional body). ### Reusable types - `T1` = `{ order: T2 }` -- `T2` = `{ id: int, number: str, type: str, entityId: int|null, date: str, lines: T29[], createdAt?: str, shipping?: T37|null, shippings?: T37[], payment?: T43|null, payments?: T43[], paid?: bool, shipped?: bool, delivered?: bool, orderTotal?: num, paidTotal?: num, orderedQuantity?: num, shippedQuantity?: num, shipments?: T5[], files?: T15[] }` +- `T2` = `{ id: int, number: str, type: str, entityId: int|null, date: str, lines: T29[], externalNumber?: str|null, createdAt?: str, shipping?: T37|null, shippings?: T37[], payment?: T43|null, payments?: T43[], paid?: bool, shipped?: bool, delivered?: bool, orderTotal?: num, paidTotal?: num, orderedQuantity?: num, shippedQuantity?: num, shipments?: T5[], files?: T15[] }` - `T3` = `{ article: T4 }` - `T4` = `{ id: int, sku: str, name: str, slug: str, desc: str|null, seo: str|null, track_stock: bool, unitamount: num|null, weight: num|null, unit: T40, brand: T38|null, categoryIds: int[], photos: T35[], eans: str[], prices: T47[], suppliers: T17[] }` - `T5` = `{ id: int, number: str, type: str, date: str, lines: T29[], shippings: T37[], entityId?: int|null, externalNumber?: str|null, createdAt?: str|null, lineCount?: int, packageCount?: int, files?: T15[] }` -- `T6` = `{ delivery: T7 }` -- `T7` = `{ id: int, number: str, type: str, supplierId: int|null, date: str, lines: T29[], files: T15[], externalNumber?: str|null, createdAt?: str, ledger?: T51 }` -- `T8` = `{ quote: T9 }` -- `T9` = `{ id: int, number: str, type: str, entityId: int|null, date: str, lines: T29[], createdAt?: str, positions?: int, grossTotal?: num, totalQuantity?: num, customerName?: str|null, files?: T15[] }` +- `T6` = `{ quote: T7 }` +- `T7` = `{ id: int, number: str, type: str, entityId: int|null, date: str, lines: T29[], externalNumber?: str|null, createdAt?: str, positions?: int, grossTotal?: num, totalQuantity?: num, customerName?: str|null, files?: T15[] }` +- `T8` = `{ delivery: T9 }` +- `T9` = `{ id: int, number: str, type: str, supplierId: int|null, date: str, lines: T29[], files: T15[], externalNumber?: str|null, createdAt?: str, ledger?: T51 }` - `T10` = `{ name: str, path: str, totalSizeBytes: int, timestamp: str|null, manifest?: T11|null }` - `T11` = `{ id: str, timestamp: str, dateKey: str, monthKey: str, dbProvider: str, files: T18, totalSizeBytes: int, durationMs: int }` - `T12` = `{ labeltemplate: T14 }` @@ -397,7 +397,7 @@ _none_ - Returns: `200 { deliveries: { id: int, number: str, type: str, supplierId: int|null, date: str, externalNumber?: str|null, createdAt?: str, ledger?: T51 }[] }` #### Create delivery — `POST /delivery` - Params: `body: { externalNumber: str, date: str, lines: T34[], supplierId?: int|null, files?: { mimetype: str, name: str, content: str, sort?: int, size?: int, hash?: str, created?: str, modified?: str, meta?: { [k]: str } }[] }` -- Returns: `201 T6` +- Returns: `201 T8` #### Parse document (SSE) — `POST /delivery/parse` - Params: `form: { file: str }` - Returns: `200 SSE` @@ -415,10 +415,10 @@ _none_ - Returns: `204 void` #### Get delivery — `GET /delivery/{id}` - Params: `id: int` -- Returns: `200 T6` +- Returns: `200 T8` #### Update delivery — `PATCH /delivery/{id}` - Params: `id: int, body: { externalNumber?: str|null, date?: str, supplierId?: int|null, lines?: T34[], files?: { mimetype: str, name: str, content: str, sort?: int, size?: int, hash?: str, created?: str, modified?: str, meta?: { [k]: str } }[] }` -- Returns: `200 T6` +- Returns: `200 T8` #### Delete delivery file attachment — `DELETE /delivery/{id}/file/{fileId}` - Params: `id: int, fileId: int` - Returns: `204 void` @@ -624,7 +624,7 @@ _none_ - Params: `query: offset?: int, limit?: int, search?: str, onlyUnpaid?: bool, onlyUndelivered?: bool, seekMonths?: int` - Returns: `200 { orders: T2[], total: int, unfilteredTotal: int, offset: int, limit: int }` #### Create order — `POST /order` -- Params: `body: { number: str, date: str, lines: T34[], entityId?: int|null }` +- Params: `body: { number: str, date: str, lines: T34[], entityId?: int|null, externalNumber?: str|null }` - Returns: `201 T1` #### Delete order — `DELETE /order/{id}` - Params: `id: int` @@ -633,7 +633,7 @@ _none_ - Params: `id: int` - Returns: `200 T1` #### Update order — `PATCH /order/{id}` -- Params: `id: int, body: { number?: str, date?: str, entityId?: int|null, lines?: T34[] }` +- Params: `id: int, body: { number?: str, date?: str, entityId?: int|null, externalNumber?: str|null, lines?: T34[] }` - Returns: `200 T1` #### Delete order file attachment — `DELETE /order/{id}/file/{fileId}` - Params: `id: int, fileId: int` @@ -763,19 +763,19 @@ _none_ #### List quotes — `GET /quote` - Params: `query: offset?: int, limit?: int, search?: str, seekMonths?: int` -- Returns: `200 { quotes: T9[], total: int, unfilteredTotal: int, offset: int, limit: int }` +- Returns: `200 { quotes: T7[], total: int, unfilteredTotal: int, offset: int, limit: int }` #### Create quote — `POST /quote` -- Params: `body: { number: str, date: str, lines: T34[], entityId?: int|null }` -- Returns: `201 T8` +- Params: `body: { number: str, date: str, lines: T34[], entityId?: int|null, externalNumber?: str|null }` +- Returns: `201 T6` #### Delete quote — `DELETE /quote/{id}` - Params: `id: int` - Returns: `204 void` #### Get quote — `GET /quote/{id}` - Params: `id: int` -- Returns: `200 T8` +- Returns: `200 T6` #### Update quote — `PATCH /quote/{id}` -- Params: `id: int, body: { number?: str, date?: str, entityId?: int|null, lines?: T34[] }` -- Returns: `200 T8` +- Params: `id: int, body: { number?: str, date?: str, entityId?: int|null, externalNumber?: str|null, lines?: T34[] }` +- Returns: `200 T6` #### Delete quote file attachment — `DELETE /quote/{id}/file/{fileId}` - Params: `id: int, fileId: int` - Returns: `204 void` diff --git a/docs/api/routes.md b/docs/api/routes.md index df6b4c7..12cf92b 100644 --- a/docs/api/routes.md +++ b/docs/api/routes.md @@ -10,14 +10,14 @@ Params: path values first, then `query:` and `body:` (`body?` = optional body). ### Reusable types - `T1` = `{ order: T2 }` -- `T2` = `{ id: int, number: str, type: str, entityId: int|null, date: str, lines: T23[], createdAt?: str, shipping?: T31|null, shippings?: T31[], payment?: T37|null, payments?: T37[], paid?: bool, shipped?: bool, delivered?: bool, orderTotal?: num, paidTotal?: num, orderedQuantity?: num, shippedQuantity?: num, shipments?: T5[], files?: T13[] }` +- `T2` = `{ id: int, number: str, type: str, entityId: int|null, date: str, lines: T23[], externalNumber?: str|null, createdAt?: str, shipping?: T31|null, shippings?: T31[], payment?: T37|null, payments?: T37[], paid?: bool, shipped?: bool, delivered?: bool, orderTotal?: num, paidTotal?: num, orderedQuantity?: num, shippedQuantity?: num, shipments?: T5[], files?: T13[] }` - `T3` = `{ article: T4 }` - `T4` = `{ id: int, sku: str, name: str, slug: str, desc: str|null, seo: str|null, track_stock: bool, unitamount: num|null, weight: num|null, unit: T34, brand: T32|null, categoryIds: int[], photos: T29[], eans: str[], prices: T39[], suppliers: T14[] }` - `T5` = `{ id: int, number: str, type: str, date: str, lines: T23[], shippings: T31[], entityId?: int|null, externalNumber?: str|null, createdAt?: str|null, lineCount?: int, packageCount?: int, files?: T13[] }` -- `T6` = `{ delivery: T7 }` -- `T7` = `{ id: int, number: str, type: str, supplierId: int|null, date: str, lines: T23[], files: T13[], externalNumber?: str|null, createdAt?: str, ledger?: T43 }` -- `T8` = `{ quote: T9 }` -- `T9` = `{ id: int, number: str, type: str, entityId: int|null, date: str, lines: T23[], createdAt?: str, positions?: int, grossTotal?: num, totalQuantity?: num, customerName?: str|null, files?: T13[] }` +- `T6` = `{ quote: T7 }` +- `T7` = `{ id: int, number: str, type: str, entityId: int|null, date: str, lines: T23[], externalNumber?: str|null, createdAt?: str, positions?: int, grossTotal?: num, totalQuantity?: num, customerName?: str|null, files?: T13[] }` +- `T8` = `{ delivery: T9 }` +- `T9` = `{ id: int, number: str, type: str, supplierId: int|null, date: str, lines: T23[], files: T13[], externalNumber?: str|null, createdAt?: str, ledger?: T43 }` - `T10` = `{ labeltemplate: T12 }` - `T11` = `{ attachment: T13, fileUrl: str }` - `T12` = `{ id: int, name: str, width: num, height: num, dpi: int, type: str, content: T19, thumb?: str|null }` @@ -315,16 +315,16 @@ _none_ - Returns: `200 { deliveries: { id: int, number: str, type: str, supplierId: int|null, date: str, externalNumber?: str|null, createdAt?: str, ledger?: T43 }[] }` #### Create delivery — `POST /delivery` - Params: `body: { externalNumber: str, date: str, lines: T28[], supplierId?: int|null, files?: { mimetype: str, name: str, content: str, sort?: int, size?: int, hash?: str, created?: str, modified?: str, meta?: { [k]: str } }[] }` -- Returns: `201 T6` +- Returns: `201 T8` #### Delete delivery — `DELETE /delivery/{id}` - Params: `id: int` - Returns: `204 void` #### Get delivery — `GET /delivery/{id}` - Params: `id: int` -- Returns: `200 T6` +- Returns: `200 T8` #### Update delivery — `PATCH /delivery/{id}` - Params: `id: int, body: { externalNumber?: str|null, date?: str, supplierId?: int|null, lines?: T28[], files?: { mimetype: str, name: str, content: str, sort?: int, size?: int, hash?: str, created?: str, modified?: str, meta?: { [k]: str } }[] }` -- Returns: `200 T6` +- Returns: `200 T8` #### Delete delivery file attachment — `DELETE /delivery/{id}/file/{fileId}` - Params: `id: int, fileId: int` - Returns: `204 void` @@ -428,7 +428,7 @@ _none_ - Params: `query: offset?: int, limit?: int, search?: str, onlyUnpaid?: bool, onlyUndelivered?: bool, seekMonths?: int` - Returns: `200 { orders: T2[], total: int, unfilteredTotal: int, offset: int, limit: int }` #### Create order — `POST /order` -- Params: `body: { number: str, date: str, lines: T28[], entityId?: int|null }` +- Params: `body: { number: str, date: str, lines: T28[], entityId?: int|null, externalNumber?: str|null }` - Returns: `201 T1` #### Delete order — `DELETE /order/{id}` - Params: `id: int` @@ -437,7 +437,7 @@ _none_ - Params: `id: int` - Returns: `200 T1` #### Update order — `PATCH /order/{id}` -- Params: `id: int, body: { number?: str, date?: str, entityId?: int|null, lines?: T28[] }` +- Params: `id: int, body: { number?: str, date?: str, entityId?: int|null, externalNumber?: str|null, lines?: T28[] }` - Returns: `200 T1` #### Delete order file attachment — `DELETE /order/{id}/file/{fileId}` - Params: `id: int, fileId: int` @@ -522,19 +522,19 @@ _none_ #### List quotes — `GET /quote` - Params: `query: offset?: int, limit?: int, search?: str, seekMonths?: int` -- Returns: `200 { quotes: T9[], total: int, unfilteredTotal: int, offset: int, limit: int }` +- Returns: `200 { quotes: T7[], total: int, unfilteredTotal: int, offset: int, limit: int }` #### Create quote — `POST /quote` -- Params: `body: { number: str, date: str, lines: T28[], entityId?: int|null }` -- Returns: `201 T8` +- Params: `body: { number: str, date: str, lines: T28[], entityId?: int|null, externalNumber?: str|null }` +- Returns: `201 T6` #### Delete quote — `DELETE /quote/{id}` - Params: `id: int` - Returns: `204 void` #### Get quote — `GET /quote/{id}` - Params: `id: int` -- Returns: `200 T8` +- Returns: `200 T6` #### Update quote — `PATCH /quote/{id}` -- Params: `id: int, body: { number?: str, date?: str, entityId?: int|null, lines?: T28[] }` -- Returns: `200 T8` +- Params: `id: int, body: { number?: str, date?: str, entityId?: int|null, externalNumber?: str|null, lines?: T28[] }` +- Returns: `200 T6` #### Delete quote file attachment — `DELETE /quote/{id}/file/{fileId}` - Params: `id: int, fileId: int` - Returns: `204 void` diff --git a/docs/api/routes/order/create.md b/docs/api/routes/order/create.md index ec14283..2130e22 100644 --- a/docs/api/routes/order/create.md +++ b/docs/api/routes/order/create.md @@ -17,6 +17,7 @@ Each line requires `sku` or `name`, `amount`, `net`, and `taxrate` (rate); `pu` | `number` | yes | string | | | `date` | yes | string | Document date / expected delivery | | `entityId` | no | integer | Customer entity (manifest.entity_id) | +| `externalNumber` | no | string | External customer reference number (manifest.external_number) | | `lines` | yes | ManifestLineInput[] | | ```json @@ -48,6 +49,7 @@ Created order "number": "…", "type": "order", "entityId": 1, + "externalNumber": "…", "date": "2026-08-10T00:00:00.000Z", "createdAt": "2026-08-10T00:00:00.000Z", "lines": [ diff --git a/docs/api/routes/order/get.md b/docs/api/routes/order/get.md index 33494bc..22ed581 100644 --- a/docs/api/routes/order/get.md +++ b/docs/api/routes/order/get.md @@ -23,6 +23,7 @@ Order "number": "…", "type": "order", "entityId": 1, + "externalNumber": "…", "date": "2026-08-10T00:00:00.000Z", "createdAt": "2026-08-10T00:00:00.000Z", "lines": [ diff --git a/docs/api/routes/order/list.md b/docs/api/routes/order/list.md index 6dc8d83..06d3077 100644 --- a/docs/api/routes/order/list.md +++ b/docs/api/routes/order/list.md @@ -32,6 +32,7 @@ Order list "number": "…", "type": "order", "entityId": 1, + "externalNumber": "…", "date": "2026-08-10T00:00:00.000Z", "createdAt": "2026-08-10T00:00:00.000Z", "lines": [ diff --git a/docs/api/routes/order/update.md b/docs/api/routes/order/update.md index 9b37e31..79cbab1 100644 --- a/docs/api/routes/order/update.md +++ b/docs/api/routes/order/update.md @@ -22,6 +22,7 @@ all lines; if omitted, leaves lines unchanged. Returns the full order. | `number` | no | string | | | `date` | no | string | Document date / expected delivery | | `entityId` | no | integer | | +| `externalNumber` | no | string | External customer reference number (manifest.external_number) | | `lines` | no | ManifestLineInput[] | | ```json @@ -42,6 +43,7 @@ Updated order "number": "…", "type": "order", "entityId": 1, + "externalNumber": "…", "date": "2026-08-10T00:00:00.000Z", "createdAt": "2026-08-10T00:00:00.000Z", "lines": [ diff --git a/docs/api/routes/quote/create.md b/docs/api/routes/quote/create.md index d61aaf1..c1e2867 100644 --- a/docs/api/routes/quote/create.md +++ b/docs/api/routes/quote/create.md @@ -17,6 +17,7 @@ Each line requires `sku` or `name`, `amount`, `net`, and `taxrate` (rate); `pu` | `number` | yes | string | | | `date` | yes | string | Document date / valid-until | | `entityId` | no | integer | Customer entity (manifest.entity_id) | +| `externalNumber` | no | string | External customer reference number (manifest.external_number) | | `lines` | yes | ManifestLineInput[] | | ```json @@ -48,6 +49,7 @@ Created quote "number": "…", "type": "quote", "entityId": 1, + "externalNumber": "…", "date": "2026-08-10T00:00:00.000Z", "createdAt": "2026-08-10T00:00:00.000Z", "positions": 1, diff --git a/docs/api/routes/quote/get.md b/docs/api/routes/quote/get.md index f055d6e..9803185 100644 --- a/docs/api/routes/quote/get.md +++ b/docs/api/routes/quote/get.md @@ -23,6 +23,7 @@ Quote "number": "…", "type": "quote", "entityId": 1, + "externalNumber": "…", "date": "2026-08-10T00:00:00.000Z", "createdAt": "2026-08-10T00:00:00.000Z", "positions": 1, diff --git a/docs/api/routes/quote/list.md b/docs/api/routes/quote/list.md index b0425cf..f9e1056 100644 --- a/docs/api/routes/quote/list.md +++ b/docs/api/routes/quote/list.md @@ -29,6 +29,7 @@ Quote list "number": "…", "type": "quote", "entityId": 1, + "externalNumber": "…", "date": "2026-08-10T00:00:00.000Z", "createdAt": "2026-08-10T00:00:00.000Z", "positions": 1, diff --git a/docs/api/routes/quote/update.md b/docs/api/routes/quote/update.md index 5acaea8..514222b 100644 --- a/docs/api/routes/quote/update.md +++ b/docs/api/routes/quote/update.md @@ -22,6 +22,7 @@ all lines; if omitted, leaves lines unchanged. Returns the full quote. | `number` | no | string | | | `date` | no | string | Document date / valid-until | | `entityId` | no | integer | | +| `externalNumber` | no | string | External customer reference number (manifest.external_number) | | `lines` | no | ManifestLineInput[] | | ```json @@ -42,6 +43,7 @@ Updated quote "number": "…", "type": "quote", "entityId": 1, + "externalNumber": "…", "date": "2026-08-10T00:00:00.000Z", "createdAt": "2026-08-10T00:00:00.000Z", "positions": 1, diff --git a/src/api/openapi.js b/src/api/openapi.js index 1b37959..9c87314 100644 --- a/src/api/openapi.js +++ b/src/api/openapi.js @@ -957,6 +957,10 @@ * type: integer * nullable: true * description: Customer (manifest.entity_id) + * externalNumber: + * type: string + * nullable: true + * description: External reference number (manifest.external_number) * date: * type: string * format: date-time @@ -1006,6 +1010,10 @@ * type: integer * nullable: true * description: Customer (manifest.entity_id) + * externalNumber: + * type: string + * nullable: true + * description: External customer reference number (manifest.external_number) * date: * type: string * format: date-time diff --git a/src/api/routes/order.js b/src/api/routes/order.js index d5c61c5..f8d2957 100644 --- a/src/api/routes/order.js +++ b/src/api/routes/order.js @@ -171,6 +171,10 @@ export function register(app, basePath = '') { * type: integer * nullable: true * description: Customer entity (manifest.entity_id) + * externalNumber: + * type: string + * nullable: true + * description: External customer reference number (manifest.external_number) * lines: * type: array * items: @@ -292,7 +296,7 @@ export function register(app, basePath = '') { return res.status(400).json({ error: selected.error }); } - const { number, date, createdAt, entityId, lines } = req.body ?? {}; + const { number, date, createdAt, entityId, externalNumber, lines } = req.body ?? {}; if (entityId !== undefined && entityId !== null && (typeof entityId !== 'number' || !Number.isInteger(entityId) || entityId <= 0)) { return res.status(400).json({ error: 'Invalid entityId' }); } @@ -303,6 +307,7 @@ export function register(app, basePath = '') { date, createdAt, entityId, + externalNumber: externalNumber !== undefined && externalNumber !== null ? String(externalNumber) : externalNumber, lines, }); res.status(201).json({ order }); @@ -397,6 +402,10 @@ export function register(app, basePath = '') { * entityId: * type: integer * nullable: true + * externalNumber: + * type: string + * nullable: true + * description: External customer reference number (manifest.external_number) * lines: * type: array * items: @@ -534,6 +543,11 @@ export function register(app, basePath = '') { } patch.entityId = body.entityId; } + if (Object.prototype.hasOwnProperty.call(body, 'externalNumber')) { + patch.externalNumber = body.externalNumber !== null && body.externalNumber !== undefined + ? String(body.externalNumber) + : null; + } if (Object.prototype.hasOwnProperty.call(body, 'lines')) { patch.lines = body.lines; } diff --git a/src/api/routes/quote.js b/src/api/routes/quote.js index 7382804..d35e71c 100644 --- a/src/api/routes/quote.js +++ b/src/api/routes/quote.js @@ -157,6 +157,10 @@ export function register(app, basePath = '') { * type: integer * nullable: true * description: Customer entity (manifest.entity_id) + * externalNumber: + * type: string + * nullable: true + * description: External customer reference number (manifest.external_number) * lines: * type: array * items: @@ -273,7 +277,7 @@ export function register(app, basePath = '') { return res.status(400).json({ error: selected.error }); } - const { number, date, createdAt, entityId, lines } = req.body ?? {}; + const { number, date, createdAt, entityId, externalNumber, lines } = req.body ?? {}; if (entityId !== undefined && entityId !== null && (typeof entityId !== 'number' || !Number.isInteger(entityId) || entityId <= 0)) { return res.status(400).json({ error: 'Invalid entityId' }); } @@ -284,6 +288,7 @@ export function register(app, basePath = '') { date, createdAt, entityId, + externalNumber: externalNumber !== undefined && externalNumber !== null ? String(externalNumber) : externalNumber, lines, }); res.status(201).json({ quote }); @@ -378,6 +383,10 @@ export function register(app, basePath = '') { * entityId: * type: integer * nullable: true + * externalNumber: + * type: string + * nullable: true + * description: External customer reference number (manifest.external_number) * lines: * type: array * items: @@ -515,6 +524,11 @@ export function register(app, basePath = '') { } patch.entityId = body.entityId; } + if (Object.prototype.hasOwnProperty.call(body, 'externalNumber')) { + patch.externalNumber = body.externalNumber !== null && body.externalNumber !== undefined + ? String(body.externalNumber) + : null; + } if (Object.prototype.hasOwnProperty.call(body, 'lines')) { patch.lines = body.lines; }