Genesis
This commit is contained in:
151
src/queries/product-list.js
Normal file
151
src/queries/product-list.js
Normal file
@@ -0,0 +1,151 @@
|
||||
import sql from 'mssql';
|
||||
import { getPool } from '../db.js';
|
||||
import { getCustomerGroupIds } from './customer-groups.js';
|
||||
import { getProductAttributes } from './product-attributes.js';
|
||||
|
||||
const LANGUAGE_ID = Number(process.env.LANGUAGE_ID) || 1;
|
||||
const TAX_ZONE_NAME = process.env.TAX_ZONE_NAME || 'Zone-EU';
|
||||
const IMAGE_PLATFORM_ID = Number(process.env.IMAGE_PLATFORM_ID) || 1;
|
||||
const IMAGE_SHOP_ID = Number(process.env.IMAGE_SHOP_ID) || 0;
|
||||
|
||||
const PRODUCT_LIST_SQL = `
|
||||
WITH TaxRates AS (
|
||||
SELECT kSteuerklasse, fSteuersatz
|
||||
FROM dbo.tSteuersatz
|
||||
WHERE kSteuerzone IN (SELECT kSteuerzone FROM dbo.tSteuerzone WHERE cName = @taxZoneName)
|
||||
)
|
||||
SELECT TOP (@limit)
|
||||
a.kArtikel AS id,
|
||||
a.cArtNr AS sku,
|
||||
ab.cName AS name,
|
||||
a.fVKNetto AS netPrice,
|
||||
tr.fSteuersatz AS taxRate,
|
||||
a.dErstelldatum AS createdAt,
|
||||
CONVERT(BIGINT, a.bRowversion) AS lastChanged,
|
||||
(
|
||||
SELECT TOP 1 img.cHash
|
||||
FROM dbo.tArtikelbildPlattform abp
|
||||
INNER JOIN dbo.tBild img ON img.kBild = abp.kBild
|
||||
WHERE abp.kArtikel = a.kArtikel
|
||||
AND abp.kPlattform = @imagePlatformId
|
||||
AND abp.kShop = @imageShopId
|
||||
ORDER BY abp.nNr
|
||||
) AS imgHash,
|
||||
(
|
||||
SELECT STRING_AGG(CAST(ka.kKategorie AS varchar(20)), ',')
|
||||
FROM dbo.tkategorieartikel ka
|
||||
WHERE ka.kArtikel = a.kArtikel
|
||||
) AS categoryIds,
|
||||
a.nIstVater AS isParent,
|
||||
a.kVaterArtikel AS parentArticleId,
|
||||
(
|
||||
SELECT TOP 1 pv.cVariantName
|
||||
FROM Pos.vProductVariant pv
|
||||
WHERE pv.kProduct = a.kArtikel
|
||||
) AS variantName
|
||||
FROM dbo.tArtikel a
|
||||
INNER JOIN dbo.tArtikelBeschreibung ab ON ab.kArtikel = a.kArtikel AND ab.kSprache = @languageId
|
||||
LEFT JOIN TaxRates tr ON tr.kSteuerklasse = a.kSteuerklasse
|
||||
WHERE a.cAktiv = 'Y'
|
||||
AND CONVERT(BIGINT, a.bRowversion) > @cursor
|
||||
ORDER BY lastChanged ASC;
|
||||
`;
|
||||
|
||||
function priceOverridesSql(articleIds) {
|
||||
const idList = articleIds.join(',');
|
||||
return `
|
||||
SELECT p.kArtikel AS articleId, p.kKundenGruppe AS customerGroupId, MIN(pd.fNettoPreis) AS netPrice
|
||||
FROM dbo.tPreis p
|
||||
INNER JOIN dbo.tPreisDetail pd ON pd.kPreis = p.kPreis
|
||||
WHERE p.kArtikel IN (${idList}) AND p.kShop = 0 AND pd.nAnzahlAb = 0
|
||||
GROUP BY p.kArtikel, p.kKundenGruppe;
|
||||
`;
|
||||
}
|
||||
|
||||
function formatDateTime(date) {
|
||||
if (!date) {
|
||||
return '0001-01-01 00:00:00';
|
||||
}
|
||||
const pad = (n) => String(n).padStart(2, '0');
|
||||
return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())} ${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}`;
|
||||
}
|
||||
|
||||
function grossPrice(netPrice, taxRate) {
|
||||
return (Number(netPrice) * (1 + Number(taxRate || 0) / 100)).toFixed(2);
|
||||
}
|
||||
|
||||
export async function getProductList({ cursor = 0, limit = 20 } = {}) {
|
||||
const pool = getPool();
|
||||
|
||||
const [productResult, customerGroupIds] = await Promise.all([
|
||||
pool
|
||||
.request()
|
||||
.input('cursor', sql.BigInt, cursor)
|
||||
.input('limit', sql.Int, limit)
|
||||
.input('languageId', sql.Int, LANGUAGE_ID)
|
||||
.input('taxZoneName', sql.NVarChar, TAX_ZONE_NAME)
|
||||
.input('imagePlatformId', sql.Int, IMAGE_PLATFORM_ID)
|
||||
.input('imageShopId', sql.Int, IMAGE_SHOP_ID)
|
||||
.query(PRODUCT_LIST_SQL),
|
||||
getCustomerGroupIds(),
|
||||
]);
|
||||
|
||||
const products = productResult.recordset;
|
||||
const articleIds = products.map((p) => p.id);
|
||||
|
||||
const overridesByArticle = new Map();
|
||||
let attributesByArticle = new Map();
|
||||
if (articleIds.length > 0) {
|
||||
const [overrideResult, attributeMap] = await Promise.all([
|
||||
pool.request().query(priceOverridesSql(articleIds)),
|
||||
getProductAttributes(pool, articleIds),
|
||||
]);
|
||||
attributesByArticle = attributeMap;
|
||||
for (const row of overrideResult.recordset) {
|
||||
if (!overridesByArticle.has(row.articleId)) {
|
||||
overridesByArticle.set(row.articleId, new Map());
|
||||
}
|
||||
overridesByArticle.get(row.articleId).set(row.customerGroupId, row.netPrice);
|
||||
}
|
||||
}
|
||||
|
||||
return products.map((product) => {
|
||||
const overrides = overridesByArticle.get(product.id);
|
||||
const basePrice = grossPrice(product.netPrice, product.taxRate);
|
||||
|
||||
const prices = customerGroupIds.map((customerGroupId) => {
|
||||
const overrideNetPrice = overrides?.get(customerGroupId);
|
||||
const price =
|
||||
overrideNetPrice !== undefined ? grossPrice(overrideNetPrice, product.taxRate) : basePrice;
|
||||
return {
|
||||
customerGroupId: String(customerGroupId),
|
||||
customerId: '0',
|
||||
price,
|
||||
quantity: '0',
|
||||
};
|
||||
});
|
||||
|
||||
const categoryIds = product.categoryIds ? product.categoryIds.split(',') : [];
|
||||
const articleAttributes = attributesByArticle.get(product.id);
|
||||
|
||||
return {
|
||||
_id: String(product.id),
|
||||
imghash: product.imgHash ?? null,
|
||||
imgsrc: product.imgHash ?? null,
|
||||
sku: product.sku,
|
||||
name: product.name,
|
||||
tax_rate: String(Math.round(Number(product.taxRate || 0))),
|
||||
price: basePrice,
|
||||
created_at: formatDateTime(product.createdAt),
|
||||
lastChanged: String(product.lastChanged),
|
||||
categories_id: categoryIds[0] ?? '0',
|
||||
categories: categoryIds.map((categoryId) => ({ categoryId })),
|
||||
prices,
|
||||
is_parent: product.isParent ? '1' : '0',
|
||||
parent: product.parentArticleId > 0 ? String(product.parentArticleId) : '0',
|
||||
variants: product.variantName ?? '',
|
||||
attributes: articleAttributes?.attributes ?? [],
|
||||
...(articleAttributes?.deposit ?? {}),
|
||||
};
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user