diff --git a/docs/api/openapi.json b/docs/api/openapi.json index a179b3a..d7f1078 100644 --- a/docs/api/openapi.json +++ b/docs/api/openapi.json @@ -14531,8 +14531,9 @@ }, "photos": { "type": "array", + "description": "Attached article photos", "items": { - "type": "object" + "$ref": "#/components/schemas/ArticlePhoto" } }, "eans": { @@ -14556,6 +14557,54 @@ } } }, + "ArticlePhoto": { + "type": "object", + "description": "Article photo metadata", + "required": [ + "sort", + "fullHash", + "fullW", + "fullH", + "fullSize", + "thumbW", + "thumbH", + "thumbHash" + ], + "properties": { + "sort": { + "type": "integer", + "description": "Display sort order" + }, + "fullHash": { + "type": "string", + "description": "SHA-256 hex hash of the full AVIF image" + }, + "fullW": { + "type": "integer", + "description": "Width in pixels of the full image" + }, + "fullH": { + "type": "integer", + "description": "Height in pixels of the full image" + }, + "fullSize": { + "type": "integer", + "description": "Byte length of full AVIF" + }, + "thumbW": { + "type": "integer", + "description": "Width in pixels of the thumbnail image" + }, + "thumbH": { + "type": "integer", + "description": "Height in pixels of the thumbnail image" + }, + "thumbHash": { + "type": "string", + "description": "Base64 thumbhash preview" + } + } + }, "ArticlePriceEntry": { "type": "object", "description": "Article selling price tier for a customer group (note price field is net, not price)", diff --git a/docs/api/routes.md b/docs/api/routes.md index aa89afc..f00e225 100644 --- a/docs/api/routes.md +++ b/docs/api/routes.md @@ -14,25 +14,25 @@ Overview of all 141 API endpoints across all modules. |:---|:---|:---|:---|:---| | `POST` | `/article` | `body: { categoryId, name, track_stock? }` | `201 { article: { id, categoryId, name, sku, track_stock } }` | Create article in category | | `DELETE` | `/article/{sku}` | `sku:string, query: cascade?:boolean` | `204 void` | Delete article by SKU | -| `GET` | `/article/{sku}` | `sku:string` | `200 { article: { id, sku, name, slug, track_stock, unitamount, weight, unit, brand, categoryIds: integer[], photos: object[], eans: string[], prices: { minmultiplier, net, taxRate, customergroupId }[], suppliers: { id, articleId, entityId, supplierName, sku, pu, stock, sort, priceId, price }[] } }` | Get article by SKU | -| `PATCH` | `/article/{sku}` | `sku:string, body: { name?, unitamount?, unitSi?, track_stock? }` | `200 { article: { id, sku, name, slug, track_stock, unitamount, weight, unit, brand, categoryIds: integer[], photos: object[], eans: string[], prices: { minmultiplier, net, taxRate, customergroupId }[], suppliers: { id, articleId, entityId, supplierName, sku, pu, stock, sort, priceId, price }[] } }` | Update article by SKU | +| `GET` | `/article/{sku}` | `sku:string` | `200 { article: { id, sku, name, slug, track_stock, unitamount, weight, unit, brand, categoryIds: integer[], photos: { sort, fullHash, fullW, fullH, fullSize, thumbW, thumbH, thumbHash }[], eans: string[], prices: { minmultiplier, net, taxRate, customergroupId }[], suppliers: { id, articleId, entityId, supplierName, sku, pu, stock, sort, priceId, price }[] } }` | Get article by SKU | +| `PATCH` | `/article/{sku}` | `sku:string, body: { name?, unitamount?, unitSi?, track_stock? }` | `200 { article: { id, sku, name, slug, track_stock, unitamount, weight, unit, brand, categoryIds: integer[], photos: { sort, fullHash, fullW, fullH, fullSize, thumbW, thumbH, thumbHash }[], eans: string[], prices: { minmultiplier, net, taxRate, customergroupId }[], suppliers: { id, articleId, entityId, supplierName, sku, pu, stock, sort, priceId, price }[] } }` | Update article by SKU | | `GET` | `/article/{sku}/articlelist` | `sku:string` | `200 { items: { id, articleId, sku, name, count, sort }[] }` | Get Stückliste (bundle items) for an article | | `PUT` | `/article/{sku}/articlelist` | `sku:string, body: { items: { articleId?, sku?: string, count?, sort? }[] }` | `200 { items: object[] }` | Set Stückliste (bundle items) for an article | | `GET` | `/article/{sku}/attributevalue` | `sku:string` | `200 { attributevalues: { id, articleId, attributeId, attributeName, exclusive, attributeValueId, value, sort }[] }` | List article attribute values | | `PUT` | `/article/{sku}/attributevalue` | `sku:string, body: { attributevalues: any[] }` | `200 { attributevalues: { id, articleId, attributeId, attributeName, exclusive, attributeValueId, value, sort }[] }` | Bulk set article attribute values | -| `PUT` | `/article/{sku}/brand` | `sku:string, body: { brandId: integer }` | `200 { article: { id, sku, name, slug, track_stock, unitamount, weight, unit, brand, categoryIds: integer[], photos: object[], eans: string[], prices: { minmultiplier, net, taxRate, customergroupId }[], suppliers: { id, articleId, entityId, supplierName, sku, pu, stock, sort, priceId, price }[] } }` | Set or clear article brand by SKU | -| `PUT` | `/article/{sku}/categories` | `sku:string, body: { categoryIds: integer[] }` | `200 { article: { id, sku, name, slug, track_stock, unitamount, weight, unit, brand, categoryIds: integer[], photos: object[], eans: string[], prices: { minmultiplier, net, taxRate, customergroupId }[], suppliers: { id, articleId, entityId, supplierName, sku, pu, stock, sort, priceId, price }[] } }` | Replace article categories by SKU | +| `PUT` | `/article/{sku}/brand` | `sku:string, body: { brandId: integer }` | `200 { article: { id, sku, name, slug, track_stock, unitamount, weight, unit, brand, categoryIds: integer[], photos: { sort, fullHash, fullW, fullH, fullSize, thumbW, thumbH, thumbHash }[], eans: string[], prices: { minmultiplier, net, taxRate, customergroupId }[], suppliers: { id, articleId, entityId, supplierName, sku, pu, stock, sort, priceId, price }[] } }` | Set or clear article brand by SKU | +| `PUT` | `/article/{sku}/categories` | `sku:string, body: { categoryIds: integer[] }` | `200 { article: { id, sku, name, slug, track_stock, unitamount, weight, unit, brand, categoryIds: integer[], photos: { sort, fullHash, fullW, fullH, fullSize, thumbW, thumbH, thumbHash }[], eans: string[], prices: { minmultiplier, net, taxRate, customergroupId }[], suppliers: { id, articleId, entityId, supplierName, sku, pu, stock, sort, priceId, price }[] } }` | Replace article categories by SKU | | `GET` | `/article/{sku}/children` | `sku:string` | `200 { children: { id, sku, name, fathersort, attributeValueId, attributeValue }[] }` | List child articles of a father article | | `POST` | `/article/{sku}/children` | `sku:string, body: { attributeValueId?, value?, name?, sku?: string }` | `201 { article: { id, categoryId, name, sku, track_stock } }` | Add a child article to a father article | | `DELETE` | `/article/{sku}/children/{childSku}` | `sku:string, childSku:string, query: deleteArticle?:boolean` | `200 { success, deleted }` | Remove a child article from a father article | -| `PUT` | `/article/{sku}/eans` | `sku:string, body: { eans: string[] }` | `200 { article: { id, sku, name, slug, track_stock, unitamount, weight, unit, brand, categoryIds: integer[], photos: object[], eans: string[], prices: { minmultiplier, net, taxRate, customergroupId }[], suppliers: { id, articleId, entityId, supplierName, sku, pu, stock, sort, priceId, price }[] } }` | Replace article EANs by SKU | +| `PUT` | `/article/{sku}/eans` | `sku:string, body: { eans: string[] }` | `200 { article: { id, sku, name, slug, track_stock, unitamount, weight, unit, brand, categoryIds: integer[], photos: { sort, fullHash, fullW, fullH, fullSize, thumbW, thumbH, thumbHash }[], eans: string[], prices: { minmultiplier, net, taxRate, customergroupId }[], suppliers: { id, articleId, entityId, supplierName, sku, pu, stock, sort, priceId, price }[] } }` | Replace article EANs by SKU | | `POST` | `/article/{sku}/father` | `sku:string, body: { isFather, attributeNameId? }` | `200 { article: { id, categoryId, name, sku, track_stock } }` | Toggle father mode for an article | | `GET` | `/article/{sku}/history` | `sku:string, query: limit?:integer` | `200 { history: { id, date, text }[], truncated }` | Get article history by SKU | | `DELETE` | `/article/{sku}/image/{fullHash}` | `sku:string, fullHash:string` | `204 void` | Delete article image | | `PUT` | `/article/{sku}/images/order` | `sku:string, body: { fullHashes: string[] }` | `200 { fullHashes: string[] }` | Reorder article images | | `GET` | `/article/{sku}/optionslist` | `sku:string` | `200 { options: { id, articleId, sku, name, count, sort, mandated }[] }` | Get options list for an article | | `PUT` | `/article/{sku}/optionslist` | `sku:string, body: { options: { articleId?, sku?: string, count?, sort?, mandated? }[] }` | `200 { options: object[] }` | Set options list for an article | -| `PUT` | `/article/{sku}/prices` | `sku:string, body: { prices: { price, tax, minmultiplier? }[] }` | `200 { article: { id, sku, name, slug, track_stock, unitamount, weight, unit, brand, categoryIds: integer[], photos: object[], eans: string[], prices: { minmultiplier, net, taxRate, customergroupId }[], suppliers: { id, articleId, entityId, supplierName, sku, pu, stock, sort, priceId, price }[] } }` | Replace POS prices by SKU | +| `PUT` | `/article/{sku}/prices` | `sku:string, body: { prices: { price, tax, minmultiplier? }[] }` | `200 { article: { id, sku, name, slug, track_stock, unitamount, weight, unit, brand, categoryIds: integer[], photos: { sort, fullHash, fullW, fullH, fullSize, thumbW, thumbH, thumbHash }[], eans: string[], prices: { minmultiplier, net, taxRate, customergroupId }[], suppliers: { id, articleId, entityId, supplierName, sku, pu, stock, sort, priceId, price }[] } }` | Replace POS prices by SKU | | `POST` | `/article/{sku}/print` | `sku:string, body: { templateId, printerId, quantity }` | `200` | Print article label | | `GET` | `/article/{sku}/property` | `sku:string` | `200 { properties: { id, articleId, propertyId, name, exclusive, value, sort }[] }` | List article properties | | `PUT` | `/article/{sku}/property` | `sku:string, body: { properties: { propertyId, value, sort? }[] }` | `200 { properties: { id, articleId, propertyId, name, exclusive, value, sort }[] }` | Bulk set article properties | @@ -42,8 +42,8 @@ Overview of all 141 API endpoints across all modules. | `PUT` | `/article/{sku}/supplier/order` | `sku:string, body: { ids: integer[] }` | `200 { ids: integer[] }` | Reorder article suppliers | | `DELETE` | `/article/{sku}/supplier/{id}` | `sku:string, id:integer` | `204 void` | Remove supplier assignment from article | | `PATCH` | `/article/{sku}/supplier/{id}` | `sku:string, id:integer, body: { sku?: string, pu?, stock?, sort?, netPrice?, taxId?, taxRate? }` | `200 { supplier: { id, articleId, entityId, supplierName, sku, pu, stock, sort, priceId, price } }` | Update article supplier assignment | -| `PUT` | `/article/{sku}/track_stock` | `sku:string, body: { track_stock: boolean }` | `200 { article: { id, sku, name, slug, track_stock, unitamount, weight, unit, brand, categoryIds: integer[], photos: object[], eans: string[], prices: { minmultiplier, net, taxRate, customergroupId }[], suppliers: { id, articleId, entityId, supplierName, sku, pu, stock, sort, priceId, price }[] } }` | Set article track_stock flag by SKU | -| `PUT` | `/article/{sku}/weight` | `sku:string, body: { weight: number }` | `200 { article: { id, sku, name, slug, track_stock, unitamount, weight, unit, brand, categoryIds: integer[], photos: object[], eans: string[], prices: { minmultiplier, net, taxRate, customergroupId }[], suppliers: { id, articleId, entityId, supplierName, sku, pu, stock, sort, priceId, price }[] } }` | Set article weight by SKU | +| `PUT` | `/article/{sku}/track_stock` | `sku:string, body: { track_stock: boolean }` | `200 { article: { id, sku, name, slug, track_stock, unitamount, weight, unit, brand, categoryIds: integer[], photos: { sort, fullHash, fullW, fullH, fullSize, thumbW, thumbH, thumbHash }[], eans: string[], prices: { minmultiplier, net, taxRate, customergroupId }[], suppliers: { id, articleId, entityId, supplierName, sku, pu, stock, sort, priceId, price }[] } }` | Set article track_stock flag by SKU | +| `PUT` | `/article/{sku}/weight` | `sku:string, body: { weight: number }` | `200 { article: { id, sku, name, slug, track_stock, unitamount, weight, unit, brand, categoryIds: integer[], photos: { sort, fullHash, fullW, fullH, fullSize, thumbW, thumbH, thumbHash }[], eans: string[], prices: { minmultiplier, net, taxRate, customergroupId }[], suppliers: { id, articleId, entityId, supplierName, sku, pu, stock, sort, priceId, price }[] } }` | Set article weight by SKU | | `GET` | `/articleIndex` | — | `200 { articles: { id, sku, name, eans: string[], categoryIds: integer[] }[] }` | List article search index | | `GET` | `/attributename` | — | `200 { attributenames: { id, name, sort, exclusive, values: { id, attributeId, value, sort }[] }[] }` | List attribute names | | `POST` | `/attributename` | `body: { name, sort?, exclusive? }` | `201 { attributename: { id, name, sort, exclusive, values: { id, attributeId, value, sort }[] } }` | Create attribute name | diff --git a/docs/api/routes/article/_sku/track_stock.md b/docs/api/routes/article/_sku/track_stock.md index 1642ea3..3148499 100644 --- a/docs/api/routes/article/_sku/track_stock.md +++ b/docs/api/routes/article/_sku/track_stock.md @@ -49,7 +49,16 @@ Updated article detail 1 ], "photos": [ - {} + { + "sort": 1, + "fullHash": "…", + "fullW": 1, + "fullH": 1, + "fullSize": 1, + "thumbW": 1, + "thumbH": 1, + "thumbHash": "…" + } ], "eans": [ "…" diff --git a/docs/api/routes/article/get.md b/docs/api/routes/article/get.md index 07a9437..4af2dba 100644 --- a/docs/api/routes/article/get.md +++ b/docs/api/routes/article/get.md @@ -32,7 +32,16 @@ Article detail 1 ], "photos": [ - {} + { + "sort": 1, + "fullHash": "…", + "fullW": 1, + "fullH": 1, + "fullSize": 1, + "thumbW": 1, + "thumbH": 1, + "thumbHash": "…" + } ], "eans": [ "…" diff --git a/docs/api/routes/article/set-brand.md b/docs/api/routes/article/set-brand.md index 3d5e6ef..4301474 100644 --- a/docs/api/routes/article/set-brand.md +++ b/docs/api/routes/article/set-brand.md @@ -50,7 +50,16 @@ Updated article detail 1 ], "photos": [ - {} + { + "sort": 1, + "fullHash": "…", + "fullW": 1, + "fullH": 1, + "fullSize": 1, + "thumbW": 1, + "thumbH": 1, + "thumbHash": "…" + } ], "eans": [ "…" diff --git a/docs/api/routes/article/set-categories.md b/docs/api/routes/article/set-categories.md index 0af867f..c138135 100644 --- a/docs/api/routes/article/set-categories.md +++ b/docs/api/routes/article/set-categories.md @@ -54,7 +54,16 @@ Updated article detail 1 ], "photos": [ - {} + { + "sort": 1, + "fullHash": "…", + "fullW": 1, + "fullH": 1, + "fullSize": 1, + "thumbW": 1, + "thumbH": 1, + "thumbHash": "…" + } ], "eans": [ "…" diff --git a/docs/api/routes/article/set-eans.md b/docs/api/routes/article/set-eans.md index ca72edb..711f554 100644 --- a/docs/api/routes/article/set-eans.md +++ b/docs/api/routes/article/set-eans.md @@ -52,7 +52,16 @@ Updated article detail 1 ], "photos": [ - {} + { + "sort": 1, + "fullHash": "…", + "fullW": 1, + "fullH": 1, + "fullSize": 1, + "thumbW": 1, + "thumbH": 1, + "thumbHash": "…" + } ], "eans": [ "…" diff --git a/docs/api/routes/article/set-prices.md b/docs/api/routes/article/set-prices.md index 061889f..d2687f1 100644 --- a/docs/api/routes/article/set-prices.md +++ b/docs/api/routes/article/set-prices.md @@ -64,7 +64,16 @@ Updated article detail 1 ], "photos": [ - {} + { + "sort": 1, + "fullHash": "…", + "fullW": 1, + "fullH": 1, + "fullSize": 1, + "thumbW": 1, + "thumbH": 1, + "thumbHash": "…" + } ], "eans": [ "…" diff --git a/docs/api/routes/article/set-weight.md b/docs/api/routes/article/set-weight.md index 7f4540f..8e981c1 100644 --- a/docs/api/routes/article/set-weight.md +++ b/docs/api/routes/article/set-weight.md @@ -50,7 +50,16 @@ Updated article detail 1 ], "photos": [ - {} + { + "sort": 1, + "fullHash": "…", + "fullW": 1, + "fullH": 1, + "fullSize": 1, + "thumbW": 1, + "thumbH": 1, + "thumbHash": "…" + } ], "eans": [ "…" diff --git a/docs/api/routes/article/update.md b/docs/api/routes/article/update.md index 512a9fa..57e1af3 100644 --- a/docs/api/routes/article/update.md +++ b/docs/api/routes/article/update.md @@ -54,7 +54,16 @@ Updated article detail 1 ], "photos": [ - {} + { + "sort": 1, + "fullHash": "…", + "fullW": 1, + "fullH": 1, + "fullSize": 1, + "thumbW": 1, + "thumbH": 1, + "thumbHash": "…" + } ], "eans": [ "…" diff --git a/src/api/openapi.js b/src/api/openapi.js index 4642c66..5b0dc73 100644 --- a/src/api/openapi.js +++ b/src/api/openapi.js @@ -144,8 +144,9 @@ * type: integer * photos: * type: array + * description: Attached article photos * items: - * type: object + * $ref: '#/components/schemas/ArticlePhoto' * eans: * type: array * items: @@ -159,6 +160,35 @@ * type: array * items: * $ref: '#/components/schemas/ArticleSupplier' + * ArticlePhoto: + * type: object + * description: Article photo metadata + * required: [sort, fullHash, fullW, fullH, fullSize, thumbW, thumbH, thumbHash] + * properties: + * sort: + * type: integer + * description: Display sort order + * fullHash: + * type: string + * description: SHA-256 hex hash of the full AVIF image + * fullW: + * type: integer + * description: Width in pixels of the full image + * fullH: + * type: integer + * description: Height in pixels of the full image + * fullSize: + * type: integer + * description: Byte length of full AVIF + * thumbW: + * type: integer + * description: Width in pixels of the thumbnail image + * thumbH: + * type: integer + * description: Height in pixels of the thumbnail image + * thumbHash: + * type: string + * description: Base64 thumbhash preview * ArticlePriceEntry: * type: object * description: Article selling price tier for a customer group (note price field is net, not price)