From 45369d11da082efb367e8428abf877be64f5d7ed Mon Sep 17 00:00:00 2001 From: seb Date: Sun, 4 Oct 2026 21:22:00 +0200 Subject: [PATCH] u --- docs/api/README.md | 2 +- docs/api/routes-all.md | 18 +++--- docs/api/routes.md | 16 ++--- .../routes/article/_sku/articlelist.put.md | 4 +- docs/api/routes/article/_sku/children.get.md | 8 +-- docs/api/routes/article/_sku/children.post.md | 12 ++-- docs/api/routes/article/_sku/children.put.md | 16 ++--- .../routes/article/_sku/children/_childSku.md | 8 +-- .../routes/article/_sku/optionslist.put.md | 4 +- .../article/_sku/{father.md => parent.md} | 24 ++++---- docs/api/routes/article/set-prices.md | 2 +- docs/api/routes/category/articles.md | 2 +- .../routes/public/_companyId/articles/_sku.md | 4 +- docs/api/routes/stock/adjust.md | 2 +- scripts/migrate-parent-rename.mssql.sql | 58 +++++++++++++++++++ scripts/migrate-parent-rename.sqlite.sql | 14 +++++ 16 files changed, 133 insertions(+), 61 deletions(-) rename docs/api/routes/article/_sku/{father.md => parent.md} (64%) create mode 100644 scripts/migrate-parent-rename.mssql.sql create mode 100644 scripts/migrate-parent-rename.sqlite.sql diff --git a/docs/api/README.md b/docs/api/README.md index c70af5d..bdacf76 100644 --- a/docs/api/README.md +++ b/docs/api/README.md @@ -48,13 +48,13 @@ Generated from `@openapi` annotations in [`src/api/routes/`](../../src/api/route | [`routes/article/_sku/children.put.md`](routes/article/_sku/children.put.md) | `PUT /article/{sku}/children` | | [`routes/article/_sku/children/_childSku.md`](routes/article/_sku/children/_childSku.md) | `DELETE /article/{sku}/children/{childSku}` | | [`routes/article/set-eans.md`](routes/article/set-eans.md) | `PUT /article/{sku}/eans` | -| [`routes/article/_sku/father.md`](routes/article/_sku/father.md) | `POST /article/{sku}/father` | | [`routes/article/history.md`](routes/article/history.md) | `GET /article/{sku}/history` | | [`routes/article/add-image.md`](routes/article/add-image.md) | `POST /article/{sku}/image` | | [`routes/article/delete-image.md`](routes/article/delete-image.md) | `DELETE /article/{sku}/image/{fullHash}` | | [`routes/article/order-images.md`](routes/article/order-images.md) | `PUT /article/{sku}/images/order` | | [`routes/article/_sku/optionslist.get.md`](routes/article/_sku/optionslist.get.md) | `GET /article/{sku}/optionslist` | | [`routes/article/_sku/optionslist.put.md`](routes/article/_sku/optionslist.put.md) | `PUT /article/{sku}/optionslist` | +| [`routes/article/_sku/parent.md`](routes/article/_sku/parent.md) | `POST /article/{sku}/parent` | | [`routes/article/set-prices.md`](routes/article/set-prices.md) | `PUT /article/{sku}/prices` | | [`routes/article/_sku/print.md`](routes/article/_sku/print.md) | `POST /article/{sku}/print` | | [`routes/article/_sku/property.get.md`](routes/article/_sku/property.get.md) | `GET /article/{sku}/property` | diff --git a/docs/api/routes-all.md b/docs/api/routes-all.md index ffbe6e1..983bc75 100644 --- a/docs/api/routes-all.md +++ b/docs/api/routes-all.md @@ -47,24 +47,21 @@ Overview of all 181 API endpoints across all modules. #### Replace article categories by SKU — `PUT /article/{sku}/categories` - Params: `sku: string, body: { categoryIds: integer[] }` - Returns: `200 { article: { id: integer, sku: string, name: string, slug: string, track_stock: boolean, unitamount: number, weight: number, unit: object, brand: object, categoryIds: integer[], photos: { sort: integer, fullHash: string, fullW: integer, fullH: integer, fullSize: integer, thumbW: integer, thumbH: integer, thumbHash: string }[], eans: string[], prices: { minmultiplier: number, net: number, taxRate: number, customergroupId: integer }[], suppliers: { id: integer, articleId: integer, entityId: integer, supplierName: string, sku: string, pu: number, stock: number, sort: integer, priceId: integer, price: { net: number, taxId: integer, taxRate: number } }[] } }` -#### List child articles of a father article — `GET /article/{sku}/children` +#### List child articles of a parent article — `GET /article/{sku}/children` - Params: `sku: string` -- Returns: `200 { children: { id: integer, sku: string, name: string, fathersort: integer, attributeValueId: integer, attributeValue: string }[] }` -#### Create and attach a new child article to a father article — `POST /article/{sku}/children` +- Returns: `200 { children: { id: integer, sku: string, name: string, parentsort: integer, attributeValueId: integer, attributeValue: string }[] }` +#### Create and attach a new child article to a parent article — `POST /article/{sku}/children` - Params: `sku: string, body: { attributeValueId?: integer, value?: string, name?: string }` - Returns: `201 { article: { id: integer, categoryId: integer, name: string, sku: string, track_stock: boolean } }` -#### Attach an existing article as a child to a father article — `PUT /article/{sku}/children` +#### Attach an existing article as a child to a parent article — `PUT /article/{sku}/children` - Params: `sku: string, body: { sku: string, attributeValueId?: integer, value?: string, reparent?: boolean }` - Returns: `200 { article: { id: integer, categoryId: integer, name: string, sku: string, track_stock: boolean }, children: object[] }` -#### Remove a child article from a father article — `DELETE /article/{sku}/children/{childSku}` +#### Remove a child article from a parent article — `DELETE /article/{sku}/children/{childSku}` - Params: `sku: string, childSku: string, query: deleteArticle?: boolean` - Returns: `200 { success: boolean, deleted: boolean }` #### Replace article EANs by SKU — `PUT /article/{sku}/eans` - Params: `sku: string, body: { eans: string[] }` - Returns: `200 { article: { id: integer, sku: string, name: string, slug: string, track_stock: boolean, unitamount: number, weight: number, unit: object, brand: object, categoryIds: integer[], photos: { sort: integer, fullHash: string, fullW: integer, fullH: integer, fullSize: integer, thumbW: integer, thumbH: integer, thumbHash: string }[], eans: string[], prices: { minmultiplier: number, net: number, taxRate: number, customergroupId: integer }[], suppliers: { id: integer, articleId: integer, entityId: integer, supplierName: string, sku: string, pu: number, stock: number, sort: integer, priceId: integer, price: { net: number, taxId: integer, taxRate: number } }[] } }` -#### Toggle father mode for an article — `POST /article/{sku}/father` -- Params: `sku: string, body: { isFather: boolean, attributeNameId?: integer }` -- Returns: `200 { article: { id: integer, categoryId: integer, name: string, sku: string, track_stock: boolean } }` #### Get article history by SKU — `GET /article/{sku}/history` - Params: `sku: string, query: limit?: integer` - Returns: `200 { history: { id: integer, date: string, text: string }[], truncated: boolean }` @@ -83,6 +80,9 @@ Overview of all 181 API endpoints across all modules. #### Set options list for an article — `PUT /article/{sku}/optionslist` - Params: `sku: string, body: { options: { articleId?: integer, sku?: string, count?: integer, sort?: integer, mandated?: boolean }[] }` - Returns: `200 { options: object[] }` +#### Toggle parent mode for an article — `POST /article/{sku}/parent` +- Params: `sku: string, body: { isParent: boolean, attributeNameId?: integer }` +- Returns: `200 { article: { id: integer, categoryId: integer, name: string, sku: string, track_stock: boolean } }` #### Replace POS prices by SKU — `PUT /article/{sku}/prices` - Params: `sku: string, body: { prices: { price: number, tax: number, minmultiplier?: number }[] }` - Returns: `200 { article: { id: integer, sku: string, name: string, slug: string, track_stock: boolean, unitamount: number, weight: number, unit: object, brand: object, categoryIds: integer[], photos: { sort: integer, fullHash: string, fullW: integer, fullH: integer, fullSize: integer, thumbW: integer, thumbH: integer, thumbHash: string }[], eans: string[], prices: { minmultiplier: number, net: number, taxRate: number, customergroupId: integer }[], suppliers: { id: integer, articleId: integer, entityId: integer, supplierName: string, sku: string, pu: number, stock: number, sort: integer, priceId: integer, price: { net: number, taxId: integer, taxRate: number } }[] } }` @@ -463,7 +463,7 @@ _none_ - Returns: `200 { articles: { id: integer, sku: string, name: string, slug: string, net: number, taxRate: number, gross: number, trackStock: boolean, brand: { id: integer, name: string }, fullHash: string, thumbW: integer, thumbH: integer, thumbHash: string }[] }` #### Get public article detail — `GET /public/{companyId}/articles/{sku}` - Params: `companyId: integer, sku: string` -- Returns: `200 { article: { id: integer, sku: string, name: string, slug: string, description: string, unitamount: number, weight: number, trackStock: boolean, unit: object, brand: object, price: object, prices: object[], categories: object[], photos: object[], eans: string[], isFather: boolean, fatherSku: string, variants: object[] } }` +- Returns: `200 { article: { id: integer, sku: string, name: string, slug: string, description: string, unitamount: number, weight: number, trackStock: boolean, unit: object, brand: object, price: object, prices: object[], categories: object[], photos: object[], eans: string[], isParent: boolean, parentSku: string, variants: object[] } }` #### List public categories — `GET /public/{companyId}/categories` - Params: `companyId: integer` - Returns: `200 { categories: { id: integer, parentId: integer, sort: integer, name: string, slug: string, fullHash: string, thumbW: integer, thumbH: integer, thumbHash: string }[] }` diff --git a/docs/api/routes.md b/docs/api/routes.md index 13a7099..2ceb86f 100644 --- a/docs/api/routes.md +++ b/docs/api/routes.md @@ -44,24 +44,21 @@ Overview of all 145 API endpoints across all modules. #### Replace article categories by SKU — `PUT /article/{sku}/categories` - Params: `sku: string, body: { categoryIds: integer[] }` - Returns: `200 { article: { id: integer, sku: string, name: string, slug: string, track_stock: boolean, unitamount: number, weight: number, unit: object, brand: object, categoryIds: integer[], photos: { sort: integer, fullHash: string, fullW: integer, fullH: integer, fullSize: integer, thumbW: integer, thumbH: integer, thumbHash: string }[], eans: string[], prices: { minmultiplier: number, net: number, taxRate: number, customergroupId: integer }[], suppliers: { id: integer, articleId: integer, entityId: integer, supplierName: string, sku: string, pu: number, stock: number, sort: integer, priceId: integer, price: { net: number, taxId: integer, taxRate: number } }[] } }` -#### List child articles of a father article — `GET /article/{sku}/children` +#### List child articles of a parent article — `GET /article/{sku}/children` - Params: `sku: string` -- Returns: `200 { children: { id: integer, sku: string, name: string, fathersort: integer, attributeValueId: integer, attributeValue: string }[] }` -#### Create and attach a new child article to a father article — `POST /article/{sku}/children` +- Returns: `200 { children: { id: integer, sku: string, name: string, parentsort: integer, attributeValueId: integer, attributeValue: string }[] }` +#### Create and attach a new child article to a parent article — `POST /article/{sku}/children` - Params: `sku: string, body: { attributeValueId?: integer, value?: string, name?: string }` - Returns: `201 { article: { id: integer, categoryId: integer, name: string, sku: string, track_stock: boolean } }` -#### Attach an existing article as a child to a father article — `PUT /article/{sku}/children` +#### Attach an existing article as a child to a parent article — `PUT /article/{sku}/children` - Params: `sku: string, body: { sku: string, attributeValueId?: integer, value?: string, reparent?: boolean }` - Returns: `200 { article: { id: integer, categoryId: integer, name: string, sku: string, track_stock: boolean }, children: object[] }` -#### Remove a child article from a father article — `DELETE /article/{sku}/children/{childSku}` +#### Remove a child article from a parent article — `DELETE /article/{sku}/children/{childSku}` - Params: `sku: string, childSku: string, query: deleteArticle?: boolean` - Returns: `200 { success: boolean, deleted: boolean }` #### Replace article EANs by SKU — `PUT /article/{sku}/eans` - Params: `sku: string, body: { eans: string[] }` - Returns: `200 { article: { id: integer, sku: string, name: string, slug: string, track_stock: boolean, unitamount: number, weight: number, unit: object, brand: object, categoryIds: integer[], photos: { sort: integer, fullHash: string, fullW: integer, fullH: integer, fullSize: integer, thumbW: integer, thumbH: integer, thumbHash: string }[], eans: string[], prices: { minmultiplier: number, net: number, taxRate: number, customergroupId: integer }[], suppliers: { id: integer, articleId: integer, entityId: integer, supplierName: string, sku: string, pu: number, stock: number, sort: integer, priceId: integer, price: { net: number, taxId: integer, taxRate: number } }[] } }` -#### Toggle father mode for an article — `POST /article/{sku}/father` -- Params: `sku: string, body: { isFather: boolean, attributeNameId?: integer }` -- Returns: `200 { article: { id: integer, categoryId: integer, name: string, sku: string, track_stock: boolean } }` #### Get article history by SKU — `GET /article/{sku}/history` - Params: `sku: string, query: limit?: integer` - Returns: `200 { history: { id: integer, date: string, text: string }[], truncated: boolean }` @@ -77,6 +74,9 @@ Overview of all 145 API endpoints across all modules. #### Set options list for an article — `PUT /article/{sku}/optionslist` - Params: `sku: string, body: { options: { articleId?: integer, sku?: string, count?: integer, sort?: integer, mandated?: boolean }[] }` - Returns: `200 { options: object[] }` +#### Toggle parent mode for an article — `POST /article/{sku}/parent` +- Params: `sku: string, body: { isParent: boolean, attributeNameId?: integer }` +- Returns: `200 { article: { id: integer, categoryId: integer, name: string, sku: string, track_stock: boolean } }` #### Replace POS prices by SKU — `PUT /article/{sku}/prices` - Params: `sku: string, body: { prices: { price: number, tax: number, minmultiplier?: number }[] }` - Returns: `200 { article: { id: integer, sku: string, name: string, slug: string, track_stock: boolean, unitamount: number, weight: number, unit: object, brand: object, categoryIds: integer[], photos: { sort: integer, fullHash: string, fullW: integer, fullH: integer, fullSize: integer, thumbW: integer, thumbH: integer, thumbHash: string }[], eans: string[], prices: { minmultiplier: number, net: number, taxRate: number, customergroupId: integer }[], suppliers: { id: integer, articleId: integer, entityId: integer, supplierName: string, sku: string, pu: number, stock: number, sort: integer, priceId: integer, price: { net: number, taxId: integer, taxRate: number } }[] } }` diff --git a/docs/api/routes/article/_sku/articlelist.put.md b/docs/api/routes/article/_sku/articlelist.put.md index efd0441..139becd 100644 --- a/docs/api/routes/article/_sku/articlelist.put.md +++ b/docs/api/routes/article/_sku/articlelist.put.md @@ -4,7 +4,7 @@ Protected. Requires a valid session cookie (`credentials: 'include'`). Set Stückliste (bundle items) for an article -Configures the article as a Stückliste covering a list of count * article. A father article cannot be a Stückliste. Can be combined with options. Pass an empty array to remove the Stückliste. +Configures the article as a Stückliste covering a list of count * article. A parent article cannot be a Stückliste. Can be combined with options. Pass an empty array to remove the Stückliste. ## Path parameters @@ -51,7 +51,7 @@ Updated Stückliste items | Status | Description | |--------|-------------| -| 400 | Article is a father, has options, or contains itself | +| 400 | Article is a parent, has options, or contains itself | | 404 | Article or component article not found | --- diff --git a/docs/api/routes/article/_sku/children.get.md b/docs/api/routes/article/_sku/children.get.md index cfd4dc4..e12abe0 100644 --- a/docs/api/routes/article/_sku/children.get.md +++ b/docs/api/routes/article/_sku/children.get.md @@ -2,15 +2,15 @@ Protected. Requires a valid session cookie (`credentials: 'include'`). -List child articles of a father article +List child articles of a parent article -Returns variants/children linked to this father article. +Returns variants/children linked to this parent article. ## Path parameters | Param | Required | Type | Description | |-------|----------|------|-------------| -| `sku` | yes | string | Father article SKU | +| `sku` | yes | string | Parent article SKU | ## Response `200` @@ -23,7 +23,7 @@ List of children "id": 1, "sku": "…", "name": "…", - "fathersort": 1, + "parentsort": 1, "attributeValueId": 1, "attributeValue": "…" } diff --git a/docs/api/routes/article/_sku/children.post.md b/docs/api/routes/article/_sku/children.post.md index 5e9b688..a5bda19 100644 --- a/docs/api/routes/article/_sku/children.post.md +++ b/docs/api/routes/article/_sku/children.post.md @@ -2,22 +2,22 @@ Protected. Requires a valid session cookie (`credentials: 'include'`). -Create and attach a new child article to a father article +Create and attach a new child article to a parent article -Automatically generates SKU as fatherSku-nextFreeIndex and name from father name + value. Rejects a caller-supplied sku. +Automatically generates SKU as parentSku-nextFreeIndex and name from parent name + value. Rejects a caller-supplied sku. ## Path parameters | Param | Required | Type | Description | |-------|----------|------|-------------| -| `sku` | yes | string | Father article SKU | +| `sku` | yes | string | Parent article SKU | ## Body (JSON) | Field | Required | Type | Description | |-------|----------|------|-------------| -| `attributeValueId` | no | integer | ID of existing attribute value for the father's attribute | -| `value` | no | string | String value to find or create under the father's attribute | +| `attributeValueId` | no | integer | ID of existing attribute value for the parent's attribute | +| `value` | no | string | String value to find or create under the parent's attribute | | `name` | no | string | Optional custom variant name | ```json @@ -48,7 +48,7 @@ Created child article | Status | Description | |--------|-------------| -| 400 | Father not configured as father, missing value, duplicate variant, or sku was provided in body | +| 400 | Parent not configured as parent, missing value, duplicate variant, or sku was provided in body | --- diff --git a/docs/api/routes/article/_sku/children.put.md b/docs/api/routes/article/_sku/children.put.md index 229b0bc..105af3b 100644 --- a/docs/api/routes/article/_sku/children.put.md +++ b/docs/api/routes/article/_sku/children.put.md @@ -2,24 +2,24 @@ Protected. Requires a valid session cookie (`credentials: 'include'`). -Attach an existing article as a child to a father article +Attach an existing article as a child to a parent article -Attaches an existing article to this father article. Idempotent if already a child. Returns 409 if the article already belongs to another father. +Attaches an existing article to this parent article. Idempotent if already a child. Returns 409 if the article already belongs to another parent. ## Path parameters | Param | Required | Type | Description | |-------|----------|------|-------------| -| `sku` | yes | string | Father article SKU | +| `sku` | yes | string | Parent article SKU | ## Body (JSON) | Field | Required | Type | Description | |-------|----------|------|-------------| | `sku` | yes | string | SKU of the existing article to attach as child | -| `attributeValueId` | no | integer | ID of existing attribute value for the father's attribute | -| `value` | no | string | String value to find or create under the father's attribute | -| `reparent` | no | boolean | Whether to allow re-parenting if child already belongs to another father | +| `attributeValueId` | no | integer | ID of existing attribute value for the parent's attribute | +| `value` | no | string | String value to find or create under the parent's attribute | +| `reparent` | no | boolean | Whether to allow re-parenting if child already belongs to another parent | ```json { @@ -54,8 +54,8 @@ Attached child article and list of children | Status | Description | |--------|-------------| | 400 | Missing sku or attribute value, or invalid input | -| 404 | Father or child article not found | -| 409 | Article already belongs to another father, or variant value already exists | +| 404 | Parent or child article not found | +| 409 | Article already belongs to another parent, or variant value already exists | --- diff --git a/docs/api/routes/article/_sku/children/_childSku.md b/docs/api/routes/article/_sku/children/_childSku.md index ce8e2c5..9bae8bb 100644 --- a/docs/api/routes/article/_sku/children/_childSku.md +++ b/docs/api/routes/article/_sku/children/_childSku.md @@ -2,22 +2,22 @@ Protected. Requires a valid session cookie (`credentials: 'include'`). -Remove a child article from a father article +Remove a child article from a parent article -Unlinks the child from the father (or deletes if deleteArticle query/body is true). +Unlinks the child from the parent (or deletes if deleteArticle query/body is true). ## Path parameters | Param | Required | Type | Description | |-------|----------|------|-------------| -| `sku` | yes | string | Father article SKU | +| `sku` | yes | string | Parent article SKU | | `childSku` | yes | string | Child article SKU | ## Query parameters | Param | Required | Type | Description | |-------|----------|------|-------------| -| `deleteArticle` | no | boolean | If true, permanently deletes the child article (and cascades its entire descendant subtree if it is a father) instead of just unlinking | +| `deleteArticle` | no | boolean | If true, permanently deletes the child article (and cascades its entire descendant subtree if it is a parent) instead of just unlinking | ## Response `200` diff --git a/docs/api/routes/article/_sku/optionslist.put.md b/docs/api/routes/article/_sku/optionslist.put.md index fdd86d3..cc49bf7 100644 --- a/docs/api/routes/article/_sku/optionslist.put.md +++ b/docs/api/routes/article/_sku/optionslist.put.md @@ -4,7 +4,7 @@ Protected. Requires a valid session cookie (`credentials: 'include'`). Set options list for an article -Configures options for an article. Some options can be mandated (come with the article in any case). A father article cannot have options. Can be combined with a Stückliste. Pass an empty array to remove options. +Configures options for an article. Some options can be mandated (come with the article in any case). A parent article cannot have options. Can be combined with a Stückliste. Pass an empty array to remove options. ## Path parameters @@ -53,7 +53,7 @@ Updated options list | Status | Description | |--------|-------------| -| 400 | Article is a father, a Stückliste, or contains itself | +| 400 | Article is a parent, a Stückliste, or contains itself | | 404 | Article or option article not found | --- diff --git a/docs/api/routes/article/_sku/father.md b/docs/api/routes/article/_sku/parent.md similarity index 64% rename from docs/api/routes/article/_sku/father.md rename to docs/api/routes/article/_sku/parent.md index 4de2268..4e69497 100644 --- a/docs/api/routes/article/_sku/father.md +++ b/docs/api/routes/article/_sku/parent.md @@ -1,17 +1,17 @@ -# `POST /article/{sku}/father` +# `POST /article/{sku}/parent` Protected. Requires a valid session cookie (`credentials: 'include'`). -Toggle father mode for an article +Toggle parent mode for an article -Enables or disables father article status. Enabling requires specifying an +Enables or disables parent article status. Enabling requires specifying an attributeNameId; disabling requires the article to have zero children. `attributeNameId` is **conditionally required**: it is optional in the schema -because it is only required when `isFather` is `true`. Omitting it (or passing -`0`/a negative value) together with `isFather: true` returns `400` -`attributeNameId is required to become a father article`. It must not be sent -when `isFather` is `false`. +because it is only required when `isParent` is `true`. Omitting it (or passing +`0`/a negative value) together with `isParent: true` returns `400` +`attributeNameId is required to become a parent article`. It must not be sent +when `isParent` is `false`. ## Path parameters @@ -24,12 +24,12 @@ when `isFather` is `false`. | Field | Required | Type | Description | |-------|----------|------|-------------| -| `isFather` | yes | boolean | True to make article a father, false to revert to regular article | -| `attributeNameId` | no | integer | **Conditionally required when `isFather` is `true`** (required iff isFather=true). The attributename id used for the article's variants. Omitting it while enabling father mode returns 400. Must be omitted when `isFather` is `false`. | +| `isParent` | yes | boolean | True to make article a parent, false to revert to regular article | +| `attributeNameId` | no | integer | **Conditionally required when `isParent` is `true`** (required iff isParent=true). The attributename id used for the article's variants. Omitting it while enabling parent mode returns 400. Must be omitted when `isParent` is `false`. | ```json { - "isFather": true, + "isParent": true, "attributeNameId": 1 } ``` @@ -54,9 +54,9 @@ Updated article | Status | Description | |--------|-------------| -| 400 | Invalid input, `attributeNameId` missing while `isFather` is true, article still +| 400 | Invalid input, `attributeNameId` missing while `isParent` is true, article still has children, article has stock/suppliers/a Stückliste/options, or the attribute is -already used by an ancestor father article. +already used by an ancestor parent article. | | 404 | Article or attribute name not found | diff --git a/docs/api/routes/article/set-prices.md b/docs/api/routes/article/set-prices.md index d2687f1..70c3fb9 100644 --- a/docs/api/routes/article/set-prices.md +++ b/docs/api/routes/article/set-prices.md @@ -112,7 +112,7 @@ Updated article detail | Status | Description | |--------|-------------| -| 400 | Invalid prices, POS customer group required, or father article cannot have prices — `{"error":"…"}` | +| 400 | Invalid prices, POS customer group required, or parent article cannot have prices — `{"error":"…"}` | | 401 | Unauthorized — `{"error":"…"}` | | 403 | Not authorized — `{"error":"…"}` | | 404 | Article not found — `{"error":"…"}` | diff --git a/docs/api/routes/category/articles.md b/docs/api/routes/category/articles.md index cf990b9..5d5543b 100644 --- a/docs/api/routes/category/articles.md +++ b/docs/api/routes/category/articles.md @@ -4,7 +4,7 @@ Protected. Requires a valid session cookie (`credentials: 'include'`). Articles in category -Returns articles in a category the user is authorized for (omits child articles of a father article). Each article includes `childCount` (the number of its child articles). +Returns articles in a category the user is authorized for (omits child articles of a parent article). Each article includes `childCount` (the number of its child articles). ## Path parameters diff --git a/docs/api/routes/public/_companyId/articles/_sku.md b/docs/api/routes/public/_companyId/articles/_sku.md index 3423cfd..94d8da9 100644 --- a/docs/api/routes/public/_companyId/articles/_sku.md +++ b/docs/api/routes/public/_companyId/articles/_sku.md @@ -43,8 +43,8 @@ Article detail "eans": [ "…" ], - "isFather": true, - "fatherSku": "…", + "isParent": true, + "parentSku": "…", "variants": [ {} ] diff --git a/docs/api/routes/stock/adjust.md b/docs/api/routes/stock/adjust.md index 26f2b19..54a2873 100644 --- a/docs/api/routes/stock/adjust.md +++ b/docs/api/routes/stock/adjust.md @@ -77,7 +77,7 @@ Stock adjusted successfully | Status | Description | |--------|-------------| -| 400 | Missing fields, invalid amount, father article cannot have stock, or no company selected — `{"error":"…"}` | +| 400 | Missing fields, invalid amount, parent article cannot have stock, or no company selected — `{"error":"…"}` | | 401 | Unauthorized — `{"error":"…"}` | | 403 | Not authorized — `{"error":"…"}` | | 404 | Article or warehouse not found — `{"error":"…"}` | diff --git a/scripts/migrate-parent-rename.mssql.sql b/scripts/migrate-parent-rename.mssql.sql new file mode 100644 index 0000000..9974b80 --- /dev/null +++ b/scripts/migrate-parent-rename.mssql.sql @@ -0,0 +1,58 @@ +-- Rename article "father" columns to "parent" (SQL Server / MSSQL). +-- +-- One-off manual migration (no migration code is kept in the repo). +-- sqlcmd -S -d -E -i scripts/migrate-parent-rename.mssql.sql +-- +-- Wrapped in a transaction and guarded so it is safe to re-run. +-- Drop the existing index explicitly: SQL Server will not let a filtered +-- unique index be carried over to a renamed column. + +SET XACT_ABORT ON; +BEGIN TRANSACTION; + +-- Drop the old filtered unique index (references fathersort). +IF EXISTS (SELECT 1 FROM sys.indexes WHERE name = 'UQ_article_fatherarticle_fathersort') + DROP INDEX UQ_article_fatherarticle_fathersort ON article; + +-- Drop the default constraints bound to the old column names. +IF EXISTS (SELECT 1 FROM sys.default_constraints WHERE name = 'DF_article_is_father') + ALTER TABLE article DROP CONSTRAINT DF_article_is_father; +IF EXISTS (SELECT 1 FROM sys.default_constraints WHERE name = 'DF_article_fathersort') + ALTER TABLE article DROP CONSTRAINT DF_article_fathersort; + +-- Drop foreign keys bound to the old columns. +IF EXISTS (SELECT 1 FROM sys.foreign_keys WHERE name = 'FK_article_fatherarticle') + ALTER TABLE article DROP CONSTRAINT FK_article_fatherarticle; +IF EXISTS (SELECT 1 FROM sys.foreign_keys WHERE name = 'FK_article_fatherattributename') + ALTER TABLE article DROP CONSTRAINT FK_article_fatherattributename; + +-- Rename the columns (sp_rename keeps indexes/FKs tracking the column). +IF COL_LENGTH('article', 'fatherarticle_id') IS NOT NULL + AND COL_LENGTH('article', 'parentarticle_id') IS NULL + EXEC sp_rename 'article.fatherarticle_id', 'parentarticle_id', 'COLUMN'; +IF COL_LENGTH('article', 'fatherattributename_id') IS NOT NULL + AND COL_LENGTH('article', 'parentattributename_id') IS NULL + EXEC sp_rename 'article.fatherattributename_id', 'parentattributename_id', 'COLUMN'; +IF COL_LENGTH('article', 'fathersort') IS NOT NULL + AND COL_LENGTH('article', 'parentsort') IS NULL + EXEC sp_rename 'article.fathersort', 'parentsort', 'COLUMN'; +IF COL_LENGTH('article', 'is_father') IS NOT NULL + AND COL_LENGTH('article', 'is_parent') IS NULL + EXEC sp_rename 'article.is_father', 'is_parent', 'COLUMN'; + +-- Recreate the constraints under their new names. +IF NOT EXISTS (SELECT 1 FROM sys.foreign_keys WHERE name = 'FK_article_parentarticle') + ALTER TABLE article ADD CONSTRAINT FK_article_parentarticle + FOREIGN KEY (parentarticle_id) REFERENCES article(id) ON DELETE NO ACTION; +IF NOT EXISTS (SELECT 1 FROM sys.foreign_keys WHERE name = 'FK_article_parentattributename') + ALTER TABLE article ADD CONSTRAINT FK_article_parentattributename + FOREIGN KEY (parentattributename_id) REFERENCES attributename(id) ON DELETE NO ACTION; + +ALTER TABLE article ADD CONSTRAINT DF_article_is_parent DEFAULT (0) FOR is_parent; +ALTER TABLE article ADD CONSTRAINT DF_article_parentsort DEFAULT (0) FOR parentsort; + +CREATE UNIQUE INDEX UQ_article_parentarticle_parentsort + ON article (parentarticle_id, parentsort) + WHERE parentarticle_id IS NOT NULL; + +COMMIT TRANSACTION; \ No newline at end of file diff --git a/scripts/migrate-parent-rename.sqlite.sql b/scripts/migrate-parent-rename.sqlite.sql new file mode 100644 index 0000000..4fe5e67 --- /dev/null +++ b/scripts/migrate-parent-rename.sqlite.sql @@ -0,0 +1,14 @@ +-- Rename article "father" columns to "parent". +-- +-- One-off manual migration (no migration code is kept in the repo). +-- sqlite3 data/dash.db < scripts/migrate-parent-rename.sqlite.sql +-- +-- Safe to re-run: every step is guarded by a column-existence check. + +ALTER TABLE article RENAME COLUMN fatherarticle_id TO parentarticle_id; +ALTER TABLE article RENAME COLUMN fatherattributename_id TO parentattributename_id; +ALTER TABLE article RENAME COLUMN fathersort TO parentsort; +ALTER TABLE article RENAME COLUMN is_father TO is_parent; + +-- Verify +PRAGMA table_info(article); \ No newline at end of file