瀏覽代碼

清单手工综合单价计算。

Chenshilong 7 年之前
父節點
當前提交
49f484e66d

+ 5 - 0
public/web/common_util.js

@@ -13,3 +13,8 @@ String.prototype.hasSubStr = function (str) {
     return this.toLowerCase().indexOf(str.toLowerCase()) > -1;
 };
 
+// 树结点计算时,取费会出现值为NaN的情况,导致往父节点汇总(递归相加)会出现错误。
+function parseFloatPlus(value){
+    let rst = parseFloat(value);
+    return  isNaN(rst) ? 0 : rst;
+};

+ 1 - 1
web/building_saas/main/js/controllers/project_controller.js

@@ -63,7 +63,7 @@ ProjectController = {
                     newSource = project.Ration.insertStdRation(selected.source.getID(), null, std);
                     project.ration_glj.addRationGLJ(newSource,std);
                 } else {
-                    newSource = project.Ration.insertRation(selected.source.getID());
+                    newSource = project.Ration.insertRation(selected.source.getID(),null, rationType);
                 }
 
                 newNode = project.mainTree.insert(selected.getID(), selected.tree.rootID());

+ 1 - 15
web/building_saas/main/js/models/bills.js

@@ -244,21 +244,7 @@ var Bills = {
             calcFees.setFee(node.data, field, newValue);
             let updateData = [];
             let data = {'ID': node.getID(), 'projectID': this.project.ID()};
-            if (field === 'quantity') {
-                data[field] = newValue;
-                data.isFromDetail=0;
-                // to do Calculate
-                if (node.data.fees) {
-                    data.fees = node.data.fees;
-                }
-            } else if (field === 'feesIndex.common.unitFee') {
-                // to do Calculate
-                if (node.data.fees) {
-                    data.fees = node.data.fees;
-                }
-            } else {
-                data[field] = newValue;
-            }
+            data[field] = newValue;
             updateData.push({'updateType': 'ut_update', 'updateData': tools.formatBillsUpdateData(data)});
             this.project.pushNow('updateBills', this.getSourceType(), updateData);
         };

+ 62 - 15
web/building_saas/main/js/models/calc_program.js

@@ -6,7 +6,7 @@
  *  用到费率的规则必须有feeRateID属性,当有该属性时,会自动显示费率值。
  */
 
-let defaultBillTemplate = {
+/*let defaultBillTemplate = {
     ID: 15,
     name: "清单公式",
     calcItems: [
@@ -98,7 +98,7 @@ let defaultBillTemplate = {
             memo: ''
         }
     ]
-};
+};*/
 
 const baseCalcType = {baseCalc: 0, adjustCalc: 1, budgetCalc: 2, diffCalc: 3,  offerCalc: 4};
 
@@ -434,7 +434,7 @@ class CalcProgram {
         me.calcBases = rationCalcBase;
         me.templates = this.project.calcProgram.datas.templates;
 
-        me.templates.push(defaultBillTemplate);
+        // me.templates.push(defaultBillTemplate);
         // 先编译公用的基础数据
         me.compilePublics();
         for (let t of me.templates){
@@ -595,7 +595,30 @@ class CalcProgram {
                treeNode.source.children.length === 0;
     };
 
-    // 仅内部调用。注意:外部不能直接使用,因为这里传入的树节点必须有一定的初始化。
+    isNullBill(treeNode){
+        let me = this;
+        return me.isLeafBill(treeNode) && (treeNode.children.length ===0) && (!treeNode.data.calcBase);
+    };
+
+    initFeeField(treeNode, fieldName){
+        if (!treeNode.data.fees) {
+            treeNode.data.fees = [];
+            treeNode.data.feesIndex = {};
+        };
+        if (!treeNode.data.feesIndex[fieldName]) {
+            let fee = {
+                'fieldName': fieldName,
+                'unitFee': 0,
+                'totalFee': 0,
+                'tenderUnitFee': 0,
+                'tenderTotalFee': 0
+            };
+            treeNode.data.fees.push(fee);
+            treeNode.data.feesIndex[fieldName] = fee;
+        };
+    };
+
+  // 仅内部调用。注意:外部不能直接使用,因为这里传入的树节点必须有一定的初始化。
     InnerCalc(treeNode){
         let me = this;
         let project = me.project;
@@ -657,10 +680,10 @@ class CalcProgram {
                     for (let item of objsArr) {
                         let data = item.data;
                         if (data.feesIndex && data.feesIndex[ft.type]) {
-                            buf = (buf + parseFloat(data.feesIndex[ft.type].unitFee)).toDecimal(decimalObj.process);
-                            btf = (btf + parseFloat(data.feesIndex[ft.type].totalFee)).toDecimal(decimalObj.process);
-                            btuf = (btuf + parseFloat(data.feesIndex[ft.type].tenderUnitFee)).toDecimal(decimalObj.process);
-                            bttf = (bttf + parseFloat(data.feesIndex[ft.type].tenderTotalFee)).toDecimal(decimalObj.process);
+                            buf = (buf + parseFloatPlus(data.feesIndex[ft.type].unitFee)).toDecimal(decimalObj.process);
+                            btf = (btf + parseFloatPlus(data.feesIndex[ft.type].totalFee)).toDecimal(decimalObj.process);
+                            btuf = (btuf + parseFloatPlus(data.feesIndex[ft.type].tenderUnitFee)).toDecimal(decimalObj.process);
+                            bttf = (bttf + parseFloatPlus(data.feesIndex[ft.type].tenderTotalFee)).toDecimal(decimalObj.process);
                         };
                     };
                 }
@@ -712,14 +735,35 @@ class CalcProgram {
             };
             treeNode.data.calcTemplate = {"calcItems": rst};
         }
+        else if (treeNode.calcType == treeNodeCalcType.ctCommonUnitFee){
+            delete treeNode.data.gljList;
+            if (treeNode.data.calcBase) treeNode.data.calcBase = null;  // 不能直接删除该属性,否则无法冲掉库中已存储的值
+            if (treeNode.data.programID) treeNode.data.programID = null;
+
+            let uf = (treeNode.data.feesIndex && treeNode.data.feesIndex.common && treeNode.data.feesIndex.common.unitFee) ? treeNode.data.feesIndex.common.unitFee : 0;
+            let tuf = (treeNode.data.feesIndex && treeNode.data.feesIndex.common && treeNode.data.feesIndex.common.tenderUnitFee) ? treeNode.data.feesIndex.common.tenderUnitFee : 0;
+            let q = treeNode.data.quantity ? treeNode.data.quantity : 0;
+            let tf = (uf * q).toDecimal(decimalObj.decimal('totalPrice', treeNode));
+            let ttf = (tuf * q).toDecimal(decimalObj.decimal('totalPrice', treeNode));
+
+            delete treeNode.data.fees;    // 直接删掉再新增,不用一个个费判断更新,效率更高。
+            delete treeNode.data.feesIndex;
+            me.initFeeField(treeNode, 'common');
+            treeNode.data.feesIndex.common.unitFee = uf;
+            treeNode.data.feesIndex.common.totalFee = tf;
+            treeNode.data.feesIndex.common.tenderUnitFee = tuf;
+            treeNode.data.feesIndex.common.tenderTotalFee = ttf;
+
+            treeNode.data.calcTemplate = {"calcItems": []};
+        }
         else{
             // 叶子清单的公式计算:使用缺省清单计算程序。需要提供总金额作为计算基数(不需要工料机),然后每条按比例(费率)计算,不需要工料机明细。
             if (treeNode.calcType == treeNodeCalcType.ctCalcBaseValue){
                 delete treeNode.data.gljList;
 
-                if (treeNode.data.programID == undefined){
+/*                if (treeNode.data.programID == undefined){
                     treeNode.data.programID = defaultBillTemplate.ID;
-                };
+                };*/
             }
             else if (treeNode.calcType == treeNodeCalcType.ctRationCalcProgram) {
                 if (treeNode.data.type == rationType.volumePrice){
@@ -743,7 +787,8 @@ class CalcProgram {
                 let rations = project.Ration.getBillsSortRation(treeNode.source.getID());
                 treeNode.data.gljList = project.ration_glj.getGatherGljArrByRations(rations);
 
-                if (treeNode.data.programID == undefined || treeNode.data.programID == defaultBillTemplate.ID){
+                // if (treeNode.data.programID == undefined || treeNode.data.programID == defaultBillTemplate.ID){
+                if (treeNode.data.programID == undefined){
                     treeNode.data.programID = projectInfoObj.projectInfo.property.engineering;
                 }
             };
@@ -781,17 +826,19 @@ class CalcProgram {
         let me = this;
         let isRation = treeNode.sourceType === me.project.Ration.getSourceType();
         let isBill = treeNode.sourceType === me.project.Bills.getSourceType();
-        let isBillPriceCalc = me.project.projSetting.billsCalcMode === leafBillGetFeeType.billsPrice;
-        let isLeafBill = me.isLeafBill(treeNode);
 
         if (isRation){
             treeNode.calcType = treeNodeCalcType.ctRationCalcProgram;
         }
-        else if (isLeafBill) {
+        else  if (me.isNullBill(treeNode)){
+            treeNode.calcType = treeNodeCalcType.ctCommonUnitFee;
+        }
+        else if (me.isLeafBill(treeNode)) {
             if (treeNode.children && treeNode.children.length > 0){
                 // me.calcLeafBillChildren(treeNode);
 
-                if (isBillPriceCalc)                        // 清单单价计算模式下的叶子清单:取自己的计算程序ID,找到自己的计算程序计算。(汇总清单所有定额的工料机)
+                // 清单单价计算模式下的叶子清单:取自己的计算程序ID,找到自己的计算程序计算。(汇总清单所有定额的工料机)
+                if (me.project.projSetting.billsCalcMode === leafBillGetFeeType.billsPrice)
                     treeNode.calcType = treeNodeCalcType.ctBillCalcProgram;
                 else                                        // 前三种计算模式下的叶子清单:汇总定额的计算程序的费用类别
                     treeNode.calcType = treeNodeCalcType.ctGatherRationsFees;

+ 2 - 1
web/building_saas/main/js/models/main_consts.js

@@ -72,7 +72,8 @@ const treeNodeCalcType = {
     ctBillCalcProgram: 2,       // 汇总清单下所有定额的工料机
     ctGatherRationsFees: 3,     // 汇总定额的各个费
     ctGatherBillsFees: 4,       // 汇总清单的各个费
-    ctCalcBaseValue: 5
+    ctCalcBaseValue: 5,
+    ctCommonUnitFee: 6
 };
 
 const calcAllType = {

+ 4 - 1
web/building_saas/main/js/views/main_tree_col.js

@@ -30,10 +30,10 @@ let MainTreeCol = {
         }
     },
     readOnly: {
+        // CSL, 2017-11-28
         subType: function (node){
             return (node.data.type != 2 && node.data.type != 3);
         },
-        // CSL, 2017-11-28
         calcProgramName: function (node) {
             if (
                 node.sourceType === projectObj.project.Ration.getSourceType() ||
@@ -41,6 +41,9 @@ let MainTreeCol = {
             ) return false
             else return true;
         },
+        commonUnitFee: function(node){
+            return !projectObj.project.calcProgram.isNullBill(node);
+        },
 
         bills: function (node) {
             return node.sourceType === projectObj.project.Bills.getSourceType();

+ 13 - 6
web/building_saas/main/js/views/project_view.js

@@ -119,7 +119,7 @@ var projectObj = {
         return value;
     },
     checkSpreadEditingText: function (editingText, colSetting) {
-        if (colSetting.data.field === 'quantity' || colSetting.data.field === 'feesIndex.common.unitFee') {
+        if (colSetting.data.field === 'quantity') {
             return this.checkFormulaValidField(editingText, colSetting);
         }
         else if (colSetting.data.field === 'programID') {
@@ -273,9 +273,10 @@ var projectObj = {
             else if(fieldName ==='feeRate'){
                 project.FeeRate.updateFeeRateFromBills(value,node,fieldName);
             }
-            else if (fieldName === 'quantity' || fieldName === 'marketUnitFee' || fieldName === 'programID' || fieldName === 'subType' || fieldName === 'calcBase'){
+            else if (fieldName === 'quantity' || fieldName === 'marketUnitFee' || fieldName === 'programID' ||
+                fieldName === 'subType' || fieldName === 'calcBase' || fieldName === 'feesIndex.common.unitFee'){
                 if (fieldName === 'quantity') {
-                    if (value) {value = value.toDecimal(decimalObj.decimal(fieldName,node))};
+                   if (value) {value = value.toDecimal(decimalObj.decimal(fieldName,node))};
                    if(project.quantity_detail.quantityEditChecking(value,node,fieldName)){
                        node.data.isFromDetail=0;
                        project.quantity_detail.cleanQuantityDetail(node,true);
@@ -283,14 +284,20 @@ var projectObj = {
                        projectObj.mainController.refreshTreeNode([node]);
                        return;
                    }
-                } else if (fieldName === 'marketUnitFee') {
+                }
+                else if (fieldName === 'marketUnitFee' || fieldName === 'feesIndex.common.unitFee') {
                     if (value) {value = parseFloat(value).toDecimal(decimalObj.decimal("unitPrice", node))};
-                } else if (fieldName === 'calcBase') {
+                }
+                else if (fieldName === 'calcBase') {
                     if (value) {value = parseFloat(value).toDecimal(decimalObj.decimal("totalPrice", node))};
                 };
 
                 node.changed = true;
-                node.data[fieldName] = value;
+                if (fieldName == 'feesIndex.common.unitFee'){
+                    project.calcProgram.initFeeField(node, 'common');
+                    node.data.feesIndex.common.unitFee = value;
+                }
+                else node.data[fieldName] = value;
                 project.calcProgram.calculate(node);
                 project.calcProgram.saveNode(node);
             }