|
@@ -1,5 +1,6 @@
|
|
|
/**
|
|
|
* Created by CSL on 2017-07-19.
|
|
|
+ * 计算程序。所有定额、清单、父清单的计算都从此入。
|
|
|
* dispExpr: F8*(L-1); expression: "@('8') * (L-1)";
|
|
|
* 说明:F后跟行号,L替换人工系数值,@后跟ID。用到L的规则必须有labourCoeID属性(反过来不要求),
|
|
|
* 用到费率的规则必须有feeRateID属性,当有该属性时,会自动显示费率值。
|
|
@@ -99,14 +100,232 @@ let defaultBillTemplate = {
|
|
|
]
|
|
|
};
|
|
|
|
|
|
+let analyzer = {
|
|
|
+ calcTemplate: null,
|
|
|
+ success: true,
|
|
|
|
|
|
+ standard: function(expr){
|
|
|
+ let str = expr;
|
|
|
+ str = str.replace(/\s/g, ""); // 去空格、去中文空格
|
|
|
+ str = str.replace(/(/g, "("); // 中文括号"("换成英文括号"("
|
|
|
+ str = str.replace(/)/g, ")"); // 中文括号")"换成英文括号")"
|
|
|
+ str = str.replace(/f/g, "F"); // f换成F
|
|
|
+ return str;
|
|
|
+ },
|
|
|
+
|
|
|
+ analyzeCalcBase: function(expr){
|
|
|
+ // 前提:必须无空格、无特殊符号
|
|
|
+ function getCalcBase(expr){
|
|
|
+ let base = '',
|
|
|
+ iPos1 = -1, iPos2 = -1;
|
|
|
+ for (let i = 0; i < expr.length; i++) {
|
|
|
+ if (expr[i] === '['){
|
|
|
+ iPos1 = i;
|
|
|
+ }
|
|
|
+ else if (iPos1 != -1 && expr[i]===']'){
|
|
|
+ iPos2 = i;
|
|
|
+ };
|
|
|
+
|
|
|
+ if (iPos1 != -1 && iPos2 != -1){
|
|
|
+ base = expr.slice(iPos1, iPos2 + 1);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ };
|
|
|
+ return base;
|
|
|
+ };
|
|
|
+ function calcBaseToIDExpr(base){
|
|
|
+ /*// for test. 公路模式,基数到ID
|
|
|
+ let id = -1;
|
|
|
+ if (base == '[人工费]'){
|
|
|
+ id = 111;
|
|
|
+ }
|
|
|
+ else if (base == '[材料费]'){
|
|
|
+ id = 222;
|
|
|
+ }
|
|
|
+ else if (base == '[机械费]'){
|
|
|
+ id = 333;
|
|
|
+ }
|
|
|
+ else id = "错误";
|
|
|
+
|
|
|
+ return "@('" + id + "')";*/
|
|
|
+ let baseValue = base.slice(1, -1);
|
|
|
+ return "base('" + baseValue + "')";
|
|
|
+ };
|
|
|
+
|
|
|
+ while (expr.indexOf('[') > 0) {
|
|
|
+ let base = getCalcBase(expr);
|
|
|
+ let id = calcBaseToIDExpr(base);
|
|
|
+ let baseValue = base.slice(1, -1); // []会给下面的正则带来干扰,这里去掉
|
|
|
+ var pattBase =new RegExp(baseValue, "g");
|
|
|
+ expr = expr.replace(pattBase, id);
|
|
|
+ expr = expr.replace(/\[base\('/g, "base('"); // [@(' [base('
|
|
|
+ expr = expr.replace(/'\)\]/g, "')"); // ')]
|
|
|
+ };
|
|
|
+
|
|
|
+ return expr;
|
|
|
+ },
|
|
|
+
|
|
|
+ analyzeLineRef: function(expr){
|
|
|
+ let me = this;
|
|
|
+ function isOperator(char){
|
|
|
+ var operator = "+-*/()";
|
|
|
+ return operator.indexOf(char) > -1;
|
|
|
+ };
|
|
|
+ function lineNumToID(lineNum){
|
|
|
+ if (lineNum > me.calcTemplate.calcItems.length){
|
|
|
+ me.success = false;
|
|
|
+ return '越界';
|
|
|
+ }
|
|
|
+ else{
|
|
|
+ let id = me.calcTemplate.calcItems[lineNum - 1].ID;
|
|
|
+ return id;
|
|
|
+ }
|
|
|
+ };
|
|
|
+ // 前提:必须无空格、无特殊符号、标准大写F
|
|
|
+ function getSection(expr){
|
|
|
+ let section = '',
|
|
|
+ iPos1 = -1, iPos2 = -1;
|
|
|
+ for (let i = 0; i < expr.length; i++) {
|
|
|
+ if (expr[i] === 'F'){
|
|
|
+ iPos1 = i;
|
|
|
+ }
|
|
|
+ else if (iPos1 != -1 && isOperator(expr[i])){
|
|
|
+ iPos2 = i;
|
|
|
+ }
|
|
|
+ else if (iPos1 != -1 && i == expr.length - 1){
|
|
|
+ iPos2 = i + 1;
|
|
|
+
|
|
|
+ };
|
|
|
+ if (iPos1 != -1 && iPos2 != -1){
|
|
|
+ section = expr.slice(iPos1, iPos2);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ };
|
|
|
+ return section;
|
|
|
+ };
|
|
|
+ function sectionToIDExpr(section){
|
|
|
+ if (section){
|
|
|
+ let lineNum = section.slice(1);
|
|
|
+ if (isNaN(lineNum)){
|
|
|
+ me.success = false;
|
|
|
+ return '错误'; // 这里的返回提示不能加上section,因为会无限循环
|
|
|
+ }
|
|
|
+ else
|
|
|
+ return "@('" + lineNumToID(lineNum) + "')";
|
|
|
+ }
|
|
|
+ else return '';
|
|
|
+ };
|
|
|
+
|
|
|
+ while (expr.indexOf('F') > 0) {
|
|
|
+ let sec = getSection(expr);
|
|
|
+ let id = sectionToIDExpr(sec);
|
|
|
+ var pattSec =new RegExp(sec, "g");
|
|
|
+ expr = expr.replace(pattSec, id);
|
|
|
+ };
|
|
|
+ return expr;
|
|
|
+ },
|
|
|
+
|
|
|
+ analyzeUserExpr: function(calcTemplate, calcItem){
|
|
|
+ let me = this;
|
|
|
+ me.calcTemplate = calcTemplate;
|
|
|
+ let expr = calcItem.dispExpr;
|
|
|
+ // 标准化:处理特殊字符、中文符号、大小写
|
|
|
+ expr = me.standard(expr);
|
|
|
+ calcItem.dispExpr = expr;
|
|
|
+ // 先换掉计算基数
|
|
|
+ expr = me.analyzeCalcBase(expr);
|
|
|
+ // 再换掉行引用
|
|
|
+ expr = me.analyzeLineRef(expr);
|
|
|
+ calcItem.expression = expr;
|
|
|
+ return me.success;
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+let executeObj = {
|
|
|
+ treeNode: null,
|
|
|
+ template: null,
|
|
|
+ calcBase: null,
|
|
|
+
|
|
|
+ at: function(ID) {
|
|
|
+ let me = executeObj,
|
|
|
+ rst = 0;
|
|
|
+ rst = me.template.compiledCalcItems[ID].unitFee;
|
|
|
+ rst = parseFloat(rst);
|
|
|
+ return rst;
|
|
|
+ },
|
|
|
+ base: function(calcBaseName) {
|
|
|
+ let me = executeObj, rst = 0,
|
|
|
+ //base = getRationCalcBase(calcBaseName);
|
|
|
+ base = me.calcBase[calcBaseName];
|
|
|
+
|
|
|
+ if (base != null) {
|
|
|
+ let price = 0, aprice = 0, mprice = 0, tmpSum = 0, mdSum = 0;
|
|
|
+
|
|
|
+ function isSubset(sub, arr){
|
|
|
+ // if(!(sub instanceof Array) || !(arr instanceof Array)) return false;
|
|
|
+ // if(sub.length > arr.length) return false;
|
|
|
+ for(var i = 0, len = sub.length; i < len; i++){
|
|
|
+ if(arr.indexOf(sub[i]) == -1) return false;
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 机上人工费:多一层
|
|
|
+ if (isSubset(base.gljTypes, [gljType.MACHINE_LABOUR])) {
|
|
|
+ for (let glj of me.treeNode.data.gljList) {
|
|
|
+ if (glj.type == gljType.GENERAL_MACHINE) {
|
|
|
+ // 获取机械组成物
|
|
|
+ let mds = projectObj.project.composition.getCompositionByCode(glj.code);
|
|
|
+ if (!mds) mds = [];
|
|
|
+ for (let md of mds){
|
|
|
+ if (base.gljTypes.indexOf(md.glj_type) >= 0) {
|
|
|
+ price = md["base_price"];
|
|
|
+ if (!price) price = 0;
|
|
|
+ mdSum = mdSum + (md["consumption"] * price).toDecimal(me.digit);
|
|
|
+ mdSum = (mdSum).toDecimal(me.digitDefault);
|
|
|
+ }
|
|
|
+ };
|
|
|
+ tmpSum = tmpSum + (glj["quantity"] * mdSum).toDecimal(me.digitDefault);
|
|
|
+ tmpSum = (tmpSum).toDecimal(me.digitDefault);
|
|
|
+ }
|
|
|
+ };
|
|
|
+ }else{
|
|
|
+ for (let glj of me.treeNode.data.gljList) {
|
|
|
+ if (base.gljTypes.indexOf(glj.type) >= 0) {
|
|
|
+ if (base.calcType == baseCalc){ price = glj["basePrice"];}
|
|
|
+ else if (base.calcType == adjustCalc){price = glj["adjustPrice"];}
|
|
|
+ else if (base.calcType == budgetCalc){price = glj["marketPrice"];}
|
|
|
+ else if (base.calcType == diffCalc){
|
|
|
+ aprice = glj["adjustPrice"];
|
|
|
+ if (!aprice) aprice = 0;
|
|
|
+ mprice = glj["marketPrice"];
|
|
|
+ if (!mprice) mprice = 0;
|
|
|
+ price = mprice - aprice;
|
|
|
+ };
|
|
|
+ if (!price) price = 0;
|
|
|
+ tmpSum = tmpSum + (glj["quantity"] * price).toDecimal(me.digitDefault);
|
|
|
+ tmpSum = (tmpSum).toDecimal(me.digitDefault);
|
|
|
+ };
|
|
|
+ };
|
|
|
+ };
|
|
|
+
|
|
|
+ rst = (tmpSum).toDecimal(me.digitDefault);
|
|
|
+ };
|
|
|
+
|
|
|
+ return rst;
|
|
|
+ },
|
|
|
+ HJ: function () {
|
|
|
+ let me = this;
|
|
|
+ return me.treeNode.calcBaseValue;
|
|
|
+ }
|
|
|
+};
|
|
|
|
|
|
class CalcProgram {
|
|
|
constructor(project){
|
|
|
- this.project = project;
|
|
|
- this.datas = [];
|
|
|
- this.calc = new Calculation();
|
|
|
- project.registerModule(ModuleNames.calc_program, this);
|
|
|
+ let me = this;
|
|
|
+ me.project = project;
|
|
|
+ me.datas = [];
|
|
|
+ project.registerModule(ModuleNames.calc_program, me);
|
|
|
};
|
|
|
|
|
|
getSourceType () {
|
|
@@ -125,27 +344,298 @@ class CalcProgram {
|
|
|
|
|
|
// 经测试,全部编译一次耗时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;
|
|
|
- calcTemplates.push(defaultBillTemplate);
|
|
|
+ let me = this;
|
|
|
+ me.digit = 2;
|
|
|
+ me.digitDefault = 6;
|
|
|
+
|
|
|
+ me.compiledFeeRates = {};
|
|
|
+ me.compiledLabourCoes = {};
|
|
|
+ me.compiledTemplates = {};
|
|
|
+ me.compiledFeeTypes = {};
|
|
|
+ me.compiledFeeTypeNames = [];
|
|
|
+ me.compiledCalcBases = {};
|
|
|
+ me.saveForReports = [];
|
|
|
|
|
|
- this.calc.compilePublics(calcFeeRates, calcLabourCoes, feeType, rationCalcBase);
|
|
|
- for (let ct of calcTemplates){
|
|
|
- this.calc.compileTemplate(ct);
|
|
|
+ me.feeRates = this.project.FeeRate.datas.rates;
|
|
|
+ me.labourCoes = this.project.labourCoe.datas.coes;
|
|
|
+ me.feeTypes = feeType;
|
|
|
+ me.calcBases = rationCalcBase;
|
|
|
+ me.templates = this.project.calcProgram.datas.templates;
|
|
|
+
|
|
|
+ me.templates.push(defaultBillTemplate);
|
|
|
+ // 先编译公用的基础数据
|
|
|
+ me.compilePublics();
|
|
|
+ for (let t of me.templates){
|
|
|
+ me.compileTemplate(t);
|
|
|
};
|
|
|
|
|
|
// 存储费率临时数据,报表用。
|
|
|
- if (this.calc.saveForReports.length > 0){
|
|
|
+ if (me.saveForReports.length > 0){
|
|
|
let saveDatas = {};
|
|
|
saveDatas.projectID = projectInfoObj.projectInfo.ID;
|
|
|
- saveDatas.calcItems = this.calc.saveForReports;
|
|
|
+ saveDatas.calcItems = me.saveForReports;
|
|
|
CommonAjax.post('/calcProgram/saveCalcItems', saveDatas, function (data) {
|
|
|
- this.calc.saveForReports = [];
|
|
|
+ me.saveForReports = [];
|
|
|
});
|
|
|
};
|
|
|
};
|
|
|
|
|
|
+ compilePublics(){
|
|
|
+ let me = this;
|
|
|
+ for (let rate of me.feeRates) {
|
|
|
+ me.compiledFeeRates[rate.ID] = rate;
|
|
|
+ }
|
|
|
+
|
|
|
+ for (let coe of me.labourCoes) {
|
|
|
+ me.compiledLabourCoes[coe.ID] = coe;
|
|
|
+ }
|
|
|
+
|
|
|
+ for (let ft of me.feeTypes) {
|
|
|
+ me.compiledFeeTypes[ft.type] = ft.name;
|
|
|
+ me.compiledFeeTypes[ft.name] = ft.type; // 中文预编译,可靠性有待验证
|
|
|
+ me.compiledFeeTypeNames.push(ft.name);
|
|
|
+ }
|
|
|
+
|
|
|
+ for (let cb of me.calcBases) {
|
|
|
+ me.compiledCalcBases[cb.dispName] = cb; // 中文预编译,可靠性有待验证
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ compileTemplate(template){
|
|
|
+ let me = this;
|
|
|
+ me.compiledTemplates[template.ID] = template;
|
|
|
+ template.hasCompiled = false;
|
|
|
+ template.errs = [];
|
|
|
+
|
|
|
+ let private_extract_ID = function(str, idx){
|
|
|
+ let rst = '', lBracket = 0, rBracket = 0, firstIdx = idx, lastIdx = 0;
|
|
|
+ for (let i = idx; i < str.length; i++) {
|
|
|
+ if (str[i] === '(') {
|
|
|
+ lBracket++;
|
|
|
+ if (lBracket == 1) firstIdx = i + 1;
|
|
|
+ }
|
|
|
+ if (str[i] === ')') {
|
|
|
+ rBracket++;
|
|
|
+ if (lBracket == rBracket) {
|
|
|
+ lastIdx = i - 1;
|
|
|
+ if (lastIdx > firstIdx) {
|
|
|
+ if (str[firstIdx] === "'") firstIdx++;
|
|
|
+ if (str[lastIdx] !== "'") lastIdx++;
|
|
|
+ if (lastIdx > firstIdx) {
|
|
|
+ rst = str.slice(firstIdx, lastIdx);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return rst;
|
|
|
+ };
|
|
|
+ let private_parse_ref = function(item, itemIdx){
|
|
|
+ let idx = item.expression.indexOf('@(', 0);
|
|
|
+ while (idx >= 0) {
|
|
|
+ let ID = private_extract_ID(item.expression, idx);
|
|
|
+ if (ID.length > 0) {
|
|
|
+ let subItem = template.compiledCalcItems[ID];
|
|
|
+ if (subItem) {
|
|
|
+ if (subItem.ID !== item.ID) {
|
|
|
+ private_parse_ref(subItem, template.compiledCalcItems[ID + "_idx"]);
|
|
|
+ } else {
|
|
|
+ template.errs.push("There exists the self refer ID: " + ID);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ template.errs.push("There exists the invalid ID by which could not find the item: " + ID);
|
|
|
+ console.log('invalid ID: ' + ID);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ idx = item.expression.indexOf('@(', idx + ID.length + 3);
|
|
|
+ }
|
|
|
+ if (template.compiledSeq.indexOf(itemIdx) < 0) {
|
|
|
+ template.compiledSeq.push(itemIdx);
|
|
|
+ }
|
|
|
+ };
|
|
|
+ let private_setup_seq = function(item, itemIdx){
|
|
|
+ if (template.compiledSeq.indexOf(itemIdx) < 0) {
|
|
|
+ private_parse_ref(item, itemIdx);
|
|
|
+ }
|
|
|
+ };
|
|
|
+ let private_compile_items = function() {
|
|
|
+ for (let idx of template.compiledSeq) {
|
|
|
+ let item = template.calcItems[idx];
|
|
|
+ item.dispExprUser = item.dispExpr; // 用于界面显示。disExpr是公式模板,不允许修改:人工系数占位符被修改后变成数值,第二次无法正确替换。
|
|
|
+ if (item.expression == 'HJ')
|
|
|
+ item.compiledExpr = '$CE.HJ()'
|
|
|
+ else{
|
|
|
+ item.compiledExpr = item.expression.split('@(').join('$CE.at(');
|
|
|
+ item.compiledExpr = item.compiledExpr.split('base(').join('$CE.base(');
|
|
|
+ };
|
|
|
+
|
|
|
+ if (item.labourCoeID){
|
|
|
+ let lc = me.compiledLabourCoes[item.labourCoeID].coe;
|
|
|
+ item.dispExprUser = item.dispExpr.replace(/L/gi, lc.toString());
|
|
|
+ item.compiledExpr = item.compiledExpr.replace(/L/gi, lc.toString());
|
|
|
+ };
|
|
|
+
|
|
|
+ if (item.feeRateID) {
|
|
|
+ let orgFeeRate = item.feeRate;
|
|
|
+ let cmf = me.compiledFeeRates[item.feeRateID];
|
|
|
+ item.feeRate = cmf?cmf.rate:100;
|
|
|
+
|
|
|
+ if (!orgFeeRate || (orgFeeRate && orgFeeRate != item.feeRate)){
|
|
|
+ me.saveForReports.push({templatesID: template.ID, calcItem: item});
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ // 字段名映射
|
|
|
+ item.displayFieldName = me.compiledFeeTypes[item.fieldName];
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ if (template && template.calcItems && template.calcItems.length > 0) {
|
|
|
+ template.compiledSeq = [];
|
|
|
+ template.compiledCalcItems = {};
|
|
|
+
|
|
|
+ for (let i = 0; i < template.calcItems.length; i++) {
|
|
|
+ let item = template.calcItems[i];
|
|
|
+ template.compiledCalcItems[item.ID] = item;
|
|
|
+ template.compiledCalcItems[item.ID + "_idx"] = i;
|
|
|
+ }
|
|
|
+
|
|
|
+ for (let i = 0; i < template.calcItems.length; i++) {
|
|
|
+ private_setup_seq(template.calcItems[i], i);
|
|
|
+ }
|
|
|
+ if (template.errs.length == 0) {
|
|
|
+ private_compile_items();
|
|
|
+ template.hasCompiled = true;
|
|
|
+ } else {
|
|
|
+ console.log('errors: ' + template.errs.toString());
|
|
|
+ }
|
|
|
+ };
|
|
|
+ };
|
|
|
+
|
|
|
+ // 内部调用,外部不能直接使用
|
|
|
+ InnerCalc(treeNode){
|
|
|
+ let me = this;
|
|
|
+ let project = me.project;
|
|
|
+
|
|
|
+ function initFees(treeNode){
|
|
|
+ if (!treeNode.data.fees) {
|
|
|
+ treeNode.data.fees = [];
|
|
|
+ treeNode.data.feesIndex = {};
|
|
|
+ treeNode.changed = true;
|
|
|
+ };
|
|
|
+ };
|
|
|
+
|
|
|
+ function checkFee(treeNode, feeObj){
|
|
|
+ if (feeObj.fieldName == '') return;
|
|
|
+
|
|
|
+ if (!treeNode.data.feesIndex[feeObj.fieldName]){
|
|
|
+ let fee = {
|
|
|
+ 'fieldName': feeObj.fieldName,
|
|
|
+ 'unitFee': feeObj.unitFee,
|
|
|
+ 'totalFee': feeObj.totalFee,
|
|
|
+ 'tenderUnitFee': 0,
|
|
|
+ 'tenderTotalFee': 0
|
|
|
+ };
|
|
|
+ treeNode.data.fees.push(fee);
|
|
|
+ treeNode.data.feesIndex[feeObj.fieldName] = fee;
|
|
|
+ treeNode.changed = true;
|
|
|
+ }
|
|
|
+ else{
|
|
|
+ if (treeNode.data.feesIndex[feeObj.fieldName].unitFee != feeObj.unitFee){
|
|
|
+ treeNode.data.feesIndex[feeObj.fieldName].unitFee = feeObj.unitFee;
|
|
|
+ treeNode.changed = true;
|
|
|
+ };
|
|
|
+
|
|
|
+ if (treeNode.data.feesIndex[feeObj.fieldName].totalFee != feeObj.totalFee){
|
|
|
+ treeNode.data.feesIndex[feeObj.fieldName].totalFee = feeObj.totalFee;
|
|
|
+ treeNode.changed = true;
|
|
|
+ };
|
|
|
+ };
|
|
|
+ };
|
|
|
+
|
|
|
+ // 汇总定额或子清单的费用类别
|
|
|
+ if (treeNode.calcType == treeNodeCalcType.ctGatherRations || treeNode.calcType == treeNodeCalcType.ctGatherBills){
|
|
|
+ initFees(treeNode);
|
|
|
+
|
|
|
+ let objsArr = (treeNode.calcType == treeNodeCalcType.ctGatherRations) ? project.Ration.getRationsByNode(treeNode) : treeNode.children;
|
|
|
+ let rst = [];
|
|
|
+ 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 = (treeNode.calcType == treeNodeCalcType.ctGatherRations) ? item : 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);
|
|
|
+
|
|
|
+ checkFee(treeNode, ftObj);
|
|
|
+
|
|
|
+ rst.push(ftObj);
|
|
|
+ };
|
|
|
+ treeNode.data.calcTemplate = {"calcItems": rst};
|
|
|
+ }
|
|
|
+ else{
|
|
|
+ // 叶子清单的缺省计算程序需要提供总金额作为计算基数(不需要工料机),然后每条按比例(费率)计算,不需要工料机明细。
|
|
|
+ if (treeNode.calcType == treeNodeCalcType.ctCalcBaseValue){
|
|
|
+ delete treeNode.data.gljList;
|
|
|
+
|
|
|
+ if (treeNode.data.programID == undefined){
|
|
|
+ treeNode.data.programID = defaultBillTemplate.ID;
|
|
|
+ };
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ if (treeNode.sourceType === project.Ration.getSourceType()) {
|
|
|
+ treeNode.data.gljList = project.ration_glj.getGljArrByRation(treeNode.data.ID);
|
|
|
+ }
|
|
|
+ else if (treeNode.sourceType === project.Bills.getSourceType()) {
|
|
|
+ let rations = project.Ration.getBillsSortRation(treeNode.source.getID());
|
|
|
+ treeNode.data.gljList = project.ration_glj.getGatherGljArrByRations(rations);
|
|
|
+ };
|
|
|
+
|
|
|
+ if (treeNode.data.programID == undefined){
|
|
|
+ treeNode.data.programID = 1;
|
|
|
+ };
|
|
|
+ };
|
|
|
+
|
|
|
+ let template = me.compiledTemplates[treeNode.data.programID];
|
|
|
+ treeNode.data.calcTemplate = template;
|
|
|
+
|
|
|
+ if (treeNode && template.hasCompiled) {
|
|
|
+ let $CE = executeObj;
|
|
|
+ $CE.treeNode = treeNode;
|
|
|
+ $CE.template = template;
|
|
|
+ $CE.calcBase = me.compiledCalcBases;
|
|
|
+
|
|
|
+ initFees(treeNode);
|
|
|
+
|
|
|
+ for (let idx of template.compiledSeq) {
|
|
|
+ let calcItem = template.calcItems[idx];
|
|
|
+
|
|
|
+ let feeRate = calcItem.feeRate;
|
|
|
+ if (!feeRate) feeRate = 100; // 100%
|
|
|
+ calcItem.unitFee = (eval(calcItem.compiledExpr) * feeRate * 0.01).toDecimal(me.digit); // 如果eval()对清单树有影响,就换成小麦的Expression对象再试
|
|
|
+
|
|
|
+ let quantity = treeNode.data.quantity;
|
|
|
+ if (!quantity) quantity = 0;
|
|
|
+ calcItem.totalFee = (calcItem.unitFee * quantity).toDecimal(me.digit);
|
|
|
+
|
|
|
+ checkFee(treeNode, calcItem);
|
|
|
+ };
|
|
|
+ }
|
|
|
+ };
|
|
|
+ }
|
|
|
+
|
|
|
// 计算本节点(默认同时递归计算所有父节点,可选)
|
|
|
calculate(treeNode, calcParents = true){
|
|
|
let me = this;
|
|
@@ -184,7 +674,7 @@ class CalcProgram {
|
|
|
else if (isBill) // 父清单:汇总子清单的费用类别
|
|
|
treeNode.calcType = treeNodeCalcType.ctGatherBills;
|
|
|
|
|
|
- me.calc.calculate(treeNode);
|
|
|
+ me.InnerCalc(treeNode);
|
|
|
|
|
|
// 计算所有父结点
|
|
|
if (treeNode.changed && calcParents && treeNode.parent) {
|
|
@@ -193,31 +683,30 @@ class CalcProgram {
|
|
|
};
|
|
|
|
|
|
// 存储、刷新本节点(默认存储刷新所有父节点,可选)
|
|
|
- saveNode(treeNode, saveParent = true) {
|
|
|
+ saveNode(treeNode, saveParents = true) {
|
|
|
if (!treeNode.changed) return;
|
|
|
-
|
|
|
+ let me = this;
|
|
|
let newDataArr = [], nodesArr = [];
|
|
|
- let project = projectObj.project;
|
|
|
|
|
|
- project.beginUpdate('');
|
|
|
+ me.project.beginUpdate('');
|
|
|
let curNode = treeNode;
|
|
|
while (curNode) {
|
|
|
if (curNode.changed){
|
|
|
let data = {
|
|
|
ID: curNode.data.ID,
|
|
|
- projectID: projectObj.project.ID(),
|
|
|
+ projectID: me.project.ID(),
|
|
|
quantity: curNode.data.quantity,
|
|
|
fees: curNode.data.fees
|
|
|
};
|
|
|
let newDta = {'updateType': 'ut_update', 'updateData': data};
|
|
|
newDataArr.push(newDta);
|
|
|
nodesArr.push(curNode);
|
|
|
- project.push(curNode.sourceType, newDataArr);
|
|
|
+ me.project.push(curNode.sourceType, newDataArr);
|
|
|
};
|
|
|
- if (saveParent) curNode = curNode.parent
|
|
|
+ if (saveParents) curNode = curNode.parent
|
|
|
else break;
|
|
|
};
|
|
|
- project.endUpdate();
|
|
|
+ me.project.endUpdate();
|
|
|
|
|
|
for (let node of nodesArr){delete node.changed;};
|
|
|
projectObj.mainController.refreshTreeNode(nodesArr);
|