This commit is contained in:
seb
2026-09-22 07:25:16 +02:00
parent 4ed6260e91
commit cca131d83a
148 changed files with 5343 additions and 3466 deletions

View File

@@ -1,16 +1,24 @@
import {
ADD_CATEGORY,
DELETE_CATEGORIES_BY_ARTICLE,
ADD_CATEGORY as MSSQL_ADD_CATEGORY,
DELETE_CATEGORIES_BY_ARTICLE as MSSQL_DELETE_CATEGORIES,
} from '../../providers/mssql/queries/article.js';
import request from '../request.js';
import {
ADD_CATEGORY as SQLITE_ADD_CATEGORY,
DELETE_CATEGORIES_BY_ARTICLE as SQLITE_DELETE_CATEGORIES,
} from '../../providers/sqlite3/queries/article.js';
import resolveCategoryAccess from '../category/resolveCategoryAccess.js';
import queryBySku from './queryBySku.js';
import resolveArticleBySku from './resolveArticleBySku.js';
import makeRunner from '../runner.js';
export default function setCategoryIdsBySku(pool) {
const resolve = resolveArticleBySku(pool);
const categoryAccess = resolveCategoryAccess(pool);
const load = queryBySku(pool);
export default function setCategoryIdsBySku(provider) {
const resolve = resolveArticleBySku(provider);
const categoryAccess = resolveCategoryAccess(provider);
const load = queryBySku(provider);
const isSqlite = provider?.dialect === 'sqlite3';
const addCategorySql = isSqlite ? SQLITE_ADD_CATEGORY : MSSQL_ADD_CATEGORY;
const deleteCategoriesSql = isSqlite ? SQLITE_DELETE_CATEGORIES : MSSQL_DELETE_CATEGORIES;
/**
* Replaces the category membership of an article by its SKU.
@@ -18,6 +26,7 @@ export default function setCategoryIdsBySku(pool) {
* @param {number} googleAuthId - The id of the Google auth user.
* @param {string} sku - The article SKU.
* @param {Array<number>} categoryIds - The category ids the article should belong to (at least one).
* @param {object} [tx] - Optional transaction to run within.
* @returns {Promise<object>} The updated article.
* @throws {Error} If the category ids are invalid or the article is not found.
*
@@ -25,7 +34,7 @@ export default function setCategoryIdsBySku(pool) {
* const article = await store.article.setCategoryIdsBySku(42, 'SKU-1', [5, 9]);
* // => { id, sku, name, ... }
*/
return async (googleAuthId, sku, categoryIds) => {
return async (googleAuthId, sku, categoryIds, tx) => {
if (!Array.isArray(categoryIds)) {
throw new Error('Invalid categoryIds');
}
@@ -42,49 +51,45 @@ export default function setCategoryIdsBySku(pool) {
throw new Error('Article must have at least one category');
}
const { articleId, languageId, companyId } = await resolve(
googleAuthId,
sku,
);
const runSet = async (runner) => {
const { articleId, languageId, companyId } = await resolve(
googleAuthId,
sku,
runner,
);
const tx = pool.transaction();
await tx.begin();
try {
for (const categoryId of normalized) {
// Ensures the category belongs to the same company as the article.
const access = await categoryAccess(googleAuthId, categoryId);
const access = await categoryAccess(googleAuthId, categoryId, runner);
if (access.companyId !== companyId) {
throw new Error('Invalid categoryIds');
}
}
await request(pool, tx)
.input('articleId', articleId)
.query(DELETE_CATEGORIES_BY_ARTICLE);
await runner.query(deleteCategoriesSql, { articleId });
for (const categoryId of normalized) {
await request(pool, tx)
.input('categoryId', categoryId)
.input('articleId', articleId)
.query(ADD_CATEGORY);
await runner.query(addCategorySql, {
categoryId,
articleId,
});
}
await tx.commit();
} catch (err) {
try {
await tx.rollback();
} catch {
// ignore
const article = await load(articleId, languageId, runner);
if (!article) {
throw new Error('Article not found');
}
throw err;
}
const article = await load(articleId, languageId);
if (!article) {
throw new Error('Article not found');
}
return article;
};
return article;
if (tx) {
return runSet(makeRunner(provider, tx));
}
if (typeof provider?.transaction === 'function') {
return provider.transaction(runSet);
}
return runSet(makeRunner(provider));
};
}