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, })), }, }; }; }