Przeglądaj źródła

Merge branch 'master' of http://smartcost.f3322.net:3000/SmartCost/ConstructionCost

zhangweicheng 7 lat temu
rodzic
commit
1fff1a8b10

+ 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;
+};

+ 43 - 45
web/building_saas/main/html/main.html

@@ -37,42 +37,6 @@
             </div>
         </div>
         <%include ../../../common/html/header.html %>
-        <nav class="navbar navbar-expand-lg justify-content-between navbar-light p-0">
-            <ul class="nav navbar-nav px-1">
-                <li class="nav-item">
-                    <a class="nav-link" href="#" aria-expanded="false" data-toggle="modal" data-target="#poj-set"><i class="fa fa-cube"></i> 项目属性</a>
-                </li>
-                <li class="nav-item">
-                    <a class="nav-link" href="#" aria-expanded="false" data-toggle="modal" data-target="#opts-set"><i class="fa fa-sliders"></i> 选项</a>
-                    <!--<a class="nav-link" href="#" aria-haspopup="true" aria-expanded="false"><i class="fa fa-sliders"></i> 选项</a>-->
-                </li>
-                <li class="nav-item dropdown">
-                    <a class="nav-link dropdown-toggle" href="#" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><i class="fa fa-wrench"></i> 工具</a>
-                    <div class="dropdown-menu">
-                        <a class="dropdown-item" href="#">定额库编辑器</a>
-                        <a class="dropdown-item" href="/complementaryGlj">工料机库编辑器</a>
-                    </div>
-                </li>
-                <li class="nav-item dropdown">
-                    <a class="nav-link dropdown-toggle" href="#" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><i class="fa fa-question-circle-o"></i> 帮助</a>
-                    <div class="dropdown-menu">
-                        <a class="dropdown-item" href="#">帮助</a>
-                        <a class="dropdown-item" href="#">升级说明</a>
-                        <a class="dropdown-item" href="#">重庆市2008定额说明</a>
-                        <a class="dropdown-item" href="#">纵横官网</a>
-                        <a class="dropdown-item" href="#">动画教程</a>
-                        <a class="dropdown-item" href="#">联系客服</a>
-                        <a class="dropdown-item" href="#">关于</a>
-                    </div>
-                </li>
-                <li class="nav-item">
-                    <a class="nav-link" href="#" aria-haspopup="true" aria-expanded="false"><i class="fa fa-history"></i> 历史记录</a>
-                </li>
-            </ul>
-            <form class="form-inline">
-                <input class="form-control form-control-sm mr-1" type="text" placeholder="告诉我你想做什么">
-            </form>
-        </nav>
     </div>
     <div class="main">
         <div class="main-nav">
@@ -90,15 +54,15 @@
               <!--造价书-->
               <div class="toolsbar px-1 d-flex justify-content-between">
                   <div class="tools-btn btn-group align-top">
-                    <a href="" class="btn btn-sm"><i class="fa fa-files-o" aria-hidden="true"></i> 复制</a>
-                    <a href="" class="btn btn-sm"><i class="fa fa-scissors" aria-hidden="true"></i> 接切</a>
-                    <a href="" class="btn btn-sm"><i class="fa fa-clipboard" aria-hidden="true"></i> 粘贴</a>
-                    <a href="javascript:void(0)" class="btn btn-sm" id="insert"><i class="fa fa-sign-in" aria-hidden="true"></i> 插入</a>
-                    <a href="javascript:void(0)" class="btn btn-sm" id="delete"><i class="fa fa-remove" aria-hidden="true"></i> 删除</a>
-                    <a href="javascript:void(0)" class="btn btn-sm" id="upLevel"><i class="fa fa-arrow-left" aria-hidden="true"></i> 升级</a>
-                    <a href="javascript:void(0)" class="btn btn-sm" id="downLevel"><i class="fa fa-arrow-right" aria-hidden="true"></i> 降级</a>
-                    <a href="javascript:void(0)" class="btn btn-sm" id="downMove"><i class="fa fa-arrow-down" aria-hidden="true"></i> 下移</a>
-                    <a href="javascript:void(0)" class="btn btn-sm" id="upMove"><i class="fa fa-arrow-up" aria-hidden="true"></i> 上移</a>
+                    <a href="" class="btn btn-sm" title="复制"><i class="fa fa-files-o" aria-hidden="true"></i></a>
+                    <a href="" class="btn btn-sm" title="接切"><i class="fa fa-scissors" aria-hidden="true"></i></a>
+                    <a href="" class="btn btn-sm" title="粘贴"><i class="fa fa-clipboard" aria-hidden="true"></i></a>
+                    <a href="javascript:void(0)" class="btn btn-sm" id="insert" title="插入"><i class="fa fa-sign-in" aria-hidden="true"></i></a>
+                    <a href="javascript:void(0)" class="btn btn-sm" id="delete" title="删除"><i class="fa fa-remove" aria-hidden="true"></i></a>
+                    <a href="javascript:void(0)" class="btn btn-sm" id="upLevel" title="升级"><i class="fa fa-arrow-left" aria-hidden="true"></i></a>
+                    <a href="javascript:void(0)" class="btn btn-sm" id="downLevel" title="降级"><i class="fa fa-arrow-right" aria-hidden="true"></i></a>
+                    <a href="javascript:void(0)" class="btn btn-sm" id="downMove" title="下移"><i class="fa fa-arrow-down" aria-hidden="true"></i></a>
+                    <a href="javascript:void(0)" class="btn btn-sm" id="upMove" title="上移"><i class="fa fa-arrow-up" aria-hidden="true"></i></a>
                   </div>
                   <div class="tools-btn">
                       <a href="javacript:void(0);" data-toggle="modal" data-target="#column" class="btn btn-sm"><i class="fa fa-table" aria-hidden="true"></i> 列设置</a>
@@ -607,6 +571,40 @@
             </div>
         </div>
     </div>
+    <!--弹出 清单 计算基数-->
+    <div class="modal fade" id="qd-jsjs" data-backdrop="static">
+        <div class="modal-dialog" role="document">
+            <div class="modal-content">
+                <div class="modal-header">
+                    <h5 class="modal-title">计算基础选择</h5>
+                    <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+                        <span aria-hidden="true">&times;</span>
+                    </button>
+                </div>
+                <div class="modal-body">
+                    <div class="form-group">
+                        <input class="form-control" value="分部分项工程费+100">
+                        <p class="form-text">
+                            <button class="btn btn-secondary btn-sm">+</button>
+                            <button class="btn btn-secondary btn-sm">-</button>
+                            <button class="btn btn-secondary btn-sm">*</button>
+                            <button class="btn btn-secondary btn-sm">/</button>
+                            <button class="btn btn-secondary btn-sm">(</button>
+                            <button class="btn btn-secondary btn-sm">)</button>
+                        </p>
+                    </div>
+                    <div class=" modal-auto-height" style="overflow: hidden" id="billsBaseSpread">
+                        <p></p>
+                        <p></p>
+                    </div>
+                </div>
+                <div class="modal-footer">
+                    <button type="button" class="btn btn-secondary" data-dismiss="modal">关闭</button>
+                    <a href="" class="btn btn-primary">确定</a>
+                </div>
+            </div>
+        </div>
+    </div>
         <!-- JS. -->
         <script type="text/javascript" src="/lib/spreadjs/sheets/gc.spread.sheets.all.10.0.1.min.js"></script>
 

+ 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

@@ -69,7 +69,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);
                 gljOprObj.showRationGLJSheetData();