u
This commit is contained in:
@@ -80,6 +80,7 @@ function articleErrorStatus(error) {
|
||||
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?.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;
|
||||
}
|
||||
|
||||
@@ -1931,5 +1932,283 @@ export function register(app, basePath = '') {
|
||||
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);
|
||||
}
|
||||
|
||||
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