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)
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": {
"type": "string",
"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",
"format": "date-time",
"description": "Document date / valid-until"
},
"createdAt": {
"type": "string",
"format": "date-time"
}
}
},
@@ -10873,6 +10905,10 @@
"type": "string",
"format": "date-time",
"description": "Document date / expected delivery"
},
"createdAt": {
"type": "string",
"format": "date-time"
}
}
},

View File

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

View File

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

View File

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

View File

@@ -21,7 +21,12 @@ Delivery list
"type": "delivery",
"supplierId": 1,
"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,
"externalNumber": "…",
"date": "2026-08-10T00:00:00.000Z",
"createdAt": "2026-08-10T00:00:00.000Z",
"ledger": {
"totalPositions": 1,
"completelyOnLedgerPositions": 1
},
"lines": [
{
"id": 1,

View File

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

View File

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

View File

@@ -20,7 +20,8 @@ Order list
"number": "…",
"type": "order",
"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",
"entityId": 1,
"date": "2026-08-10T00:00:00.000Z",
"createdAt": "2026-08-10T00:00:00.000Z",
"lines": [
{
"id": 1,

View File

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

View File

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

View File

@@ -20,7 +20,8 @@ Quote list
"number": "…",
"type": "quote",
"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",
"entityId": 1,
"date": "2026-08-10T00:00:00.000Z",
"createdAt": "2026-08-10T00:00:00.000Z",
"lines": [
{
"id": 1,

View File

@@ -361,6 +361,19 @@
* date:
* type: string
* 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:
* type: object
* required: [id, sku, name, pu, amount, net, rebate, taxrate, comment]
@@ -591,6 +604,9 @@
* type: string
* format: date-time
* description: Document date / valid-until
* createdAt:
* type: string
* format: date-time
* Quote:
* allOf:
* - $ref: '#/components/schemas/QuoteSummary'
@@ -620,6 +636,9 @@
* type: string
* format: date-time
* description: Document date / expected delivery
* createdAt:
* type: string
* format: date-time
* Order:
* allOf:
* - $ref: '#/components/schemas/OrderSummary'

View File

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

View File

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