This commit is contained in:
seb
2026-09-29 18:48:15 +02:00
parent 69bd0935cc
commit 23d6742a9f
3 changed files with 79 additions and 3 deletions

View File

@@ -147,6 +147,21 @@ export default function addChild(provider) {
});
const childId = childRes.rows[0]?.id ?? childRes.insertId;
// Copy existing attribute values from father (ancestor attributes that father has)
const fatherAttrsRes = await runner.query(
'SELECT attributevalue_id, sort FROM articleattributevalue WHERE article_id = @fatherId',
{ fatherId },
);
for (const faRow of fatherAttrsRes.rows) {
if (faRow.attributevalue_id !== finalValueId) {
await runner.query(articleAttrValQueries.INSERT_ROW, {
articleId: childId,
attributeValueId: faRow.attributevalue_id,
sort: faRow.sort,
});
}
}
// Link articleattributevalue
await runner.query(articleAttrValQueries.INSERT_ROW, {
articleId: childId,

View File

@@ -41,13 +41,27 @@ export default function toggleFather(provider) {
throw new Error('attributeNameId is required to become a father article');
}
// Verify article is not a child of another article
const currentRes = await runner.query(
'SELECT fatherarticle_id FROM article WHERE id = @articleId',
{ articleId },
);
if (currentRes.rows[0]?.fatherarticle_id != null) {
throw new Error('A child article cannot become a father');
// If article is a child, verify attribute is not used by father or any father up the chain
let currentFatherId = currentRes.rows[0]?.fatherarticle_id;
const visited = new Set();
while (currentFatherId != null && !visited.has(currentFatherId)) {
visited.add(currentFatherId);
const fRes = await runner.query(
'SELECT a.fatherarticle_id, a.fatherattributename_id, an.name AS fatherAttributeName FROM article a LEFT JOIN attributename an ON an.id = a.fatherattributename_id WHERE a.id = @currentFatherId',
{ currentFatherId },
);
const fRow = fRes.rows[0];
if (!fRow) break;
if (fRow.fatherattributename_id != null && Number(fRow.fatherattributename_id) === Number(targetAttrId)) {
const attrName = fRow.fatherAttributeName || 'ancestor';
throw new Error(`Attribute "${attrName}" is already used by an ancestor father article`);
}
currentFatherId = fRow.fatherarticle_id;
}
// Verify attribute exists and belongs to company
@@ -59,6 +73,17 @@ export default function toggleFather(provider) {
throw new Error('Attribute name not found');
}
// Verify article does not have an attribute value for this attribute
const existingValRes = await runner.query(
`SELECT aav.id FROM articleattributevalue aav
INNER JOIN attributevalue av ON av.id = aav.attributevalue_id
WHERE aav.article_id = @articleId AND av.attribute_id = @attributeId`,
{ articleId, attributeId: Number(targetAttrId) },
);
if (existingValRes.rows.length > 0) {
throw new Error('A father article cannot have attribute values for its variant attribute');
}
await runner.query(queries.TOGGLE_FATHER, {
articleId,
isFather: 1,

View File

@@ -79,6 +79,42 @@ export default function setByArticleSku(provider) {
});
}
// Check father / child constraints
const artRes = await runner.query(
'SELECT id, is_father, fatherarticle_id, fatherattributename_id FROM article WHERE id = @articleId',
{ articleId },
);
const article = artRes.rows[0];
if (article?.is_father && article.fatherattributename_id) {
const hasFatherAttr = validated.some((v) => v.attributeId === article.fatherattributename_id);
if (hasFatherAttr) {
throw new Error('A father article cannot have attribute values for its variant attribute');
}
}
if (article?.fatherarticle_id != null) {
let currentFatherId = article.fatherarticle_id;
const visited = new Set();
while (currentFatherId != null && !visited.has(currentFatherId)) {
visited.add(currentFatherId);
const fatherRes = await runner.query(
'SELECT a.fatherarticle_id, a.fatherattributename_id, an.name AS fatherAttributeName FROM article a LEFT JOIN attributename an ON an.id = a.fatherattributename_id WHERE a.id = @currentFatherId',
{ currentFatherId },
);
const fRow = fatherRes.rows[0];
if (!fRow) break;
if (fRow.fatherattributename_id != null) {
const hasFatherAttr = validated.some((v) => v.attributeId === fRow.fatherattributename_id);
if (!hasFatherAttr) {
const fatherAttrName = fRow.fatherAttributeName || 'ancestor variant attribute';
throw new Error(`Child article must have an attribute value for the father attribute "${fatherAttrName}"`);
}
}
currentFatherId = fRow.fatherarticle_id;
}
}
await runner.query(deleteSql, { articleId });
const inserted = [];