Fixes
This commit is contained in:
@@ -38,6 +38,11 @@ function normalizeUuid(value: unknown): string | null {
|
||||
return trimmed.length ? trimmed : null;
|
||||
}
|
||||
|
||||
function sanitizeCompositionRows(value: unknown): CompositionRow[] {
|
||||
if (!Array.isArray(value)) return [];
|
||||
return value.filter((entry): entry is CompositionRow => !!entry && typeof entry === "object");
|
||||
}
|
||||
|
||||
export async function recalculateServicePricesForTenant(server: FastifyInstance, tenantId: number, updatedBy?: string | null) {
|
||||
const [services, products, hourrates] = await Promise.all([
|
||||
server.db.select().from(schema.services).where(eq(schema.services.tenant, tenantId)),
|
||||
@@ -88,94 +93,111 @@ export async function recalculateServicePricesForTenant(server: FastifyInstance,
|
||||
materialPurchaseTotal: getJsonNumber(service.purchasePriceComposed, "material"),
|
||||
workerTotal: getJsonNumber(service.sellingPriceComposed, "worker"),
|
||||
workerPurchaseTotal: getJsonNumber(service.purchasePriceComposed, "worker"),
|
||||
materialComposition: Array.isArray(service.materialComposition) ? service.materialComposition as CompositionRow[] : [],
|
||||
personalComposition: Array.isArray(service.personalComposition) ? service.personalComposition as CompositionRow[] : [],
|
||||
materialComposition: sanitizeCompositionRows(service.materialComposition),
|
||||
personalComposition: sanitizeCompositionRows(service.personalComposition),
|
||||
};
|
||||
memo.set(serviceId, lockedResult);
|
||||
return lockedResult;
|
||||
}
|
||||
|
||||
stack.add(serviceId);
|
||||
try {
|
||||
const materialComposition = sanitizeCompositionRows(service.materialComposition);
|
||||
const personalComposition = sanitizeCompositionRows(service.personalComposition);
|
||||
const hasMaterialComposition = materialComposition.length > 0;
|
||||
const hasPersonalComposition = personalComposition.length > 0;
|
||||
|
||||
const materialComposition: CompositionRow[] = Array.isArray(service.materialComposition)
|
||||
? (service.materialComposition as CompositionRow[])
|
||||
: [];
|
||||
const personalComposition: CompositionRow[] = Array.isArray(service.personalComposition)
|
||||
? (service.personalComposition as CompositionRow[])
|
||||
: [];
|
||||
|
||||
let materialTotal = 0;
|
||||
let materialPurchaseTotal = 0;
|
||||
|
||||
const normalizedMaterialComposition = materialComposition.map((entry) => {
|
||||
const quantity = toNumber(entry.quantity);
|
||||
const productId = normalizeId(entry.product);
|
||||
const childServiceId = normalizeId(entry.service);
|
||||
|
||||
let sellingPrice = toNumber(entry.price);
|
||||
let purchasePrice = toNumber(entry.purchasePrice);
|
||||
|
||||
if (productId) {
|
||||
const product = productMap.get(productId);
|
||||
sellingPrice = toNumber(product?.selling_price);
|
||||
purchasePrice = toNumber(product?.purchase_price);
|
||||
} else if (childServiceId) {
|
||||
const child = calculateService(childServiceId);
|
||||
sellingPrice = toNumber(child.sellingTotal);
|
||||
purchasePrice = toNumber(child.purchaseTotal);
|
||||
// Ohne Zusammensetzung keine automatische Überschreibung:
|
||||
// manuell gepflegte Preise sollen erhalten bleiben.
|
||||
if (!hasMaterialComposition && !hasPersonalComposition) {
|
||||
const manualResult = {
|
||||
sellingTotal: getJsonNumber(service.sellingPriceComposed, "total") || toNumber(service.sellingPrice),
|
||||
purchaseTotal: getJsonNumber(service.purchasePriceComposed, "total"),
|
||||
materialTotal: getJsonNumber(service.sellingPriceComposed, "material"),
|
||||
materialPurchaseTotal: getJsonNumber(service.purchasePriceComposed, "material"),
|
||||
workerTotal: getJsonNumber(service.sellingPriceComposed, "worker"),
|
||||
workerPurchaseTotal: getJsonNumber(service.purchasePriceComposed, "worker"),
|
||||
materialComposition,
|
||||
personalComposition,
|
||||
};
|
||||
memo.set(serviceId, manualResult);
|
||||
return manualResult;
|
||||
}
|
||||
|
||||
materialTotal += quantity * sellingPrice;
|
||||
materialPurchaseTotal += quantity * purchasePrice;
|
||||
let materialTotal = 0;
|
||||
let materialPurchaseTotal = 0;
|
||||
|
||||
return {
|
||||
...entry,
|
||||
price: round2(sellingPrice),
|
||||
purchasePrice: round2(purchasePrice),
|
||||
};
|
||||
});
|
||||
const normalizedMaterialComposition = materialComposition.map((entry) => {
|
||||
const quantity = toNumber(entry.quantity);
|
||||
const productId = normalizeId(entry.product);
|
||||
const childServiceId = normalizeId(entry.service);
|
||||
|
||||
let workerTotal = 0;
|
||||
let workerPurchaseTotal = 0;
|
||||
const normalizedPersonalComposition = personalComposition.map((entry) => {
|
||||
const quantity = toNumber(entry.quantity);
|
||||
const hourrateId = normalizeUuid(entry.hourrate);
|
||||
let sellingPrice = toNumber(entry.price);
|
||||
let purchasePrice = toNumber(entry.purchasePrice);
|
||||
|
||||
let sellingPrice = toNumber(entry.price);
|
||||
let purchasePrice = toNumber(entry.purchasePrice);
|
||||
|
||||
if (hourrateId) {
|
||||
const hourrate = hourrateMap.get(hourrateId);
|
||||
if (hourrate) {
|
||||
sellingPrice = toNumber(hourrate.sellingPrice);
|
||||
purchasePrice = toNumber(hourrate.purchase_price);
|
||||
if (productId) {
|
||||
const product = productMap.get(productId);
|
||||
sellingPrice = toNumber(product?.selling_price);
|
||||
purchasePrice = toNumber(product?.purchase_price);
|
||||
} else if (childServiceId) {
|
||||
const child = calculateService(childServiceId);
|
||||
sellingPrice = toNumber(child.sellingTotal);
|
||||
purchasePrice = toNumber(child.purchaseTotal);
|
||||
}
|
||||
}
|
||||
|
||||
workerTotal += quantity * sellingPrice;
|
||||
workerPurchaseTotal += quantity * purchasePrice;
|
||||
materialTotal += quantity * sellingPrice;
|
||||
materialPurchaseTotal += quantity * purchasePrice;
|
||||
|
||||
return {
|
||||
...entry,
|
||||
price: round2(sellingPrice),
|
||||
purchasePrice: round2(purchasePrice),
|
||||
return {
|
||||
...entry,
|
||||
price: round2(sellingPrice),
|
||||
purchasePrice: round2(purchasePrice),
|
||||
};
|
||||
});
|
||||
|
||||
let workerTotal = 0;
|
||||
let workerPurchaseTotal = 0;
|
||||
const normalizedPersonalComposition = personalComposition.map((entry) => {
|
||||
const quantity = toNumber(entry.quantity);
|
||||
const hourrateId = normalizeUuid(entry.hourrate);
|
||||
|
||||
let sellingPrice = toNumber(entry.price);
|
||||
let purchasePrice = toNumber(entry.purchasePrice);
|
||||
|
||||
if (hourrateId) {
|
||||
const hourrate = hourrateMap.get(hourrateId);
|
||||
if (hourrate) {
|
||||
sellingPrice = toNumber(hourrate.sellingPrice);
|
||||
purchasePrice = toNumber(hourrate.purchase_price);
|
||||
}
|
||||
}
|
||||
|
||||
workerTotal += quantity * sellingPrice;
|
||||
workerPurchaseTotal += quantity * purchasePrice;
|
||||
|
||||
return {
|
||||
...entry,
|
||||
price: round2(sellingPrice),
|
||||
purchasePrice: round2(purchasePrice),
|
||||
};
|
||||
});
|
||||
|
||||
const result = {
|
||||
sellingTotal: round2(materialTotal + workerTotal),
|
||||
purchaseTotal: round2(materialPurchaseTotal + workerPurchaseTotal),
|
||||
materialTotal: round2(materialTotal),
|
||||
materialPurchaseTotal: round2(materialPurchaseTotal),
|
||||
workerTotal: round2(workerTotal),
|
||||
workerPurchaseTotal: round2(workerPurchaseTotal),
|
||||
materialComposition: normalizedMaterialComposition,
|
||||
personalComposition: normalizedPersonalComposition,
|
||||
};
|
||||
});
|
||||
|
||||
const result = {
|
||||
sellingTotal: round2(materialTotal + workerTotal),
|
||||
purchaseTotal: round2(materialPurchaseTotal + workerPurchaseTotal),
|
||||
materialTotal: round2(materialTotal),
|
||||
materialPurchaseTotal: round2(materialPurchaseTotal),
|
||||
workerTotal: round2(workerTotal),
|
||||
workerPurchaseTotal: round2(workerPurchaseTotal),
|
||||
materialComposition: normalizedMaterialComposition,
|
||||
personalComposition: normalizedPersonalComposition,
|
||||
};
|
||||
|
||||
memo.set(serviceId, result);
|
||||
stack.delete(serviceId);
|
||||
return result;
|
||||
memo.set(serviceId, result);
|
||||
return result;
|
||||
} finally {
|
||||
stack.delete(serviceId);
|
||||
}
|
||||
};
|
||||
|
||||
for (const service of services) {
|
||||
|
||||
@@ -58,8 +58,6 @@ const queryConfigPlugin: FastifyPluginAsync<QueryConfigPluginOptions> = async (
|
||||
|
||||
const query = req.query as Record<string, any>
|
||||
|
||||
console.log(query)
|
||||
|
||||
// Pagination deaktivieren?
|
||||
const disablePagination =
|
||||
query.noPagination === 'true' ||
|
||||
|
||||
@@ -51,6 +51,7 @@ export default async function meRoutes(server: FastifyInstance) {
|
||||
name: tenants.name,
|
||||
short: tenants.short,
|
||||
locked: tenants.locked,
|
||||
features: tenants.features,
|
||||
extraModules: tenants.extraModules,
|
||||
businessInfo: tenants.businessInfo,
|
||||
numberRanges: tenants.numberRanges,
|
||||
|
||||
Reference in New Issue
Block a user