/** * Created by CSL on 2017-07-19. * dispExpr: F8*(L-1); expression: "@('8') * (L-1)"; * 说明:F后跟行号,L替换人工系数值,@后跟ID。用到L的规则必须有labourCoeID属性(反过来不要求), * 用到费率的规则必须有feeRateID属性,当有该属性时,会自动显示费率值。 */ let defaultBillTemplate = [ { ID: 1, serialNo: '一', code: "A", name: "定额直接费", dispExpr: "A1+A2+A3", statement: "人工费+材料费+机械费", feeRate: null, memo: '' }, { ID: 2, serialNo: '1', code: "A1", name: "人工费", dispExpr: "HJ", statement: "合计", feeRate: 50, fieldName: 'labour', memo: '' }, { ID: 3, serialNo: '2', code: "A2", name: "材料费", dispExpr: "HJ", statement: "合计", feeRate: 30, fieldName: 'material', memo: '' }, { ID: 4, serialNo: '3', code: "A3", name: "机械费", dispExpr: "HJ", statement: "合计", feeRate: 20, fieldName: 'machine', memo: '' }, { ID: 5, serialNo: '二', code: "A4", name: "管理费", dispExpr: "A", statement: "定额直接费", feeRate: null, fieldName: 'manage', memo: '' }, { ID: 6, serialNo: '三', code: "B", name: "利润", dispExpr: "A", statement: "定额直接费", feeRate: null, fieldName: 'profit', memo: '' }, { ID: 7, serialNo: '四', code: "C", name: "风险费用", dispExpr: "", statement: "", feeRate: null, fieldName: 'risk', memo: '' }, { ID: 8, serialNo: '', code: "", name: "综合单价", dispExpr: "A+B", statement: "定额直接费+利润", feeRate: null, fieldName: 'common', memo: '' } ]; class CalcProgram { constructor(project){ this.project = project; this.datas = []; this.digit = 2; this.digitDefault = 6; this.calc = new Calculation(); project.registerModule(ModuleNames.calc_program, this); }; getSourceType () { return ModuleNames.calc_program; }; loadData (datas) { this.datas = datas; }; doAfterUpdate (err, data) { if(!err){ // do } }; // 经测试,全部编译一次耗时0.003~0.004秒。耗时基本忽略不计。 compileAllTemps(){ let calcFeeRates = this.project.FeeRate.datas.rates; let calcLabourCoes = this.project.labourCoe.datas.coes; let calcTemplates = this.project.calcProgram.datas.templates; this.calc.compilePublics(calcFeeRates, calcLabourCoes, feeType, rationCalcBase); for (let ct of calcTemplates){ this.calc.compileTemplate(ct); }; // 存储费率临时数据,报表用。 if (this.calc.saveForReports.length > 0){ let saveDatas = {}; saveDatas.projectID = projectInfoObj.projectInfo.ID; saveDatas.calcItems = this.calc.saveForReports; CommonAjax.post('/calcProgram/saveCalcItems', saveDatas, function (data) { this.calc.saveForReports = []; }); }; }; calculate(treeNode){ let me = this; if (treeNode.sourceType === this.project.Ration.getSourceType()) { treeNode.data.gljList = this.project.ration_glj.getGljArrByRation(treeNode.data.ID); } else if (treeNode.sourceType === this.project.Bills.getSourceType()) { let rations = this.project.Ration.getBillsSortRation(treeNode.source.getID()); treeNode.data.gljList = this.project.ration_glj.getGatherGljArrByRations(rations); }; this.calc.calculate(treeNode); // 存储、刷新本结点、所有父结点 if (treeNode.changed) { me.saveAndCalcParents(treeNode); delete treeNode.changed; }; }; saveAndCalcParents(treeNode) { if (treeNode.parent) { projectObj.converseCalculateBills(treeNode.parent); }; let data = {ID: treeNode.data.ID, projectID: projectObj.project.ID(), fees: treeNode.data.fees}; let newDta = {'updateType': 'ut_update', 'updateData': data}; let newDataArr = []; newDataArr.push(newDta); projectObj.project.pushNow('', treeNode.sourceType, newDataArr); projectObj.mainController.refreshTreeNode([treeNode]); }; initFees(treeNode){ if (!treeNode.data.fees) { treeNode.data.fees = []; treeNode.data.feesIndex = {}; treeNode.changed = true; }; }; checkFee(treeNode, ftObj){ if (!treeNode.data.feesIndex[ftObj.fieldName]){ let fee = { 'fieldName': ftObj.fieldName, 'unitFee': ftObj.unitFee, 'totalFee': ftObj.totalFee, 'tenderUnitFee': 0, 'tenderTotalFee': 0 }; treeNode.data.fees.push(fee); treeNode.data.feesIndex[ftObj.fieldName] = fee; treeNode.changed = true; } else{ if (treeNode.data.feesIndex[ftObj.fieldName].unitFee != ftObj.unitFee){ treeNode.data.feesIndex[ftObj.fieldName].unitFee = ftObj.unitFee; treeNode.changed = true; }; if (treeNode.data.feesIndex[ftObj.fieldName].totalFee != ftObj.totalFee){ treeNode.data.feesIndex[ftObj.fieldName].totalFee = ftObj.totalFee; treeNode.changed = true; }; }; }; gatherFeeTypes(treeNode, gatherType){ let me = this; let rst = []; if (treeNode.sourceType === this.project.Bills.getSourceType()) { me.initFees(treeNode); let objsArr = []; if (gatherType == CP_GatherType.rations){ objsArr = this.project.Ration.getRationsByNode(treeNode); }else if (gatherType == CP_GatherType.bills){ objsArr = treeNode.children; }; for (let ft of feeType) { let ftObj = {}; ftObj.fieldName = ft.type; ftObj.name = ft.name; let uf = 0, tf = 0, tuf = 0, ttf = 0; for (let item of objsArr) { let data = {}; if (gatherType == CP_GatherType.rations){ data = item; }else if (gatherType == CP_GatherType.bills){ data = item.data; }; if (data.feesIndex && data.feesIndex[ft.type]) { uf = (uf + parseFloat(data.feesIndex[ft.type].unitFee)).toDecimal(me.digitDefault); tf = (tf + parseFloat(data.feesIndex[ft.type].totalFee)).toDecimal(me.digitDefault); tuf = (tuf + parseFloat(data.feesIndex[ft.type].tenderUnitFee)).toDecimal(me.digitDefault); ttf = (ttf + parseFloat(data.feesIndex[ft.type].tenderTotalFee)).toDecimal(me.digitDefault); }; }; ftObj.unitFee = uf.toDecimal(me.digit); ftObj.totalFee = tf.toDecimal(me.digit); ftObj.tenderUnitFee = tuf.toDecimal(me.digit); ftObj.tenderTotalFee = ttf.toDecimal(me.digit); me.checkFee(treeNode, ftObj); rst.push(ftObj); }; if (treeNode.changed) { me.saveAndCalcParents(treeNode); delete treeNode.changed; }; }; return rst; }; calcDefaultBillTemp(treeNode, totalPrice){ let me = this; let rst = []; if (treeNode.sourceType != this.project.Bills.getSourceType()){return rst}; me.initFees(treeNode); for (let item of defaultBillTemplate) { let num = totalPrice; item.dispExprUser = item.dispExpr; item.displayFieldName = me.calc.compiledFeeTypes[item.fieldName]; if (item.feeRate) item.unitFee = (totalPrice * item.feeRate * 0.01).toDecimal(me.digit) else item.unitFee = 0; let quantity = treeNode.data.quantity; if (!quantity) quantity = 0; item.totalFee = (item.unitFee * quantity).toDecimal(me.digit); item.tenderUnitFee = 0; item.tenderTotalFee = 0; me.checkFee(treeNode, item); }; if (treeNode.changed) { me.saveAndCalcParents(treeNode); delete treeNode.changed; }; rst = defaultBillTemplate; return rst; }; getCalcDatas(treeNode){ let me = this; let rst = []; let isRation = treeNode.sourceType === me.project.Ration.getSourceType(); let isBill = treeNode.sourceType === me.project.Bills.getSourceType(); let isLeafBill = isBill && treeNode.source.children && treeNode.source.children.length === 0; let isBillPriceCalc = me.project.projSetting.billsCalcMode === billsPrice; if (isRation) { // 清单单价计算模式下的叶子清单:取自己的计算程序ID,找到自己的计算程序计算。 me.calculate(treeNode); rst = treeNode.data.calcTemplate.calcItems; } else if (isLeafBill) { let ct = ''; if (treeNode.children && treeNode.children.length > 0){ if (treeNode.children[0].sourceType == me.project.Ration.getSourceType()){ ct = childrenType.ration; } else if (treeNode.children[0].sourceType == me.project.VolumePrice.getSourceType()){ ct = childrenType.volumePrice; }; } else{ ct = childrenType.formula; }; if (ct == childrenType.ration){ if (isBillPriceCalc){ // 清单单价计算模式下的叶子清单:取自己的计算程序ID,找到自己的计算程序计算。 me.calculate(treeNode); rst = treeNode.data.calcTemplate.calcItems; }else{ // 前三种计算模式下的叶子清单:汇总定额的计算程序的费用类别 rst = me.gatherFeeTypes(treeNode, CP_GatherType.rations); }; } else if (ct == childrenType.volumePrice){ let totalPrice = 10000; rst = me.calcDefaultBillTemp(treeNode, totalPrice); } else if (ct == childrenType.formula){ let totalPrice = 20000; rst = me.calcDefaultBillTemp(treeNode, totalPrice); }; } else if (isBill){ // 父清单:汇总子清单的费用类别 rst = me.gatherFeeTypes(treeNode, CP_GatherType.bills); }; return rst; } }