This commit is contained in:
seb
2026-09-29 18:26:42 +02:00
parent 30820ba8c7
commit 69bd0935cc
14 changed files with 710 additions and 20 deletions

View File

@@ -0,0 +1,93 @@
import * as mssqlArticle from '../../providers/mssql/queries/article.js';
import * as sqliteArticle from '../../providers/sqlite3/queries/article.js';
import { GET_CHILD_COUNT as MSSQL_GET_CHILD_COUNT } from '../../providers/mssql/queries/articleDelete.js';
import { GET_CHILD_COUNT as SQLITE_GET_CHILD_COUNT } from '../../providers/sqlite3/queries/articleDelete.js';
import * as mssqlAttr from '../../providers/mssql/queries/attributename.js';
import * as sqliteAttr from '../../providers/sqlite3/queries/attributename.js';
import resolveArticleBySku from './resolveArticleBySku.js';
import getBySku from './getBySku.js';
import makeRunner from '../runner.js';
export default function toggleFather(provider) {
const resolve = resolveArticleBySku(provider);
const load = getBySku(provider);
const isSqlite = provider?.dialect === 'sqlite3';
const queries = isSqlite ? sqliteArticle : mssqlArticle;
const getChildCountSql = isSqlite ? SQLITE_GET_CHILD_COUNT : MSSQL_GET_CHILD_COUNT;
const attrQueries = isSqlite ? sqliteAttr : mssqlAttr;
/**
* Toggles an article into or out of father mode.
*
* @param {number} googleAuthId - The id of the Google auth user.
* @param {string} sku - The article SKU.
* @param {object} options
* @param {boolean} options.isFather - Whether the article should be a father article.
* @param {number} [options.attributeNameId] - The attribute name id required when enabling father mode.
* @param {number} [options.fatherAttributeNameId] - Alias for attributeNameId.
* @param {object} [tx] - Optional transaction.
* @returns {Promise<object>} The updated article detail.
*/
return async (googleAuthId, sku, { isFather, attributeNameId, fatherAttributeNameId } = {}, tx) => {
const run = async (runner) => {
const { articleId, companyId } = await resolve(googleAuthId, sku, runner);
const targetIsFather = Boolean(isFather);
const targetAttrId = attributeNameId ?? fatherAttributeNameId;
if (targetIsFather) {
if (!targetAttrId || Number(targetAttrId) <= 0) {
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');
}
// Verify attribute exists and belongs to company
const attrRes = await runner.query(attrQueries.GET_BY_COMPANY_AND_ID, {
id: Number(targetAttrId),
companyId,
});
if (!attrRes.rows[0]) {
throw new Error('Attribute name not found');
}
await runner.query(queries.TOGGLE_FATHER, {
articleId,
isFather: 1,
fatherAttributeNameId: Number(targetAttrId),
});
} else {
// Disabling father: verify zero children
const childCountRes = await runner.query(getChildCountSql, { articleId });
const childCount = childCountRes.rows[0]?.count ?? 0;
if (childCount > 0) {
throw new Error('Cannot disable father mode on an article that still has children');
}
await runner.query(queries.TOGGLE_FATHER, {
articleId,
isFather: 0,
fatherAttributeNameId: null,
});
}
return load(googleAuthId, sku, runner);
};
if (tx) {
return run(makeRunner(provider, tx));
}
if (typeof provider?.transaction === 'function') {
return provider.transaction(run);
}
return run(makeRunner(provider));
};
}