Browse Source

Merge branch 'dev' of http://192.168.1.41:3000/maixinrong/Calculation into dev

Tony Kang 3 years ago
parent
commit
8f87a1ed4d
58 changed files with 1025 additions and 453 deletions
  1. 2 0
      app/const/deal_pay.js
  2. 7 9
      app/const/spread.js
  3. 2 0
      app/const/tender_info.js
  4. 14 1
      app/controller/change_controller.js
  5. 3 3
      app/controller/ledger_controller.js
  6. 2 2
      app/controller/material_controller.js
  7. 1 1
      app/controller/revise_controller.js
  8. 14 19
      app/controller/stage_controller.js
  9. 4 1
      app/controller/wap_controller.js
  10. 28 3
      app/extend/helper.js
  11. 1 2
      app/lib/analysis_excel.js
  12. 2 2
      app/lib/ledger.js
  13. 2 1
      app/public/css/main.css
  14. BIN
      app/public/images/nulllogo.png
  15. 183 2
      app/public/js/change_information.js
  16. 15 15
      app/public/js/change_information_approval.js
  17. 71 16
      app/public/js/change_information_set.js
  18. 2 2
      app/public/js/change_information_show.js
  19. 5 3
      app/public/js/gcl_gather.js
  20. 4 0
      app/public/js/global.js
  21. 4 2
      app/public/js/ledger_check.js
  22. 2 0
      app/public/js/material.js
  23. 2 0
      app/public/js/material_exponent.js
  24. 17 7
      app/public/js/material_list.js
  25. 2 2
      app/public/js/measure_material.js
  26. 14 36
      app/public/js/stage.js
  27. 4 1
      app/public/js/stage_bwtz.js
  28. 10 4
      app/service/change.js
  29. 4 2
      app/service/ledger.js
  30. 4 0
      app/service/ledger_history.js
  31. 1 1
      app/service/material.js
  32. 2 2
      app/service/material_list.js
  33. 1 1
      app/service/material_list_self.js
  34. 63 29
      app/service/report_memory.js
  35. 5 0
      app/service/stage.js
  36. 4 3
      app/service/stage_audit.js
  37. 43 46
      app/service/stage_bills_final.js
  38. 18 23
      app/service/stage_change.js
  39. 2 2
      app/service/stage_change_final.js
  40. 35 39
      app/service/stage_pos_final.js
  41. 19 12
      app/service/stage_stash.js
  42. 20 3
      app/view/change/information.ejs
  43. 17 1
      app/view/change/information_modal.ejs
  44. 1 1
      app/view/change/project_information_modal.ejs
  45. 102 34
      app/view/dashboard/index.ejs
  46. 18 0
      app/view/material/list_modal.ejs
  47. 2 2
      app/view/stage/bwtz.ejs
  48. 1 1
      app/view/stage/index.ejs
  49. 1 1
      app/view/stage/pay_modal.ejs
  50. 6 0
      app/view/tender/detail_modal.ejs
  51. 1 1
      app/view/tender/manage_modal.ejs
  52. 1 1
      app/view/wap/dashboard.ejs
  53. 16 0
      builder_report_index_define.js
  54. 1 1
      config/config.default.js
  55. 1 1
      config/config.uat.js
  56. 82 0
      db_script/ledger_his_count.js
  57. 3 112
      sql/update.sql
  58. 134 0
      sql/update20220624.sql

+ 2 - 0
app/const/deal_pay.js

@@ -68,6 +68,8 @@ const chapterDetail = [
     {name: '清单 第500章 隧道', cType: 1, serialNo: 5, filter: '^[^0-9]*5[0-9]{2}(-|$)'},
     {name: '清单 第600章 安全设施及预埋管线', cType: 1, serialNo: 6, filter: '^[^0-9]*6[0-9]{2}(-|$)'},
     {name: '清单 第700章 绿化及环境保护', cType: 1, serialNo: 7, filter: '^[^0-9]*7[0-9]{2}(-|$)'},
+    {name: '清单 第800章 机电工程', cType: 1, serialNo: 6, filter: '^[^0-9]*8[0-9]{2}(-|$)'},
+    {name: '清单 第900章 房建工程', cType: 1, serialNo: 7, filter: '^[^0-9]*9[0-9]{2}(-|$)'},
     {name: '未计入章节清单合计', cType: 21, serialNo: 8},
     {name: '清单小计(A)', cType: 11, serialNo: 9},
     {name: '非清单项费用(B)', cType: 31, serialNo: 10},

+ 7 - 9
app/const/spread.js

@@ -203,10 +203,9 @@ const stageTz = {
             {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'end_contract_tp', hAlign: 2, width: 60, readOnly: true, type: 'Number'},
             {title: '截止本期数量变更|数量', colSpan: '2|1', rowSpan: '1|1', field: 'end_qc_qty', hAlign: 2, width: 60, readOnly: true, type: 'Number'},
             {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'end_qc_tp', hAlign: 2, width: 60, readOnly: true, type: 'Number'},
-            {title: '截止本期完成计量|数量', colSpan: '4|1', rowSpan: '1|1', field: 'end_gather_qty', 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: '|1#完成率(%)', colSpan: '1', rowSpan: '|1', field: 'end_gather_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'},
@@ -282,10 +281,9 @@ const stageCl = {
             {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'end_contract_tp', hAlign: 2, width: 60, readOnly: true, type: 'Number'},
             {title: '截止本期数量变更|数量', colSpan: '2|1', rowSpan: '1|1', field: 'end_qc_qty', hAlign: 2, width: 60, readOnly: true, type: 'Number'},
             {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'end_qc_tp', hAlign: 2, width: 60, readOnly: true, type: 'Number'},
-            {title: '截止本期完成计量|数量', colSpan: '4|1', rowSpan: '1|1', field: 'end_gather_qty', 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: '|1#完成率(%)', colSpan: '1', rowSpan: '|1', field: 'end_gather_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'},
@@ -360,10 +358,9 @@ const stageNoCl = {
             {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'end_contract_tp', hAlign: 2, width: 60, readOnly: true, type: 'Number'},
             {title: '截止本期数量变更|数量', colSpan: '2|1', rowSpan: '1|1', field: 'end_qc_qty', hAlign: 2, width: 60, readOnly: true, type: 'Number'},
             {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'end_qc_tp', hAlign: 2, width: 60, readOnly: true, type: 'Number'},
-            {title: '截止本期完成计量|数量', colSpan: '4|1', rowSpan: '1|1', field: 'end_gather_qty', 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: '|1#完成率(%)', colSpan: '1', rowSpan: '|1', field: 'end_gather_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'},
@@ -439,9 +436,10 @@ 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, readOnly: true, type: 'Number'},
-            {title: '台账+变更令|数量', colSpan: '2|1', rowSpan: '1|1', field: 'final_qty', hAlign: 2, width: 60, type: 'Number'},
+            {title: '|完成率(%)', colSpan: '|1', rowSpan: '|1', field: 'end_gather_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'},
         ],
         emptyRows: 0,
         headRows: 2,
@@ -462,7 +460,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, readOnly: true, type: 'Number'},
+            {title: '|完成率(%)', colSpan: '1', rowSpan: '|1', field: 'end_gather_percent', hAlign: 2, width: 80, type: 'Number'},
             {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: '@'},

+ 2 - 0
app/const/tender_info.js

@@ -139,6 +139,7 @@ const defaultInfo = {
             rate: '',
             contact: '',
             phone: '',
+            num: '',
         },
         worker: {
             name: '',
@@ -147,6 +148,7 @@ const defaultInfo = {
             rate: '',
             contact: '',
             phone: '',
+            num: '',
         },
     },
     shenpi: {

+ 14 - 1
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,
@@ -763,7 +776,7 @@ module.exports = app => {
                     return item.qty !== null;
                 })
                 renderData.changeUsedData = changeUsedData;
-                renderData.stageChangeNum = this.ctx.helper.sum(changeUsedData.map(x => { return Math.abs(x.used_qty); }));
+                renderData.stageChangeNum = this.ctx.helper.sum(changeUsedData.map(x => { return Math.abs(x.qty); }));
                 await this.layout('change/information.ejs', renderData, 'change/information_modal.ejs');
             } catch (err) {
                 this.log(err);

+ 3 - 3
app/controller/ledger_controller.js

@@ -116,12 +116,12 @@ module.exports = app => {
             const ledgerColumn = [
                 'id', 'tender_id', 'ledger_id', 'ledger_pid', 'level', 'order', 'full_path', 'is_leaf',
                 'code', 'b_code', 'name', 'unit', 'unit_price', 'quantity', 'total_price',
-                'sgfh_qty', 'sgfh_expr', 'sgfh_tp', 'memo', 'drawing_code'];
+                'sgfh_qty', 'sgfh_expr', 'sgfh_tp', 'memo', 'drawing_code', 'node_type'];
             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');
             if (tender.info.display.ledger.clQty) ledgerColumn.push('sjcl_qty', 'qtcl_qty', 'sjcl_expr', 'qtcl_expr', 'sjcl_tp', 'qtcl_tp');
-            const posColumn = ['id', 'tid', 'lid', 'name', 'position', 'porder', 'sgfh_qty', 'sgfh_expr', 'add_stage_order', 'drawing_code'];
-            if (tender.info.display.ledger.clQty) posColumn.push('sjcl_qty', 'qtcl_qty', 'sjcl_expr', 'qtcl_expr', 'quantity');
+            const posColumn = ['id', 'tid', 'lid', 'name', 'position', 'porder', 'sgfh_qty', 'sgfh_expr', 'add_stage_order', 'drawing_code', 'quantity'];
+            if (tender.info.display.ledger.clQty) posColumn.push('sjcl_qty', 'qtcl_qty', 'sjcl_expr', 'qtcl_expr');
             for (const field of sjsRela.ledgerCol) {
                 if (field.show) {
                     ledgerColumn.push(field.field);

+ 2 - 2
app/controller/material_controller.js

@@ -766,7 +766,7 @@ module.exports = app => {
                         responseData.data = await ctx.service.materialListSelf.add(data.select);
                         break;
                     case 'noself':
-                        await ctx.service.materialListSelf.del(data.select.id);
+                        responseData.data = await ctx.service.materialListSelf.del(data.select.id);
                         break;
                     case 'paste':
                         await ctx.service.materialList.saveDatas(data.updateData);
@@ -1471,7 +1471,7 @@ module.exports = app => {
                         responseData.data = await ctx.service.materialList.adds(data.postData, data.checklist);
                         break;
                     case 'dels':
-                        responseData.data = await ctx.service.materialList.dels(data.postData, data.checklist);
+                        responseData.data = await ctx.service.materialList.dels(data.postData, data.checklist, true);
                         break;
                     case 'updates':
                         if (data.updateData.quantity === '' || data.updateData.quantity === null) {

+ 1 - 1
app/controller/revise_controller.js

@@ -66,7 +66,7 @@ module.exports = app => {
                 if (changeLedgerList.length > 0 || changePosList.length > 0) {
                     // 判断审批中的变更令是否有调用了新增部位,有则无法新增修订,都没有则可新增修订
                     for (const c of changeList) {
-                        const caList = await ctx.service.changeAuditList.getList(c.cid);
+                        const caList = await ctx.service.changeAuditList.getList(c.cid, 0);
                         const gclIdList = ctx.helper._.uniq(ctx.helper._.map(caList, 'gcl_id'));
                         for (const gcl of gclIdList) {
                             if (gcl && (ctx.helper._.findIndex(changeLedgerList, { id: gcl }) !== -1 || ctx.helper._.findIndex(changePosList, { lid: gcl }) !== -1)) {

+ 14 - 19
app/controller/stage_controller.js

@@ -226,7 +226,7 @@ module.exports = app => {
             const 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'];
+                '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');
@@ -249,9 +249,10 @@ module.exports = app => {
             // 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 = 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 } });
             const dgnData = await ctx.service.stageBillsDgn.getDgnData(ctx.tender.id);
             const importData = await ctx.service.stageImportChange.getImportLid(ctx.stage.id);
             let curStageData;
@@ -277,9 +278,10 @@ module.exports = app => {
         }
         async _getStagePosData(ctx, posColumn) {
             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 =  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 } });
             // 根据当前人,或指定对象查询数据
             if (ctx.stage.readOnly) {
                 curStageData = await ctx.service.stagePos.getAuditorStageData2(ctx.tender.id,
@@ -350,9 +352,6 @@ module.exports = app => {
                         case 'changeBills':
                             responseData.data.changeBills = await this.ctx.service.changeAuditList.checkedChangeBills(ctx.stage.tid);
                             break;
-                        case 'minus_change':
-                            responseData.data.minus_change = await this.ctx.service.stageChangeFinal.getPreMinusChange(ctx.stage.tid, ctx.stage.order);
-                            break;
                         case 'import_change':
                             responseData.data.import_change = await this.ctx.service.stageImportChange.getStageImportData(this.ctx.stage);
                             break;
@@ -527,22 +526,18 @@ module.exports = app => {
                 if (!data.target || (!data.target.bills && !data.target.pos) || !data.change) {
                     throw '调用变更令数据错误';
                 }
-                let result, minus;
+                let result, minus, posMinus;
                 if (data.target.pos) {
                     result = await ctx.service.stageChange.posChange(data.target.pos, 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);
-                    minus = await this.ctx.service.stageChange.getBillsMinusQty(ctx.stage, data.target.pos.lid);
                 } else {
                     result = await ctx.service.stageChange.billsChange(data.target.bills, 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');
-                    minus = await this.ctx.service.stageChange.getBillsMinusQty(ctx.stage, data.target.bills.id);
                 }
-                const bills = result.bills.curStageData.find(x => { return x.lid === minus.lid });
-                if (bills) bills.minus_qc_qty = minus.qty;
                 await ctx.service.stage.updateCheckCalcFlag(ctx.stage, true);
                 await ctx.service.stage.updateCacheTime(ctx.stage.id);
                 ctx.body = { err: 0, msg: '', data: result };
@@ -1000,10 +995,11 @@ module.exports = app => {
                     switch (cd.cType) {
                         case 1:
                             const tp = await ctx.service.stageBills.getSumTotalPriceGcl(ctx.stage, cd.filter);
-                            assignStageData(cd, tp);
+                            const preTp = await ctx.service.stageBillsFinal.getSumTotalPriceGcl(ctx.stage.tid, ctx.stage.order - 1, cd.filter);
+                            assignStageData(cd, tp, preTp);
                             break;
                         case 11:
-                            assignStageData(cd, await ctx.service.stageBills.getSumTotalPriceGcl(ctx.stage));
+                            assignStageData(cd, await ctx.service.stageBills.getSumTotalPriceGcl(ctx.stage), await ctx.service.stageBillsFinal.getSumTotalPriceGcl(ctx.stage.tid, ctx.stage.order - 1));
                             break;
                         case 21:
                             const sum = _.find(calcDetail, { cType: 11 });
@@ -1013,7 +1009,7 @@ module.exports = app => {
                             }
                             break;
                         case 31:
-                            assignStageData(cd, await ctx.service.stageBills.getSumTotalPriceNotGcl(ctx.stage));
+                            assignStageData(cd, await ctx.service.stageBills.getSumTotalPriceNotGcl(ctx.stage), await ctx.service.stageBillsFinal.getSumTotalPriceNotGcl(ctx.stage.tid, ctx.stage.order - 1));
                             break;
                         case 41:
                             const sum1 = _.find(calcDetail, { cType: 11 });
@@ -1492,7 +1488,6 @@ module.exports = app => {
                     const filepath = `app/public/upload/${this.ctx.tender.id}/stage/fujian_${create_time + index.toString() + fileInfo.ext}`;
                     // await ctx.helper.saveStreamFile(stream, path.resolve(this.app.baseDir, filepath));
                     await ctx.app.fujianOss.put(ctx.app.config.fujianOssFolder + filepath, stream);
-                    // console.log(await fs.existsSync(path.resolve(this.app.baseDir, 'app', filepath)));
                     // const fileInfo = path.parse(stream.filename);
                     // const fileName = 'stage' + create_time + '_' + index + fileInfo.ext;
                     // 保存文件

+ 4 - 1
app/controller/wap_controller.js

@@ -120,7 +120,10 @@ module.exports = app => {
             // 获取待审批的期
             const auditStages = await ctx.service.stageAudit.getAuditStageByWap(ctx.session.sessionUser.accountId);
             for (const audit of auditStages) {
-                await this.ctx.service.stage.checkStageGatherData(audit);
+                if (audit.status !== auditConst.stage.status.uncheck) {
+                    const isLastage = await ctx.service.stage.isLastStage(audit.tid, audit.id);
+                    if (isLastage) await this.ctx.service.stage.checkStageGatherData(audit);
+                }
                 audit.gather_tp = ctx.helper.add(audit.contract_tp, audit.qc_tp);
                 audit.end_contract_tp = ctx.helper.add(audit.contract_tp, audit.pre_contract_tp);
                 audit.end_qc_tp = ctx.helper.add(audit.qc_tp, audit.pre_qc_tp);

+ 28 - 3
app/extend/helper.js

@@ -847,6 +847,34 @@ module.exports = {
             loadFields(r.data, r.fields, r.prefix, r.relaId);
         }
     },
+    /**
+     * 合并(并汇总) 相关数据
+     * @param {Array} main - 主数据
+     * @param {Array[]}rela - 相关数据 {data, fields, relaField}
+     *
+     * { data, fields}
+     */
+    assignSumRelaData(main, keyField, rela) {
+        const index = {},
+            indexPre = 'id_';
+        const addFun = this.add;
+        const loadFields = function(datas, fields, relaId) {
+            for (const d of datas) {
+                const key = indexPre + d[relaId];
+                const m = index[key];
+                if (!m) continue;
+                for (const f of fields) {
+                    if (d[f.source]) m[f.target] = addFun(m[f.target], d[f.source]);
+                }
+            }
+        };
+        for (const m of main) {
+            index[indexPre + m[keyField]] = m;
+        }
+        for (const r of rela) {
+            loadFields(r.data, r.fields, r.relaField);
+        }
+    },
 
     whereSql(where, as) {
         if (!where) {
@@ -1460,9 +1488,6 @@ module.exports = {
     },
 
     getStartEndMonth(month) {
-        // month = new Date('2021-10-03');
-        // const startMonth = new Date(month.getFullYear(), month.getMonth(), 1);
-        // const endMonth = new Date(month.getFullYear(), month.getMonth() + 1, 1);
         const startMonth = moment(month).startOf('month').format('YYYY-MM-DD HH:mm:ss');
         const endMonth = moment(month).endOf('month').format('YYYY-MM-DD HH:mm:ss');
         return [startMonth, endMonth];

+ 1 - 2
app/lib/analysis_excel.js

@@ -548,8 +548,7 @@ class AnalysisExcelTree {
             node.unit = this.ctx.helper.replaceReturn(row[this.colsDef.unit]);
             node.dgn_qty1 = aeUtils.toNumber(row[this.colsDef.dgn_qty1]);
             node.dgn_qty2 = aeUtils.toNumber(row[this.colsDef.dgn_qty2]);
-            // 2022-6-9 曾沛文要求不导入金额
-            //node.total_price = this.ctx.helper.round(aeUtils.toNumber(row[this.colsDef.total_price]), this.decimal.tp);
+            node.total_price = this.ctx.helper.round(aeUtils.toNumber(row[this.colsDef.total_price]), this.decimal.tp);
             node.drawing_code = this.ctx.helper.replaceReturn(row[this.colsDef.drawing_code]);
             node.memo = this.ctx.helper.replaceReturn(row[this.colsDef.memo]);
             return this.cacheTree.addXmjNode(node);

+ 2 - 2
app/lib/ledger.js

@@ -270,7 +270,7 @@ class baseTree {
         if (fun) {
             fun(node);
         } else if (this.setting.calc) {
-            this.setting.calc(node, this.ctx.helper);
+            this.setting.calc(node, this.ctx.helper, this.ctx.tender.info.decimal);
         }
     }
     calculateAll(fun) {
@@ -616,7 +616,7 @@ class checkData {
             if (ratio === 0) {
                 if (!data.contract_tp && !data.pre_contract_tp) return 2; // 漏计
             } else {
-                const tp = this.ctx.helper.mul(data.total_price, this.ctx.helper.div(ratio, 100, 4), this.ctx.tender.info.decimal.tp);
+                const tp = this.ctx.helper.mul(data.final_1_tp, this.ctx.helper.div(ratio, 100, 4), this.ctx.tender.info.decimal.tp);
                 const checkTp = this.ctx.helper.add(data.contract_tp, data.pre_contract_tp);
                 if (tp > checkTp) return 1; // 违规
                 if (tp < checkTp) return 2; // 漏计

+ 2 - 1
app/public/css/main.css

@@ -1055,7 +1055,8 @@ label{
   font-size:100%;
 }
 .modal-header{
-  padding:.5rem 1rem
+  padding:.5rem 1rem;
+  cursor: move;
 }
 .modal-title{
   font-size:16px;

BIN
app/public/images/nulllogo.png


+ 183 - 2
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();
@@ -21,7 +74,7 @@ $(document).ready(() => {
     if (cca !== null && cca !== undefined) {
         $('#customCheck1').prop('checked', cca !== 'false');
     }
-    changeSpreadSheet.setColumnVisible(2,$('#customCheck1').is(':checked'), GC.Spread.Sheets.SheetArea.viewport);
+    changeSpreadSheet.setColumnVisible(5,$('#customCheck1').is(':checked'), GC.Spread.Sheets.SheetArea.viewport);
     // 变更详情展示和隐藏
     $('.change-detail-checkbox').on('click', function (e) {
         if($(e.target).is('label')){
@@ -29,7 +82,7 @@ $(document).ready(() => {
         }
         // // 设置用户项目本地记录展示和隐藏情况
         setLocalCache('change-checkbox-account-'+ accountId, $(this).is(':checked'));
-        changeSpreadSheet.setColumnVisible(2,$(this).is(':checked'), GC.Spread.Sheets.SheetArea.viewport);
+        changeSpreadSheet.setColumnVisible(5,$(this).is(':checked'), GC.Spread.Sheets.SheetArea.viewport);
     });
 
     // 计算最新的变更总额和change的total_price是否一致,不一致则更新
@@ -236,6 +289,134 @@ $(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();
+            console.log();
+            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);
+                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',

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

@@ -21,10 +21,10 @@ $(document).ready(() => {
         cols: [
             {title: '清单编号', colSpan: '1', rowSpan: '2', field: 'code', hAlign: 0, width: 80, formatter: '@', readOnly: true},
             {title: '名称', colSpan: '1', rowSpan: '2', field: 'name', hAlign: 0, width: 120, formatter: '@', readOnly: true},
-            {title: '变更详情', colSpan: '1', rowSpan: '2', field: 'detail', hAlign: 0, width: 120, formatter: '@', readOnly: true},
             {title: '单位', colSpan: '1', rowSpan: '2', field: 'unit', hAlign: 1, width: 60, formatter: '@', readOnly: true},
             {title: '单价', colSpan: '1', rowSpan: '2', field: 'unit_price', hAlign: 2, width: 60, type: 'Number', getValue: 'getValue.unit_price', readOnly: true},
             {title: '变更部位', colSpan: '1', rowSpan: '2', field: 'bwmx', hAlign: 0, width: 120, formatter: '@', readOnly: true},
+            {title: '变更详情', colSpan: '1', rowSpan: '2', field: 'detail', hAlign: 0, width: 120, formatter: '@', readOnly: true},
             {title: '原设计|数量', colSpan: '2|1', rowSpan: '1|1', field: 'oamount', hAlign: 2, width: 60, type: 'Number', getValue: 'getValue.oamount', readOnly: true},
             {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'oa_tp', hAlign: 2, width: 80, type: 'Number', getValue: 'getValue.oa_tp', readOnly: true},
             {title: '申请变更增(+)减(-)|数量', colSpan: '2|1', rowSpan: '1|1', field: 'camount', hAlign: 2, width: 60, type: 'Number', getValue: 'getValue.camount', readOnly: true},
@@ -201,13 +201,13 @@ $(document).ready(() => {
                     validText = ZhCalc.round(validText, findDecimal(select.unit)) || 0;
                     // 判断是否 正数必须大于等于限制值,负数必须小于等于限制值,否则无法更改
                     const usedInfo = _.find(changeUsedData, { id: select.id });
-                    if (usedInfo && validText >= 0 && validText < usedInfo.used_qty) {
-                        toastr.error('清单变更数值必须大于等于已调用值 ' + usedInfo.used_qty);
+                    if (usedInfo && validText >= 0 && validText < usedInfo.qty) {
+                        toastr.error('清单变更数值必须大于等于已调用值 ' + usedInfo.qty);
                         SpreadJsObj.reLoadRowData(info.sheet, info.row);
                         changeSpreadObj.setRowValueAndSum(select, info.row, info.col);
                         return;
-                    } else if (usedInfo && validText < 0 && validText > usedInfo.used_qty) {
-                        toastr.error('清单变更数值必须小于等于已调用值 ' + usedInfo.used_qty);
+                    } else if (usedInfo && validText < 0 && validText > usedInfo.qty) {
+                        toastr.error('清单变更数值必须小于等于已调用值 ' + usedInfo.qty);
                         SpreadJsObj.reLoadRowData(info.sheet, info.row);
                         changeSpreadObj.setRowValueAndSum(select, info.row, info.col);
                         return;
@@ -294,14 +294,14 @@ $(document).ready(() => {
                         validText = ZhCalc.round(validText, findDecimal(sortData[curRow].unit)) || 0;
                         // 判断是否 正数必须大于等于限制值,负数必须小于等于限制值,否则无法更改
                         const usedInfo = _.find(changeUsedData, { id: sortData[curRow].id });
-                        if (usedInfo && usedInfo.used_qty >= 0 && validText < usedInfo.used_qty) {
-                            toastr.error(hintRow ? '清单' + (hintRow+1) + '行变更数值必须大于等于已调用值 ' + usedInfo.used_qty : '清单变更数值必须大于等于已调用值 ' + usedInfo.used_qty);
+                        if (usedInfo && usedInfo.qty >= 0 && validText < usedInfo.qty) {
+                            toastr.error(hintRow ? '清单' + (hintRow+1) + '行变更数值必须大于等于已调用值 ' + usedInfo.qty : '清单变更数值必须大于等于已调用值 ' + usedInfo.qty);
                             SpreadJsObj.reLoadRowData(info.sheet, curRow);
                             changeSpreadObj.setRowValueAndSum(sortData[curRow], curRow, curCol);
                             bPaste = false;
                             continue;
-                        } else if (usedInfo && usedInfo.used_qty < 0 && validText > usedInfo.used_qty) {
-                            toastr.error(hintRow ? '清单' + (hintRow+1) + '行变更数值必须小于等于已调用值 ' + usedInfo.used_qty : '清单变更数值必须小于等于已调用值 ' + usedInfo.used_qty);
+                        } else if (usedInfo && usedInfo.qty < 0 && validText > usedInfo.qty) {
+                            toastr.error(hintRow ? '清单' + (hintRow+1) + '行变更数值必须小于等于已调用值 ' + usedInfo.qty : '清单变更数值必须小于等于已调用值 ' + usedInfo.qty);
                             SpreadJsObj.reLoadRowData(info.sheet, curRow);
                             changeSpreadObj.setRowValueAndSum(sortData[curRow], curRow, curCol);
                             bPaste = false;
@@ -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(','));
 

+ 71 - 16
app/public/js/change_information_set.js

@@ -96,10 +96,10 @@ $(document).ready(() => {
         cols: [
             {title: '清单编号', colSpan: '1', rowSpan: '2', field: 'code', hAlign: 0, width: 80, formatter: '@', readOnly: 'readOnly.isEdit2'},
             {title: '名称', colSpan: '1', rowSpan: '2', field: 'name', hAlign: 0, width: 120, formatter: '@', readOnly: 'readOnly.isEdit2'},
-            {title: '变更详情', colSpan: '1', rowSpan: '2', field: 'detail', hAlign: 0, width: 120, formatter: '@', readOnly: false},
             {title: '单位', colSpan: '1', rowSpan: '2', field: 'unit', hAlign: 1, width: 60, formatter: '@', readOnly: 'readOnly.isEdit2', cellType: 'unit', comboItems: changeUnits, comboEdit: true},
             {title: '单价', colSpan: '1', rowSpan: '2', field: 'unit_price', hAlign: 2, width: 60, type: 'Number', readOnly: 'readOnly.isEdit2', getValue: 'getValue.unit_price'},
             {title: '变更部位', colSpan: '1', rowSpan: '2', field: 'bwmx', hAlign: 0, width: 120, formatter: '@', readOnly: 'readOnly.isEdit2'},
+            {title: '变更详情', colSpan: '1', rowSpan: '2', field: 'detail', hAlign: 0, width: 120, formatter: '@', readOnly: false},
             {title: '原设计|数量', colSpan: '2|1', rowSpan: '1|1', field: 'oamount', hAlign: 2, width: 60, type: 'Number', readOnly: 'readOnly.isEdit', getValue: 'getValue.oamount'},
             {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'oa_tp', hAlign: 2, width: 80, type: 'Number', readOnly: true, getValue: 'getValue.oa_tp'},
             {title: '申请变更增(+)减(-)|数量', colSpan: '2|1', rowSpan: '1|1', field: 'camount', hAlign: 2, width: 60, type: 'Number', readOnly: false, getValue: 'getValue.camount'},
@@ -384,7 +384,7 @@ $(document).ready(() => {
             const sel = info.sheet.getSelections()[0];
             const col = info.sheet.zh_setting.cols[sel.col];
             const data = SpreadJsObj.getSelectObject(info.sheet);
-            if (col && col.field === 'del_list' && !_.find(changeUsedData, { cbid: data.id })) {
+            if (col && col.field === 'del_list' && data && !_.find(changeUsedData, { cbid: data.id })) {
                 changeSpreadObj.del();
             }
             changeSpreadObj.resetXmjSpread(data);
@@ -456,12 +456,12 @@ $(document).ready(() => {
                 if(col.field === 'camount') {
                     // 判断是否 正数必须大于等于限制值,负数必须小于等于限制值,否则无法更改
                     const usedInfo = _.find(changeUsedData, { cbid: select.id });
-                    if (usedInfo && usedInfo.used_qty >= 0 && validText < usedInfo.used_qty) {
-                        toastr.error('清单变更数值必须大于等于已调用值 ' + usedInfo.used_qty);
+                    if (usedInfo && usedInfo.qty >= 0 && validText < usedInfo.qty) {
+                        toastr.error('清单变更数值必须大于等于已调用值 ' + usedInfo.qty);
                         SpreadJsObj.reLoadRowData(info.sheet, info.row);
                         return;
-                    } else if (usedInfo && usedInfo.used_qty < 0  && validText > usedInfo.used_qty) {
-                        toastr.error('清单变更数值必须小于等于已调用值 ' + usedInfo.used_qty);
+                    } else if (usedInfo && usedInfo.qty < 0  && validText > usedInfo.qty) {
+                        toastr.error('清单变更数值必须小于等于已调用值 ' + usedInfo.qty);
                         SpreadJsObj.reLoadRowData(info.sheet, info.row);
                         return;
                     }
@@ -509,6 +509,8 @@ $(document).ready(() => {
             }
             const data = [];
             // const rowData = [];
+            let needCopyIgnore = !$('#customCheck1').is(':checked');
+            let needColAdd = false;
             for (let iRow = 0; iRow < range.rowCount; iRow++) {
                 let bPaste = true;
                 const curRow = range.row + iRow;
@@ -518,7 +520,12 @@ $(document).ready(() => {
                 let sameCol = 0;
                 for (let iCol = 0; iCol < range.colCount; iCol++) {
                     const curCol = range.col + iCol;
-                    const colSetting = info.sheet.zh_setting.cols[curCol];
+                    let colSetting = info.sheet.zh_setting.cols[curCol];
+                    if ((needColAdd && curCol > 5) || (needCopyIgnore && curCol === 5)) { // 要判断是否已隐藏了变更详情,是则变更详情后面的curCol要+1
+                        const newCurCol = curCol + 1;
+                        needColAdd = true;
+                        colSetting = info.sheet.zh_setting.cols[newCurCol];
+                    }
                     if (!colSetting) continue;
 
                     let validText = info.sheet.getText(curRow, curCol);
@@ -546,12 +553,12 @@ $(document).ready(() => {
                         if(colSetting.field === 'camount') {
                             // 判断是否 正数必须大于等于限制值,负数必须小于等于限制值,否则无法更改
                             const usedInfo = _.find(changeUsedData, { cbid: sortData[curRow].id });
-                            if (usedInfo && usedInfo.used_qty >= 0 && validText < usedInfo.used_qty) {
-                                toastr.error(hintRow ? '清单' + (hintRow+1) + '行变更数值必须大于等于已调用值 ' + usedInfo.used_qty : '清单变更数值必须大于等于已调用值 ' + usedInfo.used_qty);
+                            if (usedInfo && usedInfo.qty >= 0 && validText < usedInfo.qty) {
+                                toastr.error(hintRow ? '清单' + (hintRow+1) + '行变更数值必须大于等于已调用值 ' + usedInfo.qty : '清单变更数值必须大于等于已调用值 ' + usedInfo.qty);
                                 bPaste = false;
                                 continue;
-                            } else if (usedInfo && usedInfo.used_qty < 0 && validText > usedInfo.used_qty) {
-                                toastr.error(hintRow ? '清单' + (hintRow+1) + '行变更数值必须小于等于已调用值 ' + usedInfo.used_qty : '清单变更数值必须小于等于已调用值 ' + usedInfo.used_qty);
+                            } else if (usedInfo && usedInfo.qty < 0 && validText > usedInfo.qty) {
+                                toastr.error(hintRow ? '清单' + (hintRow+1) + '行变更数值必须小于等于已调用值 ' + usedInfo.qty : '清单变更数值必须小于等于已调用值 ' + usedInfo.qty);
                                 bPaste = false;
                                 continue;
                             }
@@ -566,8 +573,10 @@ $(document).ready(() => {
                         cLData.camount = ZhCalc.round(sortData[curRow].camount, findDecimal(unitdecimal)) || 0;
                         cLData.oamount = ZhCalc.round(sortData[curRow].oamount, findDecimal(unitdecimal)) || 0;
                     }
-                    cLData[colSetting.field] = validText;
-                    sortData[curRow][colSetting.field] = validText;
+                    if (colSetting.field !== 'oa_tp' && colSetting.field !== 'ca_tp') {
+                        cLData[colSetting.field] = validText;
+                        sortData[curRow][colSetting.field] = validText;
+                    }
                     cLData.spamount = ZhCalc.round(sortData[curRow].camount, findDecimal(unitdecimal)) || 0;
                 }
                 if (bPaste) {
@@ -716,7 +725,53 @@ $(document).ready(() => {
         changeSpread.bind(spreadNS.Events.ValueChanged, changeSpreadObj.valueChanged);
         SpreadJsObj.addDeleteBind(changeSpread, changeSpreadObj.deletePress);
         changeSpreadSheet.getCell(-1, 10).foreColor('#dc3545');
+        const delCommand = {
+            canUndo: false,
+            execute: function (context, options, isUndo) {
+                const Commands = GC.Spread.Sheets.Commands;
+                const sel = changeSpreadSheet.getSelections()[0];
+                const col = changeSpreadSheet.zh_setting.cols[sel.col];
+                if (col && col.field !== 'ca_tp') {
+                    isUndo = true;
+                }
+                if (isUndo) {
+                    Commands.undoTransaction(context, options);
+                    return true;
+                } else {
+                    Commands.startTransaction(context, options);
 
+                    Commands.endTransaction(context, options);
+                    return true;
+                }
+            }
+        };
+        const delCommand2 = {
+            canUndo: false,
+            execute: function (context, options, isUndo) {
+                const Commands = GC.Spread.Sheets.Commands;
+                const sel = changeSpreadSheet.getSelections()[0];
+                const col = changeSpreadSheet.zh_setting.cols[sel.col];
+                if (col && col.field !== 'del_list') {
+                    isUndo = true;
+                }
+                if (isUndo) {
+                    Commands.undoTransaction(context, options);
+                    return true;
+                } else {
+                    Commands.startTransaction(context, options);
+
+                    Commands.endTransaction(context, options);
+                    return true;
+                }
+            }
+        };
+        const commandManager = changeSpread.commandManager();
+        commandManager.register('banDel', delCommand);
+        commandManager.register('banDel2', delCommand2);
+        commandManager.register('banDel3', _.cloneDeep(delCommand2));// 不能共用banDel2
+        commandManager.setShortcutKey('banDel', 39, false, false, false, false);// 改写键盘右键,防止删除清单
+        commandManager.setShortcutKey('banDel2', 40, false, false, false, false);// 改写键盘下键,防止删除清单
+        commandManager.setShortcutKey('banDel3', 38, false, false, false, false);// 改写键盘上键,防止删除清单
         let batchInsertObj;
         $.contextMenu.types.batchInsert = function (item, opt, root) {
             const self = this;
@@ -1136,7 +1191,7 @@ $(document).ready(() => {
     $('#list-input').on('blur', function () {
         const select = parseInt($('#select-list').val());
         const value = _.trim($(this).val());
-        const valueList = _.slice(_.without(_.uniq(_.replace(value, /\t/g, ' ').split(' ')), ''), 0, 10);
+        const valueList = _.slice(_.without(_.uniq(_.replace(_.replace(value, /\'|\"/g, ''), /\t/g, ' ').split(' ')), ''), 0, 10);
         console.log(valueList);
         // 判断是否存在多个分词,以换行或空格分隔,多个则显示左侧菜单
         if (value !== '' && valueList.length > 1) {
@@ -1502,8 +1557,8 @@ function checkChangeFrom() {
         returnFlag = true;
     } else {
         for (const [i,cl] of changeList.entries()) {
-            if (cl.code === '' || cl.name === '' || cl.oamount === '') {
-                toastr.error('变更清单第' + (i+1) + '行未完整填写数据(变更部位、变更详情、单位、单价可空)');
+            if (cl.name === '') {
+                toastr.error('变更清单第' + (i+1) + '行未完整填写数据(名称不可为空)');
                 returnFlag = true;
             }
         }

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

@@ -12,10 +12,10 @@ $(document).ready(() => {
         cols: [
             {title: '清单编号', colSpan: '1', rowSpan: '2', field: 'code', hAlign: 0, width: 80, formatter: '@'},
             {title: '名称', colSpan: '1', rowSpan: '2', field: 'name', hAlign: 0, width: 120, formatter: '@'},
-            {title: '变更详情', colSpan: '1', rowSpan: '2', field: 'detail', hAlign: 0, width: 120, formatter: '@'},
             {title: '单位', colSpan: '1', rowSpan: '2', field: 'unit', hAlign: 1, width: 60, formatter: '@'},
             {title: '单价', colSpan: '1', rowSpan: '2', field: 'unit_price', hAlign: 2, width: 60, type: 'Number', getValue: 'getValue.unit_price'},
             {title: '变更部位', colSpan: '1', rowSpan: '2', field: 'bwmx', hAlign: 0, width: 120, formatter: '@'},
+            {title: '变更详情', colSpan: '1', rowSpan: '2', field: 'detail', hAlign: 0, width: 120, formatter: '@'},
             {title: '原设计|数量', colSpan: '2|1', rowSpan: '1|1', field: 'oamount', hAlign: 2, width: 60, type: 'Number', getValue: 'getValue.oamount'},
             {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'oa_tp', hAlign: 2, width: 80, type: 'Number', getValue: 'getValue.oa_tp'},
             {title: '申请变更增(+)减(-)|数量', colSpan: '2|1', rowSpan: '1|1', field: 'camount', hAlign: 2, width: 60, type: 'Number', getValue: 'getValue.camount'},
@@ -121,7 +121,7 @@ $(document).ready(() => {
             for (const j in aidList) {
                 for(let i = 0; i <= rowCount - 1; i++){
                     const data = {
-                        unit_price: changeSpreadSheet.getValue(i, 5),
+                        unit_price: changeSpreadSheet.getValue(i, 3),
                         amount: parseFloat(changeSpreadSheet.getValue(i, 12 + parseInt(j)*2)),
                     };
                     const sum = ZhCalc.round(ZhCalc.mul(data.unit_price, data.amount), totalPriceUnit);

+ 5 - 3
app/public/js/gcl_gather.js

@@ -347,7 +347,6 @@ const gclGatherModel = (function () {
             gcl.end_contract_qty = ZhCalc.add(gcl.pre_contract_qty, gcl.contract_qty);
             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.end_final_qty = ZhCalc.add(gcl.end_qc_qty, gcl.quantity);
             gcl.gather_tp = ZhCalc.add(gcl.contract_tp, gcl.qc_tp);
             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);
@@ -355,11 +354,14 @@ const gclGatherModel = (function () {
             gcl.dgn_price = ZhCalc.round(ZhCalc.div(gcl.total_price, gcl.dgn_qty1), 2);
             gcl.end_final_qty = ZhCalc.add(gcl.end_qc_qty, gcl.quantity);
             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
                 ? 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.final_qty = ZhCalc.add(gcl.quantity, gcl.change_bills_qty);
-            gcl.final_tp = ZhCalc.add(gcl.total_price, gcl.change_bills_tp);
+            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);
             for (const xmj of gcl.leafXmjs) {
                 xmj.pre_gather_qty = ZhCalc.add(xmj.pre_contract_qty, xmj.pre_qc_qty);
                 xmj.gather_qty = ZhCalc.add(xmj.contract_qty, xmj.qc_qty);

+ 4 - 0
app/public/js/global.js

@@ -1151,3 +1151,7 @@ function hpackArrBack(data) {
     });
     return result;
 }
+
+$(document).ready(function () {
+  $('.modal').draggable({handle: '.modal-header'});
+});

+ 4 - 2
app/public/js/ledger_check.js

@@ -76,7 +76,9 @@ const ledgerCheckUtil = {
                     calcData[f] = ZhCalc.add(calcData[f], np[f]) || 0;
                 }
             }
-            if (!_.isMatch(checkData, calcData)) error.push(node);
+            if (!_.isMatch(checkData, calcData)) {
+                error.push(node);
+            }
         }
         return error;
     },
@@ -200,7 +202,7 @@ const ledgerCheckUtil = {
                 if (ratio === 0) {
                     if (!data.contract_tp && !data.pre_contract_tp) return 2; // 漏计
                 } else {
-                    const tp = ZhCalc.mul(data.total_price, ZhCalc.div(ratio, 100, 4), this.ctx.tender.info.decimal.tp);
+                    const tp = ZhCalc.mul(data.final_1_tp, ZhCalc.div(ratio, 100, 4), this.ctx.tender.info.decimal.tp);
                     const checkTp = ZhCalc.add(data.contract_tp, data.pre_contract_tp);
                     if (tp > checkTp) return 1; // 违规
                     if (tp < checkTp) return 2; // 漏计

+ 2 - 0
app/public/js/material.js

@@ -1106,6 +1106,8 @@ $(document).ready(() => {
                         materialRate = rate;
                         $('#rateInput').val(rate);
                     });
+                } else {
+                    $('#rateInput').val(rate);
                 }
             }, 500);
         });

+ 2 - 0
app/public/js/material_exponent.js

@@ -568,6 +568,8 @@ $(document).ready(() => {
                         materialRate = rate;
                         $('#rateInput').val(rate);
                     });
+                } else {
+                    $('#rateInput').val(rate);
                 }
             }, 500);
         });

+ 17 - 7
app/public/js/material_list.js

@@ -645,7 +645,8 @@ $(document).ready(() => {
                     return item.qc_qty || item.contract_qty
                 });
                 const nRow = leafXmjs.indexOf(leafXmjSelect);
-                return [index, iRow, nRow, leafXmjSheet, leafXmjSelect];
+                const leafXmjColor = findNotJoinLeafXmj(leafXmjSelect) ? '#d6d8db' : '';
+                return [index, iRow, nRow, leafXmjSheet, leafXmjSelect, leafXmjColor];
             },
             checkJoinMaterial: function (type) {
                 const [iGclRow, iRow, nRow, sheet, select] = leafXmjSpreadObj.getSelect();
@@ -671,7 +672,7 @@ $(document).ready(() => {
                 });
             },
             checkSelfMaterial: function (type) {
-                const [iGclRow, iRow, nRow, sheet, select] = leafXmjSpreadObj.getSelect();
+                const [iGclRow, iRow, nRow, sheet, select, color] = leafXmjSpreadObj.getSelect();
                 // const color = type === 'self' ? '' : '#d6d8db';
                 const data = {
                     type: type,
@@ -682,13 +683,15 @@ $(document).ready(() => {
                     if (type === 'noself') {
                         const index = findSelfLeafXmj(select, 'index');
                         selfList.splice(index, 1);
+                        materialListData = result;
+                        $('#cancel-self').modal('hide');
                     } else {
                         selfList.push(result);
                     }
                     gclGatherData[iGclRow].leafXmjs[iRow].jiacha = calcOneBQJC(select);
                     calculateJiaCha(gclGatherData, iGclRow);
                     SpreadJsObj.reLoadRowData(sheet, nRow);
-                    // sheet.getRange(nRow, -1, 1, -1).backColor(color);
+                    sheet.getRange(nRow, -1, 1, -1).backColor(color);
                     loadXmjMaterialData(iGclRow, nRow);
                     SpreadJsObj.reLoadRowData(ledgerSpread.getActiveSheet(), iGclRow);
                 });
@@ -769,7 +772,8 @@ $(document).ready(() => {
                     name: '取消单独添加工料',
                     icon: 'fa-remove',
                     callback: function (key, opt) {
-                        leafXmjSpreadObj.checkSelfMaterial('noself');
+                        $('#cancel-self').modal('show');
+                        // leafXmjSpreadObj.checkSelfMaterial('noself');
                     },
                     visible: function (key, opt) {
                         const sheet = leafXmjSpread.getActiveSheet();
@@ -788,6 +792,9 @@ $(document).ready(() => {
                 },
             }
         });
+        $('#cancelSelfBtn').click(function () {
+            leafXmjSpreadObj.checkSelfMaterial('noself');
+        });
         // material-spread右键功能
         const materialSpreadObj = {
             del: function () {
@@ -1213,10 +1220,11 @@ $(document).ready(() => {
                     sheet.setSelection(index > 0 ? index - 1 : 0, sel.length > 0 ? sel[0].col : 0, 1, 1);
                     const materialListIndex = materialListData.indexOf(select);
                     materialListData.splice(materialListIndex, 1);
-                    const [iGclRow, iRow, nRow, lsheet, lselect] = leafXmjSpreadObj.getSelect();
+                    const [iGclRow, iRow, nRow, lsheet, lselect, color] = leafXmjSpreadObj.getSelect();
                     gclGatherData[iGclRow].leafXmjs[iRow].jiacha = calcOneBQJC(lselect);
                     calculateJiaCha(gclGatherData, iGclRow);
                     SpreadJsObj.reLoadRowData(lsheet, nRow);
+                    lsheet.getRange(nRow, -1, 1, -1).backColor(color);
                     SpreadJsObj.reLoadRowData(ledgerSpread.getActiveSheet(), iGclRow);
                 });
             },
@@ -1286,10 +1294,12 @@ $(document).ready(() => {
                         materialListData.splice(materialListIndex, 1, select);
                         materialList.indexOf(index, 1, select);
                         SpreadJsObj.reLoadRowData(info.sheet, info.row);
-                        const [iGclRow, iRow, nRow, sheet, lselect] = leafXmjSpreadObj.getSelect();
+                        const [iGclRow, iRow, nRow, sheet, lselect, color] = leafXmjSpreadObj.getSelect();
                         gclGatherData[iGclRow].leafXmjs[iRow].jiacha = calcOneBQJC(lselect);
                         calculateJiaCha(gclGatherData, iGclRow);
                         SpreadJsObj.reLoadRowData(sheet, nRow);
+                        console.log(lselect, color);
+                        sheet.getRange(nRow, -1, 1, -1).backColor(color);
                         SpreadJsObj.reLoadRowData(ledgerSpread.getActiveSheet(), iGclRow);
                     }, function () {
                         SpreadJsObj.reLoadRowData(info.sheet, info.row);
@@ -1491,7 +1501,7 @@ $(document).ready(() => {
                         if (!select) {
                             return true;
                         }
-                        if (!readOnly && select && materialSelfBase.isEdit(select, 'del')) {
+                        if (!readOnly && select) {
                             return false;
                         } else {
                             return true;

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

@@ -322,7 +322,7 @@ $(function () {
                                 hadQtySelfList.push(bill);
                                 insertSelfList.push({
                                     gcl_id: xmj.gcl_id,
-                                    mx_id: xmj.mx_id ? xmj.mx_id : null,
+                                    mx_id: xmj.mx_id ? xmj.mx_id : '',
                                     xmj_id: xmj.id ? xmj.id : null,
                                     gather_qty: xmj.gather_qty,
                                     quantity: bill.quantity,
@@ -336,7 +336,7 @@ $(function () {
                             for (const bill of one.bills) {
                                 insertList.push({
                                     gcl_id: xmj.gcl_id,
-                                    mx_id: xmj.mx_id ? xmj.mx_id : null,
+                                    mx_id: xmj.mx_id ? xmj.mx_id : '',
                                     xmj_id: xmj.id ? xmj.id : null,
                                     gather_qty: xmj.gather_qty,
                                     quantity: bill.quantity,

+ 14 - 36
app/public/js/stage.js

@@ -36,7 +36,7 @@ function customColDisplay () {
         { 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', 'end_gather_1_percent'], visible: true },
+        { title: '截止本期完成计量', fields: ['end_gather_qty', 'end_gather_tp', 'end_gather_percent'], visible: true },
         { title: '本期批注', fields: ['postil'], visible: true },
         { title: '图册号', fields: ['drawing_code'], visible: true },
         { title: '备注', fields: ['memo'], visible: true },
@@ -267,9 +267,9 @@ $(document).ready(() => {
         markExpandSubKey: window.location.pathname.split('/')[2],
     };
     // 台账树结构计算相关设置
-    stageTreeSetting.updateFields = ['contract_qty', 'contract_tp', 'qc_qty', 'qc_tp', 'postil', 'used', 'contract_expr', 'minus_qc_qty'];
+    stageTreeSetting.updateFields = ['contract_qty', 'contract_tp', 'qc_qty', 'qc_tp', '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', 'end_1_tp'];
+        'pre_contract_tp', 'pre_qc_tp', 'pre_gather_tp', 'end_contract_tp', 'end_qc_tp', 'end_gather_tp', 'end_correct_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);
@@ -277,9 +277,6 @@ $(document).ready(() => {
             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_minus_qc_qty = ZhCalc.add(node.pre_minus_qc_qty, node.minus_qc_qty);
-            node.end_1_qty = ZhCalc.add(node.end_minus_qc_qty, node.quantity); // 1#台账 台账+负变更
-            node.end_1_tp = ZhCalc.mul(node.unit_price, node.end_1_qty, tenderInfo.decimal.tp);
         }
         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);
@@ -287,7 +284,7 @@ $(document).ready(() => {
         node.end_qc_tp = ZhCalc.add(node.pre_qc_tp, node.qc_tp);
         node.end_gather_tp = ZhCalc.add(node.pre_gather_tp, node.gather_tp);
         node.end_final_tp = ZhCalc.add(node.end_qc_tp, node.total_price);
-        node.end_final_1_tp = ZhCalc.add(node.end_qc_tp, node.end_1_tp);
+        node.end_final_1_tp = ZhCalc.add(node.end_qc_tp, node.final_1_tp);
         if (!node.children || node.children.length === 0) {
             if (node.end_contract_qty) {
                 node.end_correct_tp = ZhCalc.add(node.end_qc_tp, ZhCalc.mul(node.end_contract_qty, node.unit_price, tenderInfo.decimal.tp));
@@ -297,8 +294,6 @@ $(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.end_gather_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);
         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);
     };
     const stageTree = createNewPathTree('stage', stageTreeSetting);
@@ -418,6 +413,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);
                 }
@@ -538,7 +534,7 @@ $(document).ready(() => {
                     c.uamount = uc.qty;
                     c.vamount = ZhCalc.add(c.vamount, uc.qty);
                 }
-                c.pre_amount = ZhCalc.sub(c.used_amount, c.uamount);
+                c.pre_amount = ZhCalc.sub(ZhCalc.add(c.used_amount, c.stage_used_amount), c.uamount);
             }
         }
         _loadChangeDetail(change) {
@@ -657,9 +653,7 @@ $(document).ready(() => {
         }
     };
     const ratioCol = ledgerSpreadSetting.cols.find(x => {return x.field === 'end_gather_percent' || x.field === 'end_correct_percent'});
-    ratioCol.field = tenderInfo.display.stage.correct ? 'end_correct_percent' : 'end_gather_percent';
-    const ratioCol1 = ledgerSpreadSetting.cols.find(x => {return x.field === 'end_gather_1_percent' || x.field === 'end_correct_1_percent'});
-    ratioCol1.field = tenderInfo.display.stage.correct ? 'end_correct_1_percent' : 'end_gather_1_percent';
+    if (ratioCol) ratioCol.field = tenderInfo.display.stage.correct ? 'end_correct_percent' : 'end_gather_percent';
     ledgerSpreadSetting.imageClick = function (data, hitinfo) {
         const col = hitinfo.sheet.zh_setting.cols[hitinfo.col];
         switch (col.field) {
@@ -974,11 +968,12 @@ $(document).ready(() => {
             }
         },
         loadRelaData: function () {
-            const billsSheet = spSpread.getActiveSheet();
-            SpreadJsObj.resetTopAndSelect(billsSheet);
+            const billsSheet = slSpread.getActiveSheet();
+            SpreadJsObj.saveTopAndSelect(billsSheet, ckBillsSpread);
+            const posSheet = spSpread.getActiveSheet();
+            SpreadJsObj.resetTopAndSelect(posSheet);
             stagePosSpreadObj.loadCurPosData();
             if (posSearch) posSearch.search();
-            SpreadJsObj.saveTopAndSelect(billsSheet, ckBillsSpread);
         },
         selectionChanged: function (e, info) {
             if (!info.oldSelections || !info.oldSelections[0] || info.newSelections[0].row !== info.oldSelections[0].row) {
@@ -2041,26 +2036,11 @@ $(document).ready(() => {
     });
 
     // 加载计量单元数据 - 暂时统一加载,如有需要,切换成动态加载并缓存
-    postData(window.location.pathname + '/load', { filter: 'ledger;pos;detail;change;import_change;tag;cooperation;minus_change' }, function (result) {
+    postData(window.location.pathname + '/load', { filter: 'ledger;pos;detail;change;import_change;tag;cooperation' }, function (result) {
         // 加载树结构
         stageTree.loadDatas(result.ledgerData);
-        let mcIndex = {};
-        if (result.minus_change && result.minus_change.length > 0) {
-            for (const mc of result.minus_change) {
-                if (!mcIndex[mc.lid]) mcIndex[mc.lid] = stageTree.nodes.find(x => { return x.id === mc.lid; });
-                if (!mcIndex[mc.lid]) continue;
-                mcIndex[mc.lid].pre_minus_qc_qty = ZhCalc.add(mcIndex[mc.lid].pre_minus_qc_qty, mc.qty);
-            }
-        }
-        if (result.changeData && result.changeData.length > 0) {
-            for (const mc of result.changeData) {
-                if (!mc.minus || !mc.qty) continue;
-                if (!mcIndex[mc.lid]) mcIndex[mc.lid] = stageTree.nodes.find(x => { return x.id === mc.lid; });
-                if (!mcIndex[mc.lid]) continue;
-                mcIndex[mc.lid].minus_qc_qty = ZhCalc.add(mcIndex[mc.lid].minus_qc_qty, mc.qty);
-            }
-        }
-        mcIndex = null;
+        // 加载部位明细
+        stagePos.loadDatas(result.posData);
         checkShowLast(result.ledgerData.length);
         treeCalc.calculateAll(stageTree);
         // 加载解锁相关
@@ -2075,8 +2055,6 @@ $(document).ready(() => {
             t.node = stageTree.datas.find(x => {return x.id === t.lid});
         }
         billsTag.loadDatas(result.tags);
-        // 加载部位明细
-        stagePos.loadDatas(result.posData);
         stagePos.calculateAll();
         SpreadJsObj.loadSheetData(slSpread.getActiveSheet(), 'tree', stageTree);
         SpreadJsObj.loadTopAndSelect(slSpread.getActiveSheet(), ckBillsSpread);

+ 4 - 1
app/public/js/stage_bwtz.js

@@ -90,6 +90,9 @@ $(document).ready(() => {
     xmjSpread.bind(spreadNS.Events.SelectionChanged, function (e, info) {
         unitTreeObj.loadCurUnitData();
     });
+    unitSpread.bind(spreadNS.Events.SelectionChanged, function (e, info) {
+        console.log(SpreadJsObj.getSelectObject(info.sheet));
+    });
     const loadData = function (dataType) {
         postData(window.location.pathname + '/load', {filter: dataType}, function (result) {
             const setting = {
@@ -152,7 +155,7 @@ $(document).ready(() => {
             }
         }
     });
-    $('a', '.side-menu').bind('click', function (e) {
+    $('a', '.content-wrap .side-menu').bind('click', function (e) {
         e.preventDefault();
         const tab = $(this), tabPanel = $(tab.attr('content'));
         const showSideTools = function (show) {

+ 10 - 4
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);
                     }
@@ -1220,7 +1220,13 @@ module.exports = app => {
             const sqlParam = [tender.id, stage.order, tender.id, audit.flow.status.checked];
             const changes = await this.db.query(sql, sqlParam);
             for (const c of changes) {
-                const stageUsedData = await this.ctx.service.stageChange.getAllDataByCondition({ where: { sid: stage.id, cbid: c.cbid } });
+                let sSql = 'SELECT * FROM ' + this.ctx.service.stageChange.tableName + ' WHERE sid = ? and cbid = ?';
+                const sSqlParam = [stage.id, c.cbid];
+                if (stage.readOnly) {
+                    sSql = sSql + ' and (stimes < ? or (stimes = ? and sorder <= ?))';
+                    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');
                 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 ' +

+ 4 - 2
app/service/ledger.js

@@ -712,14 +712,16 @@ module.exports = app => {
                         drawing_code: node.drawing_code,
                         node_type: node.node_type,
                     };
+                    // 项目节不导入金额
+                    // todo 最底层项目节其实应该导入,但是由于目前项目节不能输入金额,也不能计量,导入金额就会有矛盾,故暂时不导入
                     if (this.ctx.tender.data.measure_type === measureType.tz.value) {
                         data.sgfh_qty = node.quantity;
                         data.sgfh_tp = node.total_price;
                         data.quantity = node.quantity;
-                        data.total_price = node.total_price;
+                        data.total_price = node.b_code ? node.total_price : 0;
                     } else if (this.ctx.tender.data.measure_type === measureType.gcl.value) {
                         data.deal_qty = node.quantity;
-                        data.deal_tp = node.total_price;
+                        data.deal_tp = node.b_code ? node.total_price : 0;
                     }
                     datas.push(data);
                 }

+ 4 - 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;
@@ -85,6 +86,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 +115,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 +150,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;

+ 1 - 1
app/service/material.js

@@ -385,7 +385,7 @@ module.exports = app => {
          * @return {Promise<*>}
          */
         async getExPreTpHs(tid, order, tp) {
-            const sql = 'SELECT SUM(ROUND(`ex_tp`*(1+ `rate`/100),' + tp + ')) AS `ex_pre_tp_hs` FROM ?? WHERE `tid` = ? AND `order` < ?';
+            const sql = 'SELECT SUM(ROUND(`ex_tp`*(1+ `exponent_rate`/100),' + tp + ')) AS `ex_pre_tp_hs` FROM ?? WHERE `tid` = ? AND `order` < ?';
             const sqlParam = [this.tableName, tid, order];
             const result = await this.db.queryOne(sql, sqlParam);
             return result.ex_pre_tp_hs;

+ 2 - 2
app/service/material_list.js

@@ -463,7 +463,7 @@ module.exports = app => {
          * @param {int} id 工料id
          * @return {void}
          */
-        async dels(datas, checklist = false) {
+        async dels(datas, checklist = false, fromCheckList = false) {
             if (!this.ctx.tender || !this.ctx.material) {
                 throw '数据错误';
             }
@@ -486,7 +486,7 @@ module.exports = app => {
                 await transaction.commit();
                 // console.log(datas);
                 const gclList = await this.ctx.service.materialListGcl.getAllDataByCondition({ where: { tid: this.ctx.tender.id } });
-                return checklist ? gclList : {
+                return fromCheckList ? gclList : {
                     gclList,
                     materialListData: await this.getMaterialData(this.ctx.tender.id, this.ctx.material.id),
                 };

+ 1 - 1
app/service/material_list_self.js

@@ -82,7 +82,7 @@ module.exports = app => {
                 // 判断是否可删
                 const result = await transaction.delete(this.tableName, { id });
                 await transaction.commit();
-                return result;
+                return await this.ctx.service.materialList.getMaterialData(this.ctx.tender.id, this.ctx.material.id);
             } catch (err) {
                 await transaction.rollback();
                 throw err;

+ 63 - 29
app/service/report_memory.js

@@ -29,6 +29,7 @@ const billsFields = (function () {
     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 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 stageDgn = ['deal_dgn_qty1', 'deal_dgn_qty2', 'c_dgn_qty1', 'c_dgn_qty2'];
 
     const stage = cur.concat(pre, end, final);
@@ -36,19 +37,20 @@ const billsFields = (function () {
     const bgl = ['qc_bgl_code'];
     const leafXmj = ['leaf_xmj_id'];
 
-    return {cur, pre, end, final, stageDgn, stage, stageEnd, bgl, leafXmj};
+    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 final = ['final_ratio'];
+    const final1 = ['minus_qc_qty', 'pre_minus_qc_qty', 'end_minus_qc_qty', 'final_1_qty', 'final_1_ratio'];
 
     const stage = cur.concat(pre, end, final);
     const stageEnd = pre.concat(end, final);
     const bgl = ['qc_bgl_code'];
 
-    return {cur, pre, end, final, stage, stageEnd, bgl};
+    return {cur, pre, end, final, final1, stage, stageEnd, bgl};
 })();
 
 module.exports = app => {
@@ -71,10 +73,20 @@ module.exports = app => {
                 updateFields: ['contract_qty', 'qc_qty', 'postil'],
                 calc: function (p) {
                     p.pre_gather_qty = ctx.helper.add(p.pre_contract_qty, p.pre_qc_qty);
+
                     p.gather_qty = 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_gather_qty = self.ctx.helper.add(p.pre_gather_qty, p.gather_qty);
+
+                    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.final_1_ratio = ctx.helper.mul(ctx.helper.div(p.end_gather_qty, p.end_final_1_qty, 4), 100);
                 }
             });
             // 需要缓存的数据
@@ -94,14 +106,17 @@ module.exports = app => {
                 rootId: -1,
                 keys: ['id', 'tender_id', 'ledger_id'],
                 stageId: 'id',
-                calcFields: calcFields || ['deal_tp', 'total_price', 'contract_tp', 'qc_tp', 'gather_tp', 'pre_contract_tp', 'pre_qc_tp', 'pre_gather_tp'],
-                calc: function (node, helper) {
+                calcFields: calcFields || ['deal_tp', 'total_price', 'contract_tp', 'qc_tp', 'gather_tp', 'pre_contract_tp', 'pre_qc_tp', 'pre_gather_tp', 'final_1_tp'],
+                calc: function (node, helper, decimal) {
                     if (node.children && node.children.length === 0) {
                         node.pre_gather_qty = helper.add(node.pre_contract_qty, node.pre_qc_qty);
                         node.gather_qty = helper.add(node.contract_qty, node.qc_qty);
                         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_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);
                     node.gather_tp = helper.add(node.contract_tp, node.qc_tp);
@@ -111,6 +126,10 @@ module.exports = app => {
 
                     node.final_tp = helper.add(node.total_price, node.end_qc_tp);
                     node.final_ratio = helper.mul(helper.div(node.end_gather_tp, node.final_tp, 4), 100);
+
+                    node.final_1_tp = helper.mul(node.unit_price, node.final_1_qty, decimal.tp);
+                    node.end_final_1_tp = helper.add(node.final_1_tp, node.end_qc_tp);
+                    node.final_1_ratio = helper.mul(helper.div(node.end_gather_tp, node.end_final_1_tp, 4), 100);
                 }
             });
         }
@@ -373,24 +392,31 @@ module.exports = app => {
                         this.ctx.helper._.assignIn(l, d);
                     }
                 }
+                let preStage = [], curStage = [];
                 if (this._checkFieldsExist(fields, billsFields.stage)) {
                     if (this.ctx.stage.readOnly) {
-                        const curStage = await this.ctx.service.stageBills.getAuditorStageData2(this.ctx.tender.id,
+                        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', 'contract_expr', 'qc_qty', 'qc_tp', 'postil'], 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', 'contract_expr', 'qc_qty', 'qc_tp', 'postil'], prefix: '', relaId: 'lid'}
-                        ]);
+                        curStage = await this.ctx.service.stageBills.getLastestStageData2(this.ctx.tender.id, this.ctx.stage.id);
                     }
                 }
                 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'}
+                    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'}
+                ]);
+                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'},
                     ]);
                 }
 
@@ -408,7 +434,8 @@ module.exports = app => {
 
                 return billsTree.getDefaultDatas();
             } catch(err) {
-                return []
+                this.ctx.log(err);
+                return [];
             }
         }
 
@@ -443,24 +470,31 @@ module.exports = app => {
                 }
 
                 const posData = await this.ctx.service.pos.getAllDataByCondition({ where: {tid: this.ctx.tender.id }});
+                let curPosStage = [], prePosStage = [];
                 if (this._checkFieldsExist(fields, posFields.stage)) {
                     if (this.ctx.stage.readOnly) {
-                        const curPosStage = await this.ctx.service.stagePos.getAuditorStageData2(this.ctx.tender.id,
+                        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', 'contract_expr', 'postil'], 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', 'contract_expr', 'postil'], prefix: '', relaId: 'pid'}
-                        ]);
+                        curPosStage = await this.ctx.service.stagePos.getLastestStageData2(this.ctx.tender.id, this.ctx.stage.id);
                     }
                 }
                 if (this._checkFieldsExist(fields, posFields.stageEnd)) {
-                    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'}
+                    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'}
+                ]);
+                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);
@@ -1323,8 +1357,8 @@ module.exports = app => {
                     b.qty = this.ctx.helper._.toNumber(b.samount);
                     b.tp = this.ctx.helper.round(this.ctx.helper.mul(b.qty, b.unit_price), this.ctx.tender.info.decimal.tp);
 
-                    const u = cbu.find(x => { return x.id === b.id; });
-                    b.used_qty = u ? u.used_qty : 0;
+                    const u = cbu.filter(x => { return x.cbid === b.id; });
+                    b.used_qty = u.length > 0 ? this.ctx.helper.sum(u.map(x => { return x.qty})) : 0;
 
                     b.valid_qty = this.ctx.helper.sub(b.qty, b.used_qty);
                     const cur = this.ctx.helper._.filter(curUsedBills, { cbid: b.id });

+ 5 - 0
app/service/stage.js

@@ -720,6 +720,11 @@ module.exports = app => {
             }
             return stages;
         }
+
+        async isLastStage(tid, sid) {
+            const lastStage = await this.ctx.service.stage.getLastestStage(tid, true);
+            return lastStage ? lastStage.id === sid : false;
+        }
     }
 
     return Stage;

+ 4 - 3
app/service/stage_audit.js

@@ -475,11 +475,12 @@ module.exports = app => {
                         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) {
+                        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) {
                             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;
                         }
                     }

+ 43 - 46
app/service/stage_bills_final.js

@@ -75,54 +75,50 @@ module.exports = app => {
             if (!transaction || !tender || !stage) {
                 throw '数据错误';
             }
-            if (stage.order > 1) {
-                const cur = await this.ctx.service.stageBills.getLastestStageData2(tender.id, stage.id);
-                const pre = await this.getFinalData(tender, stage.order - 1);
-                if ((!cur || cur.length === 0) && (!pre || pre.length === 0)) return;
-                for (const c of cur) {
-                    delete c.id;
-                    delete c.said;
-                    delete c.times;
-                    delete c.order;
-                    delete c.postil;
-                    c.sorder = stage.order;
-                    const p = this.ctx.helper._.find(pre, function (x) {
-                        return x.lid === c.lid;
-                    });
-                    if (p) {
-                        c.contract_qty = this.ctx.helper.add(c.contract_qty, p.contract_qty);
-                        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);
-                        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_tp);
-                        pre.splice(pre.indexOf(p), 1);
+            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;
+                delete c.said;
+                delete c.times;
+                delete c.order;
+                delete c.postil;
+                c.sorder = stage.order;
+                const p = this.ctx.helper._.find(pre, function (x) {
+                    return x.lid === c.lid;
+                });
+                if (p) {
+                    c.contract_qty = this.ctx.helper.add(c.contract_qty, p.contract_qty);
+                    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 {
-                        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_tp);
+                        const mc = minusChange.find(x => { return x.lid === c.lid && x.qty < 0 });
+                        c.used = !!mc;
+                    }
+                    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;
                     }
                 }
+            }
 
-                for (const p of pre) {
-                    if (p.id !== undefined) delete p.id;
-                    p.sid = stage.id;
-                    p.sorder = stage.order;
-                }
-                await transaction.insert(this.tableName, cur ? cur.concat(pre) : pre);
-            } else {
-                const sql = 'Insert Into ??(tid, sid, lid, sorder, contract_qty, contract_tp, qc_qty, qc_tp, used)' +
-                    '  SELECT b.tid, b.sid, b.lid, ? As `sorder`, b.contract_qty, b.contract_tp, b.qc_qty, b.qc_tp,' +
-                    '    IF(IFNULL(b.contract_qty, 0) <> 0 or IFNULL(b.contract_tp, 0) <> 0 or IFNULL(b.qc_qty, 0) <> 0 or IFNULL(b.qc_tp, 0) <> 0, 1, 0) As used' +
-                    '  FROM ' + this.ctx.service.stageBills.tableName + ' AS b' +
-                    '  INNER JOIN(' +
-                    '    SELECT Max(`times` * ' + timesLen + ' + `order`) As `flow`, `lid` FROM ' + this.ctx.service.stageBills.tableName +
-                    '    WHERE `sid` = ?' +
-                    '    GROUP By `lid`) As MF' +
-                    '  ON (b.times * ' + timesLen + ' + b.order) = MF.flow AND b.lid = MF.lid' +
-                    '  WHERE b.sid = ?';
-                const sqlParam = [this.tableName, stage.order, stage.id, stage.id];
-                await transaction.query(sql, sqlParam);
+            for (const p of pre) {
+                if (p.id !== undefined) delete p.id;
+                p.sid = stage.id;
+                p.sorder = stage.order;
             }
+            await transaction.insert(this.tableName, cur ? cur.concat(pre) : pre);
         }
 
         /**
@@ -149,10 +145,11 @@ module.exports = app => {
 
         async getSumTotalPriceFilter(tenderId, stageOrder, operate, filter) {
             const sql = 'SELECT Sum(`contract_tp`) As `contract_tp`, Sum(`qc_tp`) As `qc_tp`' +
-                '  FROM ' + this.tableName + ' As Bills ' +
+                '  FROM (SELECT * FROM ' + this.tableName + ' WHERE tid = ? And sorder = ?) As Bills ' +
                 '  LEFT JOIN ' + this.ctx.service.ledger.tableName + ' As Ledger ' +
-                '  ON Bills.lid = Ledger.id And Bills.sorder = ? And Bills.tid = ? And Ledger.b_code ' + operate + ' ?';
-            const sqlParam = [stageOrder, tenderId, filter];
+                '  ON Bills.lid = Ledger.id ' +
+                '  WHERE Ledger.b_code ' + operate + ' ?';
+            const sqlParam = [tenderId, stageOrder, filter];
             const result = await this.db.queryOne(sql, sqlParam);
             return result;
         }

+ 18 - 23
app/service/stage_change.js

@@ -156,9 +156,7 @@ module.exports = app => {
                 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);
-                    if (!change.minus) {
-                        billsQty = this.ctx.helper.add(billsQty, change.qty);
-                    }
+                    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;
                         updateChanges.push(change);
@@ -166,18 +164,14 @@ module.exports = app => {
                         newChanges.push(change);
                     }
                 } else {
-                    if (!oc.minus) {
-                        billsQty = this.ctx.helper.add(billsQty, oc.qty);
-                    }
+                    billsQty = this.ctx.helper.add(billsQty, oc.qty);
                 }
             }
             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);
-                    if (!change.minus) {
-                        billsQty = this.ctx.helper.add(billsQty, change.qty);
-                    }
+                    billsQty = this.ctx.helper.add(billsQty, change.qty);
                     newChanges.push(change);
                 }
             }
@@ -234,26 +228,22 @@ module.exports = app => {
                 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);
-                    if (!change.minus) {
-                        posQty = this.ctx.helper.add(posQty, change.qty);
-                    }
+                    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;
                         updateChanges.push(change);
+                    } else {
+                        newChanges.push(change);
                     }
                 } else {
-                    if (!oc.minus) {
-                        posQty = this.ctx.helper.add(posQty, oc.qty);
-                    }
+                    posQty = this.ctx.helper.add(posQty, oc.qty);
                 }
             }
             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);
-                    if (!change.minus) {
-                        posQty = this.ctx.helper.add(posQty, change.qty);
-                    }
+                    posQty = this.ctx.helper.add(posQty, change.qty);
                     newChanges.push(change);
                 }
             }
@@ -261,9 +251,7 @@ module.exports = app => {
             const transaction = await this.db.beginTransaction();
             try {
                 if (newChanges.length > 0) await transaction.insert(this.tableName, newChanges);
-                for (const c of updateChanges) {
-                    await transaction.update(this.tableName, c);
-                }
+                if (updateChanges.length > 0) await transaction.updateRows(this.tableName, updateChanges);
                 await this.ctx.service.stagePos.updateChangeQuantity(transaction, pos, posQty);
                 await transaction.commit();
             } catch (err) {
@@ -403,7 +391,7 @@ module.exports = app => {
             data = helper.filterLastestData(data, ['lid', 'pid', 'cbid'], 'stimes', 'sorder');
             const bqData = [];
             for (const d of data) {
-                if (!d.qty || d.minus) continue;
+                if (!d.qty) continue;
                 let bd = bqData.find(x => { return x.lid === d.lid && x.quality === d.quality; });
                 if (!bd) {
                     const bills = await this.db.get(this.ctx.service.ledger.departTableName(tender.id), { id: d.lid });
@@ -490,7 +478,7 @@ module.exports = app => {
         }
 
         async getStageMinusChange(stage) {
-            const data = this.getAllDataByCondition({ where: { sid: stage.id, minus: 1 } });
+            const data = await this.getAllDataByCondition({ where: { sid: stage.id, minus: 1 } });
             return this.ctx.helper.filterLastestData(data, ['lid', 'pid', 'cbid'], 'stimes', 'sorder');
         };
 
@@ -499,6 +487,13 @@ module.exports = app => {
             const filter = this.ctx.helper.filterLastestData(data, ['lid', 'pid', 'cbid'], 'stimes', 'sorder');
             return { lid, qty: this.ctx.helper.sum(filter.map(x => { return x.qty; })) };
         };
+
+
+        async getPosMinusQty(stage, pid) {
+            const data = await this.getAllDataByCondition({ where: { sid: stage.id, pid, minus: 1 } });
+            const filter = this.ctx.helper.filterLastestData(data, ['lid', 'pid', 'cbid'], 'stimes', 'sorder');
+            return { pid, qty: this.ctx.helper.sum(filter.map(x => { return x.qty; })) };
+        };
     }
 
     return StageChange;

+ 2 - 2
app/service/stage_change_final.js

@@ -103,13 +103,13 @@ module.exports = app => {
         }
 
         async getPreMinusChange(tid, sorder) {
-            const sql = 'SELECT lid, pid, SUM(qty) FROM ' + this.tableName + ' WHERE tid = ? and sorder < ? GROUP BY lid, pid';
+            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) FROM ' + this.tableName + ' WHERE tid = ? GROUP BY lid, pid';
+            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;
         }

+ 35 - 39
app/service/stage_pos_final.js

@@ -57,50 +57,46 @@ module.exports = app => {
             if (!transaction || !tender || !stage) {
                 throw '数据错误';
             }
-            if (stage.order > 1) {
-                const cur = await this.ctx.service.stagePos.getLastestStageData2(tender.id, stage.id);
-                const pre = await this.getFinalData(tender, stage.order - 1);
-                if ((!cur || cur.length === 0) && (!pre || pre.length === 0)) return;
-                for (const c of cur) {
-                    delete c.id;
-                    delete c.said;
-                    delete c.times;
-                    delete c.order;
-                    delete c.postil;
-                    c.sorder = stage.order;
-                    const p = this.ctx.helper._.find(pre, function (x) {
-                        return x.pid === c.pid;
-                    });
-                    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);
-                        pre.splice(pre.indexOf(p), 1);
+            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;
+                delete c.said;
+                delete c.times;
+                delete c.order;
+                delete c.postil;
+                c.sorder = stage.order;
+                const p = this.ctx.helper._.find(pre, function (x) {
+                    return x.pid === c.pid;
+                });
+                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);
+                    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 {
-                        c.used = !this.ctx.helper.checkZero(c.contract_qty) || !this.ctx.helper.checkZero(c.qc_qty);
+                        const mc = minusChange.find(x => { return x.pid === c.pid && x.qty < 0});
+                        c.used = !!mc;
                     }
                 }
-                for (const p of pre) {
-                    if (p.id !== undefined) delete p.id;
-                    p.sid = stage.id;
-                    p.sorder = stage.order;
-                    p.used = p.used || !this.ctx.helper.checkZero(p.contract_qty) || !this.ctx.helper.checkZero(p.qc_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.insert(this.tableName, cur ? cur.concat(pre) : pre);
-            } else {
-                const sql = 'Insert Into ??(tid, sid, lid, pid, sorder, contract_qty, qc_qty, used)' +
-                            '  SELECT p.tid, p.sid, p.lid, p.pid, ? As `sorder`, p.contract_qty, p.qc_qty,' +
-                            '    IF(IFNULL(p.contract_qty, 0) <> 0 or IFNULL(p.qc_qty, 0) <> 0, 1, 0) As used' +
-                            '  FROM ' + this.ctx.service.stagePos.tableName + ' AS p' +
-                            '  INNER JOIN(' +
-                            '    SELECT Max(`times` * ' + timesLen +' + `order`) As `flow`, `pid` FROM ' + this.ctx.service.stagePos.tableName +
-                            '    WHERE `sid` = ?' +
-                            '    GROUP By `pid`) As MF' +
-                            '  ON (p.times * ' + timesLen + ' + p.order) = MF.flow AND p.pid = MF.pid' +
-                            '  WHERE p.sid = ?';
-                const sqlParam = [this.tableName, stage.order, stage.id, stage.id];
-                await transaction.query(sql, sqlParam);
             }
+            await transaction.insert(this.tableName, cur ? cur.concat(pre) : pre);
         }
 
         /**

+ 19 - 12
app/service/stage_stash.js

@@ -124,20 +124,27 @@ module.exports = app => {
                     nbs.contract_tp = this.ctx.helper.mul(nbs.contract_qty, b.unit_price, decimal.tp);
                     nbs.qc_tp = this.ctx.helper.mul(nbs.qc_qty, b.unit_price, decimal.tp);
                 } else {
-                    nbs.contract_qty = this.ctx.helper.round(d.contract_qty, decimal.qty);
-                    nbs.contract_tp = this.ctx.helper.mul(nbs.contract_qty, b.unit_price, decimal.tp);
-                    nbs.qc_qty = 0;
-                    if (d.change) {
-                        for (const c of d.change) {
-                            if (!c.qty) continue;
-                            const ncs = { tid: stage.tid, sid: stage.id, lid: d.id, pid: -1, stimes: 1, sorder: 0, cid: c.cid, cbid: c.cbid, minus: c.minus };
-                            const validQty = await this.ctx.service.stageChangeFinal.getChangeBillsValidQty(c.cbid);
-                            ncs.qty = validQty >= c.qty ? c.qty : validQty;
-                            insertChangeData.push(ncs);
-                            if (!ncs.minus) nbs.qc_qty = await this.ctx.helper.add(nbs.qc_qty, ncs.qty);
+                    if (b.is_tp) {
+                        nbs.contract_qty = 0;
+                        nbs.contract_tp = this.ctx.helper.round(d.contract_tp, decimal.tp);
+                        nbs.qc_qty = 0;
+                        nbs.qc_tp = 0;
+                    } else {
+                        nbs.contract_qty = this.ctx.helper.round(d.contract_qty, decimal.qty);
+                        nbs.contract_tp = this.ctx.helper.mul(nbs.contract_qty, b.unit_price, decimal.tp);
+                        nbs.qc_qty = 0;
+                        if (d.change) {
+                            for (const c of d.change) {
+                                if (!c.qty) continue;
+                                const ncs = { tid: stage.tid, sid: stage.id, lid: d.id, pid: -1, stimes: 1, sorder: 0, cid: c.cid, cbid: c.cbid, minus: c.minus };
+                                const validQty = await this.ctx.service.stageChangeFinal.getChangeBillsValidQty(c.cbid);
+                                ncs.qty = validQty >= c.qty ? c.qty : validQty;
+                                insertChangeData.push(ncs);
+                                if (!ncs.minus) nbs.qc_qty = await this.ctx.helper.add(nbs.qc_qty, ncs.qty);
+                            }
                         }
+                        nbs.qc_tp = this.ctx.helper.mul(nbs.qc_qty, b.unit_price, decimal.tp);
                     }
-                    nbs.qc_tp = this.ctx.helper.mul(nbs.qc_qty, b.unit_price, decimal.tp);
                 }
                 insertBillsData.push(nbs);
             }

+ 20 - 3
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>
@@ -478,7 +495,7 @@
     let changeOrder = parseInt('<%- change.order_by %>');
     console.log(changeUsedData);
 </script>
-<script src="/public/js/change_information_set.js?202001181"></script>
+<script src="/public/js/change_information_set.js?202206211"></script>
 <script src="/public/js/change_audit.js"></script>
 <% } else if (auditStatus === 3 || auditStatus === 4 || auditStatus === 5 || auditStatus === 7 || auditStatus === 8) { %>
 <script>
@@ -486,7 +503,7 @@
     const aidList = _.map(auditList2, 'uid');
     aidList.splice(0, 1);
 </script>
-<script src="/public/js/change_information_show.js?202001181"></script>
+<script src="/public/js/change_information_show.js?202206211"></script>
 <% } else if (auditStatus === 6) { %>
 <script>
     const auditList2 = JSON.parse(unescape('<%- escape(JSON.stringify(auditList2)) %>'));
@@ -497,5 +514,5 @@
     const changeLedgerList = JSON.parse(unescape('<%- escape(JSON.stringify(changeLedgerList)) %>'));
     const changePosList = JSON.parse(unescape('<%- escape(JSON.stringify(changePosList)) %>'));
 </script>
-<script src="/public/js/change_information_approval.js?202001181"></script>
+<script src="/public/js/change_information_approval.js?202206211"></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 %>';

+ 1 - 1
app/view/change/project_information_modal.ejs

@@ -746,7 +746,7 @@
                             </dl>
                         </div>
                     </div>
-                    <div class="modal-height-max100" id="xs-list">
+                    <div class="modal-height-max100" style="overflow: visible" id="xs-list">
                         <% for (const xs of change.xsAuditors) { %>
                   <span class="d-inline-block">
                     <span class="badge badge-light">

+ 102 - 34
app/view/dashboard/index.ejs

@@ -38,38 +38,56 @@
                             <div>
                                 <select class="form-control form-control-sm" id="select-doing-type">
                                     <option value="0">全部</option>
-                                    <option value="6">预付款</option>
-                                    <option value="5">台账审批</option>
-                                    <option value="4">台账修订</option>
-                                    <option value="2">计量审批</option>
-                                    <option value="3">变更审批</option>
-                                    <% if (ctx.session.sessionProject.page_show.openChangeProject) { %>
-                                        <option value="7">变更立项</option>
+                                    <% if (auditAdvance.length !== 0) { %>
+                                    <option value="6">预付款(<%- auditAdvance.length %>)</option>
                                     <% } %>
-                                    <% if (ctx.session.sessionProject.page_show.openChangeApply) { %>
-                                        <option value="8">变更申请</option>
+                                    <% if (auditTenders.length !== 0) { %>
+                                    <option value="5">台账审批(<%- auditTenders.length %>)</option>
                                     <% } %>
-                                    <% if (ctx.session.sessionProject.page_show.openChangePlan) { %>
-                                        <option value="9">变更方案</option>
+                                    <% if (auditRevise.length !== 0) { %>
+                                    <option value="4">台账修订(<%- auditRevise.length %>)</option>
+                                    <% } %>
+                                    <% if (auditStages.length !== 0) { %>
+                                    <option value="2">计量审批(<%- auditStages.length %>)</option>
+                                    <% } %>
+                                    <% if (auditChanges.length !== 0) { %>
+                                    <option value="3">变更审批(<%- auditChanges.length %>)</option>
+                                    <% } %>
+                                    <% if (ctx.session.sessionProject.page_show.openChangeProject && auditChangeProject.length !== 0) { %>
+                                        <option value="7">变更立项(<%- auditChangeProject.length %>)</option>
+                                    <% } %>
+                                    <% if (ctx.session.sessionProject.page_show.openChangeApply && auditChangeApply.length !== 0) { %>
+                                        <option value="8">变更申请(<%- auditChangeApply.length %>)</option>
+                                    <% } %>
+                                    <% if (ctx.session.sessionProject.page_show.openChangePlan && auditChangePlan.length !== 0) { %>
+                                        <option value="9">变更方案(<%- auditChangePlan.length %>)</option>
+                                    <% } %>
+                                    <% if (auditMaterial.length !== 0) { %>
+                                    <option value="1">材料调差(<%- auditMaterial.length %>)</option>
                                     <% } %>
-                                    <option value="1">材料调差</option>
                                 </select>
                             </div>
                         </div>
                         <div class="card-body p-0">
                             <div class="contant-height-one">
-                                <table class="table table-middle">
+                                <% if (auditTenders.length !== 0 || auditRevise.length !== 0 || auditStages.length !== 0 || auditChanges.length !== 0 || auditMaterial.length !== 0 || auditAdvance.length !== 0 || auditChangeProject.length !== 0 || auditChangeApply.length !== 0 || auditChangePlan.length !== 0) { %>
+                                <style>
+                                    #doing-list td {
+                                        word-wrap:break-word;
+                                    }
+                                </style>
+                                <table style="table-layout:fixed;" class="table table-middle">
                                     <thead class="thead-light">
                                     <tr>
-                                        <th class="pl-3">类型</th>
+                                        <th width="110" class="pl-3">类型</th>
                                         <th>名称</th>
                                         <th width="60">状态</th>
                                         <th width="120">创建时间</th>
-                                        <th width="80">操作</th>
+                                        <th width="90">操作</th>
                                     </tr>
                                     </thead>
                                     <tbody id="doing-list">
-                                    <% if (auditTenders.length !== 0 || auditRevise.length !== 0 || auditStages.length !== 0 || auditChanges.length !== 0 || auditMaterial.length !== 0 || auditAdvance.length !== 0 || auditChangeProject.length !== 0 || auditChangeApply.length !== 0 || auditChangePlan.length !== 0) { %>
+
                                         <% for (const t of auditTenders) { %>
                                             <% if (t.ledger_status === acLedger.status.checking) { %>
                                                 <tr data-type="5">
@@ -207,9 +225,14 @@
                                                 </tr>
                                             <% } %>
                                         <% } %>
-                                    <% } %>
                                     </tbody>
                                 </table>
+                                <% } else { %>
+                                        <div class="p-5 text-center text-muted">
+                                            <img src="/public/images/nulllogo.png" />
+                                            <div class="pt-3">暂时没有需要你处理的事项</div>
+                                        </div>
+                                <% } %>
                             </div>
                             <!--&lt;!&ndash;没有处理信息&ndash;&gt;-->
                             <!--<p class="text-center text-muted">暂时没有需要你处理的事项。</p>-->
@@ -253,7 +276,10 @@
                                 <ul class="list-group list-group-flush">
                                     <% if (msgList.length === 0) { %>
                                         <!--没有通知-->
-                                        <li class="list-group-item text-muted"><p class="text-center mb-0">暂时没有通知</p></li>
+                                        <li class="list-group-item text-muted text-center p-5">
+                                            <img src="/public/images/nulllogo.png" />
+                                            <p class="pt-2 text-center mb-0">暂时没有通知</p>
+                                        </li>
                                     <% } else { %>
                                         <% for (const msg of msgList) { %>
                                             <li class="list-group-item text-muted">
@@ -299,7 +325,13 @@
                         </div>
                         <div class="card-body p-0">
                             <div class="contant-height-one">
-                                <table class="table table-middle">
+                                <% if(noticeList.length) { %>
+                                <style>
+                                    #notice-list a {
+                                        word-wrap:break-word;
+                                    }
+                                </style>
+                                <table style="table-layout:fixed;" class="table table-middle">
                                     <thead class="thead-light">
                                     <tr>
                                         <th width="110" class="pl-3">类型</th>
@@ -312,7 +344,6 @@
                                     </tr>
                                     </thead>
                                     <tbody id="notice-list">
-                                    <% if(noticeList.length) { %>
                                         <!--<ul id="notice" class="list-unstyled m-0">-->
                                         <% for (const notice of noticeList) { %>
                                             <% if(notice.type === pushType.stage) { %>
@@ -407,9 +438,14 @@
                                                 </tr>
                                             <% } %>
                                         <% } %>
-                                    <% } %>
                                     </tbody>
                                 </table>
+                                <% } else { %>
+                                    <div class="p-5 text-center text-muted">
+                                        <img src="/public/images/nulllogo.png" />
+                                        <div class="pt-3">暂时没有需要你关注的事项</div>
+                                    </div>
+                                <% } %>
                             </div>
                         </div>
                         <!--没有关注信息-->
@@ -509,13 +545,8 @@
             }
         });
     })
-    $(window).resize(resizeChart);
-    function resizeChart() {
-        myChart1.resize()
-    }
-    var myChart1 = echarts.init(document.getElementById('jechart'));
     var transparentCount = 1;
-    option = {
+    const option = {
         // title: {
         //     text: '金额统计图',
         //     left: 'center',
@@ -545,7 +576,7 @@
             {
                 orient: 'vertical',
                 left: '3%',
-                top: '20%',
+                top: 'center',
                 itemWidth: 13,
                 itemHeight: 13,
                 textStyle: {
@@ -558,7 +589,7 @@
             {
                 orient: 'vertical',
                 right: '3%',
-                top: '20%',
+                top: 'center',
                 itemWidth: 13,
                 itemHeight: 13,
                 textStyle: {
@@ -573,8 +604,8 @@
             {
                 name: '审批次数',
                 type: 'pie',
-                radius: ['50%', '75%'],
-                right:'0',
+                radius: ['35%', '55%'],
+                center: ['50%', '50%'],
                 avoidLabelOverlap: false,
                 data: [
                     <% for (const sc of shenpi_count) { %>
@@ -594,9 +625,46 @@
             }
         ]
     };
+    function optionRadius() {
+        if ($(window).outerWidth() > 1366) {
+            if ($('#jechart').outerWidth() - $('#jechart').outerHeight() < 90) {
+                option.series[0].radius = ['35%', '55%'];
+            } else if ($('#jechart').outerWidth() < 320) {
+                option.series[0].radius = ['35%', '60%'];
+            } else if ($('#jechart').outerWidth() < 330) {
+                option.series[0].radius = ['40%', '65%'];
+            } else if ($('#jechart').outerWidth() < 350) {
+                option.series[0].radius = ['45%', '70%'];
+            } else {
+                option.series[0].radius = ['50%', '75%'];
+            }
+        } else {
+            option.series[0].radius = ['50%', '75%'];
+        }
+    }
+    function initChart() {
+        const myChart1 = echarts.init(document.getElementById('jechart'));
+        optionRadius();
+        myChart1.setOption(option, true);
+        window.addEventListener('resize', function () {
+            optionRadius();
+            myChart1.setOption(option, true);
+            myChart1.resize();
+        });
+    }
+    // initChart();
     setTimeout(function () {
-        myChart1.setOption(option);
-        resizeChart();
-        resizeChart();
+        initChart();
     },500);
+
+    // $(window).resize(resizeChart);
+    // function resizeChart() {
+    //     myChart1.resize()
+    // }
+    // var myChart1 = echarts.init(document.getElementById('jechart'));
+    // setTimeout(function () {
+    //     myChart1.setOption(option);
+    //     resizeChart();
+    //     // resizeChart();
+    // },500);
 </script>

+ 18 - 0
app/view/material/list_modal.ejs

@@ -50,5 +50,23 @@
         </div>
     </div>
 </div>
+<div class="modal fade" id="cancel-self" data-backdrop="static">
+    <div class="modal-dialog" role="document">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h5 class="modal-title">取消单独添加工料</h5>
+            </div>
+            <div class="modal-body">
+                <!--<h5>确认取消单独添加工料?</h5>-->
+                <h5>取消后将清空“单独添加工料窗口”,数据无法恢复,请谨慎操作。</h5>
+            </div>
+            <div class="modal-footer">
+                <input type="hidden" name="_csrf_j" value="<%= ctx.csrf %>" />
+                <button type="button" class="btn btn-secondary btn-sm" data-dismiss="modal">关闭</button>
+                <button type="button" id="cancelSelfBtn" class="btn btn-danger btn-sm">确定取消</button>
+            </div>
+        </div>
+    </div>
+</div>
 <% } %>
 <% include ./audit_modal.ejs %>

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

@@ -169,7 +169,7 @@
             {title: '截止本期计量金额|合同计量', colSpan: '4|1', rowSpan: '1|1', field: 'end_contract_tp', hAlign: 2, width: 70, type: 'Number'},
             {title: '|数量变更', colSpan: '|1', rowSpan: '|1', field: 'end_qc_tp', hAlign: 2, width: 70, type: 'Number'},
             {title: '|完成计量', colSpan: '|1', rowSpan: '|1', field: 'end_gather_tp', hAlign: 2, width: 70, type: 'Number'},
-            {title: '|完成率(%)', colSpan: '|1', rowSpan: '|1', field: 'end_gather_percent', hAlign: 2, width: 70, type: 'Number'},
+            {title: '|完成率(%)', colSpan: '|1', rowSpan: '|1', field: 'end_gather_percent', hAlign: 2, width: 80, readOnly: true, type: 'Number'},
             {title: '图(册)号', colSpan: '1', rowSpan: '2', field: 'drawing_code', hAlign: 0, width: 80, formatter: '@'},
             {title: '本期批注', colSpan: '1', rowSpan: '2', field: 'postil', hAlign: 0, width: 100, formatter: '@', cellType: 'ellipsisAutoTip'},
             {title: '备注', colSpan: '1', rowSpan: '2', field: 'memo', hAlign: 0, width: 100, formatter: '@', cellType: 'ellipsisAutoTip'},
@@ -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: 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: '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 - 1
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.stage.readOnly && !ctx.stage.revising && ctx.stage.status === auditConst.status.uncheck) { %>
+                    <% if (ctx.app.config.is_debug && !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>

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

@@ -114,7 +114,7 @@
             <div class="modal-body">
                 <table class="table table-sm table-bordered">
                     <thead>
-                    <tr class="text-center"><th>章节名称</th><th>本期合同计量金额</th><th>本期变更计量金额</th><th>本期完成计量金</th><th>累计完成计量金额</th></tr>
+                    <tr class="text-center"><th>章节名称</th><th>本期合同计量金额</th><th>本期变更计量金额</th><th>本期完成计量金</th><th>累计完成计量金额</th></tr>
                     </thead>
                     <tbody id="detail-list"></tbody>
                 </table>

+ 6 - 0
app/view/tender/detail_modal.ejs

@@ -758,6 +758,7 @@
                         <tr><td>分账划拨比例(%)</td><td><input type="text" id="project-rate" class="form-control form-control-sm" oninput="limitReturn(this)"></td></tr>
                         <tr><td>联系人</td><td><input type="text" id="project-contact" class="form-control form-control-sm" oninput="limitReturn(this)"></td></tr>
                         <tr><td>联系电话</td><td><input type="text" id="project-phone" class="form-control form-control-sm" oninput="limitReturn(this)"></td></tr>
+                        <tr><td>行号</td><td><input type="text" id="project-num" class="form-control form-control-sm" oninput="limitReturn(this)"></td></tr>
                         <tr><th colspan="2" class="text-center">农民工工资专用账户</th></tr>
                         <tr><td>开户名称</td><td><input type="text" id="worker-name" class="form-control form-control-sm" oninput="limitReturn(this)"></td></tr>
                         <tr><td>开户银行</td><td><input type="text" id="worker-bank" class="form-control form-control-sm" oninput="limitReturn(this)"></td></tr>
@@ -765,6 +766,7 @@
                         <tr><td>分账划拨比例(%)</td><td><input type="text" id="worker-rate" class="form-control form-control-sm" oninput="limitReturn(this)"></td></tr>
                         <tr><td>联系人</td><td><input type="text" id="worker-contact" class="form-control form-control-sm" oninput="limitReturn(this)"></td></tr>
                         <tr><td>联系电话</td><td><input type="text" id="worker-phone" class="form-control form-control-sm" oninput="limitReturn(this)"></td></tr>
+                        <tr><td>行号</td><td><input type="text" id="worker-num" class="form-control form-control-sm" oninput="limitReturn(this)"></td></tr>
                     </table>
                 </div>
             </div>
@@ -1615,6 +1617,7 @@
         $('#project-rate').val(property.pay_account.project.rate);
         $('#project-contact').val(property.pay_account.project.contact);
         $('#project-phone').val(property.pay_account.project.phone);
+        $('#project-num').val(property.pay_account.project.num);
 
         $('#worker-name').val(property.pay_account.worker.name);
         $('#worker-bank').val(property.pay_account.worker.bank);
@@ -1622,6 +1625,7 @@
         $('#worker-rate').val(property.pay_account.worker.rate);
         $('#worker-contact').val(property.pay_account.worker.contact);
         $('#worker-phone').val(property.pay_account.worker.phone);
+        $('#worker-num').val(property.pay_account.worker.num);
     }
     $('#bd-set-7').on('show.bs.modal', function () {
         loadPayProperty();
@@ -1666,6 +1670,7 @@
                     rate: $('#project-rate').val(),
                     contact: $('#project-contact').val(),
                     phone: $('#project-phone').val(),
+                    num: $('#project-num').val(),
                 },
                 worker: {
                     name: $('#worker-name').val(),
@@ -1674,6 +1679,7 @@
                     rate: $('#worker-rate').val(),
                     contact: $('#worker-contact').val(),
                     phone: $('#worker-phone').val(),
+                    num: $('#worker-num').val(),
                 },
             },
         };

+ 1 - 1
app/view/tender/manage_modal.ejs

@@ -63,7 +63,7 @@
             </div>
             <div class="modal-body">
                 <h5>删除后,数据无法恢复,请谨慎操作。</h5>
-                <h5>确定删除「<strong id="del-tender-name"></strong>」?</h5>
+                <h5>确定删除「<strong style="word-break: break-word;" id="del-tender-name"></strong>」?</h5>
             </div>
             <div class="modal-footer">
                 <button type="button" class="btn btn-secondary btn-sm" data-dismiss="modal">关闭</button>

+ 1 - 1
app/view/wap/dashboard.ejs

@@ -79,7 +79,7 @@
                                 <table class="table table-sm table-bordered">
                                     <tr><th width="90">修订时间</th><td class="text-right"><%- ctx.moment(revise.in_time).format('YYYY-MM-DD') %></td></tr>
                                     <tr><th>修订人</th><td class="text-right"><%- revise.yb_name %></td></tr>
-                                    <tr><th>修订详情</th><td class=""><% if (revise.content.length <= 22) { %><%- revise.content %><% } else { %><%- revise.content.substring(0,22) %><a class="show-content" data-content="<%- revise.content %>" href="javascript:void(0);">展开更多</a><% } %></td></tr>
+                                    <tr><th>修订详情</th><td class=""><% if (!revise.content || revise.content.length <= 22) { %><%- revise.content %><% } else { %><%- revise.content.substring(0,22) %><a class="show-content" data-content="<%- revise.content %>" href="javascript:void(0);">展开更多</a><% } %></td></tr>
                                 </table>
                             </div>
                             <div class="">

+ 16 - 0
builder_report_index_define.js

@@ -709,6 +709,15 @@ const stage_bills = {
         { name: '备注1', field: 'ex_memo1', type: dataType.str },
         { 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: '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 },
+        { name: '1#台账+截止本期变更-金额', field: 'end_final_1_tp', type: dataType.double },
+        { name: '1#完成率(%)', field: 'final_1_ratio', type: dataType.double },
     ],
 };
 const stage_bills_compare = {
@@ -883,6 +892,13 @@ const stage_pos = {
         { name: '备注3', field: 'ex_memo3', type: dataType.str },
 
         { 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: '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 },
     ],
 };
 const stage_pos_compare = {

+ 1 - 1
config/config.default.js

@@ -230,7 +230,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/';

+ 82 - 0
db_script/ledger_his_count.js

@@ -0,0 +1,82 @@
+'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) {
+  const File = await ossClient.get(options.hisOssPath + url);
+  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');
+      for (const l of ledgerHis) {
+        await doCompleteLedgerHis(l);
+      }
+    } catch (err) {
+      console.log(err);
+    }
+    pool.end();
+};
+doComplete();
+

+ 3 - 112
sql/update.sql

@@ -1,112 +1,3 @@
-ALTER TABLE `zh_budget`
-ADD COLUMN `final_time`  timestamp NULL DEFAULT NULL COMMENT '生成动态决算时间' AFTER `decimal`,
-ADD COLUMN `final_id`  int(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `final_time`;
-
-CREATE TABLE `zh_budget_final_list` (
-  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
-  `bid` int(11) unsigned NOT NULL COMMENT '动态决算id',
-  `uid` int(11) unsigned NOT NULL COMMENT '生成决算人id',
-  `u_name` varchar(30) COLLATE utf8_unicode_ci NOT NULL DEFAULT '' COMMENT '生成决算人-名字(缓存)',
-  `u_role` varchar(30) COLLATE utf8_unicode_ci NOT NULL DEFAULT '' COMMENT '生成决算人-角色(缓存)',
-  `u_company` varchar(60) COLLATE utf8_unicode_ci NOT NULL DEFAULT '' COMMENT '生成决算人-单位(缓存)',
-  `u_mobile` varchar(15) COLLATE utf8_unicode_ci NOT NULL DEFAULT '' COMMENT '生成决算人-电话',
-  `u_login` varchar(10) COLLATE utf8_unicode_ci NOT NULL DEFAULT '0' COMMENT '生成决算人-登录方式',
-  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
-  `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
-  `tender` varchar(1000) COLLATE utf8_unicode_ci NOT NULL DEFAULT '' COMMENT '关联标段id('',''分隔)',
-  `tender_info` text COLLATE utf8_unicode_ci COMMENT '关联标段信息(json)',
-  `status` tinyint(4) unsigned NOT NULL DEFAULT '0' COMMENT '0: 取消, 1: 等待, 2: 进行中, 3: 完成',
-  PRIMARY KEY (`id`),
-  KEY `idx_bid` (`bid`,`create_time`) USING BTREE
-) ENGINE=InnoDB AUTO_INCREMENT=26 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
-
-CREATE TABLE `zh_budget_final` (
-  `id` varchar(36) COLLATE utf8_unicode_ci NOT NULL,
-  `bid` int(11) unsigned NOT NULL COMMENT '概算投资项目id',
-  `final_id` bigint(11) unsigned NOT NULL COMMENT '决算id',
-  `tree_id` int(11) unsigned NOT NULL COMMENT '树结构id',
-  `tree_pid` int(11) NOT NULL COMMENT '树结构父id',
-  `level` int(11) unsigned NOT NULL COMMENT '层级',
-  `order` int(11) unsigned NOT NULL COMMENT '同级排序',
-  `full_path` varchar(255) CHARACTER SET utf8 NOT NULL DEFAULT '' COMMENT '层级定位辅助字段parent.full_path.ledger_id',
-  `is_leaf` tinyint(1) NOT NULL COMMENT '是否叶子节点,界面显示辅助字段',
-  `code` varchar(50) CHARACTER SET utf8 NOT NULL DEFAULT '' COMMENT '节点编号',
-  `name` varchar(255) CHARACTER SET utf8 NOT NULL DEFAULT '' COMMENT '名称',
-  `unit` varchar(15) CHARACTER SET utf8 NOT NULL DEFAULT '' COMMENT '单位',
-  `gu_dgn_qty1` decimal(24,8) NOT NULL DEFAULT '0.00000000' COMMENT '估算-设计数量1',
-  `gu_dgn_qty2` decimal(24,8) NOT NULL DEFAULT '0.00000000' COMMENT '估算-设计数量1',
-  `gu_dgn_qty` varchar(50) COLLATE utf8_unicode_ci NOT NULL DEFAULT '' COMMENT '估算-设计数量1/设计数量2',
-  `gu_dgn_price` decimal(24,8) NOT NULL DEFAULT '0.00000000' COMMENT '估算-经济指标',
-  `gu_tp` decimal(24,8) NOT NULL DEFAULT '0.00000000' COMMENT '估算-金额',
-  `gai_dgn_qty1` decimal(24,8) NOT NULL DEFAULT '0.00000000' COMMENT '概算-设计数量1',
-  `gai_dgn_qty2` decimal(24,8) NOT NULL DEFAULT '0.00000000' COMMENT '概算-设计数量1',
-  `gai_dgn_qty` varchar(50) COLLATE utf8_unicode_ci NOT NULL DEFAULT '' COMMENT '概算-设计数量1/设计数量2',
-  `gai_dgn_price` decimal(24,8) NOT NULL DEFAULT '0.00000000' COMMENT '概算-经济指标',
-  `gai_tp` decimal(24,8) NOT NULL DEFAULT '0.00000000' COMMENT '概算-金额',
-  `yu_dgn_qty1` decimal(24,8) NOT NULL DEFAULT '0.00000000' COMMENT '预算-设计数量1',
-  `yu_dgn_qty2` decimal(24,8) NOT NULL DEFAULT '0.00000000' COMMENT '预算-设计数量1',
-  `yu_dgn_qty` varchar(50) COLLATE utf8_unicode_ci NOT NULL DEFAULT '' COMMENT '预算-设计数量1/设计数量2',
-  `yu_dgn_price` decimal(24,8) NOT NULL DEFAULT '0.00000000' COMMENT '预算-经济指标',
-  `yu_tp` decimal(24,8) NOT NULL DEFAULT '0.00000000' COMMENT '预算-金额',
-  `dgn_qty1` decimal(24,8) NOT NULL DEFAULT '0.00000000' COMMENT '决算-台账-设计数量1',
-  `dgn_qty2` decimal(24,8) NOT NULL DEFAULT '0.00000000' COMMENT '决算-台账-设计数量1',
-  `total_price` decimal(24,8) NOT NULL DEFAULT '0.00000000' COMMENT '决算-台账-经济指标',
-  `dgn_price` decimal(24,8) NOT NULL DEFAULT '0.00000000' COMMENT '决算-台账-经济指标',
-  `dgn_qty` varchar(50) COLLATE utf8_unicode_ci NOT NULL DEFAULT '' COMMENT '决算-台账-设计数量1/设计数量2',
-  `final_dgn_qty1` decimal(24,8) NOT NULL DEFAULT '0.00000000' COMMENT '决算-设计数量1',
-  `final_dgn_qty2` decimal(24,8) NOT NULL DEFAULT '0.00000000' COMMENT '决算-设计数量1',
-  `final_tp` decimal(24,8) NOT NULL DEFAULT '0.00000000' COMMENT '决算-金额',
-  `final_dgn_price` decimal(24,8) NOT NULL DEFAULT '0.00000000' COMMENT '决算-经济指标',
-  `final_dgn_qty` varchar(50) COLLATE utf8_unicode_ci NOT NULL DEFAULT '' COMMENT '决算-设计数量1/设计数量2',
-  `grow_dgn_qty1` decimal(24,8) NOT NULL DEFAULT '0.00000000' COMMENT '增幅%-设计数量1',
-  `grow_dgn_qty2` decimal(24,8) NOT NULL DEFAULT '0.00000000' COMMENT '增幅%-设计数量1',
-  `grow_tp` decimal(24,8) NOT NULL DEFAULT '0.00000000' COMMENT '增幅%-金额',
-  `grow_dgn_qty` varchar(50) COLLATE utf8_unicode_ci NOT NULL DEFAULT '' COMMENT '增幅%-设计数量1/设计数量2',
-  PRIMARY KEY (`id`),
-  KEY `idx_fid` (`final_id`) USING BTREE
-) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
-
-ALTER TABLE `zh_material_list_gcl` ADD `old_quantity` DECIMAL(30,8) NULL DEFAULT NULL COMMENT '数量,用于复原数据' AFTER `expr`,
-ADD `old_expr` VARCHAR(255) NULL DEFAULT NULL COMMENT '公式,用于复原数据' AFTER `old_quantity`;
-
-UPDATE `zh_material_list_gcl` SET `old_quantity`=`quantity`,`old_expr`=`expr`;
-
-ALTER TABLE `zh_material` ADD `exponent_rate` TINYINT(3) NULL DEFAULT '0' COMMENT '材料税税率' AFTER `rate`;
-
-UPDATE `zh_material` SET `exponent_rate`=`rate`;
-
-ALTER TABLE `zh_material_list` ADD `is_self` TINYINT(1) NOT NULL DEFAULT '0' COMMENT '是否为单独添加的工料清单关联' AFTER `is_join`;
-
-UPDATE `zh_material_list` SET `mx_id`= '' WHERE `mx_id` is null;
-
-ALTER TABLE `zh_material_list_notjoin` CHANGE `mx_id` `mx_id` VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT '' COMMENT '部位明细id';
-
-UPDATE `zh_material_list_notjoin` SET `mx_id`= '' WHERE `mx_id` is null;
-
-CREATE TABLE `zh_material_list_self`  (
-  `id` int(11) NOT NULL AUTO_INCREMENT,
-  `tid` int(11) NOT NULL COMMENT '标段id',
-  `mid` int(11) NOT NULL COMMENT '调差期id',
-  `gcl_id` varchar(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '清单id',
-  `xmj_id` varchar(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '项目节id',
-  `mx_id` varchar(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT '' COMMENT '部位明细id',
-  `in_time` datetime NOT NULL COMMENT '添加时间',
-  PRIMARY KEY (`id`) USING BTREE
-) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_unicode_ci COMMENT = '单独调差的清单表';
-
-ALTER TABLE `zh_advance_pay`
-ADD COLUMN `selected`  tinyint(4) UNSIGNED NOT NULL DEFAULT 0 COMMENT '报表用,是否选择' AFTER `id`;
-
-ALTER TABLE `zh_stage_change_final`
-ADD COLUMN `sorder`  int(11) UNSIGNED NOT NULL AFTER `sid`;
-
-Update zh_stage_change_final scf Join zh_stage s on scf.sid = s.id Set scf.sorder = s.`order`;
-
-ALTER TABLE `zh_change` ADD `order_by` TINYINT(1) NOT NULL DEFAULT '0' COMMENT '清单排序规则,默认按清单编号排(0),自定义排序(1)' AFTER `is_revise`;
-ALTER TABLE `zh_change_audit_list` ADD `order` INT NULL DEFAULT NULL COMMENT '排序序号(自定义规则时使用)' AFTER `spamount`;
-
-ALTER TABLE `zh_stage_change`
-ADD COLUMN `minus`  tinyint(4) UNSIGNED NOT NULL DEFAULT 0 COMMENT '是否负变更' AFTER `qty`;
-
-ALTER TABLE `zh_stage_change_final`
-ADD COLUMN `minus`  tinyint(4) UNSIGNED NOT NULL DEFAULT 0 COMMENT '是否负变更' AFTER `qty`;
+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`;

+ 134 - 0
sql/update20220624.sql

@@ -0,0 +1,134 @@
+ALTER TABLE `zh_budget`
+ADD COLUMN `final_time`  timestamp NULL DEFAULT NULL COMMENT '生成动态决算时间' AFTER `decimal`,
+ADD COLUMN `final_id`  int(11) UNSIGNED NOT NULL DEFAULT 0 AFTER `final_time`;
+
+CREATE TABLE `zh_budget_final_list` (
+  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
+  `bid` int(11) unsigned NOT NULL COMMENT '动态决算id',
+  `uid` int(11) unsigned NOT NULL COMMENT '生成决算人id',
+  `u_name` varchar(30) COLLATE utf8_unicode_ci NOT NULL DEFAULT '' COMMENT '生成决算人-名字(缓存)',
+  `u_role` varchar(30) COLLATE utf8_unicode_ci NOT NULL DEFAULT '' COMMENT '生成决算人-角色(缓存)',
+  `u_company` varchar(60) COLLATE utf8_unicode_ci NOT NULL DEFAULT '' COMMENT '生成决算人-单位(缓存)',
+  `u_mobile` varchar(15) COLLATE utf8_unicode_ci NOT NULL DEFAULT '' COMMENT '生成决算人-电话',
+  `u_login` varchar(10) COLLATE utf8_unicode_ci NOT NULL DEFAULT '0' COMMENT '生成决算人-登录方式',
+  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+  `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',
+  `tender` varchar(1000) COLLATE utf8_unicode_ci NOT NULL DEFAULT '' COMMENT '关联标段id('',''分隔)',
+  `tender_info` text COLLATE utf8_unicode_ci COMMENT '关联标段信息(json)',
+  `status` tinyint(4) unsigned NOT NULL DEFAULT '0' COMMENT '0: 取消, 1: 等待, 2: 进行中, 3: 完成',
+  PRIMARY KEY (`id`),
+  KEY `idx_bid` (`bid`,`create_time`) USING BTREE
+) ENGINE=InnoDB AUTO_INCREMENT=26 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
+
+CREATE TABLE `zh_budget_final` (
+  `id` varchar(36) COLLATE utf8_unicode_ci NOT NULL,
+  `bid` int(11) unsigned NOT NULL COMMENT '概算投资项目id',
+  `final_id` bigint(11) unsigned NOT NULL COMMENT '决算id',
+  `tree_id` int(11) unsigned NOT NULL COMMENT '树结构id',
+  `tree_pid` int(11) NOT NULL COMMENT '树结构父id',
+  `level` int(11) unsigned NOT NULL COMMENT '层级',
+  `order` int(11) unsigned NOT NULL COMMENT '同级排序',
+  `full_path` varchar(255) CHARACTER SET utf8 NOT NULL DEFAULT '' COMMENT '层级定位辅助字段parent.full_path.ledger_id',
+  `is_leaf` tinyint(1) NOT NULL COMMENT '是否叶子节点,界面显示辅助字段',
+  `code` varchar(50) CHARACTER SET utf8 NOT NULL DEFAULT '' COMMENT '节点编号',
+  `name` varchar(255) CHARACTER SET utf8 NOT NULL DEFAULT '' COMMENT '名称',
+  `unit` varchar(15) CHARACTER SET utf8 NOT NULL DEFAULT '' COMMENT '单位',
+  `gu_dgn_qty1` decimal(24,8) NOT NULL DEFAULT '0.00000000' COMMENT '估算-设计数量1',
+  `gu_dgn_qty2` decimal(24,8) NOT NULL DEFAULT '0.00000000' COMMENT '估算-设计数量1',
+  `gu_dgn_qty` varchar(50) COLLATE utf8_unicode_ci NOT NULL DEFAULT '' COMMENT '估算-设计数量1/设计数量2',
+  `gu_dgn_price` decimal(24,8) NOT NULL DEFAULT '0.00000000' COMMENT '估算-经济指标',
+  `gu_tp` decimal(24,8) NOT NULL DEFAULT '0.00000000' COMMENT '估算-金额',
+  `gai_dgn_qty1` decimal(24,8) NOT NULL DEFAULT '0.00000000' COMMENT '概算-设计数量1',
+  `gai_dgn_qty2` decimal(24,8) NOT NULL DEFAULT '0.00000000' COMMENT '概算-设计数量1',
+  `gai_dgn_qty` varchar(50) COLLATE utf8_unicode_ci NOT NULL DEFAULT '' COMMENT '概算-设计数量1/设计数量2',
+  `gai_dgn_price` decimal(24,8) NOT NULL DEFAULT '0.00000000' COMMENT '概算-经济指标',
+  `gai_tp` decimal(24,8) NOT NULL DEFAULT '0.00000000' COMMENT '概算-金额',
+  `yu_dgn_qty1` decimal(24,8) NOT NULL DEFAULT '0.00000000' COMMENT '预算-设计数量1',
+  `yu_dgn_qty2` decimal(24,8) NOT NULL DEFAULT '0.00000000' COMMENT '预算-设计数量1',
+  `yu_dgn_qty` varchar(50) COLLATE utf8_unicode_ci NOT NULL DEFAULT '' COMMENT '预算-设计数量1/设计数量2',
+  `yu_dgn_price` decimal(24,8) NOT NULL DEFAULT '0.00000000' COMMENT '预算-经济指标',
+  `yu_tp` decimal(24,8) NOT NULL DEFAULT '0.00000000' COMMENT '预算-金额',
+  `dgn_qty1` decimal(24,8) NOT NULL DEFAULT '0.00000000' COMMENT '决算-台账-设计数量1',
+  `dgn_qty2` decimal(24,8) NOT NULL DEFAULT '0.00000000' COMMENT '决算-台账-设计数量1',
+  `total_price` decimal(24,8) NOT NULL DEFAULT '0.00000000' COMMENT '决算-台账-经济指标',
+  `dgn_price` decimal(24,8) NOT NULL DEFAULT '0.00000000' COMMENT '决算-台账-经济指标',
+  `dgn_qty` varchar(50) COLLATE utf8_unicode_ci NOT NULL DEFAULT '' COMMENT '决算-台账-设计数量1/设计数量2',
+  `final_dgn_qty1` decimal(24,8) NOT NULL DEFAULT '0.00000000' COMMENT '决算-设计数量1',
+  `final_dgn_qty2` decimal(24,8) NOT NULL DEFAULT '0.00000000' COMMENT '决算-设计数量1',
+  `final_tp` decimal(24,8) NOT NULL DEFAULT '0.00000000' COMMENT '决算-金额',
+  `final_dgn_price` decimal(24,8) NOT NULL DEFAULT '0.00000000' COMMENT '决算-经济指标',
+  `final_dgn_qty` varchar(50) COLLATE utf8_unicode_ci NOT NULL DEFAULT '' COMMENT '决算-设计数量1/设计数量2',
+  `grow_dgn_qty1` decimal(24,8) NOT NULL DEFAULT '0.00000000' COMMENT '增幅%-设计数量1',
+  `grow_dgn_qty2` decimal(24,8) NOT NULL DEFAULT '0.00000000' COMMENT '增幅%-设计数量1',
+  `grow_tp` decimal(24,8) NOT NULL DEFAULT '0.00000000' COMMENT '增幅%-金额',
+  `grow_dgn_qty` varchar(50) COLLATE utf8_unicode_ci NOT NULL DEFAULT '' COMMENT '增幅%-设计数量1/设计数量2',
+  PRIMARY KEY (`id`),
+  KEY `idx_fid` (`final_id`) USING BTREE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
+
+ALTER TABLE `zh_material_list_gcl` ADD `old_quantity` DECIMAL(30,8) NULL DEFAULT NULL COMMENT '数量,用于复原数据' AFTER `expr`,
+ADD `old_expr` VARCHAR(255) NULL DEFAULT NULL COMMENT '公式,用于复原数据' AFTER `old_quantity`;
+
+ALTER TABLE `zh_material` ADD `exponent_rate` TINYINT(3) NULL DEFAULT '0' COMMENT '材料税税率' AFTER `rate`;
+
+ALTER TABLE `zh_material_list` ADD `is_self` TINYINT(1) NOT NULL DEFAULT '0' COMMENT '是否为单独添加的工料清单关联' AFTER `is_join`;
+
+ALTER TABLE `zh_material_list_notjoin` CHANGE `mx_id` `mx_id` VARCHAR(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT '' COMMENT '部位明细id';
+
+CREATE TABLE `zh_material_list_self`  (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `tid` int(11) NOT NULL COMMENT '标段id',
+  `mid` int(11) NOT NULL COMMENT '调差期id',
+  `gcl_id` varchar(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '清单id',
+  `xmj_id` varchar(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '项目节id',
+  `mx_id` varchar(100) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT '' COMMENT '部位明细id',
+  `in_time` datetime NOT NULL COMMENT '添加时间',
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_unicode_ci COMMENT = '单独调差的清单表';
+
+ALTER TABLE `zh_advance_pay`
+ADD COLUMN `selected`  tinyint(4) UNSIGNED NOT NULL DEFAULT 0 COMMENT '报表用,是否选择' AFTER `id`;
+
+ALTER TABLE `zh_stage_change_final`
+ADD COLUMN `sorder`  int(11) UNSIGNED NOT NULL AFTER `sid`;
+
+ALTER TABLE `zh_change` ADD `order_by` TINYINT(1) NOT NULL DEFAULT '0' COMMENT '清单排序规则,默认按清单编号排(0),自定义排序(1)' AFTER `is_revise`;
+ALTER TABLE `zh_change_audit_list` ADD `order` INT NULL DEFAULT NULL COMMENT '排序序号(自定义规则时使用)' AFTER `spamount`;
+
+ALTER TABLE `zh_stage_change`
+ADD COLUMN `minus`  tinyint(4) UNSIGNED NOT NULL DEFAULT 0 COMMENT '是否负变更' AFTER `qty`;
+
+ALTER TABLE `zh_stage_change_final`
+ADD COLUMN `minus`  tinyint(4) UNSIGNED NOT NULL DEFAULT 0 COMMENT '是否负变更' AFTER `qty`;
+
+CREATE TABLE `zh_stage_stash` (
+  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
+  `pid` int(11) unsigned NOT NULL COMMENT '项目id',
+  `tid` int(11) unsigned NOT NULL COMMENT '标段id',
+  `sid` int(11) unsigned NOT NULL COMMENT '期id',
+  `sorder` int(11) unsigned NOT NULL COMMENT '期序号',
+  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
+  `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+  `uid` int(11) unsigned NOT NULL COMMENT '保存人',
+  `uname` varchar(255) COLLATE utf8_unicode_ci NOT NULL DEFAULT '' COMMENT '保存人姓名',
+  `filepath` varchar(255) COLLATE utf8_unicode_ci NOT NULL COMMENT 'oss保存路径',
+  `valid` tinyint(4) unsigned NOT NULL DEFAULT '1' COMMENT '是否可用',
+  `info` varchar(1000) COLLATE utf8_unicode_ci NOT NULL DEFAULT '' COMMENT '相关信息',
+  `remark` varchar(255) COLLATE utf8_unicode_ci NOT NULL DEFAULT '' COMMENT '备注',
+  PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
+
+
+Update zh_stage_change_final scf Join zh_stage s on scf.sid = s.id Set scf.sorder = s.`order`;
+
+UPDATE `zh_material_list_notjoin` SET `mx_id`= '' WHERE `mx_id` is null;
+
+UPDATE `zh_material_list` SET `mx_id`= '' WHERE `mx_id` is null;
+
+UPDATE `zh_material` SET `exponent_rate`=`rate`;
+
+UPDATE `zh_material_list_gcl` SET `old_quantity`=`quantity`,`old_expr`=`expr`;
+
+Update zh_stage_change sc Left Join zh_change_audit_list cal ON sc.cbid = cal.id Set sc.minus = 1 WHERE sc.minus = 0 and cal.spamount < 0;
+
+Update zh_stage_change_final sc Left Join zh_change_audit_list cal ON sc.cbid = cal.id Set sc.minus = 1 WHERE sc.minus = 0 and cal.spamount < 0;