This commit is contained in:
seb
2026-10-17 03:47:09 +02:00
parent d729423249
commit e63abfe2c0
4 changed files with 168 additions and 101 deletions

View File

@@ -2,6 +2,7 @@
import {
formatPriceAmount,
grossFromNet,
netFromGross,
parsePriceInput,
} from './price';
@@ -156,3 +157,87 @@ export function formatPhotoSizeKb(fullSize) {
export function formatPhotoDimensions(fullW, fullH) {
return `${fullW}×${fullH}`;
}
/**
* Resolves the sales price (VK-Preis) and tax rate for an article.
* Inspects `article.prices` (matching optional `customerGroupId`, falling back to base price),
* top-level `article.net` / `article.price` / `article.vknetto`, and calculates gross with optional rebate.
*
* @param {object|null} article
* @param {object} [options]
* @param {number|string|null} [options.customerGroupId]
* @param {number|string} [options.defaultTaxRate=19]
* @param {number|string} [options.rebate=0]
* @returns {{ net: number|null, gross: number|null, taxRate: number|null }}
*/
export function resolveSalesPrice(article, { customerGroupId, defaultTaxRate = 19, rebate = 0 } = {}) {
const normTax = defaultTaxRate != null && Number.isFinite(Number(defaultTaxRate)) ? Number(defaultTaxRate) : 19;
if (!article) {
return { net: null, gross: null, taxRate: normTax };
}
const r = Number.isFinite(Number(rebate)) ? Number(rebate) : 0;
let matchedPrice = null;
if (Array.isArray(article.prices) && article.prices.length > 0) {
if (customerGroupId != null) {
matchedPrice =
article.prices.find(
(p) => String(p.customergroupId) === String(customerGroupId) && (p.minmultiplier === 1 || p.minmultiplier == null)
) ||
article.prices.find((p) => String(p.customergroupId) === String(customerGroupId));
}
if (!matchedPrice) {
matchedPrice = primaryPrice(article);
}
}
let net = null;
let taxRate = null;
let gross = null;
if (matchedPrice) {
if (matchedPrice.net != null && Number.isFinite(Number(matchedPrice.net))) {
net = Number(matchedPrice.net);
}
const rawTax = matchedPrice.taxRate ?? matchedPrice.tax;
if (rawTax != null && Number.isFinite(Number(rawTax))) {
taxRate = Number(rawTax);
}
if (matchedPrice.gross != null && Number.isFinite(Number(matchedPrice.gross))) {
gross = Number(matchedPrice.gross);
} else if (net != null && taxRate != null) {
gross = priceBrutto(matchedPrice);
}
}
if (net == null) {
const rawNet = article.price ?? article.net ?? article.vknetto;
if (rawNet != null && Number.isFinite(Number(rawNet))) {
net = Number(rawNet);
}
}
if (taxRate == null) {
const rawTax = article.taxRate ?? article.taxrate ?? article.tax;
taxRate = rawTax != null && Number.isFinite(Number(rawTax)) ? Number(rawTax) : normTax;
}
if (gross == null && article.gross != null && Number.isFinite(Number(article.gross))) {
gross = Number(article.gross);
}
if (net == null && gross != null && taxRate != null) {
net = netFromGross(gross, taxRate, 0);
}
if (net != null && taxRate != null) {
if (r !== 0) {
gross = grossFromNet(net, taxRate, r);
} else if (gross == null) {
gross = Math.round((net * (1 + taxRate / 100) + Number.EPSILON) * 100) / 100;
}
}
return { net, gross, taxRate };
}