services
This commit is contained in:
20
src/api/routes/misc/getCategories.js
Normal file
20
src/api/routes/misc/getCategories.js
Normal file
@@ -0,0 +1,20 @@
|
||||
import { getCategories } from '../../../services/misc/getCategories.js';
|
||||
|
||||
/**
|
||||
* @param {import('express').Application} app
|
||||
* @param {string} [basePath='']
|
||||
*/
|
||||
export function register(app, basePath = '') {
|
||||
/**
|
||||
* @route GET /misc/getCategories
|
||||
* @returns {Object} 200 - `{ categories, tree }`
|
||||
*/
|
||||
app.get(`${basePath}/misc/getCategories`, async (_req, res) => {
|
||||
try {
|
||||
const result = await getCategories();
|
||||
res.status(200).json(result);
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: error.message });
|
||||
}
|
||||
});
|
||||
}
|
||||
19
src/api/routes/misc/getSteuer.js
Normal file
19
src/api/routes/misc/getSteuer.js
Normal file
@@ -0,0 +1,19 @@
|
||||
import { getSteuer } from '../../../services/misc/getSteuer.js';
|
||||
|
||||
/**
|
||||
* @param {import('express').Application} app
|
||||
* @param {string} [basePath='']
|
||||
*/
|
||||
export function register(app, basePath = '') {
|
||||
/**
|
||||
* @route GET /misc/getSteuer
|
||||
* @returns {Object} 200 - `{ steuerklassen }`
|
||||
*/
|
||||
app.get(`${basePath}/misc/getSteuer`, async (_req, res) => {
|
||||
try {
|
||||
res.status(200).json(await getSteuer());
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: error.message });
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -2,3 +2,27 @@ export const LOAD_KAT_MAP = `
|
||||
SELECT kKategorie, kOberKategorie
|
||||
FROM dbo.tkategorie
|
||||
`;
|
||||
|
||||
export const LOAD_CATEGORIES = `
|
||||
SELECT
|
||||
kKategorie,
|
||||
kOberKategorie,
|
||||
nSort,
|
||||
(
|
||||
SELECT cName
|
||||
FROM dbo.tKategorieSprache
|
||||
WHERE kSprache = 1
|
||||
AND kPlattform = 1
|
||||
AND kShop = 0
|
||||
AND dbo.tkategorie.kKategorie = dbo.tKategorieSprache.kKategorie
|
||||
) AS cName
|
||||
FROM dbo.tkategorie
|
||||
ORDER BY nSort, cName
|
||||
`;
|
||||
|
||||
export const CATEGORY_ARTICLE_COUNTS = `
|
||||
SELECT ka.kKategorie, COUNT(*) AS count
|
||||
FROM tkategorieartikel ka
|
||||
INNER JOIN tArtikel a ON a.kArtikel = ka.kArtikel AND a.cAktiv = 'Y'
|
||||
GROUP BY ka.kKategorie
|
||||
`;
|
||||
|
||||
11
src/db/mssql/steuer.js
Normal file
11
src/db/mssql/steuer.js
Normal file
@@ -0,0 +1,11 @@
|
||||
export const LOAD_STEUERKLASSEN = `
|
||||
SELECT
|
||||
sk.kSteuerklasse,
|
||||
sk.cName,
|
||||
sk.nStandard,
|
||||
sz.fSteuersatz
|
||||
FROM dbo.tSteuerklasse sk
|
||||
INNER JOIN dbo.tSteuersatz sz ON sz.kSteuerklasse = sk.kSteuerklasse
|
||||
WHERE sz.kSteuerzone = 1
|
||||
ORDER BY sk.kSteuerklasse
|
||||
`;
|
||||
@@ -1,7 +1,7 @@
|
||||
import env from '../../config/env.js';
|
||||
import { getPool } from '../../db/mssqlClient.js';
|
||||
import { getBrutto } from '../../utils/tax.js';
|
||||
import { enrichSupplierAnmerkungRow } from './enrichSupplier.js';
|
||||
import { bruttoFromNetto, loadSteuerklassen } from '../misc/steuerklassen.js';
|
||||
import * as Q from '../../db/mssql/getArticle.js';
|
||||
|
||||
async function query(pool, sql, inputs = {}) {
|
||||
@@ -71,9 +71,10 @@ async function loadAttributes(pool, kArtikel) {
|
||||
|
||||
async function loadStaffel(pool, kArtikel, kSteuerklasse) {
|
||||
const rows = await query(pool, Q.STAFFEL, { kArtikel });
|
||||
const steuerklassen = await loadSteuerklassen();
|
||||
return rows.map((item) => ({
|
||||
menge: item.nAnzahlAb.toString(),
|
||||
fVKBrutto: getBrutto(item.fNEttoPreis, kSteuerklasse).toFixed(2),
|
||||
fVKBrutto: bruttoFromNetto(item.fNEttoPreis, kSteuerklasse, steuerklassen)?.toFixed(2),
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
73
src/services/misc/getCategories.js
Normal file
73
src/services/misc/getCategories.js
Normal file
@@ -0,0 +1,73 @@
|
||||
import { getPool } from '../../db/mssqlClient.js';
|
||||
import {
|
||||
CATEGORY_ARTICLE_COUNTS,
|
||||
LOAD_CATEGORIES,
|
||||
} from '../../db/mssql/categories.js';
|
||||
|
||||
function sortCategories(list) {
|
||||
list.sort((a, b) => {
|
||||
const sortDiff = (a.nSort ?? 0) - (b.nSort ?? 0);
|
||||
if (sortDiff !== 0) {
|
||||
return sortDiff;
|
||||
}
|
||||
return String(a.cName ?? '').localeCompare(String(b.cName ?? ''), 'de');
|
||||
});
|
||||
for (const node of list) {
|
||||
sortCategories(node.children);
|
||||
}
|
||||
}
|
||||
|
||||
function buildCategoryTree(rows) {
|
||||
const nodes = new Map();
|
||||
|
||||
for (const row of rows) {
|
||||
nodes.set(row.kKategorie, {
|
||||
kKategorie: row.kKategorie,
|
||||
kOberKategorie: row.kOberKategorie,
|
||||
nSort: row.nSort,
|
||||
cName: row.cName ?? null,
|
||||
count: row.count ?? 0,
|
||||
children: [],
|
||||
});
|
||||
}
|
||||
|
||||
const roots = [];
|
||||
|
||||
for (const node of nodes.values()) {
|
||||
const parent = nodes.get(node.kOberKategorie);
|
||||
if (parent && node.kOberKategorie !== node.kKategorie) {
|
||||
parent.children.push(node);
|
||||
} else {
|
||||
roots.push(node);
|
||||
}
|
||||
}
|
||||
|
||||
sortCategories(roots);
|
||||
return roots;
|
||||
}
|
||||
|
||||
export async function getCategories() {
|
||||
const pool = await getPool();
|
||||
|
||||
const [categoriesResult, countsResult] = await Promise.all([
|
||||
pool.request().query(LOAD_CATEGORIES),
|
||||
pool.request().query(CATEGORY_ARTICLE_COUNTS),
|
||||
]);
|
||||
|
||||
const countByCategory = new Map(
|
||||
countsResult.recordset.map((row) => [row.kKategorie, row.count])
|
||||
);
|
||||
|
||||
const categories = categoriesResult.recordset.map((row) => ({
|
||||
kKategorie: row.kKategorie,
|
||||
kOberKategorie: row.kOberKategorie,
|
||||
nSort: row.nSort,
|
||||
cName: row.cName ?? null,
|
||||
count: countByCategory.get(row.kKategorie) ?? 0,
|
||||
}));
|
||||
|
||||
return {
|
||||
categories,
|
||||
tree: buildCategoryTree(categories),
|
||||
};
|
||||
}
|
||||
6
src/services/misc/getSteuer.js
Normal file
6
src/services/misc/getSteuer.js
Normal file
@@ -0,0 +1,6 @@
|
||||
import { loadSteuerklassen } from './steuerklassen.js';
|
||||
|
||||
export async function getSteuer() {
|
||||
const steuerklassen = await loadSteuerklassen();
|
||||
return { steuerklassen };
|
||||
}
|
||||
28
src/services/misc/steuerklassen.js
Normal file
28
src/services/misc/steuerklassen.js
Normal file
@@ -0,0 +1,28 @@
|
||||
import { getPool } from '../../db/mssqlClient.js';
|
||||
import { LOAD_STEUERKLASSEN } from '../../db/mssql/steuer.js';
|
||||
|
||||
let cache;
|
||||
|
||||
export async function loadSteuerklassen() {
|
||||
if (cache) {
|
||||
return cache;
|
||||
}
|
||||
|
||||
const pool = await getPool();
|
||||
const result = await pool.request().query(LOAD_STEUERKLASSEN);
|
||||
cache = result.recordset.map((row) => ({
|
||||
kSteuerklasse: row.kSteuerklasse,
|
||||
cName: row.cName,
|
||||
nStandard: row.nStandard,
|
||||
fSteuersatz: row.fSteuersatz,
|
||||
}));
|
||||
return cache;
|
||||
}
|
||||
|
||||
export function bruttoFromNetto(netto, kSteuerklasse, steuerklassen) {
|
||||
const row = steuerklassen.find((item) => item.kSteuerklasse === kSteuerklasse);
|
||||
if (row == null || netto == null) {
|
||||
return null;
|
||||
}
|
||||
return netto * (1 + row.fSteuersatz / 100);
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
const STEUER_RATES = {
|
||||
1: 19,
|
||||
2: 7,
|
||||
3: 0,
|
||||
};
|
||||
|
||||
export function getSteuer(kSteuerklasse) {
|
||||
return STEUER_RATES[kSteuerklasse] ?? 19;
|
||||
}
|
||||
|
||||
export function getBrutto(netto, kSteuerklasse) {
|
||||
const rate = getSteuer(kSteuerklasse);
|
||||
return netto * (1 + rate / 100);
|
||||
}
|
||||
Reference in New Issue
Block a user