import { CREATE as MSSQL_CREATE_ARTICLE } from '../../providers/mssql/queries/article.js'; import { CREATE as SQLITE_CREATE_ARTICLE } from '../../providers/sqlite3/queries/article.js'; import { ADD as MSSQL_ADD_CATEGORYARTICLE } from '../../providers/mssql/queries/categoryarticle.js'; import { ADD as SQLITE_ADD_CATEGORYARTICLE } from '../../providers/sqlite3/queries/categoryarticle.js'; import { CREATE as MSSQL_CREATE_ARTICLETEXT } from '../../providers/mssql/queries/articletext.js'; import { CREATE as SQLITE_CREATE_ARTICLETEXT } from '../../providers/sqlite3/queries/articletext.js'; import { INSERT as MSSQL_INSERT_HISTORY } from '../../providers/mssql/queries/articlehistory.js'; import { INSERT as SQLITE_INSERT_HISTORY } from '../../providers/sqlite3/queries/articlehistory.js'; import { isUniqueConstraintError } from '../../providers/provider.js'; import resolveCategoryAccess from '../category/resolveCategoryAccess.js'; import ensureDefaultUnit from '../unit/ensureDefault.js'; import nextSku from '../numbers/nextSku.js'; import makeRunner from '../runner.js'; import slugify from '../slugify.js'; export default function createUnderParent(provider) { const access = resolveCategoryAccess(provider); const ensureUnit = ensureDefaultUnit(provider); const allocateSku = nextSku(provider); const isSqlite = provider?.dialect === 'sqlite3'; const createArticleSql = isSqlite ? SQLITE_CREATE_ARTICLE : MSSQL_CREATE_ARTICLE; const addCategoryArticleSql = isSqlite ? SQLITE_ADD_CATEGORYARTICLE : MSSQL_ADD_CATEGORYARTICLE; const createArticleTextSql = isSqlite ? SQLITE_CREATE_ARTICLETEXT : MSSQL_CREATE_ARTICLETEXT; const insertHistorySql = isSqlite ? SQLITE_INSERT_HISTORY : MSSQL_INSERT_HISTORY; /** * Creates a new article under a given parent category, allocating a SKU and * a default unit. * * @param {object} input - The article creation input. * @param {number} input.googleAuthId - The id of the Google auth user. * @param {number} input.parentId - The id of the parent category. * @param {string} input.name - The article name. * @param {boolean|number} [input.track_stock=true] - Whether inventory stock is tracked. * @param {object} [tx] - Optional transaction to run within. * @returns {Promise<{id: number, parentId: number, name: string, sku: string, track_stock: boolean}>} The created article. * * @example * const article = await store.article.createUnderParent({ googleAuthId: 42, parentId: 5, name: 'Cola' }); * // => { id, parentId, name, sku, track_stock } */ return async ({ googleAuthId, parentId, name, track_stock, trackStock }, tx) => { const rawTrack = track_stock ?? trackStock; const finalTrackStock = rawTrack == null ? 1 : (rawTrack ? 1 : 0); const runCreate = async (runner) => { const { companyId, languageId, companyuserId } = await access( googleAuthId, parentId, runner, ); const unitId = await ensureUnit(runner, languageId, companyId); const sku = await allocateSku(companyId, runner); const slug = slugify(name); let article; try { article = await runner.query(createArticleSql, { companyId, sku, unitId, unitamount: 1, weight: 0, trackStock: finalTrackStock, }); } catch (err) { if (isUniqueConstraintError(err)) { throw new Error(`SKU "${sku}" already exists`); } throw err; } const id = article.rows[0]?.id ?? article.insertId; await runner.query(addCategoryArticleSql, { categoryId: parentId, articleId: id, }); await runner.query(createArticleTextSql, { articleId: id, languageId, name, slug, }); await runner.query(insertHistorySql, { articleId: id, companyuserId, text: `Artikel "${name}" angelegt`, }); return { id, parentId, name, sku, track_stock: Boolean(finalTrackStock), }; }; if (tx) { return runCreate(makeRunner(provider, tx)); } if (typeof provider?.transaction === 'function') { return provider.transaction(runCreate); } return runCreate(makeRunner(provider)); }; }