"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.EstimateService = void 0; const client_1 = require("@prisma/client"); class EstimateService { constructor(prisma) { this.prisma = prisma; } async createEstimate(data) { // Get direction const direction = await this.prisma.surveyDirection.findUnique({ where: { code: data.directionCode }, }); if (!direction) { throw new Error(`Direction not found: ${data.directionCode}`); } // Get default executor from settings let executor = data.executor; if (!executor) { const defaultExecutor = await this.prisma.setting.findUnique({ where: { key: 'default_executor' }, }); executor = defaultExecutor?.value || 'Не указан'; } // Generate estimate number (per owner) const count = await this.prisma.estimate.count({ where: { ownerId: data.ownerId }, }); const number = `${count + 1}`; const estimate = await this.prisma.estimate.create({ data: { number, directionId: direction.id, ownerId: data.ownerId, objectName: data.objectName, customer: data.customer, executor, vatRate: data.vatRate ? new client_1.Prisma.Decimal(data.vatRate) : new client_1.Prisma.Decimal(20), status: 'draft', }, include: { direction: true, }, }); return estimate; } async updateEstimate(id, data) { const updateData = {}; if (data.objectName) updateData.objectName = data.objectName; if (data.customer) updateData.customer = data.customer; if (data.executor) updateData.executor = data.executor; if (data.regionalCoef !== undefined) updateData.regionalCoef = new client_1.Prisma.Decimal(data.regionalCoef); if (data.inflationIndex !== undefined) updateData.inflationIndex = new client_1.Prisma.Decimal(data.inflationIndex); if (data.inflationDocRef) updateData.inflationDocRef = data.inflationDocRef; if (data.companyCoef !== undefined) updateData.companyCoef = new client_1.Prisma.Decimal(data.companyCoef); if (data.executorCoef !== undefined) updateData.executorCoef = new client_1.Prisma.Decimal(data.executorCoef); if (data.vatRate !== undefined) updateData.vatRate = new client_1.Prisma.Decimal(data.vatRate); if (data.status) updateData.status = data.status; const estimate = await this.prisma.estimate.update({ where: { id }, data: updateData, include: { direction: true, items: { orderBy: { orderNumber: 'asc' } }, totals: { orderBy: { orderNumber: 'asc' } }, }, }); return estimate; } async addEstimateItem(estimateId, data) { // Get max order number const maxOrder = await this.prisma.estimateItem.aggregate({ where: { estimateId }, _max: { orderNumber: true }, }); const orderNumber = (maxOrder._max.orderNumber || 0) + 1; // Calculate total price const basePrice = new client_1.Prisma.Decimal(data.basePrice); const quantity = new client_1.Prisma.Decimal(data.quantity); let totalPrice = basePrice.mul(quantity); if (data.coef1) totalPrice = totalPrice.mul(new client_1.Prisma.Decimal(data.coef1)); if (data.coef2) totalPrice = totalPrice.mul(new client_1.Prisma.Decimal(data.coef2)); if (data.coef3) totalPrice = totalPrice.mul(new client_1.Prisma.Decimal(data.coef3)); const item = await this.prisma.estimateItem.create({ data: { estimateId, orderNumber, sectionType: data.sectionType, priceItemId: data.priceItemId || null, workName: data.workName, justification: data.justification || null, basePrice, quantity, unit: data.unit || null, coef1: data.coef1 ? new client_1.Prisma.Decimal(data.coef1) : null, coef1Desc: data.coef1Desc || null, coef2: data.coef2 ? new client_1.Prisma.Decimal(data.coef2) : null, coef2Desc: data.coef2Desc || null, coef3: data.coef3 ? new client_1.Prisma.Decimal(data.coef3) : null, coef3Desc: data.coef3Desc || null, totalPrice, }, }); return item; } async updateEstimateItem(itemId, data) { const updateData = {}; if (data.workName) updateData.workName = data.workName; if (data.justification) updateData.justification = data.justification; if (data.basePrice !== undefined) updateData.basePrice = new client_1.Prisma.Decimal(data.basePrice); if (data.quantity !== undefined) updateData.quantity = new client_1.Prisma.Decimal(data.quantity); if (data.unit) updateData.unit = data.unit; if (data.coef1 !== undefined) updateData.coef1 = data.coef1 ? new client_1.Prisma.Decimal(data.coef1) : null; if (data.coef1Desc !== undefined) updateData.coef1Desc = data.coef1Desc; if (data.coef2 !== undefined) updateData.coef2 = data.coef2 ? new client_1.Prisma.Decimal(data.coef2) : null; if (data.coef2Desc !== undefined) updateData.coef2Desc = data.coef2Desc; if (data.coef3 !== undefined) updateData.coef3 = data.coef3 ? new client_1.Prisma.Decimal(data.coef3) : null; if (data.coef3Desc !== undefined) updateData.coef3Desc = data.coef3Desc; // Recalculate total if price/quantity/coefs changed const currentItem = await this.prisma.estimateItem.findUnique({ where: { id: itemId } }); if (currentItem) { const basePrice = updateData.basePrice || currentItem.basePrice; const quantity = updateData.quantity || currentItem.quantity; let totalPrice = basePrice.mul(quantity); const coef1 = updateData.coef1 !== undefined ? updateData.coef1 : currentItem.coef1; const coef2 = updateData.coef2 !== undefined ? updateData.coef2 : currentItem.coef2; const coef3 = updateData.coef3 !== undefined ? updateData.coef3 : currentItem.coef3; if (coef1) totalPrice = totalPrice.mul(coef1); if (coef2) totalPrice = totalPrice.mul(coef2); if (coef3) totalPrice = totalPrice.mul(coef3); updateData.totalPrice = totalPrice; } const item = await this.prisma.estimateItem.update({ where: { id: itemId }, data: updateData, }); return item; } async recalculateTotals(estimateId) { const estimate = await this.prisma.estimate.findUnique({ where: { id: estimateId }, include: { items: true, }, }); if (!estimate) { throw new Error('Estimate not found'); } // Calculate section totals const fieldWorks = estimate.items .filter(i => i.sectionType === 'field') .reduce((sum, i) => sum.add(i.totalPrice), new client_1.Prisma.Decimal(0)); const officeWorks = estimate.items .filter(i => i.sectionType === 'office') .reduce((sum, i) => sum.add(i.totalPrice), new client_1.Prisma.Decimal(0)); const laboratory = estimate.items .filter(i => i.sectionType === 'laboratory') .reduce((sum, i) => sum.add(i.totalPrice), new client_1.Prisma.Decimal(0)); const subtotal = estimate.items .reduce((sum, i) => sum.add(i.totalPrice), new client_1.Prisma.Decimal(0)); // Apply coefficients const regionalCoef = estimate.regionalCoef || new client_1.Prisma.Decimal(1); const inflationIndex = estimate.inflationIndex || new client_1.Prisma.Decimal(1); const companyCoef = estimate.companyCoef || new client_1.Prisma.Decimal(1); const executorCoef = estimate.executorCoef || new client_1.Prisma.Decimal(1); let totalWithoutVat = subtotal .mul(regionalCoef) .mul(inflationIndex) .mul(companyCoef) .mul(executorCoef); const vatRate = estimate.vatRate || new client_1.Prisma.Decimal(20); const vatAmount = totalWithoutVat.mul(vatRate).div(100); const totalWithVat = totalWithoutVat.add(vatAmount); // Update estimate const updated = await this.prisma.estimate.update({ where: { id: estimateId }, data: { totalFieldWorks: fieldWorks, totalOfficeWorks: officeWorks, totalLaboratory: laboratory, subtotal, totalWithoutVat, vatAmount, totalWithVat, }, include: { direction: true, items: { orderBy: { orderNumber: 'asc' } }, totals: { orderBy: { orderNumber: 'asc' } }, }, }); // Update totals section await this.updateTotalsSection(estimateId, estimate, updated); return updated; } async updateTotalsSection(estimateId, estimate, updated) { // Delete existing totals await this.prisma.estimateTotal.deleteMany({ where: { estimateId } }); const totals = []; let order = 1; // Add totals rows if (updated.regionalCoef && Number(updated.regionalCoef) !== 1) { totals.push({ estimateId, orderNumber: order++, label: 'С районным коэффициентом', description: `К=${updated.regionalCoef}`, baseValue: updated.subtotal, coefficient: updated.regionalCoef, resultValue: updated.subtotal.mul(updated.regionalCoef), }); } if (updated.inflationIndex && Number(updated.inflationIndex) !== 1) { const prevValue = totals.length > 0 ? totals[totals.length - 1].resultValue : updated.subtotal; totals.push({ estimateId, orderNumber: order++, label: 'Перевод в текущие цены', description: updated.inflationDocRef || `Индекс: ${updated.inflationIndex}`, baseValue: prevValue, coefficient: updated.inflationIndex, resultValue: prevValue.mul(updated.inflationIndex), }); } if (updated.companyCoef && Number(updated.companyCoef) !== 1) { const prevValue = totals.length > 0 ? totals[totals.length - 1].resultValue : updated.subtotal; totals.push({ estimateId, orderNumber: order++, label: 'Коэффициент компании', description: null, baseValue: prevValue, coefficient: updated.companyCoef, resultValue: prevValue.mul(updated.companyCoef), }); } if (updated.executorCoef && Number(updated.executorCoef) !== 1) { const prevValue = totals.length > 0 ? totals[totals.length - 1].resultValue : updated.subtotal; totals.push({ estimateId, orderNumber: order++, label: `Коэффициент ${estimate.executor}`, description: null, baseValue: prevValue, coefficient: updated.executorCoef, resultValue: prevValue.mul(updated.executorCoef), }); } // Final totals totals.push({ estimateId, orderNumber: order++, label: 'Итого без НДС:', description: null, baseValue: null, coefficient: null, resultValue: updated.totalWithoutVat, }); totals.push({ estimateId, orderNumber: order++, label: `НДС ${updated.vatRate}%:`, description: null, baseValue: updated.totalWithoutVat, coefficient: updated.vatRate.div(100), resultValue: updated.vatAmount, }); totals.push({ estimateId, orderNumber: order++, label: 'Всего с НДС:', description: null, baseValue: null, coefficient: null, resultValue: updated.totalWithVat, }); // Create totals for (const total of totals) { await this.prisma.estimateTotal.create({ data: total }); } } } exports.EstimateService = EstimateService; //# sourceMappingURL=estimate.service.js.map