export const ARTICLE_LIST_JOINS = ` LEFT JOIN articletext at ON at.article_id = a.id AND at.language_id = @languageId LEFT JOIN price pr ON pr.article_id = a.id AND pr.customergroup_id = @posCustomerGroupId AND pr.minmultiplier = 1 LEFT JOIN tax t ON t.id = pr.tax_id OUTER APPLY ( SELECT TOP 1 ap.pic_id FROM articlepic ap WHERE ap.article_id = a.id ORDER BY ap.sort ASC, ap.id ASC ) first_pic LEFT JOIN pic ON pic.id = first_pic.pic_id LEFT JOIN article father ON father.id = a.fatherarticle_id `; export const ARTICLE_LIST_COLUMNS = ` a.id, a.sku, at.name, at.slug, pr.net, t.rate AS taxRate, CASE WHEN a.optionslist_id IS NOT NULL THEN ( SELECT COUNT(*) FROM optionslistarticle ola WHERE ola.optionslist_id = a.optionslist_id ) ELSE 0 END AS optionsCount, CASE WHEN a.articlelist_id IS NOT NULL THEN ( SELECT COUNT(*) FROM articlelistarticle ala WHERE ala.articlelist_id = a.articlelist_id ) ELSE 0 END AS articleListCount, ( SELECT COUNT(*) FROM article child WHERE child.fatherarticle_id = a.id ) AS childCount, a.fatherarticle_id AS fatherArticleId, father.sku AS fatherSku, pic.hash AS fullHash, pic.thumbw AS thumbW, pic.thumbh AS thumbH, pic.thumbhash AS thumbHash `; export const GET_CATEGORY_ID_BY_SKU = ` SELECT TOP 1 ca.category_id AS categoryId, a.id AS articleId FROM article a INNER JOIN categoryarticle ca ON ca.article_id = a.id WHERE a.sku = @sku `; /** SKU → article/category + company auth in one round-trip. */ export const RESOLVE_ARTICLE_ACCESS_BY_SKU = ` WITH article_cat AS ( SELECT TOP 1 a.id AS articleId, ca.category_id AS categoryId FROM article a INNER JOIN categoryarticle ca ON ca.article_id = a.id WHERE a.sku = @sku ), ancestors AS ( SELECT c.id, c.parent_id FROM category c INNER JOIN article_cat ac ON c.id = ac.categoryId UNION ALL SELECT c.id, c.parent_id FROM category c INNER JOIN ancestors a ON c.id = a.parent_id ), root AS ( SELECT TOP 1 id AS rootCategoryId FROM ancestors WHERE parent_id IS NULL ) SELECT ac.articleId, ac.categoryId, r.rootCategoryId, co.id AS companyId, co.default_language_id AS languageId, co.poscustomergroup_id AS posCustomerGroupId, cu.id AS companyuserId FROM article_cat ac LEFT JOIN root r ON 1 = 1 LEFT JOIN company co ON co.root_category_id = r.rootCategoryId LEFT JOIN companyuser cu ON cu.company_id = co.id AND cu.google_auth_id = @googleAuthId `; export const UPDATE_WEIGHT = ` UPDATE article SET weight = @weight WHERE id = @articleId `; export const UPDATE_BRAND = ` UPDATE article SET brand_id = @brandId WHERE id = @articleId `; export const UPDATE_UNIT = ` UPDATE article SET unit_id = @unitId WHERE id = @articleId `; export const UPDATE_UNITAMOUNT = ` UPDATE article SET unitamount = @unitamount WHERE id = @articleId `; export const UPDATE_UNIT_AND_AMOUNT = ` UPDATE article SET unit_id = @unitId, unitamount = @unitamount WHERE id = @articleId `; export const CREATE = ` INSERT INTO article (sku, unit_id, unitamount, weight) OUTPUT INSERTED.id VALUES (@sku, @unitId, @unitamount, @weight) `; export const DELETE_EANS_BY_ARTICLE = ` DELETE FROM articleean WHERE article_id = @articleId `; export const ADD_EAN = ` INSERT INTO articleean (article_id, ean) VALUES (@articleId, @ean) `; export const DELETE_CATEGORIES_BY_ARTICLE = ` DELETE FROM categoryarticle WHERE article_id = @articleId `; export const ADD_CATEGORY = ` INSERT INTO categoryarticle (category_id, article_id) VALUES (@categoryId, @articleId) `; export const GET_BRAND_BY_COMPANY_AND_ID = ` SELECT id FROM brand WHERE id = @brandId AND company_id = @companyId `; /** * Company-wide article search index. * Returns one row per article with id, sku, name, and all eans as a JSON array. * Used by the client for local search / autocomplete. */ export const SEARCH_ARTICLES = ` ;WITH category_tree AS ( SELECT id FROM category WHERE id = @rootCategoryId UNION ALL SELECT c.id FROM category c INNER JOIN category_tree ct ON c.parent_id = ct.id ) SELECT a.id, a.sku, at.name, ( SELECT ae.ean FROM articleean ae WHERE ae.article_id = a.id ORDER BY ae.ean FOR JSON PATH ) AS eansJson, ( SELECT ca2.category_id FROM categoryarticle ca2 WHERE ca2.article_id = a.id ORDER BY ca2.category_id FOR JSON PATH ) AS categoryIdsJson FROM article a LEFT JOIN articletext at ON at.article_id = a.id AND at.language_id = @languageId WHERE EXISTS ( SELECT 1 FROM categoryarticle ca INNER JOIN category_tree ct ON ct.id = ca.category_id WHERE ca.article_id = a.id ) ORDER BY a.id `; /** * Flat category tree (id, parentId, name) for a root category, used to resolve * breadcrumbs for the article export. */ export const GET_CATEGORY_TREE_FLAT = ` ;WITH tree AS ( SELECT id, parent_id, sort FROM category WHERE id = @rootId UNION ALL SELECT c.id, c.parent_id, c.sort FROM category c INNER JOIN tree t ON c.parent_id = t.id ) SELECT t.id, t.parent_id AS parentId, ct.name FROM tree t LEFT JOIN categorytext ct ON ct.category_id = t.id AND ct.language_id = @languageId `; /** * Export rows for every article in a category subtree (root = @categoryId). * One row per article with the columns used by the export CSV, including the * POS price (minmultiplier = 1 for the company poscustomergroup), brand, unit, * eans, categoryIds and all photo hashes as JSON arrays. */ export const GET_ARTICLE_EXPORT = ` ;WITH category_tree AS ( SELECT id FROM category WHERE id = @categoryId UNION ALL SELECT c.id FROM category c INNER JOIN category_tree ct ON c.parent_id = ct.id ) SELECT a.id, a.sku, at.name, at.slug, u.si AS unitSi, ut.symbol AS unitSymbol, a.unitamount, b.name AS brandName, b.name AS brandName, pr.net AS net, t.rate AS taxRate, ( SELECT ae.ean FROM articleean ae WHERE ae.article_id = a.id ORDER BY ae.ean FOR JSON PATH ) AS eansJson, ( SELECT ca2.category_id FROM categoryarticle ca2 WHERE ca2.article_id = a.id ORDER BY ca2.category_id FOR JSON PATH ) AS categoryIdsJson, ( SELECT p.hash FROM articlepic ap INNER JOIN pic p ON p.id = ap.pic_id WHERE ap.article_id = a.id ORDER BY ap.sort ASC, ap.id ASC FOR JSON PATH ) AS fullHashesJson FROM article a INNER JOIN categoryarticle ca ON ca.article_id = a.id INNER JOIN category_tree ct ON ct.id = ca.category_id LEFT JOIN articletext at ON at.article_id = a.id AND at.language_id = @languageId LEFT JOIN unit u ON u.id = a.unit_id LEFT JOIN unittext ut ON ut.unit_id = u.id AND ut.language_id = @languageId LEFT JOIN brand b ON b.id = a.brand_id LEFT JOIN price pr ON pr.article_id = a.id AND pr.customergroup_id = @posCustomerGroupId AND pr.minmultiplier = 1 LEFT JOIN tax t ON t.id = pr.tax_id ORDER BY a.id `; /** * Single-query replacement for resolveArticleBySku + queryBySku. * Resolves SKU → article + company + auth, then loads full article detail * including categories, photos, eans, and prices via FOR JSON sub-queries. * Returns one row with articleJson, or empty if not found/unauthorized. */ export const GET_ARTICLE_BY_SKU_FULL = ` ;WITH article_cat AS ( SELECT TOP 1 a.id AS articleId, ca.category_id AS categoryId FROM article a INNER JOIN categoryarticle ca ON ca.article_id = a.id WHERE a.sku = @sku ), ancestors AS ( SELECT c.id, c.parent_id FROM category c INNER JOIN article_cat ac ON c.id = ac.categoryId UNION ALL SELECT c.id, c.parent_id FROM category c INNER JOIN ancestors a ON c.id = a.parent_id ), root AS ( SELECT TOP 1 id AS rootCategoryId FROM ancestors WHERE parent_id IS NULL ), auth AS ( SELECT ac.articleId, ac.categoryId, r.rootCategoryId, co.id AS companyId, co.default_language_id AS languageId, co.poscustomergroup_id AS posCustomerGroupId, cu.id AS companyuserId FROM article_cat ac LEFT JOIN root r ON 1 = 1 LEFT JOIN company co ON co.root_category_id = r.rootCategoryId LEFT JOIN companyuser cu ON cu.company_id = co.id AND cu.google_auth_id = @googleAuthId ) SELECT auth.articleId, auth.categoryId, auth.rootCategoryId, auth.companyId, auth.languageId, auth.posCustomerGroupId, auth.companyuserId, ( SELECT a.id, a.sku, at.name, at.slug, a.unitamount, a.weight, u.si AS unitSi, u.basesi AS unitBasesi, u.basesifactor AS unitBasesifactor, ut.symbol AS unitSymbol, ut.name AS unitName, b.name AS brandName, bp.thumbw AS brandThumbW, bp.thumbh AS brandThumbH, bp.thumbhash AS brandThumbHash, ( SELECT COUNT(*) FROM optionslistarticle ola WHERE ola.optionslist_id = a.optionslist_id ) AS optionsCount, ( SELECT COUNT(*) FROM articlelistarticle ala WHERE ala.articlelist_id = a.articlelist_id ) AS articleListCount, ( SELECT COUNT(*) FROM article child WHERE child.fatherarticle_id = a.id ) AS childCount, a.fatherarticle_id AS fatherArticleId, fa.sku AS fatherSku, ( SELECT ca2.category_id FROM categoryarticle ca2 WHERE ca2.article_id = a.id ORDER BY ca2.category_id FOR JSON PATH ) AS categoryIdsJson, ( SELECT ap.sort, p.hash AS fullHash, p.w AS fullW, p.h AS fullH, p.size AS fullSize, p.thumbw AS thumbW, p.thumbh AS thumbH, p.thumbhash AS thumbHash FROM articlepic ap INNER JOIN pic p ON p.id = ap.pic_id WHERE ap.article_id = a.id ORDER BY ap.sort ASC, ap.id ASC FOR JSON PATH ) AS photosJson, ( SELECT ae.ean FROM articleean ae WHERE ae.article_id = a.id ORDER BY ae.ean FOR JSON PATH ) AS eansJson, ( SELECT pr.minmultiplier, pr.net, t.rate AS taxRate, pr.customergroup_id AS customergroupId FROM price pr INNER JOIN tax t ON t.id = pr.tax_id WHERE pr.article_id = a.id ORDER BY pr.customergroup_id, pr.minmultiplier FOR JSON PATH ) AS pricesJson FROM article a LEFT JOIN articletext at ON at.article_id = a.id AND at.language_id = auth.languageId LEFT JOIN unit u ON u.id = a.unit_id LEFT JOIN unittext ut ON ut.unit_id = u.id AND ut.language_id = auth.languageId LEFT JOIN brand b ON b.id = a.brand_id OUTER APPLY ( SELECT TOP 1 bp2.pic_id FROM brandpic bp2 WHERE bp2.brand_id = b.id ORDER BY bp2.sort ASC, bp2.id ASC ) first_brand_pic LEFT JOIN pic bp ON bp.id = first_brand_pic.pic_id LEFT JOIN article fa ON fa.id = a.fatherarticle_id WHERE a.id = auth.articleId FOR JSON PATH, WITHOUT_ARRAY_WRAPPER ) AS articleJson FROM auth `;