metallkart-erp/scripts/financial-tracking-quantity-backfill.ts
louis 3fbb92b2aa fix: FinancialTracking.budgetX × Order.quantity — 3 sites + backfill
Bug: budgetX stored per-unit smeta costs instead of totals, causing
absurd overrun percentages (7140% for qty=1700, 3831% for qty=100).

Fix 3 write sites:
- estimates.service.ts syncFinancialTracking: .mul(qty)
- financial.service.ts applyRevision: revision.delta*.mul(qty)
- revisions.service.ts applyRevisionToBudget: (smeta + deltas) * qty

financial.service.ts initFromSmeta was already correct (L36-40).
committedX/actualX from PO.totalAmount — already totals, no fix needed.

Backfill: 2 FTs corrected, alertLevel RED→NONE for both.
Script is one-shot non-idempotent (never re-run).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-28 11:23:57 +03:00

68 lines
2.2 KiB
TypeScript

#!/usr/bin/env tsx
import { PrismaClient } from '@prisma/client';
import { Decimal } from '@prisma/client/runtime/library';
const prisma = new PrismaClient();
const apply = process.argv.includes('--apply');
async function main() {
console.log(apply ? '🔥 MODE APPLY' : '🧪 MODE DRY-RUN (--apply to write)');
const fts = await prisma.financialTracking.findMany({
include: {
order: { select: { id: true, orderCode: true, quantity: true } as any },
},
});
console.log(`Total FinancialTracking: ${fts.length}`);
let updated = 0;
let skipped = 0;
for (const ft of fts) {
const order = ft.order as any;
const qty = order?.quantity ?? 1;
if (qty <= 1) {
skipped++;
continue;
}
const qtyDec = new Decimal(qty);
const newServices = ft.budgetServices.mul(qtyDec);
const newMaterials = ft.budgetMaterials.mul(qtyDec);
const newLabor = ft.budgetLabor.mul(qtyDec);
const newSupply = ft.budgetSupply.mul(qtyDec);
const oldTotal = Number(ft.budgetServices) + Number(ft.budgetMaterials)
+ Number(ft.budgetLabor) + Number(ft.budgetSupply);
const newTotal = Number(newServices) + Number(newMaterials)
+ Number(newLabor) + Number(newSupply);
console.log(`\n${order.orderCode} (orderId=${order.id}, qty=${qty}):`);
console.log(` budget: ${oldTotal.toLocaleString('ru')}${newTotal.toLocaleString('ru')}`);
console.log(` services: ${ft.budgetServices}${newServices}`);
console.log(` materials: ${ft.budgetMaterials}${newMaterials}`);
console.log(` labor: ${ft.budgetLabor}${newLabor}`);
console.log(` supply: ${ft.budgetSupply}${newSupply}`);
if (apply) {
await prisma.financialTracking.update({
where: { id: ft.id },
data: {
budgetServices: newServices,
budgetMaterials: newMaterials,
budgetLabor: newLabor,
budgetSupply: newSupply,
},
});
console.log(' ✅ Applied');
}
updated++;
}
console.log(`\nSummary: ${updated} to update, ${skipped} skipped (qty=1)`);
}
main()
.catch(e => { console.error(e); process.exit(1); })
.finally(() => prisma.$disconnect());