Explorar el Código

Merge branch 'uat'

MaiXinRong hace 3 años
padre
commit
571ed9f4c7
Se han modificado 88 ficheros con 2884 adiciones y 845 borrados
  1. 8 1
      app/base/base_bills_service.js
  2. 21 8
      app/base/base_tree_service.js
  3. 106 0
      app/const/report_defined_properties.js
  4. 25 13
      app/const/spread.js
  5. 15 0
      app/const/stage_filter.js
  6. 4 1
      app/const/tender_info.js
  7. 2 1
      app/controller/budget_controller.js
  8. 13 0
      app/controller/change_controller.js
  9. 84 50
      app/controller/stage_controller.js
  10. 40 1
      app/controller/tender_controller.js
  11. 8 0
      app/extend/context.js
  12. 98 30
      app/lib/analysis_excel.js
  13. 16 0
      app/lib/bills_pos_convert.js
  14. 5 5
      app/lib/ledger.js
  15. 1 1
      app/lib/rptCustomData.js
  16. 59 52
      app/lib/stage_im.js
  17. 10 8
      app/lib/sum_load.js
  18. 16 15
      app/middleware/stage_check.js
  19. 53 18
      app/public/css/main.css
  20. BIN
      app/public/css/sel_blue.png
  21. BIN
      app/public/css/sel_gary.png
  22. BIN
      app/public/images/dongtai.png
  23. BIN
      app/public/images/jingtai.png
  24. BIN
      app/public/images/tubiaoban.png
  25. 26 15
      app/public/js/budget_compare.js
  26. 182 0
      app/public/js/change_information.js
  27. 6 6
      app/public/js/change_information_approval.js
  28. 4 3
      app/public/js/change_information_set.js
  29. 8 0
      app/public/js/change_revise.js
  30. 34 9
      app/public/js/gcl_gather.js
  31. 21 6
      app/public/js/global.js
  32. 17 6
      app/public/js/ledger.js
  33. 1 1
      app/public/js/ledger_check.js
  34. 3 3
      app/public/js/ledger_gather.js
  35. 17 0
      app/public/js/path_tree.js
  36. 13 1
      app/public/js/shares/sjs_setting.js
  37. 13 9
      app/public/js/spreadjs_rela/spreadjs_zh.js
  38. 6 0
      app/public/js/sr_detail.js
  39. 76 43
      app/public/js/stage.js
  40. 3 1
      app/public/js/stage_change.js
  41. 2 2
      app/public/js/stage_compare.js
  42. 5 4
      app/public/js/stage_gather.js
  43. 32 24
      app/public/js/stage_im.js
  44. 8 1
      app/public/report/js/rpt_custom.js
  45. 11 5
      app/public/report/js/rpt_signature.js
  46. 3 1
      app/reports/rpt_component/jpc_flow_tab.js
  47. 3 1
      app/router.js
  48. 23 9
      app/service/change.js
  49. 7 7
      app/service/change_audit_list.js
  50. 10 0
      app/service/change_ledger.js
  51. 2 13
      app/service/ledger.js
  52. 37 0
      app/service/ledger_extra.js
  53. 9 0
      app/service/ledger_history.js
  54. 6 6
      app/service/ledger_revise.js
  55. 2 16
      app/service/pos.js
  56. 37 0
      app/service/pos_extra.js
  57. 4 2
      app/service/project.js
  58. 21 43
      app/service/report_memory.js
  59. 5 6
      app/service/revise_audit.js
  60. 4 0
      app/service/rpt_gather_memory.js
  61. 3 1
      app/service/stage.js
  62. 2 13
      app/service/stage_audit.js
  63. 16 7
      app/service/stage_bills.js
  64. 5 18
      app/service/stage_bills_dgn.js
  65. 6 15
      app/service/stage_bills_final.js
  66. 64 54
      app/service/stage_change.js
  67. 2 13
      app/service/stage_change_final.js
  68. 11 9
      app/service/stage_pos.js
  69. 4 14
      app/service/stage_pos_final.js
  70. 195 1
      app/service/stage_stash.js
  71. 17 0
      app/view/change/information.ejs
  72. 17 1
      app/view/change/information_modal.ejs
  73. 5 4
      app/view/dashboard/index.ejs
  74. 4 0
      app/view/report/rpt_all_popup.ejs
  75. 14 0
      app/view/setting/fun.ejs
  76. 1 1
      app/view/stage/bwtz.ejs
  77. 1 0
      app/view/stage/gather.ejs
  78. 13 2
      app/view/stage/index.ejs
  79. 19 6
      app/view/tender/detail.ejs
  80. 163 42
      app/view/tender/detail_modal.ejs
  81. 197 195
      builder_report_index_define.js
  82. 4 1
      config/config.default.js
  83. 1 1
      config/config.uat.js
  84. 89 0
      db_script/ledger_his_count.js
  85. 70 0
      db_script/minus_no_value.js
  86. 80 0
      db_script/stage_stash.js
  87. 31 0
      publish.md
  88. 605 0
      sql/update.sql

+ 8 - 1
app/base/base_bills_service.js

@@ -559,7 +559,7 @@ class BaseBillsSerivce extends TreeService {
         }
     }
 
-    async pasteBlockData (tid, sid, pasteData, defaultData) {
+    async pasteBlockData(tid, sid, pasteData, defaultData) {
         if ((tid <= 0) || (sid <= 0)) return [];
 
         if (!pasteData || pasteData.length <= 0) throw '复制数据错误';
@@ -703,6 +703,13 @@ class BaseBillsSerivce extends TreeService {
             pos: pastePosData,
         };
     }
+
+    async getCompleteDataById(id) {
+        const ledgerBills = await this.getDataById(id);
+        const ledgerExtra = await this.ctx.service.ledgerExtra.getDataById(id);
+        ledgerBills.is_tp = ledgerExtra ? ledgerExtra.is_tp : 0;
+        return ledgerBills
+    }
 }
 
 module.exports = BaseBillsSerivce;

+ 21 - 8
app/base/base_tree_service.js

@@ -351,6 +351,16 @@ class TreeService extends Service {
     _cacheMaxLid(mid, maxId) {
         this.cache.set(this.setting.keyPre + mid , maxId, 'EX', this.ctx.app.config.cacheTime);
     }
+    /**
+     * 移除最大节点id
+     *
+     * @param {Number} mid - master id
+     * @return {Number}
+     * @private
+     */
+    async _removeCacheMaxLid(mid) {
+        return await this.cache.del(this.setting.keyPre + mid);
+    }
 
     /**
      * 更新order
@@ -737,7 +747,7 @@ class TreeService extends Service {
             selfOperate: '-',
         });
         this.sqlBuilder.setUpdateData(this.setting.fullPath, {
-            value: [this.setting.fullPath, this.db.escape(select[this.setting.pid] + '-'), this.db.escape('')],
+            value: [this.setting.fullPath, this.db.escape(`-${select[this.setting.pid]}-`), this.db.escape('-')],
             literal: 'Replace',
         });
         const [sql, sqlParam] = this.sqlBuilder.build(this.tableName, 'update');
@@ -842,7 +852,7 @@ class TreeService extends Service {
                 updateData[this.setting.pid] = parent[this.setting.pid];
                 updateData[this.setting.order] = parent[this.setting.order] + i + 1;
                 updateData[this.setting.level] = s[this.setting.level] - 1;
-                updateData[this.setting.fullPath] = s[this.setting.fullPath].replace(s[this.setting.pid] + '-', '');
+                updateData[this.setting.fullPath] = s[this.setting.fullPath].replace(`-${s[this.setting.pid]}-`, '-');
                 newPath.push(updateData[this.setting.fullPath]);
                 if (s.is_leaf && s.id === last.id) {
                     const nexts = await this.getNextsData(mid, parent[this.setting.kid], last[this.setting.order]);
@@ -881,7 +891,7 @@ class TreeService extends Service {
      * @return {Promise<*>}
      * @private
      */
-    async _syncDownlevelChildren(select, pre) {
+    async _syncDownlevelChildren(select, newFullPath) {
         this.initSqlBuilder();
         this.sqlBuilder.setAndWhere(this.setting.mid, {
             value: select[this.setting.mid],
@@ -896,7 +906,7 @@ class TreeService extends Service {
             selfOperate: '+',
         });
         this.sqlBuilder.setUpdateData(this.setting.fullPath, {
-            value: [this.setting.fullPath, this.db.escape(select[this.setting.kid] + '-'), this.db.escape(pre[this.setting.kid] + '-' + select[this.setting.kid] + '-')],
+            value: [this.setting.fullPath, this.db.escape(select[this.setting.fullPath] + '-'), this.db.escape(newFullPath + '-')],
             literal: 'Replace',
         });
         const [sql, sqlParam] = this.sqlBuilder.build(this.tableName, 'update');
@@ -933,13 +943,16 @@ class TreeService extends Service {
                 updateData[this.setting.pid] = pre[this.setting.kid];
                 updateData[this.setting.order] = preLastChild ? preLastChild[this.setting.order] + i + 1 : i + 1;
                 updateData[this.setting.level] = s[this.setting.level] + 1;
-                const orgLastPath = s[this.setting.level] === 1 ? s[this.setting.kid] : '-' + s[this.setting.kid];
-                const newLastPath = s[this.setting.level] === 1 ? pre[this.setting.kid] + '-' + s[this.setting.kid] : '-' + pre[this.setting.kid] + '-' + s[this.setting.kid];
-                updateData[this.setting.fullPath] = s[this.setting.fullPath].replace(orgLastPath, newLastPath);
+                if (s[this.setting.level] === 1) {
+                    updateData[this.setting.fullPath] = pre[this.setting.kid] + '-' + s[this.setting.kid];
+                } else {
+                    const index = s[this.setting.fullPath].lastIndexOf(s[this.setting.kid]);
+                    updateData[this.setting.fullPath] = s[this.setting.fullPath].substring(0, index-1) + '-' + pre[this.setting.kid] + '-' + s[this.setting.kid];
+                }
                 newPath.push(updateData[this.setting.fullPath]);
                 await this.transaction.update(this.tableName, updateData);
                 // 选中节点--全部子节点(含孙) level++, full_path
-                await this._syncDownlevelChildren(s, pre);
+                await this._syncDownlevelChildren(s, updateData[this.setting.fullPath]);
             }
             // 选中节点--前兄弟节点 is_leaf应为false, 清空计算相关字段
             const updateData2 = { id: pre.id };

+ 106 - 0
app/const/report_defined_properties.js

@@ -1,3 +1,5 @@
+'use strict';
+
 /**
  * Created by Tony on 2019/12/26.
  */
@@ -655,6 +657,110 @@ module.exports = {
                 },
             ],
         }, {
+            ID: 'Label_TopCover',
+            CfgDispName: '上包围',
+            border_style: [
+                {
+                    Color: 'BLACK',
+                    Position: 'Left',
+                    DashStyle: 'SOLID',
+                    LineWeight: '1',
+                }, {
+                    Color: 'BLACK',
+                    Position: 'Right',
+                    DashStyle: 'SOLID',
+                    LineWeight: '1',
+                }, {
+                    Color: 'BLACK',
+                    Position: 'Top',
+                    DashStyle: 'SOLID',
+                    LineWeight: '1',
+                }, {
+                    Color: 'BLACK',
+                    Position: 'Bottom',
+                    DashStyle: 'SOLID',
+                    LineWeight: '0',
+                },
+            ],
+        }, {
+            ID: 'Label_BottomCover',
+            CfgDispName: '下包围',
+            border_style: [
+                {
+                    Color: 'BLACK',
+                    Position: 'Left',
+                    DashStyle: 'SOLID',
+                    LineWeight: '1',
+                }, {
+                    Color: 'BLACK',
+                    Position: 'Right',
+                    DashStyle: 'SOLID',
+                    LineWeight: '1',
+                }, {
+                    Color: 'BLACK',
+                    Position: 'Top',
+                    DashStyle: 'SOLID',
+                    LineWeight: '0',
+                }, {
+                    Color: 'BLACK',
+                    Position: 'Bottom',
+                    DashStyle: 'SOLID',
+                    LineWeight: '1',
+                },
+            ],
+        }, {
+            ID: 'Label_LeftCover',
+            CfgDispName: '左包围',
+            border_style: [
+                {
+                    Color: 'BLACK',
+                    Position: 'Left',
+                    DashStyle: 'SOLID',
+                    LineWeight: '1',
+                }, {
+                    Color: 'BLACK',
+                    Position: 'Right',
+                    DashStyle: 'SOLID',
+                    LineWeight: '0',
+                }, {
+                    Color: 'BLACK',
+                    Position: 'Top',
+                    DashStyle: 'SOLID',
+                    LineWeight: '1',
+                }, {
+                    Color: 'BLACK',
+                    Position: 'Bottom',
+                    DashStyle: 'SOLID',
+                    LineWeight: '1',
+                },
+            ],
+        }, {
+            ID: 'Label_RightCover',
+            CfgDispName: '右包围',
+            border_style: [
+                {
+                    Color: 'BLACK',
+                    Position: 'Left',
+                    DashStyle: 'SOLID',
+                    LineWeight: '0',
+                }, {
+                    Color: 'BLACK',
+                    Position: 'Right',
+                    DashStyle: 'SOLID',
+                    LineWeight: '1',
+                }, {
+                    Color: 'BLACK',
+                    Position: 'Top',
+                    DashStyle: 'SOLID',
+                    LineWeight: '1',
+                }, {
+                    Color: 'BLACK',
+                    Position: 'Bottom',
+                    DashStyle: 'SOLID',
+                    LineWeight: '1',
+                },
+            ],
+        }, {
             ID: 'BORDER_ALL_AROUND',
             CfgDispName: '报表边框',
             border_style: [

+ 25 - 13
app/const/spread.js

@@ -17,6 +17,7 @@ const thirdPartyCols = {
     gxby: ['gxby'],
     dagl: ['dagl']
 };
+const minusNoValueCols = ['qc_minus_qty'];
 
 const withCl = {
     ledger: {
@@ -195,8 +196,9 @@ const stageTz = {
             {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'total_price', hAlign: 2, width: 60, readOnly: true, type: 'Number'},
             {title: '本期合同计量|数量', colSpan: '2|1', rowSpan: '1|1', field: 'contract_qty', hAlign: 2, width: 60, type: 'Number'},
             {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'contract_tp', hAlign: 2, width: 60, type: 'Number'},
-            {title: '本期数量变更|数量', colSpan: '2|1', rowSpan: '1|1', field: 'qc_qty', hAlign: 2, width: 60, type: 'Number'},
+            {title: '本期数量变更|数量', colSpan: '3|1', rowSpan: '1|1', field: 'qc_qty', hAlign: 2, width: 60, type: 'Number'},
             {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'qc_tp', hAlign: 2, width: 60, type: 'Number', readOnly: true},
+            {title: '|不计价', colSpan: '|1', rowSpan: '|1', field: 'qc_minus_qty', hAlign: 2, width: 60, type: 'Number'},
             {title: '本期完成计量|数量', colSpan: '2|1', rowSpan: '1|1', field: 'gather_qty', hAlign: 2, width: 60, readOnly: true, type: 'Number'},
             {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'gather_tp', hAlign: 2, width: 60, readOnly: true, type: 'Number'},
             {title: '截止本期合同计量|数量', colSpan: '2|1', rowSpan: '1|1', field: 'end_contract_qty', hAlign: 2, width: 60, readOnly: true, type: 'Number'},
@@ -205,7 +207,7 @@ const stageTz = {
             {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'end_qc_tp', hAlign: 2, width: 60, readOnly: true, type: 'Number'},
             {title: '截止本期完成计量|数量', colSpan: '3|1', rowSpan: '1|1', field: 'end_gather_qty', hAlign: 2, width: 60, readOnly: true, type: 'Number'},
             {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'end_gather_tp', hAlign: 2, width: 60, readOnly: true, type: 'Number'},
-            {title: '|完成率(%)', colSpan: '1', rowSpan: '|1', field: 'end_gather_percent', hAlign: 2, width: 80, readOnly: true, type: 'Number'},
+            {title: '|完成率(%)', colSpan: '1', rowSpan: '|1', field: 'end_final_1_percent', hAlign: 2, width: 80, readOnly: true, type: 'Number'},
             {title: '合同|项目节数量1',  colSpan: '2|1', rowSpan: '1|1', field: 'deal_dgn_qty1', hAlign: 2, width: 60, type: 'Number'},
             {title: '|项目节数量2',  colSpan: '|1', rowSpan: '|1', field: 'deal_dgn_qty2', hAlign: 2, width: 60, type: 'Number'},
             {title: '变更|项目节数量1',  colSpan: '2|1', rowSpan: '1|1', field: 'c_dgn_qty1', hAlign: 2, width: 60, type: 'Number'},
@@ -213,7 +215,6 @@ const stageTz = {
             {title: '经济指标',  colSpan: '1', rowSpan: '2', field: 'final_dgn_price', hAlign: 2, width: 60, readOnly: true, type: 'Number'},
             {title: '本期批注', colSpan: '1', rowSpan: '2', field: 'postil', hAlign: 0, width: 100, formatter: '@', cellType: 'autoTip'},
             {title: '图(册)号', colSpan: '1', rowSpan: '2', field: 'drawing_code', hAlign: 0, width: 80, formatter: '@', readOnly: true},
-            //{title: '累计完成率(%)', colSpan: '1', rowSpan: '2', field: 'percent', hAlign: 0, width: 100, readOnly: true, type: 'Number'},
             {title: '备注', colSpan: '1', rowSpan: '2', field: 'memo', hAlign: 0, width: 100, formatter: '@', cellType: 'ellipsisAutoTip'},
             {title: 'ex_memo2', colSpan: '1', rowSpan: '2', field: 'ex_memo2', hAlign: 0, width: 100, formatter: '@', cellType: 'ellipsisAutoTip'},
             {title: 'ex_memo3', colSpan: '1', rowSpan: '2', field: 'ex_memo3', hAlign: 0, width: 100, formatter: '@', cellType: 'ellipsisAutoTip'},
@@ -227,6 +228,8 @@ const stageTz = {
         defaultRowHeight: 21,
         headerFont: '12px 微软雅黑',
         font: '12px 微软雅黑',
+        frozenColCount: 5,
+        frozenLineColor: '#93b5e4',
     },
     pos: {
         cols: [
@@ -236,8 +239,9 @@ const stageTz = {
             {title: '台账数量', colSpan: '1', rowSpan: '2', field: 'quantity', hAlign: 2, width: 60, formatter: '@', readOnly: true},
             {title: '现场实际数量', colSpan: '1', rowSpan: '2', field: 'real_qty', hAlign: 2, width: 60, type: 'Number'},
             {title: '预计变更数量', colSpan: '1', rowSpan: '2', field: 'estimate_qty', hAlign: 2, width: 60, type: 'Number', readOnly: true},
-            {title: '本期计量|合同', colSpan: '3|1', rowSpan: '1|1', field: 'contract_qty', hAlign: 2, width: 60, type: 'Number'},
+            {title: '本期计量|合同', colSpan: '4|1', rowSpan: '1|1', field: 'contract_qty', hAlign: 2, width: 60, type: 'Number'},
             {title: '|数量变更', colSpan: '|1', rowSpan: '|1', field: 'qc_qty', hAlign: 2, width: 80, type: 'Number'},
+            {title: '|不计价', colSpan: '|1', rowSpan: '|1', field: 'qc_minus_qty', hAlign: 2, width: 60, type: 'Number'},
             {title: '|完成', colSpan: '|1', rowSpan: '|1', field: 'gather_qty', hAlign: 2, width: 60, type: 'Number', readOnly: true},
             {title: '截止本期计量|合同', colSpan: '3|1', rowSpan: '1|1', field: 'end_contract_qty', hAlign: 2, width: 60, type: 'Number', readOnly: true},
             {title: '|数量变更', colSpan: '|1', rowSpan: '|1', field: 'end_qc_qty', hAlign: 2, width: 80, type: 'Number', readOnly: true},
@@ -273,8 +277,9 @@ const stageCl = {
             {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'total_price', hAlign: 2, width: 60, readOnly: true, type: 'Number'},
             {title: '本期合同计量|数量', colSpan: '2|1', rowSpan: '1|1', field: 'contract_qty', hAlign: 2, width: 60, type: 'Number'},
             {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'contract_tp', hAlign: 2, width: 60, type: 'Number'},
-            {title: '本期数量变更|数量', colSpan: '2|1', rowSpan: '1|1', field: 'qc_qty', hAlign: 2, width: 60, type: 'Number',},
+            {title: '本期数量变更|数量', colSpan: '3|1', rowSpan: '1|1', field: 'qc_qty', hAlign: 2, width: 60, type: 'Number',},
             {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'qc_tp', hAlign: 2, width: 60, type: 'Number', readOnly: true},
+            {title: '|不计价', colSpan: '|1', rowSpan: '|1', field: 'qc_minus_qty', hAlign: 2, width: 60, type: 'Number'},
             {title: '本期完成计量|数量', colSpan: '2|1', rowSpan: '1|1', field: 'gather_qty', hAlign: 2, width: 60, readOnly: true, type: 'Number'},
             {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'gather_tp', hAlign: 2, width: 60, readOnly: true, type: 'Number'},
             {title: '截止本期合同计量|数量', colSpan: '2|1', rowSpan: '1|1', field: 'end_contract_qty', hAlign: 2, width: 60, readOnly: true, type: 'Number'},
@@ -283,7 +288,7 @@ const stageCl = {
             {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'end_qc_tp', hAlign: 2, width: 60, readOnly: true, type: 'Number'},
             {title: '截止本期完成计量|数量', colSpan: '3|1', rowSpan: '1|1', field: 'end_gather_qty', hAlign: 2, width: 60, readOnly: true, type: 'Number'},
             {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'end_gather_tp', hAlign: 2, width: 60, readOnly: true, type: 'Number'},
-            {title: '|完成率(%)', colSpan: '1', rowSpan: '|1', field: 'end_gather_percent', hAlign: 2, width: 80, readOnly: true, type: 'Number'},
+            {title: '|完成率(%)', colSpan: '1', rowSpan: '|1', field: 'end_final_1_percent', hAlign: 2, width: 80, readOnly: true, type: 'Number'},
             {title: '合同|项目节数量1',  colSpan: '2|1', rowSpan: '1|1', field: 'deal_dgn_qty1', hAlign: 2, width: 60, type: 'Number'},
             {title: '|项目节数量2',  colSpan: '|1', rowSpan: '|1', field: 'deal_dgn_qty2', hAlign: 2, width: 60, type: 'Number'},
             {title: '变更|项目节数量1',  colSpan: '2|1', rowSpan: '1|1', field: 'c_dgn_qty1', hAlign: 2, width: 60, type: 'Number'},
@@ -304,6 +309,8 @@ const stageCl = {
         defaultRowHeight: 21,
         headerFont: '12px 微软雅黑',
         font: '12px 微软雅黑',
+        frozenColCount: 5,
+        frozenLineColor: '#93b5e4',
     },
     pos: {
         cols: [
@@ -312,8 +319,9 @@ const stageCl = {
             {title: '位置', colSpan: '1', rowSpan: '2', field: 'position', hAlign: 0, width: 60, formatter: '@'},
             {title: '现场实际数量', colSpan: '1', rowSpan: '2', field: 'real_qty', hAlign: 2, width: 60, type: 'Number'},
             {title: '预计变更数量', colSpan: '1', rowSpan: '2', field: 'estimate_qty', hAlign: 2, width: 60, type: 'Number', readOnly: true},
-            {title: '本期计量|合同', colSpan: '3|1', rowSpan: '1|1', field: 'contract_qty', hAlign: 2, width: 60, type: 'Number'},
+            {title: '本期计量|合同', colSpan: '4|1', rowSpan: '1|1', field: 'contract_qty', hAlign: 2, width: 60, type: 'Number'},
             {title: '|数量变更', colSpan: '|1', rowSpan: '|1', field: 'qc_qty', hAlign: 2, width: 80, type: 'Number'},
+            {title: '|不计价', colSpan: '|1', rowSpan: '|1', field: 'qc_minus_qty', hAlign: 2, width: 60, type: 'Number'},
             {title: '|完成', colSpan: '|1', rowSpan: '|1', field: 'gather_qty', hAlign: 2, width: 60, type: 'Number', readOnly: true},
             {title: '截止本期计量|合同', colSpan: '3|1', rowSpan: '1|1', field: 'end_contract_qty', hAlign: 2, width: 60, type: 'Number', readOnly: true},
             {title: '|数量变更', colSpan: '|1', rowSpan: '|1', field: 'end_qc_qty', hAlign: 2, width: 80, type: 'Number', readOnly: true},
@@ -350,8 +358,9 @@ const stageNoCl = {
             {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'total_price', hAlign: 2, width: 60, readOnly: true, type: 'Number'},
             {title: '本期合同计量|数量', colSpan: '2|1', rowSpan: '1|1', field: 'contract_qty', hAlign: 2, width: 60, type: 'Number'},
             {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'contract_tp', hAlign: 2, width: 60, type: 'Number'},
-            {title: '本期数量变更|数量', colSpan: '2|1', rowSpan: '1|1', field: 'qc_qty', hAlign: 2, width: 60, type: 'Number',},
+            {title: '本期数量变更|数量', colSpan: '3|1', rowSpan: '1|1', field: 'qc_qty', hAlign: 2, width: 60, type: 'Number',},
             {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'qc_tp', hAlign: 2, width: 60, type: 'Number', readOnly: true},
+            {title: '|不计价', colSpan: '|1', rowSpan: '|1', field: 'qc_minus_qty', hAlign: 2, width: 60, type: 'Number'},
             {title: '本期完成计量|数量', colSpan: '2|1', rowSpan: '1|1', field: 'gather_qty', hAlign: 2, width: 60, readOnly: true, type: 'Number'},
             {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'gather_tp', hAlign: 2, width: 60, readOnly: true, type: 'Number'},
             {title: '截止本期合同计量|数量', colSpan: '2|1', rowSpan: '1|1', field: 'end_contract_qty', hAlign: 2, width: 60, readOnly: true, type: 'Number'},
@@ -360,7 +369,7 @@ const stageNoCl = {
             {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'end_qc_tp', hAlign: 2, width: 60, readOnly: true, type: 'Number'},
             {title: '截止本期完成计量|数量', colSpan: '3|1', rowSpan: '1|1', field: 'end_gather_qty', hAlign: 2, width: 60, readOnly: true, type: 'Number'},
             {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'end_gather_tp', hAlign: 2, width: 60, readOnly: true, type: 'Number'},
-            {title: '|完成率(%)', colSpan: '1', rowSpan: '|1', field: 'end_gather_percent', hAlign: 2, width: 80, readOnly: true, type: 'Number'},
+            {title: '|完成率(%)', colSpan: '1', rowSpan: '|1', field: 'end_final_1_percent', hAlign: 2, width: 80, readOnly: true, type: 'Number'},
             {title: '合同|项目节数量1',  colSpan: '2|1', rowSpan: '1|1', field: 'deal_dgn_qty1', hAlign: 2, width: 60, type: 'Number'},
             {title: '|项目节数量2',  colSpan: '|1', rowSpan: '|1', field: 'deal_dgn_qty2', hAlign: 2, width: 60, type: 'Number'},
             {title: '变更|项目节数量1',  colSpan: '2|1', rowSpan: '1|1', field: 'c_dgn_qty1', hAlign: 2, width: 60, type: 'Number'},
@@ -381,6 +390,8 @@ const stageNoCl = {
         defaultRowHeight: 21,
         headerFont: '12px 微软雅黑',
         font: '12px 微软雅黑',
+        frozenColCount: 5,
+        frozenLineColor: '#93b5e4',
     },
     pos: {
         cols: [
@@ -389,8 +400,9 @@ const stageNoCl = {
             {title: 'ex_memo1', colSpan: '1', rowSpan: '2', field: 'ex_memo1', hAlign: 0, width: 100, formatter: '@', cellType: 'ellipsisAutoTip'},
             {title: '现场实际数量', colSpan: '1', rowSpan: '2', field: 'real_qty', hAlign: 2, width: 60, type: 'Number'},
             {title: '预计变更数量', colSpan: '1', rowSpan: '2', field: 'estimate_qty', hAlign: 2, width: 60, type: 'Number', readOnly: true},
-            {title: '本期计量|合同', colSpan: '3|1', rowSpan: '1|1', field: 'contract_qty', hAlign: 2, width: 60, type: 'Number'},
+            {title: '本期计量|合同', colSpan: '4|1', rowSpan: '1|1', field: 'contract_qty', hAlign: 2, width: 60, type: 'Number'},
             {title: '|数量变更', colSpan: '|1', rowSpan: '|1', field: 'qc_qty', hAlign: 2, width: 80, type: 'Number'},
+            {title: '|不计价', colSpan: '|1', rowSpan: '|1', field: 'qc_minus_qty', hAlign: 2, width: 60, type: 'Number'},
             {title: '|完成', colSpan: '|1', rowSpan: '|1', field: 'gather_qty', hAlign: 2, width: 60, type: 'Number', readOnly: true},
             {title: '截止本期计量|合同', colSpan: '3|1', rowSpan: '1|1', field: 'end_contract_qty', hAlign: 2, width: 60, type: 'Number', readOnly: true},
             {title: '|数量变更', colSpan: '|1', rowSpan: '|1', field: 'end_qc_qty', hAlign: 2, width: 80, type: 'Number', readOnly: true},
@@ -436,7 +448,7 @@ const stageGather = {
             {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'end_qc_tp', hAlign: 2, width: 60, type: 'Number'},
             {title: '截止本期完成计量|数量', colSpan: '3|1', rowSpan: '1|1', field: 'end_gather_qty', hAlign: 2, width: 60, type: 'Number'},
             {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'end_gather_tp', hAlign: 2, width: 60, type: 'Number'},
-            {title: '|完成率(%)', colSpan: '|1', rowSpan: '|1', field: 'end_gather_percent', hAlign: 2, width: 80, type: 'Number'},
+            {title: '|完成率(%)', colSpan: '|1', rowSpan: '|1', field: 'end_final_1_percent', hAlign: 2, width: 80, type: 'Number'},
             {title: '台账+变更令|数量', colSpan: '3|1', rowSpan: '1|1', field: 'final_qty', hAlign: 2, width: 60, type: 'Number'},
             {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'final_tp', hAlign: 2, width: 60, type: 'Number'},
             {title: '|完成率(%)', colSpan: '|1', rowSpan: '|1', field: 'final_percent', hAlign: 2, width: 80, type: 'Number'},
@@ -460,7 +472,7 @@ const stageGather = {
             {title: '截止本期计量数量|合同', colSpan: '4|1', rowSpan: '1|1', field: 'end_contract_qty', hAlign: 2, width: 60, type: 'Number'},
             {title: '|数量变更', colSpan: '|1', rowSpan: '|1', field: 'end_qc_qty', hAlign: 2, width: 60, type: 'Number'},
             {title: '|完成', colSpan: '|1', rowSpan: '|1', field: 'end_gather_qty', hAlign: 2, width: 60, type: 'Number'},
-            {title: '|完成率(%)', colSpan: '1', rowSpan: '|1', field: 'end_gather_percent', hAlign: 2, width: 80, type: 'Number'},
+            {title: '|完成率(%)', colSpan: '1', rowSpan: '|1', field: 'end_final_1_percent', hAlign: 2, width: 80, type: 'Number', visible: false},
             {title: '单位工程', colSpan: '1', rowSpan: '2', field: 'dwgc', hAlign: 0, width: 80, formatter: '@'},
             {title: '分部工程', colSpan: '1', rowSpan: '2', field: 'fbgc', hAlign: 0, width: 80, formatter: '@'},
             {title: '分项工程', colSpan: '1', rowSpan: '2', field: 'fxgc', hAlign: 0, width: 80, formatter: '@'},
@@ -587,7 +599,7 @@ module.exports = {
     stageNoCl,
     stageGather,
     stageCompare,
-    filterCols: { tzWithoutCols, dgnCols, clCols, stageDgnCols, realCompleteCols, thirdPartyCols},
+    filterCols: { tzWithoutCols, dgnCols, clCols, stageDgnCols, realCompleteCols, thirdPartyCols, minusNoValueCols},
     measure,
     blank,
 };

+ 15 - 0
app/const/stage_filter.js

@@ -0,0 +1,15 @@
+'use strict';
+
+/**
+ *
+ *
+ * @author Mai
+ * @date
+ * @version
+ */
+
+module.exports = {
+    stageBills: { index: ['lid'], times: 'times', order: 'order' },
+    stagePos: { index: ['pid'], times: 'times', order: 'order' },
+    stageChange: { index: ['lid', 'pid', 'cbid', 'no_value'], times: 'stimes', order: 'sorder', },
+};

+ 4 - 1
app/const/tender_info.js

@@ -166,13 +166,16 @@ const defaultInfo = {
     },
     fun_rela: {
         hintOver: true,
+        stage_change: {
+            minusNoValue: true,
+        },
         sum_load: {
             ignoreParent: false,
         },
         stage_rela: {
             show: false,
         },
-    }
+    },
 };
 
 module.exports = {

+ 2 - 1
app/controller/budget_controller.js

@@ -205,7 +205,7 @@ module.exports = app => {
                     {title: '项目节编号', colSpan: '1', rowSpan: '2', field: 'code', hAlign: 0, width: 180, formatter: '@', cellType: 'tree'},
                     {title: '清单编号', colSpan: '1', rowSpan: '2', field: 'b_code', hAlign: 0, width: 120, formatter: '@'},
                     {title: '名称', colSpan: '1', rowSpan: '2', field: 'name', hAlign: 0, width: 230, formatter: '@'},
-                    {title: '单位', colSpan: '1', rowSpan: '2', field: 'unit', hAlign: 1, width: 50, formatter: '@', cellType: 'unit'},
+                    {title: '单位', colSpan: '1', rowSpan: '2', field: 'unit', hAlign: 1, width: 50, formatter: '@', cellType: 'unit', comboEdit: true},
                     {title: '设计数量|数量1', colSpan: '2|1', rowSpan: '1|1', field: 'dgn_qty1', hAlign: 2, width: 80, type: 'Number'},
                     {title: '|数量2', colSpan: '|1', rowSpan: '|1', field: 'dgn_qty2', hAlign: 2, width: 80, type: 'Number'},
                     {title: '经济指标', colSpan: '1', rowSpan: '2', field: 'dgn_price', hAlign: 2, width: 80, type: 'Number', readOnly: true},
@@ -221,6 +221,7 @@ module.exports = app => {
                 defaultRowHeight: 21,
                 headerFont: '12px 微软雅黑',
                 font: '12px 微软雅黑',
+                localCache: { key: 'budget', colWidth: true },
             };
             if (!needGcl) {
                 spreadSetting.cols = spreadSetting.cols.filter(x => {

+ 13 - 0
app/controller/change_controller.js

@@ -594,6 +594,17 @@ module.exports = app => {
                 // 根据auditStatus获取审批人列表
                 const auditList = await ctx.service.changeAudit.getListByStatus(change, auditStatus);
 
+                // 获取变更方案的清单
+                let planList = [];
+                let showPlanBtn = false;
+                if (ctx.session.sessionProject.page_show.openChangePlan) {
+                    const planInfo = change.plan_code ? await ctx.service.changePlan.getDataByCondition({ tid: ctx.tender.id, code: change.plan_code }) : null;
+                    showPlanBtn = change.plan_code !== null && change.plan_code !== '';
+                    if (planInfo && planInfo.id) {
+                        planList = await ctx.service.changePlanList.getAllDataByCondition({ where: { cpid: planInfo.id } });
+                    }
+                }
+
                 // 获取用户人验证手机号
                 const pa = await ctx.service.projectAccount.getDataById(ctx.session.sessionUser.accountId);
                 const auth_mobile = pa.auth_mobile;
@@ -608,6 +619,8 @@ module.exports = app => {
                     attList,
                     whiteList,
                     auditList,
+                    showPlanBtn,
+                    planList,
                     tpUnit: change.tp_decimal ? change.tp_decimal : ctx.tender.info.decimal.tp,
                     upUnit: change.up_decimal ? change.up_decimal : ctx.tender.info.decimal.up,
                     authMobile: auth_mobile,

+ 84 - 50
app/controller/stage_controller.js

@@ -88,13 +88,21 @@ module.exports = app => {
          * 获取SpreadSetting
          * @private
          */
-        _getSpreadSetting() {
+        _getSpreadSetting(funInfo) {
             const _ = this.app._;
             function removeFieldCols(setting, cols) {
                 _.remove(setting.cols, function(c) {
                     return cols.indexOf(c.field) > -1;
                 });
             }
+            function hiddenFieldCols(setting, cols) {
+                setting.cols.forEach(x => {
+                    if (cols.indexOf(x.field) >= 0) {
+                        x.defaultVisible = false;
+                        x.visible = false;
+                    }
+                });
+            }
             const tender = this.ctx.tender,
                 stage = this.ctx.stage;
             const stageSetting = tender.data.measure_type === measureType.tz.value
@@ -116,6 +124,10 @@ module.exports = app => {
                 removeFieldCols(ledger, spreadConst.filterCols.thirdPartyCols.dagl);
                 removeFieldCols(pos, spreadConst.filterCols.thirdPartyCols.dagl);
             }
+            if (!funInfo.minusNoValue || !tender.info.fun_rela.stage_change.minusNoValue) {
+                hiddenFieldCols(ledger, spreadConst.filterCols.minusNoValueCols);
+                hiddenFieldCols(pos, spreadConst.filterCols.minusNoValueCols);
+            }
             if (this.ctx.stage.readOnly || this.ctx.stage.revising) {
                 ledger.readOnly = true;
                 pos.readOnly = true;
@@ -168,7 +180,8 @@ module.exports = app => {
             try {
                 await this._getStageAuditViewData(ctx);
                 const renderData = await this._getDefaultRenderData(ctx);
-                [renderData.ledgerSpread, renderData.posSpread] = this._getSpreadSetting();
+                const projectFunInfo = await this.ctx.service.project.getFunRela(ctx.session.sessionProject.id);
+                [renderData.ledgerSpread, renderData.posSpread] = this._getSpreadSetting(projectFunInfo);
                 const sjsRela = await this.ctx.service.project.getSjsRela(ctx.session.sessionProject.id);
                 this.ctx.helper.refreshSpreadShow(sjsRela.ledgerCol, [renderData.ledgerSpread, renderData.posSpread]);
                 renderData.changeConst = changeConst;
@@ -193,7 +206,7 @@ module.exports = app => {
                 renderData.sfData = sfData;
                 // 收方单附件删除权限
                 renderData.sfAttDelPower = ctx.session.sessionUser.accountId === ctx.stage.user_id || ctx.helper._.findIndex(ctx.stage.auditors2, { aid: ctx.session.sessionUser.accountId }) !== -1;
-                const projectFunInfo = await this.ctx.service.project.getFunRela(ctx.session.sessionProject.id);
+                renderData.minusNoValue = projectFunInfo.minusNoValue && ctx.tender.info.fun_rela.stage_change.minusNoValue;
                 renderData.hintOver = projectFunInfo.hintOver && ctx.tender.info.fun_rela.hintOver;
                 renderData.categoryData = await this.ctx.service.category.getAllCategory(this.ctx.session.sessionProject.id);
                 await this.layout('stage/index.ejs', renderData, 'stage/modal.ejs');
@@ -223,37 +236,40 @@ module.exports = app => {
 
         _getLedgerColumn(sjsRela) {
             const tender = this.ctx.tender;
-            const ledgerColumn = [
+            this.ledgerColumn = [
                 'id', 'tender_id', 'ledger_id', 'ledger_pid', 'level', 'order', 'full_path', 'is_leaf',
                 'code', 'b_code', 'name', 'unit', 'unit_price',
-                'quantity', 'total_price', 'memo', 'drawing_code', 'is_tp', 'node_type'];
-            if (this.ctx.session.sessionProject.gxby) ledgerColumn.push('gxby_status', 'gxby_url', 'gxby_limit');
-            if (this.ctx.session.sessionProject.dagl) ledgerColumn.push('dagl_status', 'dagl_url', 'dagl_limit');
-            if (tender.data.measure_type === measureType.gcl.value) ledgerColumn.push('deal_qty', 'deal_tp');
-            if (tender.info.display.ledger.dgnQty) ledgerColumn.push('dgn_qty1', 'dgn_qty2');
-
-            const posColumn = ['id', 'tid', 'lid', 'name', 'position', 'porder', 'quantity', 'add_stage_order', 'drawing_code'];
-            if (tender.info.display.stage.realComplete) posColumn.push('real_qty');
-            if (this.ctx.session.sessionProject.gxby) posColumn.push('gxby_status', 'gxby_url', 'gxby_limit');
-            if (this.ctx.session.sessionProject.dagl) posColumn.push('dagl_status', 'dagl_url', 'dagl_limit');
+                'quantity', 'total_price', 'memo', 'drawing_code', 'node_type'];
+            if (tender.data.measure_type === measureType.gcl.value) this.ledgerColumn.push('deal_qty', 'deal_tp');
+            if (tender.info.display.ledger.dgnQty) this.ledgerColumn.push('dgn_qty1', 'dgn_qty2');
+
+            this.ledgerExtraColumn = ['is_tp'];
+            if (this.ctx.session.sessionProject.gxby) this.ledgerExtraColumn.push('gxby_status', 'gxby_url', 'gxby_limit');
+            if (this.ctx.session.sessionProject.dagl) this.ledgerExtraColumn.push('dagl_status', 'dagl_url', 'dagl_limit');
+
+
+            this.posColumn = ['id', 'tid', 'lid', 'name', 'position', 'porder', 'quantity', 'add_stage_order', 'drawing_code'];
+            if (tender.info.display.stage.realComplete) this.posColumn.push('real_qty');
+
+            this.posExtraColumn = [];
+            if (this.ctx.session.sessionProject.gxby) this.posExtraColumn.push('gxby_status', 'gxby_url', 'gxby_limit');
+            if (this.ctx.session.sessionProject.dagl) this.posExtraColumn.push('dagl_status', 'dagl_url', 'dagl_limit');
+
+            if (!sjsRela) return;
             for (const field of sjsRela.ledgerCol) {
                 if (field.show) {
-                    ledgerColumn.push(field.field);
-                    posColumn.push(field.field);
+                    this.ledgerColumn.push(field.field);
+                    this.posColumn.push(field.field);
                 }
             }
-            return [ledgerColumn, posColumn];
         }
 
-        async _getStageLedgerData(ctx, ledgerColumn) {
-            // const ledgerData = ctx.stage.ledgerHis
-            //     ? await ctx.helper.loadLedgerDataFromOss(ctx.stage.ledgerHis.bills_file)
-            //     : await ctx.service.ledger.getAllDataByCondition({ where: { tender_id: ctx.tender.id } });
-            // const ledgerData = ctx.stage.ledgerHis
-            //     ? await ctx.service.ledger.loadDataFromOss(ctx.tender.id, ctx.stage.ledgerHis.bills_file)
-            //     : await ctx.service.ledger.getAllDataByCondition({ columns: ledgerColumn, where: { tender_id: ctx.tender.id } });
-            const ledgerData = await ctx.service.ledger.getAllDataByCondition({ columns: ledgerColumn, where: { tender_id: ctx.tender.id } });
+        async _getStageLedgerData(ctx) {
+            const ledgerData = ctx.stage.ledgerHis
+                ? await ctx.helper.loadLedgerDataFromOss(ctx.stage.ledgerHis.bills_file)
+                : await ctx.service.ledger.getAllDataByCondition({ columns: this.ledgerColumn, where: { tender_id: ctx.tender.id } });
             const dgnData = await ctx.service.stageBillsDgn.getDgnData(ctx.tender.id);
+            const extraData = await ctx.service.ledgerExtra.getData(ctx.tender.id, this.ledgerExtraColumn);
             const importData = await ctx.service.stageImportChange.getImportLid(ctx.stage.id);
             let curStageData;
             // 当前操作人查看最新数据,其他人查看历史数据
@@ -269,19 +285,20 @@ module.exports = app => {
             // 查询截止上期数据
             const preStageData = ctx.stage.order > 1 ? await ctx.service.stageBillsFinal.getFinalData(ctx.tender.data, ctx.stage.order - 1) : [];
             this.ctx.helper.assignRelaData(ledgerData, [
-                { data: dgnData, fields: ['deal_dgn_qty1', 'deal_dgn_qty2', 'c_dgn_qty1', 'c_dgn_qty2'], prefix: '', relaId: 'id'},
-                { data: importData, fields: ['is_import'], prefix: '', relaId: 'lid'},
-                { data: curStageData, fields: ['contract_qty', 'contract_expr', 'contract_tp', 'qc_qty', 'qc_tp', 'postil'], prefix: '', relaId: 'lid' },
-                { data: preStageData, fields: ['contract_qty', 'contract_tp', 'qc_qty', 'qc_tp', 'used'], prefix: 'pre_', relaId: 'lid' },
+                { data: dgnData, fields: ['deal_dgn_qty1', 'deal_dgn_qty2', 'c_dgn_qty1', 'c_dgn_qty2'], prefix: '', relaId: 'id' },
+                { data: extraData, fields: this.ledgerExtraColumn, prefix: '', relaId: 'id' },
+                { data: importData, fields: ['is_import'], prefix: '', relaId: 'lid' },
+                { data: curStageData, fields: ['contract_qty', 'contract_expr', 'contract_tp', 'qc_qty', 'qc_tp', 'qc_minus_qty', 'postil'], prefix: '', relaId: 'lid' },
+                { data: preStageData, fields: ['contract_qty', 'contract_tp', 'qc_qty', 'qc_tp', 'qc_minus_qty', 'used'], prefix: 'pre_', relaId: 'lid' },
             ]);
             return ledgerData;
         }
-        async _getStagePosData(ctx, posColumn) {
+        async _getStagePosData(ctx) {
             let curStageData;
-            // const posData =  ctx.stage.ledgerHis
-            //     ? await ctx.service.ledger.loadDataFromOss(ctx.tender.id, ctx.stage.ledgerHis.pos_file)
-            //     : await ctx.service.pos.getAllDataByCondition({ columns: posColumn, where: { tid: ctx.tender.id } });
-            const posData = await ctx.service.pos.getAllDataByCondition({ columns: posColumn, where: { tid: ctx.tender.id } });
+            const posData = ctx.stage.ledgerHis
+                ? await ctx.helper.loadLedgerDataFromOss(ctx.stage.ledgerHis.pos_file)
+                : await ctx.service.pos.getAllDataByCondition({ columns: this.posColumn, where: { tid: ctx.tender.id } });
+            const extraData = await ctx.service.posExtra.getData(ctx.tender.id, this.posExtraColumn);
             // 根据当前人,或指定对象查询数据
             if (ctx.stage.readOnly) {
                 curStageData = await ctx.service.stagePos.getAuditorStageData2(ctx.tender.id,
@@ -297,8 +314,9 @@ module.exports = app => {
             // 查询截止上期数据
             const preStageData = ctx.stage.order > 1 ? await ctx.service.stagePosFinal.getFinalData(ctx.tender.data, ctx.stage.order - 1) : [];
             this.ctx.helper.assignRelaData(posData, [
-                { data: curStageData, fields: ['contract_qty', 'contract_expr', 'qc_qty', 'postil'], prefix: '', relaId: 'pid' },
-                { data: preStageData, fields: ['contract_qty', 'qc_qty'], prefix: 'pre_', relaId: 'pid' },
+                { data: extraData, fields: this.posExtraColumn, prefix: '', relaId: 'id'},
+                { data: curStageData, fields: ['contract_qty', 'contract_expr', 'qc_qty', 'qc_minus_qty', 'postil'], prefix: '', relaId: 'pid' },
+                { data: preStageData, fields: ['contract_qty', 'qc_qty', 'qc_minus_qty'], prefix: 'pre_', relaId: 'pid' },
             ]);
             return posData;
         }
@@ -323,23 +341,23 @@ module.exports = app => {
                 const responseData = { err: 0, msg: '', data: {}, hpack: [] };
                 const hpack = true;
                 const sjsRela = await this.ctx.service.project.getSjsRela(ctx.session.sessionProject.id);
-                const [ledgerColumn, posColumn] = this._getLedgerColumn(sjsRela);
+                this._getLedgerColumn(sjsRela);
                 for (const f of filter) {
                     switch (f) {
                         case 'ledger':
                             if (hpack) {
                                 responseData.hpack.push('ledgerData');
-                                responseData.data.ledgerData = this.ctx.helper.hpackArr(await this._getStageLedgerData(ctx, ledgerColumn));
+                                responseData.data.ledgerData = this.ctx.helper.hpackArr(await this._getStageLedgerData(ctx));
                             } else {
-                                responseData.data.ledgerData = await this._getStageLedgerData(ctx, ledgerColumn);
+                                responseData.data.ledgerData = await this._getStageLedgerData(ctx);
                             }
                             break;
                         case 'pos':
                             if (hpack) {
                                 responseData.hpack.push('posData');
-                                responseData.data.posData = this.ctx.helper.hpackArr(await this._getStagePosData(ctx, posColumn));
+                                responseData.data.posData = this.ctx.helper.hpackArr(await this._getStagePosData(ctx));
                             } else {
-                                responseData.data.posData = await this._getStagePosData(ctx, posColumn);
+                                responseData.data.posData = await this._getStagePosData(ctx);
                             }
                             break;
                         case 'detail':
@@ -392,8 +410,19 @@ module.exports = app => {
 
         async check(ctx) {
             try {
+                const helper = this.ctx.helper;
+                this._getLedgerColumn();
                 const ledgerData = await this._getStageLedgerData(ctx);
+                ledgerData.forEach(x => {
+                    x.end_qc_minus_qty = helper.add(x.pre_qc_minus_qty, x.qc_minus_qty);
+                    x.final_1_qty = helper.add(x.quantity, x.end_qc_minus_qty);
+                    x.deal_final_1_qty = helper.add(x.deal_qty, x.end_qc_minus_qty);
+                });
                 const posData = await this._getStagePosData(ctx);
+                posData.forEach(x => {
+                    x.end_qc_minus_qty = helper.add(x.pre_qc_minus_qty, x.qc_minus_qty);
+                    x.final_1_qty = helper.add(x.quantity, x.end_qc_minus_qty);
+                });
 
                 const projRela = await this.ctx.service.project.getFunRela(this.ctx.session.sessionProject.id);
                 const checkDataModel = require('../lib/ledger').checkData;
@@ -442,8 +471,8 @@ module.exports = app => {
                     preStageData = [];
                 }
                 this.ctx.helper.assignRelaData(responseData.data, [
-                    { data: curStageData, fields: ['contract_qty', 'qc_qty', 'postil'], prefix: '', relaId: 'pid' },
-                    { data: preStageData, fields: ['contract_qty', 'qc_qty'], prefix: 'pre_', relaId: 'pid' },
+                    { data: curStageData, fields: ['contract_qty', 'qc_qty', 'qc_minus_qty', 'postil'], prefix: '', relaId: 'pid' },
+                    { data: preStageData, fields: ['contract_qty', 'qc_qty', 'qc_minus_qty'], prefix: 'pre_', relaId: 'pid' },
                 ]);
                 ctx.body = responseData;
             } catch (err) {
@@ -503,7 +532,8 @@ module.exports = app => {
                 }
                 const bills = data.bills ? data.bills : await ctx.service.ledger.getDataById(data.pos.lid);
                 const pos = data.pos;
-                const changes = await ctx.service.change.getValidChanges(ctx.tender, ctx.stage, bills);
+                const projectFunInfo = await this.ctx.service.project.getFunRela(ctx.session.sessionProject.id);
+                const changes = await ctx.service.change.getValidChanges(ctx.tender, ctx.stage, data, projectFunInfo.minusNoValue && ctx.tender.info.fun_rela.stage_change.minusNoValue);
                 const useChanges = ctx.stage.readOnly
                     ? await ctx.service.stageChange.getAuditorStageData(ctx.tender.id, ctx.stage.id, ctx.stage.curTimes, ctx.stage.curOrder, bills.id, pos ? pos.id : -1)
                     : await ctx.service.stageChange.getLastestStageData(ctx.tender.id, ctx.stage.id, bills.id, pos ? pos.id : -1);
@@ -526,14 +556,14 @@ module.exports = app => {
                 if (!data.target || (!data.target.bills && !data.target.pos) || !data.change) {
                     throw '调用变更令数据错误';
                 }
-                let result, minus, posMinus;
+                let result;
                 if (data.target.pos) {
-                    result = await ctx.service.stageChange.posChange(data.target.pos, data.change);
+                    result = await ctx.service.stageChange.posChange(data.target.pos, data.target.minus, data.change);
                     result.change = { target: { lid: data.target.pos.lid, pid: data.target.pos.id } };
                     result.change.data = await ctx.service.stageChange.getLastestStageData(ctx.tender.id,
                         ctx.stage.id, data.target.pos.lid, data.target.pos.id);
                 } else {
-                    result = await ctx.service.stageChange.billsChange(data.target.bills, data.change);
+                    result = await ctx.service.stageChange.billsChange(data.target.bills, data.target.minus, data.change);
                     result.change = { target: { lid: data.target.bills.id, pid: '-1' } };
                     result.change.data = await ctx.service.stageChange.getLastestStageData(ctx.tender.id,
                         ctx.stage.id, data.target.bills.id, '-1');
@@ -1368,10 +1398,10 @@ module.exports = app => {
                 if (data.main) {
                     result.main = {};
                     result.main.ledger = ctx.stage.ledgerHis
-                        ? await ctx.service.ledger.loadDataFromOss(ctx.tender.id, ctx.stage.ledgerHis.bills_file)
+                        ? await ctx.helper.loadLedgerDataFromOss(ctx.tender.id, ctx.stage.ledgerHis.bills_file)
                         : await ctx.service.ledger.getData(ctx.tender.id);
                     result.main.pos = ctx.stage.ledgerHis
-                        ? await ctx.service.pos.loadDataFromOss(ctx.tender.id, ctx.stage.ledgerHis.pos_file)
+                        ? await ctx.helper.loadLedgerDataFromOss(ctx.tender.id, ctx.stage.ledgerHis.pos_file)
                         : await ctx.service.pos.getPosData({ tid: ctx.tender.id });
                 }
                 for (const order of data.roles) {
@@ -1408,6 +1438,7 @@ module.exports = app => {
 
         async loadBwtz(ctx) {
             try {
+                this._getLedgerColumn();
                 const data = ctx.request.body.data ? JSON.parse(ctx.request.body.data) : {};
                 const ledgerData = await this._getStageLedgerData(ctx);
                 const posData = await this._getStagePosData(ctx);
@@ -2103,11 +2134,14 @@ module.exports = app => {
 
         async importStageSheet(ctx) {
             try {
+                if (!ctx.stage.status === auditConst.status.uncheck) throw '仅新增期且未上报时,可从暂存计量中导入数据';
+
                 const compressData = ctx.request.body.data;
                 const data = JSON.parse(LzString.decompressFromUTF16(compressData));
-
+                await ctx.service.stageStash.loadExcelSheet(ctx.stage, data.sheet);
                 await ctx.service.stage.updateCheckCalcFlag(ctx.stage, true);
                 await ctx.service.stage.updateCacheTime(ctx.stage.id);
+                ctx.body = { err: 0, msg: '', data: null };
             } catch (err) {
                 ctx.log(err);
                 ctx.ajaxErrorBody(err, '导入计量台账数据错误');

+ 40 - 1
app/controller/tender_controller.js

@@ -532,7 +532,7 @@ module.exports = app => {
                 ];
                 // 地图
                 const tenderALLInfo = await ctx.service.tender.getDataById(tender.id);
-                const hadMap = tenderALLInfo.had_map === 1 ? 0 : 1;
+                const hadMap = tenderALLInfo.had_map === 0 ? 1 : tenderALLInfo.had_map;// 0为初始值,因为默认可能会变化,所以暂时把0都默认为1。共三种模式坐标模式1,图片模式2,无图模式3。
                 const tenderMapList = await ctx.service.tenderMap.getAllDataByCondition({ where: { tid: tender.id } });
                 // 默认坐标,否则则取办事处坐标
                 const projectData = await ctx.service.project.getDataById(ctx.session.sessionProject.id);
@@ -571,10 +571,12 @@ module.exports = app => {
                     // reviseNum,
                     stage_total,
                     hadMap,
+                    map_pic: tenderALLInfo.map_pic,
                     jsFiles: this.app.jsFiles.common.concat(this.app.jsFiles.tender.tenderInfo),
                     gclChapter,
                     tenderMapList,
                     map_json,
+                    fujianOssPath: ctx.app.config.fujianOssPath,
                 };
                 if (ctx.session.sessionUser.is_admin) {
                     renderData.tourists = await ctx.service.tenderTourist.getTourists(tender.id);
@@ -1367,6 +1369,43 @@ module.exports = app => {
             }
         }
 
+        /**
+         * 上传静态图
+         *
+         * @param {object} ctx - egg全局变量
+         * @return {void}
+         */
+        async uploadMap(ctx) {
+            const responseData = {
+                err: 0, msg: '', data: null,
+            };
+            try {
+                const stream = await ctx.getFileStream();
+                const create_time = Date.parse(new Date()) / 1000;
+                const fileInfo = path.parse(stream.filename);
+                const filepath = `app/public/upload/${ctx.tender.id}/map/${create_time}${fileInfo.ext}`;
+                await ctx.app.fujianOss.put(ctx.app.config.fujianOssFolder + filepath, stream);
+                await sendToWormhole(stream);
+                const tenderInfo = await ctx.service.tender.getDataById(ctx.tender.id);
+                const oldMapPic = tenderInfo && tenderInfo.map_pic ? tenderInfo.map_pic : null;
+                const result = await ctx.service.tender.update({ map_pic: filepath }, { id: ctx.tender.id });
+                if (result) {
+                    // 移除旧的map_pic oss
+                    if (oldMapPic) {
+                        await ctx.app.fujianOss.delete(ctx.app.config.fujianOssFolder + oldMapPic);
+                    }
+                    responseData.data = { map_pic: filepath };
+                } else {
+                    throw '添加数据库失败';
+                }
+            } catch (err) {
+                this.log(err);
+                responseData.err = 1;
+                responseData.msg = err;
+            }
+            ctx.body = responseData;
+        }
+
         async loadData(ctx) {
             try {
                 const data = JSON.parse(ctx.request.body.data);

+ 8 - 0
app/extend/context.js

@@ -76,6 +76,14 @@ module.exports = {
         return this.app.hisOss;
     },
 
+    get stashOssPath() {
+        return this.app.config.stashOssPath;
+    },
+
+    print(str) {
+        this.getLogger('out').info(str);
+    },
+
     saveTempFile(filename, text) {
         const filepath = path.join(this.app.config.logger.dir, this.app.config.version, filename);
         this.helper.saveBufferFile(text, filepath);

+ 98 - 30
app/lib/analysis_excel.js

@@ -296,8 +296,12 @@ class ImportBaseTree {
      * @param {object} pos - 部位明细
      * @returns {*}
      */
-    addPos (pos){
+    addPos (pos, strict = false){
         if (this.finalNode && this.finalNode.pos) {
+            if (strict) {
+                const exist = this.finalNode.pos.find(x => { return x.name === pos.name; });
+                if (exist) return exist;
+            }
             pos.id = this.ctx.app.uuid.v4();
             pos.lid = this.finalNode.id;
             pos.tid = this.ctx.tender.id;
@@ -876,17 +880,12 @@ class AnalysisGclExcelTree {
     }
 }
 
-class ImportStageBaseTree {
-
-}
-
-class AnalysisStageTree {
+class AnalysisStageExcelTree extends AnalysisExcelTree {
     /**
      * 构造函数
      */
     constructor(ctx, setting) {
-        this.ctx = ctx;
-        this.setting = setting;
+        super(ctx, setting);
         this.mid = ctx.tender.id;
         this.decimal = ctx.tender.info.decimal;
         this.precision = ctx.tender.info.precision;
@@ -897,23 +896,16 @@ class AnalysisStageTree {
             pos: {value: ['计量单元'], type: colDefineType.match},
             name: {value: ['名称'], type: colDefineType.match},
             unit: {value: ['单位'], type: colDefineType.match},
+            unit_price: {value: ['单价'], type: colDefineType.match},
             contract_qty: {value: ['本期合同计量|数量'], type: colDefineType.match},
             contract_tp: {value: ['本期合同计量|金额'], type: colDefineType.match},
+            deal_dgn_qty1: {value: ['合同|项目节数量1'], type: colDefineType.match},
+            deal_dgn_qty2: {value: ['合同|项目节数量2'], type: colDefineType.match},
+            c_dgn_qty1: {value: ['变更|项目节数量1'], type: colDefineType.match},
+            c_dgn_qty2: {value: ['变更|项目节数量2'], type: colDefineType.match},
+            postil: {value: ['本期批注'], type: colDefineType.match}
         };
-        this.needCols = ['code', 'b_code', 'pos', 'name', 'unit', 'contract_qty', 'contract_tp'];
-    }
-
-    /**
-     * 读取表头并检查
-     * @param {Number} row - Excel数据行
-     */
-    checkColHeader(row) {
-        const colsDef = aeUtils.checkColHeader(row, this.colHeaderMatch);
-        let check = true;
-        for (const col of this.needCols) {
-            if (!colsDef[col]) check = false;
-        }
-        if (check) this.colsDef = colsDef;
+        this.needCols = ['code', 'b_code', 'pos', 'name', 'unit', 'unit_price', 'contract_qty', 'contract_tp'];
     }
 
     mergeHeaderRow(iRow, row, subRow, merge) {
@@ -934,8 +926,83 @@ class AnalysisStageTree {
         return result;
     }
 
-    loadRowData(row, iRow) {
-
+    /**
+     * 读取项目节节点
+     * @param {Array} row - excel行数据
+     * @returns {*}
+     * @private
+     */
+    _loadXmjNode(row) {
+        try {
+            const node = {};
+            node.code = this.ctx.helper.replaceReturn(this.ctx.helper._.trimEnd(row[this.colsDef.code]));
+            node.name = this.ctx.helper.replaceReturn(this.ctx.helper._.trimEnd(row[this.colsDef.name]));
+            node.unit = this.ctx.helper.replaceReturn(this.ctx.helper._.trimEnd(row[this.colsDef.unit]));
+            const xmj = this.cacheTree.addXmjNode(node);
+            if (xmj) {
+                xmj.deal_dgn_qty1 = aeUtils.toNumber(row[this.colsDef.deal_dgn_qty1]);
+                xmj.deal_dgn_qty2 = aeUtils.toNumber(row[this.colsDef.deal_dgn_qty2]);
+                xmj.c_dgn_qty1 = aeUtils.toNumber(row[this.colsDef.c_dgn_qty1]);
+                xmj.c_dgn_qty2 = aeUtils.toNumber(row[this.colsDef.c_dgn_qty2]);
+                xmj.postil = this.ctx.helper.replaceReturn(row[this.colsDef.postil]);
+                this.ctx.helper.checkDgnQtyPrecision(xmj);
+                return xmj;
+            } else {
+                return null;
+            }
+        } catch (error) {
+            if (error.stack) {
+                this.ctx.logger.error(error);
+            } else {
+                this.ctx.getLogger('fail').info(JSON.stringify({
+                    error,
+                    project: this.ctx.session.sessionProject,
+                    user: this.ctx.session.sessionUser,
+                    body: row,
+                }));
+            }
+            return null;
+        }
+    }
+    /**
+     * 读取工程量清单数据
+     * @param {Array} row - excel行数据
+     * @returns {*}
+     * @private
+     */
+    _loadGclNode(row) {
+        if (this.filter.filterGcl) return true;
+        const node = {};
+        node.b_code = this.ctx.helper.replaceReturn(this.ctx.helper._.trimEnd(row[this.colsDef.b_code]));
+        node.name = this.ctx.helper.replaceReturn(this.ctx.helper._.trimEnd(row[this.colsDef.name]));
+        node.unit = this.ctx.helper.replaceReturn(this.ctx.helper._.trimEnd(row[this.colsDef.unit]));
+        node.unit_price = this.ctx.helper.round(aeUtils.toNumber(row[this.colsDef.unit_price]), this.decimal.up);
+        const precision = this.ctx.helper.findPrecision(this.precision, node.unit);
+        node.contract_qty = this.ctx.helper.round(aeUtils.toNumber(row[this.colsDef.contract_qty]), precision.value);
+        if (node.contract_qty && node.unit_price) {
+            node.contract_tp = this.ctx.helper.mul(node.contract_qty, node.unit_price, this.decimal.tp);
+        } else {
+            node.contract_tp = this.ctx.helper.round(aeUtils.toNumber(row[this.colsDef.contract_tp]), this.decimal.tp);
+        }
+        node.postil = this.ctx.helper.replaceReturn(row[this.colsDef.postil]);
+        if (this.filter.filterZeroGcl && !node.contract_qty && !node.contract_tp) return true;
+        return this.cacheTree.addGclNode(node);
+    }
+    /**
+     * 读取部位明细数据
+     * @param {Array} row - excel行数据
+     * @returns {*}
+     * @private
+     */
+    _loadPos(row) {
+        if (this.filter.filterPos) return true;
+        let pos = {};
+        pos.name = this.ctx.helper.replaceReturn(row[this.colsDef.name]);
+        pos.quantity = aeUtils.toNumber(row[this.colsDef.contract_qty]);
+        pos = this.cacheTree.addPos(pos, true);
+        pos.contract_qty = pos.quantity;
+        pos.postil = this.ctx.helper.replaceReturn(row[this.colsDef.postil]);
+        return pos;
     }
 
     /**
@@ -944,20 +1011,21 @@ class AnalysisStageTree {
      * @param {Array} tempData - 新建项目使用的清单模板
      * @returns {ImportBaseTree}
      */
-    analysisData(ledger, pos, sheet) {
+    analysisData(sheet, tempData, filter) {
         this.filter = filter ? filter : {};
         this.colsDef = null;
-        this.cacheTree = this._getNewLedger();
+        this.cacheTree = this._getNewCacheTree(tempData);
         this.errorData = [];
         this.loadEnd = false;
         this.loadBegin = sheet.rows.length;
 
-        for (const iRow in sheet.rows) {
+        for (const [iRow, row] of sheet.rows.entries()) {
             if (this.colsDef && !this.loadEnd) {
                 if (iRow < this.loadBegin) continue;
-                this.loadRowData(sheet.rows[iRow], iRow);
+                this.loadRowData(row, iRow);
             } else {
-                const mergeRow = this.mergeHeaderRow(iRow, sheet.rows[iRow], sheet.rows[iRow + 1], sheet.merge);
+                if (iRow === sheet.rows.length - 1) continue;
+                const mergeRow = this.mergeHeaderRow(iRow, row, sheet.rows[iRow + 1], sheet.merge);
                 this.checkColHeader(mergeRow);
                 if (this.colsDef) this.loadBegin = iRow + 2;
             }
@@ -967,4 +1035,4 @@ class AnalysisStageTree {
     }
 }
 
-module.exports = { AnalysisExcelTree, AnalysisGclExcelTree, AnalysisStageTree };
+module.exports = { AnalysisExcelTree, AnalysisGclExcelTree, AnalysisStageExcelTree };

+ 16 - 0
app/lib/bills_pos_convert.js

@@ -98,6 +98,9 @@ class BillsPosConvert {
         node.pre_gather_qty = this.ctx.helper.add(node.pre_gather_qty, data.pre_gather_qty);
 
         node.real_qty = this.ctx.helper.add(node.real_qty, data.real_qty);
+
+        node.qc_minus_qty = this.ctx.helper.add(node.qc_minus_qty, data.qc_minus_qty);
+        node.pre_qc_minus_qty = this.ctx.helper.add(node.pre_qc_minus_qty, data.pre_qc_minus_qty);
     }
     _loadBillsCalcFields(node, data) {
         node.quantity = this.ctx.helper.add(node.quantity, data.quantity);
@@ -114,6 +117,9 @@ class BillsPosConvert {
         node.pre_qc_qty = this.ctx.helper.add(node.pre_qc_qty, data.pre_qc_qty);
         node.pre_qc_tp = this.ctx.helper.add(node.pre_qc_tp, data.pre_qc_tp);
         node.pre_gather_qty = this.ctx.helper.add(node.pre_gather_qty, data.pre_gather_qty);
+
+        node.qc_minus_qty = this.ctx.helper.add(node.qc_minus_qty, data.qc_minus_qty);
+        node.pre_qc_minus_qty = this.ctx.helper.add(node.pre_qc_minus_qty, data.pre_qc_minus_qty);
     }
     _convertGcl(node, xmj) {
         if (!xmj) return;
@@ -235,6 +241,13 @@ class BillsPosConvert {
         child.estimate_tp = this.ctx.helper.mul(child.estimate_qty, child.unit_price, tpDecimal);
 
         child.bgl_code = this.ctx.helper._.uniq(this.ctx.helper._.map(child.changes, 'c_code')).join(';');
+
+        // !#台账相关
+        child.end_qc_minus_qty = this.ctx.helper.add(child.pre_qc_minus_qty, child.qc_minus_qty); // 1#台账
+        child.final_1_qty = this.ctx.helper.add(child.end_qc_minus_qty, child.quantity); // 1#台账 = 台账+负变更
+        child.final_1_tp = this.ctx.helper.mul(child.unit_price, child.final_1_qty, tpDecimal);
+        child.end_final_1_tp = this.ctx.helper.add(child.final_1_tp, child.end_qc_tp);
+        child.end_final_1_percent = this.ctx.helper.mul(this.ctx.helper.div(child.end_gather_tp, child.end_final_1_tp, 4), 100);
     }
     _calculateNode(node, children) {
         for (const child of children) {
@@ -250,11 +263,14 @@ class BillsPosConvert {
             node.end_gather_tp = this.ctx.helper.add(node.end_gather_tp, child.end_gather_tp);
             node.real_tp = this.ctx.helper.add(node.real_tp, child.real_tp);
             node.estimate_tp = this.ctx.helper.add(node.estimate_tp, child.estimate_tp);
+            node.final_1_tp = this.ctx.helper.add(node.final_1_tp, child.final_1_tp);
         }
         if (node.dgn_qty1)
             node.dgn_price = this.ctx.helper.div(node.total_price, node.dgn_qty1, this.ctx.tender.info.decimal.up);
         node.final_tp = this.ctx.helper.add(node.total_price, node.end_qc_tp);
+        node.end_final_1_tp = this.ctx.helper.add(node.final_1_tp, node.end_qc_tp);
         node.end_gather_percent = this.ctx.helper.mul(this.ctx.helper.div(node.end_gather_tp, node.final_tp, 4), 100);
+        node.end_final_1_percent = this.ctx.helper.mul(this.ctx.helper.div(node.end_gather_tp, node.end_final_1_tp, 4), 100);
     }
     _recursiveCalcUnitNodes(nodes) {
         if (!nodes || !nodes instanceof Array || nodes.length === 0) return;

+ 5 - 5
app/lib/ledger.js

@@ -508,7 +508,7 @@ class gatherTree extends baseTree {
     resortChildrenDefault() {
         const helper = this.ctx.helper;
         this.resortChildrenByCustom((x, y) => {
-            const iCode = helper.compareCode(x.code, y.code);
+            const iCode = (x.code || y.code) ? helper.compareCode(x.code, y.code) : helper.compareCode(x.b_code, y.b_code);
             if (iCode) return iCode;
             if (!x.name) return -1;
             if (!y.name) return 1;
@@ -633,7 +633,7 @@ class checkData {
                 if (!data.contract_qty && !data.qc_qty && !data.pre_contract_qty && !data.pre_qc_qty) return 2; // 漏计
             } else {
                 const precision = this.ctx.helper.findPrecision(this.ctx.tender.info.precision, unit);
-                const checkQty = this.ctx.helper.mul(data.quantity, this.ctx.helper.div(ratio, 100, 4), precision.value);
+                const checkQty = this.ctx.helper.mul(data.final_1_qty, this.ctx.helper.div(ratio, 100, 4), precision.value);
                 const qty = this.ctx.helper.add(data.contract_qty, data.pre_contract_qty);
                 if (qty > checkQty) return 1; // 违规
                 if (qty < checkQty) return 2; // 漏计
@@ -901,9 +901,9 @@ class checkData {
                     const end_contract_qty = this.ctx.helper.add(p.pre_contract_qty, p.contract_qty);
                     if (!p.quantity && !!end_contract_qty) return true;
                     if (p.quantity > 0) {
-                        if (end_contract_qty > p.quantity) return true;
+                        if (end_contract_qty > p.final_1_qty) return true;
                     } else {
-                        if (end_contract_qty < p.quantity || end_contract_qty > 0) return true;
+                        if (end_contract_qty < p.final_1_qty || end_contract_qty > 0) return true;
                     }
                 }
                 return false;
@@ -916,7 +916,7 @@ class checkData {
                 if (!compare_tp) return !!end_contract_tp;
                 return compare_tp >= 0 ? end_contract_tp > compare_tp : end_contract_tp < compare_tp || end_contract_tp > 0;
             } else {
-                const compare_qty = isTz ? bills.quantity : bills.deal_qty;
+                const compare_qty = isTz ? bills.final_1_qty : bills.deal_final_1_qty;
                 if (!compare_qty) return !!end_contract_qty;
                 return compare_qty >= 0 ? end_contract_qty > compare_qty : end_contract_qty < compare_qty || end_contract_qty > 0;
             }

+ 1 - 1
app/lib/rptCustomData.js

@@ -304,7 +304,7 @@ class jhHelper {
         this.ctx.helper.saveBufferFile(JSON.stringify(stageChangeDetail, '', '\t'), this.ctx.app.baseDir + '/temp.json');
         for (const dc of gsDefine.defaultCompare) {
             if (!auditors[dc]) continue;
-             const scd = helper.filterTimesOrderData(stageChangeDetail, ['lid', 'pid', 'cid', 'cbid'], 'stimes', 'sorder', auditors[dc].times, auditors[dc].order);
+             const scd = helper.filterTimesOrderData(stageChangeDetail, ['lid', 'pid', 'cbid', 'no_value'], 'stimes', 'sorder', auditors[dc].times, auditors[dc].order);
             this._loadChangeDetail(billsIndex, scd, gsDefine, `r${dc}_`);
             this.prefixes.push(`r${dc}_`);
         }

+ 59 - 52
app/lib/stage_im.js

@@ -34,6 +34,7 @@ class StageIm {
                     node.gather_qty = self.ctx.helper.add(node.contract_qty, node.qc_qty);
                     node.end_contract_qty = self.ctx.helper.add(node.pre_contract_qty, node.contract_qty);
                     node.end_qc_qty = self.ctx.helper.add(node.pre_qc_qty, node.qc_qty);
+                    node.end_qc_minus_qty = self.ctx.helper.add(node.pre_qc_minus_qty, node.qc_minus_qty);
                     node.end_gather_qty = self.ctx.helper.add(node.pre_gather_qty, node.gather_qty);
                 }
                 node.pre_gather_tp = self.ctx.helper.add(node.pre_contract_tp, node.pre_qc_tp);
@@ -45,12 +46,13 @@ class StageIm {
         });
         this.pos = new Ledger.pos({
             id: 'id', ledgerId: 'lid',
-            updateFields: ['contract_qty', 'qc_qty', 'postil'],
+            updateFields: ['contract_qty', 'qc_qty', 'qc_minus_qty', 'postil'],
             calc(p) {
                 p.pre_gather_qty = self.ctx.helper.add(p.pre_contract_qty, p.pre_qc_qty);
                 p.gather_qty = self.ctx.helper.add(p.contract_qty, p.qc_qty);
                 p.end_contract_qty = self.ctx.helper.add(p.pre_contract_qty, p.contract_qty);
                 p.end_qc_qty = self.ctx.helper.add(p.pre_qc_qty, p.qc_qty);
+                p.end_qc_minus_qty = self.ctx.helper.add(p.pre_qc_minus_qty, p.qc_minus_qty);
                 p.end_gather_qty = self.ctx.helper.add(p.pre_gather_qty, p.gather_qty);
             },
         });
@@ -69,42 +71,28 @@ class StageIm {
     // 加载数据
     async _loadMainData() {
         const billsData = await this.ctx.service.ledger.getData(this.ctx.tender.id);
-        if (this.ctx.stage.readOnly) {
-            const curStage = await this.ctx.service.stageBills.getAuditorStageData2(this.ctx.tender.id,
-                this.ctx.stage.id, this.ctx.stage.curTimes, this.ctx.stage.curOrder);
-            this.ctx.helper.assignRelaData(billsData, [
-                { data: curStage, fields: ['contract_qty', 'contract_tp', 'qc_qty', 'qc_tp'], prefix: '', relaId: 'lid' },
-            ]);
-        } else {
-            const curStage = await this.ctx.service.stageBills.getLastestStageData2(this.ctx.tender.id, this.ctx.stage.id);
-            this.ctx.helper.assignRelaData(billsData, [
-                { data: curStage, fields: ['contract_qty', 'contract_tp', 'qc_qty', 'qc_tp'], prefix: '', relaId: 'lid' },
-            ]);
-        }
+        const curStage = this.ctx.stage.readOnly
+            ? await this.ctx.service.stageBills.getAuditorStageData2(this.ctx.tender.id,
+                this.ctx.stage.id, this.ctx.stage.curTimes, this.ctx.stage.curOrder)
+            : await this.ctx.service.stageBills.getLastestStageData2(this.ctx.tender.id, this.ctx.stage.id);
         const preStage = this.ctx.stage.order > 1 ? await this.ctx.service.stageBillsFinal.getFinalData(this.ctx.tender, this.ctx.stage.order - 1) : [];
 
         this.ctx.helper.assignRelaData(billsData, [
-            { data: preStage, fields: ['contract_qty', 'contract_tp', 'qc_qty', 'qc_tp'], prefix: 'pre_', relaId: 'lid' },
+            { data: curStage, fields: ['contract_qty', 'contract_tp', 'qc_qty', 'qc_tp', 'qc_minus_qty'], prefix: '', relaId: 'lid' },
+            { data: preStage, fields: ['contract_qty', 'contract_tp', 'qc_qty', 'qc_tp', 'qc_minus_qty'], prefix: 'pre_', relaId: 'lid' },
         ]);
         this.billsTree.loadDatas(billsData);
         this.billsTree.calculateAll();
 
         const posData = await this.ctx.service.pos.getAllDataByCondition({ where: { tid: this.ctx.tender.id } });
-        if (this.ctx.stage.readOnly) {
-            const curPosStage = await this.ctx.service.stagePos.getAuditorStageData2(this.ctx.tender.id,
-                this.ctx.stage.id, this.ctx.stage.curTimes, this.ctx.stage.curOrder);
-            this.ctx.helper.assignRelaData(posData, [
-                { data: curPosStage, fields: ['contract_qty', 'qc_qty'], prefix: '', relaId: 'pid' },
-            ]);
-        } else {
-            const curPosStage = await this.ctx.service.stagePos.getLastestStageData2(this.ctx.tender.id, this.ctx.stage.id);
-            this.ctx.helper.assignRelaData(posData, [
-                { data: curPosStage, fields: ['contract_qty', 'qc_qty'], prefix: '', relaId: 'pid' },
-            ]);
-        }
+        const curPosStage = this.ctx.stage.readOnly
+            ? await this.ctx.service.stagePos.getAuditorStageData2(this.ctx.tender.id,
+                this.ctx.stage.id, this.ctx.stage.curTimes, this.ctx.stage.curOrder)
+            : await this.ctx.service.stagePos.getLastestStageData2(this.ctx.tender.id, this.ctx.stage.id);
         const prePosStage = this.ctx.stage.order > 1 ? await this.ctx.service.stagePosFinal.getFinalData(this.ctx.tender, this.ctx.stage.order - 1) : [];
         this.ctx.helper.assignRelaData(posData, [
-            { data: prePosStage, fields: ['contract_qty', 'qc_qty'], prefix: 'pre_', relaId: 'pid' },
+            { data: curPosStage, fields: ['contract_qty', 'qc_qty', 'qc_minus_qty'], prefix: '', relaId: 'pid' },
+            { data: prePosStage, fields: ['contract_qty', 'qc_qty', 'qc_minus_qty'], prefix: 'pre_', relaId: 'pid' },
         ]);
         this.pos.loadDatas(posData);
         this.pos.calculateAll();
@@ -376,10 +364,10 @@ class StageIm {
         if (im.calc_memo !== undefined && im.calc_memo !== null && im.calc_memo !== '') return;
 
         if (im.leafXmjs && im.leafXmjs.length > 0) {
-            const memo = ['本期计量:' + (this.ctx.helper.checkZero(im.jl) ? 0 : im.jl) + ' ' + im.unit];
+            const memo = ['本期计量:' + (im.jl ? 0 : im.jl) + (im.qc_minus_jl ? (` (不计价 ${im.qc_minus_jl}) `) : ' ') + im.unit];
             for (const lx of im.leafXmjs) {
                 for (const p of lx.pos) {
-                    memo.push(p.name + ':' + p.jl + ' ' + im.unit);
+                    memo.push(p.name + ':' + p.jl + (p.qc_minus_jl ? (` (不计价 ${p.qc_minus_jl}) `) : ' ') + im.unit);
                 }
             }
             im.calc_memo = memo.join('\n');
@@ -389,10 +377,10 @@ class StageIm {
                 if (b.pos && b.pos.length > 0) {
                     memo.push('清单' + (i + 1) + ':' + b.b_code + ' ' + b.name);
                     for (const p of b.pos) {
-                        memo.push(p.name + ':' + p.jl + ' ' + b.unit);
+                        memo.push(p.name + ':' + p.jl + (p.qc_minus_jl ? (` (不计价 ${p.qc_minus_jl}) `) : ' ') + b.unit);
                     }
                 } else {
-                    memo.push('清单' + (i + 1) + ':' + b.b_code + ' ' + b.name + ':' + (this.ctx.helper.checkZero(b.jl) ? 0 : b.jl) + ' ' + b.unit);
+                    memo.push('清单' + (i+1) + ':' + b.b_code + ' ' + b.name + ':' + (b.jl ? 0 : b.jl) + (b.qc_minus_jl ? (` (不计价 ${b.qc_minus_jl}) `) : ' ') + b.unit);
                 }
             }
             im.calc_memo = memo.join('\n');
@@ -425,6 +413,7 @@ class StageIm {
             lp.jl = this.ctx.helper.add(lp.jl, p.gather_qty);
             lp.contract_jl = this.ctx.helper.add(lp.contract_jl, p.contract_qty);
             lp.qc_jl = this.ctx.helper.add(lp.qc_jl, p.qc_qty);
+            lp.qc_minus_jl = this.ctx.helper.add(lp.qc_minus_jl, p.qc_minus_qty);
         }
     }
     _recursiveGenerateTzGclBills(node, im) {
@@ -435,7 +424,7 @@ class StageIm {
                 if ((!p.b_code || p.b_code === '') || (p.children && p.children.length > 0)) continue;
 
                 if (this.ctx.helper.checkZero(p.contract_qty) && this.ctx.helper.checkZero(p.contract_tp) &&
-                    this.ctx.helper.checkZero(p.qc_qty) && this.ctx.helper.checkZero(p.qc_tp)) {
+                    this.ctx.helper.checkZero(p.qc_qty) && this.ctx.helper.checkZero(p.qc_tp) && this.ctx.helper.checkZero(p.qc_minus_qty)) {
                     continue;
                 }
                 let b = this._.find(im.gclBills, { bid: p.id });
@@ -449,6 +438,7 @@ class StageIm {
                 b.jl = this.ctx.helper.add(b.jl, p.gather_qty);
                 b.contract_jl = this.ctx.helper.add(b.contract_jl, p.contract_qty);
                 b.qc_jl = this.ctx.helper.add(b.qc_jl, p.qc_qty);
+                b.qc_minus_jl = this.ctx.helper.add(b.qc_minus_jl, p.qc_minus_qty);
 
                 b.tp = this.ctx.helper.add(b.tp, p.gather_tp);
                 b.contract_tp = this.ctx.helper.add(b.contract_tp, p.contract_tp);
@@ -457,6 +447,7 @@ class StageIm {
                 b.pre_jl = this.ctx.helper.add(b.pre_jl, p.pre_gather_qty);
                 b.pre_contract_jl = this.ctx.helper.add(b.pre_contract_jl, p.pre_contract_qty);
                 b.pre_qc_jl = this.ctx.helper.add(b.pre_qc_jl, p.pre_qc_qty);
+                b.pre_qc_minus_jl = this.ctx.helper.add(b.pre_qc_minus_jl, p.pre_qc_minus_qty);
 
                 b.pre_tp = this.ctx.helper.add(b.pre_tp, p.pre_gather_tp);
                 b.pre_contract_tp = this.ctx.helper.add(b.pre_contract_tp, p.pre_contract_tp);
@@ -465,6 +456,7 @@ class StageIm {
                 b.end_jl = this.ctx.helper.add(b.end_jl, p.end_gather_qty);
                 b.end_contract_jl = this.ctx.helper.add(b.end_contract_jl, p.end_contract_qty);
                 b.end_qc_jl = this.ctx.helper.add(b.end_qc_jl, p.end_qc_qty);
+                b.end_qc_minus_jl = this.ctx.helper.add(b.end_qc_minus_jl, p.end_qc_minus_qty);
 
                 b.end_tp = this.ctx.helper.add(b.end_tp, p.end_gather_tp);
                 b.end_contract_tp = this.ctx.helper.add(b.end_contract_tp, p.end_contract_tp);
@@ -515,23 +507,23 @@ class StageIm {
             for (const p of posterity) {
                 if (p.children && p.children.length > 0) continue;
                 if (!helper.checkZero(p.contract_qty) || !helper.checkZero(p.contract_tp) ||
-                    !helper.checkZero(p.qc_qty) || !helper.checkZero(p.qc_tp))
+                    !helper.checkZero(p.qc_qty) || !helper.checkZero(p.qc_tp) || !helper.checkZero(p.qc_minus_qty))
                     return true;
                 const pPos = this.pos.getLedgerPos(p.id);
                 if (!pPos || pPos.length === 0) continue;
                 for (const pp of pPos) {
-                    if (!helper.checkZero(pp.contract_qty) || !helper.checkZero(pp.qc_qty)) return true;
+                    if (!helper.checkZero(pp.contract_qty) || !helper.checkZero(pp.qc_qty) || !helper.checkZero(pp.qc_minus_qty)) return true;
                 }
             }
             return false;
         } else {
             if (!helper.checkZero(node.contract_qty) || !helper.checkZero(node.contract_tp) ||
-                !helper.checkZero(node.qc_qty) || !helper.checkZero(node.qc_tp))
+                !helper.checkZero(node.qc_qty) || !helper.checkZero(node.qc_tp) || !helper.checkZero(node.qc_minus_qty))
                 return true;
             const pPos = this.pos.getLedgerPos(node.id);
             if (!pPos || pPos.length === 0) return false;
             for (const pp of pPos) {
-                if (!helper.checkZero(pp.contract_qty) || !helper.checkZero(pp.qc_qty)) return true;
+                if (!helper.checkZero(pp.contract_qty) || !helper.checkZero(pp.qc_qty) || !helper.checkZero(pp.qc_minus_qty)) return true;
             }
         }
     }
@@ -548,7 +540,7 @@ class StageIm {
         const im = {
             id: this.ImData.length + 1,
             lid: node.id, pid: '', code: node.code,
-            jl: node.gather_tp, contract_jl: node.contract_tp, qc_jl: node.qc_tp,
+            jl: node.gather_tp, contract_jl: node.contract_tp, qc_jl: node.qc_tp, qc_minus_jl: 0,
             pre_jl: node.pre_gather_tp, pre_contract_jl: node.pre_contract_tp, pre_qc_jl: node.pre_qc_tp,
             end_jl: node.end_gather_tp, end_contract_jl: node.end_contract_tp, end_qc_jl: node.end_qc_tp,
             peg: peg ? this._getPegStr(peg.name) : '', drawing_code: this._getDrawingCode(node),
@@ -591,6 +583,7 @@ class StageIm {
             gcl.jl = helper.add(gcl.jl, pos.gather_qty);
             gcl.contract_jl = helper.add(gcl.contract_jl, pos.contract_qty);
             gcl.qc_jl = helper.add(gcl.qc_jl, pos.qc_qty);
+            gcl.qc_minus_jl = helper.add(gcl.qc_minus_jl, pos.qc_minus_qty);
 
             gcl.tp = helper.mul(gcl.unit_price, gcl.jl, tp_decimal);
             gcl.contract_tp = helper.mul(gcl.unit_price, gcl.contract_jl, tp_decimal);
@@ -599,6 +592,7 @@ class StageIm {
             gcl.pre_jl = helper.add(gcl.pre_jl, pos.pre_gather_qty);
             gcl.pre_contract_jl = helper.add(gcl.pre_contract_jl, pos.pre_contract_qty);
             gcl.pre_qc_jl = helper.add(gcl.pre_qc_jl, pos.pre_qc_qty);
+            gcl.pre_qc_minus_jl = helper.add(gcl.pre_qc_minus_jl, pos.pre_qc_minus_qty);
 
             gcl.pre_tp = helper.mul(gcl.unit_price, gcl.pre_jl, tp_decimal);
             gcl.pre_contract_tp = helper.mul(gcl.unit_price, gcl.pre_contract_jl, tp_decimal);
@@ -607,6 +601,7 @@ class StageIm {
             gcl.end_jl = helper.add(gcl.end_jl, pos.end_gather_qty);
             gcl.end_contract_jl = helper.add(gcl.end_contract_jl, pos.end_contract_qty);
             gcl.end_qc_jl = helper.add(gcl.end_qc_jl, pos.end_qc_qty);
+            gcl.end_qc_minus_jl = helper.add(gcl.end_qc_minus_jl, pos.end_qc_minus_qty);
 
             gcl.end_tp = helper.mul(gcl.unit_price, gcl.end_jl, tp_decimal);
             gcl.end_contract_tp = helper.mul(gcl.unit_price, gcl.end_contract_jl, tp_decimal);
@@ -618,6 +613,7 @@ class StageIm {
             gcl.jl = helper.add(gcl.jl, bills.gather_qty);
             gcl.contract_jl = helper.add(gcl.contract_jl, bills.contract_qty);
             gcl.qc_jl = helper.add(gcl.qc_jl, bills.qc_qty);
+            gcl.qc_minus_jl = helper.add(gcl.qc_minus_jl, bills.qc_minus_qty);
 
             gcl.tp = helper.add(gcl.tp, bills.gather_tp);
             gcl.contract_tp = helper.add(gcl.contract_tp, bills.contract_tp);
@@ -626,6 +622,7 @@ class StageIm {
             gcl.pre_jl = helper.add(gcl.pre_jl, bills.pre_gather_qty);
             gcl.pre_contract_jl = helper.add(gcl.pre_contract_jl, bills.pre_contract_qty);
             gcl.pre_qc_jl = helper.add(gcl.pre_qc_jl, bills.pre_qc_qty);
+            gcl.pre_qc_minus_jl = helper.add(gcl.pre_qc_minus_jl, bills.pre_qc_minus_qty);
 
             gcl.pre_tp = helper.add(gcl.pre_tp, bills.pre_gather_tp);
             gcl.pre_contract_tp = helper.add(gcl.pre_contract_tp, bills.pre_contract_tp);
@@ -634,6 +631,7 @@ class StageIm {
             gcl.end_jl = helper.add(gcl.end_jl, bills.end_gather_qty);
             gcl.end_contract_jl = helper.add(gcl.end_contract_jl, bills.end_contract_qty);
             gcl.end_qc_jl = helper.add(gcl.end_qc_jl, bills.end_qc_qty);
+            gcl.end_qc_minus_jl = helper.add(gcl.end_qc_minus_jl, bills.end_qc_minus_qty);
 
             gcl.end_tp = helper.add(gcl.end_tp, bills.end_gather_tp);
             gcl.end_contract_tp = helper.add(gcl.end_contract_tp, bills.end_contract_tp);
@@ -644,6 +642,7 @@ class StageIm {
         const tp_decimal = this.ctx.tender.info.decimal.tp;
         im.contract_jl = 0;
         im.qc_jl = 0;
+        im.qc_minus_jl = 0;
         for (const b of im.gclBills) {
             im.contract_jl = this.ctx.helper.add(im.contract_jl, this.ctx.helper.mul(b.contract_jl, b.unit_price, tp_decimal));
             im.pre_contract_jl = this.ctx.helper.add(im.pre_contract_jl, this.ctx.helper.mul(b.pre_contract_jl, b.unit_price, tp_decimal));
@@ -703,7 +702,7 @@ class StageIm {
             const pPos = this.pos.getLedgerPos(p.id);
             if (pPos && pPos.length > 0) {
                 for (const pp of pPos) {
-                    if (!pp.gather_qty && !pp.contract_qty && !pp.qc_qty) continue;
+                    if (!pp.gather_qty && !pp.contract_qty && !pp.qc_qty && !pp.qc_minus_qty) continue;
 
                     const im = this._getBwBillsPosIm(nodeImData, node, peg, nodeIndex, bw, pp.name);
 
@@ -728,10 +727,13 @@ class StageIm {
 
                 imDefault.contract_jl = this.ctx.helper.add(imDefault.contract_jl, p.contract_qty);
                 imDefault.qc_jl = this.ctx.helper.add(imDefault.qc_jl, p.qc_qty);
+                imDefault.qc_minus_jl = this.ctx.helper.add(imDefault.qc_minus_jl, p.qc_minus_qty);
                 imDefault.pre_contract_jl = this.ctx.helper.add(imDefault.pre_contract_jl, p.pre_contract_qty);
                 imDefault.pre_qc_jl = this.ctx.helper.add(imDefault.pre_qc_jl, p.pre_qc_qty);
+                imDefault.pre_qc_minus_jl = this.ctx.helper.add(imDefault.pre_qc_minus_jl, p.pre_qc_minus_qty);
                 imDefault.end_contract_jl = this.ctx.helper.add(imDefault.end_contract_jl, p.end_contract_qty);
                 imDefault.end_qc_jl = this.ctx.helper.add(imDefault.end_qc_jl, p.end_qc_qty);
+                imDefault.end_qc_minus_jl = this.ctx.helper.add(imDefault.end_qc_minus_jl, p.end_qc_minus_qty);
                 imDefault.used = true;
 
                 this._addBwBillsGclBills(imDefault, p);
@@ -762,7 +764,7 @@ class StageIm {
         const posRange = this.pos.getLedgerPos(node.id);
         if (!posRange) { return; }
         for (const p of posRange) {
-            if (!p.gather_qty || this.ctx.helper.checkZero(p.gather_qty)) { continue; }
+            if (!p.contract_qty && !p.qc_qty && !p.qc_minus_qty) { continue; }
             let lp = this._.find(lx.pos, { name: p.name });
             if (!lp) {
                 lp = { name: p.name };
@@ -771,6 +773,7 @@ class StageIm {
             lp.jl = this.ctx.helper.add(lp.jl, p.gather_qty);
             lp.contract_jl = this.ctx.helper.add(lp.contract_jl, p.contract_qty);
             lp.qc_jl = this.ctx.helper.add(lp.qc_jl, p.qc_qty);
+            lp.qc_minus_jl = this.ctx.helper.add(lp.qc_minus_jl, p.qc_minus_qty);
         }
     }
     _generateZlLeafXmjData(node, im) {
@@ -791,6 +794,7 @@ class StageIm {
         lx.jl = this.ctx.helper.add(lx.jl, node.gather_qty);
         lx.contract_jl = this.ctx.helper.add(lx.contract_jl, node.contract_qty);
         lx.qc_jl = this.ctx.helper.add(lx.qc_jl, node.qc_qty);
+        lx.qc_minus_jl = this.ctx.helper.add(lx.qc_minus_jl, node.qc_minus_qty);
         this._generateZlPosData(node, lx);
     }
     _generateZlChangeData(node, im) {
@@ -839,9 +843,9 @@ class StageIm {
                     id: this.ImData.length + 1,
                     lid: node.id, pid: '', code: p.b_code, name: p.name, unit: p.unit, unit_price: p.unit_price, org_unit_price: p.org_unit_price,
                     quantity: 0, total_price: 0,
-                    jl: 0, contract_jl: 0, qc_jl: 0,
-                    pre_jl: 0, pre_contract_jl: 0, pre_qc_jl: 0,
-                    end_jl: 0, end_contract_jl: 0, end_qc_jl: 0,
+                    jl: 0, contract_jl: 0, qc_jl: 0, qc_minus_jl: 0,
+                    pre_jl: 0, pre_contract_jl: 0, pre_qc_jl: 0, pre_qc_minus_jl: 0,
+                    end_jl: 0, end_contract_jl: 0, end_qc_jl: 0, end_qc_minus_jl: 0,
                     tp: 0, contract_tp: 0, qc_tp: 0,
                     pre_tp: 0, pre_contract_tp: 0, pre_qc_tp: 0,
                     end_tp: 0, end_contract_tp: 0, end_qc_tp: 0,
@@ -874,6 +878,7 @@ class StageIm {
             im.jl = this.ctx.helper.add(im.jl, p.gather_qty);
             im.contract_jl = this.ctx.helper.add(im.contract_jl, p.contract_qty);
             im.qc_jl = this.ctx.helper.add(im.qc_jl, p.qc_qty);
+            im.qc_minus_jl = this.ctx.helper.add(im.qc_minus_jl, p.qc_minus_qty);
 
             im.tp = this.ctx.helper.add(im.tp, p.gather_tp);
             im.contract_tp = this.ctx.helper.add(im.contract_tp, p.contract_tp);
@@ -882,6 +887,7 @@ class StageIm {
             im.pre_jl = this.ctx.helper.add(im.pre_jl, p.pre_gather_qty);
             im.pre_contract_jl = this.ctx.helper.add(im.pre_contract_jl, p.pre_contract_qty);
             im.pre_qc_jl = this.ctx.helper.add(im.pre_qc_jl, p.pre_qc_qty);
+            im.pre_qc_minus_jl = this.ctx.helper.add(im.pre_qc_minus_jl, p.pre_qc_minus_qty);
 
             im.pre_tp = this.ctx.helper.add(im.pre_tp, p.pre_gather_tp);
             im.pre_contract_tp = this.ctx.helper.add(im.pre_contract_tp, p.pre_contract_tp);
@@ -890,6 +896,7 @@ class StageIm {
             im.end_jl = this.ctx.helper.add(im.end_jl, p.end_gather_qty);
             im.end_contract_jl = this.ctx.helper.add(im.end_contract_jl, p.end_contract_qty);
             im.end_qc_jl = this.ctx.helper.add(im.end_qc_jl, p.end_qc_qty);
+            im.end_qc_minus_jl = this.ctx.helper.add(im.end_qc_minus_jl, p.end_qc_minus_qty);
 
             im.end_tp = this.ctx.helper.add(im.end_tp, p.end_gather_tp);
             im.end_contract_tp = this.ctx.helper.add(im.end_contract_tp, p.end_contract_tp);
@@ -909,14 +916,14 @@ class StageIm {
             if (pPos && pPos.length > 0) {
                 const nodeIndex = this.billsTree.getNodeSerialNo(node);
                 for (const pp of pPos) {
-                    if (this.ctx.helper.checkZero(pp.contract_qty) && this.ctx.helper.checkZero(pp.qc_qty)) { continue; }
+                    if (this.ctx.helper.checkZero(pp.contract_qty) && this.ctx.helper.checkZero(pp.qc_qty) && this.ctx.helper.checkZero(pp.qc_minus_qty)) { continue; }
                     const im = {
                         id: this.ImData.length + 1,
                         lid: node.id, code: p.b_code, name: p.name, unit: p.unit, unit_price: p.unit_price, org_unit_price: p.org_unit_price, pid: pp.id,
                         quantity: pp.quantity,
-                        jl: pp.gather_qty, contract_jl: pp.contract_qty, qc_jl: pp.qc_qty,
-                        pre_jl: pp.pre_gather_qty, pre_contract_jl: pp.pre_contract_qty, pre_qc_jl: pp.pre_qc_qty,
-                        end_jl: pp.end_gather_qty, end_contract_jl: pp.end_contract_qty, end_qc_jl: pp.end_qc_qty,
+                        jl: pp.gather_qty, contract_jl: pp.contract_qty, qc_jl: pp.qc_qty, qc_minus_jl: pp.qc_minus_qty,
+                        pre_jl: pp.pre_gather_qty, pre_contract_jl: pp.pre_contract_qty, pre_qc_jl: pp.pre_qc_qty, pre_qc_minus_jl: pp.pre_qc_minus_qty,
+                        end_jl: pp.end_gather_qty, end_contract_jl: pp.end_contract_qty, end_qc_jl: pp.end_qc_qty, end_qc_minus_jl: pp.end_qc_minus_qty,
                         bw,
                         peg: this._checkPeg(pp.name) ? this._getPegStr(pp.name) : (peg ? this._getPegStr(peg.name) : ''),
                         dwgc: this._getDwgc(peg, node), fbgc: this._getFbgc(peg, node), fxgc: this._getFxgc(peg, node),
@@ -936,7 +943,7 @@ class StageIm {
                     im.end_tp = this.ctx.helper.mul(im.end_jl, im.unit_price, tp_decimal);
                     im.end_contract_tp = this.ctx.helper.mul(im.end_contract_jl, im.unit_price, tp_decimal);
                     im.end_qc_tp = this.ctx.helper.mul(im.end_qc_jl, im.unit_price, tp_decimal);
-                    im.calc_memo = '本期计量:' + (this.ctx.helper.checkZero(im.jl) ? 0 : im.jl) + ' ' + im.unit;
+                    im.calc_memo = '本期计量:' + (this.ctx.helper.checkZero(im.jl) ? 0 : im.jl) + (im.qc_minus_jl ? (` (不计价 ${im.qc_minus_jl}) `) : ' ') + im.unit;
                     this.ImData.push(im);
                     for (const c of this.changes) {
                         if (c.lid === p.id && c.pid === pp.id && c.qty && c.qty !== 0) {
@@ -945,15 +952,15 @@ class StageIm {
                     }
                 }
             } else {
-                if (this.ctx.helper.checkZero(p.gather_qty) && this.ctx.helper.checkZero(p.gather_tp)) { continue; }
+                if (this.ctx.helper.checkZero(p.gather_qty) && this.ctx.helper.checkZero(p.gather_tp) && this.ctx.helper.checkZero(p.qc_minus_qty)) { continue; }
 
                 const im = {
                     id: this.ImData.length + 1,
                     lid: node.id, code: p.b_code, name: p.name, unit: p.unit, unit_price: p.unit_price, org_unit_price: p.org_unit_price, pid: '',
                     quantity: p.quantity, total_price: p.total_price,
-                    jl: p.gather_qty, contract_jl: p.contract_qty, qc_jl: p.qc_qty,
-                    pre_jl: p.pre_gather_qty, pre_contract_jl: p.pre_contract_qty, pre_qc_jl: p.pre_qc_qty,
-                    end_jl: p.end_gather_qty, end_contract_jl: p.end_contract_qty, end_qc_jl: p.end_qc_qty,
+                    jl: p.gather_qty, contract_jl: p.contract_qty, qc_jl: p.qc_qty, qc_minus_jl: p.qc_minus_qty,
+                    pre_jl: p.pre_gather_qty, pre_contract_jl: p.pre_contract_qty, pre_qc_jl: p.pre_qc_qty, pre_qc_minus_jl: p.pre_qc_minus_qty,
+                    end_jl: p.end_gather_qty, end_contract_jl: p.end_contract_qty, end_qc_jl: p.end_qc_qty, end_qc_minus_jl: p.end_qc_minus_qty,
                     tp: p.gather_tp, contract_tp: p.contract_tp, qc_tp: p.qc_tp,
                     pre_tp: p.pre_gather_tp, pre_contract_tp: p.pre_contract_tp, pre_qc_tp: p.pre_qc_tp,
                     end_tp: p.end_gather_tp, end_contract_tp: p.end_contract_tp, end_qc_tp: p.end_qc_tp,
@@ -966,7 +973,7 @@ class StageIm {
                     position: '',
                     lIndex: this.billsTree.getNodeSerialNo(node),
                 };
-                im.calc_memo = '本期计量:' + (this.ctx.helper.checkZero(im.jl) ? 0 : im.jl) + ' ' + im.unit;
+                im.calc_memo = '本期计量:' + (this.ctx.helper.checkZero(im.jl) ? 0 : im.jl) + (im.qc_minus_jl ? (` (不计价 ${im.qc_minus_jl}) `) : ' ') + im.unit;
                 this.ImData.push(im);
                 for (const c of this.changes) {
                     if (c.lid === p.id && c.pid == -1 && c.qty && c.qty !== 0) {

+ 10 - 8
app/lib/sum_load.js

@@ -210,7 +210,7 @@ class loadLedgerGclTree extends loadGclBaseTree {
 }
 
 class updateReviseGclTree extends loadGclBaseTree {
-    constructor (ctx, setting) {
+    constructor(ctx, setting) {
         super(ctx, setting);
         this.errors = [];
     }
@@ -308,14 +308,14 @@ class updateReviseGclTree extends loadGclBaseTree {
                 deal_qty: i.deal_qty, deal_tp: i.deal_tp || 0,
                 sgfh_qty: i.sgfh_qty, sjcl_qty: i.sjcl_qty, qtcl_qty: i.qtcl_qty, quantity: i.quantity,
                 sgfh_tp: i.sgfh_tp || 0, sjcl_tp: i.sjcl_tp || 0, qtcl_tp: i.qtcl_tp || 0, total_price: i.total_price || 0,
-            })
+            });
         }
         return result;
     }
 }
 
 class gatherStageGclTree extends loadGclBaseTree {
-    constructor (ctx, setting) {
+    constructor(ctx, setting) {
         super(ctx, setting);
         this.cover = setting.cover;
     }
@@ -369,7 +369,7 @@ class gatherStageGclTree extends loadGclBaseTree {
     gather(source, parent) {
         parent = parent ? parent : this.parent;
         const checkFun = function (node, source) {
-            return  (source.is_tp && node.is_tp) || (!source.is_tp && !node.is_tp);
+            return (source.is_tp && node.is_tp) || (!source.is_tp && !node.is_tp);
         };
         const node = this.ignoreParent ? this.addNodeWithoutParent(source, checkFun) : this.addNode(source, parent, checkFun);
         if (node.is_tp) {
@@ -420,7 +420,7 @@ class gatherStageGclTree extends loadGclBaseTree {
 }
 
 class sumLoad {
-    constructor (ctx) {
+    constructor(ctx) {
         this.ctx = ctx;
     }
 
@@ -524,13 +524,15 @@ class sumLoad {
             parent: select, maxId, type: 'ledger', defaultData, ignoreParent, cover,
         });
         const posterity = await this.ctx.service.ledger.getPosterityByParentId(this.ctx.tender.id, select.ledger_id);
+        const extraData = await this.ctx.service.ledgerExtra.getData(this.ctx.tender.id, ['is_tp']);
         const stageBills = await this.ctx.service.stageBills.getLastestStageData2(this.ctx.tender.id, this.ctx.stage.id);
         const importLid = await this.ctx.service.stageImportChange.getLeafXmjImportLid(this.ctx.stage.id, select.id);
         this.ctx.helper.assignRelaData(posterity, [
-            { data: importLid, fields: [ 'is_import' ], prefix: '', relaId: 'lid' },
-            { data: stageBills, fields: ['contract_qty', 'contract_tp', 'qc_qty', 'qc_tp' ], prefix: '', relaId: 'lid' },
+            { data: extraData, fields: ['is_import'], prefix: '', relaId: 'id' },
+            { data: importLid, fields: ['is_import'], prefix: '', relaId: 'lid' },
+            { data: stageBills, fields: ['contract_qty', 'contract_tp', 'qc_qty', 'qc_tp'], prefix: '', relaId: 'lid' },
         ]);
-        const pos = await this.ctx.service.revisePos.getData(this.ctx.tender.id);
+        const pos = await this.ctx.service.pos.getAllDataByCondition({ where: { tid: this.ctx.tender.id } });
         this.loadTree.loadBase(posterity, pos);
 
         for (const tender of tenders) {

+ 16 - 15
app/middleware/stage_check.js

@@ -85,21 +85,6 @@ module.exports = options => {
                     stage.curOrder = stage.curAuditor.aid === accountId ? stage.curAuditor.order : stage.curAuditor.order - 1;
                 }
                 stage.filePermission = true;
-            } else if (this.tender.isTourist) {
-                if (auditorIds.indexOf(accountId) !== -1) {
-                    stage.readOnly = (stage.status !== status.checking && stage.status !== status.checkNoPre) || accountId !== stage.curAuditor.aid;
-                } else {
-                    stage.readOnly = true;
-                }
-                stage.curTimes = stage.times;
-                if (stage.status === status.uncheck || stage.status === status.checkNo) {
-                    stage.curOrder = 0;
-                } else if (stage.status === status.checked) {
-                    stage.curOrder = _.max(_.map(stage.auditors, 'order'));
-                } else {
-                    stage.curOrder = stage.curAuditor.order;
-                }
-                stage.filePermission = this.tender.touristPermission.file || auditorIds.indexOf(accountId) !== -1;
             } else if (auditorIds.indexOf(accountId) !== -1) { // 审批人
                 if (stage.status === status.uncheck) {
                     throw '您无权查看该数据';
@@ -132,6 +117,21 @@ module.exports = options => {
                     stage.curOrder = stage.status === status.checked ? _.max(_.map(stage.auditors, 'order')) : stage.curAuditor.order - 1;
                 }
                 stage.filePermission = false;
+            } else if (this.tender.isTourist || this.session.sessionUser.is_admin) {
+                if (auditorIds.indexOf(accountId) !== -1) {
+                    stage.readOnly = (stage.status !== status.checking && stage.status !== status.checkNoPre) || accountId !== stage.curAuditor.aid;
+                } else {
+                    stage.readOnly = true;
+                }
+                stage.curTimes = stage.times;
+                if (stage.status === status.uncheck || stage.status === status.checkNo) {
+                    stage.curOrder = 0;
+                } else if (stage.status === status.checked) {
+                    stage.curOrder = _.max(_.map(stage.auditors, 'order'));
+                } else {
+                    stage.curOrder = stage.curAuditor.order;
+                }
+                stage.filePermission = this.tender.touristPermission.file || auditorIds.indexOf(accountId) !== -1;
             } else { // 其他不可见
                 throw '您无权查看该数据';
             }
@@ -165,6 +165,7 @@ module.exports = options => {
             }
             yield next;
         } catch (err) {
+            console.log(err);
             this.helper.log(err);
             // 输出错误到日志
             if (err.stack) {

+ 53 - 18
app/public/css/main.css

@@ -87,7 +87,7 @@ font-size: .875rem;
 }
 .custom-control-warning-input:checked ~ .custom-control-warning-label::before{
   border-color:#da9500 ;
-  background-color:#da9500
+  background-color:#da9500 
 }
 .custom-control-warning-label{
   color:#da9500;
@@ -195,23 +195,23 @@ input.nospin[type="number"]{-moz-appearance:textfield;}
 /*滚动条*/
 /* 滚动条 */
 /*水平滚动条的样式*/
-/*::-webkit-scrollbar-thumb:horizontal {
+/*::-webkit-scrollbar-thumb:horizontal { 
 	width: 5px;
 	background-color: #e9ecef;
 	-webkit-border-radius: 0;
 }*/
 /*滚动条的背景颜色,滚动条的圆角宽度*/
 /*::-webkit-scrollbar-track-piece {
-	background-color: #efefef;
-	-webkit-border-radius: 0;
+	background-color: #efefef; 
+	-webkit-border-radius: 0; 
 }*/
 /*滚动条的宽度,滚动条的高度*/
 /*::-webkit-scrollbar {
-	width: 14px;
-	height: 14px;
+	width: 14px; 
+	height: 14px; 
 }*/
 /*垂直滚动条的样式*/
-/*::-webkit-scrollbar-thumb:vertical {
+/*::-webkit-scrollbar-thumb:vertical { 
 	height: 50px;
 	background-color: #e9ecef;
 	-webkit-border-radius: 0;
@@ -220,7 +220,7 @@ input.nospin[type="number"]{-moz-appearance:textfield;}
 	border: 1px solid #ced4da;
 }*/
 /*滚动条的hover样式*/
-/*::-webkit-scrollbar-thumb:hover {
+/*::-webkit-scrollbar-thumb:hover { 
 	height: 50px;
 	background-color: #ced4da;
 	-webkit-border-radius: 0;
@@ -830,6 +830,10 @@ input.nospin[type="number"]{-moz-appearance:textfield;}
   height:450px;
   overflow: hidden
 }
+.modal-height-400{
+  height:400px;
+  overflow: hidden
+}
 .modal-height-300{
   height:300px;
   overflow:auto
@@ -870,7 +874,7 @@ input.nospin[type="number"]{-moz-appearance:textfield;}
   font-size: 14px
 }
 .bd-toc {
-
+  
     position: sticky;
     top:3rem;
     height: calc(100vh - 10rem);
@@ -1028,7 +1032,7 @@ body{
   line-height: 30px;
 }
 .panel-title > .title-main .btn.pull-right {
-    margin: 5px 0 0 0
+    margin: 5px 0 0 0 
 }
 .panel-content{
   padding-top:35px;
@@ -1055,7 +1059,8 @@ label{
   font-size:100%;
 }
 .modal-header{
-  padding:.5rem 1rem
+  padding:.5rem 1rem;
+  cursor: move;
 }
 .modal-title{
   font-size:16px;
@@ -1246,7 +1251,7 @@ a.maintain-icon .fa{
     }
 }
 
-a.maintain-icon:hover .fa{
+a.maintain-icon:hover .fa{ 
     animation-iteration-count:0
 }
 /*审批列表*/
@@ -1369,10 +1374,10 @@ overflow-y: auto;
   position: relative;
 }
 .circle{
-  width: 62px;
+  width: 62px; 
   height: 62px;
   border-radius: 50%;
-  background: none;
+  background: none; 
   border: 4px solid #D7B014;
 }
 .circle-num{
@@ -1913,8 +1918,8 @@ overflow-y: auto;
   font-size: 36px;
 }
 .list-text-vertical{
-  overflow:hidden;
-  text-overflow:ellipsis;
+  overflow:hidden; 
+  text-overflow:ellipsis; 
   white-space:nowrap;
 }
 .about-text i{
@@ -1938,12 +1943,12 @@ overflow-y: auto;
 }
 /*@media (min-width: 768px){
   .weixin-erweima img{
-    width:90%;
+    width:90%; 
     height:auto;
   }
 }*/
 .weixin-erweima img{
-  width:75%;
+  width:75%; 
   height:auto;
 }
 .weixin-erweima span{
@@ -1983,3 +1988,33 @@ animation:shake 1s .2s ease both;}
 .margin-inputbox .height-inputbox{
   height: 30px !important;
 }
+.card-gk-width{
+  width: 352px;
+  border: none;
+  cursor: pointer;
+}
+.card-gk-width:hover{
+  background: #f7f7f7;
+}
+.modal-body .card-gk-title{
+  font-size: 16px;
+}
+.card-gk-active{
+  border: 1px solid #3377FF;
+}
+.sel-width{
+  width: 20px;
+  height: 20px;
+}
+.sel-blue{
+  background: url(sel_blue.png);
+}
+.card-gk-width:hover .sel-gary{
+  background: url(sel_gary.png);
+}
+.card-gk-bottom{
+  display:none ;
+}
+.card-gk-active .card-gk-bottom{
+  display: inline-block;
+}

BIN
app/public/css/sel_blue.png


BIN
app/public/css/sel_gary.png


BIN
app/public/images/dongtai.png


BIN
app/public/images/jingtai.png


BIN
app/public/images/tubiaoban.png


+ 26 - 15
app/public/js/budget_compare.js

@@ -35,6 +35,10 @@ $(document).ready(() => {
         headerFont: '12px 微软雅黑',
         font: '12px 微软雅黑',
         readOnly: true,
+        frozenColCount: 3,
+        frozenLineColor: '#93b5e4',
+        localCache: { key: 'budget-compare', colWidth: true },
+
     };
     sjsSettingObj.setFxTreeStyle(spreadSetting, sjsSettingObj.FxTreeStyle.jz);
     SpreadJsObj.initSheet(compareSheet, spreadSetting);
@@ -59,6 +63,20 @@ $(document).ready(() => {
                 SpreadJsObj.reLoadSheetHeader(compareSheet);
             };
         },
+        expand(tree, tag) {
+            switch (tag) {
+                case "1":
+                case "2":
+                case "3":
+                case "4":
+                case "5":
+                    tree.expandByLevel(parseInt(tag));
+                    break;
+                case "last":
+                    tree.expandByCustom(() => { return true; });
+                    break;
+            }
+        },
         loadBudgetData(result) {
             const compareTree = createNewPathTree('final', {
                 id: 'id',
@@ -116,6 +134,8 @@ $(document).ready(() => {
                 if (!y.name) return 1;
                 return x.name.localeCompare(y.name);
             });
+            const expandTag = getLocalCache('revise-compare-level');
+            if (expandTag) compareObj.expand(compareTree, expandTag);
             SpreadJsObj.loadSheetData(compareSheet, SpreadJsObj.DataType.Tree, compareTree);
         },
         loadFinalData(result, msg) {
@@ -131,9 +151,11 @@ $(document).ready(() => {
                 rootId: -1,
             });
             finalTree.loadDatas(result.final);
+            const expandTag = getLocalCache('revise-compare-level');
+            if (expandTag) compareObj.expand(finalTree, expandTag);
             SpreadJsObj.loadSheetData(compareSheet, SpreadJsObj.DataType.Tree, finalTree);
             if (sfSelect) sfSelect.reloadSelect(this.finalInfo.tender);
-        }
+        },
     };
 
     function compareCode(str1, str2, symbol = '-') {
@@ -203,20 +225,9 @@ $(document).ready(() => {
             const tree = sheet.zh_tree;
             setTimeout(() => {
                 showWaitingView();
-                switch (tag) {
-                    case "1":
-                    case "2":
-                    case "3":
-                    case "4":
-                    case "5":
-                        tree.expandByLevel(parseInt(tag));
-                        SpreadJsObj.refreshTreeRowVisible(sheet);
-                        break;
-                    case "last":
-                        tree.expandByCustom(() => { return true; });
-                        SpreadJsObj.refreshTreeRowVisible(sheet);
-                        break;
-                }
+                compareObj.expand(tree, tag);
+                SpreadJsObj.refreshTreeRowVisible(sheet);
+                setLocalCache('revise-compare-level', tag);
                 closeWaitingView();
             }, 100);
         });

+ 182 - 0
app/public/js/change_information.js

@@ -14,6 +14,59 @@ const is_numeric = (value) => {
         return !Number.isNaN(Number(value)) && value.toString().trim() !== '';
     }
 };
+function sortByCode(a, b) {
+    let code1 = a.code.split('-');
+    let code2 = b.code.split('-');
+    let code1length = code1.length;
+    let code2length = code2.length;
+    for (let i = 0; i < code1length; i ++) {
+        if (i+1 <= code2length) {
+            if (code1[i] != code2[i]) {
+                if (/^\d+$/.test(code1[i]) && /^\d+$/.test(code2[i])) {
+                    return parseInt(code1[i]) - parseInt(code2[i]);
+                } else if (!/^\d+$/.test(code1[i]) && /^\d+$/.test(code2[i])) {
+                    return 1;
+                } else if (/^\d+$/.test(code1[i]) && !/^\d+$/.test(code2[i])) {
+                    return -1;
+                } else {
+                    const str1length = code1[i].length;
+                    const str2length = code2[i].length;
+                    for (let j = 0; j < str1length; j++) {
+                        if (j+1 <= str2length) {
+                            if (code1[i].charAt(j) != code2[i].charAt(j)) {
+                                return code1[i].charAt(j).charCodeAt() - code2[i].charAt(j).charCodeAt();
+                            }  else if (j+1 == str1length && code1[i].charAt(j) == code2[i].charAt(j)) {
+                                if (str1length == str2length) {
+                                    return 0;
+                                } else {
+                                    return str1length - str2length;
+                                }
+                            }
+                        } else {
+                            if (j+1 >= str1length) {
+                                return 1;
+                            } else {
+                                return -1;
+                            }
+                        }
+                    }
+                }
+            } else if (i+1 == code1length && code1[i] == code2[i]) {
+                if (code1length == code2length) {
+                    return 0;
+                } else {
+                    return code1length - code2length;
+                }
+            }
+        } else {
+            if (i+1 >= code1length) {
+                return 1;
+            } else {
+                return -1;
+            }
+        }
+    }
+}
 $(document).ready(() => {
     //初始化所有附件列表
     getAllList();
@@ -236,6 +289,135 @@ $(document).ready(() => {
         }
     });
 
+    // 差值对比信息获取
+    let czSpread = null;
+    const czSpreadSetting = {
+        cols: [
+            {title: '清单编号', colSpan: '1', rowSpan: '2', field: 'code', hAlign: 0, width: 80},
+            {title: '名称', colSpan: '1', rowSpan: '2', field: 'name', hAlign: 0, width: 120},
+            {title: '单位', colSpan: '1', rowSpan: '2', field: 'unit', hAlign: 1, width: 60},
+            {title: '单价', colSpan: '1', rowSpan: '2', field: 'unit_price', hAlign: 2, width: 60, type: 'Number', getValue: 'getValue.unit_price'},
+            {title: '变更方案|数量', colSpan: '2|1', rowSpan: '1|1', field: 'pamount', hAlign: 2, width: 60, type: 'Number', getValue: 'getValue.pamount'},
+            {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'pa_tp', hAlign: 2, width: 80, type: 'Number', getValue: 'getValue.pa_tp'},
+            {title: '变更令|数量', colSpan: '2|1', rowSpan: '1|1', field: 'camount', hAlign: 2, width: 60, type: 'Number', getValue: 'getValue.camount'},
+            {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'ca_tp', hAlign: 2, width: 80, type: 'Number', getValue: 'getValue.ca_tp'},
+            {title: '差值对比|数量', colSpan: '2|1', rowSpan: '1|1', field: 'czamount', hAlign: 2, width: 60, type: 'Number', getValue: 'getValue.czamount'},
+            {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'cz_tp', hAlign: 2, width: 80, type: 'Number', getValue: 'getValue.cz_tp'},
+        ],
+        emptyRows: 0,
+        headRows: 2,
+        headRowHeight: [25, 25],
+        defaultRowHeight: 21,
+        headerFont: '12px 微软雅黑',
+        font: '12px 微软雅黑',
+        readOnly: true,
+        localCache: {
+            key: 'changes-cz',
+            colWidth: true,
+        }
+    };
+    const czCol = {
+        getValue: {
+            unit_price: function(data) {
+                return ZhCalc.round(data.unit_price, unitPriceUnit);
+            },
+            pa_tp: function (data) {
+                return ZhCalc.round(ZhCalc.mul(ZhCalc.round(data.unit_price, unitPriceUnit), ZhCalc.round(data.pamount, findDecimal(data.unit))), totalPriceUnit);
+            },
+            ca_tp: function (data) {
+                return ZhCalc.round(ZhCalc.mul(ZhCalc.round(data.unit_price, unitPriceUnit), ZhCalc.round(data.camount, findDecimal(data.unit))), totalPriceUnit);
+            },
+            pamount: function (data) {
+                return ZhCalc.round(data.pamount, findDecimal(data.unit));
+            },
+            camount: function (data) {
+                return ZhCalc.round(data.camount, findDecimal(data.unit));
+            },
+            czamount: function (data) {
+                return ZhCalc.sub(ZhCalc.round(data.camount, findDecimal(data.unit)), ZhCalc.round(data.pamount, findDecimal(data.unit)));
+            },
+            cz_tp: function (data) {
+                return ZhCalc.round(ZhCalc.mul(ZhCalc.round(data.unit_price, unitPriceUnit), ZhCalc.round(ZhCalc.sub(ZhCalc.round(data.camount, findDecimal(data.unit)), ZhCalc.round(data.pamount, findDecimal(data.unit))), findDecimal(data.unit))), totalPriceUnit);
+            },
+        }
+    };
+    const czSpreadObj = {
+        makeBackColor: function () {
+            const rowCount = czSpread.getActiveSheet().getRowCount();
+            for (let i = 0; i < rowCount; i++) {
+                if (czSpread.getActiveSheet().zh_data[i].color) czSpread.getActiveSheet().getRange(i, -1, 1, -1).backColor('#f5c6cb');
+            }
+        },
+        makeSjsFooter: function () {
+            // 增加汇总行并设为锁定禁止编辑状态
+            czSpread.getActiveSheet().addRows(czSpread.getActiveSheet().getRowCount(), 1);
+            czSpread.getActiveSheet().setValue(czSpread.getActiveSheet().getRowCount() - 1, 0, '合计');
+            czSpread.getActiveSheet().setStyle(czSpread.getActiveSheet().getRowCount() - 1, -1, style1);
+            czSpreadObj.countSum();
+        },
+        countSum: function () {
+            const rowCount = czSpread.getActiveSheet().getRowCount();
+            let pSum = 0,
+                cSum = 0,
+                czSum = 0;
+            for (let i = 0; i < rowCount - 1; i++) {
+                pSum = ZhCalc.add(pSum, czSpread.getActiveSheet().getValue(i, 5));
+                cSum = ZhCalc.add(cSum, czSpread.getActiveSheet().getValue(i, 7));
+                czSum = ZhCalc.add(czSum, czSpread.getActiveSheet().getValue(i, 9));
+            }
+            czSpread.getActiveSheet().setValue(czSpread.getActiveSheet().getRowCount() - 1, 5, pSum !== 0 ? pSum : null);
+            czSpread.getActiveSheet().setValue(czSpread.getActiveSheet().getRowCount() - 1, 7, cSum !== 0 ? cSum : null);
+            czSpread.getActiveSheet().setValue(czSpread.getActiveSheet().getRowCount() - 1, 9, czSum !== 0 ? czSum : null);
+        },
+    };
+
+    $('#bgfadb').on('shown.bs.modal', function () {
+        if (!czSpread) {
+            czSpread = SpreadJsObj.createNewSpread($('#cz-spread')[0]);
+            SpreadJsObj.initSpreadSettingEvents(czSpreadSetting, czCol);
+            SpreadJsObj.initSheet(czSpread.getActiveSheet(), czSpreadSetting);
+        }
+        const cList = [];
+        const newChangeList = _.cloneDeep(changeList);
+        for (const cl of newChangeList) {
+            const cIndex = _.findIndex(cList, { code: cl.code, name: cl.name, unit: cl.unit, unit_price: cl.unit_price});
+            if (cIndex !== -1) {
+                cList[cIndex].spamount = ZhCalc.add(cList[cIndex].spamount, cl.spamount);
+            } else {
+                cList.push(cl);
+            }
+        }
+        // 生成差值对比数据列表
+        const czList = [];
+        const newPlanList = _.cloneDeep(planList);
+        for (const c of cList) {
+            const planInfo = _.find(newPlanList, { code: c.code, name: c.name, unit: c.unit, unit_price: c.unit_price });
+            const pamount = planInfo ? planInfo.spamount : null;
+            let color = true;
+            if (planInfo) {
+                _.remove(newPlanList, (item) => item === planInfo);
+                if ((pamount ? pamount : 0) === (c.spamount ? c.spamount : 0)) {
+                    color = false;
+                }
+            }
+            czList.push({ code: c.code, name: c.name, unit: c.unit, unit_price: c.unit_price, camount: c.spamount, pamount, color });
+        }
+        if (newPlanList.length > 0) {
+            for (const np of newPlanList) {
+                czList.push({ code: np.code, name: np.name, unit: np.unit, unit_price: np.unit_price, camount: null, pamount: np.spamount, color: true });
+            }
+        }
+        if (czList.length > 0) {
+            // 按清单编号排序
+            czList.sort(sortByCode);
+        }
+        console.log(czList);
+        // sjs设置
+        SpreadJsObj.loadSheetData(czSpread.getActiveSheet(), SpreadJsObj.DataType.Data, czList);
+        czSpreadObj.makeBackColor();
+        czSpreadObj.makeSjsFooter();
+    });
+
     $.subMenu({
         menu: '#sub-menu', miniMenu: '#sub-mini-menu', miniMenuList: '#mini-menu-list',
         toMenu: '#to-menu', toMiniMenu: '#to-mini-menu',

+ 6 - 6
app/public/js/change_information_approval.js

@@ -380,12 +380,12 @@ $(document).ready(() => {
             // 判断并提交变更清单表格数据到表单中
             const clist = [];
             for(const [i,cl] of changeList.entries()) {
-                if (cl['audit_amount_' + accountId] === null || cl['audit_amount_' + accountId] === '') {
-                    toastr.error('清单第' + (i+1) + '行审批变更数量不能为空');
-                    returnflag = false;
-                } else {
-                    clist.push(cl.id + '_' + cl['audit_amount_' + accountId]);
-                }
+                // if (cl['audit_amount_' + accountId] === null || cl['audit_amount_' + accountId] === '') {
+                //     toastr.error('清单第' + (i+1) + '行审批变更数量不能为空');
+                //     returnflag = false;
+                // } else {
+                clist.push(cl.id + '_' + cl['audit_amount_' + accountId]);
+                // }
             }
             $('#change-list-approval').val(clist.join(','));
 

+ 4 - 3
app/public/js/change_information_set.js

@@ -166,7 +166,8 @@ $(document).ready(() => {
             },
         },
     };
-
+    // 数字只判断几个值(unit_price, oamount, camount)
+    const numField = ['unit_price', 'oamount', 'camount'];
     const changeSpreadObj = {
         makeSjsFooter: function () {
             // 增加汇总行并设为锁定禁止编辑状态
@@ -430,7 +431,7 @@ $(document).ready(() => {
                     return;
                 }
                 // 未改变值则不提交
-                let validText = is_numeric(info.editingText) ? parseFloat(info.editingText) : (info.editingText ? trimInvalidChar(info.editingText) : '');
+                let validText = is_numeric(info.editingText) && _.indexOf(numField, col.field) !== -1 ? parseFloat(info.editingText) : (info.editingText ? trimInvalidChar(info.editingText) : '');
                 const orgValue = select[col.field];
                 if (orgValue == validText || ((!orgValue || orgValue === '') && (validText === ''))) {
                     SpreadJsObj.reLoadRowData(info.sheet, info.row);
@@ -529,7 +530,7 @@ $(document).ready(() => {
                     if (!colSetting) continue;
 
                     let validText = info.sheet.getText(curRow, curCol);
-                    validText = is_numeric(validText) ? parseFloat(validText) : (validText ? trimInvalidChar(validText) : '');
+                    validText = is_numeric(validText) && _.indexOf(numField, colSetting.field) !== -1 ? parseFloat(validText) : (validText ? trimInvalidChar(validText) : '');
                     const orgValue = sortData[curRow][colSetting.field];
                     if (orgValue == validText || ((!orgValue || orgValue === '') && (validText === ''))) {
                         sameCol++;

+ 8 - 0
app/public/js/change_revise.js

@@ -96,6 +96,10 @@ $(document).ready(() => {
             },
         },
     ];
+    billsSpreadSetting.localCache = {
+        key: 'changes-ledger-spread',
+        colWidth: true,
+    };
     sjsSettingObj.setFxTreeStyle(billsSpreadSetting, sjsSettingObj.FxTreeStyle.jz);
     if (thousandth) sjsSettingObj.setTpThousandthFormat(billsSpreadSetting);
     SpreadJsObj.initSpreadSettingEvents(billsSpreadSetting, billsCol);
@@ -116,6 +120,10 @@ $(document).ready(() => {
             },
         },
     ];
+    posSpreadSetting.localCache = {
+        key: 'changes-pos-spread',
+            colWidth: true,
+    };
     sjsSettingObj.setGridSelectStyle(posSpreadSetting);
     if (thousandth) sjsSettingObj.setTpThousandthFormat(posSpreadSetting);
     SpreadJsObj.initSpreadSettingEvents(posSpreadSetting, posCol);

+ 34 - 9
app/public/js/gcl_gather.js

@@ -12,11 +12,12 @@
 const gclGatherModel = (function () {
     // 需要汇总计算的字段
     const ledgerGatherFields = ['quantity', 'total_price', 'deal_qty', 'deal_tp',
-        'contract_qty', 'contract_tp', 'qc_qty', 'qc_tp',
-        'pre_contract_qty', 'pre_contract_tp', 'pre_qc_qty', 'pre_qc_tp',
-        'end_contract_qty', 'end_contract_tp', 'end_qc_qty', 'end_qc_tp'];
-    const posGatherFields = ['quantity', 'contract_qty', 'qc_qty', 'gather_qty',
-        'pre_contract_qty', 'pre_qc_qty', 'pre_gather_qty', 'end_contract_qty', 'end_qc_qty', 'end_gather_qty'];
+        'contract_qty', 'contract_tp', 'qc_qty', 'qc_tp', 'qc_minus_qty',
+        'pre_contract_qty', 'pre_contract_tp', 'pre_qc_qty', 'pre_qc_tp', 'pre_qc_minus_qty',
+        'end_contract_qty', 'end_contract_tp', 'end_qc_qty', 'end_qc_tp', 'end_qc_minus_qty'];
+    const posGatherFields = ['quantity', 'contract_qty', 'qc_qty', 'gather_qty','qc_minus_qty',
+        'pre_contract_qty', 'pre_qc_qty', 'pre_gather_qty', 'pre_qc_minus_qty',
+        'end_contract_qty', 'end_qc_qty', 'end_gather_qty', 'end_qc_minus_qty'];
     // 初始化 清单树
     const gsTreeSetting = {
         id: 'ledger_id',
@@ -27,18 +28,23 @@ const gclGatherModel = (function () {
         keys: ['id', 'tender_id', 'ledger_id'],
         stageId: 'id',
     };
-    gsTreeSetting.updateFields = ['contract_qty', 'contract_tp', 'qc_qty', 'qc_tp'];
+    gsTreeSetting.updateFields = ['contract_qty', 'contract_tp', 'qc_qty', 'qc_tp', 'qc_minus_qty'];
     const gsTree = createNewPathTree('stage', gsTreeSetting);
     // 初始化 部位明细
     const posSetting = {
         id: 'id', ledgerId: 'lid',
-        updateFields: ['contract_qty', 'qc_qty'],
+        updateFields: ['contract_qty', 'qc_qty', 'qc_minus_qty'],
     };
     const gsPos = new StagePosData(posSetting);
     let deal = [], change;
 
     const gclList = [], leafXmjs = [];
     const mergeChar = ';';
+    let tpDecimal = 0;
+
+    function loadDecimal(decimal) {
+        tpDecimal = decimal.tp;
+    }
 
     /**
      * 将所有数据加载至树结构
@@ -48,7 +54,7 @@ const gclGatherModel = (function () {
      * @param preStage - 截止上期计量数据
      * @param bgl - 变更令数据
      */
-    function loadLedgerData (ledger, curStage, preStage, bgl) {
+    function loadLedgerData (ledger, curStage, preStage) {
         // 加载树结构数据
         gsTree.loadDatas(ledger);
         // 加载本期计量数据
@@ -348,6 +354,8 @@ const gclGatherModel = (function () {
             gcl.end_qc_qty = ZhCalc.add(gcl.pre_qc_qty, gcl.qc_qty);
             gcl.end_gather_qty = ZhCalc.add(gcl.pre_gather_qty, gcl.gather_qty);
             gcl.gather_tp = ZhCalc.add(gcl.contract_tp, gcl.qc_tp);
+            gcl.end_qc_minus_qty = ZhCalc.add(gcl.pre_qc_minus_qty, gcl.qc_minus_qty);
+
             gcl.end_contract_tp = ZhCalc.add(gcl.pre_contract_tp, gcl.contract_tp);
             gcl.end_qc_tp = ZhCalc.add(gcl.pre_qc_tp, gcl.qc_tp);
             gcl.end_gather_tp = ZhCalc.add(gcl.pre_gather_tp, gcl.gather_tp);
@@ -356,9 +364,21 @@ const gclGatherModel = (function () {
             gcl.end_final_tp = ZhCalc.add(gcl.end_qc_tp, gcl.total_price);
             gcl.final_qty = ZhCalc.add(gcl.quantity, gcl.change_bills_qty);
             gcl.final_tp = ZhCalc.add(gcl.total_price, gcl.change_bills_tp);
-            gcl.end_gather_percent = gcl.end_final_qty && gcl.end_gather_qty
+            gcl.deal_final_qty = ZhCalc.add(gcl.deal_qty, gcl.change_bills_qty);
+            gcl.deal_final_tp = ZhCalc.add(gcl.deal_tp, gcl.change_bills_tp);
+            gcl.final_1_qty = ZhCalc.add(gcl.quantity, gcl.end_qc_minus_qty);
+            gcl.final_1_tp = ZhCalc.mul(gcl.unit_price, gcl.final_1_qty, tpDecimal);
+            gcl.deal_final_1_qty = ZhCalc.add(gcl.deal_qty, gcl.end_qc_minus_qty);
+            gcl.deal_final_1_tp = ZhCalc.add(gcl.unit_price, gcl.deal_final_1_qty, tpDecimal);
+            gcl.end_final_1_qty = ZhCalc.add(gcl.final_1_qty, gcl.end_qc_qty);
+            gcl.end_final_1_tp = ZhCalc.add(gcl.final_1_tp, gcl.end_qc_tp);
+
+            gcl.end_gather_percent = gcl.end_gather_qty && gcl.end_final_qty
                 ? ZhCalc.mul(ZhCalc.div(gcl.end_gather_qty, gcl.end_final_qty), 100, 2)
                 : ZhCalc.mul(ZhCalc.div(gcl.end_gather_tp, gcl.end_final_tp), 100, 2);
+            gcl.end_final_1_percent = gcl.end_gather_qty && gcl.end_final_1_qty
+                ? ZhCalc.mul(ZhCalc.div(gcl.end_gather_qty, gcl.end_final_1_qty), 100, 2)
+                : ZhCalc.mul(ZhCalc.div(gcl.end_gather_tp, gcl.end_final_1_tp), 100, 2);
             gcl.final_percent = gcl.final_qty && gcl.end_gather_qty
                 ? ZhCalc.mul(ZhCalc.div(gcl.end_gather_qty, gcl.final_qty), 100, 2)
                 : ZhCalc.mul(ZhCalc.div(gcl.end_gather_tp, gcl.final_tp), 100, 2);
@@ -369,7 +389,11 @@ const gclGatherModel = (function () {
                 xmj.end_qc_qty = ZhCalc.add(xmj.pre_qc_qty, xmj.qc_qty);
                 xmj.end_gather_qty = ZhCalc.add(xmj.pre_gather_qty, xmj.gather_qty);
                 xmj.end_final_qty = ZhCalc.add(xmj.end_qc_qty, xmj.quantity);
+                xmj.end_qc_minus_qty = ZhCalc.add(xmj.pre_qc_minus_qty, xmj.qc_minus_qty);
+                xmj.final_1_qty = ZhCalc.add(xmj.quantity, xmj.end_qc_minus_qty);
+                xmj.end_final_1_qty = ZhCalc.add(xmj.final_1_qty, xmj.end_qc_qty);
                 xmj.end_gather_percent = ZhCalc.mul(ZhCalc.div(xmj.end_gather_qty, xmj.end_final_qty), 100, 2);
+                xmj.end_final_1_percent = ZhCalc.mul(ZhCalc.div(xmj.end_gather_qty, xmj.end_final_1_qty), 100, 2);
             }
         }
     }
@@ -549,6 +573,7 @@ const gclGatherModel = (function () {
     }
 
     return {
+        loadDecimal,
         loadLedgerData,
         loadPosData,
         loadDealBillsData,

+ 21 - 6
app/public/js/global.js

@@ -1019,8 +1019,8 @@ const checkUtils = {
         if (!data) return false;
         if (!data.quantity) return !!data.end_contract_qty;
         return data.quantity > 0
-            ? data.end_contract_qty > data.quantity
-            : data.end_contract_qty < data.quantity || data.end_contract_qty > 0;
+            ? data.end_contract_qty > data.final_1_qty
+            : data.end_contract_qty < data.final_1_qty || data.end_contract_qty > 0;
     },
     billsOver(data, isTz, relaPos) {
         if (!data) return false;
@@ -1039,8 +1039,8 @@ const checkUtils = {
             } else {
                 if (!data.quantity) return !!data.end_contract_qty;
                 return data.quantity > 0
-                    ? data.end_contract_qty > data.quantity
-                    : data.end_contract_qty < data.quantity || data.end_contract_qty > 0;
+                    ? data.end_contract_qty > data.final_1_qty
+                    : data.end_contract_qty < data.final_1_qty || data.end_contract_qty > 0;
             }
         } else {
             if (data.is_tp) {
@@ -1051,8 +1051,8 @@ const checkUtils = {
             } else {
                 if (!data.deal_qty) return !!data.end_contract_qty;
                 return data.deal_qty > 0
-                    ? data.end_contract_qty > data.deal_qty
-                    : data.end_contract_qty < data.deal_qty || data.end_contract_qty > 0;
+                    ? data.end_contract_qty > data.deal_final_1_qty
+                    : data.end_contract_qty < data.deal_final_1_qty || data.end_contract_qty > 0;
             }
         }
     }
@@ -1151,3 +1151,18 @@ function hpackArrBack(data) {
     });
     return result;
 }
+
+const spreadColor = {
+    stage: {
+        over: '#FF9595', //'#ff6f5c', '#f8d7da'
+        differ: '#F2DEDE',
+    },
+    gcl: {
+        differ: '#FFE699', // 同编号时,名称、单位、单价存在不同
+        calc_differ: '#f8d7da', //
+    },
+};
+
+$(document).ready(function () {
+  $('.modal').draggable({handle: '.modal-header'});
+});

+ 17 - 6
app/public/js/ledger.js

@@ -986,23 +986,34 @@ $(document).ready(function() {
             const select = SpreadJsObj.getSelectObject(sheet);
             if (!select || !select.code) return;
 
-            const recursiveSortCode = function (data, parentCode, children) {
+            const getChildSort = function (i, split) {
+                if (i <= 0) throw '参数错误';
+                switch(split) {
+                    case '0':
+                        return i < 10 ? split + i : i + '';
+                    case '-':
+                    default:
+                        return split + i;
+                }
+            };
+
+            const recursiveSortCode = function (data, parentCode, children, split) {
                 if (!children || children.length === 0) return;
 
                 for (const [i, child] of children.entries()) {
                     if (!child.b_code || child.b_code === '') {
-                        const code = parentCode + '-' + (i + 1);
+                        const code = parentCode + getChildSort(i + 1, split);
                         const cData = tree.getNodeKeyData(child);
                         cData.code = code;
                         data.push(cData);
                         if (!tree.isLeafXmj(child)) {
-                            recursiveSortCode(data, code, child.children);
+                            recursiveSortCode(data, code, child.children, split);
                         }
                     }
                 }
             };
             const data = [];
-            recursiveSortCode(data, select.code, select.children);
+            recursiveSortCode(data, select.code, select.children, tree.getCodeSplit());
             if (data.length > 0) {
                 postData(window.location.pathname + '/update', {postType: 'update', postData: data}, function (result) {
                     const refreshNode = tree.loadPostData(result);
@@ -1420,12 +1431,12 @@ $(document).ready(function() {
             icon: 'fa-sort-numeric-asc',
             disabled: function (key, opt) {
                 const node = SpreadJsObj.getSelectObject(ledgerSpread.getActiveSheet());
-                return !node || !node.code || !node.children || node.children === 0 || node.code.indexOf('-') < 0;
+                return !node || !node.code || !node.children || node.children === 0 || node.code.length < 3;
             },
             callback: function (key, opt) {
                 treeOperationObj.sortCode(ledgerSpread.getActiveSheet());
             },
-            visible: function (key, opt) {;
+            visible: function (key, opt) {
                 return !readOnly;
             }
         };

+ 1 - 1
app/public/js/ledger_check.js

@@ -219,7 +219,7 @@ const ledgerCheckUtil = {
                     if (!data.contract_qty && !data.qc_qty && !data.pre_contract_qty && !data.pre_qc_qty) return 2; // 漏计
                 } else {
                     const precision = findPrecision(tenderInfo.precision, unit);
-                    const checkQty = ZhCalc.mul(data.quantity, ZhCalc.div(ratio, 100, 4), precision.value);
+                    const checkQty = ZhCalc.mul(data.final_1_qty, ZhCalc.div(ratio, 100, 4), precision.value);
                     const qty = ZhCalc.add(data.contract_qty, data.pre_contract_qty) || 0;
                     if (qty > checkQty) return 1; // 违规
                     if (qty < checkQty) return 2; // 漏计

+ 3 - 3
app/public/js/ledger_gather.js

@@ -65,9 +65,9 @@ $(document).ready(() => {
         getColor: function (sheet, data, row, col, defaultColor) {
             return data
                 ? $('#compare-tag')[0].checked && data.compare_differ
-                    ? '#f8d7da'
-                    : (data.differ ? '#FFE699' : '#ffffff')
-                : '#ffffff';
+                    ? spreadColor.gcl.calc_differ
+                    : (data.differ ? spreadColor.gcl.differ : defaultColor)
+                : defaultColor;
         }
     };
     if (thousandth) sjsSettingObj.setTpThousandthFormat(gclSpreadSetting);

+ 17 - 0
app/public/js/path_tree.js

@@ -1023,6 +1023,23 @@ const createNewPathTree = function (type, setting) {
                 return false;
             })
         }
+
+        checkCodeType() {
+            for (const node of this.nodes) {
+                if (!node.code) continue;
+
+                if (node.code.indexOf('-') >= 0) {
+                    return '07';
+                } else if (node.code.length > 5) {
+                    const num = _.toNumber(node.code);
+                    if (num && num > 10000) return '18';
+                }
+            }
+            return '18';
+        }
+        getCodeSplit() {
+            return this.checkCodeType() === '07' ? '-' : '0';
+        }
     }
 
     class LedgerTree extends FxTree {

+ 13 - 1
app/public/js/shares/sjs_setting.js

@@ -80,5 +80,17 @@ const sjsSettingObj = (function () {
             }
         }
     };
-    return {setFxTreeStyle, FxTreeStyle, setGridSelectStyle, setTpThousandthFormat, setThousandthFormat, setTpColsThousandthFormat, setPropValue, set3FCols};
+    const setQcCols = function (cols, rela){
+        for (const r of rela) {
+            const col = _.find(cols, {field: r.field});
+            if (!col) continue;
+
+            col.readOnly = true;
+            col.cellType = 'activeImageBtn';
+            col.normalImg = '#ellipsis-icon';
+            col.indent = 5;
+            col.showImage = r.showImage;
+        }
+    };
+    return {setFxTreeStyle, FxTreeStyle, setGridSelectStyle, setTpThousandthFormat, setThousandthFormat, setTpColsThousandthFormat, setPropValue, set3FCols, setQcCols};
 })();

+ 13 - 9
app/public/js/spreadjs_rela/spreadjs_zh.js

@@ -304,15 +304,17 @@ const SpreadJsObj = {
      * @param {GC.Spread.Sheets.Worksheet} sheet
      */
     _initSheetHeader: function (sheet) {
-        if (!sheet.zh_setting || !sheet.zh_setting.cols) { return; }
+        const setting = sheet.zh_setting;
+        if (!setting || !setting.cols) { return; }
 
-        sheet.setColumnCount(sheet.zh_setting.cols.length);
-        sheet.setRowCount(sheet.zh_setting.headRows, spreadNS.SheetArea.colHeader);
-        for (let iRow = 0; iRow < sheet.zh_setting.headRowHeight.length; iRow ++) {
-            sheet.setRowHeight(iRow, sheet.zh_setting.headRowHeight[iRow], spreadNS.SheetArea.colHeader);
+
+        sheet.setColumnCount(setting.cols.length);
+        sheet.setRowCount(setting.headRows, spreadNS.SheetArea.colHeader);
+        for (let iRow = 0; iRow < setting.headRowHeight.length; iRow ++) {
+            sheet.setRowHeight(iRow, setting.headRowHeight[iRow], spreadNS.SheetArea.colHeader);
         }
-        for (let iCol = 0; iCol < sheet.zh_setting.cols.length; iCol++) {
-            const col = sheet.zh_setting.cols[iCol];
+        for (let iCol = 0; iCol < setting.cols.length; iCol++) {
+            const col = setting.cols[iCol];
             const title = col.title.split('|');
             const colSpan = col.colSpan ? col.colSpan.split('|'): ['1'], rowSpan = col.rowSpan ? col.rowSpan.split('|'): ['1'];
             for (let i = 0; i < title.length; i++) {
@@ -329,9 +331,11 @@ const SpreadJsObj = {
         }
         sheet.rowOutlines.direction(spreadNS.Outlines.OutlineDirection.backward);
         sheet.showRowOutline(false);
-        if (sheet.zh_setting.defaultRowHeight) {
-            sheet.defaults.rowHeight = sheet.zh_setting.defaultRowHeight;
+        if (setting.defaultRowHeight) {
+            sheet.defaults.rowHeight = setting.defaultRowHeight;
         }
+        if (setting.frozenLineColor) sheet.options.frozenlineColor = setting.frozenLineColor;
+        if (setting.frozenColCount) sheet.frozenColumnCount(setting.frozenColCount);
     },
     reinitSheetHeader: function (sheet) {
         this.beginMassOperation(sheet);

+ 6 - 0
app/public/js/sr_detail.js

@@ -894,6 +894,8 @@ $(document).ready(() => {
                 SpreadJsObj.reLoadSheetHeader(self.sheet);
                 $('[name=type-title-contract]').text('本期合同计量金额');
                 $('[name=type-title-qc]').text('本期变更计量金额');
+                $('#show-qc-minus-jl').parent().hidden();
+                $('#qc-minus-jl').parent().hidden();
             } else {
                 const jlCol = self.spreadSetting.cols.find(function (x) {return x.field === 'jl'});
                 jlCol.title = '本期计量数量';
@@ -967,6 +969,10 @@ $(document).ready(() => {
             $('#show-qc-jl').text(qcJl);
             $('#qc-jl').val(qcJl);
 
+            const qcMinusJl = data && data.qc_minus_jl ? data.qc_minus_jl : '';
+            $('#show-qc-minus-jl').text(qcMinusJl);
+            $('#qc-jl-minus-jl').val(qcMinusJl);
+
             const bglCode = data && data.bgl_code ? data.bgl_code : '';
             $('#show-bgl-code').text(bglCode);
             $('#bgl-code').val(bglCode);

+ 76 - 43
app/public/js/stage.js

@@ -32,11 +32,11 @@ function getExprInfo (field) {
 function customColDisplay () {
     const defaultSetting = [
         { title: '本期计量合同', fields: ['contract_qty', 'contract_tp'], visible: true },
-        { title: '本期数量变更', fields: ['qc_qty', 'qc_tp', 'qc_bgl'], visible: true },
+        { title: '本期数量变更', fields: ['qc_qty', 'qc_tp', 'qc_bgl', 'qc_minus_qty'], visible: true },
         { title: '本期完成计量', fields: ['gather_qty', 'gather_tp'], visible: true },
         { title: '截止本期计量合同', fields: ['end_contract_qty', 'end_contract_tp'], visible: true },
         { title: '截止本期数量变更', fields: ['end_qc_qty', 'end_qc_tp', 'end_qc_bgl'], visible: true },
-        { title: '截止本期完成计量', fields: ['end_gather_qty', 'end_gather_tp', 'end_gather_percent'], visible: true },
+        { title: '截止本期完成计量', fields: ['end_gather_qty', 'end_gather_tp', 'end_gather_percent', 'end_final_1_precent'], visible: true },
         { title: '本期批注', fields: ['postil'], visible: true },
         { title: '图册号', fields: ['drawing_code'], visible: true },
         { title: '备注', fields: ['memo'], visible: true },
@@ -65,7 +65,7 @@ function customizeStageTreeSetting(setting, customDisplay) {
     for (const cd of customDisplay) {
         for (const c of setting.cols) {
             if (cd.fields.indexOf(c.field) !== -1) {
-                c.visible = cd.visible;
+                c.visible = c.defaultVisible === undefined ? cd.visible : c.defaultVisible && cd.visible;
             }
         }
     }
@@ -204,7 +204,7 @@ $(document).ready(() => {
             {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'end_qc_tp', hAlign: 2, width: 60, type: 'Number'},
             {title: '截止本期完成计量|数量', colSpan: '3|1', rowSpan: '1|1', field: 'end_gather_qty', hAlign: 2, width: 60, type: 'Number'},
             {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'end_gather_tp', hAlign: 2, width: 60, type: 'Number'},
-            {title: '|完成率(%)', colSpan: '|1', rowSpan: '|1', field: 'end_gather_percent', hAlign: 2, width: 80, type: 'Number'},
+            {title: '|完成率(%)', colSpan: '|1', rowSpan: '|1', field: 'end_final_1_percent', hAlign: 2, width: 80, type: 'Number'},
             {title: '合同|项目节数量1',  colSpan: '2|1', rowSpan: '1|1', field: 'deal_dgn_qty1', hAlign: 2, width: 60, type: 'Number'},
             {title: '|项目节数量2',  colSpan: '|1', rowSpan: '|1', field: 'deal_dgn_qty2', hAlign: 2, width: 60, type: 'Number'},
             {title: '变更|项目节数量1',  colSpan: '2|1', rowSpan: '1|1', field: 'c_dgn_qty1', hAlign: 2, width: 60, type: 'Number'},
@@ -226,7 +226,7 @@ $(document).ready(() => {
         empty_code: { enable: 0 },
         calc: {
             enable: 1,
-            fields: ['contract_qty', 'qc_qty'],
+            fields: ['contract_qty', 'qc_qty', 'qc_minus_qty'],
         },
         zero: { enable: 0 },
         tp: {
@@ -267,16 +267,21 @@ $(document).ready(() => {
         markExpandSubKey: window.location.pathname.split('/')[2],
     };
     // 台账树结构计算相关设置
-    stageTreeSetting.updateFields = ['contract_qty', 'contract_tp', 'qc_qty', 'qc_tp', 'postil', 'used', 'contract_expr'];
+    stageTreeSetting.updateFields = ['contract_qty', 'contract_tp', 'qc_qty', 'qc_tp', 'qc_minus_qty', 'postil', 'used', 'contract_expr'];
     stageTreeSetting.calcFields = ['deal_tp', 'total_price', 'contract_tp', 'qc_tp', 'gather_tp',
-        'pre_contract_tp', 'pre_qc_tp', 'pre_gather_tp', 'end_contract_tp', 'end_qc_tp', 'end_gather_tp', 'end_correct_tp'];
+        'pre_contract_tp', 'pre_qc_tp', 'pre_gather_tp', 'end_contract_tp', 'end_qc_tp', 'end_gather_tp', 'end_correct_tp', 'final_1_tp', 'end_final_1_tp'];
     stageTreeSetting.calcFun = function (node) {
         if (!node.children || node.children.length === 0) {
             node.pre_gather_qty = ZhCalc.add(node.pre_contract_qty, node.pre_qc_qty);
             node.gather_qty = ZhCalc.add(node.contract_qty, node.qc_qty);
             node.end_contract_qty = ZhCalc.add(node.pre_contract_qty, node.contract_qty);
-            node.end_qc_qty = ZhCalc.add(node.pre_qc_qty, node.qc_qty);
             node.end_gather_qty = ZhCalc.add(node.pre_gather_qty, node.gather_qty);
+            node.end_qc_qty = ZhCalc.add(node.pre_qc_qty, node.qc_qty);
+            node.end_qc_minus_qty = ZhCalc.add(node.pre_qc_minus_qty, node.qc_minus_qty);
+            node.final_1_qty = ZhCalc.add(node.end_qc_minus_qty, node.quantity);
+            node.final_1_tp = ZhCalc.mul(node.final_1_qty, node.unit_price, tenderInfo.decimal.tp);
+            node.deal_final_1_qty = ZhCalc.add(node.end_qc_minus_qty, node.deal_qty);
+            node.end_final_1_qty = ZhCalc.add(node.end_qc_qty, node.final_1_qty);
         }
         node.pre_gather_tp = ZhCalc.add(node.pre_contract_tp, node.pre_qc_tp);
         node.gather_tp = ZhCalc.add(node.contract_tp, node.qc_tp);
@@ -295,24 +300,30 @@ $(document).ready(() => {
         node.end_gather_percent = ZhCalc.mul(ZhCalc.div(node.end_gather_tp, node.end_final_tp), 100, 2);
         node.end_correct_percent = ZhCalc.mul(ZhCalc.div(node.end_correct_tp, node.end_final_tp), 100, 2);
         node.final_dgn_price = ZhCalc.round(ZhCalc.div(node.end_gather_tp, ZhCalc.add(node.deal_dgn_qty1, node.c_dgn_qty1)), tenderInfo.decimal.up);
+        node.end_final_1_percent = ZhCalc.mul(ZhCalc.div(node.end_gather_tp, node.end_final_1_tp), 100, 2);
+        node.end_correct_1_percent = ZhCalc.mul(ZhCalc.div(node.end_correct_tp, node.end_final_1_tp), 100, 2);
     };
     const stageTree = createNewPathTree('stage', stageTreeSetting);
     // 初始化 计量单元 数据结构
     const stagePosSetting = {
         id: 'id', ledgerId: 'lid',
-        updateFields: ['contract_qty', 'qc_qty', 'postil', 'contract_expr'],
+        updateFields: ['contract_qty', 'qc_qty', 'qc_minus_qty', 'postil', 'contract_expr'],
     };
     stagePosSetting.calcFun = function (pos) {
         pos.pre_gather_qty = ZhCalc.add(pos.pre_contract_qty, pos.pre_qc_qty);
         pos.gather_qty = ZhCalc.add(pos.contract_qty, pos.qc_qty);
         pos.end_contract_qty = ZhCalc.add(pos.pre_contract_qty, pos.contract_qty);
         pos.end_qc_qty = ZhCalc.add(pos.pre_qc_qty, pos.qc_qty);
+        pos.end_qc_minus_qty = ZhCalc.add(pos.pre_qc_minus_qty, pos.qc_minus_qty);
         pos.end_gather_qty = ZhCalc.add(pos.pre_gather_qty, pos.gather_qty);
         pos.sum = ZhCalc.add(pos.end_qc_qty, pos.quantity);
         pos.end_gather_percent = ZhCalc.mul(ZhCalc.div(pos.end_gather_qty, pos.sum), 100, 2);
         pos.estimate_qty = !checkZero(pos.real_qty)
             ? ZhCalc.sub(ZhCalc.sub(pos.real_qty, pos.quantity), pos.end_qc_qty)
             : null;
+        pos.final_1_qty = ZhCalc.add(pos.end_qc_minus_qty, pos.quantity);
+        pos.deal_final_1_qty = ZhCalc.add(pos.end_qc_minus_qty, pos.deal_qty);
+        pos.end_final_1_qty = ZhCalc.add(pos.end_qc_qty, pos.final_1_qty);
     };
     const stagePos = new StagePosData(stagePosSetting);
 
@@ -387,12 +398,12 @@ $(document).ready(() => {
                     if (col.field === 'uamount') {
                         if (data.bamount > 0) {
                             const usedAmount = ZhCalc.add(data.uamount, data.pre_amount);
-                            return usedAmount < 0 || usedAmount > data.bamount ? '#ff6f5c' : defaultColor;
+                            return usedAmount < 0 || usedAmount > data.bamount ? spreadColor.stage.over : defaultColor;
                         } else if (data.bamount < 0) {
                             const usedAmount = ZhCalc.add(data.uamount, data.pre_amount);
-                            return usedAmount > 0 || usedAmount < data.bamount ? '#ff6f5c' : defaultColor;
+                            return usedAmount > 0 || usedAmount < data.bamount ? spreadColor.stage.over : defaultColor;
                         } else {
-                            return data.uamount ? '#ff6f5c' : defaultColor;
+                            return data.uamount ? spreadColor.stage.over : defaultColor;
                         }
                     } else {
                         return defaultColor;
@@ -413,10 +424,7 @@ $(document).ready(() => {
             // 切换变更令,加载右侧明细数据
             this.spread.bind(spreadNS.Events.SelectionChanged, function (e, info) {
                 const change = SpreadJsObj.getSelectObject(info.sheet);
-                console.log(change);
-                if(change) {
-                    self._loadChangeDetail(change);
-                }
+                if(change) self._loadChangeDetail(change);
             });
             // 填写本期计量
             this.spread.bind(spreadNS.Events.EditEnded, function (e, info) {
@@ -528,7 +536,7 @@ $(document).ready(() => {
             for (const c of this.changes) {
                 c.bamount = _.toNumber(c.b_amount);
                 c.vamount = ZhCalc.sub(ZhCalc.sub(c.bamount, c.used_amount), c.stage_used_amount);
-                const uc = _.find(this.useChanges, {cid: c.cid, cbid: c.cbid});
+                const uc = _.find(this.useChanges, {cid: c.cid, cbid: c.cbid, no_value: this.callData.noValue});
                 if (uc) {
                     c.org_uamount = uc.qty;
                     c.uamount = uc.qty;
@@ -639,12 +647,7 @@ $(document).ready(() => {
     const slSpread = SpreadJsObj.createNewSpread($('#stage-ledger')[0]);
     customizeStageTreeSetting(ledgerSpreadSetting, customColDisplay());
     // 数量变更列,添加按钮
-    const qcCol = _.find(ledgerSpreadSetting.cols, {field: 'qc_qty'});
-    qcCol.readOnly = true;
-    qcCol.cellType = 'activeImageBtn';
-    qcCol.normalImg = '#ellipsis-icon';
-    qcCol.indent = 5;
-    qcCol.showImage = function (data) {
+    const qcColShowImage = function (data) {
         if (!data || (data.children && data.children.length > 0) || !(data.b_code && data.b_code !== '')) {
             return false;
         } else {
@@ -652,18 +655,26 @@ $(document).ready(() => {
             return !(nodePos && nodePos.length > 0);
         }
     };
-    const ratioCol = ledgerSpreadSetting.cols.find(x => {return x.field === 'end_gather_percent' || x.field === 'end_correct_percent'});
-    if (ratioCol) ratioCol.field = tenderInfo.display.stage.correct ? 'end_correct_percent' : 'end_gather_percent';
+    sjsSettingObj.setQcCols(ledgerSpreadSetting.cols, [
+        {field: 'qc_qty', showImage: qcColShowImage},
+        {field: 'qc_minus_qty', showImage: qcColShowImage},
+    ]);
+    // const ratioCol = ledgerSpreadSetting.cols.find(x => {return x.field === 'end_gather_percent' || x.field === 'end_correct_percent'});
+    // if (ratioCol) ratioCol.field = tenderInfo.display.stage.correct ? 'end_correct_percent' : 'end_gather_percent';
+    const ratioCol = ledgerSpreadSetting.cols.find(x => {return x.field === 'end_final_1_percent' || x.field === 'end_correct_1_percent'});
+    if (ratioCol) ratioCol.field = tenderInfo.display.stage.correct ? 'end_correct_1_percent' : 'end_final_1_percent';
     ledgerSpreadSetting.imageClick = function (data, hitinfo) {
         const col = hitinfo.sheet.zh_setting.cols[hitinfo.col];
         switch (col.field) {
             case 'dagl': data.dagl_url && window.open(data.dagl_url); break;
             case 'gxby': data.gxby_url && window.open(data.gxby_url); break;
             case 'qc_qty':
+            case 'qc_minus_qty':
                 if (data.children && data.children.length > 0 || data.lock || data.is_import) return;
                 const nodePos = stagePos.getLedgerPos(data.id);
                 if (nodePos && nodePos.length > 0) return;
-                changesObj.loadChanges({bills: data});
+                const minus = col.field === 'qc_minus_qty' ? 1 : 0;
+                changesObj.loadChanges({bills: data, minus, noValue: minus});
                 break;
             default: return;
         }
@@ -683,7 +694,7 @@ $(document).ready(() => {
                 if (def && def.color) return def.color;
             }
 
-            return hintOver && checkUtils.billsOver(data, checkTzMeasureType(), stagePos) ? '#f8d7da' : defaultColor;
+            return hintOver && checkUtils.billsOver(data, checkTzMeasureType(), stagePos) ? spreadColor.stage.over : defaultColor;
         } else {
             return defaultColor;
         }
@@ -729,31 +740,30 @@ $(document).ready(() => {
         return data.lock || false;
     };
     SpreadJsObj.initSheet(slSpread.getActiveSheet(), ledgerSpreadSetting);
-    slSpread.getActiveSheet().frozenColumnCount(5);
-    slSpread.getActiveSheet().options.frozenlineColor = '#93b5e4';
 
     //初始化所有附件列表
     getAllList();
 
     // 初始化 计量单元 Spread
     const spSpread = SpreadJsObj.createNewSpread($('#stage-pos')[0]);
-    const spCol = _.find(posSpreadSetting.cols, {field: 'qc_qty'});
-    spCol.readOnly = true;
-    spCol.cellType = 'activeImageBtn';
-    spCol.normalImg = '#ellipsis-icon';
-    spCol.indent = 5;
-    spCol.showImage = function (data) {
+    const posQcColShowImage = function (data) {
         return data !== undefined && data !== null;
     };
+    sjsSettingObj.setQcCols(posSpreadSetting.cols, [
+        { field: 'qc_qty', showImage: posQcColShowImage },
+        { field: 'qc_minus_qty', showImage: posQcColShowImage }
+    ]);
     posSpreadSetting.imageClick = function (data, hitinfo) {
         const col = hitinfo.sheet.zh_setting.cols[hitinfo.col];
         switch (col.field) {
             case 'gxby': data.gxby_url && window.open(data.gxby_url); break;
             case 'dagl': data.dagl_url && window.open(data.dagl_url); break;
             case 'qc_qty':
+            case 'qc_minus_qty':
                 const node = SpreadJsObj.getSelectObject(slSpread.getActiveSheet());
                 if (node.lock) return;
-                changesObj.loadChanges({bills: node, pos: data});
+                const minus = col.field === 'qc_minus_qty' ? 1 : 0;
+                changesObj.loadChanges({bills: node, pos: data, minus, noValue: minus});
                 break;
             default: return;
         }
@@ -773,7 +783,7 @@ $(document).ready(() => {
             }
         }
         if (checkTzMeasureType()) {
-            return hintOver && checkUtils.posOver(data)  ? '#f8d7da' : defaultColor;
+            return hintOver && checkUtils.posOver(data)  ? spreadColor.stage.over : defaultColor;
         }
     };
     sjsSettingObj.setGridSelectStyle(posSpreadSetting);
@@ -976,6 +986,7 @@ $(document).ready(() => {
             if (posSearch) posSearch.search();
         },
         selectionChanged: function (e, info) {
+            console.log(SpreadJsObj.getSelectObject(info.sheet));
             if (!info.oldSelections || !info.oldSelections[0] || info.newSelections[0].row !== info.oldSelections[0].row) {
                 stageTreeSpreadObj.loadRelaData();
                 // 全选去除
@@ -992,7 +1003,7 @@ $(document).ready(() => {
                 const validCols = [];
                 for (let iCol = sel.col; iCol < sel.col + sel.colCount; iCol++) {
                     const colSetting = sheet.zh_setting.cols[iCol];
-                    if (!colSetting.readOnly && colSetting.field !== 'qc_qty') {
+                    if (!colSetting.readOnly && colSetting.field !== 'qc_qty' && colSetting.field !== 'qc_minus_qty') {
                         validCols.push(iCol);
                     }
                 }
@@ -1068,7 +1079,7 @@ $(document).ready(() => {
             if (info.sheet.zh_setting) {
                 const setting = info.sheet.zh_setting;
                 const range = info.cellRange;
-                const validField = ['contract_qty', 'contract_tp', 'qc_qty', 'postil'].concat(['memo', 'ex_memo1', 'ex_memo2', 'ex_memo3'], setting.dgnUpFields);
+                const validField = ['contract_qty', 'contract_tp', 'qc_qty', 'qc_minus_qty', 'postil'].concat(['memo', 'ex_memo1', 'ex_memo2', 'ex_memo3'], setting.dgnUpFields);
                 for (let iCol = range.col; iCol < range.col + range.colCount; iCol++) {
                     const col = info.sheet.zh_setting.cols[iCol];
                     if ((validField.indexOf(col.field) === -1)) {
@@ -1247,6 +1258,7 @@ $(document).ready(() => {
             switch (col.field) {
                 case 'contract_qty':
                 case 'qc_qty':
+                case 'qc_minus_qty':
                     info.cancel = node.is_tp;
                     break;
                 case 'contract_tp':
@@ -1477,6 +1489,7 @@ $(document).ready(() => {
                 sumLoadMiss.show();
             } else {
                 sumLoadMiss.clearMissData();
+
             }
             // todo 优化,仅加载需要刷新的变更令
             if (checkedChanges) checkedChanges.reloadChangeData();
@@ -1771,7 +1784,7 @@ $(document).ready(() => {
             if (info.sheet.zh_setting) {
                 const sortData = info.sheet.zh_data;
                 const range = info.cellRange;
-                const validField = ['contract_qty', 'qc_qty', 'postil', 'real_qty', 'ex_memo1', 'ex_memo2', 'ex_memo3'];
+                const validField = ['contract_qty', 'qc_qty', 'qc_minus_qty', 'postil', 'real_qty', 'ex_memo1', 'ex_memo2', 'ex_memo3'];
                 if (!checkTzMeasureType()) {
                     validField.push('name', 'sgfh_qty', 'sjcl_qty', 'qtcl_qty', 'position', 'drawing_code');
                 }
@@ -1930,7 +1943,7 @@ $(document).ready(() => {
                 const validCols = [];
                 for (let iCol = sel.col; iCol < sel.col + sel.colCount; iCol++) {
                     const colSetting = sheet.zh_setting.cols[iCol];
-                    if (!colSetting.readOnly && colSetting.field !== 'qc_qty') {
+                    if (!colSetting.readOnly && colSetting.field !== 'qc_qty' && colSetting.field !== 'qc_minus_qty') {
                         validCols.push(iCol);
                     }
                 }
@@ -2004,6 +2017,7 @@ $(document).ready(() => {
         },
         selectionChanged: function (e, info) {
             stagePosSpreadObj.loadExprToInput(info.sheet);
+            console.log(SpreadJsObj.getSelectObject(info.sheet));
         },
         addPegs: function (pegs) {
             if (!pegs || pegs.length <= 0) return;
@@ -2907,12 +2921,16 @@ $(document).ready(() => {
                 SpreadJsObj.reLoadSheetHeader(self.sheet);
                 $('[name=type-title-contract]').text('本期合同计量金额');
                 $('[name=type-title-qc]').text('本期变更计量金额');
+                $('#show-qc-minus-jl').parent().hide();
+                $('#qc-minus-jl').parent().hide();
             } else {
                 const jlCol = self.spreadSetting.cols.find(function (x) {return x.field === 'jl'});
                 jlCol.title = '本期计量数量';
                 SpreadJsObj.reLoadSheetHeader(self.sheet);
                 $('[name=type-title-contract]').text('本期合同计量数量');
                 $('[name=type-title-qc]').text('本期变更计量数量');
+                $('#show-qc-minus-jl').parent().show();
+                $('#qc-minus-jl').parent().show();
             }
             if (stage.im_type === imType.bb.value || stage.im_type === imType.bw.value) {
                 $('#show-jldy').parent().show();
@@ -3002,12 +3020,16 @@ $(document).ready(() => {
                         SpreadJsObj.reLoadSheetHeader(self.sheet);
                         $('[name=type-title-contract]').text('本期合同计量金额');
                         $('[name=type-title-qc]').text('本期变更计量金额');
+                        $('#show-qc-minus-jl').parent().hide();
+                        $('#qc-minus-jl').parent().hide();
                     } else {
                         const jlCol = self.spreadSetting.cols.find(function (x) {return x.field === 'jl'});
                         jlCol.title = '本期计量数量';
                         SpreadJsObj.reLoadSheetHeader(self.sheet);
                         $('[name=type-title-contract]').text('本期合同计量数量');
                         $('[name=type-title-qc]').text('本期变更计量数量');
+                        $('#show-qc-minus-jl').parent().show();
+                        $('#qc-minus-jl').parent().show();
                     }
                     if (stage.im_type === imType.bb.value || stage.im_type === imType.bw.value) {
                         $('#show-jldy').parent().show();
@@ -3595,6 +3617,10 @@ $(document).ready(() => {
             $('#show-qc-jl').text(qcJl);
             $('#qc-jl').val(qcJl);
 
+            const qcMinusJl = data && data.qc_minus_jl ? data.qc_minus_jl : '';
+            $('#show-qc-minus-jl').text(qcMinusJl);
+            $('#qc-minus-jl').val(qcMinusJl);
+
             const bglCode = data && data.bgl_code ? data.bgl_code : '';
             $('#show-bgl-code').text(bglCode);
             $('#bgl-code').val(bglCode);
@@ -3743,12 +3769,19 @@ $(document).ready(() => {
                             if (change.is_import) {
                                 if (changeBills.pos && changeBills.pos.length > 0) {
                                     SpreadJsObj.locateTreeNode(slSpread.getActiveSheet(), changeBills.pos[0].ledger_id, true);
+                                    SpreadJsObj.resetTopAndSelect(spSpread.getActiveSheet());
                                     stagePosSpreadObj.loadCurPosData();
                                 }
                             } else if (changeBills.gcl_id) {
                                 const node = stageTree.nodes.find(x => {return x.id === changeBills.gcl_id});
                                 SpreadJsObj.locateTreeNode(slSpread.getActiveSheet(), node.ledger_id, true);
+                                SpreadJsObj.resetTopAndSelect(spSpread.getActiveSheet());
                                 stagePosSpreadObj.loadCurPosData();
+                                const posData = spSpread.getActiveSheet().zh_data;
+                                if (!posData || posData.length === 0) return;
+
+                                const changePos = posData.find(x => { return x.name === changeBills.bwmx; });
+                                if (changePos) SpreadJsObj.locateData(spSpread.getActiveSheet(), changePos);
                             } else {
                                 const cb = {
                                     b_code: changeBills.code || '',
@@ -3767,6 +3800,7 @@ $(document).ready(() => {
                                     };
                                     if (_.isMatch(cb, b)) {
                                         SpreadJsObj.locateTreeNode(slSpread.getActiveSheet(), node.ledger_id);
+                                        SpreadJsObj.resetTopAndSelect(spSpread.getActiveSheet());
                                         stagePosSpreadObj.loadCurPosData();
                                         return;
                                     }
@@ -4726,8 +4760,7 @@ $(document).ready(() => {
             },
             callback: function (sheet) {
                 postDataCompress(window.location.pathname + '/importStageSheet', {sheet}, function (result) {
-                    // todo 刷新界面
-                    console.log(result);
+                    window.location.reload();
                 }, null);
             }
         });

+ 3 - 1
app/public/js/stage_change.js

@@ -39,7 +39,9 @@ class ChangeAnalysis {
             b.qty = _.toNumber(b.samount);
             b.valid_qty = ZhCalc.sub(b.qty, b.used_qty);
             b.tp = ZhCalc.round(ZhCalc.mul(b.qty, b.unit_price), tenderInfo.decimal.tp);
-            b.pos = _.filter(change.detail.curUsedBills, { cbid: b.id });
+            b.pos = change.detail.curUsedBills.filter(x => {
+                return x.cbid === b.id && x.qty;
+            });
             b.cur_qty = 0;
             for (const p of b.pos) {
                 // 查询最底层项目节

+ 2 - 2
app/public/js/stage_compare.js

@@ -68,7 +68,7 @@ $(document).ready(function () {
                 if ((base || compare) && (compare !== base)) return true;
             }
         }
-        return data.children.length === 0 && checkDiffer(data) ? '#F2DEDE' : defaultColor;
+        return data.children.length === 0 && checkDiffer(data) ? spreadColor.stage.differ : defaultColor;
     };
     posSpreadSetting.getColor = function (sheet, data, row, col, defaultColor) {
         function checkDiffer(data) {
@@ -80,7 +80,7 @@ $(document).ready(function () {
                 if ((base || compare) && (compare!== base)) return true;
             }
         }
-        return checkDiffer(data) ? '#F2DEDE' : defaultColor;
+        return checkDiffer(data) ? spreadColor.stage.differ : defaultColor;
     };
     // 初始化台账
     const ledgerSpread = SpreadJsObj.createNewSpread($('#ledger-spread')[0]);

+ 5 - 4
app/public/js/stage_gather.js

@@ -58,7 +58,7 @@ $(document).ready(function () {
     gclSheet.options.frozenlineColor = '#93b5e4';
     gclSpreadSetting.getColor = function (sheet, data, row, col, defaultColor) {
         if (!data) return defaultColor;
-        return data.overRange && hintOver ? '#f8d7da' : data.differ ? '#FFE699' : defaultColor;
+        return data.overRange && hintOver ? spreadColor.stage.over : data.differ ? spreadColor.gcl.differ : defaultColor;
     };
     if (thousandth) sjsSettingObj.setTpThousandthFormat(gclSpreadSetting);
     SpreadJsObj.initSheet(gclSpread.getActiveSheet(), gclSpreadSetting);
@@ -97,8 +97,8 @@ $(document).ready(function () {
         const nPercent = Math.min(Math.max(ZhCalc.div(parseFloat($('#over-percent').val()), 100), 0.5), 1);
         for (const node of data) {
             if (node) {
-                const bOverRangeTz = billsGatherOver(node, 'quantity', 'total_price', nPercent);
-                const bOverRangeDeal = billsGatherOver(node, 'deal_bills_qty', 'deal_bills_tp', nPercent);
+                const bOverRangeTz = billsGatherOver(node, 'final_1_qty', 'final_1_tp', nPercent);
+                const bOverRangeDeal = billsGatherOver(node, 'deal_final_1_qty', 'deal_final_1_tp', nPercent);
                 node.overRange = bQty ? bOverRangeTz : (bDealQty ? bOverRangeDeal : bOverRangeTz || bOverRangeDeal);
             }
         }
@@ -126,6 +126,7 @@ $(document).ready(function () {
 
     postData(preUrl + '/load', { filter: 'ledger;pos;dealBills;spec;changeBills' }, function (result) {
         // 解析清单汇总数据
+        gclGatherModel.loadDecimal(tenderDecimal);
         gclGatherModel.loadLedgerData(result.ledgerData);
         gclGatherModel.loadPosData(result.posData);
         gclGatherModel.loadDealBillsData(result.dealBills);
@@ -251,7 +252,7 @@ $(document).ready(function () {
                 {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'end_qc_tp', hAlign: 2, width: 60, type: 'Number'},
                 {title: '截止本期完成计量|数量', colSpan: '3|1', rowSpan: '1|1', field: 'end_gather_qty', hAlign: 2, width: 60, type: 'Number'},
                 {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'end_gather_tp', hAlign: 2, width: 60, type: 'Number'},
-                {title: '|完成率(%)', colSpan: '|1', rowSpan: '|1', field: 'end_gather_percent', hAlign: 2, width: 60, type: 'Number'},
+                {title: '|完成率(%)', colSpan: '|1', rowSpan: '|1', field: 'end_final_1_percent', hAlign: 2, width: 60, type: 'Number'},
                 {title: '台账+变更令|数量', colSpan: '2|1', rowSpan: '1|1', field: 'end_final_qty', hAlign: 2, width: 60, type: 'Number'},
                 {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'end_final_tp', hAlign: 2, width: 60, type: 'Number'},
                 {title: '单位工程', colSpan: '1', rowSpan: '2', field: 'dwgc', hAlign: 0, width: 80, formatter: '@'},

+ 32 - 24
app/public/js/stage_im.js

@@ -24,7 +24,7 @@ const stageIm = (function () {
         keys: ['id', 'tender_id', 'ledger_id'],
         stageId: 'id',
     };
-    gsTreeSetting.updateFields = ['contract_qty', 'contract_tp', 'qc_qty', 'qc_tp'];
+    gsTreeSetting.updateFields = ['contract_qty', 'contract_tp', 'qc_qty', 'qc_tp', 'qc_minus_qty'];
     gsTreeSetting.calcFields = ['deal_tp', 'total_price', 'contract_tp', 'qc_tp', 'gather_tp', 'end_contract_tp', 'end_qc_tp', 'end_gather_tp'];
     gsTreeSetting.calcFun = function (node) {
         if (node.children && node.children.length === 0) {
@@ -389,10 +389,10 @@ const stageIm = (function () {
         if (im.calc_memo !== undefined && im.calc_memo !== null && im.calc_memo !== '') return;
 
         if (im.leafXmjs && im.leafXmjs.length > 0) {
-            const memo = ['本期计量:' + (checkZero(im.jl) ? 0 : im.jl) + ' ' + im.unit];
+            const memo = ['本期计量:' + (checkZero(im.jl) ? 0 : im.jl) + (im.qc_minus_jl ? (` (不计价 ${im.qc_minus_jl}) `) : ' ') + im.unit];
             for (const lx of im.leafXmjs) {
                 for (const p of lx.pos) {
-                    memo.push(p.name + ':' + p.jl + ' ' + im.unit);
+                    memo.push(p.name + ':' + p.jl + (p.qc_minus_jl ? (` (不计价 ${p.qc_minus_jl}) `) : ' ') + im.unit);
                 }
             }
             im.calc_memo = memo.join('\n');
@@ -405,10 +405,10 @@ const stageIm = (function () {
                 if (b.pos && b.pos.length > 0) {
                     memo.push('清单' + (i+1) + ':' + b.b_code + ' ' + b.name);
                     for (const p of b.pos) {
-                        memo.push(p.name + ':' + p.jl + ' ' + b.unit);
+                        memo.push(p.name + ':' + p.jl + (p.qc_minus_jl ? (` (不计价 ${p.qc_minus_jl}) `) : ' ') + b.unit);
                     }
                 } else {
-                    memo.push('清单' + (i+1) + ':' + b.b_code + ' ' + b.name + ':' + (checkZero(b.jl) ? 0 : b.jl) + ' ' + b.unit);
+                    memo.push('清单' + (i+1) + ':' + b.b_code + ' ' + b.name + ':' + (checkZero(b.jl) ? 0 : b.jl) + (b.qc_minus_jl ? (` (不计价 ${b.qc_minus_jl}) `) : ' ') + b.unit);
                 }
             }
             im.calc_memo = memo.join('\n');
@@ -457,7 +457,7 @@ const stageIm = (function () {
         const posRange = gsPos.getLedgerPos(node.id);
         if (!posRange) { return }
         for (const p of posRange) {
-            if (checkZero(p.contract_qty) && checkZero(p.qc_qty)) { continue; }
+            if (checkZero(p.contract_qty) && checkZero(p.qc_qty) && checkZero(p.qc_minus_qty)) { continue; }
             let lp = _.find(gclBills.pos, {name: p.name});
             if (!lp) {
                 lp = {name: p.name};
@@ -466,6 +466,7 @@ const stageIm = (function () {
             lp.jl = ZhCalc.add(lp.jl, p.gather_qty);
             lp.contract_jl = ZhCalc.add(lp.contract_jl, p.contract_qty);
             lp.qc_jl = ZhCalc.add(lp.qc_jl, p.qc_qty);
+            lp.qc_minus_jl = ZhCalc.add(lp.qc_minus_jl, p.qc_minus_qty);
         }
     }
     function recursiveGenerateTzGclBills(node, im) {
@@ -477,7 +478,7 @@ const stageIm = (function () {
                     continue;
                 }
                 if (checkZero(p.contract_qty) && checkZero(p.contract_tp) &&
-                    checkZero(p.qc_qty) && checkZero(p.qc_tp)) {
+                    checkZero(p.qc_qty) && checkZero(p.qc_tp) && checkZero(p.qc_minus_qty)) {
                     continue;
                 }
                 let b = _.find(im.gclBills, {bid: p.id});
@@ -488,6 +489,7 @@ const stageIm = (function () {
                 b.jl = ZhCalc.add(b.jl, p.gather_qty);
                 b.contract_jl = ZhCalc.add(b.contract_jl, p.contract_qty);
                 b.qc_jl = ZhCalc.add(b.qc_jl, p.qc_qty);
+                b.qc_minus_jl = ZhCalc.add(b.qc_minus_jl, p.qc_minus_qty);
                 generateTzPosData(p, b);
             }
         }
@@ -533,23 +535,23 @@ const stageIm = (function () {
             for (const p of posterity) {
                 if (p.children && p.children.length > 0) continue;
                 if (!checkZero(p.contract_qty) || !checkZero(p.contract_tp) ||
-                    !checkZero(p.qc_qty) || !checkZero(p.qc_tp))
+                    !checkZero(p.qc_qty) || !checkZero(p.qc_tp) || !checkZero(p.qc_minus_qty))
                     return true;
                 const pPos = gsPos.getLedgerPos(p.id);
                 if (!pPos || pPos.length === 0) continue;
                 for (const pp of pPos) {
-                    if (!checkZero(pp.contract_qty) || !checkZero(pp.qc_qty)) return true;
+                    if (!checkZero(pp.contract_qty) || !checkZero(pp.qc_qty) || !checkZero(pp.qc_minus_qty)) return true;
                 }
             }
             return false;
         } else {
             if (!checkZero(node.contract_qty) || !checkZero(node.contract_tp) ||
-                !checkZero(node.qc_qty) || !checkZero(node.qc_tp))
+                !checkZero(node.qc_qty) || !checkZero(node.qc_tp) || !checkZero(node.qc_minus_qty))
                 return true;
             const pPos = gsPos.getLedgerPos(node.id);
             if (!pPos || pPos.length === 0) return false;
             for (const pp of pPos) {
-                if (!checkZero(pp.contract_qty) || !checkZero(pp.qc_qty)) return true;
+                if (!checkZero(pp.contract_qty) || !checkZero(pp.qc_qty) || !checkZero(pp.qc_minus_qty)) return true;
             }
         }
     }
@@ -558,7 +560,7 @@ const stageIm = (function () {
         const pPos = gsPos.getLedgerPos(node.id);
         if (!pPos || pPos.length === 0) return null;
         for (const pp of pPos) {
-            if (!checkZero(pp.contract_qty) || !checkZero(pp.qc_qty)) return pp;
+            if (!checkZero(pp.contract_qty) || !checkZero(pp.qc_qty) || !checkZero(pp.qc_minus_qty)) return pp;
         }
     }
 
@@ -587,7 +589,7 @@ const stageIm = (function () {
             const peg = getPegNode(node);
             const im = {
                 lid: node.id, pid: '', code: node.code,
-                jl: node.gather_tp, contract_jl: node.contract_tp, qc_jl: node.qc_tp,
+                jl: node.gather_tp, contract_jl: node.contract_tp, qc_jl: node.qc_tp, qc_minus_jl: 0,
                 //im_code: getNewImCode(),
                 peg: peg ? getPegStr(peg.name) : '', drawing_code: getDrawingCode(node),
                 position: '',
@@ -625,11 +627,13 @@ const stageIm = (function () {
         }
         gcl.contract_jl = ZhCalc.add(gcl.contract_jl, bills.contract_jl);
         gcl.qc_jl = ZhCalc.add(gcl.qc_jl, bills.qc_jl);
+        gcl.qc_minus_jl = ZhCalc.add(gcl.qc_minus_jl, bills.qc_minus_jl);
         gcl.jl = ZhCalc.add(gcl.jl, bills.jl);
     }
     function calculateBwBillsIm(im) {
         im.contract_jl = 0;
         im.qc_jl = 0;
+        im.qc_minus_jl = 0;
         for (const b of im.gclBills) {
             im.contract_jl = ZhCalc.add(im.contract_jl, ZhCalc.mul(b.contract_jl, b.unit_price, decimal.tp));
             im.qc_jl = ZhCalc.add(im.qc_jl, ZhCalc.mul(b.qc_jl, b.unit_price, decimal.tp));
@@ -661,7 +665,7 @@ const stageIm = (function () {
                 const pPos = gsPos.getLedgerPos(p.id);
                 if (pPos && pPos.length > 0) {
                     for (const pp of pPos) {
-                        if (checkZero(pp.contract_qty) && checkZero(pp.qc_qty)) continue;
+                        if (checkZero(pp.contract_qty) && checkZero(pp.qc_qty) && checkZero(pp.qc_minus_qty)) continue;
                         let im = nodeImData.find(function (d) {
                             return d.lid === node.id && d.pos_name === pp.name;
                         });
@@ -689,7 +693,7 @@ const stageIm = (function () {
                         }
                         addBwBillsGclBills(im, {
                             b_code: p.b_code, name: p.name, unit: p.unit, unit_price: p.unit_price,
-                            jl: pp.gather_qty, contract_jl: pp.contract_qty, qc_jl: pp.qc_qty
+                            jl: pp.gather_qty, contract_jl: pp.contract_qty, qc_jl: pp.qc_qty, qc_minus_jl: pp.qc_minus_qty,
                         });
 
                         if (pp.drawing_code && im.drawing_code instanceof Array)
@@ -707,11 +711,12 @@ const stageIm = (function () {
 
                     imDefault.contract_jl = ZhCalc.add(imDefault.contract_jl, p.contract_tp);
                     imDefault.qc_jl = ZhCalc.add(imDefault.qc_jl, p.qc_tp);
+                    imDefault.qc_minus_jl = 0;
                     imDefault.used = true;
 
                     addBwBillsGclBills(imDefault, {
                         b_code: p.b_code, name: p.name, unit: p.unit, unit_price: p.unit_price,
-                        jl: p.gather_qty, contract_jl: p.contract_qty, qc_jl: p.qc_jl,
+                        jl: p.gather_qty, contract_jl: p.contract_qty, qc_jl: p.qc_qty, qc_minus_jl: p.qc_qty,
                     });
                 }
             }
@@ -737,7 +742,7 @@ const stageIm = (function () {
         const posRange = gsPos.getLedgerPos(node.id);
         if (!posRange) { return }
         for (const p of posRange) {
-            if (!p.gather_qty || checkZero(p.gather_qty)) { continue; }
+            if (checkZero(p.contract_qty) && checkZero(p.qc_qty) && checkZero(p.qc_minus_qty)) { continue; }
             let lp = _.find(lx.pos, {name: p.name});
             if (!lp) {
                 lp = {name: p.name};
@@ -746,6 +751,7 @@ const stageIm = (function () {
             lp.jl = ZhCalc.add(lp.jl, p.gather_qty);
             lp.contract_jl = ZhCalc.add(lp.contract_jl, p.contract_qty);
             lp.qc_jl = ZhCalc.add(lp.qc_jl, p.qc_qty);
+            lp.qc_minus_jl = ZhCalc.add(lp.qc_minus_jl, p.qc_minus_qty);
         }
     }
     function generateZlLeafXmjData(node, im) {
@@ -766,6 +772,7 @@ const stageIm = (function () {
         lx.jl = ZhCalc.add(lx.jl, node.gather_qty);
         lx.contract_jl = ZhCalc.add(lx.contract_jl, node.contract_qty);
         lx.qc_jl = ZhCalc.add(lx.qc_jl, node.qc_qty);
+        lx.qc_minus_jl = ZhCalc.add(lx.qc_minus_jl, node.qc_minus_qty);
         generateZlPosData(node, lx);
     }
     function generateZlChangeData(node, im) {
@@ -809,7 +816,7 @@ const stageIm = (function () {
                 const peg = getPegNode(node);
                 im = {
                     lid: node.id, pid: '', code: p.b_code, name: p.name, unit: p.unit, unit_price: p[up_field],
-                    jl: 0, contract_jl: 0, qc_jl: 0,
+                    jl: 0, contract_jl: 0, qc_jl: 0, qc_minus_jl: 0,
                     peg: peg ? getPegStr(peg.name) : '',
                     position: '',
                     lIndex: nodeIndex,
@@ -837,6 +844,7 @@ const stageIm = (function () {
             im.jl = ZhCalc.add(im.jl, p.gather_qty);
             im.contract_jl = ZhCalc.add(im.contract_jl, p.contract_qty);
             im.qc_jl = ZhCalc.add(im.qc_jl, p.qc_qty);
+            im.qc_minus_jl = ZhCalc.add(im.qc_minus_jl, p.qc_minus_qty);
         }
     }
 
@@ -851,10 +859,10 @@ const stageIm = (function () {
             if (pPos && pPos.length > 0) {
                 const nodeIndex = gsTree.getNodeIndex(node);
                 for (const pp of pPos) {
-                    if (checkZero(pp.contract_qty) && checkZero(pp.qc_qty)) { continue }
+                    if (checkZero(pp.contract_qty) && checkZero(pp.qc_qty) && checkZero(pp.qc_minus_qty)) { continue }
                     const im = {
                         lid: node.id, code: p.b_code, name: p.name, unit: p.unit, unit_price: p[up_field], pid: pp.id,
-                        jl: pp.gather_qty, contract_jl: pp.contract_qty, qc_jl: pp.qc_qty,
+                        jl: pp.gather_qty, contract_jl: pp.contract_qty, qc_jl: pp.qc_qty, qc_minus_jl: pp.qc_minus_qty,
                         //im_code: getNewImCode(),
                         bw: bw, jldy: pp.name,
                         peg: CheckPeg(pp.name) ? getPegStr(pp.name) : (peg ? getPegStr(peg.name) : ''),
@@ -867,7 +875,7 @@ const stageIm = (function () {
                         source: [{id: p.ledger_id, code: p.code, b_code: p.b_code}],
                         im_type: imType.bw.value,
                     };
-                    im.calc_memo = '本期计量:' + (checkZero(im.jl) ? 0 : im.jl) + ' ' + im.unit;
+                    im.calc_memo = '本期计量:' + (checkZero(im.jl) ? 0 : im.jl) + (im.qc_minus_jl ? (` (不计价 ${im.qc_minus_jl}) `) : ' ') + im.unit;
                     ImData.push(im);
                     for (const c of changes) {
                         if (c.lid === p.id && c.pid === pp.id && c.qty && c.qty !== 0) {
@@ -876,11 +884,11 @@ const stageIm = (function () {
                     }
                 }
             } else {
-                if (checkZero(p.gather_qty) && checkZero(p.gather_tp)) { continue }
+                if (checkZero(p.gather_qty) && checkZero(p.gather_tp) && checkZero(p.qc_minus_qty)) { continue }
 
                 const im = {
                     lid: node.id, code: p.b_code, name: p.name, unit: p.unit, unit_price: p[up_field], pid: '',
-                    jl: p.gather_qty, contract_jl: p.contract_qty, qc_jl: p.qc_qty,
+                    jl: p.gather_qty, contract_jl: p.contract_qty, qc_jl: p.qc_qty, qc_minus_jl: p.qc_minus_qty,
                     im_code: getNewImCode(),
                     bw: bw,
                     peg: peg ? getPegStr(peg.name) : '',
@@ -893,7 +901,7 @@ const stageIm = (function () {
                     source: [{id: p.ledger_id, code: p.code, b_code: p.b_code}],
                     im_type: imType.bw.value,
                 };
-                im.calc_memo = '本期计量:' + (checkZero(im.jl) ? 0 : im.jl) + ' ' + im.unit;
+                im.calc_memo = '本期计量:' + (checkZero(im.jl) ? 0 : im.jl) + (im.qc_minus_jl ? (` (不计价 ${im.qc_minus_jl}) `) : ' ') + im.unit;
                 ImData.push(im);
                 for (const c of changes) {
                     if (c.lid === p.id && c.pid == -1 && c.qty && c.qty !== 0) {

+ 8 - 1
app/public/report/js/rpt_custom.js

@@ -195,7 +195,7 @@ const rptCustomObj = (function () {
                     }
                 }
                 $('#change-select-result').html(selectHtml.join(''));
-            })
+            });
         },
 
         show: async function (title, resolve) {
@@ -392,6 +392,13 @@ const rptCustomObj = (function () {
             rptCustomObj.resetMaterialSumSelect(resolve);
             // $("#stage-select").modal('hide');
         });
+        $('#material-sum-select-all').unbind('click');
+        $('#material-sum-select-all').bind('click', function () {
+            const material = $('[name=material-sum-select-check]');
+            for (const m of material) {
+                m.checked = this.checked;
+            }
+        })
     };
     const init = function (cDefine, sfData, cSelect, rptName, resolve = null) {
         stageFlow = sfData;

+ 11 - 5
app/public/report/js/rpt_signature.js

@@ -344,9 +344,15 @@ let rptSignatureHelper = {
         // 2. 日期
         elementsStrArr.push('<div class="col-6">');
         let dftDate = '';
-        if (userAcc) dftDate = _getSignDateByAllScenarios(userAcc.id);
-        if (dftDate !== '' && dftDate.length > 20) {
-            dftDate = (new Date(dftDate)).Format('yyyy-MM-dd');
+        if (role_rel.sign_date !== '' && role_rel.sign_date.length > 20) {
+            dftDate = (new Date(role_rel.sign_date)).Format('yyyy-MM-dd');
+        } else if (role_rel.sign_date instanceof Date){
+            dftDate = role_rel.sign_date.Format('yyyy-MM-dd');
+        } else {
+            if (userAcc) dftDate = _getSignDateByAllScenarios(userAcc.id);
+            if (dftDate !== '' && dftDate.length > 20) {
+                dftDate = (new Date(dftDate)).Format('yyyy-MM-dd');
+            }
         }
         elementsStrArr.push('<div class="input-group input-group-sm margin-inputbox">');
         elementsStrArr.push('   <div class="input-group-prepend">');
@@ -496,14 +502,14 @@ let rptSignatureHelper = {
         rptSignatureHelper.resetSignAudit();
         if (current_stage_status === 3) {
             //1. 重刷page
-            let hasStamp = false;
+            // let hasStamp = false;
             for (const page of zTreeOprObj.currentRptPageRst.items) {
                 if (page.signature_cells) {
                     for (let cIdx = page.signature_cells.length - 1; cIdx >= 0; cIdx--) {
                         const sCell = page.signature_cells[cIdx];
                         if (sCell.isStamp) {
                             page.signature_cells.splice(cIdx);
-                            hasStamp = true;
+                            // hasStamp = true;
                         } else if (sCell.hasOwnProperty('pre_path')) {
                             sCell.path = sCell.pre_path;
                             delete sCell.pre_path;

+ 3 - 1
app/reports/rpt_component/jpc_flow_tab.js

@@ -977,7 +977,7 @@ JpcFlowTabSrv.prototype.createNew = function() {
         // 另:要考虑紧密输出情况,需要重新拆分数据
         const _splitValues = function(oCell) {
             // JpcFieldHelper.setValue(data_field, theRecIdx, value);
-            const values = oCell.Value.split('|');
+            const values = (typeof oCell.Value === 'string') ? oCell.Value.split('|') : [oCell.Value];
             let font = oCell[JV.PROP_FONT];
             if (typeof oCell[JV.PROP_FONT] === 'string') {
                 font = fonts[oCell[JV.PROP_FONT]];
@@ -1361,6 +1361,8 @@ JpcFlowTabSrv.prototype.createNew = function() {
     };
     JpcFlowTabResult.checkCombineEvent = function($RUN_TYPE, $VER_COMB_ARRAY, $HOR_COMB_ARRAY, $CURRENT_CELL_ITEMS, $CURRENT_RPT, $CURRENT_DATA) {
         if ($CURRENT_RPT.formulas) {
+            const $JE = JE;
+            const $JV = JV;
             for (let execFmlIdx = 0; execFmlIdx < $CURRENT_RPT.formulas.length; execFmlIdx++) {
                 if ($CURRENT_RPT.formulas[execFmlIdx][JV.PROP_RUN_TYPE] === $RUN_TYPE) {
                     const expression = $CURRENT_RPT.formulas[execFmlIdx][JV.PROP_EXPRESSION];

+ 3 - 1
app/router.js

@@ -162,6 +162,7 @@ module.exports = app => {
     app.post('/tender/:id/copy-setting', sessionAuth, tenderCheck, 'tenderController.copyTender');
     app.post('/tender/:id/tourist/audit/save', sessionAuth, tenderCheck, uncheckTenderCheck, 'tenderController.saveTourist');
     app.post('/tender/:id/map/save', sessionAuth, tenderCheck, uncheckTenderCheck, 'tenderController.saveMap');
+    app.post('/tender/:id/map/upload', sessionAuth, tenderCheck, uncheckTenderCheck, 'tenderController.uploadMap');
     app.post('/tender/:id/load', sessionAuth, tenderCheck, 'tenderController.loadData');
     app.post('/tender/:id/saveRela', sessionAuth, tenderCheck, 'tenderController.saveRelaData');
 
@@ -291,6 +292,7 @@ module.exports = app => {
     app.post('/tender/:id/measure/stage/:order/stash/add', sessionAuth, tenderCheck, stageCheck, 'stageController.addStash');
     app.post('/tender/:id/measure/stage/:order/stash/del', sessionAuth, tenderCheck, stageCheck, 'stageController.delStash');
     app.post('/tender/:id/measure/stage/:order/stash/recover', sessionAuth, tenderCheck, stageCheck, 'stageController.recoverStash');
+    app.post('/tender/:id/measure/stage/:order/importStageSheet', sessionAuth, tenderCheck, stageCheck, 'stageController.importStageSheet');
 
     // 计量附件
     app.post('/tender/:id/measure/stage/:order/upload/file', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageController.uploadFile');
@@ -606,7 +608,7 @@ module.exports = app => {
     app.post('/wap/tender/:id/change/approval', sessionAuth, tenderCheck, uncheckTenderCheck, 'wapController.changeApproval');
     app.get('/wap/tender/:id/revise/:rid/info', sessionAuth, tenderCheck, uncheckTenderCheck, 'wapController.revise');
     app.get('/wap/tender/:id/advance', sessionAuth, tenderCheck, uncheckTenderCheck, 'wapController.advance');
-    app.get('/wap/tender/:id/advance/:order/detail', sessionAuth, tenderCheck, uncheckTenderCheck, advanceCheck, 'wapController.advanceDetail');
+    app.get('/wap/tender/:id/advance/:order/detail', sessionAuth, tenderCheck, advanceCheck, 'wapController.advanceDetail');
 
     // 微信
     app.get('/wx', 'wechatController.index');

+ 23 - 9
app/service/change.js

@@ -787,7 +787,7 @@ module.exports = app => {
                 for (const bl of bills_list) {
                     const listInfo = bl.split('_');
                     const lid = listInfo[0];
-                    const amount = listInfo[1];
+                    const amount = listInfo[1] !== 'null' && listInfo[1] !== '' ? listInfo[1] : null;
                     const changeListInfo = await this.ctx.service.changeAuditList.getDataById(lid);
                     if (changeListInfo !== undefined) {
                         total_price = this.ctx.helper.add(total_price, this.ctx.helper.mul(changeListInfo.unit_price, amount, tp_decimal));
@@ -796,10 +796,10 @@ module.exports = app => {
                         const list_update = {
                             id: lid,
                             audit_amount: audit_amount.join(','),
-                            spamount: parseFloat(amount),
+                            spamount: amount !== null ? parseFloat(amount) : null,
                         };
                         if (postData.audit_next_id === undefined) {
-                            list_update.samount = amount;
+                            list_update.samount = amount !== null ? amount : '';
                         }
                         await this.transaction.update(this.ctx.service.changeAuditList.tableName, list_update);
                     }
@@ -1190,18 +1190,19 @@ module.exports = app => {
          * @param pos - 查询的部位
          * @return {Promise<*>} - 可用的变更令列表
          */
-        async getValidChanges(tender, stage, bills, pos) {
+        async getValidChanges(tender, stage, data, minusNoValue) {
+            const bills = data.bills, pos = data.pos;
             const self = this;
             const getFilterPart = function(field, value) {
                 return value
                     ? field + ' = ' + self.db.escape(value)
                     : self.db.format("(?? = null or ?? = '')", [field, field]);
             };
-            const filter = getFilterPart('cb.code', bills.b_code) +
+            let filter = getFilterPart('cb.code', bills.b_code) +
                 ' And ' + getFilterPart('cb.name', bills.name) +
                 ' And ' + getFilterPart('cb.unit', bills.unit) +
-                ' And cb.`unit_price` = ' + this.db.escape(bills.unit_price) +
-                (pos ? getFilterPart('cb.bwmx', pos.name) : '');
+                ' And cb.`unit_price` = ' + this.db.escape(bills.unit_price);
+            // if (data.pos) filter = filter + ' And ' + getFilterPart('cb.bwmx', pos.name);
             const sql =
                 'SELECT c.cid, c.code, c.name, c.w_code, c.p_code, c.peg, c.org_name, c.org_code, c.new_name, c.new_code,' +
                 '    c.content, c.basis, c.memo, c.type, c.class, c.quality, c.company, c.charge, ' +
@@ -1218,7 +1219,20 @@ module.exports = app => {
                 '  WHERE c.tid = ? And c.status = ? And c.valid And ' + filter +
                 '  ORDER BY c.in_time';
             const sqlParam = [tender.id, stage.order, tender.id, audit.flow.status.checked];
-            const changes = await this.db.query(sql, sqlParam);
+            let changes = await this.db.query(sql, sqlParam);
+            if (minusNoValue) {
+                if (data.minus) {
+                    changes = changes.filter(c => {
+                        c.bamount = c.b_amount ? parseFloat(c.b_amount) : 0;
+                        return c.bamount < 0;
+                    });
+                } else {
+                    changes = changes.filter(c => {
+                        c.bamount = c.b_amount ? parseFloat(c.b_amount) : 0;
+                        return c.bamount >= 0;
+                    });
+                }
+            }
             for (const c of changes) {
                 let sSql = 'SELECT * FROM ' + this.ctx.service.stageChange.tableName + ' WHERE sid = ? and cbid = ?';
                 const sSqlParam = [stage.id, c.cbid];
@@ -1227,7 +1241,7 @@ module.exports = app => {
                     sSqlParam.push(stage.curTimes, stage.curTimes, stage.curOrder);
                 }
                 const stageUsedData = await this.db.query(sSql, sSqlParam);
-                const filter = this.ctx.helper.filterLastestData(stageUsedData, ['pid', 'lid'], 'stimes', 'sorder');
+                const filter = this.ctx.helper.filterLastestData(stageUsedData, ['pid', 'lid', 'no_value'], 'stimes', 'sorder');
                 c.stage_used_amount = this.ctx.helper.sum(filter.map(x => { return x.qty }));
                 const aSql = 'SELECT ca.*, pa.name As u_name, pa.role As u_role ' +
                     '  FROM ?? As ca ' +

+ 7 - 7
app/service/change_audit_list.js

@@ -914,6 +914,9 @@ module.exports = app => {
                     total_price: sum.total_price,
                     deal_tp: sum.deal_tp,
                 });
+                // 清除修订及台账的maxLid缓存,防止树结构混乱
+                await this.ctx.service.reviseBills._removeCacheMaxLid(tid);
+                await this.ctx.service.ledger._removeCacheMaxLid(tid);
             }
         }
 
@@ -936,21 +939,20 @@ module.exports = app => {
                         l.ledger_pid, l.level, l.order, l.full_path, l.is_leaf, l.quantity, l.total_price,
                         l.unit_price, l.drawing_code, l.memo, l.dgn_qty1, l.dgn_qty2, l.deal_qty, l.deal_tp,
                         l.sgfh_qty, l.sgfh_tp, l.sjcl_qty, l.sjcl_tp, l.qtcl_qty, l.qtcl_tp, l.node_type, l.crid,
-                        l.tender_id, l.is_tp, l.sgfh_expr, l.sjcl_expr, l.qtcl_expr, l.check_calc, l.gxby_status,
-                        l.dagl_status, l.dagl_url, l.gxby_limit, l.dagl_limit, l.ex_memo1, l.ex_memo2, l.ex_memo3,
+                        l.tender_id, l.sgfh_expr, l.sjcl_expr, l.qtcl_expr, l.check_calc,
+                        l.ex_memo1, l.ex_memo2, l.ex_memo3,
                     ];
                     insertLedgerArr.push('(' + this.ctx.helper.getInArrStrSqlFilter(insertL) + ')');
                     await transaction.delete(this.ctx.service.changeLedger.tableName, { id: l.id });
                     // 日志添加
-                    await transaction.insert(this.ctx.service.changeReviseLog.tableName, { tid, cid, lid: l.id, name: l.name, create_time: new Date() });
+                    await transaction.insert(this.ctx.service.changeReviseLog.tableName, { tid, cid, lid: l.id, name: l.name ? l.name : (l.code ? l.code : ''), create_time: new Date() });
                 }
                 const bSql = 'Insert Into ' +
                     this.ctx.service.ledger.tableName +
                     '  (id, code, b_code, name, unit, source, remark, ledger_id, ledger_pid, level, `order`, full_path, is_leaf,' +
                     '     quantity, total_price, unit_price, drawing_code, memo, dgn_qty1, dgn_qty2, deal_qty, deal_tp,' +
-                    '     sgfh_qty, sgfh_tp, sjcl_qty, sjcl_tp, qtcl_qty, qtcl_tp, node_type, crid, tender_id, is_tp,' +
+                    '     sgfh_qty, sgfh_tp, sjcl_qty, sjcl_tp, qtcl_qty, qtcl_tp, node_type, crid, tender_id,' +
                     '     sgfh_expr, sjcl_expr, qtcl_expr, check_calc,' +
-                    '     gxby_status, dagl_status, dagl_url, gxby_limit,  dagl_limit,' +
                     '     ex_memo1, ex_memo2, ex_memo3) VALUES ' + insertLedgerArr.join(',') + ';';
                 await transaction.query(bSql, []);
             }
@@ -961,7 +963,6 @@ module.exports = app => {
                         p.id, p.tid, p.lid, p.name, p.drawing_code, p.quantity, p.add_stage, p.add_stage_order, p.add_times,
                         p.add_user, p.sgfh_qty, p.sjcl_qty, p.qtcl_qty, p.crid, p.porder, p.position,
                         p.sgfh_expr, p.sjcl_expr, p.qtcl_expr, p.real_qty,
-                        p.gxby_status, p.dagl_status, p.dagl_url, p.gxby_limit, p.dagl_limit,
                         p.ex_memo1, p.ex_memo2, p.ex_memo3,
                     ];
                     insertPosArr.push('(' + this.ctx.helper.getInArrStrSqlFilter(insertp) + ')');
@@ -975,7 +976,6 @@ module.exports = app => {
                     '  (id, tid, lid, name, drawing_code, quantity, add_stage, add_stage_order, add_times, add_user,' +
                     '     sgfh_qty, sjcl_qty, qtcl_qty, crid, porder, position, ' +
                     '     sgfh_expr, sjcl_expr, qtcl_expr, real_qty,' +
-                    '     gxby_status, dagl_status, dagl_url, gxby_limit,  dagl_limit,' +
                     '     ex_memo1, ex_memo2, ex_memo3)  VALUES ' + insertPosArr.join(',') + ';';
                 await transaction.query(pSql, []);
             }

+ 10 - 0
app/service/change_ledger.js

@@ -157,6 +157,16 @@ module.exports = app => {
             }
             return maxId;
         }
+        /**
+         * 移除最大节点id(修订时使用)
+         *
+         * @param {Number} mid - master id
+         * @return {Number}
+         * @private
+         */
+        async _removeCacheMaxLid(mid) {
+            return await this.cache.del(this.setting.keyPre + mid);
+        }
 
         /**
          * 根据 父节点id 和 节点排序order 获取数据

+ 2 - 13
app/service/ledger.js

@@ -686,6 +686,7 @@ module.exports = app => {
             const analysisExcel = new AnalysisExcel(this.ctx, this.setting);
             const tempData = await this.ctx.service.tenderNodeTemplate.getData(templateId, true);
             const cacheTree = analysisExcel.analysisData(excelData, tempData, { filterZeroGcl: filter });
+            cacheTree.calculateLeafWithPos();
             const transaction = await this.db.beginTransaction();
             try {
                 await transaction.delete(this.tableName, { tender_id: this.ctx.tender.id });
@@ -716,7 +717,7 @@ module.exports = app => {
                     // todo 最底层项目节其实应该导入,但是由于目前项目节不能输入金额,也不能计量,导入金额就会有矛盾,故暂时不导入
                     if (this.ctx.tender.data.measure_type === measureType.tz.value) {
                         data.sgfh_qty = node.quantity;
-                        data.sgfh_tp = node.total_price;
+                        data.sgfh_tp = node.b_code ? node.total_price : 0;
                         data.quantity = node.quantity;
                         data.total_price = node.b_code ? node.total_price : 0;
                     } else if (this.ctx.tender.data.measure_type === measureType.gcl.value) {
@@ -759,18 +760,6 @@ module.exports = app => {
                 throw (err.stack ? '导入工程量数据出错': err);
             }
         }
-
-        async loadDataFromOss(tid, url) {
-            const data = await this.ctx.helper.loadLedgerDataFromOss(url);
-            const curData = await this.getAllDataByCondition({
-                columns: ['id', 'is_tp', 'gxby_status', 'gxby_limit', 'gxby_url', 'dagl_status', 'dagl_limit', 'dagl_url'],
-                where: { tender_id: tid }
-            });
-            this.ctx.helper.assignRelaData(data, [
-                { data: curData, fields: ['is_tp', 'gxby_status', 'gxby_limit', 'gxby_url', 'dagl_status', 'dagl_limit', 'dagl_url'], prefix: '', relaId: 'id' },
-            ]);
-            return data;
-        }
     }
 
     return Ledger;

+ 37 - 0
app/service/ledger_extra.js

@@ -0,0 +1,37 @@
+'use strict';
+
+/**
+ * 部位明细
+ *
+ * @author Mai
+ * @date
+ * @version
+ */
+
+module.exports = app => {
+
+    class LedgerExtra extends app.BaseService {
+        /**
+         * 构造函数
+         *
+         * @param {Object} ctx - egg全局变量
+         * @return {void}
+         */
+        constructor(ctx) {
+            super(ctx);
+            this.depart = 10;
+            this.tableName = 'ledger_extra';
+        }
+
+        async getData(tid, columns) {
+            if (!columns || columns.length === 0) return [];
+
+            return await this.getAllDataByCondition({
+                where: { tid },
+                columns: ['id', ...columns],
+            });
+        }
+    }
+
+    return LedgerExtra;
+};

+ 9 - 0
app/service/ledger_history.js

@@ -58,6 +58,7 @@ module.exports = app => {
                 pid: this.ctx.session.sessionProject.id, tid: tender.id,
                 in_time: now,
                 bills_file: billsHis, pos_file: posHis,
+                bills_count: bills.length, pos_count: pos.length,
             });
 
             return result.insertId;
@@ -70,6 +71,11 @@ module.exports = app => {
          * @private
          */
         async backupStageLedgerHistory(stage) {
+            const sbCount = await this.ctx.service.ledger.count({ tender_id: this.ctx.stage.tid });
+            const spCount = await this.ctx.service.pos.count({ tid: this.ctx.stage.tid });
+            const ledgerHis = await this.ctx.service.ledgerHistory.getLatestHistory(this.ctx.tender.id);
+            if (sbCount === ledgerHis.bills_count && spCount === ledgerHis.pos_count) return ledgerHis.id;
+
             const now = new Date();
             const timestamp = (now).getTime();
 
@@ -85,6 +91,7 @@ module.exports = app => {
                 pid: this.ctx.session.sessionProject.id, tid: stage.tid, sid: stage.id,
                 in_time: now,
                 bills_file: billsHis, pos_file: posHis,
+                bills_count: bills.length, pos_count: pos.length,
             });
 
             return result.insertId;
@@ -113,6 +120,7 @@ module.exports = app => {
                 rid: revise.id, rorder: revise.corder,
                 in_time: now,
                 bills_file: billsHis, pos_file: posHis,
+                bills_count: bills.length, pos_count: pos.length,
             });
 
             return result.insertId;
@@ -147,6 +155,7 @@ module.exports = app => {
                 cid: change.cid,
                 in_time: now,
                 bills_file: billsHis, pos_file: posHis,
+                bills_count: bills.length, pos_count: pos.length,
             });
 
             return result.insertId;

+ 6 - 6
app/service/ledger_revise.js

@@ -98,14 +98,14 @@ module.exports = app => {
             const sql = 'Insert Into ' + this.ctx.service.reviseBills.tableName +
                 '  (id, code, b_code, name, unit, source, remark, ledger_id, ledger_pid, level, `order`, full_path, is_leaf,' +
                 '     quantity, total_price, unit_price, drawing_code, memo, dgn_qty1, dgn_qty2, deal_qty, deal_tp,' +
-                '     sgfh_qty, sgfh_tp, sjcl_qty, sjcl_tp, qtcl_qty, qtcl_tp, node_type, crid, tender_id, is_tp,' +
+                '     sgfh_qty, sgfh_tp, sjcl_qty, sjcl_tp, qtcl_qty, qtcl_tp, node_type, crid, tender_id,' +
                 '     sgfh_expr, sjcl_expr, qtcl_expr, check_calc,' +
-                '     gxby_status, dagl_status, gxby_url, dagl_url, gxby_limit, dagl_limit, ex_memo1, ex_memo2, ex_memo3)' +
+                '     ex_memo1, ex_memo2, ex_memo3)' +
                 '  Select id, code, b_code, name, unit, source, remark, ledger_id, ledger_pid, level, `order`, full_path, is_leaf,' +
                 '      quantity, total_price, unit_price, drawing_code, memo, dgn_qty1, dgn_qty2, deal_qty, deal_tp,' +
-                '      sgfh_qty, sgfh_tp, sjcl_qty, sjcl_tp, qtcl_qty, qtcl_tp, node_type, crid, tender_id, is_tp,' +
+                '      sgfh_qty, sgfh_tp, sjcl_qty, sjcl_tp, qtcl_qty, qtcl_tp, node_type, crid, tender_id,' +
                 '      sgfh_expr, sjcl_expr, qtcl_expr, 0,' +
-                '      gxby_status, dagl_status, gxby_url, dagl_url, gxby_limit, dagl_limit, ex_memo1, ex_memo2, ex_memo3' +
+                '      ex_memo1, ex_memo2, ex_memo3' +
                 '  From ' + this.ctx.service.ledger.tableName +
                 '  Where `tender_id` = ?';
             const sqlParam = [tid];
@@ -117,11 +117,11 @@ module.exports = app => {
                 '  (id, tid, lid, name, drawing_code, quantity, add_stage, add_stage_order, add_times, add_user,' +
                 '     sgfh_qty, sjcl_qty, qtcl_qty, crid, in_time, porder, position,' +
                 '     sgfh_expr, sjcl_expr, qtcl_expr, real_qty,' +
-                '     gxby_status, dagl_status, gxby_url, dagl_url, gxby_limit, dagl_limit, ex_memo1, ex_memo2, ex_memo3)' +
+                '     ex_memo1, ex_memo2, ex_memo3)' +
                 '  Select id, tid, lid, name, drawing_code, quantity, add_stage, add_stage_order, add_times, add_user,' +
                 '     sgfh_qty, sjcl_qty, qtcl_qty, crid, in_time, porder, position,' +
                 '     sgfh_expr, sjcl_expr, qtcl_expr, real_qty,' +
-                '     gxby_status, dagl_status, gxby_url, dagl_url, gxby_limit, dagl_limit, ex_memo1, ex_memo2, ex_memo3' +
+                '     ex_memo1, ex_memo2, ex_memo3' +
                 '  From ' + this.ctx.service.pos.tableName +
                 '  Where `tid` = ?';
             const sqlParam = [tid];

+ 2 - 16
app/service/pos.js

@@ -29,7 +29,6 @@ module.exports = app => {
                 where: condition,
                 columns: column || ['id', 'tid', 'lid', 'name', 'quantity', 'position', 'drawing_code', 'sgfh_qty', 'sjcl_qty',
                     'qtcl_qty', 'in_time', 'porder', 'add_stage', 'sgfh_expr', 'sjcl_expr', 'qtcl_expr', 'real_qty',
-                    'dagl_status', 'dagl_url', 'gxby_status', 'gxby_url', 'gxby_limit', 'dagl_limit',
                     'ex_memo1', 'ex_memo2', 'ex_memo3'],
                 order: [['porder', 'ASC']],
             });
@@ -39,8 +38,7 @@ module.exports = app => {
             if (!condition.tid) throw '查询计量单元缺少必要信息';
             const sql = 'SELECT id, tid, lid, name, quantity, position, drawing_code,' +
                 '    sgfh_qty, sjcl_qty, qtcl_qty, porder, add_stage, add_times, add_user, add_stage_order,' +
-                '    sgfh_expr, sjcl_expr, qtcl_expr, real_qty, gxby_status, gxby_url, dagl_status, dagl_url,' +
-                '    gxby_limit, dagl_limit, ex_memo1, ex_memo2, ex_memo3' +
+                '    sgfh_expr, sjcl_expr, qtcl_expr, real_qty, ex_memo1, ex_memo2, ex_memo3' +
                 '  FROM ' + this.departTableName(condition.tid) + this.ctx.helper.whereSql(condition);
             return await this.db.query(sql);
         }
@@ -49,7 +47,7 @@ module.exports = app => {
             if (ids instanceof Array && ids.length > 0) {
                 const sql = 'SELECT id, tid, lid, name, quantity, position, drawing_code,' +
                     '    sgfh_qty, sjcl_qty, qtcl_qty, add_stage, add_times, add_user, sgfh_expr, sjcl_expr, qtcl_expr, real_qty,' +
-                    '    dagl_status, dagl_url, gxby_status, gxby_url, gxby_limit, dagl_limit, ex_memo1, ex_memo2, ex_memo3' +
+                    '    ex_memo1, ex_memo2, ex_memo3' +
                     '  FROM ' + this.departTableName(tid) +
                     '  WHERE id in (' + this.ctx.helper.getInArrStrSqlFilter(ids) + ')';
                 return await this.db.query(sql, []);
@@ -503,18 +501,6 @@ module.exports = app => {
         async deletePosData(transaction, tid, lid) {
             await transaction.delete(this.tableName, {tid: tid, lid: lid});
         }
-
-        async loadDataFromOss(tid, url) {
-            const data = await this.ctx.helper.loadLedgerDataFromOss(url);
-            const curData = await this.getAllDataByCondition({
-                columns: ['id', 'gxby_status', 'gxby_limit', 'gxby_url', 'dagl_status', 'dagl_limit', 'dagl_url'],
-                where: { tid: tid }
-            });
-            this.ctx.helper.assignRelaData(data, [
-                { data: curData, fields: ['gxby_status', 'gxby_limit', 'gxby_url', 'dagl_status', 'dagl_limit', 'dagl_url'], prefix: '', relaId: 'id' },
-            ]);
-            return data;
-        }
     }
 
     return Pos;

+ 37 - 0
app/service/pos_extra.js

@@ -0,0 +1,37 @@
+'use strict';
+
+/**
+ * 部位明细
+ *
+ * @author Mai
+ * @date
+ * @version
+ */
+
+module.exports = app => {
+
+    class LedgerExtra extends app.BaseService {
+        /**
+         * 构造函数
+         *
+         * @param {Object} ctx - egg全局变量
+         * @return {void}
+         */
+        constructor(ctx) {
+            super(ctx);
+            this.depart = 20;
+            this.tableName = 'pos_extra';
+        }
+
+        async getData(tid, columns) {
+            if (!columns || columns.length === 0) return [];
+
+            return await this.getAllDataByCondition({
+                where: { tid },
+                columns: ['id', ...columns],
+            });
+        }
+    }
+
+    return LedgerExtra;
+};

+ 4 - 2
app/service/project.js

@@ -11,6 +11,7 @@ const imType = require('../const/tender').imType;
 const defaultFunRela = {
     banOver: true,
     hintOver: true,
+    minusNoValue: true,
     imType: imType.zl.value,
     needGcl: false,
 };
@@ -55,7 +56,8 @@ module.exports = app => {
                     rule = {
                         imType: {type: 'enum', values: [imType.tz.value, imType.zl.value, imType.bb.value, imType.bw.value], required: true},
                         banOver: {type: 'bool', required: true,},
-                        hintOver: {type: 'bool', required: true,}
+                        hintOver: {type: 'bool', required: true,},
+                        minusNoValue: {type: 'bool', required: true,}
                     };
                     break;
                 default:
@@ -162,7 +164,7 @@ module.exports = app => {
             const result = await this.db.update(this.tableName, {
                 id: id, fun_rela: JSON.stringify({
                     banOver: data.banOver, hintOver: data.hintOver,
-                    imType: data.imType, needGcl: data.needGcl,
+                    imType: data.imType, needGcl: data.needGcl, minusNoValue: data.minusNoValue,
                 }),
             });
             return result.affectedRows === 1;

+ 21 - 43
app/service/report_memory.js

@@ -25,11 +25,11 @@ const stageImVersion = '1.3';
 const Ledger = require('../lib/ledger');
 
 const billsFields = (function () {
-    const cur = ['contract_qty', 'contract_tp', 'contract_expr', 'qc_qty', 'qc_tp', 'gather_qty', 'gather_tp', 'postil'];
-    const pre = ['pre_contract_qty', 'pre_contract_tp', 'pre_qc_qty', 'pre_qc_tp', 'pre_gather_qty', 'pre_gather_tp'];
-    const end = ['end_contract_qty', 'end_contract_tp', 'end_qc_qty', 'end_qc_tp', 'end_gather_qty', 'end_gather_tp'];
+    const cur = ['contract_qty', 'contract_tp', 'contract_expr', 'qc_qty', 'qc_tp', 'qc_minus_qty', 'qc_minus_tp', 'gather_qty', 'gather_tp', 'postil'];
+    const pre = ['pre_contract_qty', 'pre_contract_tp', 'pre_qc_qty', 'pre_qc_tp', 'pre_qc_minus_qty', 'pre_qc_minus_tp', 'pre_gather_qty', 'pre_gather_tp'];
+    const end = ['end_contract_qty', 'end_contract_tp', 'end_qc_qty', 'end_qc_tp', 'end_qc_minus_qty', 'end_qc_minus_tp', 'end_gather_qty', 'end_gather_tp'];
     const final = ['final_tp', 'final_ratio'];
-    const final1 = ['minus_qc_qty', 'pre_minus_qc_qty', 'end_minus_qc_qty', 'final_1_qty', 'final_1_tp', 'final_1_ratio'];
+    const final1 = [ 'final_1_qty', 'final_1_tp', 'final_1_ratio'];
     const stageDgn = ['deal_dgn_qty1', 'deal_dgn_qty2', 'c_dgn_qty1', 'c_dgn_qty2'];
 
     const stage = cur.concat(pre, end, final);
@@ -40,11 +40,11 @@ const billsFields = (function () {
     return {cur, pre, end, final, final1, stageDgn, stage, stageEnd, bgl, leafXmj};
 })();
 const posFields = (function () {
-    const cur = ['contract_qty', 'qc_qty', 'gather_qty', 'postil'];
-    const pre = ['pre_contract_qty', 'pre_qc_qty', 'pre_gather_qty'];
-    const end = ['end_contract_qty', 'end_qc_qty', 'end_gather_qty'];
+    const cur = ['contract_qty', 'qc_qty', 'qc_minus_qty', 'gather_qty', 'postil'];
+    const pre = ['pre_contract_qty', 'pre_qc_qty', 'pre_qc_minus_qty', 'pre_gather_qty'];
+    const end = ['end_contract_qty', 'end_qc_qty', 'end_qc_minus_qty', 'end_gather_qty'];
     const final = ['final_ratio'];
-    const final1 = ['minus_qc_qty', 'pre_minus_qc_qty', 'end_minus_qc_qty', 'final_1_qty', 'final_1_ratio'];
+    const final1 = ['final_1_qty', 'final_1_ratio'];
 
     const stage = cur.concat(pre, end, final);
     const stageEnd = pre.concat(end, final);
@@ -83,9 +83,9 @@ module.exports = app => {
                     p.final_qty = ctx.helper.add(p.end_qc_qty, p.quantity);
                     p.final_ratio = ctx.helper.mul(ctx.helper.div(p.end_gather_qty, p.final_qty, 4), 100);
 
-                    p.end_minus_qc_qty = ctx.helper.add(p.pre_minus_qc_qty, p.minus_qc_qty);
-                    p.final_1_qty = ctx.helper.add(p.end_minus_qc_qty, p.quantity);
-                    p.end_final_1_qty = ctx.helper.add(p.final_1_qty, p.end_qc_qty);
+                    p.end_qc_minus_qty = ctx.helper.add(p.pre_qc_minus_qty, p.qc_minus_qty);
+                    p.final_1_qty = ctx.helper.add(p.end_qc_minus_qty, p.quantity);
+                    p.end_final_1_qty = ctx.helper.add(p.end_qc_qty, p.final_1_qty);
                     p.final_1_ratio = ctx.helper.mul(ctx.helper.div(p.end_gather_qty, p.end_final_1_qty, 4), 100);
                 }
             });
@@ -114,8 +114,8 @@ module.exports = app => {
                         node.end_contract_qty = helper.add(node.pre_contract_qty, node.contract_qty);
                         node.end_qc_qty = helper.add(node.pre_qc_qty, node.qc_qty);
                         node.end_gather_qty = helper.add(node.pre_gather_qty, node.gather_qty);
-                        node.end_minus_qc_qty = helper.add(node.pre_minus_qc_qty, node.minus_qc_qty);
-                        node.final_1_qty = helper.add(node.quantity, node.end_minus_qc_qty);
+                        node.end_qc_minus_qty = helper.add(node.pre_qc_minus_qty, node.qc_minus_qty);
+                        node.final_1_qty = helper.add(node.quantity, node.end_qc_minus_qty);
                         node.end_final_1_qty = helper.add(node.final_1_qty, node.end_qc_qty);
                     }
                     node.pre_gather_tp = helper.add(node.pre_contract_tp, node.pre_qc_tp);
@@ -405,20 +405,9 @@ module.exports = app => {
                     preStage = this.ctx.stage.order > 1 ? await this.ctx.service.stageBillsFinal.getFinalData(this.ctx.tender, this.ctx.stage.order - 1) : [];
                 }
                 this.ctx.helper.assignRelaData(billsData, [
-                    {data: curStage, fields: ['contract_qty', 'contract_tp', 'contract_expr', 'qc_qty', 'qc_tp', 'postil'], prefix: '', relaId: 'lid'},
-                    {data: preStage, fields: ['contract_qty', 'contract_tp', 'qc_qty', 'qc_tp'], prefix: 'pre_', relaId: 'lid'}
+                    {data: curStage, fields: ['contract_qty', 'contract_tp', 'contract_expr', 'qc_qty', 'qc_tp', 'qc_minus_qty', 'postil'], prefix: '', relaId: 'lid'},
+                    {data: preStage, fields: ['contract_qty', 'contract_tp', 'qc_qty', 'qc_tp', 'qc_minus_qty'], prefix: 'pre_', relaId: 'lid'}
                 ]);
-                if (this._checkFieldsExist(fields, billsFields.final1)) {
-                    const preMinusChange = await this.ctx.service.stageChangeFinal.getPreMinusChange(this.ctx.stage.tid, this.ctx.stage.order);
-                    const changeData = this.ctx.stage.readOnly
-                        ? await this.ctx.service.stageChange.getAuditorAllStageData(this.ctx.tender.id, this.ctx.stage.id, this.ctx.stage.curTimes, this.ctx.stage.curOrder)
-                        : await this.ctx.service.stageChange.getLastestAllStageData(this.ctx.tender.id, this.ctx.stage.id);
-                    const minusChange = changeData.filter(x => { return x.minus });
-                    this.ctx.helper.assignSumRelaData(billsData, 'id', [
-                        {data: preMinusChange, fields: [{source: 'qty', target: 'pre_minus_qc_qty'}], relaField: 'lid'},
-                        {data: minusChange, fields: [{source: 'qty', target: 'minus_qc_qty'}], relaField: 'lid'},
-                    ]);
-                }
 
                 const billsTree = this._getNewBillsTree();
                 billsTree.loadDatas(billsData);
@@ -483,20 +472,9 @@ module.exports = app => {
                     prePosStage = this.ctx.stage.order > 1 ? await this.ctx.service.stagePosFinal.getFinalData(this.ctx.tender, this.ctx.stage.order - 1) : [];
                 }
                 this.ctx.helper.assignRelaData(posData, [
-                    {data: curPosStage, fields: ['contract_qty', 'qc_qty', 'contract_expr', 'postil'], prefix: '', relaId: 'pid'},
-                    {data: prePosStage, fields: ['contract_qty', 'qc_qty'], prefix: 'pre_', relaId: 'pid'}
+                    {data: curPosStage, fields: ['contract_qty', 'qc_qty', 'qc_minus_qty', 'contract_expr', 'postil'], prefix: '', relaId: 'pid'},
+                    {data: prePosStage, fields: ['contract_qty', 'qc_qty', 'qc_minus_qty'], prefix: 'pre_', relaId: 'pid'}
                 ]);
-                if (this._checkFieldsExist(fields, posFields.final1)) {
-                    const preMinusChange = await this.ctx.service.stageChangeFinal.getPreMinusChange(this.ctx.stage.tid, this.ctx.stage.order);
-                    const changeData = this.ctx.stage.readOnly
-                        ? await this.ctx.service.stageChange.getAuditorAllStageData(this.ctx.tender.id, this.ctx.stage.id, this.ctx.stage.curTimes, this.ctx.stage.curOrder)
-                        : await this.ctx.service.stageChange.getLastestAllStageData(this.ctx.tender.id, this.ctx.stage.id);
-                    const minusChange = changeData.filter(x => { return x.minus });
-                    this.ctx.helper.assignSumRelaData(posData, 'id', [
-                        {data: preMinusChange, fields: [{source: 'qty', target: 'pre_minus_qc_qty'}], relaField: 'pid'},
-                        {data: minusChange, fields: [{source: 'qty', target: 'minus_qc_qty'}], relaField: 'pid'},
-                    ]);
-                }
                 this.pos.loadDatas(posData);
                 this.pos.calculateAll();
 
@@ -566,14 +544,14 @@ module.exports = app => {
                         filterStageBills.push(stageBillsIndex[prop]);
                     }
                     this.ctx.helper.assignRelaData(billsData, [
-                        {data: filterStageBills, fields: ['contract_qty', 'contract_tp', 'qc_qty', 'qc_tp'], prefix: 'r' + role.flowOrder + '_', relaId: 'lid'}
+                        {data: filterStageBills, fields: ['contract_qty', 'contract_tp', 'qc_qty', 'qc_tp', 'qc_minus_qty'], prefix: 'r' + role.flowOrder + '_', relaId: 'lid'}
                     ]);
                 }
 
                 if (this._checkFieldsExist(fields, billsFields.stageEnd)) {
                     const preStage = this.ctx.stage.order > 1 ? await this.ctx.service.stageBillsFinal.getFinalData(this.ctx.tender, this.ctx.stage.order - 1) : [];
                     this.ctx.helper.assignRelaData(billsData, [
-                        {data: preStage, fields: ['contract_qty', 'contract_tp', 'qc_qty', 'qc_tp'], prefix: 'pre_', relaId: 'lid'}
+                        {data: preStage, fields: ['contract_qty', 'contract_tp', 'qc_qty', 'qc_tp', 'qc_minus_qty'], prefix: 'pre_', relaId: 'lid'}
                     ]);
                 }
                 const billsTree = this._getNewBillsTree();
@@ -642,7 +620,7 @@ module.exports = app => {
                 const posData = await this.ctx.service.pos.getAllDataByCondition({ where: {tid: this.ctx.tender.id }});
                 const prePosStage = this.ctx.stage.order > 1 ? await this.ctx.service.stagePosFinal.getFinalData(this.ctx.tender, this.ctx.stage.order - 1) : [];
                 this.ctx.helper.assignRelaData(posData, [
-                    {data: prePosStage, fields: ['contract_qty', 'qc_qty'], prefix: 'pre_', relaId: 'pid'}
+                    {data: prePosStage, fields: ['contract_qty', 'qc_qty', 'qc_minus_qty'], prefix: 'pre_', relaId: 'pid'}
                 ]);
                 const stagePosIndex = {}, timesLen = 100;
                 for (const role of validRole) {
@@ -664,7 +642,7 @@ module.exports = app => {
                         filterStagePos.push(stagePosIndex[prop]);
                     }
                     this.ctx.helper.assignRelaData(posData, [
-                        {data: filterStagePos, fields: ['contract_qty', 'qc_qty'], prefix: 'r' + role.flowOrder + '_', relaId: 'pid'}
+                        {data: filterStagePos, fields: ['contract_qty', 'qc_qty', 'qc_minus_qty'], prefix: 'r' + role.flowOrder + '_', relaId: 'pid'}
                     ]);
                 }
                 this.pos.loadDatas(posData);

+ 5 - 6
app/service/revise_audit.js

@@ -303,15 +303,13 @@ module.exports = app => {
                 this.ctx.service.ledger.tableName +
                 '  (id, code, b_code, name, unit, source, remark, ledger_id, ledger_pid, level, `order`, full_path, is_leaf,' +
                 '     quantity, total_price, unit_price, drawing_code, memo, dgn_qty1, dgn_qty2, deal_qty, deal_tp,' +
-                '     sgfh_qty, sgfh_tp, sjcl_qty, sjcl_tp, qtcl_qty, qtcl_tp, node_type, crid, tender_id, is_tp,' +
+                '     sgfh_qty, sgfh_tp, sjcl_qty, sjcl_tp, qtcl_qty, qtcl_tp, node_type, crid, tender_id,' +
                 '     sgfh_expr, sjcl_expr, qtcl_expr, check_calc,' +
-                '     gxby_status, dagl_status, gxby_url, dagl_url, gxby_limit,  dagl_limit,' +
                 '     ex_memo1, ex_memo2, ex_memo3)' +
                 '  Select id, code, b_code, name, unit, source, remark, ledger_id, ledger_pid, level, `order`, full_path, is_leaf,' +
                 '      quantity, total_price, unit_price, drawing_code, memo, dgn_qty1, dgn_qty2, deal_qty, deal_tp,' +
-                '      sgfh_qty, sgfh_tp, sjcl_qty, sjcl_tp, qtcl_qty, qtcl_tp, node_type, crid, tender_id, is_tp, ' +
+                '      sgfh_qty, sgfh_tp, sjcl_qty, sjcl_tp, qtcl_qty, qtcl_tp, node_type, crid, tender_id, ' +
                 '      sgfh_expr, sjcl_expr, qtcl_expr, check_calc,' +
-                '      gxby_status, dagl_status, gxby_url, dagl_url, gxby_limit,  dagl_limit,' +
                 '      ex_memo1, ex_memo2, ex_memo3' +
                 '  From ' +
                 this.ctx.service.reviseBills.tableName +
@@ -324,12 +322,10 @@ module.exports = app => {
                 '  (id, tid, lid, name, drawing_code, quantity, add_stage, add_stage_order, add_times, add_user,' +
                 '     sgfh_qty, sjcl_qty, qtcl_qty, crid, porder, position, ' +
                 '     sgfh_expr, sjcl_expr, qtcl_expr, real_qty,' +
-                '     gxby_status, dagl_status, gxby_url, dagl_url, gxby_limit,  dagl_limit,' +
                 '     ex_memo1, ex_memo2, ex_memo3)' +
                 '  Select id, tid, lid, name, drawing_code, quantity, add_stage, add_stage_order, add_times, add_user,' +
                 '     sgfh_qty, sjcl_qty, qtcl_qty, crid, porder, position,' +
                 '     sgfh_expr, sjcl_expr, qtcl_expr, real_qty,' +
-                '     gxby_status, dagl_status, gxby_url, dagl_url, gxby_limit,  dagl_limit,' +
                 '     ex_memo1, ex_memo2, ex_memo3' +
                 '  From ' +
                 this.ctx.service.revisePos.tableName +
@@ -427,6 +423,7 @@ module.exports = app => {
                         await this.ctx.helper.sendAliSms(users, smsTypeConst.const.XD, smsTypeConst.judge.result.toString(), SmsAliConst.template.revise_result2, {
                             status: SmsAliConst.status.success,
                         });
+
                         // 微信模板通知
                         // const wechatData2 = {
                         //     status: wxConst.status.success,
@@ -462,6 +459,8 @@ module.exports = app => {
                             total_price: sum.total_price,
                             deal_tp: sum.deal_tp,
                         });
+                        // 清除变更新增部位maxLid缓存,防止树结构混乱
+                        await this.ctx.service.changeLedger._removeCacheMaxLid(audit.tender_id);
                         // 短信通知-审批通过提醒功能
                         // 下一人
                         // const msg = '台账修订审批通过,请登录系统处理。';

+ 4 - 0
app/service/rpt_gather_memory.js

@@ -581,6 +581,10 @@ module.exports = app => {
                 info.yf_tp = stage.yf_tp;
                 info.pre_yf_tp = stage.pre_yf_tp;
                 info.end_yf_tp = helper.add(stage.yf_tp, stage.pre_yf_tp);
+
+                info.sf_tp = stage.sf_tp;
+                info.pre_sf_tp = stage.pre_sf_tp;
+                info.end_sf_tp = helper.add(stage.sf_tp, stage.pre_sf_tp);
             }
         }
 

+ 3 - 1
app/service/stage.js

@@ -267,7 +267,7 @@ module.exports = app => {
                 s.end_tp = this.ctx.helper.add(s.pre_tp, s.tp);
                 s.tp_history = s.tp_history ? JSON.parse(s.tp_history) : [];
             }
-            if (stages.length !== 0) {
+            if (stages.length !== 0 && !this.ctx.session.sessionUser.is_admin) {
                 const lastStage = stages[0];
                 if (lastStage.status === auditConst.status.uncheck && lastStage.user_id !== this.ctx.session.sessionUser.accountId && !this.ctx.tender.isTourist) {
                     stages.splice(0, 1);
@@ -545,6 +545,7 @@ module.exports = app => {
                 await transaction.delete(this.ctx.service.stageAudit.tableName, { sid: id });
                 await transaction.delete(this.ctx.service.stageBills.tableName, { sid: id });
                 await transaction.delete(this.ctx.service.stageChange.tableName, { sid: id });
+                await transaction.delete(this.ctx.service.stageChangeFinal.tableName, { sid: id });
                 await transaction.delete(this.ctx.service.stageImportChange.tableName, { sid: id });
                 await transaction.delete(this.ctx.service.stagePos.tableName, { sid: id });
                 await transaction.delete(this.ctx.service.stageDetail.tableName, { sid: id });
@@ -725,6 +726,7 @@ module.exports = app => {
             const lastStage = await this.ctx.service.stage.getLastestStage(tid, true);
             return lastStage ? lastStage.id === sid : false;
         }
+
     }
 
     return Stage;

+ 2 - 13
app/service/stage_audit.js

@@ -470,19 +470,8 @@ module.exports = app => {
                     await this.ctx.helper.sendWechat(nextAudit.aid, smsTypeConst.const.JL, smsTypeConst.judge.approval.toString(), wxConst.template.stage, wechatData);
                 } else {
                     await this.ctx.service.tenderTag.saveTenderTag(this.ctx.tender.id, {stage_time: new Date()}, transaction);
-                    let his_id;
-                    if (this.ctx.tender.measureType === measureType.tz.value) {
-                        const ledgerHis = await this.ctx.service.ledgerHistory.getLatestHistory(this.ctx.tender.id);
-                        his_id = ledgerHis.id;
-                    } else {
-                        const sapCount = await this.ctx.service.pos.count({ add_stage: this.ctx.stage.id });
-                        if (sapCount > 0) {
-                            his_id = await this.ctx.service.ledgerHistory.backupStageLedgerHistory(this.ctx.stage);
-                        } else {
-                            const ledgerHis = await this.ctx.service.ledgerHistory.getLatestHistory(this.ctx.tender.id);
-                            his_id = ledgerHis.id;
-                        }
-                    }
+                    const his_id = await this.ctx.service.ledgerHistory.backupStageLedgerHistory(this.ctx.stage);
+
                     // 本期结束
                     // 生成截止本期数据 final数据
                     await this.ctx.service.stageBillsFinal.generateFinalData(transaction, this.ctx.tender, this.ctx.stage);

+ 16 - 7
app/service/stage_bills.js

@@ -182,6 +182,7 @@ module.exports = app => {
                 d.contract_tp = orgData.contract_tp;
                 d.qc_qty = orgData.qc_qty;
                 d.qc_tp = orgData.qc_tp;
+                d.qc_minus_qty = orgData.qc_minus_qty;
                 d.postil = orgData.postil;
             }
             const precision = this.ctx.helper.findPrecision(this.ctx.tender.info.precision, ledgerData.unit);
@@ -195,6 +196,7 @@ module.exports = app => {
                 d.qc_qty = this.round(insertData.qc_qty, precision.value);
                 d.qc_tp = this.ctx.helper.mul(d.qc_qty, ledgerData.unit_price, info.decimal.tp);
             }
+            d.qc_minus_qty = insertData.qc_minus_qty ? this.round(insertData.qc_minus_qty, precision.value) : 0;
             if (insertData.postil) {
                 d.postil = insertData.postil;
             }
@@ -215,7 +217,7 @@ module.exports = app => {
             try {
                 for (const d of datas) {
                     const stageBills = await this.getLastestStageData2(this.ctx.tender.id, this.ctx.stage.id, d.lid);
-                    const ledgerBills = await this.ctx.service.ledger.getDataById(d.lid);
+                    const ledgerBills = await this.ctx.service.ledger.getCompleteDataById(d.lid);
                     if (!stageBills || stageBills.times !== this.ctx.stage.curTimes || stageBills.order !== this.ctx.stage.curOrder) {
                         await this._insertStageBillsData(transaction, d, stageBills, ledgerBills);
                     } else {
@@ -268,12 +270,13 @@ module.exports = app => {
         async calc(tid, sid, lid, transaction) {
             const info = this.ctx.tender.info;
             const stageBills = await this.getLastestStageData2(tid, sid, lid);
-            const ledgerBills = await this.ctx.service.ledger.getDataById(lid);
+            const ledgerBills = await this.ctx.service.ledger.getCompleteDataById(lid);
             if (!ledgerBills) {
                 throw '提交数据错误';
             }
             const posGather = await this.ctx.service.stagePos.getPosGather(tid, sid, lid, transaction);
             if (!posGather) { return; }
+            posGather.qc_minus_qty = posGather.qc_minus_qty || 0;
 
             const precision = this.ctx.helper.findPrecision(info.precision, ledgerBills.unit);
             // 计算
@@ -286,7 +289,7 @@ module.exports = app => {
                 posGather.qc_tp = this.ctx.helper.mul(posGather.qc_qty, ledgerBills.unit_price, info.decimal.tp);
             }
             if (stageBills) {
-                if (stageBills.contract_qty === posGather.contract_qty && stageBills.qc_qty === posGather.qc_qty) {
+                if (stageBills.contract_qty === posGather.contract_qty && stageBills.qc_qty === posGather.qc_qty && stageBills.qc_minus_qty === posGather.qc_minus_qty) {
                     return;
                 }
                 if (stageBills.times === this.ctx.stage.curTimes && stageBills.order === this.ctx.stage.curOrder) {
@@ -303,14 +306,20 @@ module.exports = app => {
 
         async updateStageBillsCalcType(data) {
             const stageBills = await this.getLastestStageData2(this.ctx.tender.id, this.ctx.stage.id, data.id);
+            const le = await this.ctx.service.ledgerExtra.getDataById(data.id);
             const updateData = { contract_qty: null, contract_tp: null };
 
             const transaction = await this.db.beginTransaction();
             try {
-                await transaction.update(this.ctx.service.ledger.tableName, data);
+                if (le) {
+                    await transaction.update(this.ctx.service.ledgerExtra.tableName, data);
+                } else {
+                    data.tid = this.ctx.tender.id;
+                    await transaction.insert(this.ctx.service.ledgerExtra.tableName, data);
+                }
                 if (stageBills) {
                     if (stageBills.times !== this.ctx.stage.curTimes || stageBills.order !== this.ctx.stage.curOrder) {
-                        const ledgerBills = await this.ctx.service.ledger.getDataById(data.id);
+                        const ledgerBills = await this.ctx.service.ledger.getCompleteDataById(data.id);
                         await this._insertStageBillsData(transaction, updateData, stageBills, ledgerBills);
                     } else {
                         updateData.id = stageBills.id;
@@ -323,7 +332,7 @@ module.exports = app => {
                 throw err;
             }
 
-            const bills = await this.ctx.service.ledger.getDataById(data.id);
+            const bills = await this.ctx.service.ledger.getCompleteDataById(data.id);
             const curStageData = await this.getLastestStageData2(this.ctx.tender.id, this.ctx.stage.id, [data.id]);
             return { bills: [bills], curStageData };
         }
@@ -449,7 +458,7 @@ module.exports = app => {
             const conn = await this.db.beginTransaction();
             try {
                 const maxId = await this.ctx.service.ledger._getMaxLid(this.ctx.tender.id);
-                const select = await this.ctx.service.ledger.getDataById(lid);
+                const select = await this.ctx.service.ledger.getCompleteDataById(lid);
                 const sumLoad = new SumLoad(this.ctx);
                 const loadTree = await sumLoad.stageGatherGcl(select, maxId, tenders, null, cover);
                 const result = loadTree.getUpdateData();

+ 5 - 18
app/service/stage_bills_dgn.js

@@ -77,11 +77,8 @@ module.exports = app => {
          * @private
          */
         async _saveDgnDatas(datas) {
-            const orgDatas = await this.db.select(this.tableName, {
-                where: {
-                    id: this._.map(datas, 'id'),
-                }
-            });
+            const ids = this._.map(datas, 'id');
+            const orgDatas = await this.db.select(this.tableName, { where: { id: ids } });
             const updateDatas = [], newDatas = [];
             for(const d of datas) {
                 this._filterInvalidField(d);
@@ -95,24 +92,14 @@ module.exports = app => {
             }
             const transaction = await this.db.beginTransaction();
             try {
-                if (newDatas.length > 0) {
-                    await transaction.insert(this.tableName, newDatas);
-                }
-                if (updateDatas.length > 0) {
-                    for (const u of updateDatas) {
-                        await transaction.update(this.tableName, u);
-                    }
-                }
+                if (newDatas.length > 0) await transaction.insert(this.tableName, newDatas);
+                if (updateDatas.length > 0) await transaction.updateRows(this.tableName, updateDatas);
                 await transaction.commit();
             } catch (err) {
                 await transaction.rollback();
                 throw err;
             }
-            await this.db.select(this.tableName, {
-                where: {
-                    id: this._.map(datas, 'id')
-                }
-            });
+            return await this.db.select(this.tableName, {where: { id: ids } });
         }
 
         /**

+ 6 - 15
app/service/stage_bills_final.js

@@ -77,7 +77,6 @@ module.exports = app => {
             }
             const cur = await this.ctx.service.stageBills.getLastestStageData2(tender.id, stage.id);
             const pre = await this.getFinalData(tender, stage.order - 1);
-            const minusChange = await this.ctx.service.stageChange.getStageMinusChange(stage);
             if ((!cur || cur.length === 0) && (!pre || pre.length === 0)) return;
             for (const c of cur) {
                 delete c.id;
@@ -94,22 +93,13 @@ module.exports = app => {
                     c.contract_tp = this.ctx.helper.add(c.contract_tp, p.contract_tp);
                     c.qc_qty = this.ctx.helper.add(c.qc_qty, p.qc_qty);
                     c.qc_tp = this.ctx.helper.add(c.qc_tp, p.qc_tp);
-                    if (p.used || !this.ctx.helper.checkZero(c.contract_qty) || !this.ctx.helper.checkZero(c.qc_qty)
-                        || !this.ctx.helper.checkZero(c.contract_tp)) {
-                        c.used = true;
-                    } else {
-                        const mc = minusChange.find(x => { return x.lid === c.lid && x.qty < 0 });
-                        c.used = !!mc;
-                    }
+                    c.qc_minus_qty = this.ctx.helper.add(c.qc_minus_qty, p.qc_minus_qty);
+                    c.used = p.used || !this.ctx.helper.checkZero(c.contract_qty) || !this.ctx.helper.checkZero(c.qc_qty)
+                        || !this.ctx.helper.checkZero(c.contract_tp) || ! this.ctx.helper.checkZero(c.qc_minus_qty);
                     pre.splice(pre.indexOf(p), 1);
                 } else {
-                    if (!this.ctx.helper.checkZero(c.contract_qty) || !this.ctx.helper.checkZero(c.qc_qty)
-                        || !this.ctx.helper.checkZero(c.contract_tp)) {
-                        c.used = true;
-                    } else {
-                        const mc = minusChange.find(x => { return x.lid === c.lid && x.qty < 0 });
-                        c.used = !!mc;
-                    }
+                    c.used = !this.ctx.helper.checkZero(c.contract_qty) || !this.ctx.helper.checkZero(c.qc_qty)
+                        || !this.ctx.helper.checkZero(c.contract_tp) || ! this.ctx.helper.checkZero(c.qc_minus_qty);
                 }
             }
 
@@ -118,6 +108,7 @@ module.exports = app => {
                 p.sid = stage.id;
                 p.sorder = stage.order;
             }
+            await transaction.delete(this.tableName, { tid: tender.id, sid: stage.id });
             await transaction.insert(this.tableName, cur ? cur.concat(pre) : pre);
         }
 

+ 64 - 54
app/service/stage_change.js

@@ -36,22 +36,24 @@ module.exports = app => {
          * @param {Number} pid - 部位明细id
          * @return {Promise<*>}
          */
-        async getLastestStageData(tid, sid, lid, pid) {
+        async getLastestStageData(tid, sid, lid, pid, noValue) {
+            const filter = noValue !== undefined ? ' And no_value = ?' : '';
             const sql = 'SELECT c.*,' +
                 '  oc.p_code As c_code, oc.new_code As c_new_code' +
                 '  FROM ' + this.tableName + ' As c ' +
                 '  INNER JOIN ( ' +
-                '    SELECT MAX(`stimes` * ' + timesLen + ' + `sorder`) As `progress`, `lid`, `pid`, `sid`, `cid`, `cbid` From ' + this.tableName +
-                '      WHERE tid = ? And sid = ? And lid = ? And pid = ?' +
-                '      GROUP By `lid`, `pid`, `cid`, `cbid`' +
+                '    SELECT MAX(`stimes` * ' + timesLen + ' + `sorder`) As `progress`, `lid`, `pid`, `sid`, `cid`, `cbid`, `no_value` From ' + this.tableName +
+                '      WHERE tid = ? And sid = ? And lid = ? And pid = ?' + filter +
+                '      GROUP By `lid`, `pid`, `cid`, `cbid`, `no_value`' +
                 '  ) As m ' +
-                '  ON (c.stimes * ' + timesLen + ' + c.sorder) = m.progress And c.lid = m.lid And c.pid = m.pid And c.`sid` = m.`sid` And c.`cid` = m.`cid` And c.`cbid` = m.`cbid`' +
+                '  ON (c.stimes * ' + timesLen + ' + c.sorder) = m.progress And c.lid = m.lid And c.pid = m.pid And c.`sid` = m.`sid` And c.`cid` = m.`cid` And c.`cbid` = m.`cbid` And c.`no_value` = m.`no_value`' +
                 '  LEFT JOIN ' + this.ctx.service.change.tableName + ' As oc' +
                 '  ON c.cid = oc.cid' +
                 '  LEFT JOIN ' + this.ctx.service.changeAuditList.tableName + ' As ocb' +
                 '  ON c.cbid = ocb.id' +
                 '  WHERE not ISNULL(ocb.id)';
             const sqlParam = [tid, sid, lid, pid ? pid : -1];
+            if (noValue !== undefined) sqlParam.push(noValue);
             return await this.db.query(sql, sqlParam);
         }
 
@@ -65,22 +67,24 @@ module.exports = app => {
          * @param {Number} pid - 部位明细id
          * @return {Promise<*>}
          */
-        async getAuditorStageData(tid, sid, times, order, lid, pid) {
+        async getAuditorStageData(tid, sid, times, order, lid, pid, noValue) {
+            const filter = noValue !== undefined ? ' And no_value = ?' : '';
             const sql = 'SELECT c.*,' +
                 '  oc.p_code As c_code, oc.new_code As c_new_code, oc.quality, ocb.code as b_code, ocb.name, ocb.unit' +
                 '  FROM ' + this.tableName + ' As c ' +
                 '  INNER JOIN ( ' +
-                '    SELECT MAX(`stimes` * ' + timesLen + ' + `sorder`) As `progress`, `lid`, `pid`, `sid`, `cid`, `cbid` From ' + this.tableName +
-                '      WHERE tid = ? And sid = ? And (`stimes` < ? OR (`stimes` = ? AND `sorder` <= ?)) And lid = ? And pid = ?' +
-                '      GROUP By `lid`, `pid`, cid, cbid' +
+                '    SELECT MAX(`stimes` * ' + timesLen + ' + `sorder`) As `progress`, `lid`, `pid`, `sid`, `cid`, `cbid`, `no_value` From ' + this.tableName +
+                '      WHERE tid = ? And sid = ? And (`stimes` < ? OR (`stimes` = ? AND `sorder` <= ?)) And lid = ? And pid = ?' + filter +
+                '      GROUP By `lid`, `pid`, cid, cbid, no_value' +
                 '  ) As m ' +
-                '  ON (c.stimes * ' + timesLen + ' + c.sorder) = m.progress And c.lid = m.lid And c.pid = m.pid And c.`sid` = m.`sid` And c.`cid` = m.`cid` And c.`cbid` = m.`cbid`' +
+                '  ON (c.stimes * ' + timesLen + ' + c.sorder) = m.progress And c.lid = m.lid And c.pid = m.pid And c.`sid` = m.`sid` And c.`cid` = m.`cid` And c.`cbid` = m.`cbid` And c.`no_value` = m.`no_value`' +
                 '  LEFT JOIN ' + this.ctx.service.change.tableName + ' As oc' +
                 '  ON c.cid = oc.cid' +
                 '  LEFT JOIN ' + this.ctx.service.changeAuditList.tableName + ' As ocb' +
                 '  ON c.cbid = ocb.id' +
                 '  WHERE not ISNULL(ocb.id)';
             const sqlParam = [tid, sid, times, times, order, lid, pid ? pid : -1];
+            if (noValue !== undefined) sqlParam.push(noValue);
             return await this.db.query(sql, sqlParam);
         }
 
@@ -89,11 +93,11 @@ module.exports = app => {
                 '  oc.p_code As c_code, oc.new_code As c_new_code, oc.quality, ocb.code as b_code, ocb.name, ocb.unit' +
                 '  FROM ' + this.tableName + ' As c ' +
                 '  INNER JOIN ( ' +
-                '    SELECT MAX(`stimes` * ' + timesLen + ' + `sorder`) As `progress`, `lid`, `pid`, `sid`, `cid`, `cbid` From ' + this.tableName +
+                '    SELECT MAX(`stimes` * ' + timesLen + ' + `sorder`) As `progress`, `lid`, `pid`, `sid`, `cid`, `cbid`, `no_value` From ' + this.tableName +
                 '      WHERE tid = ? And sid = ?' +
-                '      GROUP By `lid`, `pid`, cid, cbid' +
+                '      GROUP By `lid`, `pid`, cid, cbid, no_value' +
                 '  ) As m ' +
-                '  ON (c.stimes * ' + timesLen + ' + c.sorder) = m.progress And c.lid = m.lid And c.pid = m.pid And c.`sid` = m.`sid` And c.`cid` = m.`cid` And c.`cbid` = m.`cbid`' +
+                '  ON (c.stimes * ' + timesLen + ' + c.sorder) = m.progress And c.lid = m.lid And c.pid = m.pid And c.`sid` = m.`sid` And c.`cid` = m.`cid` And c.`cbid` = m.`cbid` And c.`no_value` = m.`no_value`' +
                 '  LEFT JOIN ' + this.ctx.service.change.tableName + ' As oc' +
                 '  ON c.cid = oc.cid' +
                 '  LEFT JOIN ' + this.ctx.service.changeAuditList.tableName + ' As ocb' +
@@ -108,11 +112,11 @@ module.exports = app => {
                 '  oc.p_code As c_code, oc.new_code As c_new_code, oc.quality, ocb.code as b_code, ocb.name, ocb.unit' +
                 '  FROM ' + this.tableName + ' As c ' +
                 '  INNER JOIN ( ' +
-                '    SELECT MAX(`stimes` * ' + timesLen + ' + `sorder`) As `progress`, `lid`, `pid`, `sid`, `cid`, `cbid` From ' + this.tableName +
+                '    SELECT MAX(`stimes` * ' + timesLen + ' + `sorder`) As `progress`, `lid`, `pid`, `sid`, `cid`, `cbid`, `no_value` From ' + this.tableName +
                 '      WHERE tid = ? And sid = ? And (`stimes` < ? OR (`stimes` = ? AND `sorder` <= ?))' +
-                '      GROUP By `lid`, `pid`, cid, cbid' +
+                '      GROUP By `lid`, `pid`, cid, cbid, no_value' +
                 '  ) As m ' +
-                '  ON (c.stimes * ' + timesLen + ' + c.sorder) = m.progress And c.lid = m.lid And c.pid = m.pid And c.`sid` = m.`sid` And c.`cid` = m.`cid` And c.`cbid` = m.`cbid`' +
+                '  ON (c.stimes * ' + timesLen + ' + c.sorder) = m.progress And c.lid = m.lid And c.pid = m.pid And c.`sid` = m.`sid` And c.`cid` = m.`cid` And c.`cbid` = m.`cbid` And c.`no_value` = m.`no_value`' +
                 '  LEFT JOIN ' + this.ctx.service.change.tableName + ' As oc' +
                 '  ON c.cid = oc.cid' +
                 '  LEFT JOIN ' + this.ctx.service.changeAuditList.tableName + ' As ocb' +
@@ -129,24 +133,24 @@ module.exports = app => {
          * @param {Array} changes - 调用的变更令
          * @return {Promise<void>}
          */
-        async billsChange(bills, changes) {
+        async billsChange(bills, noValue, changes) {
             const self = this;
-            function getNewChange(cid, cbid, times, order, qty, minus) {
+            function getNewChange(cid, cbid, times, order, qty, minus, no_value) {
                 return {
                     tid: self.ctx.tender.id, sid: self.ctx.stage.id,
                     lid: bills.id, pid: -1,
                     cid, cbid,
                     stimes: times, sorder: order,
-                    qty, minus
+                    qty, minus, no_value,
                 };
             }
-            const ledgerBills = await this.ctx.service.ledger.getDataById(bills.id);
+            const ledgerBills = await this.ctx.service.ledger.getCompleteDataById(bills.id);
             if (!ledgerBills || ledgerBills.tender_id !== this.ctx.tender.id) {
                 throw '提交数据错误';
             }
             const precision = this.ctx.helper.findPrecision(this.ctx.tender.info.precision, ledgerBills.unit);
             // 获取原变更令
-            const oldChanges = await this.getLastestStageData(this.ctx.tender.id, this.ctx.stage.id, bills.id, -1);
+            const oldChanges = await this.getLastestStageData(this.ctx.tender.id, this.ctx.stage.id, bills.id, -1, noValue);
             // 获取更新数据
             const updateChanges = [],
                 newChanges = [];
@@ -155,7 +159,7 @@ module.exports = app => {
                 const nc = this._.find(changes, { cid: oc.cid, cbid: oc.cbid });
                 if (!nc || nc.qty !== oc.qty) {
                     const qty = nc ? this.round(nc.qty, precision.value) : null;
-                    const change = getNewChange(oc.cid, oc.cbid, this.ctx.stage.curTimes, this.ctx.stage.curOrder, qty, nc ? nc.minus : oc.minus);
+                    const change = getNewChange(oc.cid, oc.cbid, this.ctx.stage.curTimes, this.ctx.stage.curOrder, qty, nc ? nc.minus : oc.minus, noValue);
                     billsQty = this.ctx.helper.add(billsQty, change.qty);
                     if (oc.stimes === this.ctx.stage.curTimes && oc.sorder === this.ctx.stage.curOrder) {
                         change.id = oc.id;
@@ -170,7 +174,7 @@ module.exports = app => {
             for (const c of changes) {
                 const nc = this._.find(oldChanges, { cid: c.cid, cbid: c.cbid });
                 if (!nc) {
-                    const change = getNewChange(c.cid, c.cbid, this.ctx.stage.curTimes, this.ctx.stage.curOrder, this.round(c.qty, precision.value), c.minus);
+                    const change = getNewChange(c.cid, c.cbid, this.ctx.stage.curTimes, this.ctx.stage.curOrder, this.round(c.qty, precision.value), c.minus, noValue);
                     billsQty = this.ctx.helper.add(billsQty, change.qty);
                     newChanges.push(change);
                 }
@@ -185,7 +189,8 @@ module.exports = app => {
                     await transaction.update(this.tableName, c);
                 }
                 const stageBills = await this.ctx.service.stageBills.getLastestStageData2(this.ctx.tender.id, this.ctx.stage.id, bills.id);
-                await this.ctx.service.stageBills.updateStageBillsQty(transaction, ledgerBills, stageBills, { qc_qty: billsQty });
+                const sbUpdate = noValue ? {qc_minus_qty: billsQty} : {qc_qty: billsQty};
+                await this.ctx.service.stageBills.updateStageBillsQty(transaction, ledgerBills, stageBills, sbUpdate);
                 await transaction.commit();
             } catch (err) {
                 await transaction.rollback();
@@ -202,24 +207,24 @@ module.exports = app => {
          * @param {Array} changes - 调用的变更令
          * @return {Promise<{}>}
          */
-        async posChange(pos, changes) {
+        async posChange(pos, noValue, changes) {
             const self = this;
-            function getNewChange(cid, cbid, times, order, qty, minus) {
+            function getNewChange(cid, cbid, times, order, qty, minus, no_value) {
                 return {
                     tid: self.ctx.tender.id, sid: self.ctx.stage.id,
                     lid: pos.lid, pid: pos.id,
                     cid, cbid,
                     stimes: times, sorder: order,
-                    qty, minus
+                    qty, minus, no_value,
                 };
             }
-            const ledgerBills = await this.ctx.service.ledger.getDataById(pos.lid);
+            const ledgerBills = await this.ctx.service.ledger.getCompleteDataById(pos.lid);
             if (!ledgerBills || ledgerBills.tender_id !== this.ctx.tender.id) {
                 throw '提交数据错误';
             }
             const precision = this.ctx.helper.findPrecision(this.ctx.tender.info.precision, ledgerBills.unit);
             // 获取原变更令
-            const oldChanges = await this.getLastestStageData(this.ctx.tender.id, this.ctx.stage.id, pos.lid, pos.id);
+            const oldChanges = await this.getLastestStageData(this.ctx.tender.id, this.ctx.stage.id, pos.lid, pos.id, noValue);
             const updateChanges = [],
                 newChanges = [];
             let posQty = 0;
@@ -227,7 +232,7 @@ module.exports = app => {
                 const nc = this._.find(changes, { cid: oc.cid, cbid: oc.cbid });
                 if (!nc || nc.qty !== oc.qty) {
                     const qty = nc ? this.round(nc.qty, precision.value) : null;
-                    const change = getNewChange(oc.cid, oc.cbid, this.ctx.stage.curTimes, this.ctx.stage.curOrder, qty, nc ? nc.minus : oc.minus);
+                    const change = getNewChange(oc.cid, oc.cbid, this.ctx.stage.curTimes, this.ctx.stage.curOrder, qty, nc ? nc.minus : oc.minus, noValue);
                     posQty = this.ctx.helper.add(posQty, change.qty);
                     if (oc.stimes === this.ctx.stage.curTimes && oc.sorder === this.ctx.stage.curOrder) {
                         change.id = oc.id;
@@ -242,7 +247,7 @@ module.exports = app => {
             for (const c of changes) {
                 const nc = this._.find(oldChanges, { cid: c.cid, cbid: c.cbid });
                 if (!nc) {
-                    const change = getNewChange(c.cid, c.cbid, this.ctx.stage.curTimes, this.ctx.stage.curOrder, this.round(c.qty, precision.value), c.minus);
+                    const change = getNewChange(c.cid, c.cbid, this.ctx.stage.curTimes, this.ctx.stage.curOrder, this.round(c.qty, precision.value), c.minus, noValue);
                     posQty = this.ctx.helper.add(posQty, change.qty);
                     newChanges.push(change);
                 }
@@ -252,7 +257,7 @@ module.exports = app => {
             try {
                 if (newChanges.length > 0) await transaction.insert(this.tableName, newChanges);
                 if (updateChanges.length > 0) await transaction.updateRows(this.tableName, updateChanges);
-                await this.ctx.service.stagePos.updateChangeQuantity(transaction, pos, posQty);
+                await this.ctx.service.stagePos.updateChangeQuantity(transaction, pos, posQty, noValue);
                 await transaction.commit();
             } catch (err) {
                 await transaction.rollback();
@@ -292,7 +297,7 @@ module.exports = app => {
                 const pre = await this.db.query(preSql, [tid, cid, this.ctx.stage.order]);
                 const sql = 'SELECT * FROM ' + this.tableName + ' WHERE sid = ?';
                 const curAll = await this.db.query(sql, [this.ctx.stage.id]);
-                const cur = this.ctx.helper.filterLastestData(curAll, ['lid', 'pid', 'cid', 'cbid'], 'stimes', 'sorder');
+                const cur = this.ctx.helper.filterLastestData(curAll, ['lid', 'pid', 'cbid', 'no_value'], 'stimes', 'sorder');
                 return [...pre, ...cur];
             }
         }
@@ -317,7 +322,7 @@ module.exports = app => {
                 const pre = await this.db.query(preSql, [tid, cid, stage.order]);
                 const sql = 'SELECT * FROM ' + this.tableName + ' WHERE sid = ? and cid = ?';
                 const curAll = await this.db.query(sql, [stage.id, cid]);
-                const cur = this.ctx.helper.filterLastestData(curAll, ['lid', 'pid', 'cid', 'cbid'], 'stimes', 'sorder');
+                const cur = this.ctx.helper.filterLastestData(curAll, ['lid', 'pid', 'cbid', 'no_value'], 'stimes', 'sorder');
                 return [...pre, ...cur];
             }
         }
@@ -329,22 +334,27 @@ module.exports = app => {
          * @return {Promise<*>}
          */
         async getStageUsedData(sid, cid) {
-            const sql = 'SELECT c.*, ' +
-                        '    l.ledger_id As `ledger_id`, l.b_code As `l_code`, l.name As `l_name`, l.unit As `l_unit`, l.unit_price As `l_up`,' +
-                        '    l.deal_qty As `l_deal_qty`, l.deal_tp As `l_deal_tp`, l.quantity As `l_qty`, l.total_price As `l_tp`, ' +
-                        '    l.drawing_code As `l_drawing_code`, ' +
-                        '    p.name As `p_name`, p.drawing_code As `p_drawing_code`, p.`quantity` As `p_qty`' +
-                        '  FROM ' + this.tableName + ' As c ' +
-                        '  INNER JOIN ( ' +
-                        '    SELECT MAX(`stimes` * ' + timesLen + ' + `sorder`) As `flow`, `lid`, `pid`, `cbid`, `sid` From ' + this.tableName +
-                        '      WHERE sid = ? And cid = ?' +
-                        '      GROUP By `lid`, `pid`, `cbid`' +
-                        '  ) As m ' +
-                        '  ON (c.stimes * ' + timesLen + ' + c.sorder) = m.flow And c.lid = m.lid And c.pid = m.pid And c.cbid = m.cbid And c.sid = m.sid' +
-                        '  LEFT JOIN ' + this.ctx.service.ledger.tableName + ' As l ON c.lid = l.id' +
-                        '  LEFT JOIN ' + this.ctx.service.pos.tableName + ' As p ON c.pid = p.id';
-            const sqlParam = [sid, cid];
-            return await this.db.query(sql, sqlParam);
+            const data = await this.getAllDataByCondition({ where: { sid, cid } });
+            const _ = this.ctx.helper._;
+            const filter = this.ctx.helper.filterLastestData(data, ['lid', 'pid', 'cbid', 'no_value'], 'stimes', 'sorder');
+            if (filter.length === 0) return filter;
+
+            const bills = await this.ctx.service.ledger.getAllDataByCondition({
+                where: { id: _.uniq(_.map(filter, 'lid')) }
+            });
+            const pos = await this.ctx.service.pos.getAllDataByCondition({
+                where: { id: _.uniq(_.map(filter, 'pid')) }
+            });
+            return filter.map(x => {
+                const b = bills.find(y => { return y.id === x.lid });
+                const p = pos.find(y => { return y.id === x.pid });
+                return {
+                    ...x,
+                    ledger_id: b.ledger_id, l_code: b.b_code, l_name: b.name, l_unit: b.unit, l_up: b.unit_price,
+                    l_deal_qty: b.deal_qty, l_deal_tp: b.deal_tp, l_qty: b.quantity, l_tp: b.total_price, l_drawing_code: b.drawing_code,
+                    p_name: p ? p.name : '', p_drawing_code: p ? p.drawing_code : '', p_qty: p ? p.quantity : '',
+                };
+            });
         }
 
         /**
@@ -355,13 +365,13 @@ module.exports = app => {
         async getStageUsedChangeId(sid) {
             const sql = 'SELECT lid, pid, cid, cbid, qty, stimes, sorder FROM ' + this.tableName + ' WHERE sid = ?';
             const curAll = await this.db.query(sql, [sid]);
-            const cur = this.ctx.helper.filterLastestData(curAll, ['lid', 'pid', 'cid', 'cbid'], 'stimes', 'sorder');
+            const cur = this.ctx.helper.filterLastestData(curAll, ['lid', 'pid', 'cbid'], 'stimes', 'sorder');
             return this._.map(this._.filter(cur, 'qty'), 'cid');
         }
 
         async getFinalStageData(tid, sid) {
             const data = await this.getAllDataByCondition({ where: { tid, sid } });
-            return this.ctx.helper.filterLastestData(data, ['lid', 'pid', 'cid', 'cbid'], 'stimes', 'sorder');
+            return this.ctx.helper.filterLastestData(data, ['lid', 'pid', 'cbid', 'no_value'], 'stimes', 'sorder');
         }
 
         async getSumLoadFinalData(sid) {
@@ -370,7 +380,7 @@ module.exports = app => {
                 '  Left Join ' + this.ctx.service.change.tableName + ' c ON cf.cid = c.cid' +
                 '  Where cf.sid = ?';
             const result = await this.db.query(sql, [sid]);
-            return this.ctx.helper.filterLastestData(result, ['lid', 'pid', 'cbid'], 'stimes', 'sorder');
+            return this.ctx.helper.filterLastestData(result, ['lid', 'pid', 'cbid', 'no_value'], 'stimes', 'sorder');
         }
 
         async _getTender(stage) {
@@ -425,7 +435,7 @@ module.exports = app => {
                 const pre = await this.db.query(preSql, [stage.tid, stage.order]);
                 const sql = 'SELECT * FROM ' + this.tableName + ' WHERE sid = ? AND (stimes * 100 + sorder) <= (? * 100 + ?)';
                 const curAll = await this.db.query(sql, [stage.id, stage.curTimes, stage.curOrder]);
-                const cur = this.ctx.helper.filterLastestData(curAll, ['lid', 'pid', 'cid', 'cbid'], 'stimes', 'sorder');
+                const cur = this.ctx.helper.filterLastestData(curAll, ['lid', 'pid', 'cbid', 'no_value'], 'stimes', 'sorder');
                 return [...pre, ...cur];
             }
         }

+ 2 - 13
app/service/stage_change_final.js

@@ -64,9 +64,10 @@ module.exports = app => {
                 data.push({
                     tid: c.tid, sid: c.sid, sorder: stage.order,
                     lid: c.lid, pid: c.pid, cid: c.cid, cbid: c.cbid,
-                    qty: c.qty, minus: c.minus,
+                    qty: c.qty, minus: c.minus, no_value: c.no_value,
                 });
             }
+            await transaction.delete(this.tableName, { tid: tender.id, sid: stage.id });
             if (data.length > 0) await transaction.insert(this.tableName, data);
         }
 
@@ -101,18 +102,6 @@ module.exports = app => {
             const usedQty = await this.db.queryOne('Select SUM(qty) as qty FROM ' + this.tableName + ' WHERE cbid = ?', [cbid]);
             return usedQty ? this.ctx.helper.sub(qty, usedQty.qty) : qty;
         }
-
-        async getPreMinusChange(tid, sorder) {
-            const sql = 'SELECT lid, pid, SUM(qty) as qty FROM ' + this.tableName + ' WHERE tid = ? and sorder < ? and minus GROUP BY lid, pid';
-            const data = await this.db.query(sql, [tid, sorder]);
-            return data;
-        }
-
-        async getMinusChange(tid) {
-            const sql = 'SELECT lid, pid, SUM(qty) as qty FROM ' + this.tableName + ' WHERE tid = ? GROUP BY lid, pid';
-            const data = await this.db.query(sql, [tid]);
-            return data;
-        }
     }
 
     return StageChangeFinal;

+ 11 - 9
app/service/stage_pos.js

@@ -23,7 +23,7 @@ module.exports = app => {
             super(ctx);
             this.depart = 20;
             this.tableName = 'stage_pos';
-            this.qtyFields = ['contract_qty', 'qc_qty']
+            this.qtyFields = ['contract_qty', 'qc_qty', 'qc_minus_qty']
         }
 
         _getPosFilterSql(where, asTable = '') {
@@ -108,7 +108,7 @@ module.exports = app => {
         }
         async getLastestStageData2(tid, sid, where) {
             const filterSql = this._getPosFilterSql(where);
-            const sql = 'SELECT id, tid, sid, pid, lid, contract_qty, qc_qty, postil, `times`, `order`, `contract_expr`' +
+            const sql = 'SELECT id, tid, sid, pid, lid, contract_qty, qc_qty, qc_minus_qty, postil, `times`, `order`, `contract_expr`' +
                 '  FROM ' + this.departTableName(tid) +
                 '  WHERE tid = ? And sid = ? ' + filterSql;
             const sqlParam = [tid, sid];
@@ -117,7 +117,7 @@ module.exports = app => {
         }
         async getAuditorStageData2(tid, sid, times, order, where) {
             const filterSql = this._getPosFilterSql(where);
-            const sql = 'SELECT id, tid, sid, pid, lid, contract_qty, qc_qty, postil, `times`, `order`, `contract_expr`' +
+            const sql = 'SELECT id, tid, sid, pid, lid, contract_qty, qc_qty, qc_minus_qty, postil, `times`, `order`, `contract_expr`' +
                 '  FROM ' + this.departTableName(tid) +
                 '  WHERE tid = ? And sid = ? And (`times` < ? OR (`times` = ? AND `order` <= ?)) ' + filterSql;
             const sqlParam = [tid, sid, times, times, order];
@@ -129,7 +129,7 @@ module.exports = app => {
             const self = this;
             const stagePos = await this.getLastestStageData2(tid, sid, where);
             const pids = this._.map(stagePos, function (sp) {
-                if (!self.ctx.helper.checkZero(sp.contract_qty) || !self.ctx.helper.checkZero(sp.qc_qty)) {
+                if (!self.ctx.helper.checkZero(sp.contract_qty) || !self.ctx.helper.checkZero(sp.qc_qty) || !self.ctx.helper.checkZero(sp.qc_minus_qty)) {
                     return sp.pid;
                 } else {
                     return -1;
@@ -310,6 +310,7 @@ module.exports = app => {
                         if (d.postil || osp) {
                             sp.postil = d.postil === undefined && osp ? osp.postil : d.postil;
                         }
+                        sp.qc_minus_qty = osp ? osp.qc_minus_qty : 0;
                         insertPosStage.push(sp);
                     }
                 }
@@ -545,7 +546,7 @@ module.exports = app => {
             }
         }
 
-        async updateChangeQuantity(transaction, pos, qty) {
+        async updateChangeQuantity(transaction, pos, qty, noValue) {
             let orgPos = await this.getLastestStageData2(this.ctx.tender.id, this.ctx.stage.id, {pid: pos.id});
             if (orgPos.length > 1) {
                 throw '数据错误';
@@ -553,7 +554,7 @@ module.exports = app => {
                 orgPos = orgPos[0];
             }
             if (orgPos && orgPos.times === this.ctx.stage.curTimes && orgPos.order === this.ctx.stage.curOrder) {
-                await transaction.update(this.tableName, {id: orgPos.id, qc_qty: qty});
+                await transaction.update(this.tableName, noValue ? { id: orgPos.id, qc_minus_qty: qty || 0 } : {id: orgPos.id, qc_qty: qty});
             } else {
                 await transaction.insert(this.tableName, {
                     tid: this.ctx.tender.id,
@@ -564,7 +565,8 @@ module.exports = app => {
                     times: this.ctx.stage.curTimes,
                     order: this.ctx.stage.curOrder,
                     contract_qty: orgPos ? orgPos.contract_qty : 0,
-                    qc_qty: qty,
+                    qc_qty: !noValue ? qty : (orgPos ? orgPos.qc_qty : 0),
+                    qc_minus_qty: noValue ? qty : (orgPos ? orgPos.qc_minus_qty : 0),
                 });
             }
             await this.ctx.service.stageBills.calc(this.ctx.tender.id, this.ctx.stage.id, pos.lid, transaction);
@@ -579,8 +581,8 @@ module.exports = app => {
          * @returns {Promise<*>}
          */
         async getPosGather(tid, sid, lid, transaction) {
-            const calcQtySql = 'SELECT SUM(`contract_qty`) As `contract_qty`, SUM(`qc_qty`) As `qc_qty` FROM (' +
-                '  SELECT `contract_qty`, `qc_qty` FROM ' + this.ctx.service.stagePos.tableName + ' As Pos ' +
+            const calcQtySql = 'SELECT SUM(`contract_qty`) As `contract_qty`, SUM(`qc_qty`) As `qc_qty`, SUM(`qc_minus_qty`) AS `qc_minus_qty` FROM (' +
+                '  SELECT `contract_qty`, `qc_qty`, `qc_minus_qty` FROM ' + this.ctx.service.stagePos.tableName + ' As Pos ' +
                 '    INNER JOIN (' +
                 '      SELECT MAX(`times` * ' + timesLen + ' + `order`) As `flow`, `pid` ' +
                 '        FROM ' + this.ctx.service.stagePos.tableName +

+ 4 - 14
app/service/stage_pos_final.js

@@ -59,7 +59,6 @@ module.exports = app => {
             }
             const cur = await this.ctx.service.stagePos.getLastestStageData2(tender.id, stage.id);
             const pre = stage.order > 1 ? await this.getFinalData(tender, stage.order - 1) : [];
-            const minusChange = await this.ctx.service.stageChange.getStageMinusChange(stage);
             if ((!cur || cur.length === 0) && (!pre || pre.length === 0)) return;
             for (const c of cur) {
                 delete c.id;
@@ -74,28 +73,19 @@ module.exports = app => {
                 if (p) {
                     c.contract_qty = this.ctx.helper.add(c.contract_qty, p.contract_qty);
                     c.qc_qty = this.ctx.helper.add(c.qc_qty, p.qc_qty);
-                    c.used = p.used || !this.ctx.helper.checkZero(c.contract_qty) || !this.ctx.helper.checkZero(c.qc_qty);
+                    c.qc_minus_qty = this.ctx.helper.add(c.qc_minus_qty, p.qc_minus_qty);
+                    c.used = p.used || !this.ctx.helper.checkZero(c.contract_qty) || !this.ctx.helper.checkZero(c.qc_qty) || !this.ctx.helper.checkZero(c.qc_minus_qty);
                     pre.splice(pre.indexOf(p), 1);
                 } else {
-                    if (!this.ctx.helper.checkZero(c.contract_qty) || !this.ctx.helper.checkZero(c.qc_qty)) {
-                        c.used = true;
-                    } else {
-                        const mc = minusChange.find(x => { return x.pid === c.pid && x.qty < 0});
-                        c.used = !!mc;
-                    }
+                    c.used = !this.ctx.helper.checkZero(c.contract_qty) || !this.ctx.helper.checkZero(c.qc_qty) || !this.ctx.helper.checkZero(c.qc_minus_qty);
                 }
             }
             for (const p of pre) {
                 if (p.id !== undefined) delete p.id;
                 p.sid = stage.id;
                 p.sorder = stage.order;
-                if (p.used || !this.ctx.helper.checkZero(p.contract_qty) || !this.ctx.helper.checkZero(p.qc_qty)) {
-                    p.used = true;
-                } else {
-                    const mc = minusChange.find(x => { return x.pid === p.pid && x.qty < 0});
-                    p.used = !!mc;
-                }
             }
+            await transaction.delete(this.tableName, { tid: tender.id, sid: stage.id });
             await transaction.insert(this.tableName, cur ? cur.concat(pre) : pre);
         }
 

+ 195 - 1
app/service/stage_stash.js

@@ -8,6 +8,144 @@
  * @version
  */
 
+class loadStageExcelTree {
+    constructor(ctx) {
+        this.ctx = ctx;
+
+        this.decimal = ctx.tender.info.decimal;
+
+        this.insertBills = [];
+        this.insertPos = [];
+        this.updateBills = [];
+        this.updatePos = [];
+        this.insertDgn = [];
+        this.updateDgn = [];
+    }
+    init(source) {
+        this.default = source.default;
+
+        const LedgerModel = require('../lib/ledger');
+        this.ledgerTree = new LedgerModel.billsTree(this.ctx, {
+            id: 'ledger_id', pid: 'ledger_pid', order: 'order', level: 'level', rootId: -1, calcFields: [],
+        });
+        this.pos = new LedgerModel.pos({ id: 'id', ledgerId: 'lid' });
+        this.ledgerTree.loadDatas(source.ledgerData);
+        this.pos.loadDatas(source.posData);
+
+        this.stageBills = source.stageBills;
+        this.stagePos = source.stagePos;
+
+        this.stageBillsDgn = source.stageBillsDgn;
+    }
+    findNode(node, parent) {
+        const _ = this.ctx.helper._;
+        const sibling = parent ? parent.children : this.ledgerTree.children;
+        const self = this;
+        return sibling.find(x => {
+            if (node.is_leaf !== x.is_leaf) return false;
+
+            if (node.b_code) {
+                if (x.has_pos === undefined) {
+                    const relaPos = self.pos.getLedgerPos(x.id);
+                    x.has_pos = !!relaPos && relaPos.length > 0;
+                }
+                return node.b_code === _.trimEnd(x.b_code) && node.name === _.trimEnd(x.name) && node.unit === _.trimEnd(x.unit)
+                    && node.unit_price === x.unit_price && node.has_pos === x.has_pos;
+            } else {
+                return node.code === _.trimEnd(x.code) && node.name === _.trimEnd(x.name);
+            }
+        });
+    }
+    loadLeaf(node, source) {
+        const curStageBills = this.stageBills.find(csb => { return csb.lid === source.id; });
+        if (node.has_pos) {
+            const sourcePos = this.pos.getLedgerPos(source.id);
+            const sourceStagePos = this.stagePos.filter(sp => { return sp.lid === source.id; });
+
+            let contract_qty = 0;
+            for (const p of node.pos) {
+                if (!p.contract_qty) continue;
+                const sp = sourcePos.find(x => { return x.name === p.name; });
+                if (!sp) continue;
+
+                contract_qty = this.ctx.helper.add(contract_qty, p.contract_qty);
+                let ssp = sourceStagePos.find(x => { return x.pid === sp.id; });
+                if (ssp) {
+                    this.updatePos.push({ id: ssp.id, contract_qty: p.contract_qty, postil: p.postil || ssp.postil || '' });
+                    sourceStagePos.splice(sourceStagePos.indexOf(ssp), 1);
+                } else {
+                    this.insertPos.push({
+                        tid: this.default.tid, sid: this.default.sid, said: this.default.said, times: 1, order: 0,
+                        lid: source.id, pid:sp.id, contract_qty: p.contract_qty, postil: p.postil || ''
+                    });
+                }
+            }
+            for (const ssp of sourceStagePos) {
+                contract_qty = this.ctx.helper.add(contract_qty, ssp.contract_qty);
+            }
+            const contract_tp = this.ctx.helper.mul(contract_qty, source.unit_price, this.decimal.tp);
+            if (curStageBills) {
+                this.updateBills.push({ id: curStageBills.id, contract_qty, contract_tp, postil: node.postil || curStageBills.postil || '' });
+            } else {
+                if (contract_qty) this.insertBills.push({
+                    tid: this.default.tid, sid: this.default.sid, said: this.default.said, times: 1, order: 0,
+                    lid: source.id, contract_qty, contract_tp, postil: node.postil || ''
+                });
+            }
+        } else {
+            if (!node.contract_qty && !node.contract_tp) return;
+            const contract_qty = source.is_tp ? 0 : node.contract_qty;
+            const contract_tp = contract_qty
+                ? this.ctx.helper.mul(contract_qty, source.unit_price, this.decimal.tp)
+                : source.is_tp ? this.ctx.helper.round(node.contract_tp, this.decimal.tp) : 0;
+
+            if (curStageBills) {
+                this.updateBills.push({ id: curStageBills.id, contract_qty: contract_qty, contract_tp: contract_tp, postil: node.postil || curStageBills.postil || '' });
+            } else {
+                this.insertBills.push({
+                    tid: this.default.tid, sid: this.default.sid, said: this.default.said, times: 1, order: 0,
+                    lid: source.id, contract_qty: contract_qty, contract_tp: contract_tp, postil: node.postil || ''
+                });
+            }
+        }
+    }
+    loadDgn(node, cur) {
+        if (!node.deal_dgn_qty1 && !node.deal_dgn_qty2 && !node.c_dgn_qty1 && !node.c_dgn_qty2) return;
+
+        const dgn = this.stageBillsDgn.find(x => { return x.id === cur.id; });
+        if (dgn) {
+            this.updateDgn.push({ id: cur.id, deal_dgn_qty1: node.deal_dgn_qty1, deal_dgn_qty2: node.deal_dgn_qty2, c_dgn_qty1: node.c_dgn_qty1, c_dgn_qty2: node.c_dgn_qty2 });
+        } else {
+            this.insertDgn.push({ id: cur.id, tid: this.default.tid, deal_dgn_qty1: node.deal_dgn_qty1, deal_dgn_qty2: node.deal_dgn_qty2, c_dgn_qty1: node.c_dgn_qty1, c_dgn_qty2: node.c_dgn_qty2 });
+        }
+    }
+    loadNode(node, parent) {
+        node.is_leaf = !node.children || node.children.length === 0 ? 1 : 0;
+        node.has_pos = node.pos && node.pos.length > 0;
+        const cur = this.findNode(node, parent);
+        if (!cur) return;
+
+        if (cur) {
+            if (!node.b_code) this.loadDgn(node, cur);
+            if (node.is_leaf) {
+                this.loadLeaf(node, cur);
+            } else {
+                for (const c of node.children) {
+                    this.loadNode(c, cur);
+                }
+            }
+        }
+    }
+    load(excelTree, source) {
+        this.init(source);
+
+        for (const node of excelTree.roots) {
+            this.loadNode(node, null);
+        }
+    }
+}
+
+
 module.exports = app => {
     class StageStash extends app.BaseService {
         /**
@@ -38,7 +176,7 @@ module.exports = app => {
             const result = await this.db.insert(this.tableName, {
                 pid: this.ctx.session.sessionProject.id, tid: stage.tid, sid: stage.id, sorder: stage.order,
                 uid: this.ctx.session.sessionUser.accountId, uname: this.ctx.session.sessionUser.name,
-                filepath, info: {status: stage.status, flow: stage.curAuditor ? stage.curAuditor.user_id : stage.uid}, remark
+                filepath, info: JSON.stringify({ status: stage.status, flow: stage.curAuditor ? stage.curAuditor.user_id : stage.uid }), remark
             });
             return result.insertId;
         }
@@ -174,6 +312,62 @@ module.exports = app => {
                 throw err;
             }
         };
+
+        /**
+         * 导入Excel期计量(仅导入合同计量)
+         * 该方法本应该独立或者在stage下,但是跟stage_stash业务非常类似,暂归类于此
+         * @param stage
+         * @param sheet
+         * @returns {Promise<void>}
+         */
+        async loadExcelSheet(stage, excelData) {
+            const AnalysisExcel = require('../lib/analysis_excel').AnalysisStageExcelTree;
+            const analysisExcel = new AnalysisExcel(this.ctx, this.ctx.service.ledger.setting);
+
+            try {
+                const templateId = await this.ctx.service.valuation.getValuationTemplate(
+                    this.ctx.tender.data.valuation, this.ctx.tender.data.measure_type);
+                const tempData = await this.ctx.service.tenderNodeTemplate.getData(templateId, true);
+                const cacheTree = analysisExcel.analysisData(excelData, tempData, { filterZeroGcl: false });
+
+                const ledgerData = await this.ctx.service.ledger.getAllDataByCondition({
+                    columns: ['id', 'ledger_id', 'ledger_pid', 'level', 'order', 'full_path', 'is_leaf', 'code', 'b_code', 'name', 'unit', 'unit_price'],
+                    where: { tender_id: stage.tid},
+                });
+                const extraData = await this.ctx.service.ledgerExtra.getData(this.ctx.tender.id, ['is_tp']);
+                this.ctx.helper.assignRelaData(ledgerData, [
+                    { data: extraData, fields: ['is_tp'], prefix: '', relaId: 'id' },
+                ]);
+                const posData = await this.ctx.service.pos.getAllDataByCondition({
+                    columns: ['id', 'lid', 'name', 'porder'],
+                    where: { tid: stage.tid },
+                });
+                const stageBills = await this.ctx.service.stageBills.getAllDataByCondition({ where: { sid: stage.id } });
+                const stagePos = await this.ctx.service.stagePos.getAllDataByCondition({ where: { sid: stage.id } });
+                const stageBillsDgn = await this.ctx.service.stageBillsDgn.getAllDataByCondition({ where: { tid: stage.tid } });
+
+                const loadModal = new loadStageExcelTree(this.ctx);
+                loadModal.load(cacheTree, {ledgerData, posData, stageBills, stagePos, stageBillsDgn, default: { tid: stage.tid, sid: stage.id, said: this.ctx.session.sessionUser.accountId } });
+
+                const conn = await this.db.beginTransaction();
+                try {
+                    if (loadModal.insertBills.length > 0) conn.insert(this.ctx.service.stageBills.tableName, loadModal.insertBills);
+                    if (loadModal.updateBills.length > 0) conn.updateRows(this.ctx.service.stageBills.tableName, loadModal.updateBills);
+                    if (loadModal.insertPos.length > 0) conn.insert(this.ctx.service.stagePos.tableName, loadModal.insertPos);
+                    if (loadModal.updatePos.length > 0) conn.updateRows(this.ctx.service.stagePos.tableName, loadModal.updatePos);
+                    if (loadModal.insertDgn.length > 0) conn.insert(this.ctx.service.stageBillsDgn.tableName, loadModal.insertDgn);
+                    if (loadModal.updateDgn.length > 0) conn.updateRows(this.ctx.service.stageBillsDgn.tableName, loadModal.updateDgn);
+                    await conn.commit();
+                } catch (err) {
+                    await conn.rollback();
+                    this.ctx.log(err);
+                    throw '保存导入数据失败';
+                }
+            } catch (err) {
+                this.ctx.log(err);
+                throw '解析Excel错误';
+            }
+        }
     }
 
     return StageStash;

+ 17 - 0
app/view/change/information.ejs

@@ -54,6 +54,11 @@
                         </div>
                     </div>
                 <% } %>
+                <% if (showPlanBtn) { %>
+                <div class="d-inline-block ml-3">
+                    <a class="btn btn-sm btn-primary" href="#bgfadb" data-toggle="modal" data-target="#bgfadb">差值对比</a>
+                </div>
+                <% } %>
             </div>
             <div class="ml-auto" id="sp-btn">
                 <!--info状态区分-->
@@ -440,6 +445,18 @@
     console.log(changeList);
     const style1 = new GC.Spread.Sheets.Style();
     style1.locked = true;
+    const changePlanList = JSON.parse(unescape('<%- escape(JSON.stringify(planList)) %>'));
+    const planList = [];
+    if (changePlanList.length > 0) {
+        for (const cp of changePlanList) {
+            const planIndex = _.findIndex(planList, { code: cp.code, name: cp.name, unit: cp.unit, unit_price: cp.unit_price});
+            if (planIndex !== -1) {
+                planList[planIndex].spamount = ZhCalc.add(planList[planIndex].spamount, cp.spamount);
+            } else {
+                planList.push(cp);
+            }
+        }
+    }
 </script>
 <% if (auditStatus === 1 || auditStatus === 2 || auditStatus === 9) { %>
 <script>

+ 17 - 1
app/view/change/information_modal.ejs

@@ -1138,7 +1138,23 @@
         </div>
     </div>
 </div>
-
+<% if (showPlanBtn) { %>
+<div class="modal fade" id="bgfadb" data-backdrop="static">
+    <div class="modal-dialog modal-lg" style="max-width:900px;" role="document">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h5 class="modal-title">清单差值对比</h5>
+            </div>
+            <div class="modal-body">
+                <div class="modal-height-300" id="cz-spread"></div>
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-sm btn-secondary" data-dismiss="modal">关闭</button>
+            </div>
+        </div>
+    </div>
+</div>
+<% } %>
 <script type="text/javascript">
     const csrf = '<%= ctx.csrf %>';
     const authMobile = '<%= authMobile %>';

+ 5 - 4
app/view/dashboard/index.ejs

@@ -23,10 +23,11 @@
         <% } %>
         <% if (maintainData.status !== maintainConst.status.notset && new Date().getTime() + (86400*1000) > parseFloat(maintainData.maintain_time)) { %>
             <!--系统维护信息-->
-            <div class="alert alert-danger mx-3 maintain-height">
-                <span class="badge badge-pill badge-danger mr-2"><i class="fa fa-exclamation"></i></span>
-                系统将于 <%- moment(parseFloat(maintainData.maintain_time)).format('YYYY年MM月DD日 HH:mm') %> 开始停机维护,<%- (maintainData.duration !== maintainConst.duration.forever ? '持续'+ maintainConst.durationString[maintainData.duration] +'。' : '') %>造成不便敬请谅解。
-                <p class="ml-4 mb-0"><%- maintainData.msg %></p>
+            <div class="card mb-3 bg-danger text-white mx-3 maintain-height">
+                <div class="card-body">
+                    <h4><i class="fa fa-wrench"></i> 系统将于 <%- moment(parseFloat(maintainData.maintain_time)).format('YYYY年MM月DD日 HH:mm') %> 开始停机维护,<%- (maintainData.duration !== maintainConst.duration.forever ? '持续'+ maintainConst.durationString[maintainData.duration] +'。' : '') %>造成不便敬请谅解。</h4>
+                    <p class="ml-4 mb-0"><%- maintainData.msg %></p>
+                </div>
             </div>
         <% } %>
         <div class="dashboard-height mx-3">

+ 4 - 0
app/view/report/rpt_all_popup.ejs

@@ -466,6 +466,10 @@
                 <div class="alert alert-danger my-2 p-2" id="material-sum-select-hint">我是提示呀</div>
             </div>
             <div class="modal-footer">
+                <div class="form-check form-check-inline mr-auto">
+                    <input class="form-check-input" type="checkbox" id="material-sum-select-all">
+                    <label class="form-check-label" for="material-sum-select-all">全选</label>
+                </div>
                 <button type="button" class="btn btn-sm btn-secondary" data-dismiss="modal">取消</button>
                 <button class="btn btn-sm btn-primary" id="material-sum-select-ok">确定</button>
             </div>

+ 14 - 0
app/view/setting/fun.ejs

@@ -29,6 +29,19 @@
                         </div>
                         <div class="card mb-3">
                             <div class="card-body">
+                                <h5 class="card-title">负变更</h5>
+                                <div class="form-group mb-4">
+                                    <div>
+                                        <div class="form-check form-check-inline">
+                                            <input class="form-check-input" type="checkbox" id="minusNoValue" name="minusNoValue" <% if (funRela.minusNoValue) { %>checked<% } %> onchange="updateSetting();">
+                                            <label class="form-check-label" for="minusNoValue">计量不计价</label>
+                                        </div>
+                                    </div>
+                                </div>
+                            </div>
+                        </div>
+                        <div class="card mb-3">
+                            <div class="card-body">
                                 <h5 class="card-title">中间计量模式设置</h5>
                                 <div class="form-group mb-4">
                                     <div>
@@ -135,6 +148,7 @@
             imType: parseInt($('[name=im_type]:checked').val()),
             banOver: $('[name=ban_over]')[0].checked,
             hintOver: $('#hint_over')[0].checked,
+            minusNoValue: $('[name=minusNoValue]')[0].checked,
             needGcl: $('#need_gcl')[0].checked,
             openChangeProject: $('#openChangeProject')[0].checked,
             openChangeApply: $('#openChangeApply')[0].checked,

+ 1 - 1
app/view/stage/bwtz.ejs

@@ -244,7 +244,7 @@
             {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'end_qc_tp', hAlign: 2, width: 60, type: 'Number'},
             {title: '截止本期完成计量|数量', colSpan: '3|1', rowSpan: '1|1', field: 'end_gather_qty', hAlign: 2, width: 60, type: 'Number'},
             {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'end_gather_tp', hAlign: 2, width: 60, type: 'Number'},
-            {title: '|完成率(%)', colSpan: '|1', rowSpan: '|1', field: 'end_gather_percent', hAlign: 2, width: 80, readOnly: true, type: 'Number'},
+            {title: '|完成率(%)', colSpan: '|1', rowSpan: '|1', field: 'end_final_1_percent', hAlign: 2, width: 80, type: 'Number'},
             {title: '图(册)号', colSpan: '1', rowSpan: '2', field: 'drawing_code_merge', hAlign: 0, width: 80, formatter: '@'},
             {title: '本期批注', colSpan: '1', rowSpan: '2', field: 'postil_merge', hAlign: 0, width: 100, formatter: '@', cellType: 'ellipsisAutoTip'},
             {title: '备注', colSpan: '1', rowSpan: '2', field: 'memo_merge', hAlign: 0, width: 100, formatter: '@', cellType: 'ellipsisAutoTip'},

+ 1 - 0
app/view/stage/gather.ejs

@@ -104,4 +104,5 @@
     const chapter = JSON.parse('<%- JSON.stringify(ctx.tender.info.chapter) %>');
     const thousandth = <%- ctx.tender.info.display.thousandth %>;
     const hintOver = <%- hintOver %>;
+    const tenderDecimal = JSON.parse(unescape('<%- escape(JSON.stringify(ctx.tender.info.decimal)) %>'));
 </script>

+ 13 - 2
app/view/stage/index.ejs

@@ -34,7 +34,7 @@
                 </div>
                 <div class="d-inline-block ml-3">
                     <a id="exportExcel" class="btn btn-primary btn-sm" href="javascript: void(0)">导出计量台账Excel</a>
-                    <% if (ctx.app.config.is_debug && !ctx.stage.readOnly && !ctx.stage.revising && ctx.stage.status === auditConst.status.uncheck) { %>
+                    <% if (!ctx.stage.readOnly && !ctx.stage.revising && ctx.stage.status === auditConst.status.uncheck) { %>
                     <a id="importExcel" class="btn btn-primary btn-sm" href="javascript: void(0)">导入计量台账Excel</a>
                     <% } %>
                     <a class="btn btn-sm btn-primary" href="javascript: void(0);" id="ledger-check2">数据检查</a>
@@ -44,7 +44,7 @@
                 </div>
             </div>
             <div class="ml-auto">
-                <% if (ctx.session.sessionUser.is_admin) { %>
+                <% if (ctx.session.sessionUser.is_admin && ctx.tender.data.measure_type === measureType.tz.value) { %>
                 <a class="btn btn-primary btn-sm" href="#stage-stash" data-toggle="modal" data-target="#stage-stash" href="javascript: void(0)">暂存计量</a>
                 <% } %>
             </div>
@@ -151,6 +151,9 @@
                                 <tbody>
                                 <tr><th width="120" name="type-title-contract">本期合同计量数量</th><td id="show-contract-jl"></td></tr>
                                 <tr><th name="type-title-qc">本期变更计量数量</th><td id="show-qc-jl"></td></tr>
+                                <% if (minusNoValue) { %>
+                                <tr><th name="type-title-qc-minus">本期不计价变更数量</th><td id="show-qc-minus-jl"></td></tr>
+                                <% } %>
                                 <tr><th>变更令号</th><td id="show-bgl-code"></td></tr>
                                 <tr><th>变更图号</th><td id="show-bgl-drawing-code"></td></tr>
                                 <tr><th>部位</th><td id="show-bw-name"></td></tr>
@@ -180,6 +183,14 @@
                                     </div>
                                     <input type="text" class="form-control" value="" id="qc-jl" readonly="">
                                 </div>
+                                <% if (minusNoValue) { %>
+                                <div class="input-group input-group-sm mb-2">
+                                    <div class="input-group-prepend">
+                                        <span class="input-group-text" name="type-title-qc-minus">本期不计价变更数量</span>
+                                    </div>
+                                    <input type="text" class="form-control" value="" id="qc-minus-jl" readonly="">
+                                </div>
+                                <% } %>
                                 <div class="input-group input-group-sm mb-2">
                                     <div class="input-group-prepend">
                                         <span class="input-group-text">变更令号</span>

+ 19 - 6
app/view/tender/detail.ejs

@@ -183,8 +183,21 @@
                             <!--章节计量情况图-->
                             <div class="col-6 pl-0">
                                 <div class="card mb-3 <% if (!ctx.tender.info.display.dayMode) { %>bg-dark text-white<% } %>">
-                                    <% if (hadMap) { %>
-                                        <div class="card-body" id="map" style="height: 388px; width: 100%;">
+                                    <% if (hadMap === 1) { %>
+                                        <div class="card-body" id="map" style="height: 388px; width: 100%;"></div>
+                                    <% } else if (hadMap === 2) { %>
+                                        <div style="position:relative;height: 388px; width: 100%;">
+                                            <% if (map_pic) { %>
+                                            <% if (!ctx.tender.info.display.dayMode) { %>
+                                            <div style="position:absolute;top:0;left:0;width:100%;height: 388px;background-color: rgba(44, 50, 55, 0.2);z-index: 10"></div>
+                                            <% } %>
+                                            <img style="display:block;width:100%;height: 388px;margin:0 auto;" src="<%- fujianOssPath + map_pic %>">
+                                            <% } else { %>
+                                            <div class="p-5 text-center text-muted">
+                                                <img src="/public/images/nulllogo.png" />
+                                                <div class="pt-3">请上传你的静态图片</div>
+                                            </div>
+                                            <% } %>
                                         </div>
                                     <% } else  { %>
                                         <div class="card-header"><h6 class="mb-0">章节计量情况图</h6></div>
@@ -342,7 +355,7 @@
                             <!--期进度表-->
                             <div class="col-6">
                                 <div class="card mb-3 <% if (!ctx.tender.info.display.dayMode) { %>bg-dark text-white<% } %> bottom-height">
-                                    <% if (hadMap) { %>
+                                    <% if (hadMap === 1 || hadMap === 2) { %>
                                         <div class="card-header"><h6 class="mb-0">章节计量情况表</h6></div>
                                         <div class="card-body">
                                             <div id="jlchart3" style="height: 300px; width: 100%;"></div>
@@ -358,7 +371,7 @@
                             <!--月进度表-->
                             <div class="col-6 pl-0">
                                 <div class="card mb-3 bottom-height <% if (!ctx.tender.info.display.dayMode) { %>bg-dark text-white<% } %>">
-                                    <% if (hadMap) { %>
+                                    <% if (hadMap === 1 || hadMap === 2) { %>
                                         <div class="card-header">
                                             <ul class="nav nav-tabs card-header-tabs panel-card-tabs <% if (ctx.tender.info.display.dayMode) { %>nav-white-tabs<% } %>" id="change-echarts">
                                                 <li class="nav-item">
@@ -1341,14 +1354,14 @@
         };
     })
 </script>
-<% if (hadMap || ctx.session.sessionUser.is_admin) { %>
+<% if (hadMap === 1 || ctx.session.sessionUser.is_admin) { %>
     <script src="/public/js/map/turf.min.js"></script>
     <script src="/public/js/map/gcoord.js"></script>
     <script>
         const tenderMapList = JSON.parse(unescape('<%- escape(JSON.stringify(tenderMapList)) %>'));
     </script>
 <% } %>
-<% if (hadMap) { %>
+<% if (hadMap === 1) { %>
     <!--<script src="//bj.bcebos.com/v1/mapopen/api-demos/js/mapStyle.js"></script>-->
     <script type="text/javascript" src="https://api.map.baidu.com/api?v=1.0&type=webgl&ak=C3hLZAjuWTaCdwnwoYY83APrwlPEj4v7"></script>
     <script type="text/javascript">

+ 163 - 42
app/view/tender/detail_modal.ejs

@@ -1806,6 +1806,12 @@
                 </div>
                 <div class="form-group">
                     <div class="custom-control custom-checkbox mb-2">
+                        <input type="checkbox" class="custom-control-input" id="sc_minusNoValue" checked="">
+                        <label class="custom-control-label" for="sc_minusNoValue">计量台账-负变更-计量不计价</label>
+                    </div>
+                </div>
+                <div class="form-group">
+                    <div class="custom-control custom-checkbox mb-2">
                         <input type="checkbox" class="custom-control-input" id="sr_show" checked="">
                         <label class="custom-control-label" for="sr_show">关联台账</label>
                     </div>
@@ -1856,6 +1862,7 @@
 
     const loadFunRelaProperty = function () {
         $('#sl_ignoreParent')[0].checked = property.fun_rela.sum_load.ignoreParent;
+        $('#sc_minusNoValue')[0].checked = property.fun_rela.stage_change.minusNoValue;
         $('#sr_show')[0].checked = property.fun_rela.stage_rela.show;
         $('#hint_over')[0].checked = property.fun_rela.hintOver;
     };
@@ -1870,6 +1877,9 @@
                 sum_load: {
                     ignoreParent: $('#sl_ignoreParent')[0].checked,
                 },
+                stage_change: {
+                    minusNoValue: $('#sc_minusNoValue')[0].checked,
+                },
                 stage_rela: {
                     show: $('#sr_show')[0].checked,
                 }
@@ -2039,49 +2049,97 @@
 </script>
 <!--概况设置-->
 <div class="modal fade" id="bd-set-11" data-backdrop="static">
-    <div class="modal-dialog" role="document">
+    <div class="modal-dialog modal-lg" role="document">
         <div class="modal-content">
             <div class="modal-header">
                 <h5 class="modal-title">概况设置</h5>
             </div>
-            <div class="modal-body">
-                <div class="row">
-                    <div class="col-6">
-                        <div class="card <% if (!hadMap) { %>border-dark<% } %>">
-                            <div class="card-body">
-                                <h5 class="card-title"><i class="fa fa-bookmark"></i> 无地图版</h5>
-                                <p class="card-text">概况中间展示图表</p>
-                                <% if (hadMap) { %>
-                                <a href="javascript:void(0);" data-value="1" class="btn select-map btn-primary btn-sm">选择</a>
-                                <% } else { %>
-                                <a href="javascript:void(0);" data-value="1" class="btn btn-primary btn-sm disabled">当前</a>
-                                <% } %>
+            <div class="modal-body modal-height-400">
+                <div class="container-fluid">
+                    <div class="d-flex justify-content-between">
+                        <div class="map-set">
+                            <div class="card card-gk-width p-3 select-map <% if (hadMap === 3) { %>card-gk-active<% } %>" data-value="3">
+                                <div class="card-body p-0">
+                                    <h5 class="card-title card-gk-title">
+                                        <div class="d-flex justify-content-between align-items-center">
+                                            <div>图表版</div>
+                                            <div class="sel-width <% if (hadMap === 3) { %>sel-blue<% } else { %>sel-gary<% } %>"></div>
+                                        </div>
+                                    </h5>
+                                    <div class="card-text">
+                                        <div class="my-4"><img src="/public/images/tubiaoban.png"></div>
+                                    </div>
+                                </div>
                             </div>
                         </div>
-                    </div>
-                    <div class="col-6">
-                        <div class="card <% if (hadMap) { %>border-dark<% } %>">
-                            <div class="card-body">
-                                <h5 class="card-title"><i class="fa fa-bookmark"></i> 地图版</h5>
-                                <p class="card-text">概况中间展示地图</p>
-                                <% if (!hadMap) { %>
-                                    <a href="javascript:void(0);" data-value="0" class="btn select-map btn-primary btn-sm">选择</a>
-                                <% } else { %>
-                                    <a href="javascript:void(0);" data-value="0" class="btn btn-primary btn-sm disabled">当前</a>
-                                <% } %>
-                                <a href="#bd-set-11-1" data-toggle="modal" data-target="#bd-set-11-1" data-dismiss="modal">编辑地图</a>
+                        <div class="map-set">
+                            <div class="card card-gk-width p-3 select-map <% if (hadMap === 1 || hadMap === 2) { %>card-gk-active<% } %>" data-value="<%- hadMap === 3 ? 1 : hadMap %>">
+                                <div class="card-body p-0">
+                                    <h5 class="card-title card-gk-title">
+                                        <div class="d-flex justify-content-between align-items-center">
+                                            <div>地图版</div>
+                                            <div class="sel-width <% if (hadMap === 1 || hadMap === 2) { %>sel-blue<% } else { %>sel-gary<% } %>"></div>
+                                        </div>
+                                    </h5>
+                                    <div class="card-text">
+                                        <div class="my-4"><img src="<% if (hadMap === 1 || hadMap === 3) { %>/public/images/dongtai.png<% } else { %>/public/images/jingtai.png<% } %>"></div>
+                                    </div>
+                                </div>
+                                <div class="card-gk-bottom">
+                                    <div class="d-flex justify-content-between align-items-center">
+                                        <div class="btn-group btn-group-sm" role="group" aria-label="Basic example">
+                                            <button type="button" data-value="1" class="btn change-map btn-secondary">动态坐标</button>
+                                            <button type="button" data-value="2" class="btn change-map btn-outline-primary">静态图片</button>
+                                        </div>
+                                        <div>
+                                            <a href="#bd-set-11-1" class="show-map-edit" data-toggle="modal" data-target="#bd-set-11-1" data-dismiss="modal">编辑坐标</a>
+                                            <a href="#bd-set-11-5" class="show-map-edit" data-toggle="modal" data-target="#bd-set-11-5" data-dismiss="modal" style="display:none;">上传图片</a>
+                                        </div>
+                                    </div>
+                                </div>
                             </div>
                         </div>
                     </div>
                 </div>
             </div>
             <div class="modal-footer">
+                <input type="hidden" id="map-value" value="<%- hadMap %>">
                 <button type="button" class="btn btn-sm btn-secondary" data-dismiss="modal">取消</button>
                 <button type="button" class="btn btn-sm btn-primary" id="save-select-map" >确认修改</button>
             </div>
         </div>
     </div>
 </div>
+<!--上传图片-->
+<div class="modal fade" id="bd-set-11-5" data-backdrop="static">
+    <div class="modal-dialog modal-lg" role="document">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h5 class="modal-title">上传静态图片</h5>
+            </div>
+            <div class="modal-body">
+                <p><input value="选择图片" type="file" id="upload-map-pic" /></p>
+                <p>预览</p>
+                <div id="show-map-pic" style="border: 1px solid rgba(0,0,0,.125);height: 388px; width: 100%;">
+                    <% if (map_pic) { %>
+                        <img style="display:block;width:100%;height: 387px;margin:0 auto;" src="<%- fujianOssPath + map_pic %>">
+                    <% } else { %>
+                        <div class="p-5 text-center text-muted">
+                            <img src="/public/images/nulllogo.png" />
+                            <div class="pt-3">暂无静态图片</div>
+                        </div>
+                    <% } %>
+                </div>
+            </div>
+            <div class="modal-footer">
+                <a href="#bd-set-11" class="btn btn-sm btn-secondary show-map-edit" data-toggle="modal" data-target="#bd-set-11" onclick="back=true" data-dismiss="modal">关闭</a>
+                <% if (hadMap === 2) { %>
+                    <button type="button" class="btn btn-sm btn-success" onclick="window.location.reload()" >刷新显示</button>
+                <% } %>
+            </div>
+        </div>
+    </div>
+</div>
 <!--地图路线-->
 <div class="modal fade" id="bd-set-11-1" data-backdrop="static">
     <div class="modal-dialog" role="document">
@@ -2104,7 +2162,7 @@
             </div>
             <div class="modal-footer">
                 <button type="button" class="btn btn-sm btn-secondary" data-dismiss="modal">关闭</button>
-                <% if (hadMap) { %>
+                <% if (hadMap === 1) { %>
                 <button type="button" class="btn btn-sm btn-success" onclick="window.location.reload()" >刷新显示</button>
                 <% } %>
             </div>
@@ -2174,32 +2232,95 @@
 
 <script>
     const hadMap = parseInt(<%- hadMap %>);
+    const fujianOssPath = JSON.parse(unescape('<%- escape(JSON.stringify(fujianOssPath)) %>'));
+    let back = false;
     $(function () {
-        $('#bd-set-11').on('show.bs.modal', function () {
-            if (parseInt(hadMap) == 0) {
-                $('#bd-set-11').find('.card').eq(0).addClass('border-dark');
-                $('#bd-set-11').find('.card').eq(0).find('.btn').removeClass('select-map').addClass('disabled').text('当前');
-                $('#bd-set-11').find('.card').eq(1).removeClass('border-dark');
-                $('#bd-set-11').find('.card').eq(1).find('.btn').removeClass('disabled').addClass('select-map').text('选择');
+        $('#bd-set-11').on('shown.bs.modal', function () {
+            if (!back) {
+                if (hadMap === 1 || hadMap === 2) {
+                    $('#bd-set-11').find('.card').eq(1).addClass('card-gk-active');
+                    $('#bd-set-11').find('.card').eq(1).find('.sel-width').removeClass('sel-gary').addClass('sel-blue');
+                    $('#bd-set-11').find('.card').eq(0).removeClass('card-gk-active');
+                    $('#bd-set-11').find('.card').eq(0).find('.sel-width').removeClass('sel-blue').addClass('sel-gary');
+                    $('#bd-set-11').find('.card').eq(1).attr('data-value', hadMap);
+                    if (hadMap === 1) {
+                        $('.change-map').eq(0).removeClass('btn-outline-primary').addClass('btn-secondary');
+                        $('.change-map').eq(1).removeClass('btn-secondary').addClass('btn-outline-primary');
+                        $('.show-map-edit').eq(0).show();
+                        $('.show-map-edit').eq(1).hide();
+                        $('#bd-set-11').find('.card').eq(1).find('img').attr('src', '/public/images/dongtai.png');
+                    } else {
+                        $('.change-map').eq(1).removeClass('btn-outline-primary').addClass('btn-secondary');
+                        $('.change-map').eq(0).removeClass('btn-secondary').addClass('btn-outline-primary');
+                        $('.show-map-edit').eq(1).show();
+                        $('.show-map-edit').eq(0).hide();
+                        $('#bd-set-11').find('.card').eq(1).find('img').attr('src', '/public/images/jingtai.png');
+                    }
+                } else if (hadMap === 3) {
+                    $('#bd-set-11').find('.card').eq(0).addClass('card-gk-active');
+                    $('#bd-set-11').find('.card').eq(0).find('.sel-width').removeClass('sel-gary').addClass('sel-blue');
+                    $('#bd-set-11').find('.card').eq(1).removeClass('card-gk-active');
+                    $('#bd-set-11').find('.card').eq(1).find('.sel-width').removeClass('sel-blue').addClass('sel-gary');
+                }
+                $('#map-value').val(hadMap);
             } else {
-                $('#bd-set-11').find('.card').eq(1).addClass('border-dark');
-                $('#bd-set-11').find('.card').eq(1).find('.btn').removeClass('select-map').addClass('disabled').text('当前');
-                $('#bd-set-11').find('.card').eq(0).removeClass('border-dark');
-                $('#bd-set-11').find('.card').eq(0).find('.btn').removeClass('disabled').addClass('select-map').text('选择');
+                back = false;
             }
         })
         $('body').on('click', '#bd-set-11 .select-map', function () {
             // const val = parseInt($(this).data('value'));
-            $(this).parents('.card').addClass('border-dark');
-            $(this).removeClass('select-map').addClass('disabled').text('当前');
-            $(this).parents('.col-6').siblings('.col-6').children('.card').removeClass('border-dark');
-            $(this).parents('.col-6').siblings('.col-6').find('.btn').removeClass('disabled').addClass('select-map').text('选择');
+            $(this).addClass('card-gk-active');
+            $(this).find('.sel-width').removeClass('sel-gary').addClass('sel-blue');
+            $(this).parents('.map-set').siblings('.map-set').children('.card').removeClass('card-gk-active');
+            $(this).parents('.map-set').siblings('.map-set').find('.sel-width').removeClass('sel-blue').addClass('sel-gary');
+            $('#map-value').val($(this).attr('data-value'));
+        });
+        // 切换坐标和图片选择
+        $('.change-map').on('click', function (e) {
+            e.preventDefault();
+            event.stopPropagation();
+            if ($(this).hasClass('btn-outline-primary')) {
+                $(this).addClass('btn-secondary').removeClass('btn-outline-primary');
+                $(this).siblings('button').removeClass('btn-secondary').addClass('btn-outline-primary');
+                const value = $(this).attr('data-value');
+                $(this).parents('.card').attr('data-value', value);
+                $('#map-value').val(value);
+                if (parseInt(value) === 2) {
+                    $(this).parents('.card').find('img').attr('src', '/public/images/jingtai.png');
+                    $('.show-map-edit').eq(0).hide();
+                    $('.show-map-edit').eq(1).show();
+                } else {
+                    $(this).parents('.card').find('img').attr('src', '/public/images/dongtai.png');
+                    $('.show-map-edit').eq(1).hide();
+                    $('.show-map-edit').eq(0).show();
+                }
+            }
         });
 
+        $('#upload-map-pic').change(function () {
+            const file = this.files[0];
+            const ext = file.name.toLowerCase().split('.').splice(-1)[0];
+            const imgStr = /(jpg|jpeg|png|bmp|BMP|JPG|PNG|JPEG)$/;
+            if (!imgStr.test(ext)) {
+                toastr.error('请上传正确的图片格式文件');
+                $('#upload-map-pic').val('');
+                return
+            }
+            if ($(this).val()) {
+                const formData = new FormData();
+                formData.append('file', this.files[0]);
+                postDataWithFile('/tender/' + tenderId + '/map/upload', formData, function (result) {
+                    const html = '<img style="display:block;width:100%;height: 387px;margin:0 auto;" src="'+ fujianOssPath + result.map_pic +'">';
+                    $('#show-map-pic').html(html);
+                    $('#upload-map-pic').val('');
+                });
+            }
+        })
+
         $('#save-select-map').click(function () {
             $(this).attr('disabled', true);
-            const val = parseInt($('#bd-set-11').find('.disabled').data('value'));
-            if (hadMap === val) {
+            const val = parseInt($('#map-value').val());
+            if (hadMap !== val) {
                 postData('/tender/' + tenderId + '/map/save', { type: 'select-map', value: val }, function () {
                     toastr.success('修改成功,重新加载中...');
                     setTimeout(function () {

+ 197 - 195
builder_report_index_define.js

@@ -19,10 +19,6 @@ const dataType = {
     time: 'string',
     arr: 'array',
 };
-const tag = {
-    tp: { type: 'tp' },
-    up: { type: 'up' },
-};
 
 // 预付款
 const advance_pay = {
@@ -115,7 +111,7 @@ const stage_bonus = {
         { name: '所属第几期', field: 'sorder', type: dataType.int },
         { name: '新增人id', field: 'uid', type: dataType.int },
         { name: '名称', field: 'name', type: dataType.str },
-        { name: '金额', field: 'tp', type: dataType.currency, tag: { type: 'tp' } },
+        { name: '金额', field: 'tp', type: dataType.currency },
         { name: '证明材料', field: 'proof', type: dataType.str },
         { name: '创建时间', field: 'create_time', type: dataType.time },
         { name: '时间', field: 'real_time', type: dataType.time },
@@ -244,18 +240,18 @@ const change = {
         { name: '变更性质', field: 'quality', type: dataType.int },
         { name: '变更提出单位', field: 'company', type: dataType.str },
         { name: '费用承担方', field: 'charge', type: dataType.int },
-        { name: '金额', field: 'total_price', type: dataType.currency, tag: { type: 'tp' } },
+        { name: '金额', field: 'total_price', type: dataType.currency },
         { name: '变更状态发生时间(时间戳)', field: 'cin_time', type: dataType.str },
         { name: '完成审批时间(时间戳)', field: 'sin_time', type: dataType.str },
-        { name: '金额_1', field: 'tp_1', type: dataType.currency, tag: { type: 'tp' } },
-        { name: '金额_2', field: 'tp_2', type: dataType.currency, tag: { type: 'tp' } },
-        { name: '金额_3', field: 'tp_3', type: dataType.currency, tag: { type: 'tp' } },
-        { name: '金额_4', field: 'tp_4', type: dataType.currency, tag: { type: 'tp' } },
-        { name: '金额_5', field: 'tp_5', type: dataType.currency, tag: { type: 'tp' } },
-        { name: '金额_6', field: 'tp_6', type: dataType.currency, tag: { type: 'tp' } },
-        { name: '金额_7', field: 'tp_7', type: dataType.currency, tag: { type: 'tp' } },
-        { name: '金额_8', field: 'tp_8', type: dataType.currency, tag: { type: 'tp' } },
-        { name: '金额_9', field: 'tp_9', type: dataType.currency, tag: { type: 'tp' } },
+        { name: '金额_1', field: 'tp_1', type: dataType.currency },
+        { name: '金额_2', field: 'tp_2', type: dataType.currency },
+        { name: '金额_3', field: 'tp_3', type: dataType.currency },
+        { name: '金额_4', field: 'tp_4', type: dataType.currency },
+        { name: '金额_5', field: 'tp_5', type: dataType.currency },
+        { name: '金额_6', field: 'tp_6', type: dataType.currency },
+        { name: '金额_7', field: 'tp_7', type: dataType.currency },
+        { name: '金额_8', field: 'tp_8', type: dataType.currency },
+        { name: '金额_9', field: 'tp_9', type: dataType.currency },
         { name: '附件名称列表', field: 'attNames', type: dataType.currency },
         { name: '报表用,是否选择', field: 'selected', type: dataType.int },
     ],
@@ -272,33 +268,33 @@ const change_bills = {
         { name: '清单编号', field: 'code', type: dataType.str },
         { name: '名称', field: 'name', type: dataType.str },
         { name: '单位', field: 'unit', type: dataType.str },
-        { name: '单价', field: 'unit_price', type: dataType.currency, tag: { type: 'up' } },
-        { name: '原-数量', field: 'o_qty', type: dataType.currency, tag: { type: 'qty', unitKey: 5 } },
-        { name: '原-金额', field: 'o_tp', type: dataType.currency, tag: { type: 'tp' } },
-        { name: '变更-数量', field: 'c_qty', type: dataType.currency, tag: { type: 'qty', unitKey: 5 } },
-        { name: '变更-金额', field: 'c_tp', type: dataType.currency, tag: { type: 'tp' } },
-        { name: '审批变更后-数量', field: 's_qty', type: dataType.currency, tag: { type: 'qty', unitKey: 5 } },
-        { name: '审批变更后-金额', field: 's_tp', type: dataType.currency, tag: { type: 'tp' } },
+        { name: '单价', field: 'unit_price', type: dataType.currency },
+        { name: '原-数量', field: 'o_qty', type: dataType.currency },
+        { name: '原-金额', field: 'o_tp', type: dataType.currency },
+        { name: '变更-数量', field: 'c_qty', type: dataType.currency },
+        { name: '变更-金额', field: 'c_tp', type: dataType.currency },
+        { name: '审批变更后-数量', field: 's_qty', type: dataType.currency },
+        { name: '审批变更后-金额', field: 's_tp', type: dataType.currency },
         { name: '部位明细', field: 'bwmx', type: dataType.str },
         { name: '变更详情', field: 'detail', type: dataType.str },
-        { name: '数量_1', field: 'qty_1', type: dataType.currency, tag: { type: 'qty', unitKey: 5 } },
-        { name: '金额_1', field: 'tp_1', type: dataType.currency, tag: { type: 'tp' } },
-        { name: '数量_2', field: 'qty_2', type: dataType.currency, tag: { type: 'qty', unitKey: 5 } },
-        { name: '金额_2', field: 'tp_2', type: dataType.currency, tag: { type: 'tp' } },
-        { name: '数量_3', field: 'qty_3', type: dataType.currency, tag: { type: 'qty', unitKey: 5 } },
-        { name: '金额_3', field: 'tp_3', type: dataType.currency, tag: { type: 'tp' } },
-        { name: '数量_4', field: 'qty_4', type: dataType.currency, tag: { type: 'qty', unitKey: 5 } },
-        { name: '金额_4', field: 'tp_4', type: dataType.currency, tag: { type: 'tp' } },
-        { name: '数量_5', field: 'qty_5', type: dataType.currency, tag: { type: 'qty', unitKey: 5 } },
-        { name: '金额_5', field: 'tp_5', type: dataType.currency, tag: { type: 'tp' } },
-        { name: '数量_6', field: 'qty_6', type: dataType.currency, tag: { type: 'qty', unitKey: 5 } },
-        { name: '金额_6', field: 'tp_6', type: dataType.currency, tag: { type: 'tp' } },
-        { name: '数量_7', field: 'qty_7', type: dataType.currency, tag: { type: 'qty', unitKey: 5 } },
-        { name: '金额_7', field: 'tp_7', type: dataType.currency, tag: { type: 'tp' } },
-        { name: '数量_8', field: 'qty_8', type: dataType.currency, tag: { type: 'qty', unitKey: 5 } },
-        { name: '金额_8', field: 'tp_8', type: dataType.currency, tag: { type: 'tp' } },
-        { name: '数量_9', field: 'qty_9', type: dataType.currency, tag: { type: 'qty', unitKey: 5 } },
-        { name: '金额_9', field: 'tp_9', type: dataType.currency, tag: { type: 'tp' } },
+        { name: '数量_1', field: 'qty_1', type: dataType.currency },
+        { name: '金额_1', field: 'tp_1', type: dataType.currency },
+        { name: '数量_2', field: 'qty_2', type: dataType.currency },
+        { name: '金额_2', field: 'tp_2', type: dataType.currency },
+        { name: '数量_3', field: 'qty_3', type: dataType.currency },
+        { name: '金额_3', field: 'tp_3', type: dataType.currency },
+        { name: '数量_4', field: 'qty_4', type: dataType.currency },
+        { name: '金额_4', field: 'tp_4', type: dataType.currency },
+        { name: '数量_5', field: 'qty_5', type: dataType.currency },
+        { name: '金额_5', field: 'tp_5', type: dataType.currency },
+        { name: '数量_6', field: 'qty_6', type: dataType.currency },
+        { name: '金额_6', field: 'tp_6', type: dataType.currency },
+        { name: '数量_7', field: 'qty_7', type: dataType.currency },
+        { name: '金额_7', field: 'tp_7', type: dataType.currency },
+        { name: '数量_8', field: 'qty_8', type: dataType.currency },
+        { name: '金额_8', field: 'tp_8', type: dataType.currency },
+        { name: '数量_9', field: 'qty_9', type: dataType.currency },
+        { name: '金额_9', field: 'tp_9', type: dataType.currency },
         { name: '项目节编号', field: 'xmj_code', type: dataType.str },
         { name: '细目', field: 'xmj_jldy', type: dataType.str },
         { name: '单位工程', field: 'xmj_dwgc', type: dataType.str },
@@ -633,19 +629,19 @@ const stage_bills = {
         { name: '清单编号', field: 'b_code', type: dataType.str },
         { name: '名称', field: 'name', type: dataType.str },
         { name: '单位', field: 'unit', type: dataType.str }, // 12
-        { name: '单价', field: 'unit_price', type: dataType.currency, tag: { type: 'up' } },
+        { name: '单价', field: 'unit_price', type: dataType.currency },
 
-        { name: '签约-数量', field: 'deal_qty', type: dataType.currency, tag: { type: 'qty', unitKey: 12 } },
-        { name: '签约-金额', field: 'deal_tp', type: dataType.currency, tag: { type: 'tp' } },
+        { name: '签约-数量', field: 'deal_qty', type: dataType.currency },
+        { name: '签约-金额', field: 'deal_tp', type: dataType.currency },
 
-        { name: '施工复核-数量', field: 'sgfh_qty', type: dataType.currency, tag: { type: 'qty', unitKey: 12 } },
-        { name: '施工复核-金额', field: 'sgfh_tp', type: dataType.currency, tag: { type: 'tp' } },
-        { name: '设计错漏-数量', field: 'sjcl_qty', type: dataType.currency, tag: { type: 'qty', unitKey: 12 } },
-        { name: '设计错漏-金额', field: 'sjcl_tp', type: dataType.currency, tag: { type: 'tp' } },
-        { name: '其他错漏-数量', field: 'qtcl_qty', type: dataType.currency, tag: { type: 'qty', unitKey: 12 } },
-        { name: '其他错漏-金额', field: 'qtcl_tp', type: dataType.currency, tag: { type: 'tp' } },
-        { name: '台账-数量', field: 'quantity', type: dataType.currency, tag: { type: 'qty', unitKey: 12 } },
-        { name: '台账-金额', field: 'total_price', type: dataType.currency, tag: { type: 'tp' } },
+        { name: '施工复核-数量', field: 'sgfh_qty', type: dataType.currency },
+        { name: '施工复核-金额', field: 'sgfh_tp', type: dataType.currency },
+        { name: '设计错漏-数量', field: 'sjcl_qty', type: dataType.currency },
+        { name: '设计错漏-金额', field: 'sjcl_tp', type: dataType.currency },
+        { name: '其他错漏-数量', field: 'qtcl_qty', type: dataType.currency },
+        { name: '其他错漏-金额', field: 'qtcl_tp', type: dataType.currency },
+        { name: '台账-数量', field: 'quantity', type: dataType.currency },
+        { name: '台账-金额', field: 'total_price', type: dataType.currency },
 
         { name: '项目节-数量1', field: 'dgn_qty1', type: dataType.currency },
         { name: '项目节-数量2', field: 'dgn_qty2', type: dataType.currency },
@@ -655,29 +651,29 @@ const stage_bills = {
         { name: '节点类型', field: 'node_type', type: dataType.int },
         { name: '总额计量', field: 'is_tp', type: dataType.int },
 
-        { name: '本期-合同-数量', field: 'contract_qty', type: dataType.currency, tag: { type: 'qty', unitKey: 12 } },
-        { name: '本期-合同-金额', field: 'contract_tp', type: dataType.currency, tag: { type: 'tp' } },
-        { name: '本期-数量变更-数量', field: 'qc_qty', type: dataType.currency, tag: { type: 'qty', unitKey: 12 } },
-        { name: '本期-数量变更-金额', field: 'qc_tp', type: dataType.currency, tag: { type: 'tp' } },
-        { name: '本期-完成-数量', field: 'gather_qty', type: dataType.currency, tag: { type: 'qty', unitKey: 12 } },
-        { name: '本期-完成-金额', field: 'gather_tp', type: dataType.currency, tag: { type: 'tp' } },
+        { name: '本期-合同-数量', field: 'contract_qty', type: dataType.currency },
+        { name: '本期-合同-金额', field: 'contract_tp', type: dataType.currency },
+        { name: '本期-数量变更-数量', field: 'qc_qty', type: dataType.currency },
+        { name: '本期-数量变更-金额', field: 'qc_tp', type: dataType.currency },
+        { name: '本期-完成-数量', field: 'gather_qty', type: dataType.currency },
+        { name: '本期-完成-金额', field: 'gather_tp', type: dataType.currency },
         { name: '本期批注', field: 'postil', type: dataType.str },
 
-        { name: '截止上期-合同-数量', field: 'pre_contract_qty', type: dataType.currency, tag: { type: 'qty', unitKey: 12 } },
-        { name: '截止上期-合同-金额', field: 'pre_contract_tp', type: dataType.currency, tag: { type: 'tp' } },
-        { name: '截止上期-数量变更-数量', field: 'pre_qc_qty', type: dataType.currency, tag: { type: 'qty', unitKey: 12 } },
-        { name: '截止上期-数量变更-金额', field: 'pre_qc_tp', type: dataType.currency, tag: { type: 'tp' } },
-        { name: '截止上期-完成-数量', field: 'pre_gather_qty', type: dataType.currency, tag: { type: 'qty', unitKey: 12 } },
-        { name: '截止上期-完成-金额', field: 'pre_gather_tp', type: dataType.currency, tag: { type: 'tp' } },
-
-        { name: '截止本期-合同-数量', field: 'end_contract_qty', type: dataType.currency, tag: { type: 'qty', unitKey: 12 } },
-        { name: '截止本期-合同-金额', field: 'end_contract_tp', type: dataType.currency, tag: { type: 'tp' } },
-        { name: '截止本期-数量变更-数量', field: 'end_qc_qty', type: dataType.currency, tag: { type: 'qty', unitKey: 12 } },
-        { name: '截止本期-数量变更-金额', field: 'end_qc_tp', type: dataType.currency, tag: { type: 'tp' } },
-        { name: '截止本期-完成-数量', field: 'end_gather_qty', type: dataType.currency, tag: { type: 'qty', unitKey: 12 } },
-        { name: '截止本期-完成-金额', field: 'end_gather_tp', type: dataType.currency, tag: { type: 'tp' } },
-
-        { name: '(台账 + 截止本期变更)-金额', field: 'final_tp', type: dataType.currency, tag: { type: 'tp' } },
+        { name: '截止上期-合同-数量', field: 'pre_contract_qty', type: dataType.currency },
+        { name: '截止上期-合同-金额', field: 'pre_contract_tp', type: dataType.currency },
+        { name: '截止上期-数量变更-数量', field: 'pre_qc_qty', type: dataType.currency },
+        { name: '截止上期-数量变更-金额', field: 'pre_qc_tp', type: dataType.currency },
+        { name: '截止上期-完成-数量', field: 'pre_gather_qty', type: dataType.currency },
+        { name: '截止上期-完成-金额', field: 'pre_gather_tp', type: dataType.currency },
+
+        { name: '截止本期-合同-数量', field: 'end_contract_qty', type: dataType.currency },
+        { name: '截止本期-合同-金额', field: 'end_contract_tp', type: dataType.currency },
+        { name: '截止本期-数量变更-数量', field: 'end_qc_qty', type: dataType.currency },
+        { name: '截止本期-数量变更-金额', field: 'end_qc_tp', type: dataType.currency },
+        { name: '截止本期-完成-数量', field: 'end_gather_qty', type: dataType.currency },
+        { name: '截止本期-完成-金额', field: 'end_gather_tp', type: dataType.currency },
+
+        { name: '(台账 + 截止本期变更)-金额', field: 'final_tp', type: dataType.currency },
         { name: '截止本期完成率(%)', field: 'final_ratio', type: dataType.double },
 
         { name: '本期-数量变更-变更令', field: 'qc_bgl_code', type: dataType.str },
@@ -710,9 +706,9 @@ const stage_bills = {
         { name: '备注2', field: 'ex_memo2', type: dataType.str },
         { name: '备注3', field: 'ex_memo3', type: dataType.str },
 
-        { name: '本期负变更', field: 'minus_qc_qty', type: dataType.double },
-        { name: '截止上期负变更', field: 'pre_minus_qc_qty', type: dataType.double },
-        { name: '截止本期负变更', field: 'pre_minus_qc_qty', type: dataType.double },
+        { name: '本期负变更', field: 'qc_minus_qty', type: dataType.double },
+        { name: '截止上期负变更', field: 'pre_qc_minus_qty', type: dataType.double },
+        { name: '截止本期负变更', field: 'end_qc_minus_qty', type: dataType.double },
         { name: '1#台账(台账+截止本期负变更)-数量', field: 'final_1_qty', type: dataType.double },
         { name: '1#台账(台账+截止本期负变更)-金额', field: 'final_1_tp', type: dataType.double },
         { name: '1#台账+截止本期变更-数量', field: 'end_final_1_qty', type: dataType.double },
@@ -740,19 +736,19 @@ const stage_bills_compare = {
         { name: '清单编号', field: 'b_code', type: dataType.str },
         { name: '名称', field: 'name', type: dataType.str },
         { name: '单位', field: 'unit', type: dataType.str }, // 12
-        { name: '单价', field: 'unit_price', type: dataType.currency, tag: { type: 'up' } },
+        { name: '单价', field: 'unit_price', type: dataType.currency },
 
-        { name: '签约-数量', field: 'deal_qty', type: dataType.currency, tag: { type: 'qty', unitKey: 12 } },
-        { name: '签约-金额', field: 'deal_tp', type: dataType.currency, tag: { type: 'tp' } },
+        { name: '签约-数量', field: 'deal_qty', type: dataType.currency },
+        { name: '签约-金额', field: 'deal_tp', type: dataType.currency },
 
-        { name: '施工复核-数量', field: 'sgfh_qty', type: dataType.currency, tag: { type: 'qty', unitKey: 12 } },
-        { name: '施工复核-金额', field: 'sgfh_tp', type: dataType.currency, tag: { type: 'tp' } },
-        { name: '设计错漏-数量', field: 'sjcl_qty', type: dataType.currency, tag: { type: 'qty', unitKey: 12 } },
-        { name: '设计错漏-金额', field: 'sjcl_tp', type: dataType.currency, tag: { type: 'tp' } },
-        { name: '其他错漏-数量', field: 'qtcl_qty', type: dataType.currency, tag: { type: 'qty', unitKey: 12 } },
-        { name: '其他错漏-金额', field: 'qtcl_tp', type: dataType.currency, tag: { type: 'tp' } },
-        { name: '台账-数量', field: 'quantity', type: dataType.currency, tag: { type: 'qty', unitKey: 12 } },
-        { name: '台账-金额', field: 'total_price', type: dataType.currency, tag: { type: 'tp' } },
+        { name: '施工复核-数量', field: 'sgfh_qty', type: dataType.currency },
+        { name: '施工复核-金额', field: 'sgfh_tp', type: dataType.currency },
+        { name: '设计错漏-数量', field: 'sjcl_qty', type: dataType.currency },
+        { name: '设计错漏-金额', field: 'sjcl_tp', type: dataType.currency },
+        { name: '其他错漏-数量', field: 'qtcl_qty', type: dataType.currency },
+        { name: '其他错漏-金额', field: 'qtcl_tp', type: dataType.currency },
+        { name: '台账-数量', field: 'quantity', type: dataType.currency },
+        { name: '台账-金额', field: 'total_price', type: dataType.currency },
 
         { name: '项目节-数量1', field: 'dgn_qty1', type: dataType.currency },
         { name: '项目节-数量2', field: 'dgn_qty2', type: dataType.currency },
@@ -762,82 +758,82 @@ const stage_bills_compare = {
         { name: '节点类型', field: 'node_type', type: dataType.int },
         { name: '总额计量', field: 'is_tp', type: dataType.int },
 
-        { name: '截止上期-合同-数量', field: 'pre_contract_qty', type: dataType.currency, tag: { type: 'qty', unitKey: 12 } },
-        { name: '截止上期-合同-金额', field: 'pre_contract_tp', type: dataType.currency, tag: { type: 'tp' } },
-        { name: '截止上期-数量变更-数量', field: 'pre_qc_qty', type: dataType.currency, tag: { type: 'qty', unitKey: 12 } },
-        { name: '截止上期-数量变更-金额', field: 'pre_qc_tp', type: dataType.currency, tag: { type: 'tp' } },
-        { name: '截止上期-完成-数量', field: 'pre_gather_qty', type: dataType.currency, tag: { type: 'qty', unitKey: 12 } },
-        { name: '截止上期-完成-金额', field: 'pre_gather_tp', type: dataType.currency, tag: { type: 'tp' } },
-
-        { name: '本期-合同-数量_0', field: 'r0_contract_qty', type: dataType.currency, tag: { type: 'qty', unitKey: 12 } },
-        { name: '本期-合同-金额_0', field: 'r0_contract_tp', type: dataType.currency, tag: { type: 'tp' } },
-        { name: '本期-数量变更-数量_0', field: 'r0_qc_qty', type: dataType.currency, tag: { type: 'qty', unitKey: 12 } },
-        { name: '本期-数量变更-金额_0', field: 'r0_qc_tp', type: dataType.currency, tag: { type: 'tp' } },
-        { name: '本期-完成-数量_0', field: 'r0_gather_qty', type: dataType.currency, tag: { type: 'qty', unitKey: 12 } },
-        { name: '本期-完成-金额_0', field: 'r0_gather_tp', type: dataType.currency, tag: { type: 'tp' } },
-
-        { name: '本期-合同-数量_1', field: 'r1_contract_qty', type: dataType.currency, tag: { type: 'qty', unitKey: 12 } },
-        { name: '本期-合同-金额_1', field: 'r1_contract_tp', type: dataType.currency, tag: { type: 'tp' } },
-        { name: '本期-数量变更-数量_1', field: 'r1_qc_qty', type: dataType.currency, tag: { type: 'qty', unitKey: 12 } },
-        { name: '本期-数量变更-金额_1', field: 'r1_qc_tp', type: dataType.currency, tag: { type: 'tp' } },
-        { name: '本期-完成-数量_1', field: 'r1_gather_qty', type: dataType.currency, tag: { type: 'qty', unitKey: 12 } },
-        { name: '本期-完成-金额_1', field: 'r1_gather_tp', type: dataType.currency, tag: { type: 'tp' } },
-
-        { name: '本期-合同-数量_2', field: 'r2_contract_qty', type: dataType.currency, tag: { type: 'qty', unitKey: 12 } },
-        { name: '本期-合同-金额_2', field: 'r2_contract_tp', type: dataType.currency, tag: { type: 'tp' } },
-        { name: '本期-数量变更-数量_2', field: 'r2_qc_qty', type: dataType.currency, tag: { type: 'qty', unitKey: 12 } },
-        { name: '本期-数量变更-金额_2', field: 'r2_qc_tp', type: dataType.currency, tag: { type: 'tp' } },
-        { name: '本期-完成-数量_2', field: 'r2_gather_qty', type: dataType.currency, tag: { type: 'qty', unitKey: 12 } },
-        { name: '本期-完成-金额_2', field: 'r2_gather_tp', type: dataType.currency, tag: { type: 'tp' } },
-
-        { name: '本期-合同-数量_3', field: 'r3_contract_qty', type: dataType.currency, tag: { type: 'qty', unitKey: 12 } },
-        { name: '本期-合同-金额_3', field: 'r3_contract_tp', type: dataType.currency, tag: { type: 'tp' } },
-        { name: '本期-数量变更-数量_3', field: 'r3_qc_qty', type: dataType.currency, tag: { type: 'qty', unitKey: 12 } },
-        { name: '本期-数量变更-金额_3', field: 'r3_qc_tp', type: dataType.currency, tag: { type: 'tp' } },
-        { name: '本期-完成-数量_3', field: 'r3_gather_qty', type: dataType.currency, tag: { type: 'qty', unitKey: 12 } },
-        { name: '本期-完成-金额_3', field: 'r3_gather_tp', type: dataType.currency, tag: { type: 'tp' } },
-
-        { name: '本期-合同-数量_4', field: 'r4_contract_qty', type: dataType.currency, tag: { type: 'qty', unitKey: 12 } },
-        { name: '本期-合同-金额_4', field: 'r4_contract_tp', type: dataType.currency, tag: { type: 'tp' } },
-        { name: '本期-数量变更-数量_4', field: 'r4_qc_qty', type: dataType.currency, tag: { type: 'qty', unitKey: 12 } },
-        { name: '本期-数量变更-金额_4', field: 'r4_qc_tp', type: dataType.currency, tag: { type: 'tp' } },
-        { name: '本期-完成-数量_4', field: 'r4_gather_qty', type: dataType.currency, tag: { type: 'qty', unitKey: 12 } },
-        { name: '本期-完成-金额_4', field: 'r4_gather_tp', type: dataType.currency, tag: { type: 'tp' } },
-
-        { name: '本期-合同-数量_5', field: 'r5_contract_qty', type: dataType.currency, tag: { type: 'qty', unitKey: 12 } },
-        { name: '本期-合同-金额_5', field: 'r5_contract_tp', type: dataType.currency, tag: { type: 'tp' } },
-        { name: '本期-数量变更-数量_5', field: 'r5_qc_qty', type: dataType.currency, tag: { type: 'qty', unitKey: 12 } },
-        { name: '本期-数量变更-金额_5', field: 'r5_qc_tp', type: dataType.currency, tag: { type: 'tp' } },
-        { name: '本期-完成-数量_5', field: 'r5_gather_qty', type: dataType.currency, tag: { type: 'qty', unitKey: 12 } },
-        { name: '本期-完成-金额_5', field: 'r5_gather_tp', type: dataType.currency, tag: { type: 'tp' } },
-
-        { name: '本期-合同-数量_6', field: 'r6_contract_qty', type: dataType.currency, tag: { type: 'qty', unitKey: 12 } },
-        { name: '本期-合同-金额_6', field: 'r6_contract_tp', type: dataType.currency, tag: { type: 'tp' } },
-        { name: '本期-数量变更-数量_6', field: 'r6_qc_qty', type: dataType.currency, tag: { type: 'qty', unitKey: 12 } },
-        { name: '本期-数量变更-金额_6', field: 'r6_qc_tp', type: dataType.currency, tag: { type: 'tp' } },
-        { name: '本期-完成-数量_6', field: 'r6_gather_qty', type: dataType.currency, tag: { type: 'qty', unitKey: 12 } },
-        { name: '本期-完成-金额_6', field: 'r6_gather_tp', type: dataType.currency, tag: { type: 'tp' } },
-
-        { name: '本期-合同-数量_7', field: 'r7_contract_qty', type: dataType.currency, tag: { type: 'qty', unitKey: 12 } },
-        { name: '本期-合同-金额_7', field: 'r7_contract_tp', type: dataType.currency, tag: { type: 'tp' } },
-        { name: '本期-数量变更-数量_7', field: 'r7_qc_qty', type: dataType.currency, tag: { type: 'qty', unitKey: 12 } },
-        { name: '本期-数量变更-金额_7', field: 'r7_qc_tp', type: dataType.currency, tag: { type: 'tp' } },
-        { name: '本期-完成-数量_7', field: 'r7_gather_qty', type: dataType.currency, tag: { type: 'qty', unitKey: 12 } },
-        { name: '本期-完成-金额_7', field: 'r7_gather_tp', type: dataType.currency, tag: { type: 'tp' } },
-
-        { name: '本期-合同-数量_8', field: 'r8_contract_qty', type: dataType.currency, tag: { type: 'qty', unitKey: 12 } },
-        { name: '本期-合同-金额_8', field: 'r8_contract_tp', type: dataType.currency, tag: { type: 'tp' } },
-        { name: '本期-数量变更-数量_8', field: 'r8_qc_qty', type: dataType.currency, tag: { type: 'qty', unitKey: 12 } },
-        { name: '本期-数量变更-金额_8', field: 'r8_qc_tp', type: dataType.currency, tag: { type: 'tp' } },
-        { name: '本期-完成-数量_8', field: 'r8_gather_qty', type: dataType.currency, tag: { type: 'qty', unitKey: 12 } },
-        { name: '本期-完成-金额_8', field: 'r8_gather_tp', type: dataType.currency, tag: { type: 'tp' } },
-
-        { name: '本期-合同-数量_9', field: 'r9_contract_qty', type: dataType.currency, tag: { type: 'qty', unitKey: 12 } },
-        { name: '本期-合同-金额_9', field: 'r9_contract_tp', type: dataType.currency, tag: { type: 'tp' } },
-        { name: '本期-数量变更-数量_9', field: 'r9_qc_qty', type: dataType.currency, tag: { type: 'qty', unitKey: 12 } },
-        { name: '本期-数量变更-金额_9', field: 'r9_qc_tp', type: dataType.currency, tag: { type: 'tp' } },
-        { name: '本期-完成-数量_9', field: 'r9_gather_qty', type: dataType.currency, tag: { type: 'qty', unitKey: 12 } },
-        { name: '本期-完成-金额_9', field: 'r9_gather_tp', type: dataType.currency, tag: { type: 'tp' } },
+        { name: '截止上期-合同-数量', field: 'pre_contract_qty', type: dataType.currency },
+        { name: '截止上期-合同-金额', field: 'pre_contract_tp', type: dataType.currency },
+        { name: '截止上期-数量变更-数量', field: 'pre_qc_qty', type: dataType.currency },
+        { name: '截止上期-数量变更-金额', field: 'pre_qc_tp', type: dataType.currency },
+        { name: '截止上期-完成-数量', field: 'pre_gather_qty', type: dataType.currency },
+        { name: '截止上期-完成-金额', field: 'pre_gather_tp', type: dataType.currency },
+
+        { name: '本期-合同-数量_0', field: 'r0_contract_qty', type: dataType.currency },
+        { name: '本期-合同-金额_0', field: 'r0_contract_tp', type: dataType.currency },
+        { name: '本期-数量变更-数量_0', field: 'r0_qc_qty', type: dataType.currency },
+        { name: '本期-数量变更-金额_0', field: 'r0_qc_tp', type: dataType.currency },
+        { name: '本期-完成-数量_0', field: 'r0_gather_qty', type: dataType.currency },
+        { name: '本期-完成-金额_0', field: 'r0_gather_tp', type: dataType.currency },
+
+        { name: '本期-合同-数量_1', field: 'r1_contract_qty', type: dataType.currency },
+        { name: '本期-合同-金额_1', field: 'r1_contract_tp', type: dataType.currency },
+        { name: '本期-数量变更-数量_1', field: 'r1_qc_qty', type: dataType.currency },
+        { name: '本期-数量变更-金额_1', field: 'r1_qc_tp', type: dataType.currency },
+        { name: '本期-完成-数量_1', field: 'r1_gather_qty', type: dataType.currency },
+        { name: '本期-完成-金额_1', field: 'r1_gather_tp', type: dataType.currency },
+
+        { name: '本期-合同-数量_2', field: 'r2_contract_qty', type: dataType.currency },
+        { name: '本期-合同-金额_2', field: 'r2_contract_tp', type: dataType.currency },
+        { name: '本期-数量变更-数量_2', field: 'r2_qc_qty', type: dataType.currency },
+        { name: '本期-数量变更-金额_2', field: 'r2_qc_tp', type: dataType.currency },
+        { name: '本期-完成-数量_2', field: 'r2_gather_qty', type: dataType.currency },
+        { name: '本期-完成-金额_2', field: 'r2_gather_tp', type: dataType.currency },
+
+        { name: '本期-合同-数量_3', field: 'r3_contract_qty', type: dataType.currency },
+        { name: '本期-合同-金额_3', field: 'r3_contract_tp', type: dataType.currency },
+        { name: '本期-数量变更-数量_3', field: 'r3_qc_qty', type: dataType.currency },
+        { name: '本期-数量变更-金额_3', field: 'r3_qc_tp', type: dataType.currency },
+        { name: '本期-完成-数量_3', field: 'r3_gather_qty', type: dataType.currency },
+        { name: '本期-完成-金额_3', field: 'r3_gather_tp', type: dataType.currency },
+
+        { name: '本期-合同-数量_4', field: 'r4_contract_qty', type: dataType.currency },
+        { name: '本期-合同-金额_4', field: 'r4_contract_tp', type: dataType.currency },
+        { name: '本期-数量变更-数量_4', field: 'r4_qc_qty', type: dataType.currency },
+        { name: '本期-数量变更-金额_4', field: 'r4_qc_tp', type: dataType.currency },
+        { name: '本期-完成-数量_4', field: 'r4_gather_qty', type: dataType.currency },
+        { name: '本期-完成-金额_4', field: 'r4_gather_tp', type: dataType.currency },
+
+        { name: '本期-合同-数量_5', field: 'r5_contract_qty', type: dataType.currency },
+        { name: '本期-合同-金额_5', field: 'r5_contract_tp', type: dataType.currency },
+        { name: '本期-数量变更-数量_5', field: 'r5_qc_qty', type: dataType.currency },
+        { name: '本期-数量变更-金额_5', field: 'r5_qc_tp', type: dataType.currency },
+        { name: '本期-完成-数量_5', field: 'r5_gather_qty', type: dataType.currency },
+        { name: '本期-完成-金额_5', field: 'r5_gather_tp', type: dataType.currency },
+
+        { name: '本期-合同-数量_6', field: 'r6_contract_qty', type: dataType.currency },
+        { name: '本期-合同-金额_6', field: 'r6_contract_tp', type: dataType.currency },
+        { name: '本期-数量变更-数量_6', field: 'r6_qc_qty', type: dataType.currency },
+        { name: '本期-数量变更-金额_6', field: 'r6_qc_tp', type: dataType.currency },
+        { name: '本期-完成-数量_6', field: 'r6_gather_qty', type: dataType.currency },
+        { name: '本期-完成-金额_6', field: 'r6_gather_tp', type: dataType.currency },
+
+        { name: '本期-合同-数量_7', field: 'r7_contract_qty', type: dataType.currency },
+        { name: '本期-合同-金额_7', field: 'r7_contract_tp', type: dataType.currency },
+        { name: '本期-数量变更-数量_7', field: 'r7_qc_qty', type: dataType.currency },
+        { name: '本期-数量变更-金额_7', field: 'r7_qc_tp', type: dataType.currency },
+        { name: '本期-完成-数量_7', field: 'r7_gather_qty', type: dataType.currency },
+        { name: '本期-完成-金额_7', field: 'r7_gather_tp', type: dataType.currency },
+
+        { name: '本期-合同-数量_8', field: 'r8_contract_qty', type: dataType.currency },
+        { name: '本期-合同-金额_8', field: 'r8_contract_tp', type: dataType.currency },
+        { name: '本期-数量变更-数量_8', field: 'r8_qc_qty', type: dataType.currency },
+        { name: '本期-数量变更-金额_8', field: 'r8_qc_tp', type: dataType.currency },
+        { name: '本期-完成-数量_8', field: 'r8_gather_qty', type: dataType.currency },
+        { name: '本期-完成-金额_8', field: 'r8_gather_tp', type: dataType.currency },
+
+        { name: '本期-合同-数量_9', field: 'r9_contract_qty', type: dataType.currency },
+        { name: '本期-合同-金额_9', field: 'r9_contract_tp', type: dataType.currency },
+        { name: '本期-数量变更-数量_9', field: 'r9_qc_qty', type: dataType.currency },
+        { name: '本期-数量变更-金额_9', field: 'r9_qc_tp', type: dataType.currency },
+        { name: '本期-完成-数量_9', field: 'r9_gather_qty', type: dataType.currency },
+        { name: '本期-完成-金额_9', field: 'r9_gather_tp', type: dataType.currency },
 
         { name: '章节编号', field: 'chapter', type: dataType.str },
         { name: '最底层项目节id', field: 'leaf_xmj_id', type: dataType.str },
@@ -893,9 +889,9 @@ const stage_pos = {
 
         { name: '现场实际数量', field: 'real_qty', type: dataType.currency },
 
-        { name: '本期负变更', field: 'minus_qc_qty', type: dataType.double },
-        { name: '截止上期负变更', field: 'pre_minus_qc_qty', type: dataType.double },
-        { name: '截止本期负变更', field: 'pre_minus_qc_qty', type: dataType.double },
+        { name: '本期负变更', field: 'qc_minus_qty', type: dataType.double },
+        { name: '截止上期负变更', field: 'pre_qc_minus_qty', type: dataType.double },
+        { name: '截止本期负变更', field: 'end_qc_minus_qty', type: dataType.double },
         { name: '1#台账(台账+截止本期负变更)-数量', field: 'final_1_qty', type: dataType.double },
         { name: '1#台账+截止本期变更-数量', field: 'end_final_1_qty', type: dataType.double },
         { name: '1#完成率(%)', field: 'final_1_ratio', type: dataType.double },
@@ -963,9 +959,9 @@ const month_progress = {
     prefix: '工程进度',
     cols: [
         { name: '计量年月', field: 'month', type: dataType.str },
-        { name: '本月计量', field: 'tp', type: dataType.currency, tag: { type: 'tp' } },
+        { name: '本月计量', field: 'tp', type: dataType.currency },
         { name: '本月完成度', field: 'ratio', type: dataType.double },
-        { name: '累计计量', field: 'end_tp', type: dataType.currency, tag: { type: 'tp' } },
+        { name: '累计计量', field: 'end_tp', type: dataType.currency },
         { name: '累计完成度', field: 'end_ratio', type: dataType.double },
     ],
 };
@@ -1520,6 +1516,12 @@ const gather_tender_info = {
         { name: '中标信息-业主控制价', field: 'bid_info.controlPrice', type: dataType.currency },
         { name: '中标信息-中标价', field: 'bid_info.bidPrice', type: dataType.currency },
         { name: '中标信息-开标日期', field: 'bid_info.bidStartDate', type: dataType.str },
+        { name: '中标信息-招标方式', field: 'bid_info.bidType', type: dataType.str },
+        { name: '中标信息-合同计价方式', field: 'bid_info.dealCalcType', type: dataType.str },
+
+        { name: '截止上期-实付', field: 'pre_sf_tp', type: dataType.currency },
+        { name: '本期-实付', field: 'sf_tp', type: dataType.currency },
+        { name: '截止本期-实付', field: 'end_sf_tp', type: dataType.currency },
     ],
 };
 const gather_stage_pay = {
@@ -1727,19 +1729,19 @@ const material_bills = {
         { name: '清单编号', field: 'b_code', type: dataType.str },
         { name: '名称', field: 'name', type: dataType.str },
         { name: '单位', field: 'unit', type: dataType.str }, // 12
-        { name: '单价', field: 'unit_price', type: dataType.currency, tag: { type: 'up' } },
+        { name: '单价', field: 'unit_price', type: dataType.currency },
 
-        { name: '签约-数量', field: 'deal_qty', type: dataType.currency, tag: { type: 'qty', unitKey: 12 } },
-        { name: '签约-金额', field: 'deal_tp', type: dataType.currency, tag: { type: 'tp' } },
+        { name: '签约-数量', field: 'deal_qty', type: dataType.currency },
+        { name: '签约-金额', field: 'deal_tp', type: dataType.currency },
 
-        { name: '施工复核-数量', field: 'sgfh_qty', type: dataType.currency, tag: { type: 'qty', unitKey: 12 } },
-        { name: '施工复核-金额', field: 'sgfh_tp', type: dataType.currency, tag: { type: 'tp' } },
-        { name: '设计错漏-数量', field: 'sjcl_qty', type: dataType.currency, tag: { type: 'qty', unitKey: 12 } },
-        { name: '设计错漏-金额', field: 'sjcl_tp', type: dataType.currency, tag: { type: 'tp' } },
-        { name: '其他错漏-数量', field: 'qtcl_qty', type: dataType.currency, tag: { type: 'qty', unitKey: 12 } },
-        { name: '其他错漏-金额', field: 'qtcl_tp', type: dataType.currency, tag: { type: 'tp' } },
-        { name: '台账-数量', field: 'quantity', type: dataType.currency, tag: { type: 'qty', unitKey: 12 } },
-        { name: '台账-金额', field: 'total_price', type: dataType.currency, tag: { type: 'tp' } },
+        { name: '施工复核-数量', field: 'sgfh_qty', type: dataType.currency },
+        { name: '施工复核-金额', field: 'sgfh_tp', type: dataType.currency },
+        { name: '设计错漏-数量', field: 'sjcl_qty', type: dataType.currency },
+        { name: '设计错漏-金额', field: 'sjcl_tp', type: dataType.currency },
+        { name: '其他错漏-数量', field: 'qtcl_qty', type: dataType.currency },
+        { name: '其他错漏-金额', field: 'qtcl_tp', type: dataType.currency },
+        { name: '台账-数量', field: 'quantity', type: dataType.currency },
+        { name: '台账-金额', field: 'total_price', type: dataType.currency },
 
         { name: '项目节-数量1', field: 'dgn_qty1', type: dataType.currency },
         { name: '项目节-数量2', field: 'dgn_qty2', type: dataType.currency },
@@ -1749,12 +1751,12 @@ const material_bills = {
         { name: '节点类型', field: 'node_type', type: dataType.int },
         { name: '总额计量', field: 'is_tp', type: dataType.int },
 
-        { name: '本期-合同-数量', field: 'contract_qty', type: dataType.currency, tag: { type: 'qty', unitKey: 12 } },
-        { name: '本期-合同-金额', field: 'contract_tp', type: dataType.currency, tag: { type: 'tp' } },
-        { name: '本期-数量变更-数量', field: 'qc_qty', type: dataType.currency, tag: { type: 'qty', unitKey: 12 } },
-        { name: '本期-数量变更-金额', field: 'qc_tp', type: dataType.currency, tag: { type: 'tp' } },
-        { name: '本期-完成-数量', field: 'gather_qty', type: dataType.currency, tag: { type: 'qty', unitKey: 12 } },
-        { name: '本期-完成-金额', field: 'gather_tp', type: dataType.currency, tag: { type: 'tp' } },
+        { name: '本期-合同-数量', field: 'contract_qty', type: dataType.currency },
+        { name: '本期-合同-金额', field: 'contract_tp', type: dataType.currency },
+        { name: '本期-数量变更-数量', field: 'qc_qty', type: dataType.currency },
+        { name: '本期-数量变更-金额', field: 'qc_tp', type: dataType.currency },
+        { name: '本期-完成-数量', field: 'gather_qty', type: dataType.currency },
+        { name: '本期-完成-金额', field: 'gather_tp', type: dataType.currency },
         { name: '本期批注', field: 'postil', type: dataType.str },
 
         { name: '预留扩展字段_1', field: 'ex_value1', type: dataType.currency },
@@ -2328,18 +2330,18 @@ const stage_change_info = {
         { name: '变更性质', field: 'quality', type: dataType.int },
         { name: '变更提出单位', field: 'company', type: dataType.str },
         { name: '费用承担方', field: 'charge', type: dataType.int },
-        { name: '金额', field: 'total_price', type: dataType.currency, tag: { type: 'tp' } },
+        { name: '金额', field: 'total_price', type: dataType.currency },
         { name: '变更状态发生时间(时间戳)', field: 'cin_time', type: dataType.str },
         { name: '完成审批时间(时间戳)', field: 'sin_time', type: dataType.str },
-        { name: '金额_1', field: 'tp_1', type: dataType.currency, tag: { type: 'tp' } },
-        { name: '金额_2', field: 'tp_2', type: dataType.currency, tag: { type: 'tp' } },
-        { name: '金额_3', field: 'tp_3', type: dataType.currency, tag: { type: 'tp' } },
-        { name: '金额_4', field: 'tp_4', type: dataType.currency, tag: { type: 'tp' } },
-        { name: '金额_5', field: 'tp_5', type: dataType.currency, tag: { type: 'tp' } },
-        { name: '金额_6', field: 'tp_6', type: dataType.currency, tag: { type: 'tp' } },
-        { name: '金额_7', field: 'tp_7', type: dataType.currency, tag: { type: 'tp' } },
-        { name: '金额_8', field: 'tp_8', type: dataType.currency, tag: { type: 'tp' } },
-        { name: '金额_9', field: 'tp_9', type: dataType.currency, tag: { type: 'tp' } },
+        { name: '金额_1', field: 'tp_1', type: dataType.currency },
+        { name: '金额_2', field: 'tp_2', type: dataType.currency },
+        { name: '金额_3', field: 'tp_3', type: dataType.currency },
+        { name: '金额_4', field: 'tp_4', type: dataType.currency },
+        { name: '金额_5', field: 'tp_5', type: dataType.currency },
+        { name: '金额_6', field: 'tp_6', type: dataType.currency },
+        { name: '金额_7', field: 'tp_7', type: dataType.currency },
+        { name: '金额_8', field: 'tp_8', type: dataType.currency },
+        { name: '金额_9', field: 'tp_9', type: dataType.currency },
         { name: '附件名称列表', field: 'attNames', type: dataType.currency },
         { name: '截止本期-已执行(%)', field: 'used_ratio', type: dataType.currency },
         { name: '本期使用', field: 'cur_used', type: dataType.int },
@@ -2364,7 +2366,7 @@ const stage_change_info_bills = {
         { name: '清单编号', field: 'code', type: dataType.str },
         { name: '名称', field: 'name', type: dataType.str },
         { name: '单位', field: 'unit', type: dataType.str },
-        { name: '单价', field: 'unit_price', type: dataType.currency, tag: { type: 'up' } },
+        { name: '单价', field: 'unit_price', type: dataType.currency },
         { name: '变更详情', field: 'detail', type: dataType.str },
         { name: '变更部位', field: 'bwmx', type: dataType.str },
         { name: '数量', field: 'qty', type: dataType.currency },

+ 4 - 1
config/config.default.js

@@ -170,6 +170,9 @@ module.exports = appInfo => {
         },
         warning: {
             file: path.join(appInfo.root, 'logs', appInfo.name, config.version, 'warning.log'),
+        },
+        out: {
+            file: path.join(appInfo.root, 'logs', appInfo.name, config.version, 'out.log'),
         }
     };
 
@@ -230,7 +233,7 @@ module.exports = appInfo => {
         },
     };
 
-    config.fujianOssPath = 'https://jiliang-saas-oss.smartcost.com.cn/';
+    config.fujianOssPath = 'https://jiliang-saas-oss-cdn.smartcost.com.cn/';
     config.fujianOssFolder = '';
 
     config.syncUrl = 'http://sync.jl.smartcost.com.cn/';

+ 1 - 1
config/config.uat.js

@@ -81,7 +81,7 @@ module.exports = appInfo => {
         },
     };
 
-    config.fujianOssPath = 'https://jiliang-qa-oss.smartcost.com.cn/uat/';
+    config.fujianOssPath = 'https://jiliang-qa-oss-cdn.smartcost.com.cn/uat/';
     config.fujianOssFolder = 'uat/';
 
     config.syncUrl = 'https://jluat-sync.smartcost.com.cn/';

+ 89 - 0
db_script/ledger_his_count.js

@@ -0,0 +1,89 @@
+'use strict';
+
+/**
+ *
+ *
+ * @author Mai
+ * @date
+ * @version
+ */
+
+const fs = require('fs');
+const path = require('path');
+var util = require('util');
+var logPath = path.join(__dirname, 'update_ledger_his.log');
+var logFile = fs.createWriteStream(logPath, { flags: 'a' });
+console.log = function() {
+  logFile.write(util.format.apply(null, arguments) + '\n');
+  process.stdout.write(util.format.apply(null, arguments) + '\n');
+};
+
+const mysql = require('mysql');
+const oss = require('ali-oss');
+const config = process.argv.splice(2)[0];
+if (['local', 'uat', 'default'].indexOf(config) < 0) throw `参数错误: ${config}`;
+const options = require(`../config/config.${config}`)({ baseDir: __dirname + '/app', root: __dirname, name: 'calc' });
+
+const pool = mysql.createPool(options.mysql.client);
+const ossOption = {
+  bucket: options.oss.clients.his.bucket,
+  accessKeyId: options.oss.default.accessKeyId,
+  accessKeySecret: options.oss.default.accessKeySecret,
+  endpoint: options.oss.default.endpoint,
+  timeout: options.oss.default.timeout,
+};
+const ossClient = new oss(ossOption);
+
+const querySql = async function(sql, sqlParam) {
+  return new Promise(function(resolve, reject) {
+    pool.getConnection(function(err, conn) {
+      if (err) {
+        if (err) console.log(err);
+        reject(err);
+      } else {
+        conn.query(sql, sqlParam, function(err, rows, fields) {
+          if (err) console.log(err);
+          // 释放连接
+          conn.release();
+          // 传递Promise回调对象
+          resolve(rows);
+        });
+      }
+    });
+  });
+};
+
+const loadLedgerDataFromOss = async function(url) {
+  let File;
+  try {
+    File = await ossClient.get(options.hisOssPath + url);
+  } catch(err) {
+    if (err.status === 404) return 0;
+    throw err;
+  }
+  if (File.res.status !== 200) return '获取修订台账有误';
+  const result = JSON.parse(File.content);
+  return result.length;
+};
+
+const doCompleteLedgerHis = async function(l) {
+  const bills_count = await loadLedgerDataFromOss(l.bills_file);
+  const pos_count = await loadLedgerDataFromOss(l.pos_file);
+  await querySql('Update zh_ledger_history Set bills_count = ?, pos_count = ? Where id = ?', [bills_count, pos_count, l.id]);
+  console.log(`ledgerHis-${l.id}(${l.tid}): billsCount(${bills_count}), posCount(${pos_count})`);
+};
+
+const doComplete = async function() {
+    try {
+      //const ledgerHis = await querySql('Select * From zh_ledger_history where bills_count = 0 order by id asc');
+      const ledgerHis = await querySql('Select * From zh_ledger_history');
+      for (const l of ledgerHis) {
+        await doCompleteLedgerHis(l);
+      }
+    } catch (err) {
+      console.log(err);
+    }
+    pool.end();
+};
+doComplete();
+

+ 70 - 0
db_script/minus_no_value.js

@@ -0,0 +1,70 @@
+'use strict';
+
+/**
+ *
+ *
+ * @author Mai
+ * @date
+ * @version
+ */
+
+const mysql = require('mysql');
+const config = process.argv.splice(2)[0];
+if (['local', 'uat', 'default'].indexOf(config) < 0) throw `参数错误: ${config}`;
+const options = require(`../config/config.${config}`)({ baseDir: __dirname + '/app', root: __dirname, name: 'calc' });
+
+const pool = mysql.createPool(options.mysql.client);
+
+const querySql = async function(sql, sqlParam) {
+    return new Promise(function(resolve, reject) {
+        pool.getConnection(function(err, conn) {
+            if (err) {
+                if (err) console.log(err);
+                reject(err);
+            } else {
+                conn.query(sql, sqlParam, function(err, rows, fields) {
+                    if (err) console.log(err);
+                    // 释放连接
+                    conn.release();
+                    // 传递Promise回调对象
+                    resolve(rows);
+                });
+            }
+        });
+    });
+};
+
+const doCompleteProject = async function(p) {
+    const fun_rela = p.fun_rela ? JSON.parse(p.fun_rela) : {};
+    fun_rela.minusNoValue = false;
+    await querySql(`Update zh_project Set fun_rela = '${JSON.stringify(fun_rela)}' Where id = ${p.id}`);
+};
+const doCompleteTender = async function(t) {
+    const info = await querySql('Select * From zh_tender_info Where tid = ?', [t.id]);
+    if (info.length > 0) {
+        const fun_rela = t.fun_rela ? JSON.parse(t.fun_rela) : {};
+        fun_rela.stage_chagne = { minusNoValue: false };
+        await querySql(`Update zh_tender_info Set fun_rela = '${JSON.stringify(fun_rela)}' Where tid = ${t.id}`);
+    } else {
+        const fun_rela = { stage_change: { minusNoValue: false } };
+        await querySql(`Insert Into zh_tender_info (pid, tid, fun_rela) Values(${t.project_id}, ${t.id}, '${JSON.stringify(fun_rela)}')`);
+    }
+};
+
+const doComplete = async function() {
+    try {
+        const project = await querySql('Select * From zh_project');
+        for (const p of project) {
+            await doCompleteProject(p);
+        }
+        const tenders = await querySql('Select * From zh_tender');
+        for (const t of tenders) {
+            await doCompleteTender(t);
+        }
+    } catch (err) {
+        console.log(err);
+    }
+    pool.end();
+};
+doComplete();
+

+ 80 - 0
db_script/stage_stash.js

@@ -0,0 +1,80 @@
+'use strict';
+
+/**
+ *
+ *
+ * @author Mai
+ * @date
+ * @version
+ */
+
+const fs = require('fs');
+const path = require('path');
+var util = require('util');
+var logPath = path.join(__dirname, 'update_ledger_his.log');
+var logFile = fs.createWriteStream(logPath, { flags: 'a' });
+console.log = function() {
+    logFile.write(util.format.apply(null, arguments) + '\n');
+    process.stdout.write(util.format.apply(null, arguments) + '\n');
+};
+
+const mysql = require('mysql');
+const oss = require('ali-oss');
+const config = process.argv.splice(2)[0];
+if (['local', 'uat', 'default'].indexOf(config) < 0) throw `参数错误: ${config}`;
+const options = require(`../config/config.${config}`)({ baseDir: __dirname + '/app', root: __dirname, name: 'calc' });
+
+const pool = mysql.createPool(options.mysql.client);
+const ossOption = {
+    bucket: options.oss.clients.his.bucket,
+    accessKeyId: options.oss.default.accessKeyId,
+    accessKeySecret: options.oss.default.accessKeySecret,
+    endpoint: options.oss.default.endpoint,
+    timeout: options.oss.default.timeout,
+};
+const ossClient = new oss(ossOption);
+
+const querySql = async function(sql, sqlParam) {
+    return new Promise(function(resolve, reject) {
+        pool.getConnection(function(err, conn) {
+            if (err) {
+                if (err) console.log(err);
+                reject(err);
+            } else {
+                conn.query(sql, sqlParam, function(err, rows, fields) {
+                    if (err) console.log(err);
+                    // 释放连接
+                    conn.release();
+                    // 传递Promise回调对象
+                    resolve(rows);
+                });
+            }
+        });
+    });
+};
+
+const loadDataFromOss = async function(url) {
+    const File = await ossClient.get('undefined' + url);
+    if (File.res.status !== 200) return '获取修订台账有误';
+    return File.content;
+};
+
+const doCompleteStashStash = async function(stash) {
+    const data = await loadDataFromOss(stash.filepath);
+    await ossClient.put(options.stashOssPath + stash.filepath, data);
+};
+
+const doComplete = async function() {
+    try {
+        const stash = await querySql('Select * From zh_stage_stash');
+        for (const s of stash) {
+            console.log(s);
+            await doCompleteStashStash(s);
+        }
+    } catch (err) {
+        console.log(err);
+    }
+    pool.end();
+};
+doComplete();
+

+ 31 - 0
publish.md

@@ -0,0 +1,31 @@
+# 发布相关
+记录发布流程,执行脚本写完后,需更新到
+
+## 默认操作
+1. 合并代码至uat/master
+2. 登录阿里云,在相关数据库中,执行update.sql和index.sql
+3. jenkins,发布脚本,执行升级脚本(按需)
+4. 重启服务
+
+##特殊操作
+如果没有特殊说明,则在第默认操作的第3步前,执行相关脚本,如果有特殊要求,需特别说明
+
+### V3.6
+
+
+### V3.5.24.0822
+2022-05-31 ~ 2022-08-22(uat) ~ ...(prod)
+3.1. ledger_his_count: 更新ledger_history表中新增的bills_count和pos_count两个字段数据
+3.2. minus_no_value: 更新project.fun_rela.minusNoValue=false和tender_info.fun_rela.stage_change.minusNoValue=false
+
+### uat
+```bash
+$ node ledger_his_count uat
+$ node minus_no_value uat
+```
+
+### prod
+```bash
+$ node ledger_his_count default
+$ node minus_no_value default
+```

+ 605 - 0
sql/update.sql

@@ -0,0 +1,605 @@
+ALTER TABLE `zh_ledger_history`
+ADD COLUMN `bills_count`  int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '清单条数' AFTER `valid`,
+ADD COLUMN `pos_count`  int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '计量单元数量' AFTER `bills_count`;
+
+UPDATE `zh_tender` SET `had_map`=3 WHERE `had_map`=1;
+
+ALTER TABLE `zh_tender` ADD `map_pic` VARCHAR(255) NULL DEFAULT NULL COMMENT '静态图片地址' AFTER `had_map`;
+
+CREATE TABLE `zh_ledger_extra_0` (
+`id`  varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'uuid' ,
+`tid`  int(11) UNSIGNED NOT NULL COMMENT '标段id' ,
+`is_tp`  tinyint(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT '总额计量' ,
+`gxby_status`  tinyint(4) NULL DEFAULT '-1' COMMENT '工序报验-状态' ,
+`gxby_limit`  int(4) NOT NULL DEFAULT 0 COMMENT '计量是否受限,0不受限,1受限' ,
+`dagl_status`  tinyint(4) NULL DEFAULT '-1' COMMENT '档案管理-状态' ,
+`gxby_url`  varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '工序报验-查看链接' ,
+`dagl_limit`  int(4) NOT NULL DEFAULT 0 COMMENT '计量是否受限,0不受限,1受限' ,
+`dagl_url`  varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '档案管理-查看链接' ,
+PRIMARY KEY (`id`)
+);
+CREATE TABLE `zh_ledger_extra_1` (
+`id`  varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'uuid' ,
+`tid`  int(11) UNSIGNED NOT NULL COMMENT '标段id' ,
+`is_tp`  tinyint(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT '总额计量' ,
+`gxby_status`  tinyint(4) NULL DEFAULT '-1' COMMENT '工序报验-状态' ,
+`gxby_limit`  int(4) NOT NULL DEFAULT 0 COMMENT '计量是否受限,0不受限,1受限' ,
+`dagl_status`  tinyint(4) NULL DEFAULT '-1' COMMENT '档案管理-状态' ,
+`gxby_url`  varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '工序报验-查看链接' ,
+`dagl_limit`  int(4) NOT NULL DEFAULT 0 COMMENT '计量是否受限,0不受限,1受限' ,
+`dagl_url`  varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '档案管理-查看链接' ,
+PRIMARY KEY (`id`)
+);
+CREATE TABLE `zh_ledger_extra_2` (
+`id`  varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'uuid' ,
+`tid`  int(11) UNSIGNED NOT NULL COMMENT '标段id' ,
+`is_tp`  tinyint(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT '总额计量' ,
+`gxby_status`  tinyint(4) NULL DEFAULT '-1' COMMENT '工序报验-状态' ,
+`gxby_limit`  int(4) NOT NULL DEFAULT 0 COMMENT '计量是否受限,0不受限,1受限' ,
+`dagl_status`  tinyint(4) NULL DEFAULT '-1' COMMENT '档案管理-状态' ,
+`gxby_url`  varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '工序报验-查看链接' ,
+`dagl_limit`  int(4) NOT NULL DEFAULT 0 COMMENT '计量是否受限,0不受限,1受限' ,
+`dagl_url`  varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '档案管理-查看链接' ,
+PRIMARY KEY (`id`)
+);
+CREATE TABLE `zh_ledger_extra_3` (
+`id`  varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'uuid' ,
+`tid`  int(11) UNSIGNED NOT NULL COMMENT '标段id' ,
+`is_tp`  tinyint(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT '总额计量' ,
+`gxby_status`  tinyint(4) NULL DEFAULT '-1' COMMENT '工序报验-状态' ,
+`gxby_limit`  int(4) NOT NULL DEFAULT 0 COMMENT '计量是否受限,0不受限,1受限' ,
+`dagl_status`  tinyint(4) NULL DEFAULT '-1' COMMENT '档案管理-状态' ,
+`gxby_url`  varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '工序报验-查看链接' ,
+`dagl_limit`  int(4) NOT NULL DEFAULT 0 COMMENT '计量是否受限,0不受限,1受限' ,
+`dagl_url`  varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '档案管理-查看链接' ,
+PRIMARY KEY (`id`)
+);
+CREATE TABLE `zh_ledger_extra_4` (
+`id`  varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'uuid' ,
+`tid`  int(11) UNSIGNED NOT NULL COMMENT '标段id' ,
+`is_tp`  tinyint(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT '总额计量' ,
+`gxby_status`  tinyint(4) NULL DEFAULT '-1' COMMENT '工序报验-状态' ,
+`gxby_limit`  int(4) NOT NULL DEFAULT 0 COMMENT '计量是否受限,0不受限,1受限' ,
+`dagl_status`  tinyint(4) NULL DEFAULT '-1' COMMENT '档案管理-状态' ,
+`gxby_url`  varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '工序报验-查看链接' ,
+`dagl_limit`  int(4) NOT NULL DEFAULT 0 COMMENT '计量是否受限,0不受限,1受限' ,
+`dagl_url`  varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '档案管理-查看链接' ,
+PRIMARY KEY (`id`)
+);
+CREATE TABLE `zh_ledger_extra_5` (
+`id`  varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'uuid' ,
+`tid`  int(11) UNSIGNED NOT NULL COMMENT '标段id' ,
+`is_tp`  tinyint(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT '总额计量' ,
+`gxby_status`  tinyint(4) NULL DEFAULT '-1' COMMENT '工序报验-状态' ,
+`gxby_limit`  int(4) NOT NULL DEFAULT 0 COMMENT '计量是否受限,0不受限,1受限' ,
+`dagl_status`  tinyint(4) NULL DEFAULT '-1' COMMENT '档案管理-状态' ,
+`gxby_url`  varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '工序报验-查看链接' ,
+`dagl_limit`  int(4) NOT NULL DEFAULT 0 COMMENT '计量是否受限,0不受限,1受限' ,
+`dagl_url`  varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '档案管理-查看链接' ,
+PRIMARY KEY (`id`)
+);
+CREATE TABLE `zh_ledger_extra_6` (
+`id`  varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'uuid' ,
+`tid`  int(11) UNSIGNED NOT NULL COMMENT '标段id' ,
+`is_tp`  tinyint(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT '总额计量' ,
+`gxby_status`  tinyint(4) NULL DEFAULT '-1' COMMENT '工序报验-状态' ,
+`gxby_limit`  int(4) NOT NULL DEFAULT 0 COMMENT '计量是否受限,0不受限,1受限' ,
+`dagl_status`  tinyint(4) NULL DEFAULT '-1' COMMENT '档案管理-状态' ,
+`gxby_url`  varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '工序报验-查看链接' ,
+`dagl_limit`  int(4) NOT NULL DEFAULT 0 COMMENT '计量是否受限,0不受限,1受限' ,
+`dagl_url`  varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '档案管理-查看链接' ,
+PRIMARY KEY (`id`)
+);
+CREATE TABLE `zh_ledger_extra_7` (
+`id`  varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'uuid' ,
+`tid`  int(11) UNSIGNED NOT NULL COMMENT '标段id' ,
+`is_tp`  tinyint(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT '总额计量' ,
+`gxby_status`  tinyint(4) NULL DEFAULT '-1' COMMENT '工序报验-状态' ,
+`gxby_limit`  int(4) NOT NULL DEFAULT 0 COMMENT '计量是否受限,0不受限,1受限' ,
+`dagl_status`  tinyint(4) NULL DEFAULT '-1' COMMENT '档案管理-状态' ,
+`gxby_url`  varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '工序报验-查看链接' ,
+`dagl_limit`  int(4) NOT NULL DEFAULT 0 COMMENT '计量是否受限,0不受限,1受限' ,
+`dagl_url`  varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '档案管理-查看链接' ,
+PRIMARY KEY (`id`)
+);
+CREATE TABLE `zh_ledger_extra_8` (
+`id`  varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'uuid' ,
+`tid`  int(11) UNSIGNED NOT NULL COMMENT '标段id' ,
+`is_tp`  tinyint(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT '总额计量' ,
+`gxby_status`  tinyint(4) NULL DEFAULT '-1' COMMENT '工序报验-状态' ,
+`gxby_limit`  int(4) NOT NULL DEFAULT 0 COMMENT '计量是否受限,0不受限,1受限' ,
+`dagl_status`  tinyint(4) NULL DEFAULT '-1' COMMENT '档案管理-状态' ,
+`gxby_url`  varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '工序报验-查看链接' ,
+`dagl_limit`  int(4) NOT NULL DEFAULT 0 COMMENT '计量是否受限,0不受限,1受限' ,
+`dagl_url`  varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '档案管理-查看链接' ,
+PRIMARY KEY (`id`)
+);
+CREATE TABLE `zh_ledger_extra_9` (
+`id`  varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'uuid' ,
+`tid`  int(11) UNSIGNED NOT NULL COMMENT '标段id' ,
+`is_tp`  tinyint(1) UNSIGNED NOT NULL DEFAULT 0 COMMENT '总额计量' ,
+`gxby_status`  tinyint(4) NULL DEFAULT '-1' COMMENT '工序报验-状态' ,
+`gxby_limit`  int(4) NOT NULL DEFAULT 0 COMMENT '计量是否受限,0不受限,1受限' ,
+`dagl_status`  tinyint(4) NULL DEFAULT '-1' COMMENT '档案管理-状态' ,
+`gxby_url`  varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '工序报验-查看链接' ,
+`dagl_limit`  int(4) NOT NULL DEFAULT 0 COMMENT '计量是否受限,0不受限,1受限' ,
+`dagl_url`  varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '档案管理-查看链接' ,
+PRIMARY KEY (`id`)
+);
+
+
+CREATE TABLE `zh_pos_extra_0` (
+`id`  varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'uuid' ,
+`tid`  int(11) UNSIGNED NOT NULL COMMENT '标段id' ,
+`gxby_status`  tinyint(4) NULL DEFAULT '-1' COMMENT '工序报验-状态' ,
+`gxby_limit`  int(4) NOT NULL DEFAULT 0 COMMENT '计量是否受限,0不受限,1受限' ,
+`dagl_status`  tinyint(4) NULL DEFAULT '-1' COMMENT '档案管理-状态' ,
+`gxby_url`  varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '工序报验-查看链接' ,
+`dagl_limit`  int(4) NOT NULL DEFAULT 0 COMMENT '计量是否受限,0不受限,1受限' ,
+`dagl_url`  varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '档案管理-查看链接' ,
+PRIMARY KEY (`id`)
+);
+CREATE TABLE `zh_pos_extra_1` (
+`id`  varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'uuid' ,
+`tid`  int(11) UNSIGNED NOT NULL COMMENT '标段id' ,
+`gxby_status`  tinyint(4) NULL DEFAULT '-1' COMMENT '工序报验-状态' ,
+`gxby_limit`  int(4) NOT NULL DEFAULT 0 COMMENT '计量是否受限,0不受限,1受限' ,
+`dagl_status`  tinyint(4) NULL DEFAULT '-1' COMMENT '档案管理-状态' ,
+`gxby_url`  varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '工序报验-查看链接' ,
+`dagl_limit`  int(4) NOT NULL DEFAULT 0 COMMENT '计量是否受限,0不受限,1受限' ,
+`dagl_url`  varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '档案管理-查看链接' ,
+PRIMARY KEY (`id`)
+);
+CREATE TABLE `zh_pos_extra_2` (
+`id`  varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'uuid' ,
+`tid`  int(11) UNSIGNED NOT NULL COMMENT '标段id' ,
+`gxby_status`  tinyint(4) NULL DEFAULT '-1' COMMENT '工序报验-状态' ,
+`gxby_limit`  int(4) NOT NULL DEFAULT 0 COMMENT '计量是否受限,0不受限,1受限' ,
+`dagl_status`  tinyint(4) NULL DEFAULT '-1' COMMENT '档案管理-状态' ,
+`gxby_url`  varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '工序报验-查看链接' ,
+`dagl_limit`  int(4) NOT NULL DEFAULT 0 COMMENT '计量是否受限,0不受限,1受限' ,
+`dagl_url`  varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '档案管理-查看链接' ,
+PRIMARY KEY (`id`)
+);
+CREATE TABLE `zh_pos_extra_3` (
+`id`  varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'uuid' ,
+`tid`  int(11) UNSIGNED NOT NULL COMMENT '标段id' ,
+`gxby_status`  tinyint(4) NULL DEFAULT '-1' COMMENT '工序报验-状态' ,
+`gxby_limit`  int(4) NOT NULL DEFAULT 0 COMMENT '计量是否受限,0不受限,1受限' ,
+`dagl_status`  tinyint(4) NULL DEFAULT '-1' COMMENT '档案管理-状态' ,
+`gxby_url`  varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '工序报验-查看链接' ,
+`dagl_limit`  int(4) NOT NULL DEFAULT 0 COMMENT '计量是否受限,0不受限,1受限' ,
+`dagl_url`  varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '档案管理-查看链接' ,
+PRIMARY KEY (`id`)
+);
+CREATE TABLE `zh_pos_extra_4` (
+`id`  varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'uuid' ,
+`tid`  int(11) UNSIGNED NOT NULL COMMENT '标段id' ,
+`gxby_status`  tinyint(4) NULL DEFAULT '-1' COMMENT '工序报验-状态' ,
+`gxby_limit`  int(4) NOT NULL DEFAULT 0 COMMENT '计量是否受限,0不受限,1受限' ,
+`dagl_status`  tinyint(4) NULL DEFAULT '-1' COMMENT '档案管理-状态' ,
+`gxby_url`  varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '工序报验-查看链接' ,
+`dagl_limit`  int(4) NOT NULL DEFAULT 0 COMMENT '计量是否受限,0不受限,1受限' ,
+`dagl_url`  varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '档案管理-查看链接' ,
+PRIMARY KEY (`id`)
+);
+CREATE TABLE `zh_pos_extra_5` (
+`id`  varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'uuid' ,
+`tid`  int(11) UNSIGNED NOT NULL COMMENT '标段id' ,
+`gxby_status`  tinyint(4) NULL DEFAULT '-1' COMMENT '工序报验-状态' ,
+`gxby_limit`  int(4) NOT NULL DEFAULT 0 COMMENT '计量是否受限,0不受限,1受限' ,
+`dagl_status`  tinyint(4) NULL DEFAULT '-1' COMMENT '档案管理-状态' ,
+`gxby_url`  varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '工序报验-查看链接' ,
+`dagl_limit`  int(4) NOT NULL DEFAULT 0 COMMENT '计量是否受限,0不受限,1受限' ,
+`dagl_url`  varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '档案管理-查看链接' ,
+PRIMARY KEY (`id`)
+);
+CREATE TABLE `zh_pos_extra_6` (
+`id`  varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'uuid' ,
+`tid`  int(11) UNSIGNED NOT NULL COMMENT '标段id' ,
+`gxby_status`  tinyint(4) NULL DEFAULT '-1' COMMENT '工序报验-状态' ,
+`gxby_limit`  int(4) NOT NULL DEFAULT 0 COMMENT '计量是否受限,0不受限,1受限' ,
+`dagl_status`  tinyint(4) NULL DEFAULT '-1' COMMENT '档案管理-状态' ,
+`gxby_url`  varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '工序报验-查看链接' ,
+`dagl_limit`  int(4) NOT NULL DEFAULT 0 COMMENT '计量是否受限,0不受限,1受限' ,
+`dagl_url`  varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '档案管理-查看链接' ,
+PRIMARY KEY (`id`)
+);
+CREATE TABLE `zh_pos_extra_7` (
+`id`  varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'uuid' ,
+`tid`  int(11) UNSIGNED NOT NULL COMMENT '标段id' ,
+`gxby_status`  tinyint(4) NULL DEFAULT '-1' COMMENT '工序报验-状态' ,
+`gxby_limit`  int(4) NOT NULL DEFAULT 0 COMMENT '计量是否受限,0不受限,1受限' ,
+`dagl_status`  tinyint(4) NULL DEFAULT '-1' COMMENT '档案管理-状态' ,
+`gxby_url`  varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '工序报验-查看链接' ,
+`dagl_limit`  int(4) NOT NULL DEFAULT 0 COMMENT '计量是否受限,0不受限,1受限' ,
+`dagl_url`  varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '档案管理-查看链接' ,
+PRIMARY KEY (`id`)
+);
+CREATE TABLE `zh_pos_extra_8` (
+`id`  varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'uuid' ,
+`tid`  int(11) UNSIGNED NOT NULL COMMENT '标段id' ,
+`gxby_status`  tinyint(4) NULL DEFAULT '-1' COMMENT '工序报验-状态' ,
+`gxby_limit`  int(4) NOT NULL DEFAULT 0 COMMENT '计量是否受限,0不受限,1受限' ,
+`dagl_status`  tinyint(4) NULL DEFAULT '-1' COMMENT '档案管理-状态' ,
+`gxby_url`  varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '工序报验-查看链接' ,
+`dagl_limit`  int(4) NOT NULL DEFAULT 0 COMMENT '计量是否受限,0不受限,1受限' ,
+`dagl_url`  varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '档案管理-查看链接' ,
+PRIMARY KEY (`id`)
+);
+CREATE TABLE `zh_pos_extra_9` (
+`id`  varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'uuid' ,
+`tid`  int(11) UNSIGNED NOT NULL COMMENT '标段id' ,
+`gxby_status`  tinyint(4) NULL DEFAULT '-1' COMMENT '工序报验-状态' ,
+`gxby_limit`  int(4) NOT NULL DEFAULT 0 COMMENT '计量是否受限,0不受限,1受限' ,
+`dagl_status`  tinyint(4) NULL DEFAULT '-1' COMMENT '档案管理-状态' ,
+`gxby_url`  varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '工序报验-查看链接' ,
+`dagl_limit`  int(4) NOT NULL DEFAULT 0 COMMENT '计量是否受限,0不受限,1受限' ,
+`dagl_url`  varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '档案管理-查看链接' ,
+PRIMARY KEY (`id`)
+);
+CREATE TABLE `zh_pos_extra_10` (
+`id`  varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'uuid' ,
+`tid`  int(11) UNSIGNED NOT NULL COMMENT '标段id' ,
+`gxby_status`  tinyint(4) NULL DEFAULT '-1' COMMENT '工序报验-状态' ,
+`gxby_limit`  int(4) NOT NULL DEFAULT 0 COMMENT '计量是否受限,0不受限,1受限' ,
+`dagl_status`  tinyint(4) NULL DEFAULT '-1' COMMENT '档案管理-状态' ,
+`gxby_url`  varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '工序报验-查看链接' ,
+`dagl_limit`  int(4) NOT NULL DEFAULT 0 COMMENT '计量是否受限,0不受限,1受限' ,
+`dagl_url`  varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '档案管理-查看链接' ,
+PRIMARY KEY (`id`)
+);
+CREATE TABLE `zh_pos_extra_11` (
+`id`  varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'uuid' ,
+`tid`  int(11) UNSIGNED NOT NULL COMMENT '标段id' ,
+`gxby_status`  tinyint(4) NULL DEFAULT '-1' COMMENT '工序报验-状态' ,
+`gxby_limit`  int(4) NOT NULL DEFAULT 0 COMMENT '计量是否受限,0不受限,1受限' ,
+`dagl_status`  tinyint(4) NULL DEFAULT '-1' COMMENT '档案管理-状态' ,
+`gxby_url`  varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '工序报验-查看链接' ,
+`dagl_limit`  int(4) NOT NULL DEFAULT 0 COMMENT '计量是否受限,0不受限,1受限' ,
+`dagl_url`  varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '档案管理-查看链接' ,
+PRIMARY KEY (`id`)
+);
+CREATE TABLE `zh_pos_extra_12` (
+`id`  varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'uuid' ,
+`tid`  int(11) UNSIGNED NOT NULL COMMENT '标段id' ,
+`gxby_status`  tinyint(4) NULL DEFAULT '-1' COMMENT '工序报验-状态' ,
+`gxby_limit`  int(4) NOT NULL DEFAULT 0 COMMENT '计量是否受限,0不受限,1受限' ,
+`dagl_status`  tinyint(4) NULL DEFAULT '-1' COMMENT '档案管理-状态' ,
+`gxby_url`  varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '工序报验-查看链接' ,
+`dagl_limit`  int(4) NOT NULL DEFAULT 0 COMMENT '计量是否受限,0不受限,1受限' ,
+`dagl_url`  varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '档案管理-查看链接' ,
+PRIMARY KEY (`id`)
+);
+CREATE TABLE `zh_pos_extra_13` (
+`id`  varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'uuid' ,
+`tid`  int(11) UNSIGNED NOT NULL COMMENT '标段id' ,
+`gxby_status`  tinyint(4) NULL DEFAULT '-1' COMMENT '工序报验-状态' ,
+`gxby_limit`  int(4) NOT NULL DEFAULT 0 COMMENT '计量是否受限,0不受限,1受限' ,
+`dagl_status`  tinyint(4) NULL DEFAULT '-1' COMMENT '档案管理-状态' ,
+`gxby_url`  varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '工序报验-查看链接' ,
+`dagl_limit`  int(4) NOT NULL DEFAULT 0 COMMENT '计量是否受限,0不受限,1受限' ,
+`dagl_url`  varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '档案管理-查看链接' ,
+PRIMARY KEY (`id`)
+);
+CREATE TABLE `zh_pos_extra_14` (
+`id`  varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'uuid' ,
+`tid`  int(11) UNSIGNED NOT NULL COMMENT '标段id' ,
+`gxby_status`  tinyint(4) NULL DEFAULT '-1' COMMENT '工序报验-状态' ,
+`gxby_limit`  int(4) NOT NULL DEFAULT 0 COMMENT '计量是否受限,0不受限,1受限' ,
+`dagl_status`  tinyint(4) NULL DEFAULT '-1' COMMENT '档案管理-状态' ,
+`gxby_url`  varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '工序报验-查看链接' ,
+`dagl_limit`  int(4) NOT NULL DEFAULT 0 COMMENT '计量是否受限,0不受限,1受限' ,
+`dagl_url`  varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '档案管理-查看链接' ,
+PRIMARY KEY (`id`)
+);
+CREATE TABLE `zh_pos_extra_15` (
+`id`  varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'uuid' ,
+`tid`  int(11) UNSIGNED NOT NULL COMMENT '标段id' ,
+`gxby_status`  tinyint(4) NULL DEFAULT '-1' COMMENT '工序报验-状态' ,
+`gxby_limit`  int(4) NOT NULL DEFAULT 0 COMMENT '计量是否受限,0不受限,1受限' ,
+`dagl_status`  tinyint(4) NULL DEFAULT '-1' COMMENT '档案管理-状态' ,
+`gxby_url`  varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '工序报验-查看链接' ,
+`dagl_limit`  int(4) NOT NULL DEFAULT 0 COMMENT '计量是否受限,0不受限,1受限' ,
+`dagl_url`  varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '档案管理-查看链接' ,
+PRIMARY KEY (`id`)
+);
+CREATE TABLE `zh_pos_extra_16` (
+`id`  varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'uuid' ,
+`tid`  int(11) UNSIGNED NOT NULL COMMENT '标段id' ,
+`gxby_status`  tinyint(4) NULL DEFAULT '-1' COMMENT '工序报验-状态' ,
+`gxby_limit`  int(4) NOT NULL DEFAULT 0 COMMENT '计量是否受限,0不受限,1受限' ,
+`dagl_status`  tinyint(4) NULL DEFAULT '-1' COMMENT '档案管理-状态' ,
+`gxby_url`  varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '工序报验-查看链接' ,
+`dagl_limit`  int(4) NOT NULL DEFAULT 0 COMMENT '计量是否受限,0不受限,1受限' ,
+`dagl_url`  varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '档案管理-查看链接' ,
+PRIMARY KEY (`id`)
+);
+CREATE TABLE `zh_pos_extra_17` (
+`id`  varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'uuid' ,
+`tid`  int(11) UNSIGNED NOT NULL COMMENT '标段id' ,
+`gxby_status`  tinyint(4) NULL DEFAULT '-1' COMMENT '工序报验-状态' ,
+`gxby_limit`  int(4) NOT NULL DEFAULT 0 COMMENT '计量是否受限,0不受限,1受限' ,
+`dagl_status`  tinyint(4) NULL DEFAULT '-1' COMMENT '档案管理-状态' ,
+`gxby_url`  varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '工序报验-查看链接' ,
+`dagl_limit`  int(4) NOT NULL DEFAULT 0 COMMENT '计量是否受限,0不受限,1受限' ,
+`dagl_url`  varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '档案管理-查看链接' ,
+PRIMARY KEY (`id`)
+);
+CREATE TABLE `zh_pos_extra_18` (
+`id`  varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'uuid' ,
+`tid`  int(11) UNSIGNED NOT NULL COMMENT '标段id' ,
+`gxby_status`  tinyint(4) NULL DEFAULT '-1' COMMENT '工序报验-状态' ,
+`gxby_limit`  int(4) NOT NULL DEFAULT 0 COMMENT '计量是否受限,0不受限,1受限' ,
+`dagl_status`  tinyint(4) NULL DEFAULT '-1' COMMENT '档案管理-状态' ,
+`gxby_url`  varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '工序报验-查看链接' ,
+`dagl_limit`  int(4) NOT NULL DEFAULT 0 COMMENT '计量是否受限,0不受限,1受限' ,
+`dagl_url`  varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '档案管理-查看链接' ,
+PRIMARY KEY (`id`)
+);
+CREATE TABLE `zh_pos_extra_19` (
+`id`  varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT 'uuid' ,
+`tid`  int(11) UNSIGNED NOT NULL COMMENT '标段id' ,
+`gxby_status`  tinyint(4) NULL DEFAULT '-1' COMMENT '工序报验-状态' ,
+`gxby_limit`  int(4) NOT NULL DEFAULT 0 COMMENT '计量是否受限,0不受限,1受限' ,
+`dagl_status`  tinyint(4) NULL DEFAULT '-1' COMMENT '档案管理-状态' ,
+`gxby_url`  varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '工序报验-查看链接' ,
+`dagl_limit`  int(4) NOT NULL DEFAULT 0 COMMENT '计量是否受限,0不受限,1受限' ,
+`dagl_url`  varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '档案管理-查看链接' ,
+PRIMARY KEY (`id`)
+);
+
+
+INSERT INTO zh_ledger_extra_0 ( id, tid, is_tp, gxby_status, gxby_limit, gxby_url, dagl_status, dagl_limit, dagl_url )
+  SELECT id, tender_id, is_tp, gxby_status, gxby_limit, gxby_url, dagl_status, dagl_limit, dagl_url
+  FROM zh_ledger_0
+  WHERE is_tp <> 0 or gxby_status <> -1 or gxby_limit <> 0 or gxby_url <> '' or dagl_status <> -1 or dagl_limit <> 0 or dagl_url <> '';
+INSERT INTO zh_ledger_extra_1 ( id, tid, is_tp, gxby_status, gxby_limit, gxby_url, dagl_status, dagl_limit, dagl_url )
+  SELECT id, tender_id, is_tp, gxby_status, gxby_limit, gxby_url, dagl_status, dagl_limit, dagl_url
+  FROM zh_ledger_1
+  WHERE is_tp <> 0 or gxby_status <> -1 or gxby_limit <> 0 or gxby_url <> '' or dagl_status <> -1 or dagl_limit <> 0 or dagl_url <> '';
+INSERT INTO zh_ledger_extra_2 ( id, tid, is_tp, gxby_status, gxby_limit, gxby_url, dagl_status, dagl_limit, dagl_url )
+  SELECT id, tender_id, is_tp, gxby_status, gxby_limit, gxby_url, dagl_status, dagl_limit, dagl_url
+  FROM zh_ledger_2
+  WHERE is_tp <> 0 or gxby_status <> -1 or gxby_limit <> 0 or gxby_url <> '' or dagl_status <> -1 or dagl_limit <> 0 or dagl_url <> '';
+INSERT INTO zh_ledger_extra_3 ( id, tid, is_tp, gxby_status, gxby_limit, gxby_url, dagl_status, dagl_limit, dagl_url )
+  SELECT id, tender_id, is_tp, gxby_status, gxby_limit, gxby_url, dagl_status, dagl_limit, dagl_url
+  FROM zh_ledger_3
+  WHERE is_tp <> 0 or gxby_status <> -1 or gxby_limit <> 0 or gxby_url <> '' or dagl_status <> -1 or dagl_limit <> 0 or dagl_url <> '';
+INSERT INTO zh_ledger_extra_4 ( id, tid, is_tp, gxby_status, gxby_limit, gxby_url, dagl_status, dagl_limit, dagl_url )
+  SELECT id, tender_id, is_tp, gxby_status, gxby_limit, gxby_url, dagl_status, dagl_limit, dagl_url
+  FROM zh_ledger_4
+  WHERE is_tp <> 0 or gxby_status <> -1 or gxby_limit <> 0 or gxby_url <> '' or dagl_status <> -1 or dagl_limit <> 0 or dagl_url <> '';
+INSERT INTO zh_ledger_extra_5 ( id, tid, is_tp, gxby_status, gxby_limit, gxby_url, dagl_status, dagl_limit, dagl_url )
+  SELECT id, tender_id, is_tp, gxby_status, gxby_limit, gxby_url, dagl_status, dagl_limit, dagl_url
+  FROM zh_ledger_5
+  WHERE is_tp <> 0 or gxby_status <> -1 or gxby_limit <> 0 or gxby_url <> '' or dagl_status <> -1 or dagl_limit <> 0 or dagl_url <> '';
+INSERT INTO zh_ledger_extra_6 ( id, tid, is_tp, gxby_status, gxby_limit, gxby_url, dagl_status, dagl_limit, dagl_url )
+  SELECT id, tender_id, is_tp, gxby_status, gxby_limit, gxby_url, dagl_status, dagl_limit, dagl_url
+  FROM zh_ledger_6
+  WHERE is_tp <> 0 or gxby_status <> -1 or gxby_limit <> 0 or gxby_url <> '' or dagl_status <> -1 or dagl_limit <> 0 or dagl_url <> '';
+INSERT INTO zh_ledger_extra_7 ( id, tid, is_tp, gxby_status, gxby_limit, gxby_url, dagl_status, dagl_limit, dagl_url )
+  SELECT id, tender_id, is_tp, gxby_status, gxby_limit, gxby_url, dagl_status, dagl_limit, dagl_url
+  FROM zh_ledger_7
+  WHERE is_tp <> 0 or gxby_status <> -1 or gxby_limit <> 0 or gxby_url <> '' or dagl_status <> -1 or dagl_limit <> 0 or dagl_url <> '';
+INSERT INTO zh_ledger_extra_8 ( id, tid, is_tp, gxby_status, gxby_limit, gxby_url, dagl_status, dagl_limit, dagl_url )
+  SELECT id, tender_id, is_tp, gxby_status, gxby_limit, gxby_url, dagl_status, dagl_limit, dagl_url
+  FROM zh_ledger_8
+  WHERE is_tp <> 0 or gxby_status <> -1 or gxby_limit <> 0 or gxby_url <> '' or dagl_status <> -1 or dagl_limit <> 0 or dagl_url <> '';
+INSERT INTO zh_ledger_extra_9 ( id, tid, is_tp, gxby_status, gxby_limit, gxby_url, dagl_status, dagl_limit, dagl_url )
+  SELECT id, tender_id, is_tp, gxby_status, gxby_limit, gxby_url, dagl_status, dagl_limit, dagl_url
+  FROM zh_ledger_9
+  WHERE is_tp <> 0 or gxby_status <> -1 or gxby_limit <> 0 or gxby_url <> '' or dagl_status <> -1 or dagl_limit <> 0 or dagl_url <> '';
+
+INSERT INTO zh_pos_extra_0 ( id, tid, gxby_status, gxby_limit, gxby_url, dagl_status, dagl_limit, dagl_url )
+  SELECT id, tid, gxby_status, gxby_limit, gxby_url, dagl_status, dagl_limit, dagl_url
+  FROM zh_pos_0
+  WHERE gxby_status <> -1 or gxby_limit <> 0 or gxby_url <> '' or dagl_status <> -1 or dagl_limit <> 0 or dagl_url <> '';
+INSERT INTO zh_pos_extra_1 ( id, tid, gxby_status, gxby_limit, gxby_url, dagl_status, dagl_limit, dagl_url )
+  SELECT id, tid, gxby_status, gxby_limit, gxby_url, dagl_status, dagl_limit, dagl_url
+  FROM zh_pos_1
+  WHERE gxby_status <> -1 or gxby_limit <> 0 or gxby_url <> '' or dagl_status <> -1 or dagl_limit <> 0 or dagl_url <> '';
+INSERT INTO zh_pos_extra_2 ( id, tid, gxby_status, gxby_limit, gxby_url, dagl_status, dagl_limit, dagl_url )
+  SELECT id, tid, gxby_status, gxby_limit, gxby_url, dagl_status, dagl_limit, dagl_url
+  FROM zh_pos_2
+  WHERE gxby_status <> -1 or gxby_limit <> 0 or gxby_url <> '' or dagl_status <> -1 or dagl_limit <> 0 or dagl_url <> '';
+INSERT INTO zh_pos_extra_3 ( id, tid, gxby_status, gxby_limit, gxby_url, dagl_status, dagl_limit, dagl_url )
+  SELECT id, tid, gxby_status, gxby_limit, gxby_url, dagl_status, dagl_limit, dagl_url
+  FROM zh_pos_3
+  WHERE gxby_status <> -1 or gxby_limit <> 0 or gxby_url <> '' or dagl_status <> -1 or dagl_limit <> 0 or dagl_url <> '';
+INSERT INTO zh_pos_extra_4 ( id, tid, gxby_status, gxby_limit, gxby_url, dagl_status, dagl_limit, dagl_url )
+  SELECT id, tid, gxby_status, gxby_limit, gxby_url, dagl_status, dagl_limit, dagl_url
+  FROM zh_pos_4
+  WHERE gxby_status <> -1 or gxby_limit <> 0 or gxby_url <> '' or dagl_status <> -1 or dagl_limit <> 0 or dagl_url <> '';
+INSERT INTO zh_pos_extra_5 ( id, tid, gxby_status, gxby_limit, gxby_url, dagl_status, dagl_limit, dagl_url )
+  SELECT id, tid, gxby_status, gxby_limit, gxby_url, dagl_status, dagl_limit, dagl_url
+  FROM zh_pos_5
+  WHERE gxby_status <> -1 or gxby_limit <> 0 or gxby_url <> '' or dagl_status <> -1 or dagl_limit <> 0 or dagl_url <> '';
+INSERT INTO zh_pos_extra_6 ( id, tid, gxby_status, gxby_limit, gxby_url, dagl_status, dagl_limit, dagl_url )
+  SELECT id, tid, gxby_status, gxby_limit, gxby_url, dagl_status, dagl_limit, dagl_url
+  FROM zh_pos_6
+  WHERE gxby_status <> -1 or gxby_limit <> 0 or gxby_url <> '' or dagl_status <> -1 or dagl_limit <> 0 or dagl_url <> '';
+INSERT INTO zh_pos_extra_7 ( id, tid, gxby_status, gxby_limit, gxby_url, dagl_status, dagl_limit, dagl_url )
+  SELECT id, tid, gxby_status, gxby_limit, gxby_url, dagl_status, dagl_limit, dagl_url
+  FROM zh_pos_7
+  WHERE gxby_status <> -1 or gxby_limit <> 0 or gxby_url <> '' or dagl_status <> -1 or dagl_limit <> 0 or dagl_url <> '';
+INSERT INTO zh_pos_extra_8 ( id, tid, gxby_status, gxby_limit, gxby_url, dagl_status, dagl_limit, dagl_url )
+  SELECT id, tid, gxby_status, gxby_limit, gxby_url, dagl_status, dagl_limit, dagl_url
+  FROM zh_pos_8
+  WHERE gxby_status <> -1 or gxby_limit <> 0 or gxby_url <> '' or dagl_status <> -1 or dagl_limit <> 0 or dagl_url <> '';
+INSERT INTO zh_pos_extra_9 ( id, tid, gxby_status, gxby_limit, gxby_url, dagl_status, dagl_limit, dagl_url )
+  SELECT id, tid, gxby_status, gxby_limit, gxby_url, dagl_status, dagl_limit, dagl_url
+  FROM zh_pos_9
+  WHERE gxby_status <> -1 or gxby_limit <> 0 or gxby_url <> '' or dagl_status <> -1 or dagl_limit <> 0 or dagl_url <> '';
+INSERT INTO zh_pos_extra_10 ( id, tid, gxby_status, gxby_limit, gxby_url, dagl_status, dagl_limit, dagl_url )
+  SELECT id, tid, gxby_status, gxby_limit, gxby_url, dagl_status, dagl_limit, dagl_url
+  FROM zh_pos_10
+  WHERE gxby_status <> -1 or gxby_limit <> 0 or gxby_url <> '' or dagl_status <> -1 or dagl_limit <> 0 or dagl_url <> '';
+INSERT INTO zh_pos_extra_11 ( id, tid, gxby_status, gxby_limit, gxby_url, dagl_status, dagl_limit, dagl_url )
+  SELECT id, tid, gxby_status, gxby_limit, gxby_url, dagl_status, dagl_limit, dagl_url
+  FROM zh_pos_11
+  WHERE gxby_status <> -1 or gxby_limit <> 0 or gxby_url <> '' or dagl_status <> -1 or dagl_limit <> 0 or dagl_url <> '';
+INSERT INTO zh_pos_extra_12 ( id, tid, gxby_status, gxby_limit, gxby_url, dagl_status, dagl_limit, dagl_url )
+  SELECT id, tid, gxby_status, gxby_limit, gxby_url, dagl_status, dagl_limit, dagl_url
+  FROM zh_pos_12
+  WHERE gxby_status <> -1 or gxby_limit <> 0 or gxby_url <> '' or dagl_status <> -1 or dagl_limit <> 0 or dagl_url <> '';
+INSERT INTO zh_pos_extra_13 ( id, tid, gxby_status, gxby_limit, gxby_url, dagl_status, dagl_limit, dagl_url )
+  SELECT id, tid, gxby_status, gxby_limit, gxby_url, dagl_status, dagl_limit, dagl_url
+  FROM zh_pos_13
+  WHERE gxby_status <> -1 or gxby_limit <> 0 or gxby_url <> '' or dagl_status <> -1 or dagl_limit <> 0 or dagl_url <> '';
+INSERT INTO zh_pos_extra_14 ( id, tid, gxby_status, gxby_limit, gxby_url, dagl_status, dagl_limit, dagl_url )
+  SELECT id, tid, gxby_status, gxby_limit, gxby_url, dagl_status, dagl_limit, dagl_url
+  FROM zh_pos_14
+  WHERE gxby_status <> -1 or gxby_limit <> 0 or gxby_url <> '' or dagl_status <> -1 or dagl_limit <> 0 or dagl_url <> '';
+INSERT INTO zh_pos_extra_15 ( id, tid, gxby_status, gxby_limit, gxby_url, dagl_status, dagl_limit, dagl_url )
+  SELECT id, tid, gxby_status, gxby_limit, gxby_url, dagl_status, dagl_limit, dagl_url
+  FROM zh_pos_15
+  WHERE gxby_status <> -1 or gxby_limit <> 0 or gxby_url <> '' or dagl_status <> -1 or dagl_limit <> 0 or dagl_url <> '';
+INSERT INTO zh_pos_extra_16 ( id, tid, gxby_status, gxby_limit, gxby_url, dagl_status, dagl_limit, dagl_url )
+  SELECT id, tid, gxby_status, gxby_limit, gxby_url, dagl_status, dagl_limit, dagl_url
+  FROM zh_pos_16
+  WHERE gxby_status <> -1 or gxby_limit <> 0 or gxby_url <> '' or dagl_status <> -1 or dagl_limit <> 0 or dagl_url <> '';
+INSERT INTO zh_pos_extra_17 ( id, tid, gxby_status, gxby_limit, gxby_url, dagl_status, dagl_limit, dagl_url )
+  SELECT id, tid, gxby_status, gxby_limit, gxby_url, dagl_status, dagl_limit, dagl_url
+  FROM zh_pos_17
+  WHERE gxby_status <> -1 or gxby_limit <> 0 or gxby_url <> '' or dagl_status <> -1 or dagl_limit <> 0 or dagl_url <> '';
+INSERT INTO zh_pos_extra_18 ( id, tid, gxby_status, gxby_limit, gxby_url, dagl_status, dagl_limit, dagl_url )
+  SELECT id, tid, gxby_status, gxby_limit, gxby_url, dagl_status, dagl_limit, dagl_url
+  FROM zh_pos_18
+  WHERE gxby_status <> -1 or gxby_limit <> 0 or gxby_url <> '' or dagl_status <> -1 or dagl_limit <> 0 or dagl_url <> '';
+INSERT INTO zh_pos_extra_19 ( id, tid, gxby_status, gxby_limit, gxby_url, dagl_status, dagl_limit, dagl_url )
+  SELECT id, tid, gxby_status, gxby_limit, gxby_url, dagl_status, dagl_limit, dagl_url
+  FROM zh_pos_19
+  WHERE gxby_status <> -1 or gxby_limit <> 0 or gxby_url <> '' or dagl_status <> -1 or dagl_limit <> 0 or dagl_url <> '';
+
+ALTER TABLE `zh_stage_bills_0`
+ADD COLUMN `qc_minus_qty`  decimal(24,8) NOT NULL DEFAULT 0 COMMENT '计量不计价变更' AFTER `qc_tp`;
+ALTER TABLE `zh_stage_bills_1`
+ADD COLUMN `qc_minus_qty`  decimal(24,8) NOT NULL DEFAULT 0 COMMENT '计量不计价变更' AFTER `qc_tp`;
+ALTER TABLE `zh_stage_bills_2`
+ADD COLUMN `qc_minus_qty`  decimal(24,8) NOT NULL DEFAULT 0 COMMENT '计量不计价变更' AFTER `qc_tp`;
+ALTER TABLE `zh_stage_bills_3`
+ADD COLUMN `qc_minus_qty`  decimal(24,8) NOT NULL DEFAULT 0 COMMENT '计量不计价变更' AFTER `qc_tp`;
+ALTER TABLE `zh_stage_bills_4`
+ADD COLUMN `qc_minus_qty`  decimal(24,8) NOT NULL DEFAULT 0 COMMENT '计量不计价变更' AFTER `qc_tp`;
+ALTER TABLE `zh_stage_bills_5`
+ADD COLUMN `qc_minus_qty`  decimal(24,8) NOT NULL DEFAULT 0 COMMENT '计量不计价变更' AFTER `qc_tp`;
+ALTER TABLE `zh_stage_bills_6`
+ADD COLUMN `qc_minus_qty`  decimal(24,8) NOT NULL DEFAULT 0 COMMENT '计量不计价变更' AFTER `qc_tp`;
+ALTER TABLE `zh_stage_bills_7`
+ADD COLUMN `qc_minus_qty`  decimal(24,8) NOT NULL DEFAULT 0 COMMENT '计量不计价变更' AFTER `qc_tp`;
+ALTER TABLE `zh_stage_bills_8`
+ADD COLUMN `qc_minus_qty`  decimal(24,8) NOT NULL DEFAULT 0 COMMENT '计量不计价变更' AFTER `qc_tp`;
+ALTER TABLE `zh_stage_bills_9`
+ADD COLUMN `qc_minus_qty`  decimal(24,8) NOT NULL DEFAULT 0 COMMENT '计量不计价变更' AFTER `qc_tp`;
+
+ALTER TABLE `zh_stage_bills_final_0`
+ADD COLUMN `qc_minus_qty`  decimal(24,8) NOT NULL DEFAULT 0 COMMENT '计量不计价变更' AFTER `qc_tp`;
+ALTER TABLE `zh_stage_bills_final_1`
+ADD COLUMN `qc_minus_qty`  decimal(24,8) NOT NULL DEFAULT 0 COMMENT '计量不计价变更' AFTER `qc_tp`;
+ALTER TABLE `zh_stage_bills_final_2`
+ADD COLUMN `qc_minus_qty`  decimal(24,8) NOT NULL DEFAULT 0 COMMENT '计量不计价变更' AFTER `qc_tp`;
+ALTER TABLE `zh_stage_bills_final_3`
+ADD COLUMN `qc_minus_qty`  decimal(24,8) NOT NULL DEFAULT 0 COMMENT '计量不计价变更' AFTER `qc_tp`;
+ALTER TABLE `zh_stage_bills_final_4`
+ADD COLUMN `qc_minus_qty`  decimal(24,8) NOT NULL DEFAULT 0 COMMENT '计量不计价变更' AFTER `qc_tp`;
+ALTER TABLE `zh_stage_bills_final_5`
+ADD COLUMN `qc_minus_qty`  decimal(24,8) NOT NULL DEFAULT 0 COMMENT '计量不计价变更' AFTER `qc_tp`;
+ALTER TABLE `zh_stage_bills_final_6`
+ADD COLUMN `qc_minus_qty`  decimal(24,8) NOT NULL DEFAULT 0 COMMENT '计量不计价变更' AFTER `qc_tp`;
+ALTER TABLE `zh_stage_bills_final_7`
+ADD COLUMN `qc_minus_qty`  decimal(24,8) NOT NULL DEFAULT 0 COMMENT '计量不计价变更' AFTER `qc_tp`;
+ALTER TABLE `zh_stage_bills_final_8`
+ADD COLUMN `qc_minus_qty`  decimal(24,8) NOT NULL DEFAULT 0 COMMENT '计量不计价变更' AFTER `qc_tp`;
+ALTER TABLE `zh_stage_bills_final_9`
+ADD COLUMN `qc_minus_qty`  decimal(24,8) NOT NULL DEFAULT 0 COMMENT '计量不计价变更' AFTER `qc_tp`;
+
+ALTER TABLE `zh_stage_pos_0`
+ADD COLUMN `qc_minus_qty`  decimal(24,8) NOT NULL DEFAULT 0 COMMENT '计量不计价变更' AFTER `qc_qty`;
+ALTER TABLE `zh_stage_pos_1`
+ADD COLUMN `qc_minus_qty`  decimal(24,8) NOT NULL DEFAULT 0 COMMENT '计量不计价变更' AFTER `qc_qty`;
+ALTER TABLE `zh_stage_pos_2`
+ADD COLUMN `qc_minus_qty`  decimal(24,8) NOT NULL DEFAULT 0 COMMENT '计量不计价变更' AFTER `qc_qty`;
+ALTER TABLE `zh_stage_pos_3`
+ADD COLUMN `qc_minus_qty`  decimal(24,8) NOT NULL DEFAULT 0 COMMENT '计量不计价变更' AFTER `qc_qty`;
+ALTER TABLE `zh_stage_pos_4`
+ADD COLUMN `qc_minus_qty`  decimal(24,8) NOT NULL DEFAULT 0 COMMENT '计量不计价变更' AFTER `qc_qty`;
+ALTER TABLE `zh_stage_pos_5`
+ADD COLUMN `qc_minus_qty`  decimal(24,8) NOT NULL DEFAULT 0 COMMENT '计量不计价变更' AFTER `qc_qty`;
+ALTER TABLE `zh_stage_pos_6`
+ADD COLUMN `qc_minus_qty`  decimal(24,8) NOT NULL DEFAULT 0 COMMENT '计量不计价变更' AFTER `qc_qty`;
+ALTER TABLE `zh_stage_pos_7`
+ADD COLUMN `qc_minus_qty`  decimal(24,8) NOT NULL DEFAULT 0 COMMENT '计量不计价变更' AFTER `qc_qty`;
+ALTER TABLE `zh_stage_pos_8`
+ADD COLUMN `qc_minus_qty`  decimal(24,8) NOT NULL DEFAULT 0 COMMENT '计量不计价变更' AFTER `qc_qty`;
+ALTER TABLE `zh_stage_pos_9`
+ADD COLUMN `qc_minus_qty`  decimal(24,8) NOT NULL DEFAULT 0 COMMENT '计量不计价变更' AFTER `qc_qty`;
+ALTER TABLE `zh_stage_pos_10`
+ADD COLUMN `qc_minus_qty`  decimal(24,8) NOT NULL DEFAULT 0 COMMENT '计量不计价变更' AFTER `qc_qty`;
+ALTER TABLE `zh_stage_pos_11`
+ADD COLUMN `qc_minus_qty`  decimal(24,8) NOT NULL DEFAULT 0 COMMENT '计量不计价变更' AFTER `qc_qty`;
+ALTER TABLE `zh_stage_pos_12`
+ADD COLUMN `qc_minus_qty`  decimal(24,8) NOT NULL DEFAULT 0 COMMENT '计量不计价变更' AFTER `qc_qty`;
+ALTER TABLE `zh_stage_pos_13`
+ADD COLUMN `qc_minus_qty`  decimal(24,8) NOT NULL DEFAULT 0 COMMENT '计量不计价变更' AFTER `qc_qty`;
+ALTER TABLE `zh_stage_pos_14`
+ADD COLUMN `qc_minus_qty`  decimal(24,8) NOT NULL DEFAULT 0 COMMENT '计量不计价变更' AFTER `qc_qty`;
+ALTER TABLE `zh_stage_pos_15`
+ADD COLUMN `qc_minus_qty`  decimal(24,8) NOT NULL DEFAULT 0 COMMENT '计量不计价变更' AFTER `qc_qty`;
+ALTER TABLE `zh_stage_pos_16`
+ADD COLUMN `qc_minus_qty`  decimal(24,8) NOT NULL DEFAULT 0 COMMENT '计量不计价变更' AFTER `qc_qty`;
+ALTER TABLE `zh_stage_pos_17`
+ADD COLUMN `qc_minus_qty`  decimal(24,8) NOT NULL DEFAULT 0 COMMENT '计量不计价变更' AFTER `qc_qty`;
+ALTER TABLE `zh_stage_pos_18`
+ADD COLUMN `qc_minus_qty`  decimal(24,8) NOT NULL DEFAULT 0 COMMENT '计量不计价变更' AFTER `qc_qty`;
+ALTER TABLE `zh_stage_pos_19`
+ADD COLUMN `qc_minus_qty`  decimal(24,8) NOT NULL DEFAULT 0 COMMENT '计量不计价变更' AFTER `qc_qty`;
+
+
+ALTER TABLE `zh_stage_pos_final_0`
+ADD COLUMN `qc_minus_qty`  decimal(24,8) NOT NULL DEFAULT 0 COMMENT '计量不计价变更' AFTER `qc_qty`;
+ALTER TABLE `zh_stage_pos_final_1`
+ADD COLUMN `qc_minus_qty`  decimal(24,8) NOT NULL DEFAULT 0 COMMENT '计量不计价变更' AFTER `qc_qty`;
+ALTER TABLE `zh_stage_pos_final_2`
+ADD COLUMN `qc_minus_qty`  decimal(24,8) NOT NULL DEFAULT 0 COMMENT '计量不计价变更' AFTER `qc_qty`;
+ALTER TABLE `zh_stage_pos_final_3`
+ADD COLUMN `qc_minus_qty`  decimal(24,8) NOT NULL DEFAULT 0 COMMENT '计量不计价变更' AFTER `qc_qty`;
+ALTER TABLE `zh_stage_pos_final_4`
+ADD COLUMN `qc_minus_qty`  decimal(24,8) NOT NULL DEFAULT 0 COMMENT '计量不计价变更' AFTER `qc_qty`;
+ALTER TABLE `zh_stage_pos_final_5`
+ADD COLUMN `qc_minus_qty`  decimal(24,8) NOT NULL DEFAULT 0 COMMENT '计量不计价变更' AFTER `qc_qty`;
+ALTER TABLE `zh_stage_pos_final_6`
+ADD COLUMN `qc_minus_qty`  decimal(24,8) NOT NULL DEFAULT 0 COMMENT '计量不计价变更' AFTER `qc_qty`;
+ALTER TABLE `zh_stage_pos_final_7`
+ADD COLUMN `qc_minus_qty`  decimal(24,8) NOT NULL DEFAULT 0 COMMENT '计量不计价变更' AFTER `qc_qty`;
+ALTER TABLE `zh_stage_pos_final_8`
+ADD COLUMN `qc_minus_qty`  decimal(24,8) NOT NULL DEFAULT 0 COMMENT '计量不计价变更' AFTER `qc_qty`;
+ALTER TABLE `zh_stage_pos_final_9`
+ADD COLUMN `qc_minus_qty`  decimal(24,8) NOT NULL DEFAULT 0 COMMENT '计量不计价变更' AFTER `qc_qty`;
+ALTER TABLE `zh_stage_pos_final_10`
+ADD COLUMN `qc_minus_qty`  decimal(24,8) NOT NULL DEFAULT 0 COMMENT '计量不计价变更' AFTER `qc_qty`;
+ALTER TABLE `zh_stage_pos_final_11`
+ADD COLUMN `qc_minus_qty`  decimal(24,8) NOT NULL DEFAULT 0 COMMENT '计量不计价变更' AFTER `qc_qty`;
+ALTER TABLE `zh_stage_pos_final_12`
+ADD COLUMN `qc_minus_qty`  decimal(24,8) NOT NULL DEFAULT 0 COMMENT '计量不计价变更' AFTER `qc_qty`;
+ALTER TABLE `zh_stage_pos_final_13`
+ADD COLUMN `qc_minus_qty`  decimal(24,8) NOT NULL DEFAULT 0 COMMENT '计量不计价变更' AFTER `qc_qty`;
+ALTER TABLE `zh_stage_pos_final_14`
+ADD COLUMN `qc_minus_qty`  decimal(24,8) NOT NULL DEFAULT 0 COMMENT '计量不计价变更' AFTER `qc_qty`;
+ALTER TABLE `zh_stage_pos_final_15`
+ADD COLUMN `qc_minus_qty`  decimal(24,8) NOT NULL DEFAULT 0 COMMENT '计量不计价变更' AFTER `qc_qty`;
+ALTER TABLE `zh_stage_pos_final_16`
+ADD COLUMN `qc_minus_qty`  decimal(24,8) NOT NULL DEFAULT 0 COMMENT '计量不计价变更' AFTER `qc_qty`;
+ALTER TABLE `zh_stage_pos_final_17`
+ADD COLUMN `qc_minus_qty`  decimal(24,8) NOT NULL DEFAULT 0 COMMENT '计量不计价变更' AFTER `qc_qty`;
+ALTER TABLE `zh_stage_pos_final_18`
+ADD COLUMN `qc_minus_qty`  decimal(24,8) NOT NULL DEFAULT 0 COMMENT '计量不计价变更' AFTER `qc_qty`;
+ALTER TABLE `zh_stage_pos_final_19`
+ADD COLUMN `qc_minus_qty`  decimal(24,8) NOT NULL DEFAULT 0 COMMENT '计量不计价变更' AFTER `qc_qty`;
+
+ALTER TABLE `zh_stage_change`
+ADD COLUMN `no_value`  tinyint(4) UNSIGNED NOT NULL DEFAULT 0 COMMENT '是否不计价' AFTER `minus`;
+ALTER TABLE `zh_stage_change_final`
+ADD COLUMN `no_value`  tinyint(4) UNSIGNED NOT NULL DEFAULT 0 COMMENT '是否不计价' AFTER `minus`;
+ALTER TABLE `zh_stage_detail`
+ADD COLUMN `no_value`  tinyint(4) UNSIGNED NOT NULL DEFAULT 0 COMMENT '计量不计价' AFTER `unit_price`;