refactor(api): update manifest line schema docs with name and pu, update deliveryParsePdf model

This commit is contained in:
seb
2026-09-16 17:04:32 +02:00
parent ed36c534b9
commit ab6d018a1f
15 changed files with 142 additions and 70 deletions

View File

@@ -762,7 +762,7 @@
"Quote" "Quote"
], ],
"summary": "Create quote", "summary": "Create quote",
"description": "Creates a quote with header and lines in one transaction.\n`date` is the document date (valid-until).\n`entityId` must be a company customer (not Lieferanten/POS), or null.\nEach line requires `sku`, `amount`, `net`, and `tax` (rate); `rebate` defaults to `0`.\n", "description": "Creates a quote with header and lines in one transaction.\n`date` is the document date (valid-until).\n`entityId` must be a company customer (not Lieferanten/POS), or null.\nEach line requires `sku` or `name`, `amount`, `net`, and `tax` (rate); `pu` defaults to `1`; `rebate` defaults to `0`.\n",
"security": [ "security": [
{ {
"cookieAuth": [] "cookieAuth": []
@@ -808,6 +808,8 @@
"lines": [ "lines": [
{ {
"sku": "1", "sku": "1",
"name": "Sample Article",
"pu": 1,
"amount": 10, "amount": 10,
"net": 99.5, "net": 99.5,
"tax": 19 "tax": 19
@@ -2012,7 +2014,7 @@
"Order" "Order"
], ],
"summary": "Create order", "summary": "Create order",
"description": "Creates a sales order with header and lines in one transaction.\n`date` is the document date (expected delivery).\n`entityId` must be a company customer (not Lieferanten/POS), or null.\nEach line requires `sku`, `amount`, `net`, and `tax` (rate); `rebate` defaults to `0`.\n", "description": "Creates a sales order with header and lines in one transaction.\n`date` is the document date (expected delivery).\n`entityId` must be a company customer (not Lieferanten/POS), or null.\nEach line requires `sku` or `name`, `amount`, `net`, and `tax` (rate); `pu` defaults to `1`; `rebate` defaults to `0`.\n",
"security": [ "security": [
{ {
"cookieAuth": [] "cookieAuth": []
@@ -2058,6 +2060,8 @@
"lines": [ "lines": [
{ {
"sku": "1", "sku": "1",
"name": "Sample Article",
"pu": 1,
"amount": 10, "amount": 10,
"net": 99.5, "net": 99.5,
"tax": 19 "tax": 19
@@ -4223,7 +4227,7 @@
"Delivery" "Delivery"
], ],
"summary": "Create delivery", "summary": "Create delivery",
"description": "Creates a goods receipt with header and lines in one transaction.\nThe manifest `number` is allocated automatically via\n`nextNumber('delivery')`; the user-supplied reference is stored as\n`externalNumber`. Each line requires `sku`, `amount`, `net`, and\n`tax` (rate). `rebate` defaults to `0`; `transactedAmount` defaults\nto `amount`.\n", "description": "Creates a goods receipt with header and lines in one transaction.\nThe manifest `number` is allocated automatically via\n`nextNumber('delivery')`; the user-supplied reference is stored as\n`externalNumber`. Each line requires `sku` or `name`, `amount`, `net`, and\n`tax` (rate). `pu` defaults to `1`; `rebate` defaults to `0`.\n",
"security": [ "security": [
{ {
"cookieAuth": [] "cookieAuth": []
@@ -4268,6 +4272,8 @@
"lines": [ "lines": [
{ {
"sku": "1", "sku": "1",
"name": "Sample Article",
"pu": 1,
"amount": 10, "amount": 10,
"net": 99.5, "net": 99.5,
"tax": 19 "tax": 19
@@ -8940,11 +8946,11 @@
"type": "object", "type": "object",
"required": [ "required": [
"id", "id",
"articleId",
"sku", "sku",
"name",
"pu",
"amount", "amount",
"net", "net",
"transactedAmount",
"rebate", "rebate",
"tax", "tax",
"comment" "comment"
@@ -8953,29 +8959,31 @@
"id": { "id": {
"type": "integer" "type": "integer"
}, },
"articleId": {
"type": "integer",
"nullable": true
},
"sku": { "sku": {
"type": "string", "type": "string",
"nullable": true "nullable": true
}, },
"name": {
"type": "string",
"nullable": true,
"description": "Line item name or custom description"
},
"pu": {
"type": "number",
"description": "Packaging unit (defaults to 1)"
},
"amount": { "amount": {
"type": "number" "type": "number"
}, },
"net": { "net": {
"type": "number" "type": "number"
}, },
"transactedAmount": {
"type": "number"
},
"rebate": { "rebate": {
"type": "number" "type": "number"
}, },
"tax": { "tax": {
"type": "number", "type": "number",
"description": "tax.rate" "description": "tax.rate (manifestarticle.taxrate)"
}, },
"comment": { "comment": {
"type": "string", "type": "string",
@@ -8986,14 +8994,25 @@
"DeliveryLineInput": { "DeliveryLineInput": {
"type": "object", "type": "object",
"required": [ "required": [
"sku",
"amount", "amount",
"net", "net",
"tax" "tax"
], ],
"description": "Line item input. Requires `sku` or `name`.",
"properties": { "properties": {
"sku": { "sku": {
"type": "string" "type": "string",
"nullable": true,
"description": "SKU reference (sku or name is required)"
},
"name": {
"type": "string",
"nullable": true,
"description": "Line item name (sku or name is required)"
},
"pu": {
"type": "number",
"description": "Packaging unit (defaults to 1)"
}, },
"amount": { "amount": {
"type": "number" "type": "number"
@@ -9009,10 +9028,6 @@
"type": "number", "type": "number",
"description": "Defaults to 0" "description": "Defaults to 0"
}, },
"transactedAmount": {
"type": "number",
"description": "Defaults to amount"
},
"comment": { "comment": {
"type": "string", "type": "string",
"nullable": true "nullable": true
@@ -9044,27 +9059,33 @@
"type": "object", "type": "object",
"required": [ "required": [
"id", "id",
"articleId",
"sku", "sku",
"name",
"pu",
"amount", "amount",
"net", "net",
"rebate", "rebate",
"tax", "tax",
"comment" "comment"
], ],
"description": "Line shape for quote and order (no transactedAmount)", "description": "Line shape for quote and order",
"properties": { "properties": {
"id": { "id": {
"type": "integer" "type": "integer"
}, },
"articleId": {
"type": "integer",
"nullable": true
},
"sku": { "sku": {
"type": "string", "type": "string",
"nullable": true "nullable": true
}, },
"name": {
"type": "string",
"nullable": true,
"description": "Line item name or custom description"
},
"pu": {
"type": "number",
"description": "Packaging unit (defaults to 1)"
},
"amount": { "amount": {
"type": "number" "type": "number"
}, },
@@ -9076,7 +9097,7 @@
}, },
"tax": { "tax": {
"type": "number", "type": "number",
"description": "tax.rate" "description": "tax.rate (manifestarticle.taxrate)"
}, },
"comment": { "comment": {
"type": "string", "type": "string",
@@ -9087,14 +9108,25 @@
"ManifestLineInput": { "ManifestLineInput": {
"type": "object", "type": "object",
"required": [ "required": [
"sku",
"amount", "amount",
"net", "net",
"tax" "tax"
], ],
"description": "Line item input. Requires `sku` or `name`.",
"properties": { "properties": {
"sku": { "sku": {
"type": "string" "type": "string",
"nullable": true,
"description": "SKU reference (sku or name is required)"
},
"name": {
"type": "string",
"nullable": true,
"description": "Line item name (sku or name is required)"
},
"pu": {
"type": "number",
"description": "Packaging unit (defaults to 1)"
}, },
"amount": { "amount": {
"type": "number" "type": "number"

View File

@@ -7,9 +7,8 @@ Create delivery
Creates a goods receipt with header and lines in one transaction. Creates a goods receipt with header and lines in one transaction.
The manifest `number` is allocated automatically via The manifest `number` is allocated automatically via
`nextNumber('delivery')`; the user-supplied reference is stored as `nextNumber('delivery')`; the user-supplied reference is stored as
`externalNumber`. Each line requires `sku`, `amount`, `net`, and `externalNumber`. Each line requires `sku` or `name`, `amount`, `net`, and
`tax` (rate). `rebate` defaults to `0`; `transactedAmount` defaults `tax` (rate). `pu` defaults to `1`; `rebate` defaults to `0`.
to `amount`.
## Body (JSON) ## Body (JSON)
@@ -22,6 +21,8 @@ to `amount`.
"lines": [ "lines": [
{ {
"sku": "1", "sku": "1",
"name": "Sample Article",
"pu": 1,
"amount": 10, "amount": 10,
"net": 99.5, "net": 99.5,
"tax": 19 "tax": 19
@@ -46,11 +47,11 @@ Created delivery
"lines": [ "lines": [
{ {
"id": 1, "id": 1,
"articleId": 1,
"sku": "…", "sku": "…",
"name": "…",
"pu": 1,
"amount": 1, "amount": 1,
"net": 1, "net": 1,
"transactedAmount": 1,
"rebate": 1, "rebate": 1,
"tax": 1, "tax": 1,
"comment": "…" "comment": "…"

View File

@@ -28,11 +28,11 @@ Delivery
"lines": [ "lines": [
{ {
"id": 1, "id": 1,
"articleId": 1,
"sku": "…", "sku": "…",
"name": "…",
"pu": 1,
"amount": 1, "amount": 1,
"net": 1, "net": 1,
"transactedAmount": 1,
"rebate": 1, "rebate": 1,
"tax": 1, "tax": 1,
"comment": "…" "comment": "…"

View File

@@ -41,11 +41,11 @@ Updated delivery
"lines": [ "lines": [
{ {
"id": 1, "id": 1,
"articleId": 1,
"sku": "…", "sku": "…",
"name": "…",
"pu": 1,
"amount": 1, "amount": 1,
"net": 1, "net": 1,
"transactedAmount": 1,
"rebate": 1, "rebate": 1,
"tax": 1, "tax": 1,
"comment": "…" "comment": "…"

View File

@@ -7,7 +7,7 @@ Create order
Creates a sales order with header and lines in one transaction. Creates a sales order with header and lines in one transaction.
`date` is the document date (expected delivery). `date` is the document date (expected delivery).
`entityId` must be a company customer (not Lieferanten/POS), or null. `entityId` must be a company customer (not Lieferanten/POS), or null.
Each line requires `sku`, `amount`, `net`, and `tax` (rate); `rebate` defaults to `0`. Each line requires `sku` or `name`, `amount`, `net`, and `tax` (rate); `pu` defaults to `1`; `rebate` defaults to `0`.
## Body (JSON) ## Body (JSON)
@@ -20,6 +20,8 @@ Each line requires `sku`, `amount`, `net`, and `tax` (rate); `rebate` defaults t
"lines": [ "lines": [
{ {
"sku": "1", "sku": "1",
"name": "Sample Article",
"pu": 1,
"amount": 10, "amount": 10,
"net": 99.5, "net": 99.5,
"tax": 19 "tax": 19
@@ -43,8 +45,9 @@ Created order
"lines": [ "lines": [
{ {
"id": 1, "id": 1,
"articleId": 1,
"sku": "…", "sku": "…",
"name": "…",
"pu": 1,
"amount": 1, "amount": 1,
"net": 1, "net": 1,
"rebate": 1, "rebate": 1,

View File

@@ -27,8 +27,9 @@ Order
"lines": [ "lines": [
{ {
"id": 1, "id": 1,
"articleId": 1,
"sku": "…", "sku": "…",
"name": "…",
"pu": 1,
"amount": 1, "amount": 1,
"net": 1, "net": 1,
"rebate": 1, "rebate": 1,

View File

@@ -39,8 +39,9 @@ Updated order
"lines": [ "lines": [
{ {
"id": 1, "id": 1,
"articleId": 1,
"sku": "…", "sku": "…",
"name": "…",
"pu": 1,
"amount": 1, "amount": 1,
"net": 1, "net": 1,
"rebate": 1, "rebate": 1,

View File

@@ -7,7 +7,7 @@ Create quote
Creates a quote with header and lines in one transaction. Creates a quote with header and lines in one transaction.
`date` is the document date (valid-until). `date` is the document date (valid-until).
`entityId` must be a company customer (not Lieferanten/POS), or null. `entityId` must be a company customer (not Lieferanten/POS), or null.
Each line requires `sku`, `amount`, `net`, and `tax` (rate); `rebate` defaults to `0`. Each line requires `sku` or `name`, `amount`, `net`, and `tax` (rate); `pu` defaults to `1`; `rebate` defaults to `0`.
## Body (JSON) ## Body (JSON)
@@ -20,6 +20,8 @@ Each line requires `sku`, `amount`, `net`, and `tax` (rate); `rebate` defaults t
"lines": [ "lines": [
{ {
"sku": "1", "sku": "1",
"name": "Sample Article",
"pu": 1,
"amount": 10, "amount": 10,
"net": 99.5, "net": 99.5,
"tax": 19 "tax": 19
@@ -43,8 +45,9 @@ Created quote
"lines": [ "lines": [
{ {
"id": 1, "id": 1,
"articleId": 1,
"sku": "…", "sku": "…",
"name": "…",
"pu": 1,
"amount": 1, "amount": 1,
"net": 1, "net": 1,
"rebate": 1, "rebate": 1,

View File

@@ -27,8 +27,9 @@ Quote
"lines": [ "lines": [
{ {
"id": 1, "id": 1,
"articleId": 1,
"sku": "…", "sku": "…",
"name": "…",
"pu": 1,
"amount": 1, "amount": 1,
"net": 1, "net": 1,
"rebate": 1, "rebate": 1,

View File

@@ -39,8 +39,9 @@ Updated quote
"lines": [ "lines": [
{ {
"id": 1, "id": 1,
"articleId": 1,
"sku": "…", "sku": "…",
"name": "…",
"pu": 1,
"amount": 1, "amount": 1,
"net": 1, "net": 1,
"rebate": 1, "rebate": 1,

View File

@@ -264,36 +264,48 @@
* format: date-time * format: date-time
* DeliveryLine: * DeliveryLine:
* type: object * type: object
* required: [id, articleId, sku, amount, net, transactedAmount, rebate, tax, comment] * required: [id, sku, name, pu, amount, net, rebate, tax, comment]
* properties: * properties:
* id: * id:
* type: integer * type: integer
* articleId:
* type: integer
* nullable: true
* sku: * sku:
* type: string * type: string
* nullable: true * nullable: true
* name:
* type: string
* nullable: true
* description: Line item name or custom description
* pu:
* type: number
* description: Packaging unit (defaults to 1)
* amount: * amount:
* type: number * type: number
* net: * net:
* type: number * type: number
* transactedAmount:
* type: number
* rebate: * rebate:
* type: number * type: number
* tax: * tax:
* type: number * type: number
* description: tax.rate * description: tax.rate (manifestarticle.taxrate)
* comment: * comment:
* type: string * type: string
* nullable: true * nullable: true
* DeliveryLineInput: * DeliveryLineInput:
* type: object * type: object
* required: [sku, amount, net, tax] * required: [amount, net, tax]
* description: Line item input. Requires `sku` or `name`.
* properties: * properties:
* sku: * sku:
* type: string * type: string
* nullable: true
* description: SKU reference (sku or name is required)
* name:
* type: string
* nullable: true
* description: Line item name (sku or name is required)
* pu:
* type: number
* description: Packaging unit (defaults to 1)
* amount: * amount:
* type: number * type: number
* net: * net:
@@ -304,9 +316,6 @@
* rebate: * rebate:
* type: number * type: number
* description: Defaults to 0 * description: Defaults to 0
* transactedAmount:
* type: number
* description: Defaults to amount
* comment: * comment:
* type: string * type: string
* nullable: true * nullable: true
@@ -322,17 +331,21 @@
* $ref: '#/components/schemas/DeliveryLine' * $ref: '#/components/schemas/DeliveryLine'
* ManifestLine: * ManifestLine:
* type: object * type: object
* required: [id, articleId, sku, amount, net, rebate, tax, comment] * required: [id, sku, name, pu, amount, net, rebate, tax, comment]
* description: Line shape for quote and order (no transactedAmount) * description: Line shape for quote and order
* properties: * properties:
* id: * id:
* type: integer * type: integer
* articleId:
* type: integer
* nullable: true
* sku: * sku:
* type: string * type: string
* nullable: true * nullable: true
* name:
* type: string
* nullable: true
* description: Line item name or custom description
* pu:
* type: number
* description: Packaging unit (defaults to 1)
* amount: * amount:
* type: number * type: number
* net: * net:
@@ -341,16 +354,26 @@
* type: number * type: number
* tax: * tax:
* type: number * type: number
* description: tax.rate * description: tax.rate (manifestarticle.taxrate)
* comment: * comment:
* type: string * type: string
* nullable: true * nullable: true
* ManifestLineInput: * ManifestLineInput:
* type: object * type: object
* required: [sku, amount, net, tax] * required: [amount, net, tax]
* description: Line item input. Requires `sku` or `name`.
* properties: * properties:
* sku: * sku:
* type: string * type: string
* nullable: true
* description: SKU reference (sku or name is required)
* name:
* type: string
* nullable: true
* description: Line item name (sku or name is required)
* pu:
* type: number
* description: Packaging unit (defaults to 1)
* amount: * amount:
* type: number * type: number
* net: * net:

View File

@@ -81,9 +81,8 @@ export function register(app, basePath = '') {
* Creates a goods receipt with header and lines in one transaction. * Creates a goods receipt with header and lines in one transaction.
* The manifest `number` is allocated automatically via * The manifest `number` is allocated automatically via
* `nextNumber('delivery')`; the user-supplied reference is stored as * `nextNumber('delivery')`; the user-supplied reference is stored as
* `externalNumber`. Each line requires `sku`, `amount`, `net`, and * `externalNumber`. Each line requires `sku` or `name`, `amount`, `net`, and
* `tax` (rate). `rebate` defaults to `0`; `transactedAmount` defaults * `tax` (rate). `pu` defaults to `1`; `rebate` defaults to `0`.
* to `amount`.
* security: * security:
* - cookieAuth: [] * - cookieAuth: []
* x-markdown: delivery/create.md * x-markdown: delivery/create.md
@@ -114,6 +113,8 @@ export function register(app, basePath = '') {
* supplierId: 1 * supplierId: 1
* lines: * lines:
* - sku: '1' * - sku: '1'
* name: 'Sample Article'
* pu: 1
* amount: 10 * amount: 10
* net: 99.5 * net: 99.5
* tax: 19 * tax: 19

View File

@@ -194,8 +194,9 @@ export function register(app, basePath = '') {
// ── Fetch OpenRouter API key from company settings ──────────────── // ── Fetch OpenRouter API key from company settings ────────────────
let apiKey; let apiKey;
try { try {
const setting = await dbCompanySetting.getByKey(req.user.id, 'keys.openrouter'); const setting = await dbCompanySetting.getByKey(req.user.id, 'keys.openrouter', { maskWriteonly: false });
apiKey = setting?.value; apiKey = setting?.value;
console.log('parsePDF debug: user=', req.user.id, 'setting=', setting ? { ...setting, value: setting.value ? `${setting.value.slice(0, 8)}... (len=${setting.value.length})` : null } : null);
} catch (err) { } catch (err) {
console.error('parsePDF: failed to read OpenRouter key:', err); console.error('parsePDF: failed to read OpenRouter key:', err);
} }
@@ -356,7 +357,7 @@ export function register(app, basePath = '') {
}); });
// ── LLMOrbiter setup ───────────────────────────────────────────── // ── LLMOrbiter setup ─────────────────────────────────────────────
const model = '~openai/gpt-sol-latest'; const model = '~openai/gpt-luna-latest:floor';
const provider = new OpenRouterProvider({ apiKey }); const provider = new OpenRouterProvider({ apiKey });
const orbiter = new LLMOrbiter(provider, { const orbiter = new LLMOrbiter(provider, {
onStatus: (status) => sseWrite(res, 'status', { message: status }), onStatus: (status) => sseWrite(res, 'status', { message: status }),

View File

@@ -81,7 +81,7 @@ export function register(app, basePath = '') {
* Creates a sales order with header and lines in one transaction. * Creates a sales order with header and lines in one transaction.
* `date` is the document date (expected delivery). * `date` is the document date (expected delivery).
* `entityId` must be a company customer (not Lieferanten/POS), or null. * `entityId` must be a company customer (not Lieferanten/POS), or null.
* Each line requires `sku`, `amount`, `net`, and `tax` (rate); `rebate` defaults to `0`. * Each line requires `sku` or `name`, `amount`, `net`, and `tax` (rate); `pu` defaults to `1`; `rebate` defaults to `0`.
* security: * security:
* - cookieAuth: [] * - cookieAuth: []
* x-markdown: order/create.md * x-markdown: order/create.md
@@ -113,6 +113,8 @@ export function register(app, basePath = '') {
* entityId: 1 * entityId: 1
* lines: * lines:
* - sku: '1' * - sku: '1'
* name: 'Sample Article'
* pu: 1
* amount: 10 * amount: 10
* net: 99.5 * net: 99.5
* tax: 19 * tax: 19

View File

@@ -81,7 +81,7 @@ export function register(app, basePath = '') {
* Creates a quote with header and lines in one transaction. * Creates a quote with header and lines in one transaction.
* `date` is the document date (valid-until). * `date` is the document date (valid-until).
* `entityId` must be a company customer (not Lieferanten/POS), or null. * `entityId` must be a company customer (not Lieferanten/POS), or null.
* Each line requires `sku`, `amount`, `net`, and `tax` (rate); `rebate` defaults to `0`. * Each line requires `sku` or `name`, `amount`, `net`, and `tax` (rate); `pu` defaults to `1`; `rebate` defaults to `0`.
* security: * security:
* - cookieAuth: [] * - cookieAuth: []
* x-markdown: quote/create.md * x-markdown: quote/create.md
@@ -113,6 +113,8 @@ export function register(app, basePath = '') {
* entityId: 1 * entityId: 1
* lines: * lines:
* - sku: '1' * - sku: '1'
* name: 'Sample Article'
* pu: 1
* amount: 10 * amount: 10
* net: 99.5 * net: 99.5
* tax: 19 * tax: 19