Files
dashlibstorage/src/providers/mssql/queries/article.js
2026-09-26 23:06:05 +02:00

492 lines
14 KiB
JavaScript

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 AND (@companyId IS NULL OR a.company_id = @companyId)
`;
/** Resolve an article id by sku (used to wire father/child compound links). */
export const GET_ID_BY_SKU = `
SELECT TOP 1 id AS articleId
FROM article
WHERE sku = @sku AND (@companyId IS NULL OR company_id = @companyId)
`;
/** True if an EAN is already assigned to any article (duplicate guard). */
export const EAN_EXISTS = `
SELECT TOP 1 1 AS used
FROM articleean
WHERE ean = @ean
`;
/** Link an article to its father article and mark the father. */
export const UPDATE_FATHER_BY_SKU = `
UPDATE article
SET fatherarticle_id = @fatherArticleId,
fathersort = COALESCE(@fathersort, 0)
WHERE sku = @sku AND (@companyId IS NULL OR company_id = @companyId)
`;
export const SET_IS_FATHER = `
UPDATE article
SET is_father = 1
WHERE id = @articleId
`;
export const SET_FATHER_SORT = `
UPDATE article
SET fathersort = @fathersort
WHERE id = @articleId AND fatherarticle_id = @fatherArticleId
`;
/** SKU → article/category + company auth in one round-trip. */
export const RESOLVE_ARTICLE_ACCESS_BY_SKU = `
SELECT TOP 1
a.id AS articleId,
ca.category_id AS categoryId,
co.root_category_id AS rootCategoryId,
co.id AS companyId,
co.default_language_id AS languageId,
co.poscustomergroup_id AS posCustomerGroupId,
cu.id AS companyuserId
FROM article a
INNER JOIN company co ON co.id = a.company_id
INNER JOIN google_auth ga ON ga.id = @googleAuthId
INNER JOIN companyuser cu
ON cu.company_id = a.company_id AND cu.google_auth_id = @googleAuthId
LEFT JOIN categoryarticle ca ON ca.article_id = a.id
WHERE a.sku = @sku
AND (ga.selected_company IS NULL OR a.company_id = ga.selected_company)
`;
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 (company_id, sku, unit_id, unitamount, weight)
OUTPUT INSERTED.id
VALUES (@companyId, @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 auth AS (
SELECT TOP 1
a.id AS articleId,
ca.category_id AS categoryId,
co.root_category_id AS rootCategoryId,
co.id AS companyId,
co.default_language_id AS languageId,
co.poscustomergroup_id AS posCustomerGroupId,
cu.id AS companyuserId
FROM article a
INNER JOIN company co ON co.id = a.company_id
INNER JOIN google_auth ga ON ga.id = @googleAuthId
INNER JOIN companyuser cu
ON cu.company_id = a.company_id AND cu.google_auth_id = @googleAuthId
LEFT JOIN categoryarticle ca ON ca.article_id = a.id
WHERE a.sku = @sku
AND (ga.selected_company IS NULL OR a.company_id = ga.selected_company)
)
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,
(
SELECT
asup.id,
asup.article_id AS articleId,
asup.entity_id AS entityId,
e.name AS supplierName,
asup.sku,
asup.pu,
asup.stock,
asup.sort,
asup.price_id AS priceId,
p.net AS [price.net],
p.tax_id AS [price.taxId],
t.rate AS [price.taxRate]
FROM articlesupplier asup
INNER JOIN entity e ON e.id = asup.entity_id
LEFT JOIN price p ON p.id = asup.price_id
LEFT JOIN tax t ON t.id = p.tax_id
WHERE asup.article_id = a.id
ORDER BY asup.sort ASC, asup.id ASC
FOR JSON PATH
) AS suppliersJson,
(
SELECT
w.id,
w.name,
COALESCE(stock_calc.stock, 0) AS stock
FROM warehouse w
LEFT JOIN (
SELECT l.warehouse_id, SUM(l.amount) AS stock
FROM ledger l
INNER JOIN manifestarticle ma ON ma.id = l.manifestarticle_id
INNER JOIN manifest m ON m.id = ma.manifest_id
WHERE m.company_id = a.company_id
AND (
ma.sku = a.sku
OR ma.sku IN (SELECT asup.sku FROM articlesupplier asup WHERE asup.article_id = a.id)
)
GROUP BY l.warehouse_id
) stock_calc ON stock_calc.warehouse_id = w.id
WHERE w.company_id = a.company_id
ORDER BY w.name ASC
FOR JSON PATH
) AS warehousesJson
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
`;