'use strict'; /** * * 单价调整计算: * 1. 台账修订上报,保存台账修订历史时,使用当前单价调整计算一次 * 2. 台账修订完成:计算台账、应用到未审完成期、应用到所有工程变更 * 3. 新增期:检查是否存在未应用的单价变更 * 4. 期审批完成:所有未应用的单价调整,记录应用到该期(记录revise_price.use_stage/use_stage_order) - 一条sql即可 * 5. 期重现审批:上一次应用的所有单价调整,回到未应用状态(revise_price.use_stage/use_stage_order均回到0) - 一条sql即可 * * @author Mai * @date * @version */ const Ledger = require('./ledger'); const audit = require('../const/audit'); class revisePriceCalc { constructor(ctx) { this.ctx = ctx; } set price(price) { this._price = price; this.common_price_c = []; this.rela_price_c = []; price.forEach(x => { x.rela_lid = x.rela_lid ? x.rela_lid.split(',') : []; if (x.rela_cid) { x.rela_cid = x.rela_cid.split(','); this.rela_price_c.push(x); } else { x.his_rela_cid = []; this.common_price_c.push(x); } }); } get price() { return this._price; } findChangeBillsPrice(b_code, name, unit, unit_price, cid) { const helper = this.ctx.helper; const p = this.rela_price_c.find(x => { return b_code === x.b_code && name === x.name && unit === x.unit && helper.numEqual(unit_price, x.org_price) && x.rela_cid.indexOf(cid) >= 0; }); if (p) return p; return this.common_price_c.find(x => { return b_code === x.b_code && name === x.name && unit === x.unit && helper.numEqual(unit_price, x.org_price); }); } findCommonChangeBillsPrice(b_code, name, unit, unit_price) { const helper = this.ctx.helper; const p = this.price.find(x => { return b_code === x.b_code && name === x.name && unit === x.unit && helper.numEqual(unit_price, x.org_price); }); return p; } /** * 新增一期计量,检查单价调整 * @param {Object} newStage - 新计量期 * @param {Object} preStage - 上一计量期 * @return { inseretPosData, insertBillsData } */ async newStagePriceChange(newStage, preStage, transaction) { const pcTp = { contract_pc_tp: 0, qc_pc_tp: 0, pc_tp: 0, positive_qc_pc_tp: 0, negative_qc_pc_tp: 0 }; // 获取未执行的单价变更,无单价变更不执行 this.price = await this.ctx.service.revisePrice.getAllDataByCondition({ where: { tid: newStage.tid, valid: 1, use_stage: 0 } }); if (this.price.length === 0) return pcTp; // 无截止上期数据不执行 const preBillsData = await this.ctx.service.stageBillsFinal.getAllDataByCondition({ where: { sid: preStage.id } }); if (preBillsData.length === 0) return pcTp; // 加载树结构 const bills = await this.ctx.service.ledger.getData(newStage.tid); this.ctx.helper.assignRelaData(bills, [ { data: preBillsData, fields: ['id', 'contract_qty', 'contract_tp', 'qc_qty', 'qc_tp', 'unit_price', 'positive_qc_qty', 'negative_qc_qty', 'positive_qc_tp', 'negative_qc_tp'], prefix: 'pre_', relaId: 'lid' }, ]); const billsTree = new Ledger.billsTree(this.ctx, { id: 'ledger_id', pid: 'ledger_pid', order: 'order', level: 'level', rootId: -1, calcFields: [] }); billsTree.loadDatas(bills); // 计算 const result = { ibData: [] }; const helper = this.ctx.helper; const decimal = this.ctx.tender.info.decimal; billsTree.calculateAll(node => { if (!node.pre_id) return; if (!node.pre_contract_qty && !node.pre_qc_qty) return; if (node.children && node.children.length > 0) return; const priceDiff = helper.sub(node.unit_price, node.pre_unit_price); if (!priceDiff) return; node.contract_pc_tp = helper.sub(helper.mul(node.pre_contract_qty, node.unit_price, decimal.tp), node.pre_contract_tp); node.qc_pc_tp = helper.sub(helper.mul(node.pre_qc_qty, node.unit_price, decimal.tp), node.pre_qc_tp); node.pc_tp = helper.add(node.contract_pc_tp, node.qc_pc_tp); node.positive_qc_pc_tp = helper.sub(helper.mul(node.pre_positive_qc_qty, node.unit_price, decimal.tp), node.pre_positive_qc_tp); node.negative_qc_pc_tp = helper.sub(helper.mul(node.pre_negative_qc_qty, node.unit_price, decimal.tp), node.pre_negative_qc_tp); result.ibData.push({ tid: newStage.tid, sid: newStage.id, sorder: newStage.order, lid: node.id, org_price: node.pre_unit_price, unit_price: node.unit_price, contract_pc_tp: node.contract_pc_tp, qc_pc_tp: node.qc_pc_tp, pc_tp: node.pc_tp, positive_qc_pc_tp: node.positive_qc_pc_tp, negative_qc_pc_tp: node.negative_qc_pc_tp, }); }); if (result.ibData.length > 0) await transaction.insert(this.ctx.service.stageBillsPc.tableName, result.ibData); for (const ibc of result.ibData) { pcTp.contract_pc_tp = helper.add(pcTp.contract_pc_tp, ibc.contract_pc_tp); pcTp.qc_pc_tp = helper.add(pcTp.qc_pc_tp, ibc.qc_pc_tp); pcTp.pc_tp = helper.add(pcTp.pc_tp, ibc.pc_tp); pcTp.positive_qc_pc_tp = helper.add(pcTp.positive_qc_pc_tp, ibc.positive_qc_pc_tp); pcTp.negative_qc_pc_tp = helper.add(pcTp.negative_qc_pc_tp, ibc.negative_qc_pc_tp); } await transaction.update(this.ctx.service.stage.tableName, { id: newStage.id, ...pcTp, check_calc: true, cache_time_l: new Date() }); return pcTp; } /** * 期,重新审批,检查单价调整 * @param {Object} stage - 期 * @param {Number} auditOrder - 重新审批,最新审批人序号 * @param {Object} transaction - 事务 */ async stageCheckAgainPriceChange(stage, auditOrder, transaction) { const pcTp = { contract_pc_tp: 0, qc_pc_tp: 0, pc_tp: 0, positive_qc_pc_tp: 0, negative_qc_pc_tp: 0 }; // 获取未执行的单价变更,无单价变更不执行 this.price = await this.ctx.service.revisePrice.getAllDataByCondition({ where: { tid: stage.tid, valid: 1, use_stage: 0 } }); if (this.price.length === 0) return pcTp; const curBillsData = await this.ctx.service.stageBills.getLastestStageData2(stage.tid, stage.id); const preBillsData = await this.ctx.service.stageBillsFinal.getAllDataByCondition({ where: { tid: stage.tid, sorder: stage.order - 1 } }); // 加载树结构 const bills = await this.ctx.service.ledger.getData(stage.tid); this.ctx.helper.assignRelaData(bills, [ { data: curBillsData, fields: ['id', 'contract_qty', 'qc_qty', 'positive_qc_qty', 'negative_qc_qty', 'postil', 'times', 'order', 'ex_stage_qty1'], prefix: 'cur_', relaId: 'lid' }, { data: preBillsData, fields: ['id', 'contract_qty', 'contract_tp', 'qc_qty', 'qc_tp', 'unit_price', 'positive_qc_qty', 'negative_qc_qty', 'positive_qc_tp', 'negative_qc_tp'], prefix: 'pre_', relaId: 'lid' }, ]); const billsTree = new Ledger.billsTree(this.ctx, { id: 'ledger_id', pid: 'ledger_pid', order: 'order', level: 'level', rootId: -1, calcFields: [] }); billsTree.loadDatas(bills); const stageChange = await this.ctx.service.stageChange.getFinalStageData(stage.tid, stage.id); // 计算 insertBills billsPriceChange stageChange const result = { ibData: [], bpcData: [], scData: [] }; const helper = this.ctx.helper; const decimal = this.ctx.tender.info.decimal; const said = this.ctx.session.sessionUser.accountId; billsTree.calculateAll(node => { if (node.children && node.children.length > 0) return; // const priceDiff = helper.sub(node.unit_price, node.pre_unit_price); // if (!priceDiff) return; if (node.cur_id && (node.cur_contract_qty || node.cur_qc_qty || node.cur_ex_stage_qty1)) { const cur_contract_tp = helper.mul(node.cur_contract_qty, node.unit_price, decimal.tp); const cur_qc_tp = helper.mul(node.cur_qc_qty, node.unit_price, decimal.tp); const cur_positive_qc_tp = helper.mul(node.cur_positive_qc_qty, node.unit_price, decimal.tp); const cur_negative_qc_tp = helper.mul(node.cur_negative_qc_qty, node.unit_price, decimal.tp); const cur_ex_stage_tp1 = helper.mul(node.cur_ex_stage_qty1, node.unit_price, decimal.tp); if (cur_contract_tp !== node.cur_contract_tp || cur_qc_tp !== node.cur_qc_tp || cur_positive_qc_tp !== node.cur_positive_qc_tp || cur_negative_qc_tp !== node.cur_positive_qc_tp || cur_ex_stage_tp1 !== node.cur_ex_stage_tp1) { result.ibData.push({ tid: stage.tid, sid: stage.id, said, lid: node.id, times: stage.times, order: auditOrder, contract_qty: node.cur_contract_qty, contract_tp: cur_contract_tp, qc_qty: node.cur_qc_qty, qc_tp: cur_qc_tp, positive_qc_qty: node.cur_positive_qc_qty, positive_qc_tp: cur_positive_qc_tp, negative_qc_qty: node.cur_negative_qc_qty, negative_qc_tp: cur_negative_qc_tp, ex_stage_qty1: node.cur_ex_stage_qty1, ex_stage_tp1: cur_ex_stage_tp1, postil: node.postil, }); } } if (node.pre_id && (node.pre_contract_qty || node.pre_qc_qty)) { const contract_pc_tp = helper.sub(helper.mul(node.pre_contract_qty, node.unit_price, decimal.tp), node.pre_contract_tp); const qc_pc_tp = helper.sub(helper.mul(node.pre_qc_qty, node.unit_price, decimal.tp), node.pre_qc_tp); const pc_tp = helper.add(contract_pc_tp, qc_pc_tp); const positive_qc_pc_tp = helper.sub(helper.mul(node.pre_positive_qc_qty, node.unit_price, decimal.tp), node.pre_positive_qc_tp); const negative_qc_pc_tp = helper.sub(helper.mul(node.pre_negative_qc_qty, node.unit_price, decimal.tp), node.pre_negative_qc_tp); if (contract_pc_tp || qc_pc_tp || pc_tp || positive_qc_pc_tp || negative_qc_pc_tp) { result.bpcData.push({ tid: stage.tid, sid: stage.id, sorder: stage.order, lid: node.id, org_price: node.pre_unit_price, unit_price: node.unit_price, contract_pc_tp, qc_pc_tp, pc_tp, positive_qc_pc_tp, negative_qc_pc_tp, }); } } const scDetail = stageChange.filter(x => { return x.lid === node.id; }); for (const scd of scDetail) { result.scData.push({ id: scd.id, unit_price: node.unit_price }); } }); if (result.ibData.length > 0) await transaction.insert(this.ctx.service.stageBills.tableName, result.ibData); await transaction.delete(this.ctx.service.stageBillsPc.tableName, { sid: stage.id }); if (result.bpcData.length > 0) await transaction.insert(this.ctx.service.stageBillsPc.tableName, result.bpcData); if (result.scData.length > 0) await transaction.updateRows(this.ctx.service.stageChange.tableName, result.scData); for (const bpc of result.bpcData) { pcTp.contract_pc_tp = helper.add(pcTp.contract_pc_tp, bpc.contract_pc_tp); pcTp.qc_pc_tp = helper.add(pcTp.qc_pc_tp, bpc.qc_pc_tp); pcTp.pc_tp = helper.add(pcTp.pc_tp, bpc.pc_tp); pcTp.positive_qc_pc_tp = helper.add(pcTp.positive_qc_pc_tp, bpc.positive_qc_pc_tp); pcTp.negative_qc_pc_tp = helper.add(pcTp.negative_qc_pc_tp, bpc.negative_qc_pc_tp); } await transaction.update(this.ctx.service.stage.tableName, { id: stage.id, ...pcTp, check_calc: true, cache_time_l: new Date() }); return pcTp; } /** * 重算工程变更(调整单价) * @param {Object} change - 工程变更 * @param {Object} transaction - 事务 (无则非事务提交) */ async calcChange(change, transaction) { const decimal = this.ctx.tender.info.decimal; const changeBills = await this.ctx.service.changeAuditList.getAllDataByCondition({ where: { cid: change.cid } }); const updateBills = []; const sumBills = []; for (const b of changeBills) { const p = this.findChangeBillsPrice(b.code, b.name, b.unit, b.unit_price, change.cid); const settleGcl = b.gcl_id ? this.settleBills.find(x => { return x.lid === b.gcl_id; }) : null; const settlePos = b.mx_id ? this.settlePos.find(x => { return x.pid === b.mx_id; }): null; let bills_tp; if (p && !settleGcl && !settlePos) { bills_tp = this.ctx.helper.mul(p.new_price, b.spamount, change.tp_decimal || decimal.tp); updateBills.push({ id: b.id, unit_price: p.new_price, checked_price: bills_tp }); if (!p.rela_cid) p.his_rela_cid.push(change.cid); } else { bills_tp = this.ctx.helper.mul(b.unit_price, b.spamount, change.tp_decimal || decimal.tp); } let sb; if (b.gcl_id) { sb = sumBills.find(x => { return x.gcl_id === b.gcl_id }); if (!sb) { sb = {gcl_id: b.gcl_id, unit_price: p ? p.new_price : b.unit_price, v_qty: 0, uv_qty: 0, p_qty: 0, n_qty: 0 }; sumBills.push(sb); } } else { sb = { gcl_id: b.gcl_id, unit_price: p ? p.new_price : b.unit_price, v_qty: 0, uv_qty: 0, p_qty: 0, n_qty: 0 }; sumBills.push(sb); } if (b.spamount >= 0) { sb.p_qty = this.ctx.helper.add(sb.p_qty, b.spamount); } else { sb.n_qty = this.ctx.helper.add(sb.n_qty, b.spamount); } if (b.is_valuation) { sb.v_qty = this.ctx.helper.add(sb.v_qty, b.spamount); } else { sb.uv_qty = this.ctx.helper.add(sb.uv_qty, b.spamount); } } let total_price = 0, positive_tp = 0, negative_tp = 0, valuation_tp = 0, unvaluation_tp = 0; for (const sb of sumBills) { sb.qty = this.ctx.helper.add(sb.v_qty, sb.uv_qty); sb.tp = this.ctx.helper.mul(sb.qty, sb.unit_price, change.tp_decimal || decimal.tp); sb.v_tp = this.ctx.helper.mul(sb.v_qty, sb.unit_price, change.tp_decimal || decimal.tp); sb.uv_tp = this.ctx.helper.mul(sb.uv_qty, sb.unit_price, change.tp_decimal || decimal.tp); sb.p_tp = this.ctx.helper.mul(sb.p_qty, sb.unit_price, change.tp_decimal || decimal.tp); sb.n_tp = this.ctx.helper.mul(sb.n_qty, sb.unit_price, change.tp_decimal || decimal.tp); total_price = this.ctx.helper.add(sb.tp, total_price); valuation_tp = this.ctx.helper.add(sb.v_tp, valuation_tp); unvaluation_tp = this.ctx.helper.add(sb.uv_tp, unvaluation_tp); positive_tp = this.ctx.helper.add(sb.p_tp, positive_tp); negative_tp = this.ctx.helper.add(sb.n_tp, negative_tp); } // const total_price = this.ctx.helper.add(valuation_tp, unvaluation_tp); if (updateBills.length > 0) { await transaction.updateRows(this.ctx.service.changeAuditList.tableName, updateBills); await transaction.update(this.ctx.service.change.tableName, { total_price, positive_tp, negative_tp, valuation_tp, unvaluation_tp }, { where: { cid: change.cid } }); } } /** * 重算标段下所有工程变更(调整单价) * @param {Number} tid - 标段id * @param {Object} transaction - 事务 (无则非事务提交) */ async calcAllChanges(tid, transaction) { const change = await this.ctx.service.change.getAllDataByCondition({ where: { tid, valid: 1 } }); if (change.length === 0) return; for (const c of change) { await this.calcChange(c, transaction); } const revisePriceUpdate = []; for (const p of this.common_price_c) { if (p.his_rela_cid.length > 0) revisePriceUpdate.push({id: p.id, his_rela_cid: p.his_rela_cid.join(',')}); } if (revisePriceUpdate.length > 0) await transaction.updateRows(this.ctx.service.revisePrice.tableName, revisePriceUpdate); } /** * 重算变更方案(调整单价) * @param {Object} change - 工程变更 * @param {Object} transaction - 事务 (无则非事务提交) */ async calcChangePlan(changePlan, transaction) { const decimal = changePlan.decimal ? JSON.parse(changePlan.decimal) : this.ctx.tender.info.decimal; const changeBills = await this.ctx.service.changePlanList.getAllDataByCondition({ where: { cpid: changePlan.id } }); const updateBills = []; let total_price = 0; for (const b of changeBills) { const p = this.findCommonChangeBillsPrice(b.code, b.name, b.unit, b.unit_price); let bills_tp; if (p) { bills_tp = this.ctx.helper.mul(p.new_price, b.spamount, decimal.tp); updateBills.push({ id: b.id, unit_price: p.new_price }); } else { bills_tp = this.ctx.helper.mul(b.unit_price, b.spamount, decimal.tp); } total_price = this.ctx.helper.add(total_price, bills_tp); } if (updateBills.length > 0) { await transaction.updateRows(this.ctx.service.changePlanList.tableName, updateBills); await transaction.update(this.ctx.service.changePlan.tableName, { id: changePlan.id, total_price}); } } async calcAllChangePlan(tid, transaction) { const changePlan = await this.ctx.service.changePlan.getAllDataByCondition({ where: { tid } }); if (changePlan.length === 0) return; for (const c of changePlan) { await this.calcChangePlan(c, transaction); } } /** * 重算变更申请(调整单价) * @param {Object} change - 工程变更 * @param {Object} transaction - 事务 (无则非事务提交) */ async calcChangeApply(changeApply, transaction) { const decimal = changeApply.decimal ? JSON.parse(changeApply.decimal) : this.ctx.tender.info.decimal; const changeBills = await this.ctx.service.changeApplyList.getAllDataByCondition({ where: { caid: changeApply.id } }); const updateBills = []; let total_price = 0; for (const b of changeBills) { const p = this.findCommonChangeBillsPrice(b.code, b.name, b.unit, b.unit_price); let bills_tp; if (p) { bills_tp = this.ctx.helper.mul(p.new_price, b.camount, decimal.tp); updateBills.push({ id: b.id, unit_price: p.new_price }); } else { bills_tp = this.ctx.helper.mul(b.unit_price, b.camount, decimal.tp); } total_price = this.ctx.helper.add(total_price, bills_tp); } if (updateBills.length > 0) { await transaction.updateRows(this.ctx.service.changeApplyList.tableName, updateBills); await transaction.update(this.ctx.service.changeApply.tableName, { id: changeApply.id, total_price}); } } async calcAllChangeApply(tid, transaction) { const changeApply = await this.ctx.service.changeApply.getAllDataByCondition({ where: { tid } }); if (changeApply.length === 0) return; for (const c of changeApply) { await this.calcChangeApply(c, transaction); } } async _calcStage(stage, bills, transaction) { const pcTp = { contract_pc_tp: 0, qc_pc_tp: 0, pc_tp: 0, positive_qc_pc_tp: 0, negative_qc_pc_tp: 0 }; // 无单价变更不执行 if (this.price.length === 0) return pcTp; const curBillsData = await this.ctx.service.stageBills.getLastestStageData2(stage.tid, stage.id); const preBillsData = await this.ctx.service.stageBillsFinal.getAllDataByCondition({ where: { tid: stage.tid, sorder: stage.order - 1 } }); // 加载树结构 this.ctx.helper.assignRelaData(bills, [ { data: curBillsData, fields: ['id', 'contract_qty', 'qc_qty', 'positive_qc_qty', 'negative_qc_qty', 'times', 'order', 'postil', 'ex_stage_qty1', 'ex_stage_tp1'], prefix: 'cur_', relaId: 'lid' }, { data: preBillsData, fields: ['id', 'contract_qty', 'contract_tp', 'qc_qty', 'qc_tp', 'unit_price', 'positive_qc_qty', 'negative_qc_qty', 'positive_qc_tp', 'negative_qc_tp'], prefix: 'pre_', relaId: 'lid' }, ], 'id', true); const billsTree = new Ledger.billsTree(this.ctx, { id: 'ledger_id', pid: 'ledger_pid', order: 'order', level: 'level', rootId: -1, calcFields: [] }); billsTree.loadDatas(bills); const stageChange = await this.ctx.service.stageChange.getFinalStageData(stage.tid, stage.id); // 计算 insertBills/updateBills billsPriceChange StageChange const result = { ibData: [], ubData: [], bpcData: [], scData: [] }; const helper = this.ctx.helper; const decimal = this.ctx.tender.info.decimal; const said = this.ctx.session.sessionUser.accountId; billsTree.calculateAll(node => { if (node.children && node.children.length > 0) return; if (node.cur_id && (node.cur_contract_qty || node.cur_qc_qty || node.cur_ex_stage_qty1)) { const cur_contract_tp = helper.mul(node.cur_contract_qty, node.unit_price, decimal.tp); const cur_qc_tp = helper.mul(node.cur_qc_qty, node.unit_price, decimal.tp); const cur_positive_qc_tp = helper.mul(node.cur_positive_qc_qty, node.unit_price, decimal.tp); const cur_negative_qc_tp = helper.mul(node.cur_negative_qc_qty, node.unit_price, decimal.tp); const cur_ex_stage_tp1 = helper.mul(node.cur_ex_stage_qty1, node.unit_price, decimal.tp); if (cur_contract_tp !== node.cur_contract_tp || cur_qc_tp !== node.cur_qc_tp || cur_positive_qc_tp !== node.cur_positive_qc_tp || cur_negative_qc_tp !== node.cur_positive_qc_tp || cur_ex_stage_tp1 !== node.cur_ex_stage_tp1) { if (node.cur_times === stage.times && node.cur_order === 0) { result.ubData.push({ id: node.cur_id, contract_tp: cur_contract_tp, qc_tp: cur_qc_tp, positive_qc_tp: cur_positive_qc_tp, negative_qc_tp: cur_negative_qc_tp, ex_stage_tp1: cur_ex_stage_tp1, }); } else { result.ibData.push({ tid: stage.tid, sid: stage.id, said, lid: node.id, times: stage.times, order: 0, contract_qty: node.cur_contract_qty, contract_tp: cur_contract_tp, qc_qty: node.cur_qc_qty, qc_tp: cur_qc_tp, positive_qc_qty: node.cur_positive_qc_qty, positive_qc_tp: cur_positive_qc_tp, negative_qc_qty: node.cur_negative_qc_qty, negative_qc_tp: cur_negative_qc_tp, ex_stage_qty1: node.cur_ex_stage_qty1, ex_stage_tp1: cur_ex_stage_tp1, postil: node.cur_postil, }); } } } const scDetail = stageChange.filter(x => { return x.lid === node.id; }); for (const scd of scDetail) { result.scData.push({ id: scd.id, unit_price: node.unit_price }); } const priceDiff = helper.sub(node.unit_price, node.pre_unit_price); if (!priceDiff) return; if (node.pre_id && (node.pre_contract_qty || node.pre_qc_qty)) { node.contract_pc_tp = helper.sub(helper.mul(node.pre_contract_qty, node.unit_price, decimal.tp), node.pre_contract_tp); node.qc_pc_tp = helper.sub(helper.mul(node.pre_qc_qty, node.unit_price, decimal.tp), node.pre_qc_tp); node.pc_tp = helper.add(node.contract_pc_tp, node.qc_pc_tp); node.positive_qc_pc_tp = helper.sub(helper.mul(node.pre_positive_qc_qty, node.unit_price, decimal.tp), node.pre_positive_qc_tp); node.negative_qc_pc_tp = helper.sub(helper.mul(node.pre_negative_qc_qty, node.unit_price, decimal.tp), node.pre_negative_qc_tp); result.bpcData.push({ tid: stage.tid, sid: stage.id, sorder: stage.order, lid: node.id, org_price: node.pre_unit_price, unit_price: node.unit_price, contract_pc_tp: node.contract_pc_tp, qc_pc_tp: node.qc_pc_tp, pc_tp: node.pc_tp, positive_qc_pc_tp: node.positive_qc_pc_tp, negative_qc_pc_tp: node.negative_qc_pc_tp, }); } }); if (result.ibData.length > 0) await transaction.insert(this.ctx.service.stageBills.tableName, result.ibData); if (result.ubData.length > 0) await transaction.updateRows(this.ctx.service.stageBills.tableName, result.ubData); await transaction.delete(this.ctx.service.stageBillsPc.tableName, { sid: stage.id }); if (result.bpcData.length > 0) await transaction.insert(this.ctx.service.stageBillsPc.tableName, result.bpcData); if (result.scData.length > 0) await transaction.updateRows(this.ctx.service.stageChange.tableName, result.scData); for (const bpc of result.bpcData) { pcTp.contract_pc_tp = helper.add(pcTp.contract_pc_tp, bpc.contract_pc_tp); pcTp.qc_pc_tp = helper.add(pcTp.qc_pc_tp, bpc.qc_pc_tp); pcTp.pc_tp = helper.add(pcTp.pc_tp, bpc.pc_tp); pcTp.positive_qc_pc_tp = helper.add(pcTp.positive_qc_pc_tp, bpc.positive_qc_pc_tp); pcTp.negative_qc_pc_tp = helper.add(pcTp.negative_qc_pc_tp, bpc.negative_qc_pc_tp); } await transaction.update(this.ctx.service.stage.tableName, { id: stage.id, ...pcTp, check_calc: true, cache_time_l: new Date() }); return pcTp; } async _calcStageWithoutPc(stage, bills, transaction) { // 无单价变更不执行 if (this.price.length === 0) return; const curBillsData = await this.ctx.service.stageBills.getLastestStageData2(stage.tid, stage.id); // 加载树结构 this.ctx.helper.assignRelaData(bills, [ { data: curBillsData, fields: ['id', 'contract_qty', 'qc_qty', 'positive_qc_qty', 'negative_qc_qty', 'times', 'order', 'postil'], prefix: 'cur_', relaId: 'lid' }, ], 'id', true); const billsTree = new Ledger.billsTree(this.ctx, { id: 'ledger_id', pid: 'ledger_pid', order: 'order', level: 'level', rootId: -1, calcFields: [] }); billsTree.loadDatas(bills); const stageChange = await this.ctx.service.stageChange.getFinalStageData(stage.tid, stage.id); // 计算 insertBills/updateBills StageChange const result = { ibData: [], ubData: [], scData: [] }; const helper = this.ctx.helper; const decimal = this.ctx.tender.info.decimal; const said = this.ctx.session.sessionUser.accountId; billsTree.calculateAll(node => { if (node.children && node.children.length > 0) return; if (node.cur_id && (node.cur_contract_qty || node.cur_qc_qty)) { const cur_contract_tp = helper.mul(node.cur_contract_qty, node.unit_price, decimal.tp); const cur_qc_tp = helper.mul(node.cur_qc_qty, node.unit_price, decimal.tp); const cur_positive_qc_tp = helper.mul(node.cur_positive_qc_qty, node.unit_price, decimal.tp); const cur_negative_qc_tp = helper.mul(node.cur_negative_qc_qty, node.unit_price, decimal.tp); if (cur_contract_tp !== node.cur_contract_tp || cur_qc_tp !== node.cur_qc_tp || cur_positive_qc_tp !== node.cur_positive_qc_tp || cur_negative_qc_tp !== node.cur_positive_qc_tp) { if (node.cur_times === stage.times && node.cur_order === 0) { result.ubData.push({ id: node.cur_id, contract_tp: cur_contract_tp, qc_tp: cur_qc_tp, positive_qc_tp: cur_positive_qc_tp, negative_qc_tp: cur_negative_qc_tp, }); } else { result.ibData.push({ tid: stage.tid, sid: stage.id, said, lid: node.id, times: stage.times, order: 0, contract_qty: node.cur_contract_qty, contract_tp: cur_contract_tp, qc_qty: node.cur_qc_qty, qc_tp: cur_qc_tp, positive_qc_qty: node.cur_positive_qc_qty, positive_qc_tp: cur_positive_qc_tp, negative_qc_qty: node.cur_negative_qc_qty, negative_qc_tp: cur_negative_qc_tp, postil: node.cur_postil, }); } } } const scDetail = stageChange.filter(x => { return x.lid === node.id; }); for (const scd of scDetail) { result.scData.push({ id: scd.id, unit_price: node.unit_price }); } }); if (result.ibData.length > 0) await transaction.insert(this.ctx.service.stageBills.tableName, result.ibData); if (result.ubData.length > 0) await transaction.updateRows(this.ctx.service.stageBills.tableName, result.ubData); if (result.scData.length > 0) await transaction.updateRows(this.ctx.service.stageChange.tableName, result.scData); if (result.ibData.length > 0 || result.ubData.length > 0) await transaction.update(this.ctx.service.stage.tableName, { id: stage.id, check_calc: true}); } /** * 计算修订台账 * @param {Object}revise - 最新一次台账修订(此处不检查) * @param {Object} transaction - 事务 (无则非事务提交) */ async calcReviseLedger(revise, transaction) { const xmj = await this.ctx.helper.loadLedgerDataFromOss(revise.curHis.bills_file); xmj.forEach(x => { delete x.is_tp; delete x.gxby_status; delete x.gxby_limit; delete x.gxby_ratio; delete x.gxby_url; delete x.dagl_status; delete x.dagl_limit; delete x.dagl_ratio; delete x.dagl_url; }); const pos = await this.ctx.helper.loadLedgerDataFromOss(revise.curHis.pos_file); pos.forEach(p => { p.in_time = new Date(p.in_time); delete p.gxby_status; delete p.gxby_limit; delete p.gxby_ratio; delete p.gxby_url; delete p.dagl_status; delete p.dagl_limit; delete p.dagl_ratio; delete p.dagl_url; }); await transaction.delete(this.ctx.service.ledger.tableName, { tender_id: revise.tid }); if (xmj.length > 0) await transaction.insert(this.ctx.service.ledger.tableName, xmj); await transaction.delete(this.ctx.service.pos.tableName, { tid: revise.tid }); if (pos.length > 0) await transaction.insert(this.ctx.service.pos.tableName, pos); // 应用到未审完成期 const stages = await this.ctx.service.stage.getAllDataByCondition({ where: { tid: revise.tid }, orders: [['order', 'asc']] }); const latestStage = stages[stages.length - 1]; let pcTp; if (latestStage && latestStage.status !== audit.stage.status.checked) { for (const s of stages) { if (s.status === audit.stage.status.checked) continue; if (!pcTp) { pcTp = await this._calcStage(s, xmj, transaction); } else { await this._calcStageWithoutPc(s, xmj, transaction); } } } return pcTp; } async calcRevise(revise, transaction) { if (revise.tid !== this.ctx.tender.id) throw '数据错误'; this.price = await this.ctx.service.revisePrice.getAllDataByCondition({ where: { rid: revise.id } }); this.settleStatus = this.ctx.service.settle.settleStatus; this.settleBills = revise.readySettle ? await this.ctx.service.settleBills.getAllDataByCondition({ where: { settle_id: revise.readySettle.id, settle_status: this.settleStatus.finish } }) : []; this.settlePos = revise.readySettle ? await this.ctx.service.settlePos.getAllDataByCondition({ where: { settle_id: revise.readySettle.id }}) : []; const pcTp = await this.calcReviseLedger(revise, transaction); // 引用到所有工程变更 await this.calcAllChanges(revise.tid, transaction); await this.calcAllChangePlan(revise.tid, transaction); await this.calcAllChangeApply(revise.tid, transaction); return pcTp; } } module.exports = revisePriceCalc;