139 lines
5.9 KiB
JavaScript
139 lines
5.9 KiB
JavaScript
import { GET_ARTICLE_BY_SKU_FULL as MSSQL_QUERY } from '../../providers/mssql/queries/article.js';
|
|
import { GET_ARTICLE_BY_SKU_FULL as SQLITE_QUERY } from '../../providers/sqlite3/queries/article.js';
|
|
import makeRunner from '../runner.js';
|
|
|
|
function parseJsonArray(raw) {
|
|
if (!raw) return [];
|
|
const arr = typeof raw === 'string' ? JSON.parse(raw) : raw;
|
|
return Array.isArray(arr) ? arr : [];
|
|
}
|
|
|
|
export default function getBySku(provider) {
|
|
const sql = provider?.dialect === 'sqlite3' ? SQLITE_QUERY : MSSQL_QUERY;
|
|
|
|
/**
|
|
* Returns the full detail of an article by its SKU, including unit, brand,
|
|
* categories, photos, EANs and prices.
|
|
*
|
|
* @param {number} googleAuthId - The id of the Google auth user.
|
|
* @param {string} sku - The article SKU.
|
|
* @param {object} [tx] - Optional transaction.
|
|
* @returns {Promise<{article: {id: number, sku: string, name: string, slug: string, unitamount: number|null, weight: number|null, track_stock: boolean, unit: {si: string|null, basesi: string|null, basesifactor: number|null, symbol: string|null, name: string|null}, brand: {id: number|null, name: string, fullHash: string|null, thumbW: number|null, thumbH: number|null, thumbHash: string|null}|null, categoryIds: number[], photos: Array<{sort: number, fullHash: string, fullW: number, fullH: number, fullSize: number, thumbW: number, thumbH: number, thumbHash: string}>, eans: string[], prices: Array<{minmultiplier: number, net: number, taxRate: number, customergroupId: number}>, suppliers: Array<{id: number, articleId: number, entityId: number, supplierName: string|null, sku: string|null, pu: number, stock: number|null, sort: number, priceId: number|null, price: {net: number, taxId: number, taxRate?: number}|null}>, optionsCount: number, articleListCount: number, childCount: number, parentArticleId: number|null, parentSku: string|null}}>} The full article detail.
|
|
* @throws {Error} If the article is not found or the user is not authorized.
|
|
*
|
|
* @example
|
|
* const article = await store.article.getBySku(42, 'SKU-1');
|
|
* // => { article: { id, sku, name, unit, brand, categoryIds, photos, eans, prices, ... } }
|
|
*/
|
|
return async (googleAuthId, sku, tx) => {
|
|
const t0 = performance.now();
|
|
const runner = makeRunner(provider, tx);
|
|
const result = await runner.query(sql, { sku, googleAuthId });
|
|
console.log(`[getBySku] single query ${(performance.now() - t0).toFixed(1)}ms`);
|
|
|
|
const row = result.rows[0];
|
|
if (!row) {
|
|
throw new Error('Article not found');
|
|
}
|
|
if (!row.articleId || !row.categoryId) {
|
|
throw new Error('Article not found');
|
|
}
|
|
if (!row.companyId || !row.rootCategoryId || !row.languageId) {
|
|
throw new Error('Parent not found');
|
|
}
|
|
if (!row.companyuserId) {
|
|
throw new Error('Not authorized');
|
|
}
|
|
|
|
|
|
const a = typeof row.articleJson === 'string' ? JSON.parse(row.articleJson) : row.articleJson;
|
|
|
|
return {
|
|
article: {
|
|
id: a.id,
|
|
sku: a.sku,
|
|
name: a.name,
|
|
slug: a.slug,
|
|
unitamount: a.unitamount,
|
|
weight: a.weight,
|
|
track_stock: Boolean(a.track_stock ?? 1),
|
|
unit: {
|
|
si: a.unitSi,
|
|
basesi: a.unitBasesi,
|
|
basesifactor: a.unitBasesifactor,
|
|
symbol: a.unitSymbol ?? null,
|
|
name: a.unitName ?? null,
|
|
},
|
|
brand: a.brandName
|
|
? {
|
|
id: a.brandId ?? null,
|
|
name: a.brandName,
|
|
fullHash: a.brandFullHash ?? null,
|
|
thumbW: a.brandThumbW ?? null,
|
|
thumbH: a.brandThumbH ?? null,
|
|
thumbHash: a.brandThumbHash ?? null,
|
|
}
|
|
: null,
|
|
categoryIds: parseJsonArray(a.categoryIdsJson).map((r) => r.category_id),
|
|
photos: parseJsonArray(a.photosJson),
|
|
eans: parseJsonArray(a.eansJson).map((r) => r.ean),
|
|
prices: parseJsonArray(a.pricesJson),
|
|
suppliers: parseJsonArray(a.suppliersJson).map((s) => ({
|
|
id: s.id,
|
|
articleId: s.articleId,
|
|
entityId: s.entityId,
|
|
supplierName: s.supplierName,
|
|
sku: s.sku ?? null,
|
|
pu: s.pu,
|
|
stock: s.stock ?? null,
|
|
sort: s.sort,
|
|
priceId: s.priceId ?? null,
|
|
price: s.priceId != null && s.price?.net != null ? s.price : null,
|
|
})),
|
|
warehouses: parseJsonArray(a.warehousesJson).map((w) => ({
|
|
id: w.id,
|
|
name: w.name,
|
|
sort: Number(w.sort ?? 0),
|
|
stock: Number(w.stock ?? 0),
|
|
})),
|
|
optionsCount: a.optionsCount,
|
|
optionslistId: a.optionslistId ?? null,
|
|
options: parseJsonArray(a.optionslistItemsJson).map((o) => ({
|
|
id: o.id,
|
|
articleId: o.articleId,
|
|
sku: o.sku,
|
|
name: o.name ?? null,
|
|
count: Number(o.count ?? 1),
|
|
sort: Number(o.sort ?? 0),
|
|
mandated: Boolean(o.mandated),
|
|
})),
|
|
articleListCount: a.articleListCount,
|
|
articlelistId: a.articlelistId ?? null,
|
|
articlelist: parseJsonArray(a.articlelistItemsJson).map((item) => ({
|
|
id: item.id,
|
|
articleId: item.articleId,
|
|
sku: item.sku,
|
|
name: item.name ?? null,
|
|
count: Number(item.count ?? 1),
|
|
sort: Number(item.sort ?? 0),
|
|
})),
|
|
childCount: a.childCount,
|
|
isParent: Boolean(a.isParent),
|
|
parentAttributeNameId: a.parentAttributeNameId ?? null,
|
|
parentAttributeName: a.parentAttributeName ?? null,
|
|
parentAttributeExclusive: a.parentAttributeExclusive != null ? Boolean(a.parentAttributeExclusive) : null,
|
|
parentArticleId: a.parentArticleId,
|
|
parentSku: a.parentSku,
|
|
children: parseJsonArray(a.childrenJson).map((c) => ({
|
|
id: c.id,
|
|
sku: c.sku,
|
|
parentsort: c.parentsort,
|
|
name: c.name ?? null,
|
|
attributeValueId: c.attributeValueId ?? null,
|
|
attributeValue: c.attributeValue ?? null,
|
|
})),
|
|
},
|
|
};
|
|
};
|
|
}
|