This commit is contained in:
seb
2026-09-30 22:37:40 +02:00
parent 3d2f8e9296
commit 74ed74fc68
19 changed files with 122 additions and 56 deletions

View File

@@ -9,43 +9,71 @@ export default function del(provider) {
const queries = isSqlite ? sqliteQueries : mssqlQueries;
/**
* Deletes an article by its SKU, refusing when it still has children.
* Deletes an article by its SKU, refusing when it still has children unless cascade is true.
*
* @param {number} googleAuthId - The id of the Google auth user.
* @param {string} sku - The article SKU.
* @param {object} [tx] - Optional transaction to run within.
* @param {object|*} [optionsOrTx] - Options object ({ cascade?: boolean }) or optional transaction.
* @param {object} [maybeTx] - Optional transaction if options was passed.
* @returns {Promise<void>}
* @throws {Error} If the article has children or is not found.
* @throws {Error} If the article has children (when cascade=false) or is not found.
*
* @example
* await store.article.delete(42, 'SKU-1');
* await store.article.delete(42, 'SKU-1', { cascade: true });
*/
return async (googleAuthId, sku, tx) => {
return async (googleAuthId, sku, optionsOrTx, maybeTx) => {
let options = {};
let tx;
if (optionsOrTx && typeof optionsOrTx === 'object' && typeof optionsOrTx.query !== 'function') {
options = optionsOrTx;
tx = maybeTx;
} else {
tx = optionsOrTx;
}
const cascade = Boolean(options.cascade);
const runDelete = async (runner) => {
const { articleId } = await resolve(googleAuthId, sku, runner);
const deleteArticleAndLists = async (id) => {
const listIds = await runner.query(queries.GET_LIST_IDS, { articleId: id });
const { articlelistId, optionslistId } = listIds.rows[0] ?? {};
await runner.query(queries.DELETE_PICS_BY_ARTICLE, { articleId: id });
const deleted = await runner.query(queries.DELETE_BY_ID, { articleId: id });
if (!deleted.rowsAffected) {
throw new Error('Article not found');
}
if (articlelistId != null) {
await runner.query(queries.DELETE_ARTICLELIST, { id: articlelistId });
}
if (optionslistId != null) {
await runner.query(queries.DELETE_OPTIONSLIST, { id: optionslistId });
}
};
const deleteSubtree = async (id) => {
const children = await runner.query(queries.GET_CHILDREN_IDS, { id });
for (const child of children.rows) {
await deleteSubtree(child.id);
}
await deleteArticleAndLists(id);
};
const childCount = await runner.query(queries.GET_CHILD_COUNT, { articleId });
if (childCount.rows[0].count > 0) {
throw new Error('Article has children');
if (!cascade) {
throw new Error('Article has children');
}
await deleteSubtree(articleId);
return;
}
const listIds = await runner.query(queries.GET_LIST_IDS, { articleId });
const { articlelistId, optionslistId } = listIds.rows[0] ?? {};
await runner.query(queries.DELETE_PICS_BY_ARTICLE, { articleId });
const deleted = await runner.query(queries.DELETE_BY_ID, { articleId });
if (!deleted.rowsAffected) {
throw new Error('Article not found');
}
if (articlelistId != null) {
await runner.query(queries.DELETE_ARTICLELIST, { id: articlelistId });
}
if (optionslistId != null) {
await runner.query(queries.DELETE_OPTIONSLIST, { id: optionslistId });
}
await deleteArticleAndLists(articleId);
};
if (tx) {