u
This commit is contained in:
@@ -37,6 +37,8 @@ Generated from `@openapi` annotations in [`src/api/routes/`](../../src/api/route
|
|||||||
| [`routes/article/delete.md`](routes/article/delete.md) | `DELETE /article/{sku}` |
|
| [`routes/article/delete.md`](routes/article/delete.md) | `DELETE /article/{sku}` |
|
||||||
| [`routes/article/get.md`](routes/article/get.md) | `GET /article/{sku}` |
|
| [`routes/article/get.md`](routes/article/get.md) | `GET /article/{sku}` |
|
||||||
| [`routes/article/update.md`](routes/article/update.md) | `PATCH /article/{sku}` |
|
| [`routes/article/update.md`](routes/article/update.md) | `PATCH /article/{sku}` |
|
||||||
|
| [`routes/article/_sku/articlelist.get.md`](routes/article/_sku/articlelist.get.md) | `GET /article/{sku}/articlelist` |
|
||||||
|
| [`routes/article/_sku/articlelist.put.md`](routes/article/_sku/articlelist.put.md) | `PUT /article/{sku}/articlelist` |
|
||||||
| [`routes/article/_sku/attributevalue.get.md`](routes/article/_sku/attributevalue.get.md) | `GET /article/{sku}/attributevalue` |
|
| [`routes/article/_sku/attributevalue.get.md`](routes/article/_sku/attributevalue.get.md) | `GET /article/{sku}/attributevalue` |
|
||||||
| [`routes/article/_sku/attributevalue.put.md`](routes/article/_sku/attributevalue.put.md) | `PUT /article/{sku}/attributevalue` |
|
| [`routes/article/_sku/attributevalue.put.md`](routes/article/_sku/attributevalue.put.md) | `PUT /article/{sku}/attributevalue` |
|
||||||
| [`routes/article/set-brand.md`](routes/article/set-brand.md) | `PUT /article/{sku}/brand` |
|
| [`routes/article/set-brand.md`](routes/article/set-brand.md) | `PUT /article/{sku}/brand` |
|
||||||
@@ -50,6 +52,8 @@ Generated from `@openapi` annotations in [`src/api/routes/`](../../src/api/route
|
|||||||
| [`routes/article/add-image.md`](routes/article/add-image.md) | `POST /article/{sku}/image` |
|
| [`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/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/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/set-prices.md`](routes/article/set-prices.md) | `PUT /article/{sku}/prices` |
|
| [`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/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` |
|
| [`routes/article/_sku/property.get.md`](routes/article/_sku/property.get.md) | `GET /article/{sku}/property` |
|
||||||
|
|||||||
@@ -12947,6 +12947,319 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/article/{sku}/articlelist": {
|
||||||
|
"get": {
|
||||||
|
"summary": "Get Stückliste (bundle items) for an article",
|
||||||
|
"description": "Returns the list of component items for a Stückliste article.",
|
||||||
|
"tags": [
|
||||||
|
"Article"
|
||||||
|
],
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"cookieAuth": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"in": "path",
|
||||||
|
"name": "sku",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"description": "Article SKU"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "List of bundle items",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"items": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"articleId": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"sku": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"count": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"sort": {
|
||||||
|
"type": "integer"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"404": {
|
||||||
|
"description": "Article not found"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"put": {
|
||||||
|
"summary": "Set Stückliste (bundle items) for an article",
|
||||||
|
"description": "Configures the article as a Stückliste covering a list of count * article. An article that is a father or has options cannot be a Stückliste. Pass an empty array to remove the Stückliste.",
|
||||||
|
"tags": [
|
||||||
|
"Article"
|
||||||
|
],
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"cookieAuth": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"in": "path",
|
||||||
|
"name": "sku",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"description": "Article SKU"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"requestBody": {
|
||||||
|
"required": true,
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"items"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"items": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"articleId": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"sku": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"count": {
|
||||||
|
"type": "integer",
|
||||||
|
"default": 1
|
||||||
|
},
|
||||||
|
"sort": {
|
||||||
|
"type": "integer"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "Updated Stückliste items",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"items": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "object"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"400": {
|
||||||
|
"description": "Article is a father, has options, or contains itself"
|
||||||
|
},
|
||||||
|
"404": {
|
||||||
|
"description": "Article or component article not found"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"/article/{sku}/optionslist": {
|
||||||
|
"get": {
|
||||||
|
"summary": "Get options list for an article",
|
||||||
|
"description": "Returns the available options for an article.",
|
||||||
|
"tags": [
|
||||||
|
"Article"
|
||||||
|
],
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"cookieAuth": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"in": "path",
|
||||||
|
"name": "sku",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"description": "Article SKU"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "List of options",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"options": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"articleId": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"sku": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"name": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"count": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"sort": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"mandated": {
|
||||||
|
"type": "boolean"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"404": {
|
||||||
|
"description": "Article not found"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"put": {
|
||||||
|
"summary": "Set options list for an article",
|
||||||
|
"description": "Configures options for an article. Some options can be mandated (come with the article in any case). An article that is a father or a Stückliste cannot have options. Pass an empty array to remove options.",
|
||||||
|
"tags": [
|
||||||
|
"Article"
|
||||||
|
],
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"cookieAuth": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"in": "path",
|
||||||
|
"name": "sku",
|
||||||
|
"required": true,
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"description": "Article SKU"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"requestBody": {
|
||||||
|
"required": true,
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"type": "object",
|
||||||
|
"required": [
|
||||||
|
"options"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"options": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"articleId": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"sku": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"count": {
|
||||||
|
"type": "integer",
|
||||||
|
"default": 1
|
||||||
|
},
|
||||||
|
"sort": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"mandated": {
|
||||||
|
"type": "boolean",
|
||||||
|
"default": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"description": "Updated options list",
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"options": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "object"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"400": {
|
||||||
|
"description": "Article is a father, a Stückliste, or contains itself"
|
||||||
|
},
|
||||||
|
"404": {
|
||||||
|
"description": "Article or option article not found"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"/auth/selected-company": {
|
"/auth/selected-company": {
|
||||||
"put": {
|
"put": {
|
||||||
"tags": [
|
"tags": [
|
||||||
|
|||||||
42
docs/api/routes/article/_sku/articlelist.get.md
Normal file
42
docs/api/routes/article/_sku/articlelist.get.md
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
# `GET /article/{sku}/articlelist`
|
||||||
|
|
||||||
|
Protected. Requires a valid session cookie (`credentials: 'include'`).
|
||||||
|
|
||||||
|
Get Stückliste (bundle items) for an article
|
||||||
|
|
||||||
|
Returns the list of component items for a Stückliste article.
|
||||||
|
|
||||||
|
## Path parameters
|
||||||
|
|
||||||
|
| Param | Required | Type | Description |
|
||||||
|
|-------|----------|------|-------------|
|
||||||
|
| `sku` | yes | string | Article SKU |
|
||||||
|
|
||||||
|
## Response `200`
|
||||||
|
|
||||||
|
List of bundle items
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"articleId": 1,
|
||||||
|
"sku": "…",
|
||||||
|
"name": "…",
|
||||||
|
"count": 1,
|
||||||
|
"sort": 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Errors
|
||||||
|
|
||||||
|
| Status | Description |
|
||||||
|
|--------|-------------|
|
||||||
|
| 404 | Article not found |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
_Generated from `@openapi` JSDoc. Do not edit by hand — run `npm run docs:api`._
|
||||||
51
docs/api/routes/article/_sku/articlelist.put.md
Normal file
51
docs/api/routes/article/_sku/articlelist.put.md
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
# `PUT /article/{sku}/articlelist`
|
||||||
|
|
||||||
|
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. An article that is a father or has options cannot be a Stückliste. Pass an empty array to remove the Stückliste.
|
||||||
|
|
||||||
|
## Path parameters
|
||||||
|
|
||||||
|
| Param | Required | Type | Description |
|
||||||
|
|-------|----------|------|-------------|
|
||||||
|
| `sku` | yes | string | Article SKU |
|
||||||
|
|
||||||
|
## Body (JSON)
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"articleId": 1,
|
||||||
|
"sku": "…",
|
||||||
|
"count": 1,
|
||||||
|
"sort": 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Response `200`
|
||||||
|
|
||||||
|
Updated Stückliste items
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"items": [
|
||||||
|
{}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Errors
|
||||||
|
|
||||||
|
| Status | Description |
|
||||||
|
|--------|-------------|
|
||||||
|
| 400 | Article is a father, has options, or contains itself |
|
||||||
|
| 404 | Article or component article not found |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
_Generated from `@openapi` JSDoc. Do not edit by hand — run `npm run docs:api`._
|
||||||
43
docs/api/routes/article/_sku/optionslist.get.md
Normal file
43
docs/api/routes/article/_sku/optionslist.get.md
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
# `GET /article/{sku}/optionslist`
|
||||||
|
|
||||||
|
Protected. Requires a valid session cookie (`credentials: 'include'`).
|
||||||
|
|
||||||
|
Get options list for an article
|
||||||
|
|
||||||
|
Returns the available options for an article.
|
||||||
|
|
||||||
|
## Path parameters
|
||||||
|
|
||||||
|
| Param | Required | Type | Description |
|
||||||
|
|-------|----------|------|-------------|
|
||||||
|
| `sku` | yes | string | Article SKU |
|
||||||
|
|
||||||
|
## Response `200`
|
||||||
|
|
||||||
|
List of options
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"options": [
|
||||||
|
{
|
||||||
|
"id": 1,
|
||||||
|
"articleId": 1,
|
||||||
|
"sku": "…",
|
||||||
|
"name": "…",
|
||||||
|
"count": 1,
|
||||||
|
"sort": 1,
|
||||||
|
"mandated": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Errors
|
||||||
|
|
||||||
|
| Status | Description |
|
||||||
|
|--------|-------------|
|
||||||
|
| 404 | Article not found |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
_Generated from `@openapi` JSDoc. Do not edit by hand — run `npm run docs:api`._
|
||||||
52
docs/api/routes/article/_sku/optionslist.put.md
Normal file
52
docs/api/routes/article/_sku/optionslist.put.md
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
# `PUT /article/{sku}/optionslist`
|
||||||
|
|
||||||
|
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). An article that is a father or a Stückliste cannot have options. Pass an empty array to remove options.
|
||||||
|
|
||||||
|
## Path parameters
|
||||||
|
|
||||||
|
| Param | Required | Type | Description |
|
||||||
|
|-------|----------|------|-------------|
|
||||||
|
| `sku` | yes | string | Article SKU |
|
||||||
|
|
||||||
|
## Body (JSON)
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"options": [
|
||||||
|
{
|
||||||
|
"articleId": 1,
|
||||||
|
"sku": "…",
|
||||||
|
"count": 1,
|
||||||
|
"sort": 1,
|
||||||
|
"mandated": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Response `200`
|
||||||
|
|
||||||
|
Updated options list
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"options": [
|
||||||
|
{}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Errors
|
||||||
|
|
||||||
|
| Status | Description |
|
||||||
|
|--------|-------------|
|
||||||
|
| 400 | Article is a father, a Stückliste, or contains itself |
|
||||||
|
| 404 | Article or option article not found |
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
_Generated from `@openapi` JSDoc. Do not edit by hand — run `npm run docs:api`._
|
||||||
@@ -80,6 +80,7 @@ function articleErrorStatus(error) {
|
|||||||
if (error.message === 'Child article does not belong to this father') return 400;
|
if (error.message === 'Child article does not belong to this father') return 400;
|
||||||
if (error.message === 'Father article not found') return 404;
|
if (error.message === 'Father article not found') return 404;
|
||||||
if (error.message?.includes('already exists') || error.code === 'SQLITE_CONSTRAINT_UNIQUE') return 409;
|
if (error.message?.includes('already exists') || error.code === 'SQLITE_CONSTRAINT_UNIQUE') return 409;
|
||||||
|
if (error.message?.includes('Stückliste') || error.message?.includes('options') || error.message?.includes('Invalid items array') || error.message?.includes('Invalid options array')) return 400;
|
||||||
return 500;
|
return 500;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1931,5 +1932,283 @@ export function register(app, basePath = '') {
|
|||||||
res.status(status).json({ error: error.message });
|
res.status(status).json({ error: error.message });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @openapi
|
||||||
|
* /article/{sku}/articlelist:
|
||||||
|
* get:
|
||||||
|
* summary: Get Stückliste (bundle items) for an article
|
||||||
|
* description: Returns the list of component items for a Stückliste article.
|
||||||
|
* tags:
|
||||||
|
* - Article
|
||||||
|
* security:
|
||||||
|
* - cookieAuth: []
|
||||||
|
* parameters:
|
||||||
|
* - in: path
|
||||||
|
* name: sku
|
||||||
|
* required: true
|
||||||
|
* schema:
|
||||||
|
* type: string
|
||||||
|
* description: Article SKU
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: List of bundle items
|
||||||
|
* content:
|
||||||
|
* application/json:
|
||||||
|
* schema:
|
||||||
|
* type: object
|
||||||
|
* properties:
|
||||||
|
* items:
|
||||||
|
* type: array
|
||||||
|
* items:
|
||||||
|
* type: object
|
||||||
|
* properties:
|
||||||
|
* id:
|
||||||
|
* type: integer
|
||||||
|
* articleId:
|
||||||
|
* type: integer
|
||||||
|
* sku:
|
||||||
|
* type: string
|
||||||
|
* name:
|
||||||
|
* type: string
|
||||||
|
* count:
|
||||||
|
* type: integer
|
||||||
|
* sort:
|
||||||
|
* type: integer
|
||||||
|
* 404:
|
||||||
|
* description: Article not found
|
||||||
|
*/
|
||||||
|
app.get(`${basePath}/article/:sku/articlelist`, async (req, res) => {
|
||||||
|
const parsed = parseSku(req.params.sku);
|
||||||
|
if (parsed.error) return res.status(400).json({ error: parsed.error });
|
||||||
|
|
||||||
|
try {
|
||||||
|
const items = await db.getArticlelist(req.user.id, parsed.sku);
|
||||||
|
res.status(200).json({ items });
|
||||||
|
} catch (error) {
|
||||||
|
const status = articleErrorStatus(error);
|
||||||
|
if (status === 500) console.error('Get articlelist failed:', error);
|
||||||
|
res.status(status).json({ error: error.message });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @openapi
|
||||||
|
* /article/{sku}/articlelist:
|
||||||
|
* put:
|
||||||
|
* summary: Set Stückliste (bundle items) for an article
|
||||||
|
* description: Configures the article as a Stückliste covering a list of count * article. An article that is a father or has options cannot be a Stückliste. Pass an empty array to remove the Stückliste.
|
||||||
|
* tags:
|
||||||
|
* - Article
|
||||||
|
* security:
|
||||||
|
* - cookieAuth: []
|
||||||
|
* parameters:
|
||||||
|
* - in: path
|
||||||
|
* name: sku
|
||||||
|
* required: true
|
||||||
|
* schema:
|
||||||
|
* type: string
|
||||||
|
* description: Article SKU
|
||||||
|
* requestBody:
|
||||||
|
* required: true
|
||||||
|
* content:
|
||||||
|
* application/json:
|
||||||
|
* schema:
|
||||||
|
* type: object
|
||||||
|
* required: [items]
|
||||||
|
* properties:
|
||||||
|
* items:
|
||||||
|
* type: array
|
||||||
|
* items:
|
||||||
|
* type: object
|
||||||
|
* properties:
|
||||||
|
* articleId:
|
||||||
|
* type: integer
|
||||||
|
* sku:
|
||||||
|
* type: string
|
||||||
|
* count:
|
||||||
|
* type: integer
|
||||||
|
* default: 1
|
||||||
|
* sort:
|
||||||
|
* type: integer
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: Updated Stückliste items
|
||||||
|
* content:
|
||||||
|
* application/json:
|
||||||
|
* schema:
|
||||||
|
* type: object
|
||||||
|
* properties:
|
||||||
|
* items:
|
||||||
|
* type: array
|
||||||
|
* items:
|
||||||
|
* type: object
|
||||||
|
* 400:
|
||||||
|
* description: Article is a father, has options, or contains itself
|
||||||
|
* 404:
|
||||||
|
* description: Article or component article not found
|
||||||
|
*/
|
||||||
|
app.put(`${basePath}/article/:sku/articlelist`, async (req, res) => {
|
||||||
|
const parsed = parseSku(req.params.sku);
|
||||||
|
if (parsed.error) return res.status(400).json({ error: parsed.error });
|
||||||
|
|
||||||
|
const items = req.body?.items;
|
||||||
|
if (!Array.isArray(items)) {
|
||||||
|
return res.status(400).json({ error: 'items array is required' });
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const updated = await db.setArticlelist(req.user.id, parsed.sku, items);
|
||||||
|
emitArticleSignal(req, parsed.sku);
|
||||||
|
emitArticlesSignal(req);
|
||||||
|
res.status(200).json({ items: updated });
|
||||||
|
} catch (error) {
|
||||||
|
const status = articleErrorStatus(error);
|
||||||
|
if (status === 500) console.error('Set articlelist failed:', error);
|
||||||
|
res.status(status).json({ error: error.message });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @openapi
|
||||||
|
* /article/{sku}/optionslist:
|
||||||
|
* get:
|
||||||
|
* summary: Get options list for an article
|
||||||
|
* description: Returns the available options for an article.
|
||||||
|
* tags:
|
||||||
|
* - Article
|
||||||
|
* security:
|
||||||
|
* - cookieAuth: []
|
||||||
|
* parameters:
|
||||||
|
* - in: path
|
||||||
|
* name: sku
|
||||||
|
* required: true
|
||||||
|
* schema:
|
||||||
|
* type: string
|
||||||
|
* description: Article SKU
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: List of options
|
||||||
|
* content:
|
||||||
|
* application/json:
|
||||||
|
* schema:
|
||||||
|
* type: object
|
||||||
|
* properties:
|
||||||
|
* options:
|
||||||
|
* type: array
|
||||||
|
* items:
|
||||||
|
* type: object
|
||||||
|
* properties:
|
||||||
|
* id:
|
||||||
|
* type: integer
|
||||||
|
* articleId:
|
||||||
|
* type: integer
|
||||||
|
* sku:
|
||||||
|
* type: string
|
||||||
|
* name:
|
||||||
|
* type: string
|
||||||
|
* count:
|
||||||
|
* type: integer
|
||||||
|
* sort:
|
||||||
|
* type: integer
|
||||||
|
* mandated:
|
||||||
|
* type: boolean
|
||||||
|
* 404:
|
||||||
|
* description: Article not found
|
||||||
|
*/
|
||||||
|
app.get(`${basePath}/article/:sku/optionslist`, async (req, res) => {
|
||||||
|
const parsed = parseSku(req.params.sku);
|
||||||
|
if (parsed.error) return res.status(400).json({ error: parsed.error });
|
||||||
|
|
||||||
|
try {
|
||||||
|
const options = await db.getOptionslist(req.user.id, parsed.sku);
|
||||||
|
res.status(200).json({ options });
|
||||||
|
} catch (error) {
|
||||||
|
const status = articleErrorStatus(error);
|
||||||
|
if (status === 500) console.error('Get optionslist failed:', error);
|
||||||
|
res.status(status).json({ error: error.message });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @openapi
|
||||||
|
* /article/{sku}/optionslist:
|
||||||
|
* put:
|
||||||
|
* summary: Set options list for an article
|
||||||
|
* description: Configures options for an article. Some options can be mandated (come with the article in any case). An article that is a father or a Stückliste cannot have options. Pass an empty array to remove options.
|
||||||
|
* tags:
|
||||||
|
* - Article
|
||||||
|
* security:
|
||||||
|
* - cookieAuth: []
|
||||||
|
* parameters:
|
||||||
|
* - in: path
|
||||||
|
* name: sku
|
||||||
|
* required: true
|
||||||
|
* schema:
|
||||||
|
* type: string
|
||||||
|
* description: Article SKU
|
||||||
|
* requestBody:
|
||||||
|
* required: true
|
||||||
|
* content:
|
||||||
|
* application/json:
|
||||||
|
* schema:
|
||||||
|
* type: object
|
||||||
|
* required: [options]
|
||||||
|
* properties:
|
||||||
|
* options:
|
||||||
|
* type: array
|
||||||
|
* items:
|
||||||
|
* type: object
|
||||||
|
* properties:
|
||||||
|
* articleId:
|
||||||
|
* type: integer
|
||||||
|
* sku:
|
||||||
|
* type: string
|
||||||
|
* count:
|
||||||
|
* type: integer
|
||||||
|
* default: 1
|
||||||
|
* sort:
|
||||||
|
* type: integer
|
||||||
|
* mandated:
|
||||||
|
* type: boolean
|
||||||
|
* default: false
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: Updated options list
|
||||||
|
* content:
|
||||||
|
* application/json:
|
||||||
|
* schema:
|
||||||
|
* type: object
|
||||||
|
* properties:
|
||||||
|
* options:
|
||||||
|
* type: array
|
||||||
|
* items:
|
||||||
|
* type: object
|
||||||
|
* 400:
|
||||||
|
* description: Article is a father, a Stückliste, or contains itself
|
||||||
|
* 404:
|
||||||
|
* description: Article or option article not found
|
||||||
|
*/
|
||||||
|
app.put(`${basePath}/article/:sku/optionslist`, async (req, res) => {
|
||||||
|
const parsed = parseSku(req.params.sku);
|
||||||
|
if (parsed.error) return res.status(400).json({ error: parsed.error });
|
||||||
|
|
||||||
|
const options = req.body?.options;
|
||||||
|
if (!Array.isArray(options)) {
|
||||||
|
return res.status(400).json({ error: 'options array is required' });
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const updated = await db.setOptionslist(req.user.id, parsed.sku, options);
|
||||||
|
emitArticleSignal(req, parsed.sku);
|
||||||
|
emitArticlesSignal(req);
|
||||||
|
res.status(200).json({ options: updated });
|
||||||
|
} catch (error) {
|
||||||
|
const status = articleErrorStatus(error);
|
||||||
|
if (status === 500) console.error('Set optionslist failed:', error);
|
||||||
|
res.status(status).json({ error: error.message });
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -100,3 +100,24 @@ export async function listChildren(googleAuthId, sku) {
|
|||||||
return store.article.listChildren(googleAuthId, sku);
|
return store.article.listChildren(googleAuthId, sku);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function getArticlelist(googleAuthId, sku) {
|
||||||
|
const store = await getStore();
|
||||||
|
return store.article.getArticlelist(googleAuthId, sku);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function setArticlelist(googleAuthId, sku, items) {
|
||||||
|
const store = await getStore();
|
||||||
|
return store.article.setArticlelist(googleAuthId, sku, items);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getOptionslist(googleAuthId, sku) {
|
||||||
|
const store = await getStore();
|
||||||
|
return store.article.getOptionslist(googleAuthId, sku);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function setOptionslist(googleAuthId, sku, options) {
|
||||||
|
const store = await getStore();
|
||||||
|
return store.article.setOptionslist(googleAuthId, sku, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user