This commit is contained in:
seb
2026-06-29 19:42:04 +02:00
parent 3bff749b49
commit b320887508
2 changed files with 51 additions and 27 deletions

View File

@@ -13,7 +13,7 @@ export function register(app, basePath = '') {
* @query {string} [filter] - Optional comma-separated category filter IDs (empty = all)
* @query {number} [offset=0] - Number of results to skip
* @query {number} [maxCount=10] - Maximum number of results to return
* @returns {Object} 200 - `{ katagg, length, recordset }`
* @returns {Object} 200 - `{ categories, length, recordset }`
* @returns {Object} 400 - `{ error }` when target is missing
*/
app.get(`${basePath}/article/search`, async (req, res) => {

View File

@@ -1,9 +1,9 @@
import { getPool } from '../../db/mssqlClient.js';
import { LOAD_KAT_MAP } from '../../db/mssql/categories.js';
import { LOAD_CATEGORIES } from '../../db/mssql/categories.js';
import * as Q from '../../db/mssql/searchArticles.js';
import { bruttoFromNetto, loadSteuersatz } from '../misc/getSteuer.js';
let katMapCache;
let categoryCache;
export function parseFilter(raw) {
if (raw === undefined || raw === null || raw === '') {
@@ -13,47 +13,68 @@ export function parseFilter(raw) {
return parts.length ? parts : [''];
}
function getUpPath(kat, katMap) {
function getUpPath(kat, parentMap) {
const list = [kat];
if (katMap[kat]) {
for (const item of getUpPath(katMap[kat], katMap)) {
if (parentMap[kat]) {
for (const item of getUpPath(parentMap[kat], parentMap)) {
list.push(item);
}
}
return list;
}
async function loadKatMap(pool) {
if (katMapCache) {
return katMapCache;
async function loadCategoryCache(pool) {
if (categoryCache) {
return categoryCache;
}
const result = await pool.request().query(LOAD_KAT_MAP);
katMapCache = {};
const result = await pool.request().query(LOAD_CATEGORIES);
const byId = {};
const parentMap = {};
for (const item of result.recordset) {
katMapCache[item.kKategorie] = item.kOberKategorie;
byId[item.kKategorie] = {
name: item.cName ?? null,
parent: item.kOberKategorie,
};
parentMap[item.kKategorie] = item.kOberKategorie;
}
return katMapCache;
categoryCache = { byId, parentMap };
return categoryCache;
}
function buildKatAgg(recordset, katMap) {
const katagg = {};
function buildKatAgg(recordset, parentMap) {
const counts = {};
for (const item of recordset) {
if (!item.katList) {
continue;
}
for (const kat of item.katList.split(',')) {
for (const katpart of getUpPath(kat, katMap)) {
if (!katagg[katpart]) {
katagg[katpart] = 0;
for (const katpart of getUpPath(kat, parentMap)) {
if (!counts[katpart]) {
counts[katpart] = 0;
}
katagg[katpart]++;
counts[katpart]++;
}
}
}
return katagg;
return counts;
}
function shapeCategories(counts, byId) {
const categories = {};
for (const [id, count] of Object.entries(counts)) {
const meta = byId[id] ?? {};
categories[id] = {
count,
name: meta.name ?? null,
parent: meta.parent ?? null,
};
}
return categories;
}
function shapeArticle(row, steuersaetze) {
@@ -61,7 +82,7 @@ function shapeArticle(row, steuersaetze) {
const brutto = bruttoFromNetto(row.fVKNEtto, row.kSteuerklasse, steuersaetze);
return {
katList: row.katList,
categories: row.katList,
available: row.fVerfuegbar,
id: row.kArtikel,
stock: row.fBestand,
@@ -140,7 +161,7 @@ function buildQuery(filter, categoryFilter) {
export async function searchArticles(target, filter = [''], offset = 0, maxCount = 10) {
const trimmed = target?.toString().trim();
if (!trimmed) {
return { katagg: {}, length: 0, recordset: [] };
return { categories: {}, length: 0, recordset: [] };
}
const start = Math.max(0, Number(offset) || 0);
@@ -159,17 +180,20 @@ export async function searchArticles(target, filter = [''], offset = 0, maxCount
}
const result = await request.query(sql);
const [katMap, steuersaetze] = await Promise.all([
loadKatMap(pool),
const [categoryData, steuersaetze] = await Promise.all([
loadCategoryCache(pool),
loadSteuersatz(),
]);
const katagg = buildKatAgg(result.recordset, katMap);
const categories = shapeCategories(
buildKatAgg(result.recordset, categoryData.parentMap),
categoryData.byId
);
const length = result.recordset.length;
const recordset = result.recordset
.slice(start, start + count)
.map((row) => shapeArticle(row, steuersaetze));
console.dir({ katagg, length, recordset }, { depth: null });
console.dir({ categories, length, recordset }, { depth: null });
return { katagg, length, recordset };
return { categories, length, recordset };
}