This commit is contained in:
seb
2026-09-26 07:34:35 +02:00
parent 67758d5ec2
commit f0176e0fe0
19 changed files with 106 additions and 8 deletions

View File

@@ -30,3 +30,5 @@ KAT_LISTS=0
# Tax zone name for VAT rates (tSteuerzone.cName) # Tax zone name for VAT rates (tSteuerzone.cName)
STEUER_ZONE=Zone-EU STEUER_ZONE=Zone-EU
OPENROUTER_FREE_KEY=sk-or-v1-3d3c4e

View File

@@ -8173,6 +8173,16 @@
} }
} }
} }
},
"409": {
"description": "SKU already exists",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Error"
}
}
}
} }
} }
} }
@@ -10444,6 +10454,24 @@
"date": { "date": {
"type": "string", "type": "string",
"format": "date-time" "format": "date-time"
},
"createdAt": {
"type": "string",
"format": "date-time"
},
"ledger": {
"type": "object",
"description": "Ledger booking summary for this delivery",
"properties": {
"totalPositions": {
"type": "integer",
"description": "Total number of position lines on this manifest"
},
"completelyOnLedgerPositions": {
"type": "integer",
"description": "Number of positions whose quantity is fully transacted in the ledger"
}
}
} }
} }
}, },
@@ -10818,6 +10846,10 @@
"type": "string", "type": "string",
"format": "date-time", "format": "date-time",
"description": "Document date / valid-until" "description": "Document date / valid-until"
},
"createdAt": {
"type": "string",
"format": "date-time"
} }
} }
}, },
@@ -10873,6 +10905,10 @@
"type": "string", "type": "string",
"format": "date-time", "format": "date-time",
"description": "Document date / expected delivery" "description": "Document date / expected delivery"
},
"createdAt": {
"type": "string",
"format": "date-time"
} }
} }
}, },

View File

@@ -42,6 +42,7 @@ Created
| 401 | Unauthorized — `{"error":"…"}` | | 401 | Unauthorized — `{"error":"…"}` |
| 403 | Not authorized for parent category — `{"error":"…"}` | | 403 | Not authorized for parent category — `{"error":"…"}` |
| 404 | Parent not found — `{"error":"…"}` | | 404 | Parent not found — `{"error":"…"}` |
| 409 | SKU already exists — `{"error":"…"}` |
--- ---

View File

@@ -59,6 +59,11 @@ Created delivery
"supplierId": 1, "supplierId": 1,
"externalNumber": "…", "externalNumber": "…",
"date": "2026-08-10T00:00:00.000Z", "date": "2026-08-10T00:00:00.000Z",
"createdAt": "2026-08-10T00:00:00.000Z",
"ledger": {
"totalPositions": 1,
"completelyOnLedgerPositions": 1
},
"lines": [ "lines": [
{ {
"id": 1, "id": 1,

View File

@@ -25,6 +25,11 @@ Delivery
"supplierId": 1, "supplierId": 1,
"externalNumber": "…", "externalNumber": "…",
"date": "2026-08-10T00:00:00.000Z", "date": "2026-08-10T00:00:00.000Z",
"createdAt": "2026-08-10T00:00:00.000Z",
"ledger": {
"totalPositions": 1,
"completelyOnLedgerPositions": 1
},
"lines": [ "lines": [
{ {
"id": 1, "id": 1,

View File

@@ -21,7 +21,12 @@ Delivery list
"type": "delivery", "type": "delivery",
"supplierId": 1, "supplierId": 1,
"externalNumber": "…", "externalNumber": "…",
"date": "2026-08-10T00:00:00.000Z" "date": "2026-08-10T00:00:00.000Z",
"createdAt": "2026-08-10T00:00:00.000Z",
"ledger": {
"totalPositions": 1,
"completelyOnLedgerPositions": 1
}
} }
] ]
} }

View File

@@ -46,6 +46,11 @@ Updated delivery
"supplierId": 1, "supplierId": 1,
"externalNumber": "…", "externalNumber": "…",
"date": "2026-08-10T00:00:00.000Z", "date": "2026-08-10T00:00:00.000Z",
"createdAt": "2026-08-10T00:00:00.000Z",
"ledger": {
"totalPositions": 1,
"completelyOnLedgerPositions": 1
},
"lines": [ "lines": [
{ {
"id": 1, "id": 1,

View File

@@ -42,6 +42,7 @@ Created order
"type": "order", "type": "order",
"entityId": 1, "entityId": 1,
"date": "2026-08-10T00:00:00.000Z", "date": "2026-08-10T00:00:00.000Z",
"createdAt": "2026-08-10T00:00:00.000Z",
"lines": [ "lines": [
{ {
"id": 1, "id": 1,

View File

@@ -24,6 +24,7 @@ Order
"type": "order", "type": "order",
"entityId": 1, "entityId": 1,
"date": "2026-08-10T00:00:00.000Z", "date": "2026-08-10T00:00:00.000Z",
"createdAt": "2026-08-10T00:00:00.000Z",
"lines": [ "lines": [
{ {
"id": 1, "id": 1,

View File

@@ -20,7 +20,8 @@ Order list
"number": "…", "number": "…",
"type": "order", "type": "order",
"entityId": 1, "entityId": 1,
"date": "2026-08-10T00:00:00.000Z" "date": "2026-08-10T00:00:00.000Z",
"createdAt": "2026-08-10T00:00:00.000Z"
} }
] ]
} }

View File

@@ -36,6 +36,7 @@ Updated order
"type": "order", "type": "order",
"entityId": 1, "entityId": 1,
"date": "2026-08-10T00:00:00.000Z", "date": "2026-08-10T00:00:00.000Z",
"createdAt": "2026-08-10T00:00:00.000Z",
"lines": [ "lines": [
{ {
"id": 1, "id": 1,

View File

@@ -42,6 +42,7 @@ Created quote
"type": "quote", "type": "quote",
"entityId": 1, "entityId": 1,
"date": "2026-08-10T00:00:00.000Z", "date": "2026-08-10T00:00:00.000Z",
"createdAt": "2026-08-10T00:00:00.000Z",
"lines": [ "lines": [
{ {
"id": 1, "id": 1,

View File

@@ -24,6 +24,7 @@ Quote
"type": "quote", "type": "quote",
"entityId": 1, "entityId": 1,
"date": "2026-08-10T00:00:00.000Z", "date": "2026-08-10T00:00:00.000Z",
"createdAt": "2026-08-10T00:00:00.000Z",
"lines": [ "lines": [
{ {
"id": 1, "id": 1,

View File

@@ -20,7 +20,8 @@ Quote list
"number": "…", "number": "…",
"type": "quote", "type": "quote",
"entityId": 1, "entityId": 1,
"date": "2026-08-10T00:00:00.000Z" "date": "2026-08-10T00:00:00.000Z",
"createdAt": "2026-08-10T00:00:00.000Z"
} }
] ]
} }

View File

@@ -36,6 +36,7 @@ Updated quote
"type": "quote", "type": "quote",
"entityId": 1, "entityId": 1,
"date": "2026-08-10T00:00:00.000Z", "date": "2026-08-10T00:00:00.000Z",
"createdAt": "2026-08-10T00:00:00.000Z",
"lines": [ "lines": [
{ {
"id": 1, "id": 1,

View File

@@ -361,6 +361,19 @@
* date: * date:
* type: string * type: string
* format: date-time * format: date-time
* createdAt:
* type: string
* format: date-time
* ledger:
* type: object
* description: Ledger booking summary for this delivery
* properties:
* totalPositions:
* type: integer
* description: Total number of position lines on this manifest
* completelyOnLedgerPositions:
* type: integer
* description: Number of positions whose quantity is fully transacted in the ledger
* DeliveryLine: * DeliveryLine:
* type: object * type: object
* required: [id, sku, name, pu, amount, net, rebate, taxrate, comment] * required: [id, sku, name, pu, amount, net, rebate, taxrate, comment]
@@ -591,6 +604,9 @@
* type: string * type: string
* format: date-time * format: date-time
* description: Document date / valid-until * description: Document date / valid-until
* createdAt:
* type: string
* format: date-time
* Quote: * Quote:
* allOf: * allOf:
* - $ref: '#/components/schemas/QuoteSummary' * - $ref: '#/components/schemas/QuoteSummary'
@@ -620,6 +636,9 @@
* type: string * type: string
* format: date-time * format: date-time
* description: Document date / expected delivery * description: Document date / expected delivery
* createdAt:
* type: string
* format: date-time
* Order: * Order:
* allOf: * allOf:
* - $ref: '#/components/schemas/OrderSummary' * - $ref: '#/components/schemas/OrderSummary'

View File

@@ -47,7 +47,7 @@ function parseDeliveryPayload(req) {
throw new Error('Invalid delivery'); throw new Error('Invalid delivery');
} }
const { externalNumber, date, supplierId, lines } = payload; const { externalNumber, date, createdAt, supplierId, lines } = payload;
let files = payload.files; let files = payload.files;
// If binary files were uploaded via multer: // If binary files were uploaded via multer:
if (Array.isArray(req.files) && req.files.length > 0) { if (Array.isArray(req.files) && req.files.length > 0) {
@@ -96,7 +96,7 @@ function parseDeliveryPayload(req) {
}; };
}); });
} }
return { payload, externalNumber, date, supplierId, lines, files }; return { payload, externalNumber, date, createdAt, supplierId, lines, files };
} }
function requireSelectedCompany(req) { function requireSelectedCompany(req) {
@@ -354,11 +354,12 @@ export function register(app, basePath = '') {
} }
try { try {
const { externalNumber, date, supplierId, lines, files } = parseDeliveryPayload(req); const { externalNumber, date, createdAt, supplierId, lines, files } = parseDeliveryPayload(req);
logDeliveryFiles(files, 'create'); logDeliveryFiles(files, 'create');
const delivery = await db.create(req.user.id, { const delivery = await db.create(req.user.id, {
externalNumber, externalNumber,
date, date,
createdAt,
supplierId, supplierId,
lines, lines,
files, files,
@@ -628,6 +629,9 @@ export function register(app, basePath = '') {
if (Object.prototype.hasOwnProperty.call(parsed.payload, 'date')) { if (Object.prototype.hasOwnProperty.call(parsed.payload, 'date')) {
patch.date = parsed.date; patch.date = parsed.date;
} }
if (Object.prototype.hasOwnProperty.call(parsed.payload, 'createdAt')) {
patch.createdAt = parsed.createdAt;
}
if (Object.prototype.hasOwnProperty.call(parsed.payload, 'supplierId')) { if (Object.prototype.hasOwnProperty.call(parsed.payload, 'supplierId')) {
patch.supplierId = parsed.supplierId; patch.supplierId = parsed.supplierId;
} }

View File

@@ -175,12 +175,13 @@ export function register(app, basePath = '') {
return res.status(400).json({ error: selected.error }); return res.status(400).json({ error: selected.error });
} }
const { number, date, entityId, lines } = req.body ?? {}; const { number, date, createdAt, entityId, lines } = req.body ?? {};
try { try {
const order = await db.create(req.user.id, { const order = await db.create(req.user.id, {
number, number,
date, date,
createdAt,
entityId, entityId,
lines, lines,
}); });
@@ -396,6 +397,9 @@ export function register(app, basePath = '') {
if (Object.prototype.hasOwnProperty.call(body, 'date')) { if (Object.prototype.hasOwnProperty.call(body, 'date')) {
patch.date = body.date; patch.date = body.date;
} }
if (Object.prototype.hasOwnProperty.call(body, 'createdAt')) {
patch.createdAt = body.createdAt;
}
if (Object.prototype.hasOwnProperty.call(body, 'entityId')) { if (Object.prototype.hasOwnProperty.call(body, 'entityId')) {
patch.entityId = body.entityId; patch.entityId = body.entityId;
} }

View File

@@ -175,12 +175,13 @@ export function register(app, basePath = '') {
return res.status(400).json({ error: selected.error }); return res.status(400).json({ error: selected.error });
} }
const { number, date, entityId, lines } = req.body ?? {}; const { number, date, createdAt, entityId, lines } = req.body ?? {};
try { try {
const quote = await db.create(req.user.id, { const quote = await db.create(req.user.id, {
number, number,
date, date,
createdAt,
entityId, entityId,
lines, lines,
}); });
@@ -396,6 +397,9 @@ export function register(app, basePath = '') {
if (Object.prototype.hasOwnProperty.call(body, 'date')) { if (Object.prototype.hasOwnProperty.call(body, 'date')) {
patch.date = body.date; patch.date = body.date;
} }
if (Object.prototype.hasOwnProperty.call(body, 'createdAt')) {
patch.createdAt = body.createdAt;
}
if (Object.prototype.hasOwnProperty.call(body, 'entityId')) { if (Object.prototype.hasOwnProperty.call(body, 'entityId')) {
patch.entityId = body.entityId; patch.entityId = body.entityId;
} }