140 lines
5.7 KiB
JavaScript
140 lines
5.7 KiB
JavaScript
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 resolveUniqueSlug from './resolveUniqueSlug.js';
|
|
|
|
export default function createUnderParent(provider) {
|
|
const access = resolveCategoryAccess(provider);
|
|
const ensureUnit = ensureDefaultUnit(provider);
|
|
const allocateSku = nextSku(provider);
|
|
const resolveSlug = resolveUniqueSlug(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 {string} [input.description] - The article description.
|
|
* @param {string} [input.desc] - Alias for description.
|
|
* @param {object|string} [input.seo] - The SEO configuration or JSON string.
|
|
* @param {string} [input.seoTitle] - The SEO title.
|
|
* @param {string} [input.seoDescription] - The SEO meta description.
|
|
* @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, description, desc, shortDescription, seo, seoTitle, seoDescription, track_stock, trackStock, sku: inputSku }, 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 = (typeof inputSku === 'string' && inputSku.trim()) ? inputSku.trim() : await allocateSku(companyId, runner);
|
|
const slug = await resolveSlug(runner, { companyId, languageId, 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,
|
|
});
|
|
|
|
const rawDesc = description !== undefined ? description : desc;
|
|
const finalDesc = rawDesc != null && rawDesc !== '' ? String(rawDesc) : null;
|
|
let finalSeo = null;
|
|
if (shortDescription !== undefined) {
|
|
finalSeo = shortDescription != null && shortDescription !== '' ? String(shortDescription) : null;
|
|
} else if (typeof seo === 'string') {
|
|
finalSeo = seo !== '' ? seo : null;
|
|
} else if (seoDescription && !seoTitle) {
|
|
finalSeo = String(seoDescription);
|
|
} else if (seo != null) {
|
|
finalSeo = typeof seo === 'string' ? seo : JSON.stringify(seo);
|
|
} else if (seoTitle || seoDescription) {
|
|
finalSeo = JSON.stringify({
|
|
title: seoTitle != null && seoTitle !== '' ? String(seoTitle) : '',
|
|
description: seoDescription != null && seoDescription !== '' ? String(seoDescription) : '',
|
|
});
|
|
}
|
|
|
|
await runner.query(createArticleTextSql, {
|
|
articleId: id,
|
|
languageId,
|
|
name,
|
|
slug,
|
|
desc: finalDesc,
|
|
seo: finalSeo,
|
|
});
|
|
|
|
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));
|
|
};
|
|
}
|
|
|