Files
dashlibstorage/src/store/article/setFatherBySku.js
2026-10-01 17:40:04 +02:00

158 lines
5.5 KiB
JavaScript

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 { INSERT as MSSQL_INSERT_HISTORY } from '../../providers/mssql/queries/articlehistory.js';
import { INSERT as SQLITE_INSERT_HISTORY } from '../../providers/sqlite3/queries/articlehistory.js';
import queryBySku from './queryBySku.js';
import resolveArticleBySku from './resolveArticleBySku.js';
import makeRunner from '../runner.js';
export default function setFatherBySku(provider) {
const resolve = resolveArticleBySku(provider);
const load = queryBySku(provider);
const isSqlite = provider?.dialect === 'sqlite3';
const queries = isSqlite ? sqliteArticle : mssqlArticle;
const getChildCountSql = isSqlite ? SQLITE_GET_CHILD_COUNT : MSSQL_GET_CHILD_COUNT;
const insertHistorySql = isSqlite ? SQLITE_INSERT_HISTORY : MSSQL_INSERT_HISTORY;
/**
* Links an article to a father article (V/K compound) by their SKUs.
*
* @param {number} googleAuthId - The id of the Google auth user.
* @param {string} sku - The child article SKU.
* @param {string|null} fatherSku - The father article SKU, or `null` to unlink.
* @param {object} [tx] - Optional transaction to run within.
* @returns {Promise<object>} The updated child article.
* @throws {Error} If the article or father is not found, or the link is invalid.
*
* @example
* const article = await store.article.setFatherBySku(42, '42001190-1', '42001190');
* // => { id, sku, name, fatherSku: '42001190', ... }
*/
return async (googleAuthId, sku, fatherSku, tx) => {
const runSet = async (runner) => {
const { articleId, languageId, companyId, companyuserId } = await resolve(googleAuthId, sku, runner);
const childTextRes = await runner.query(
'SELECT name FROM articletext WHERE article_id = @articleId AND language_id = @languageId',
{ articleId, languageId },
);
const childName = childTextRes.rows[0]?.name || sku;
if (fatherSku == null || fatherSku === '') {
const prevFatherRes = await runner.query(
'SELECT fatherarticle_id FROM article WHERE id = @articleId',
{ articleId },
);
const prevFatherId = prevFatherRes.rows[0]?.fatherarticle_id;
await runner.query(queries.UPDATE_FATHER_BY_SKU, {
sku,
companyId,
fatherArticleId: null,
});
if (prevFatherId) {
const prevFatherTextRes = await runner.query(
'SELECT sku FROM article WHERE id = @prevFatherId',
{ prevFatherId },
);
const prevFatherSku = prevFatherTextRes.rows[0]?.sku || String(prevFatherId);
await runner.query(insertHistorySql, {
articleId,
companyuserId,
text: `Artikel "${sku}" von Vaterartikel "${prevFatherSku}" getrennt`,
});
await runner.query(insertHistorySql, {
articleId: prevFatherId,
companyuserId,
text: `Variante "${childName}" (${sku}) getrennt`,
});
}
const unlinked = await load(articleId, languageId, runner);
if (!unlinked) {
throw new Error('Article not found');
}
return unlinked;
}
const father = await runner.query(
'SELECT id, is_father, sku FROM article WHERE sku = @sku AND (@companyId IS NULL OR company_id = @companyId)',
{ sku: fatherSku, companyId },
);
const fatherRow = father.rows[0];
const fatherId = fatherRow?.id;
if (!fatherId) {
throw new Error('Father not found');
}
if (fatherId === articleId) {
throw new Error('Invalid father');
}
const wasFather = Boolean(fatherRow.is_father);
const existingSortsRes = await runner.query(
'SELECT fathersort FROM article WHERE fatherarticle_id = @fatherId ORDER BY fathersort ASC',
{ fatherId },
);
const usedSorts = new Set(existingSortsRes.rows.map((r) => Number(r.fathersort)));
let fathersort = 0;
while (usedSorts.has(fathersort)) {
fathersort++;
}
await runner.query(queries.UPDATE_FATHER_BY_SKU, {
sku,
companyId,
fatherArticleId: fatherId,
fathersort,
});
await runner.query(queries.SET_IS_FATHER, {
articleId: fatherId,
});
if (!wasFather) {
await runner.query(insertHistorySql, {
articleId: fatherId,
companyuserId,
text: 'Artikel zu Vaterartikel konvertiert',
});
}
await runner.query(insertHistorySql, {
articleId: fatherId,
companyuserId,
text: `Variante "${childName}" (${sku}) hinzugefügt`,
});
await runner.query(insertHistorySql, {
articleId,
companyuserId,
text: `Artikel "${sku}" als Variante von "${fatherSku}" zugewiesen`,
});
const article = await load(articleId, languageId, runner);
if (!article) {
throw new Error('Article not found');
}
return article;
};
if (tx) {
return runSet(makeRunner(provider, tx));
}
if (typeof provider?.transaction === 'function') {
return provider.transaction(runSet);
}
return runSet(makeRunner(provider));
};
}