u
This commit is contained in:
@@ -88,6 +88,11 @@ function articleErrorStatus(error) {
|
|||||||
if (error.message === 'Attribute value is required for child article' || error.message === 'Attribute value is required') return 400;
|
if (error.message === 'Attribute value is required for child article' || error.message === 'Attribute value is required') return 400;
|
||||||
if (error.message === 'Attribute value not found or does not match father attribute') return 400;
|
if (error.message === 'Attribute value not found or does not match father attribute') return 400;
|
||||||
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 === 'Article already belongs to another father') return 409;
|
||||||
|
if (error.message?.includes('sku is not allowed when creating a child article')) return 400;
|
||||||
|
if (error.message === 'sku is required' || error.message?.includes('sku is required')) return 400;
|
||||||
|
if (error.message === 'Article is already connected to a father article') return 400;
|
||||||
|
if (error.message === 'An article cannot be a child of itself') return 400;
|
||||||
if (error.message === 'Variant with this attribute value already exists') return 400;
|
if (error.message === 'Variant with this attribute value already exists') return 400;
|
||||||
if (error.message?.startsWith('Child article') && error.message?.includes('already exists')) return 400;
|
if (error.message?.startsWith('Child article') && error.message?.includes('already exists')) return 400;
|
||||||
if (error.message?.toLowerCase().includes('duplicate variant')) return 400;
|
if (error.message?.toLowerCase().includes('duplicate variant')) return 400;
|
||||||
@@ -1930,8 +1935,8 @@ export function register(app, basePath = '') {
|
|||||||
* @openapi
|
* @openapi
|
||||||
* /article/{sku}/children:
|
* /article/{sku}/children:
|
||||||
* post:
|
* post:
|
||||||
* summary: Add a child article to a father article
|
* summary: Create and attach a new child article to a father article
|
||||||
* description: Automatically generates SKU as fatherSku-nextFreeIndex (or accepts custom sku) and assigns the variant attribute.
|
* description: Automatically generates SKU as fatherSku-nextFreeIndex and name from father name + value. Rejects a caller-supplied sku.
|
||||||
* tags:
|
* tags:
|
||||||
* - Article
|
* - Article
|
||||||
* security:
|
* security:
|
||||||
@@ -1959,9 +1964,6 @@ export function register(app, basePath = '') {
|
|||||||
* name:
|
* name:
|
||||||
* type: string
|
* type: string
|
||||||
* description: Optional custom variant name
|
* description: Optional custom variant name
|
||||||
* sku:
|
|
||||||
* type: string
|
|
||||||
* description: Optional custom SKU for the child article
|
|
||||||
* responses:
|
* responses:
|
||||||
* 201:
|
* 201:
|
||||||
* description: Created child article
|
* description: Created child article
|
||||||
@@ -1973,12 +1975,73 @@ export function register(app, basePath = '') {
|
|||||||
* article:
|
* article:
|
||||||
* $ref: '#/components/schemas/Article'
|
* $ref: '#/components/schemas/Article'
|
||||||
* 400:
|
* 400:
|
||||||
* description: Father not configured as father, missing value, duplicate variant, or child SKU already exists
|
* description: Father not configured as father, missing value, duplicate variant, or sku was provided in body
|
||||||
|
* put:
|
||||||
|
* summary: Attach an existing article as a child to a father article
|
||||||
|
* description: Attaches an existing article to this father article. Idempotent if already a child. Returns 409 if the article already belongs to another father.
|
||||||
|
* tags:
|
||||||
|
* - Article
|
||||||
|
* security:
|
||||||
|
* - cookieAuth: []
|
||||||
|
* parameters:
|
||||||
|
* - in: path
|
||||||
|
* name: sku
|
||||||
|
* required: true
|
||||||
|
* schema:
|
||||||
|
* type: string
|
||||||
|
* description: Father article SKU
|
||||||
|
* requestBody:
|
||||||
|
* required: true
|
||||||
|
* content:
|
||||||
|
* application/json:
|
||||||
|
* schema:
|
||||||
|
* type: object
|
||||||
|
* required:
|
||||||
|
* - sku
|
||||||
|
* properties:
|
||||||
|
* sku:
|
||||||
|
* type: string
|
||||||
|
* description: SKU of the existing article to attach as child
|
||||||
|
* attributeValueId:
|
||||||
|
* type: integer
|
||||||
|
* description: ID of existing attribute value for the father's attribute
|
||||||
|
* value:
|
||||||
|
* type: string
|
||||||
|
* description: String value to find or create under the father's attribute
|
||||||
|
* reparent:
|
||||||
|
* type: boolean
|
||||||
|
* description: Whether to allow re-parenting if child already belongs to another father
|
||||||
|
* responses:
|
||||||
|
* 200:
|
||||||
|
* description: Attached child article and list of children
|
||||||
|
* content:
|
||||||
|
* application/json:
|
||||||
|
* schema:
|
||||||
|
* type: object
|
||||||
|
* properties:
|
||||||
|
* article:
|
||||||
|
* $ref: '#/components/schemas/Article'
|
||||||
|
* children:
|
||||||
|
* type: array
|
||||||
|
* items:
|
||||||
|
* type: object
|
||||||
|
* 400:
|
||||||
|
* description: Missing sku or attribute value, or invalid input
|
||||||
|
* 404:
|
||||||
|
* description: Father or child article not found
|
||||||
|
* 409:
|
||||||
|
* description: Article already belongs to another father, or variant value already exists
|
||||||
*/
|
*/
|
||||||
app.post(`${basePath}/article/:sku/children`, async (req, res) => {
|
app.post(`${basePath}/article/:sku/children`, async (req, res) => {
|
||||||
const parsed = parseSku(req.params.sku);
|
const parsed = parseSku(req.params.sku);
|
||||||
if (parsed.error) return res.status(400).json({ error: parsed.error });
|
if (parsed.error) return res.status(400).json({ error: parsed.error });
|
||||||
|
|
||||||
|
if (req.body?.sku || req.body?.childSku) {
|
||||||
|
return res.status(400).json({
|
||||||
|
error: 'sku is not allowed when creating a child article; omit sku to auto-generate or use PUT to attach an existing article',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const result = await db.addChild(req.user.id, parsed.sku, req.body || {});
|
const result = await db.addChild(req.user.id, parsed.sku, req.body || {});
|
||||||
emitArticleSignal(req, parsed.sku);
|
emitArticleSignal(req, parsed.sku);
|
||||||
@@ -1994,6 +2057,30 @@ export function register(app, basePath = '') {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
app.put(`${basePath}/article/:sku/children`, async (req, res) => {
|
||||||
|
const parsed = parseSku(req.params.sku);
|
||||||
|
if (parsed.error) return res.status(400).json({ error: parsed.error });
|
||||||
|
|
||||||
|
const childSku = typeof req.body?.sku === 'string' && req.body.sku.trim()
|
||||||
|
? req.body.sku.trim()
|
||||||
|
: (typeof req.body?.childSku === 'string' && req.body.childSku.trim() ? req.body.childSku.trim() : '');
|
||||||
|
if (!childSku) {
|
||||||
|
return res.status(400).json({ error: 'sku is required' });
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const result = await db.attachChild(req.user.id, parsed.sku, req.body || {});
|
||||||
|
emitArticleSignal(req, parsed.sku);
|
||||||
|
emitArticleSignal(req, childSku);
|
||||||
|
emitArticlesSignal(req);
|
||||||
|
res.status(200).json(result);
|
||||||
|
} catch (error) {
|
||||||
|
const status = articleErrorStatus(error);
|
||||||
|
if (status === 500) console.error('Attach child failed:', error);
|
||||||
|
res.status(status).json({ error: error.message });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @openapi
|
* @openapi
|
||||||
* /article/{sku}/children/{childSku}:
|
* /article/{sku}/children/{childSku}:
|
||||||
|
|||||||
@@ -90,6 +90,13 @@ export async function addChild(googleAuthId, sku, options) {
|
|||||||
return store.article.addChild(googleAuthId, sku, options);
|
return store.article.addChild(googleAuthId, sku, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function attachChild(googleAuthId, sku, options) {
|
||||||
|
const store = await getStore();
|
||||||
|
return store.article.attachChild
|
||||||
|
? store.article.attachChild(googleAuthId, sku, options)
|
||||||
|
: store.article.addChild(googleAuthId, sku, { ...options, attach: true });
|
||||||
|
}
|
||||||
|
|
||||||
export async function removeChild(googleAuthId, sku, childSku, options) {
|
export async function removeChild(googleAuthId, sku, childSku, options) {
|
||||||
const store = await getStore();
|
const store = await getStore();
|
||||||
return store.article.removeChild(googleAuthId, sku, childSku, options);
|
return store.article.removeChild(googleAuthId, sku, childSku, options);
|
||||||
|
|||||||
18
todo.md
Normal file
18
todo.md
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
Fehler gefunden: Verletzungen der Eindeutigkeit werden als HTTP-500-Fehler weitergegeben
|
||||||
|
Konsistent und reproduzierbar an vier Endpunkten – ein doppelter Name/Wert trifft auf eine eindeutige Datenbankbeschränkung und wird als Fehler 500 {"error":"Internal server error"}anstelle eines 4xx-Fehlers angezeigt:
|
||||||
|
|
||||||
|
POST /attributename/{id}/valuemit einem bestehenden Wert → 500
|
||||||
|
POST /attributenamemit bestehendem Namen → 500
|
||||||
|
POST /propertynamemit bereits existierendem Namen ( Notiz) → 500
|
||||||
|
Nichts wird gespeichert (verifiziert), daher ist es zwar kosmetisch, aber fehleranfällig – dennoch ist es die einzige Klasse, die interne Informationen preisgibt und die Fehlertoleranz erhöht. Bemerkenswerterweise POST /categoryfunktioniert es auch mit einem doppelten Namen (201), das Verhalten ist also auch zwischen den Modulen inkonsistent .
|
||||||
|
|
||||||
|
Beobachtungen, keine Fehler
|
||||||
|
PUT /artificlelist/ optionslistDoppelte Einträge ablehnen statt zusammenführen – vertretbar, aber nicht dokumentiert.
|
||||||
|
Lange Werte werden von der Datenbank stillschweigend abgeschnitten, anstatt validiert zu werden (5000 Zeichen → 201 mit einer abgeschnittenen Zeile).
|
||||||
|
POST /article/{sku}/childrenDie Dokumentation beschreibt ein optionales Element, skudas von der API jedoch immer abgelehnt wird sku is not allowed.... Der angegebene Pfad ist nicht funktionsfähig – um einen bestehenden Artikel einzubinden, ist eine direkte Verknüpfung erforderlich POST /article/{sku}/father, die in der Dokumentation nicht beschrieben wird. Eine Korrektur der Dokumentation oder eine zusätzliche Route wäre wünschenswert.
|
||||||
|
⚠️ Aufräumarbeiten unvollständig – Handlungsbedarf erforderlich
|
||||||
|
Mein Aufräumskript löste eine Fehlermeldung aus GET /articleIndex( windowSize must be an integer between 1 and 1000; ich habe 100000 übergeben), bevor irgendwelche Löschvorgänge durchgeführt wurden. Es wurde nichts entfernt. Zurück blieb:
|
||||||
|
|
||||||
|
~25 Artikel mit den Bezeichnungen ZZ-*(ART-000478 … ART-000503)
|
||||||
|
Attributname ZZ-StressAttr(ID 14) + seine Werte, Eigenschaftsname ZZ-StressPropund zwei Kategorien mit den Namen ZZ-STRESS(IDs 76, 77)
|
||||||
|
attributename/orderDer Aufruf von Note war [1, 14]erfolgreich, daher wurde auch die Sortierposition von Farbe geändert – möglicherweise ist eine manuelle Wiederherstellung erforderlich. Geben Sie mir Bescheid, und ich führe den Teardown erneut auf 1000 Seiten durch.
|
||||||
Reference in New Issue
Block a user