Parcourir la source

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

Tony Kang il y a 1 an
Parent
commit
be8441237e
52 fichiers modifiés avec 1174 ajouts et 442 suppressions
  1. 45 0
      app/const/project_setting.js
  2. 200 1
      app/const/spread.js
  3. 17 0
      app/controller/project_controller.js
  4. 24 21
      app/controller/revise_controller.js
  5. 13 9
      app/controller/setting_controller.js
  6. 8 17
      app/controller/stage_controller.js
  7. 15 3
      app/controller/tender_controller.js
  8. 1 1
      app/lib/budget_final.js
  9. 1 1
      app/lib/pay_calc.js
  10. 71 2
      app/lib/revise_price.js
  11. 3 3
      app/lib/rptCustomData.js
  12. 13 10
      app/lib/spread_setting.js
  13. 2 2
      app/lib/stage_im.js
  14. 1 1
      app/lib/tender_info.js
  15. 1 0
      app/middleware/stage_check.js
  16. 2 2
      app/public/js/file_detail.js
  17. 4 4
      app/public/js/project_spread.js
  18. 1 0
      app/public/js/revise.js
  19. 7 3
      app/public/js/setting.js
  20. 39 38
      app/public/js/shares/sjs_setting.js
  21. 1 3
      app/public/js/stage.js
  22. 160 89
      app/public/js/tender_list_info.js
  23. 1 0
      app/router.js
  24. 2 2
      app/service/change.js
  25. 24 15
      app/service/project_account.js
  26. 75 0
      app/service/project_col_set.js
  27. 52 21
      app/service/project_spread.js
  28. 6 6
      app/service/report_memory.js
  29. 6 6
      app/service/rpt_gather_memory.js
  30. 1 1
      app/service/settle.js
  31. 43 20
      app/service/stage.js
  32. 21 3
      app/service/stage_audit.js
  33. 23 4
      app/service/stage_pay.js
  34. 4 0
      app/service/tender_cache.js
  35. 2 2
      app/view/file/file.ejs
  36. 1 2
      app/view/measure/stage.ejs
  37. 1 2
      app/view/measure/stage_modal.ejs
  38. 31 19
      app/view/setting/show.ejs
  39. 1 0
      app/view/setting/spread.ejs
  40. 4 3
      app/view/setting/user.ejs
  41. 1 1
      app/view/setting/user_add_modal.ejs
  42. 4 3
      app/view/setting/user_permission.ejs
  43. 5 4
      app/view/setting/user_unit.ejs
  44. 5 0
      app/view/stage/audit_btn.ejs
  45. 1 1
      app/view/stage/pay.ejs
  46. 1 0
      app/view/tender/detail.ejs
  47. 49 6
      app/view/tender/detail_modal.ejs
  48. 60 1
      app/view/tender/modal.ejs
  49. 6 3
      app/view/tender/sub_menu.ejs
  50. 39 33
      db_script/project_spread.js
  51. 2 74
      sql/update.sql
  52. 74 0
      sql/update20240313.sql

+ 45 - 0
app/const/project_setting.js

@@ -21,6 +21,51 @@ const notice_setting = {
         end: null,
     },
 };
+
+const colSet = {
+    info: [
+        { field: 'name', name: '标段名称', fixed: ['show', 'alias'] },
+        { field: 'measure_type', name: '计量模式', fixed: ['show', 'alias'] },
+        { field: 'calc_flow', name: '计量进度', fixed: ['show', 'alias'] },
+        { field: 'cur_flow', name: '当前流程', fixed: ['show', 'alias'] },
+        { field: 'contract_price', name: '签约合同价', fixed: ['show', 'alias'] },
+        { field: 'total_price', name: '0号台账', fixed: [] },
+        { field: 'gather_tp', name: '本期完成', fixed: [] },
+        { field: 'end_contract_tp', name: '截止本期合同', fixed: [] },
+        { field: 'end_qc_tp', name: '截止本期变更', fixed: [] },
+        { field: 'end_gather_tp', name: '截止本期完成', fixed: [] },
+        { field: 'pre_gather_tp', name: '截止上期完成', fixed: [] },
+        { field: 'advance_tp', name: '预付款', fixed: [] },
+        { field: 'yf_tp', name: '本期应付', fixed: [] },
+        { field: 'end_yf_tp', name: '截止本期应付', fixed: [] },
+        { field: 'sf_tp', name: '本期实付', fixed: [] },
+        { field: 'end_sf_tp', name: '截止本期实付', fixed: [] },
+        { field: 'wf_tp', name: '未付金额', fixed: [], hint:'截止本期完成-截止本期实付' },
+    ]
+};
+const defaultColSet = {
+    info: [
+        { field: 'name', show: 1, alias: '' },
+        { field: 'measure_type', show: 1, alias: '' },
+        { field: 'calc_flow', show: 1, alias: '' },
+        { field: 'cur_flow', show: 1, alias: '' },
+        { field: 'contract_price', show: 1, alias: '' },
+        { field: 'total_price', show: 1, alias: '' },
+        { field: 'gather_tp', show: 1, alias: '' },
+        { field: 'end_contract_tp', show: 1, alias: '' },
+        { field: 'end_qc_tp', show: 1, alias: '' },
+        { field: 'end_gather_tp', show: 1, alias: '' },
+        { field: 'pre_gather_tp', show: 1, alias: '' },
+        { field: 'advance_tp', show: 1, alias: '' },
+        { field: 'yf_tp', show: 1, alias: '' },
+        { field: 'end_yf_tp', show: 1, alias: '' },
+        { field: 'sf_tp', show: 0, alias: '' },
+        { field: 'end_sf_tp', show: 0, alias: '' },
+        { field: 'wf_tp', show: 0, alias: '' },
+    ],
+};
 module.exports = {
     noticeSetting: notice_setting,
+    colSet,
+    defaultColSet,
 };

+ 200 - 1
app/const/spread.js

@@ -118,6 +118,7 @@ const BaseSetCol = {
         { key: 'b_code', name: '清单编号', fixed: ['alias'], bills: 1, pos: 0, },
         { key: 'ex_memo1', name: '备注1', fixed: [], bills: 1, pos: 1, },
         { key: 'name', name: '名称/计量单元', fixed: ['alias'], bills: 1, pos: 1 },
+        { key: 'features', name: '项目特征', fixed: ['valid', 'alias'], bills: 1, pos: 0 },
         { key: 'position', name: '位置', fixed: [], bills: 0, pos: 1 },
         { key: 'unit', name: '单位', fixed: ['alias'], bills: 1, pos: 0 },
         { key: 'unit_price', name: '单价', fixed: ['alias'], bills: 1, pos: 0 },
@@ -136,6 +137,7 @@ const BaseSetCol = {
         { key: 'b_code', name: '清单编号', fixed: ['alias'], bills: 1, pos: 0 },
         { key: 'ex_memo1', name: '备注1', fixed: [], bills: 1, pos: 1, },
         { key: 'name', name: '名称/计量单元', fixed: ['alias'], bills: 1, pos: 1 },
+        { key: 'features', name: '项目特征', fixed: ['valid', 'alias'], bills: 1, pos: 0 },
         { key: 'position', name: '位置', fixed: [], bills: 0, pos: 1},
         { key: 'unit', name: '单位', fixed: ['alias'], bills: 1, pos: 0 },
         { key: 'unit_price', name: '单价', fixed: ['alias'], bills: 1, pos: 0 },
@@ -159,12 +161,13 @@ const BaseSetCol = {
     ],
 };
 // 默认的列设置
-const ProjectSpreadTemplate = {
+const glSpreadTemplate = {
     tz_ledger_set: [
         { key: 'code', valid: 1 },
         { key: 'b_code', valid: 1 },
         { key: 'ex_memo1', valid: 0 },
         { key: 'name', valid: 1 },
+        { key: 'features', valid: 0 },
         { key: 'position', valid: 1 },
         { key: 'unit', valid: 1 },
         { key: 'unit_price', valid: 1 },
@@ -183,6 +186,7 @@ const ProjectSpreadTemplate = {
         { key: 'b_code', valid: 1 },
         { key: 'ex_memo1', valid: 0 },
         { key: 'name', valid: 1 },
+        { key: 'features', valid: 0 },
         { key: 'position', valid: 1 },
         { key: 'unit', valid: 1 },
         { key: 'unit_price', valid: 1 },
@@ -209,6 +213,7 @@ const ProjectSpreadTemplate = {
         { key: 'b_code', valid: 1 },
         { key: 'ex_memo1', valid: 0 },
         { key: 'name', valid: 1 },
+        { key: 'features', valid: 0 },
         { key: 'position', valid: 1 },
         { key: 'unit', valid: 1 },
         { key: 'unit_price', valid: 1 },
@@ -227,6 +232,7 @@ const ProjectSpreadTemplate = {
         { key: 'b_code', valid: 1 },
         { key: 'ex_memo1', valid: 0 },
         { key: 'name', valid: 1 },
+        { key: 'features', valid: 0 },
         { key: 'position', valid: 1 },
         { key: 'unit', valid: 1 },
         { key: 'unit_price', valid: 1 },
@@ -249,6 +255,199 @@ const ProjectSpreadTemplate = {
         { key: 'dagl', valid: 1},
     ],
 };
+const szSpreadTemplate = {
+    tz_ledger_set: [
+        { key: 'code', valid: 1 },
+        { key: 'b_code', valid: 1 },
+        { key: 'ex_memo1', valid: 0 },
+        { key: 'name', valid: 1 },
+        { key: 'features', valid: 0 },
+        { key: 'position', valid: 1 },
+        { key: 'unit', valid: 1 },
+        { key: 'unit_price', valid: 1 },
+        { key: 'dgn_qty', valid: 1 },
+        { key: 'dgn_price', valid: 1 },
+        { key: 'deal_calc', valid: 0, },
+        { key: 'tz_calc', valid: 1 },
+        { key: 'drawing_code', valid: 1 },
+        { key: 'node_type', valid: 1 },
+        { key: 'memo', valid: 1 },
+        { key: 'ex_memo2', valid: 0 },
+        { key: 'ex_memo3', valid: 0 },
+    ],
+    tz_stage_set: [
+        { key: 'code', valid: 1 },
+        { key: 'b_code', valid: 1 },
+        { key: 'ex_memo1', valid: 0 },
+        { key: 'name', valid: 1 },
+        { key: 'features', valid: 0 },
+        { key: 'position', valid: 1 },
+        { key: 'unit', valid: 1 },
+        { key: 'unit_price', valid: 1 },
+        { key: 'deal_calc', valid: 0, },
+        { key: 'tz_calc', valid: 1 },
+        { key: 'real_qty', valid: 1 },
+        { key: 'estimate_qty', valid: 1 },
+        { key: 'cur_calc', valid: 1 },
+        { key: 'end_calc', valid: 1 },
+        { key: 'deal_dgn_qty', valid: 1 },
+        { key: 'c_dgn_qty', valid: 1 },
+        { key: 'final_dgn_price', valid: 1 },
+        { key: 'postil', valid: 1},
+        { key: 'drawing_code', valid: 1 },
+        { key: 'memo', valid: 1 },
+        { key: 'ex_memo2', valid: 0 },
+        { key: 'ex_memo3', valid: 0 },
+        { key: 'is_tp', valid: 1},
+        { key: 'gxby', valid: 1},
+        { key: 'dagl', valid: 1},
+    ],
+    gcl_ledger_set: [
+        { key: 'code', valid: 1 },
+        { key: 'b_code', valid: 1 },
+        { key: 'ex_memo1', valid: 0 },
+        { key: 'name', valid: 1 },
+        { key: 'features', valid: 0 },
+        { key: 'position', valid: 1 },
+        { key: 'unit', valid: 1 },
+        { key: 'unit_price', valid: 1 },
+        { key: 'dgn_qty', valid: 1 },
+        { key: 'dgn_price', valid: 1 },
+        { key: 'deal_calc', valid: 1, },
+        { key: 'tz_calc', valid: 0 },
+        { key: 'drawing_code', valid: 1 },
+        { key: 'node_type', valid: 1 },
+        { key: 'memo', valid: 1 },
+        { key: 'ex_memo2', valid: 0 },
+        { key: 'ex_memo3', valid: 0 },
+    ],
+    gcl_stage_set: [
+        { key: 'code', valid: 1 },
+        { key: 'b_code', valid: 1 },
+        { key: 'ex_memo1', valid: 0 },
+        { key: 'name', valid: 1 },
+        { key: 'features', valid: 0 },
+        { key: 'position', valid: 1 },
+        { key: 'unit', valid: 1 },
+        { key: 'unit_price', valid: 1 },
+        { key: 'deal_calc', valid: 0, },
+        { key: 'tz_calc', valid: 1 },
+        { key: 'real_qty', valid: 1 },
+        { key: 'estimate_qty', valid: 1 },
+        { key: 'cur_calc', valid: 1 },
+        { key: 'end_calc', valid: 1 },
+        { key: 'deal_dgn_qty', valid: 1 },
+        { key: 'c_dgn_qty', valid: 1 },
+        { key: 'final_dgn_price', valid: 1 },
+        { key: 'postil', valid: 1},
+        { key: 'drawing_code', valid: 1 },
+        { key: 'memo', valid: 1 },
+        { key: 'ex_memo2', valid: 0 },
+        { key: 'ex_memo3', valid: 0 },
+        { key: 'is_tp', valid: 1},
+        { key: 'gxby', valid: 1},
+        { key: 'dagl', valid: 1},
+    ],
+};
+const fjSpreadTemplate = {
+    tz_ledger_set: [
+        { key: 'code', valid: 1 },
+        { key: 'b_code', valid: 1 },
+        { key: 'ex_memo1', valid: 0 },
+        { key: 'name', valid: 1 },
+        { key: 'features', valid: 0 },
+        { key: 'position', valid: 1 },
+        { key: 'unit', valid: 1 },
+        { key: 'unit_price', valid: 1 },
+        { key: 'dgn_qty', valid: 1 },
+        { key: 'dgn_price', valid: 1 },
+        { key: 'deal_calc', valid: 0, },
+        { key: 'tz_calc', valid: 1 },
+        { key: 'drawing_code', valid: 1 },
+        { key: 'node_type', valid: 1 },
+        { key: 'memo', valid: 1 },
+        { key: 'ex_memo2', valid: 0 },
+        { key: 'ex_memo3', valid: 0 },
+    ],
+    tz_stage_set: [
+        { key: 'code', valid: 1 },
+        { key: 'b_code', valid: 1 },
+        { key: 'ex_memo1', valid: 0 },
+        { key: 'name', valid: 1 },
+        { key: 'features', valid: 0 },
+        { key: 'position', valid: 1 },
+        { key: 'unit', valid: 1 },
+        { key: 'unit_price', valid: 1 },
+        { key: 'deal_calc', valid: 0, },
+        { key: 'tz_calc', valid: 1 },
+        { key: 'real_qty', valid: 1 },
+        { key: 'estimate_qty', valid: 1 },
+        { key: 'cur_calc', valid: 1 },
+        { key: 'end_calc', valid: 1 },
+        { key: 'deal_dgn_qty', valid: 1 },
+        { key: 'c_dgn_qty', valid: 1 },
+        { key: 'final_dgn_price', valid: 1 },
+        { key: 'postil', valid: 1},
+        { key: 'drawing_code', valid: 1 },
+        { key: 'memo', valid: 1 },
+        { key: 'ex_memo2', valid: 0 },
+        { key: 'ex_memo3', valid: 0 },
+        { key: 'is_tp', valid: 1},
+        { key: 'gxby', valid: 1},
+        { key: 'dagl', valid: 1},
+    ],
+    gcl_ledger_set: [
+        { key: 'code', valid: 1 },
+        { key: 'b_code', valid: 1 },
+        { key: 'ex_memo1', valid: 0 },
+        { key: 'name', valid: 1 },
+        { key: 'features', valid: 0 },
+        { key: 'position', valid: 1 },
+        { key: 'unit', valid: 1 },
+        { key: 'unit_price', valid: 1 },
+        { key: 'dgn_qty', valid: 1 },
+        { key: 'dgn_price', valid: 1 },
+        { key: 'deal_calc', valid: 1, },
+        { key: 'tz_calc', valid: 0 },
+        { key: 'drawing_code', valid: 1 },
+        { key: 'node_type', valid: 1 },
+        { key: 'memo', valid: 1 },
+        { key: 'ex_memo2', valid: 0 },
+        { key: 'ex_memo3', valid: 0 },
+    ],
+    gcl_stage_set: [
+        { key: 'code', valid: 1 },
+        { key: 'b_code', valid: 1 },
+        { key: 'ex_memo1', valid: 0 },
+        { key: 'name', valid: 1 },
+        { key: 'features', valid: 0 },
+        { key: 'position', valid: 1 },
+        { key: 'unit', valid: 1 },
+        { key: 'unit_price', valid: 1 },
+        { key: 'deal_calc', valid: 0, },
+        { key: 'tz_calc', valid: 1 },
+        { key: 'real_qty', valid: 1 },
+        { key: 'estimate_qty', valid: 1 },
+        { key: 'cur_calc', valid: 1 },
+        { key: 'end_calc', valid: 1 },
+        { key: 'deal_dgn_qty', valid: 1 },
+        { key: 'c_dgn_qty', valid: 1 },
+        { key: 'final_dgn_price', valid: 1 },
+        { key: 'postil', valid: 1},
+        { key: 'drawing_code', valid: 1 },
+        { key: 'memo', valid: 1 },
+        { key: 'ex_memo2', valid: 0 },
+        { key: 'ex_memo3', valid: 0 },
+        { key: 'is_tp', valid: 1},
+        { key: 'gxby', valid: 1},
+        { key: 'dagl', valid: 1},
+    ],
+};
+const ProjectSpreadTemplate = [
+    { code: 'gl', name: '公路', template: glSpreadTemplate, isDefault: 1 },
+    { code: 'sz', name: '市政', template: szSpreadTemplate },
+    { code: 'fj', name: '房建', template: fjSpreadTemplate },
+];
 const BaseSpreadColSetting = {
     Ledger: {
         bills: {

+ 17 - 0
app/controller/project_controller.js

@@ -152,6 +152,23 @@ module.exports = app => {
 
             ctx.body = responseData;
         }
+
+        /**
+         * 保存列设置
+         * @param ctx
+         * @returns {Promise<void>}
+         */
+        async colSet(ctx) {
+            try {
+                const colType = ctx.request.body.col_type;
+                const colSet = JSON.parse(ctx.request.body.col_set);
+                await ctx.service.projectColSet.setProjectColSet(ctx.session.sessionProject.id, colType, colSet);
+                ctx.redirect(ctx.request.header.referer);
+            } catch (err) {
+                ctx.redirect(ctx.request.header.referer);
+            }
+
+        }
     }
 
     return ProjectController;

+ 24 - 21
app/controller/revise_controller.js

@@ -410,29 +410,32 @@ module.exports = app => {
                 // 已计量
                 if (revise.uid === ctx.session.sessionUser.accountId &&
                     (revise.status === audit.revise.status.uncheck || revise.status === audit.revise.status.checkNo)) {
-                    const lastStage = await ctx.service.stage.getLastestStage(ctx.tender.id, true);
-                    if (lastStage) {
-                        if (lastStage.status === audit.stage.status.checked) {
-                            const usedPreBills = await ctx.service.stageBillsFinal.getUsedBills(ctx.tender.id, lastStage.order);
-                            for (const b of reviseBills) {
-                                b.used = usedPreBills.indexOf(b.id) >= 0;
-                            }
-                            const usedPrePos = await ctx.service.stagePosFinal.getUsedPos(ctx.tender.id, lastStage.order);
-                            for (const p of revisePos) {
-                                p.used = usedPrePos.indexOf(p.id) >= 0;
-                            }
-                        } else {
-                            const usedPreBills = lastStage.order > 1 ? await ctx.service.stageBillsFinal.getUsedBills(ctx.tender.id, lastStage.order - 1) : [];
-                            const usedCurBills = await ctx.service.stageBills.getStageUsedBills(ctx.tender.id, lastStage.id);
-                            for (const b of reviseBills) {
-                                b.used = usedPreBills.indexOf(b.id) >= 0 || usedCurBills.indexOf(b.id) >= 0;
-                            }
-                            const usedPrePos = lastStage.order > 1 ? await ctx.service.stagePosFinal.getUsedPos(ctx.tender.id, lastStage.order - 1) : [];
-                            const usedCurPos = await ctx.service.stagePos.getStageUsedPos(ctx.tender.id, lastStage.id);
-                            for (const p of revisePos) {
-                                p.used = usedPrePos.indexOf(p.id) >= 0 || usedCurPos.indexOf(p.id) >= 0;
+                    const stages = await ctx.service.stage.getAllDataByCondition({
+                        where: { tid: ctx.tender.id },
+                        orders: [['order', 'desc']],
+                    });
+                    if (stages.length > 0) {
+                        const usedBills = [], usedPos = [];
+                        for (const s of stages) {
+                            if (s.status === audit.stage.status.checked) {
+                                const usedPreBills = await ctx.service.stageBillsFinal.getUsedBills(ctx.tender.id, s.order);
+                                usedBills.push(...usedPreBills);
+                                const usedPrePos = await ctx.service.stagePosFinal.getUsedPos(ctx.tender.id, s.order);
+                                usedPos.push(...usedPrePos);
+                                break;
+                            } else {
+                                const usedCurBills = await ctx.service.stageBills.getStageUsedBills(ctx.tender.id, s.id);
+                                usedBills.push(...usedCurBills);
+                                const usedCurPos = await ctx.service.stagePos.getStageUsedPos(ctx.tender.id, s.id);
+                                usedPos.push(...usedCurPos);
                             }
                         }
+                        for (const b of reviseBills) {
+                            b.used = usedBills.indexOf(b.id) >= 0;
+                        }
+                        for (const p of revisePos) {
+                            p.used = usedPos.indexOf(p.id) >= 0;
+                        }
                     }
                 }
                 // 结算状态

+ 13 - 9
app/controller/setting_controller.js

@@ -324,6 +324,7 @@ module.exports = app => {
                     accountGroup,
                     unitList,
                     user_total,
+                    company: null,
                     fujianOssPath: ctx.app.config.fujianOssPath,
                     jsFiles: this.app.jsFiles.common.concat(this.app.jsFiles.setting.user),
                 };
@@ -424,8 +425,7 @@ module.exports = app => {
                         await ctx.service.constructionUnit.update({sign_path: null}, {id: info.id});
                         break;
                     case 'import-users':
-                        const import_result = await ctx.service.projectAccount.addUsers(projectData.id, data.users);
-                        responseData.data.insertNum = import_result;
+                        responseData.data = await ctx.service.projectAccount.addUsers(projectData.id, data.users);
                         break;
                     default:
                         break;
@@ -904,7 +904,8 @@ module.exports = app => {
                 }
                 const showList = await ctx.service.settingShow.getList(projectData.page_path);
                 const sjsRela = await ctx.service.project.getSjsRela(projectId);
-                const renderData = {projectData, showList, sjsRela, settingConst};
+                const projectSpread  = await ctx.service.projectSpread.getProjectSpreadType(projectId);
+                const renderData = {projectData, showList, sjsRela, settingConst, projectSpread};
                 await this.layout('setting/show.ejs', renderData);
             } catch (error) {
                 this.log(error);
@@ -1383,11 +1384,13 @@ module.exports = app => {
                 const projectData = await ctx.service.project.getDataById(projectId);
                 if (!projectData) throw '没有对应的项目数据';
 
-                const projectSpread = await this.ctx.service.projectSpread.getProjectSpread(projectData.id);
                 const sType = ctx.query.stype;
+                const code = ctx.query.code;
+                const projectSpread = await this.ctx.service.projectSpread.getProjectSpread(projectData.id, code);
                 const renderData = {
                     BaseSetCol: sType.indexOf('stage') > 0 ? SpreadConst.BaseSetCol.Stage : SpreadConst.BaseSetCol.Ledger,
                     sType,
+                    code,
                     colSet: projectSpread[sType],
                     jsFiles: this.app.jsFiles.common.concat(this.app.jsFiles.setting.spread),
                 };
@@ -1402,8 +1405,8 @@ module.exports = app => {
             try {
                 const projectId = ctx.session.sessionProject.id;
                 const data = JSON.parse(ctx.request.body.data);
-                await this.ctx.service.projectSpread.updateProjectSet(projectId, data.sType, data.colSet);
-                const projectSpread = await this.ctx.service.projectSpread.getProjectSpread(projectId);
+                await this.ctx.service.projectSpread.updateProjectSet(projectId, data.code, data.sType, data.colSet);
+                const projectSpread = await this.ctx.service.projectSpread.getProjectSpread(projectId, data.code);
                 ctx.body = { err: 0, msg: '', data: { colSet: projectSpread[data.sType] } };
             } catch (error) {
                 ctx.log(error);
@@ -1426,9 +1429,10 @@ module.exports = app => {
             try {
                 const projectId = ctx.session.sessionProject.id;
                 const data = JSON.parse(ctx.request.body.data);
-                const colSet = SpreadConst.ProjectSpreadTemplate[data.sType];
-                await this.ctx.service.projectSpread.updateProjectSet(projectId, data.sType, colSet);
-                const projectSpread = await this.ctx.service.projectSpread.getProjectSpread(projectId);
+                const spreadTemplate = SpreadConst.ProjectSpreadTemplate.find(x => { return x.code === data.code; });
+                const colSet = spreadTemplate.template[data.sType];
+                await this.ctx.service.projectSpread.updateProjectSet(projectId, data.code, data.sType, colSet);
+                const projectSpread = await this.ctx.service.projectSpread.getProjectSpread(projectId, data.code);
                 ctx.body = { err: 0, msg: '', data: { colSet: projectSpread[data.sType] } };
             } catch (error) {
                 ctx.log(error);

+ 8 - 17
app/controller/stage_controller.js

@@ -272,7 +272,7 @@ module.exports = app => {
             // 结算状态
             const settleStatus = ctx.stage.readySettle ? await ctx.service.settleBills.getAllDataByCondition({ where: { settle_id: ctx.stage.readySettle.id }}) : [];
             // 查询截止上期数据
-            const preStageData = ctx.stage.order > 1 ? await ctx.service.stageBillsFinal.getFinalData(ctx.tender.data, ctx.stage.order - 1) : [];
+            const preStageData = ctx.stage.preCheckedStage ? await ctx.service.stageBillsFinal.getFinalData(ctx.tender.data, ctx.stage.preCheckedStage.order) : [];
             this.ctx.helper.assignRelaData(ledgerData, [
                 { data: dgnData, fields: ['deal_dgn_qty1', 'deal_dgn_qty2', 'c_dgn_qty1', 'c_dgn_qty2'], prefix: '', relaId: 'id' },
                 { data: memoData, fields: this.ledgerMemoColumn, prefix: '', relaId: 'id' },
@@ -308,7 +308,7 @@ module.exports = app => {
             // 结算状态
             const settleStatus = ctx.stage.readySettle ? await ctx.service.settlePos.getAllDataByCondition({ where: { settle_id: ctx.stage.readySettle.id }}) : [];
             // 查询截止上期数据
-            const preStageData = ctx.stage.order > 1 ? await ctx.service.stagePosFinal.getFinalData(ctx.tender.data, ctx.stage.order - 1) : [];
+            const preStageData = ctx.stage.preCheckedStage ? await ctx.service.stagePosFinal.getFinalData(ctx.tender.data, ctx.stage.preCheckedStage.order) : [];
             this.ctx.helper.assignRelaData(posData, [
                 { data: memoData, fields: this.posMemoColumn, prefix: '', relaId: 'id'},
                 { data: extraData, fields: this.posExtraColumn, prefix: '', relaId: 'id'},
@@ -487,23 +487,14 @@ module.exports = app => {
                 condition.tid = ctx.tender.id;
                 const responseData = { err: 0, msg: '', data: {} };
 
-                let curStageData,
-                    preStageData;
                 responseData.data = await ctx.service.pos.getPosDataWithAddStageOrder(condition);
                 // 根据当前人,或指定对象查询数据
                 const curWhere = JSON.parse(ctx.request.body.data);
-                if (ctx.stage.readOnly) {
-                    curStageData = await ctx.service.stagePos.getAuditorStageData2(ctx.tender.id,
-                        ctx.stage.id, ctx.stage.curTimes, ctx.stage.curOrder, curWhere);
-                } else {
-                    curStageData = await ctx.service.stagePos.getLastestStageData2(ctx.tender.id, ctx.stage.id, curWhere);
-                }
+                const curStageData = ctx.stage.readOnly
+                    ? await ctx.service.stagePos.getAuditorStageData2(ctx.tender.id, ctx.stage.id, ctx.stage.curTimes, ctx.stage.curOrder, curWhere)
+                    : await ctx.service.stagePos.getLastestStageData2(ctx.tender.id, ctx.stage.id, curWhere);
                 // 查询截止上期数据
-                if (ctx.stage.order > 1) {
-                    preStageData = await ctx.service.stagePosFinal.getFinalData(ctx.tender.data, ctx.stage.order - 1);
-                } else {
-                    preStageData = [];
-                }
+                const preStageData = ctx.stage.preCheckedStage ? await ctx.service.stagePosFinal.getFinalData(ctx.tender.data, ctx.stage.preCheckedStage.order) : [];
                 this.ctx.helper.assignRelaData(responseData.data, [
                     { data: curStageData, fields: ['contract_qty', 'qc_qty', 'qc_minus_qty', 'postil'], prefix: '', relaId: 'pid' },
                     { data: preStageData, fields: ['contract_qty', 'qc_qty', 'qc_minus_qty'], prefix: 'pre_', relaId: 'pid' },
@@ -974,8 +965,8 @@ module.exports = app => {
                 renderData.calcBase = await ctx.service.stage.getStagePayCalcBase(ctx.stage, ctx.tender.info);
                 renderData.jsFiles = this.app.jsFiles.common.concat(this.app.jsFiles.stage.pay);
                 renderData.whiteList = this.ctx.app.config.multipart.whitelist;
-                if (ctx.stage.order > 1) {
-                    renderData.pre = await ctx.service.stageBillsFinal.getSumTotalPrice(ctx.stage.tid, ctx.stage.order - 1);
+                if (ctx.stage.preCheckedStage) {
+                    renderData.pre = await ctx.service.stageBillsFinal.getSumTotalPrice(ctx.stage.tid, ctx.stage.preCheckedStage.order);
                     renderData.pre.gather_tp = ctx.helper.add(renderData.pre.contract_tp, renderData.pre.qc_tp);
                 } else {
                     renderData.pre = { contract_tp: null, qc_tp: null, gather_tp: null };

+ 15 - 3
app/controller/tender_controller.js

@@ -25,6 +25,7 @@ const changeConst = require('../const/change');
 const tenderInfoModel = require('../lib/tender_info');
 const mapConst = require('../const/map');
 const advanceConst = require('../const/advance');
+const projectSetting = require('../const/project_setting');
 
 module.exports = app => {
 
@@ -40,9 +41,10 @@ module.exports = app => {
             super(ctx);
             ctx.showProject = true;
             ctx.showTitle = true;
+            this.colSet = [];
         }
 
-        async _listDetailCache(view, modal = '') {
+        async _listDetailCache(view, modal = '', type) {
             try {
                 // 获取用户新建标段权利
                 const accountInfo = await this.ctx.service.projectAccount.getDataById(this.ctx.session.sessionUser.accountId);
@@ -66,6 +68,7 @@ module.exports = app => {
                     valuations,
                     uid: this.ctx.session.sessionUser.accountId,
                     pid: this.ctx.session.sessionProject.id,
+                    colSet: this.colSet,
                 };
                 renderData.selfCategoryLevel = await this.ctx.service.projectAccount.getSelfCategoryLevel(this.ctx.session.sessionUser.accountId);
                 renderData.is_finish = false;
@@ -76,7 +79,7 @@ module.exports = app => {
             }
         }
 
-        async _listDetailFinish(view, modal = '') {
+        async _listDetailFinish(view, modal = '', type) {
             try {
                 // 获取用户新建标段权利
                 const accountInfo = await this.ctx.service.projectAccount.getDataById(this.ctx.session.sessionUser.accountId);
@@ -100,6 +103,7 @@ module.exports = app => {
                     valuations,
                     uid: this.ctx.session.sessionUser.accountId,
                     pid: this.ctx.session.sessionProject.id,
+                    colSet: this.colSet,
                 };
                 renderData.selfCategoryLevel = await this.ctx.service.projectAccount.getSelfCategoryLevel(this.ctx.session.sessionUser.accountId);
                 renderData.is_finish = true;
@@ -129,6 +133,7 @@ module.exports = app => {
                 renderData.pid = this.ctx.session.sessionProject.id;
                 renderData.selfCategoryLevel = await this.ctx.service.projectAccount.getSelfCategoryLevel(this.ctx.session.sessionUser.accountId);
                 renderData.is_finish = false;
+                renderData.colSet = this.colSet;
                 await this.layout(view, renderData, modal);
             } catch (err) {
                 this.log(err);
@@ -155,6 +160,7 @@ module.exports = app => {
                 renderData.pid = this.ctx.session.sessionProject.id;
                 renderData.selfCategoryLevel = await this.ctx.service.projectAccount.getSelfCategoryLevel(this.ctx.session.sessionUser.accountId);
                 renderData.is_finish = true;
+                renderData.colSet = this.colSet;
                 await this.layout(view, renderData, modal);
             } catch (err) {
                 this.log(err);
@@ -169,6 +175,7 @@ module.exports = app => {
             const renderData = {
                 accountInfo,
                 userPermission,
+                colSet: this.colSet,
             };
             await this._listCache('tender/index.ejs', renderData, 'tender/modal.ejs');
         }
@@ -181,6 +188,8 @@ module.exports = app => {
          */
         async listInfo(ctx) {
             this.jsFiles = this.app.jsFiles.tender.info;
+            const projectColSet = await ctx.service.projectColSet.getProjectColSet(ctx.session.sessionProject.id);
+            this.colSet = ctx.service.projectColSet.analysisColSetWithDefine(projectSetting.colSet.info, projectColSet.info);
             await this._listDetailCache('tender/info.ejs', 'tender/modal.ejs');
         }
 
@@ -515,6 +524,8 @@ module.exports = app => {
                 }
                 const canFinish = await this.ctx.service.tender.checkTenderCanFinish(tender);
 
+                const projectSpread  = await ctx.service.projectSpread.getProjectSpreadType(tender.project_id);
+
                 const renderData = {
                     tenders,
                     categoryData,
@@ -542,6 +553,7 @@ module.exports = app => {
                     fujianOssPath: ctx.app.config.fujianOssPath,
                     canFinish: canFinish,
                     buildStatus: tenderConst.buildStatus,
+                    projectSpread,
                 };
                 if (ctx.session.sessionUser.is_admin) {
                     renderData.tourists = await ctx.service.tenderTourist.getTourists(tender.id);
@@ -627,7 +639,7 @@ module.exports = app => {
         async saveTenderInfo2(ctx) {
             try {
                 const data = JSON.parse(ctx.request.body.data);
-                if (!data || (!data.ledger_check && !data.fun_rela)) throw '提交数据错误';
+                if (!data || (!data.ledger_check && !data.fun_rela && !data.s_type)) throw '提交数据错误';
                 if (!ctx.session.sessionUser.is_admin) throw '您无权修改该内容';
 
                 const updateData = {};

+ 1 - 1
app/lib/budget_final.js

@@ -175,7 +175,7 @@ class BudgetFinal {
             const curBills = stage.readOnly
                 ? await this.ctx.service.stageBills.getAuditorStageData2(id, stage.id, stage.curTimes, stage.curOrder)
                 : await this.ctx.service.stageBills.getLastestStageData2(id, stage.id);
-            const preBills = stage.order > 1 ? await this.ctx.service.stageBillsFinal.getFinalData({id}, stage.order - 1) : [];
+            const preBills = stage.preCheckedStage ? await this.ctx.service.stageBillsFinal.getFinalData({id}, stage.preCheckedStage.order) : [];
             const bpcData = await this.ctx.service.stageBillsPc.getAllDataByCondition({ where: { sid: stage.id } });
             helper.assignRelaData(bills, [
                 { data: curBills, fields: ['contract_tp', 'qc_tp'], prefix: '', relaId: 'lid' },

+ 1 - 1
app/lib/pay_calc.js

@@ -157,7 +157,7 @@ class PayCalculate {
     async _getAddCalcRela() {
         if (this.cur && this.add) return;
 
-        this.pre = this.stage.order > 1 ? await this.ctx.service.stageBillsFinal.getSumTotalPrice(this.stage.tid, this.stage.order - 1) : {};
+        this.pre = this.stage.preCheckedStage ? await this.ctx.service.stageBillsFinal.getSumTotalPrice(this.stage.tid, this.stage.preCheckedStage.order) : {};
         this.cur = await this.ctx.service.stageBills.getSumTotalPrice(this.stage);
         this.add = {};
         if (this.pre) {

+ 71 - 2
app/lib/revise_price.js

@@ -335,6 +335,63 @@ class revisePriceCalc {
             { id: stage.id, ...pcTp, check_calc: true, cache_time_l: new Date() });
         return pcTp;
     }
+    async _calcStageWithoutPc(stage, bills, transaction) {
+        // 无单价变更不执行
+        if (this.price.length === 0) return;
+
+        const curBillsData = await this.ctx.service.stageBills.getLastestStageData2(stage.tid, stage.id);
+
+        // 加载树结构
+        this.ctx.helper.assignRelaData(bills, [
+            { data: curBillsData, fields: ['id', 'contract_qty', 'qc_qty', 'positive_qc_qty', 'negative_qc_qty', 'times', 'order', 'postil'], prefix: 'cur_', relaId: 'lid' },
+        ]);
+        const billsTree = new Ledger.billsTree(this.ctx, { id: 'ledger_id', pid: 'ledger_pid', order: 'order', level: 'level', rootId: -1, calcFields: [] });
+        billsTree.loadDatas(bills);
+        const stageChange = await this.ctx.service.stageChange.getFinalStageData(stage.tid, stage.id);
+
+        // 计算 insertBills/updateBills StageChange
+        const result = { ibData: [], ubData: [], scData: [] };
+        const helper = this.ctx.helper;
+        const decimal = this.ctx.tender.info.decimal;
+        const said = this.ctx.session.sessionUser.accountId;
+        billsTree.calculateAll(node => {
+            if (node.children && node.children.length > 0) return;
+            // const priceDiff = helper.sub(node.unit_price, node.pre_unit_price);
+            // if (!priceDiff) return;
+            if (node.cur_id && (node.cur_contract_qty || node.cur_qc_qty)) {
+                const cur_contract_tp = helper.mul(node.cur_contract_qty, node.unit_price, decimal.tp);
+                const cur_qc_tp = helper.mul(node.cur_qc_qty, node.unit_price, decimal.tp);
+                const cur_positive_qc_tp = helper.mul(node.cur_positive_qc_qty, node.unit_price, decimal.tp);
+                const cur_negative_qc_tp = helper.mul(node.cur_negative_qc_qty, node.unit_price, decimal.tp);
+                if (cur_contract_tp !== node.cur_contract_tp || cur_qc_tp !== node.cur_qc_tp || cur_positive_qc_tp !== node.cur_positive_qc_tp || cur_negative_qc_tp !== node.cur_positive_qc_tp) {
+                    if (node.cur_times === stage.times && node.cur_order === 0) {
+                        result.ubData.push({
+                            id: node.cur_id,
+                            contract_tp: cur_contract_tp, qc_tp: cur_qc_tp,
+                            positive_qc_tp: cur_positive_qc_tp, negative_qc_tp: cur_negative_qc_tp,
+                        });
+                    } else {
+                        result.ibData.push({
+                            tid: stage.tid, sid: stage.id, said,
+                            lid: node.id, times: stage.times, order: 0,
+                            contract_qty: node.cur_contract_qty, contract_tp: cur_contract_tp,
+                            qc_qty: node.cur_qc_qty, qc_tp: cur_qc_tp,
+                            positive_qc_qty: node.cur_positive_qc_qty, positive_qc_tp: cur_positive_qc_tp,
+                            negative_qc_qty: node.cur_negative_qc_qty, negative_qc_tp: cur_negative_qc_tp,
+                            postil: node.cur_postil,
+                        });
+                    }
+                }
+            }
+            const scDetail = stageChange.filter(x => { return x.lid === node.id; });
+            for (const scd of scDetail) {
+                result.scData.push({ id: scd.id, unit_price: node.unit_price });
+            }
+        });
+        if (result.ibData.length > 0) await transaction.insert(this.ctx.service.stageBills.tableName, result.ibData);
+        if (result.ubData.length > 0) await transaction.updateRows(this.ctx.service.stageBills.tableName, result.ubData);
+        if (result.scData.length > 0) await transaction.updateRows(this.ctx.service.stageChange.tableName, result.scData);
+    }
     /**
      * 计算修订台账
      * @param {Object}revise - 最新一次台账修订(此处不检查)
@@ -371,8 +428,20 @@ class revisePriceCalc {
         if (pos.length > 0) await transaction.insert(this.ctx.service.pos.tableName, pos);
 
         // 应用到未审完成期
-        const latestStage = await this.ctx.service.stage.getLastestStage(revise.tid, true);
-        if (latestStage && latestStage.status !== audit.stage.status.checked) return await this._calcStage(latestStage, xmj, transaction);
+        const stages = await this.ctx.service.stage.getAllDataByCondition({ where: { tid: revise.tid }, order: ['order', 'asc'] });
+        const latestStage = stages[stages.length - 1];
+        let pcTp;
+        if (latestStage && latestStage.status !== audit.stage.status.checked) {
+            for (const s of stages) {
+                if (s.status === audit.stage.status.checked) continue;
+                if (!pcTp) {
+                    pcTp = await this._calcStage(latestStage, xmj, transaction);
+                } else {
+                    await this._calcStageWithoutPc(latestStage, xmj, transaction);
+                }
+            }
+        }
+        return pcTp;
     }
     async calcRevise(revise, transaction) {
         if (revise.tid !== this.ctx.tender.id) throw '数据错误';

+ 3 - 3
app/lib/rptCustomData.js

@@ -235,7 +235,7 @@ class jhHelper {
         let billsData = await this.ctx.service.ledger.getData(tender.id);
         if (filterGcl) billsData = billsData.filter(x => { return x.b_code && x.is_leaf });
         const curStage = await this.ctx.service.stageBills.getLastestStageData2(tender.id, stage.id);
-        const preStage = stage.order > 1 ? await this.ctx.service.stageBillsFinal.getFinalData(tender, stage.order - 1) : [];
+        const preStage = stage.preCheckedStage ? await this.ctx.service.stageBillsFinal.getFinalData(tender, stage.preCheckedStage.order) : [];
         const loadData = [
             { data: curStage, fields: this.billsQueryField, prefix: '', relaId: 'lid' },
             { data: preStage, fields: this.billsQueryField, prefix: 'pre_', relaId: 'lid' }
@@ -254,7 +254,7 @@ class jhHelper {
         const helper = this.ctx.helper;
         const posData = await this.ctx.service.pos.getPosData({tid: tender.id});
         const curStage = await this.ctx.service.stagePos.getLastestStageData2(tender.id, stage.id);
-        const preStage = stage.order > 1 ? await this.ctx.service.stagePosFinal.getFinalData(tender, stage.order - 1) : [];
+        const preStage = stage.preCheckedStage ? await this.ctx.service.stagePosFinal.getFinalData(tender, stage.preCheckedStage.order) : [];
         const loadData = [
             { data: curStage, fields: ['qc_qty'], prefix: '', relaId: 'pid' },
             { data: preStage, fields: ['qc_qty'], prefix: 'pre_', relaId: 'pid' }
@@ -526,7 +526,7 @@ class fjHelper {
             ? await this.ctx.helper.loadLedgerDataFromOss(this.ctx.stage.ledgerHis.bills_file)
             : await this.ctx.service.ledger.getData(this.ctx.tender.id);
 
-        const preStage = this.ctx.stage.order > 1 ? await this.ctx.service.stageBillsFinal.getFinalData(this.ctx.tender, this.ctx.stage.order - 1) : [];
+        const preStage = this.ctx.stage.preCheckedStage ? await this.ctx.service.stageBillsFinal.getFinalData(this.ctx.tender, this.ctx.stage.preCheckedStage.order) : [];
         const curStage = this.ctx.stage.readOnly
             ? await this.ctx.service.stageBills.getAuditorStageData2(tid, this.ctx.stage.id, this.ctx.stage.curTimes, this.ctx.stage.curOrder)
             : await this.ctx.service.stageBills.getLastestStageData2(tid, this.ctx.stage.id);

+ 13 - 10
app/lib/spread_setting.js

@@ -70,17 +70,21 @@ function refreshSpreadShow(sjsRela, sjsSetting) {
 const getLedgerSpreadSetting = async function(ctx, tid, readOnly) {
     let tender = tid ? await getCtxTender(ctx, tid) : ctx.tender;
 
-    const projectSpread = await ctx.service.projectSpread.getProjectSpread(ctx.session.sessionProject.id);
+    const projectSpread = await ctx.service.projectSpread.getProjectSpread(ctx.session.sessionProject.id, tender.info.s_type);
     const prefix = tender.data.measure_type === measureType.tz.value ? 'tz' : 'gcl';
     const ledger = projectSpread[`${prefix}_ledger_bills_spread`];
     const pos = projectSpread[`${prefix}_ledger_pos_spread`];
     if (!tender.info.display.ledger.clQty) {
         const billsColIndex = ledger.cols.findIndex(x => { return x.field === spreadConst.withoutClReplace.indexField; });
-        removeFieldCols(ledger, spreadConst.withoutClReplace.remove);
-        ledger.cols.splice(billsColIndex, 0, ...spreadConst.withoutClReplace.billsCols);
+        if (billsColIndex >= 0) {
+            removeFieldCols(ledger, spreadConst.withoutClReplace.remove);
+            ledger.cols.splice(billsColIndex, 0, ...spreadConst.withoutClReplace.billsCols);
+        }
         const posColIndex = pos.cols.findIndex(x => { return x.field === spreadConst.withoutClReplace.indexField; });
-        removeFieldCols(pos, spreadConst.withoutClReplace.remove);
-        pos.cols.splice(posColIndex, 0, ...spreadConst.withoutClReplace.posCols);
+        if (posColIndex >= 0) {
+            removeFieldCols(pos, spreadConst.withoutClReplace.remove);
+            pos.cols.splice(posColIndex, 0, ...spreadConst.withoutClReplace.posCols);
+        }
     }
     // const setting = tender.data.measure_type === measureType.tz.value
     //     ? (tender.info.display.ledger.clQty ? spreadConst.withCl : spreadConst.withoutCl)
@@ -102,14 +106,13 @@ const getLedgerSpreadSetting = async function(ctx, tid, readOnly) {
 const getStageSpreadSetting = async function (ctx, tid, readOnly, funInfo) {
     const tender = tid ? await getCtxTender(ctx, tid) : ctx.tender;
 
-    const stageSetting = tender.data.measure_type === measureType.tz.value
-        ? spreadConst.stageTz
-        : (tender.info.display.ledger.clQty ? spreadConst.stageCl : spreadConst.stageNoCl);
-    const ledger = JSON.parse(JSON.stringify(stageSetting.ledger));
+    const projectSpread = await ctx.service.projectSpread.getProjectSpread(ctx.session.sessionProject.id, tender.info.s_type);
+    const prefix = tender.data.measure_type === measureType.tz.value ? 'tz' : 'gcl';
+    const ledger = projectSpread[`${prefix}_stage_bills_spread`];
+    const pos = projectSpread[`${prefix}_stage_pos_spread`];
     if (!tender.info.display.ledger.dgnQty) {
         removeFieldCols(ledger, spreadConst.filterCols.stageDgnCols);
     }
-    const pos = JSON.parse(JSON.stringify(stageSetting.pos));
     if (!tender.info.display.stage.realComplete) {
         removeFieldCols(pos, spreadConst.filterCols.realCompleteCols);
     }

+ 2 - 2
app/lib/stage_im.js

@@ -77,7 +77,7 @@ class StageIm {
             ? await this.ctx.service.stageBills.getAuditorStageData2(this.ctx.tender.id,
                 this.ctx.stage.id, this.ctx.stage.curTimes, this.ctx.stage.curOrder)
             : await this.ctx.service.stageBills.getLastestStageData2(this.ctx.tender.id, this.ctx.stage.id);
-        const preStage = this.ctx.stage.order > 1 ? await this.ctx.service.stageBillsFinal.getFinalData(this.ctx.tender, this.ctx.stage.order - 1) : [];
+        const preStage = this.ctx.stage.preCheckedStage ? await this.ctx.service.stageBillsFinal.getFinalData(this.ctx.tender, this.ctx.stage.preCheckedStage.order) : [];
         const bpcStage = await this.ctx.service.stageBillsPc.getAllDataByCondition({ where: { sid: this.ctx.stage.id } });
 
         this.ctx.helper.assignRelaData(billsData, [
@@ -95,7 +95,7 @@ class StageIm {
             ? await this.ctx.service.stagePos.getAuditorStageData2(this.ctx.tender.id,
                 this.ctx.stage.id, this.ctx.stage.curTimes, this.ctx.stage.curOrder)
             : await this.ctx.service.stagePos.getLastestStageData2(this.ctx.tender.id, this.ctx.stage.id);
-        const prePosStage = this.ctx.stage.order > 1 ? await this.ctx.service.stagePosFinal.getFinalData(this.ctx.tender, this.ctx.stage.order - 1) : [];
+        const prePosStage = this.ctx.stage.preCheckedStage ? await this.ctx.service.stagePosFinal.getFinalData(this.ctx.tender, this.ctx.stage.preCheckedStage.order) : [];
         this.ctx.helper.assignRelaData(posData, [
             { data: curPosStage, fields: ['contract_qty', 'qc_qty', 'qc_minus_qty'], prefix: '', relaId: 'pid' },
             { data: prePosStage, fields: ['contract_qty', 'qc_qty', 'qc_minus_qty'], prefix: 'pre_', relaId: 'pid' },

+ 1 - 1
app/lib/tender_info.js

@@ -45,7 +45,7 @@ class TenderInfo {
                 ? await this.ctx.service.stageBills.getAuditorStageData2(this.tender.id, this.stage.id, this.stage.curTimes, this.stage.curOrder)
                 : await this.ctx.service.stageBills.getLastestStageData2(this.tender.id, this.stage.id);
 
-            const preStage = this.stage.order > 1 ? await this.ctx.service.stageBillsFinal.getFinalData(this.tender, this.stage.order - 1) : [];
+            const preStage = this.stage.preCheckedStage ? await this.ctx.service.stageBillsFinal.getFinalData(this.tender, this.stage.preCheckedStage.order) : [];
             const bpcStage = await this.ctx.service.stageBillsPc.getAllDataByCondition({ where: { sid: this.stage.id } });
             this.ctx.helper.assignRelaData(billsData, [
                 { data: curStage, fields: ['contract_qty', 'contract_tp', 'qc_qty', 'qc_tp'], prefix: '', relaId: 'lid' },

+ 1 - 0
app/middleware/stage_check.js

@@ -48,6 +48,7 @@ module.exports = options => {
 
             // 读取原报、审核人数据
             yield this.service.stage.loadStageUser(stage);
+            yield this.service.stage.loadPreCheckedStage(stage);
 
             // 历史台账
             if (stage.status === status.checked) {

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

@@ -19,7 +19,7 @@ $(document).ready(function() {
             const cache = getLocalCache(this.expandKey);
             this.expandCache = cache ? _.uniq(cache.split(',')) : [];
             this.curFilingKey = 'cur-filing-' + window.location.pathname.split('/')[2];
-            $('#filing').height($(".sjs-height-0").height()-$('.d-flex',".sjs-height-0").height());
+            $('#filing').height($(".sjs-height-0").height()-$('.d-flex',".sjs-height-0").height() - 10);
             this.fileOrderKey = 'fileOrder';
             this.fileOrder = getLocalCache(this.fileOrderKey) || 'create_time|desc';
         }
@@ -1178,4 +1178,4 @@ $(document).ready(function() {
             }, 100);
         });
     })('a[name=showLevel]');
-});
+});

+ 4 - 4
app/public/js/project_spread.js

@@ -149,8 +149,8 @@ $(document).ready(() => {
             if (datas.length > 0) {
                 postData(window.location.pathname + '/update', {postType: 'update', postData: datas}, function (result) {
                     const refreshNode = sheet.zh_tree.loadPostData(result);
-                    billsTreeSpreadObj.refreshTree(sheet, refreshNode);
-                    billsTreeSpreadObj.loadExprToInput(sheet);
+                    colSpreadObj.refreshTree(sheet, refreshNode);
+                    colSpreadObj.loadExprToInput(sheet);
                 });
             }
         },
@@ -211,7 +211,7 @@ $(document).ready(() => {
     });
 
     $('#spread-save').click(() => {
-        const data = { sType, colSet: getCurrentColSet() };
+        const data = { sType, code: sCode, colSet: getCurrentColSet() };
         postData('/setting/spread/save', data, function(result) {
             colSet.length = 0;
             colSet.push(...result.colSet);
@@ -227,7 +227,7 @@ $(document).ready(() => {
         })
     });
     $('#spread-reset').click(() => {
-        const data = { sType };
+        const data = { sType, code: sCode };
         postData('/setting/spread/reset', data, function(result) {
             colSet.length = 0;
             colSet.push(...result.colSet);

+ 1 - 0
app/public/js/revise.js

@@ -915,6 +915,7 @@ $(document).ready(() => {
                     info.cancel = posRange && posRange.length > 0;
                     break;
                 case 'unit_price':
+                    console.log(node);
                     info.cancel = (node.children && node.children.length > 0) || node.used || node.settle_status === settleStatus.finish;
                     break;
                 case 'sgfh_qty':

+ 7 - 3
app/public/js/setting.js

@@ -251,7 +251,6 @@ $(document).ready(() => {
     });
 
     $('#one_unit input').blur(function () {
-        console.log('hello');
         const val_name = $(this).data('name');
         let val = _.trim($(this).val()) !== '' ? _.trim($(this).val()) : null;
         if (!oneUnit) {
@@ -462,11 +461,16 @@ $(document).ready(() => {
                 postData('/setting/user/unit/save', { type: 'import-users', users: tree }, function (result) {
                     if (result.insertNum > 0) {
                         toastr.success('成功导入了' + result.insertNum + '个账号');
+                        if (result.overMax) {
+                            toastr.warning('添加账号个数受限,部分账号无法导入,请去后台开放限制。');
+                        }
                         setTimeout(function () {
                             window.location.reload();
                         }, 1500);
-                    } else {
-                        toastr.warning('未能导入任何账号,请检查账号、公司是否已存在或excel是否符合模版要求。');
+                    } else if (result.insertNum === 0 && !result.overMax) {
+                        toastr.error('未能导入任何账号,请检查账号、公司是否已存在或excel是否符合模版要求。');
+                    } else if (result.insertNum === 0 && result.overMax) {
+                        toastr.warning('添加账号个数受限,账号无法导入,请去后台开放限制。');
                     }
                 })
             } catch (error) {

+ 39 - 38
app/public/js/shares/sjs_setting.js

@@ -69,64 +69,65 @@ const sjsSettingObj = (function () {
             if (col) col[prop] = value;
         }
     };
-    const set3FCols = function (cols, rela) {
+    const setRelaCols = function(cols, rela, fun) {
         for (const r of rela) {
             const col = _.find(cols, {field: r.field});
-            if (col) {
-                col.getValue = r.getValue;
-                col.cellType = 'imageBtn';
-                col.normalImg = '#rela-file-icon';
-                col.indent = 12;
-                col.imgAlign = 2;
-                col.showImage = function (data) { return data && data[r.url_field]; }
-            }
+            if (!col) continue;
+            fun(col, r);
         }
     };
+    const set3FCols = function (cols, rela) {
+        setRelaCols(cols, rela, function(col, r) {
+            col.getValue = r.getValue;
+            col.cellType = 'imageBtn';
+            col.normalImg = '#rela-file-icon';
+            col.indent = 12;
+            col.imgAlign = 2;
+            col.showImage = function (data) { return data && data[r.url_field]; }
+        });
+    };
     const setQcCols = function (cols, rela){
-        for (const r of rela) {
-            const col = _.find(cols, {field: r.field});
-            if (!col) continue;
-
+        setRelaCols(cols, rela, function(col, r) {
             col.readOnly = true;
             col.cellType = 'activeImageBtn';
             col.normalImg = '#ellipsis-icon';
             col.indent = 5;
             col.showImage = r.showImage;
-        }
+        });
     };
     const setOrgPriceCol = function (cols, rela) {
-        for (const r of rela) {
-            const col = _.find(cols, {field: r.field});
-            if (col) {
-                col.getValue = function (data) { return data.contract_pc_tp || data.qc_pc_tp || data.pc_tp ? data.org_price : null; };
-            }
-        }
+        setRelaCols(cols, rela, function(col, r) {
+            col.getValue = function (data) { return data.contract_pc_tp || data.qc_pc_tp || data.pc_tp ? data.org_price : null; };
+        });
     };
     const setNodeTypeCol = function (cols, rela) {
-        for (const r of rela) {
-            const col = _.find(cols, {field: r.field});
-            if (col) {
-                col.comboItems = nodeType;
-                col.cellType = 'specCombo';
-                col.comboEdit = function (sheet, data) {
-                    if (!data) return false;
+        setRelaCols(cols, rela, function(col, r) {
+            col.comboItems = nodeType;
+            col.cellType = 'specCombo';
+            col.comboEdit = function (sheet, data) {
+                if (!data) return false;
 
-                    const tree = sheet.zh_tree;
-                    if (!tree) return false;
+                const tree = sheet.zh_tree;
+                if (!tree) return false;
 
-                    const parent = tree.getParent(data);
-                    if (!parent) return false;
+                const parent = tree.getParent(data);
+                if (!parent) return false;
 
-                    return true;
-                    // const topParent = tree.getTopParent(data);
-                    // return [1, 5].indexOf(topParent.node_type) >= 0;
-                };
-            }
-        }
+                return true;
+                // const topParent = tree.getTopParent(data);
+                // return [1, 5].indexOf(topParent.node_type) >= 0;
+            };
+        });
+    };
+    const setIsTpCol = function(cols, rela) {
+        setRelaCols(cols, rela, function(col, r) {
+            col.headerCellType = 'tip';
+            col.getHeaderTip = function() { return '可用单位:元、总额、台、个、处、月 、棵、套、组、辆'; };
+        });
     };
     return {
         setFxTreeStyle, FxTreeStyle, setGridSelectStyle,
         setTpThousandthFormat, setThousandthFormat, setTpColsThousandthFormat,
-        setPropValue, set3FCols, setQcCols, setOrgPriceCol, setNodeTypeCol,
+        setPropValue, set3FCols, setQcCols, setOrgPriceCol, setNodeTypeCol, setIsTpCol,
     };
 })();

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

@@ -779,9 +779,7 @@ $(document).ready(() => {
             },
         },
     ];
-    const isTpCol = ledgerSpreadSetting.cols.find(x => { return x.field === 'is_tp'; });
-    isTpCol.headerCellType = 'tip';
-    isTpCol.getHeaderTip = function() { return '可用单位:元、总额、台、个、处、月 、棵、套、组、辆'; };
+    sjsSettingObj.setIsTpCol(ledgerSpreadSetting.cols, [ {field: 'is_tp'} ]);
     ledgerSpreadSetting.readOnly = function (data) {
         if (!data) return false;
         return data.lock || stageTreeSpreadObj.assistReadOnly;

+ 160 - 89
app/public/js/tender_list_info.js

@@ -8,65 +8,81 @@
  * @version
  */
 const tenderListSpec = (function(){
+    let colSetCache;
+    function generateColSetCache() {
+        const result = {};
+        colSet.forEach(x => {
+            result[x.field] = { show: x.show, alias: x.alias || x.name };
+        });
+        return result;
+    };
     function getTenderNodeHtml(node, arr, pid) {
         const html = [];
         html.push('<tr pid="' + pid + '">');
         // 名称
-        html.push('<td style="min-width: 300px;" class="in-' + node.level + '">');
-        if (node.cid) {
-            html.push('<span onselectstart="return false" style="{-moz-user-select:none}" class="fold-switch mr-1" title="收起" cid="'+ node.sort_id +'"><i class="fa fa-minus-square-o"></i></span> <i class="fa fa-folder-o"></i> ');
-            html.push((node.level === 1 ? '<b>' : ''), node.name, (node.level === 1 ? '</b>' : ''));
-        } else {
-            html.push('<span class="text-muted mr-2">');
-            html.push(arr.indexOf(node) === arr.length - 1 ? '└' : '├');
-            html.push('</span>');
-            //html.push('<a href="/tender/' + node.id + '">', node[c.field], '</a>');
-            html.push('<a href="javascript: void(0)" name="name" style="min-width: 300px;word-break:break-all;" id="' + node.id + '">', node.name, '</a>');
-        }
-        html.push('</td>');
+        if (colSetCache.name.show) {
+            html.push('<td style="min-width: 300px;" class="in-' + node.level + '">');
+            if (node.cid) {
+                html.push('<span onselectstart="return false" style="{-moz-user-select:none}" class="fold-switch mr-1" title="收起" cid="' + node.sort_id + '"><i class="fa fa-minus-square-o"></i></span> <i class="fa fa-folder-o"></i> ');
+                html.push((node.level === 1 ? '<b>' : ''), node.name, (node.level === 1 ? '</b>' : ''));
+            } else {
+                html.push('<span class="text-muted mr-2">');
+                html.push(arr.indexOf(node) === arr.length - 1 ? '└' : '├');
+                html.push('</span>');
+                //html.push('<a href="/tender/' + node.id + '">', node[c.field], '</a>');
+                html.push('<a href="javascript: void(0)" name="name" style="min-width: 300px;word-break:break-all;" id="' + node.id + '">', node.name, '</a>');
+            }
+            html.push('</td>');
+        }
         // 计量模式
-        html.push('<td style="width: 85px" class="text-center">');
-        if (node.measure_type) {
-            html.push(node.measure_type === measureType.tz.value ? '0号台账' : '工程量清单');
+        if (colSetCache.measure_type.show) {
+            html.push('<td style="width: 85px" class="text-center">');
+            if (node.measure_type) {
+                html.push(node.measure_type === measureType.tz.value ? '0号台账' : '工程量清单');
+            }
+            html.push('</td>');
         }
-        html.push('</td>');
         // 计量进度
-        html.push('<td style="width: 125px">');
-        if (!node.cid && node.cur_flow) {
-            if (node.progress) {
-                html.push(node.progress.title + ' (' + '<span class="' + node.progress.status_class +'">' + node.progress.status + '</span>' + ')');
-            } else {
-                html.push(node.cur_flow.title + ' (' + '<span class="' + node.cur_flow.status_class +'">' + node.cur_flow.status + '</span>' + ')');
+        if (colSetCache.calc_flow.show) {
+            html.push('<td style="width: 125px">');
+            if (!node.cid && node.cur_flow) {
+                if (node.progress) {
+                    html.push(node.progress.title + ' (' + '<span class="' + node.progress.status_class + '">' + node.progress.status + '</span>' + ')');
+                } else {
+                    html.push(node.cur_flow.title + ' (' + '<span class="' + node.cur_flow.status_class + '">' + node.cur_flow.status + '</span>' + ')');
+                }
             }
+            html.push('</td>');
         }
-        html.push('</td>');
         // 当前流程
-        html.push('<td style="width: 230px">');
-        if (!node.cid && node.cur_flow) {
-            const curUser = node.cur_flow instanceof Array && node.cur_flow[0].audit_type && node.cur_flow[0].audit_type !== auditType.key.common
-                ? transFormToChinese(node.cur_flow[0].audit_order) + '审'
-                : node.cur_flow instanceof Array ? (node.cur_flow[0].name + (node.cur_flow[0].role ? '-'+node.cur_flow[0].role  : '')): (node.cur_flow.name + (node.cur_flow.role ? '-'+node.cur_flow.role  : ''));
-            if (node.stage_status !== undefined) {
-                html.push(((node.stage_count && node.stage_status === auditConst.stage.status.uncheck) || node.ledger_status === auditConst.ledger.status.uncheck)
-                    ? curUser
-                    : `<a href="#sp-list" data-toggle="modal" data-target="#sp-list"  data-type="${node.stage_count ? 'stage' : 'ledger'}" data-tender="${node.id}" data-order="${node.stage_count ? node.stage_count + '' : ''}">${curUser}</a>`
-                );
-                html.push(`<span class="${node.progress.status_class} ml-1">${node.progress.status}</span>`);
-            } else {
-                html.push((node.lastStage && node.lastStage.status === auditConst.stage.status.uncheck) || (!node.lastStage && node.ledger_status === auditConst.ledger.status.uncheck ) ? '' :
-                    '<a href="#sp-list" data-toggle="modal" data-target="#sp-list"  data-type="'+ (node.lastStage ? 'stage' : 'ledger') +'"' +
-                    ' data-tender="'+ node.id +'" data-order="'+ (node.lastStage ? node.lastStage.order : '') +'">');
-                html.push(curUser);
-                html.push((node.lastStage && node.lastStage.status === auditConst.stage.status.uncheck) || (!node.lastStage && node.ledger_status === auditConst.ledger.status.uncheck ) ? ' ':
-                    '</a> ');
-                if (node.cur_flow instanceof Array) {
-                    html.push('<span class="' + node.cur_flow[0].status_class +'">' + node.cur_flow[0].status + '</span>');
+        if (colSetCache.cur_flow.show) {
+            html.push('<td style="width: 230px">');
+            if (!node.cid && node.cur_flow) {
+                const curUser = node.cur_flow instanceof Array && node.cur_flow[0].audit_type && node.cur_flow[0].audit_type !== auditType.key.common
+                    ? transFormToChinese(node.cur_flow[0].audit_order) + '审'
+                    : node.cur_flow instanceof Array ? (node.cur_flow[0].name + (node.cur_flow[0].role ? '-' + node.cur_flow[0].role : '')) : (node.cur_flow.name + (node.cur_flow.role ? '-' + node.cur_flow.role : ''));
+                if (node.stage_status !== undefined) {
+                    html.push(((node.stage_count && node.stage_status === auditConst.stage.status.uncheck) || node.ledger_status === auditConst.ledger.status.uncheck)
+                        ? curUser
+                        : `<a href="#sp-list" data-toggle="modal" data-target="#sp-list"  data-type="${node.stage_count ? 'stage' : 'ledger'}" data-tender="${node.id}" data-order="${node.stage_count ? node.stage_count + '' : ''}">${curUser}</a>`
+                    );
+                    html.push(`<span class="${node.progress.status_class} ml-1">${node.progress.status}</span>`);
                 } else {
-                    html.push('<span class="' + node.cur_flow.status_class +'">' + node.cur_flow.status + '</span>');
+                    html.push((node.lastStage && node.lastStage.status === auditConst.stage.status.uncheck) || (!node.lastStage && node.ledger_status === auditConst.ledger.status.uncheck) ? '' :
+                        '<a href="#sp-list" data-toggle="modal" data-target="#sp-list"  data-type="' + (node.lastStage ? 'stage' : 'ledger') + '"' +
+                        ' data-tender="' + node.id + '" data-order="' + (node.lastStage ? node.lastStage.order : '') + '">');
+                    html.push(curUser);
+                    html.push((node.lastStage && node.lastStage.status === auditConst.stage.status.uncheck) || (!node.lastStage && node.ledger_status === auditConst.ledger.status.uncheck) ? ' ' :
+                        '</a> ');
+                    if (node.cur_flow instanceof Array) {
+                        html.push('<span class="' + node.cur_flow[0].status_class + '">' + node.cur_flow[0].status + '</span>');
+                    } else {
+                        html.push('<span class="' + node.cur_flow.status_class + '">' + node.cur_flow.status + '</span>');
+                    }
                 }
             }
+            html.push('</td>');
         }
-        html.push('</td>');
         // 上一流程审批时间
         // html.push('<td style="width: 7%">');
         // if (!node.cid && node.pre_flow) {
@@ -74,67 +90,110 @@ const tenderListSpec = (function(){
         // }
         // html.push('</td>');
         // 签约合同价
-        html.push('<td style="width: 100px" class="text-right">');
-        html.push(node.contract_price || '');
-        html.push('</td>');
+        if (colSetCache.contract_price.show) {
+            html.push('<td style="width: 100px" class="text-right">');
+            html.push(node.contract_price || '');
+            html.push('</td>');
+        }
         // 0号台账合同
-        html.push('<td style="width: 100px" class="text-right">');
-        html.push(node.total_price || '');
-        html.push('</td>');
+        if (colSetCache.total_price.show) {
+            html.push('<td style="width: 100px" class="text-right">');
+            html.push(node.total_price || '');
+            html.push('</td>');
+        }
         // 本期完成
-        html.push('<td style="width: 100px" class="text-right">');
-        html.push(node.gather_tp || '');
-        html.push('</td>');
+        if (colSetCache.gather_tp.show) {
+            html.push('<td style="width: 100px" class="text-right">');
+            html.push(node.gather_tp || '');
+            html.push('</td>');
+        }
         // 截止本期合同
-        html.push('<td style="width: 100px" class="text-right">');
-        html.push(node.end_contract_tp || '');
-        html.push('</td>');
+        if (colSetCache.end_contract_tp.show) {
+            html.push('<td style="width: 100px" class="text-right">');
+            html.push(node.end_contract_tp || '');
+            html.push('</td>');
+        }
         // 截止本期变更
-        html.push('<td style="width: 100px" class="text-right">');
-        html.push(node.end_qc_tp || '');
-        html.push('</td>');
+        if (colSetCache.end_qc_tp.show) {
+            html.push('<td style="width: 100px" class="text-right">');
+            html.push(node.end_qc_tp || '');
+            html.push('</td>');
+        }
         // 截止本期完成
-        html.push('<td style="width: 100px" class="text-right">');
-        html.push(node.end_gather_tp || '');
-        html.push('</td>');
+        if (colSetCache.end_gather_tp.show) {
+            html.push('<td style="width: 100px" class="text-right">');
+            html.push(node.end_gather_tp || '');
+            html.push('</td>');
+        }
         // 截止上期完成
-        html.push('<td style="width: 100px" class="text-right">');
-        html.push(node.pre_gather_tp || '');
-        html.push('</td>');
+        if (colSetCache.pre_gather_tp.show) {
+            html.push('<td style="width: 100px" class="text-right">');
+            html.push(node.pre_gather_tp || '');
+            html.push('</td>');
+        }
         // 预付款
-        html.push('<td style="width: 100px" class="text-right">');
-        html.push(node.advance_tp || '');
-        html.push('</td>');
+        if (colSetCache.advance_tp.show) {
+            html.push('<td style="width: 100px" class="text-right">');
+            html.push(node.advance_tp || '');
+            html.push('</td>');
+        }
         // 本期应付
-        html.push('<td style="width: 100px" class="text-right">');
-        html.push(node.yf_tp || '');
-        html.push('</td>');
+        if (colSetCache.yf_tp.show) {
+            html.push('<td style="width: 100px" class="text-right">');
+            html.push(node.yf_tp || '');
+            html.push('</td>');
+        }
         // 截止本期应付
-        html.push('<td style="width: 100px" class="text-right">');
-        html.push(node.end_yf_tp || '');
-        html.push('</td>');
+        if (colSetCache.end_yf_tp.show) {
+            html.push('<td style="width: 100px" class="text-right">');
+            html.push(node.end_yf_tp || '');
+            html.push('</td>');
+        }
+        // 本期实付
+        if (colSetCache.sf_tp.show) {
+            html.push('<td style="width: 100px" class="text-right">');
+            html.push(node.yf_tp || '');
+            html.push('</td>');
+        }
+        // 截止本期实付
+        if (colSetCache.end_sf_tp.show) {
+            html.push('<td style="width: 100px" class="text-right">');
+            html.push(node.end_sf_tp || '');
+            html.push('</td>');
+        }
+        // 本期未付
+        if (colSetCache.wf_tp.show) {
+            html.push('<td style="width: 100px" class="text-right">');
+            html.push(node.wf_tp || '');
+            html.push('</td>');
+        }
         html.push('</tr>');
         return html.join('');
     }
     function getTenderTreeHeaderHtml() {
+        colSetCache = generateColSetCache();
+        console.log(colSetCache);
         const html = [];
         html.push('<table class="table table-hover table-bordered">');
         html.push('<thead style="position: fixed;left:56px;top: 34px;">', '<tr>');
-        html.push('<th class="text-center" style="min-width: 300px;">', '标段名称', '</th>');
-        html.push('<th class="text-center" style="width: 85px">', '计量模式', '</th>');
-        html.push('<th class="text-center" style="width: 125px">', '计量进度', '</th>');
-        html.push('<th class="text-center" style="width: 230px">', '当前流程', '</th>');
+        if (colSetCache.name.show) html.push('<th class="text-center" style="min-width: 300px;">', colSetCache.name.alias, '</th>');
+        if (colSetCache.measure_type.show) html.push('<th class="text-center" style="width: 85px">', colSetCache.measure_type.alias, '</th>');
+        if (colSetCache.calc_flow.show) html.push('<th class="text-center" style="width: 125px">', colSetCache.calc_flow.alias, '</th>');
+        if (colSetCache.cur_flow.show) html.push('<th class="text-center" style="width: 230px">', colSetCache.cur_flow.alias, '</th>');
         // html.push('<th class="text-center" style="width: 7%">', '上一流程审批时间', '</th>');
-        html.push('<th class="text-center" style="width: 100px">', '签约合同价', '</th>');
-        html.push('<th class="text-center" style="width: 100px">', '0号台账', '</th>');
-        html.push('<th class="text-center" style="width: 100px">', '本期完成', '</th>');
-        html.push('<th class="text-center" style="width: 100px">', '截止本期合同', '</th>');
-        html.push('<th class="text-center" style="width: 100px">', '截止本期变更', '</th>');
-        html.push('<th class="text-center" style="width: 100px">', '截止本期完成', '</th>');
-        html.push('<th class="text-center" style="width: 100px">', '截止上期完成', '</th>');
-        html.push('<th class="text-center" style="width: 100px">', '预付款', '<i class="fa fa-question-circle text-primary" data-placement="bottom" data-toggle="tooltip" data-original-title="预付款流程中截止本期金额"></i>', '</th>');
-        html.push('<th class="text-center" style="width: 100px">', '本期应付', '</th>');
-        html.push('<th class="text-center" style="width: 100px">', '截止本期应付', '</th>');
+        if (colSetCache.contract_price.show) html.push('<th class="text-center" style="width: 100px">', colSetCache.contract_price.alias, '</th>');
+        if (colSetCache.total_price.show) html.push('<th class="text-center" style="width: 100px">', colSetCache.total_price.alias, '</th>');
+        if (colSetCache.gather_tp.show) html.push('<th class="text-center" style="width: 100px">', colSetCache.gather_tp.alias, '</th>');
+        if (colSetCache.end_contract_tp.show) html.push('<th class="text-center" style="width: 100px">', colSetCache.end_contract_tp.alias, '</th>');
+        if (colSetCache.end_qc_tp.show) html.push('<th class="text-center" style="width: 100px">', colSetCache.end_qc_tp.alias, '</th>');
+        if (colSetCache.end_gather_tp.show) html.push('<th class="text-center" style="width: 100px">', colSetCache.end_gather_tp.alias, '</th>');
+        if (colSetCache.pre_gather_tp.show) html.push('<th class="text-center" style="width: 100px">', colSetCache.pre_gather_tp.alias, '</th>');
+        if (colSetCache.advance_tp.show) html.push('<th class="text-center" style="width: 100px">', colSetCache.advance_tp.alias, '<i class="fa fa-question-circle text-primary" data-placement="bottom" data-toggle="tooltip" data-original-title="预付款流程中截止本期金额"></i>', '</th>');
+        if (colSetCache.yf_tp.show) html.push('<th class="text-center" style="width: 100px">', colSetCache.yf_tp.alias, '</th>');
+        if (colSetCache.end_yf_tp.show) html.push('<th class="text-center" style="width: 100px">', colSetCache.end_yf_tp.alias, '</th>');
+        if (colSetCache.sf_tp.show) html.push('<th class="text-center" style="width: 100px">', colSetCache.sf_tp.alias, '</th>');
+        if (colSetCache.end_sf_tp.show) html.push('<th class="text-center" style="width: 100px">', colSetCache.end_sf_tp.alias, '</th>');
+        if (colSetCache.wf_tp.show) html.push('<th class="text-center" style="width: 100px">', colSetCache.wf_tp.alias, '</th>');
         html.push('</tr>', '</thead>');
         return html.join('');
     }
@@ -147,6 +206,9 @@ const tenderListSpec = (function(){
             tender.pre_gather_tp = ZhCalc.add(tender.stage_tp.pre_contract_tp, tender.stage_tp.pre_qc_tp);
             tender.yf_tp = ZhCalc.add(tender.stage_tp.yf_tp);
             tender.end_yf_tp = ZhCalc.add(tender.stage_tp.pre_yf_tp, tender.yf_tp);
+            tender.sf_tp = ZhCalc.add(tender.stage_tp.sf_tp);
+            tender.end_sf_tp = ZhCalc.add(tender.stage_tp.pre_sf_tp, tender.sf_tp);
+            tender.wf_tp = ZhCalc.sub(tender.end_yf_tp, tender.end_sf_tp);
         } else if (tender.lastStage) {
             tender.gather_tp = ZhCalc.sum([tender.lastStage.contract_tp, tender.lastStage.qc_tp, tender.lastStage.pc_tp]);
             tender.end_contract_tp = ZhCalc.sum([tender.lastStage.pre_contract_tp, tender.lastStage.contract_tp, tender.lastStage.contract_pc_tp]);
@@ -155,6 +217,9 @@ const tenderListSpec = (function(){
             tender.pre_gather_tp = ZhCalc.add(tender.lastStage.pre_contract_tp, tender.lastStage.pre_qc_tp);
             tender.yf_tp = ZhCalc.add(tender.lastStage.yf_tp);
             tender.end_yf_tp = ZhCalc.add(tender.lastStage.pre_yf_tp, tender.yf_tp);
+            tender.sf_tp = ZhCalc.add(tender.lastStage.sf_tp);
+            tender.end_sf_tp = ZhCalc.add(tender.lastStage.pre_sf_tp, tender.sf_tp);
+            tender.wf_tp = ZhCalc.sub(tender.end_yf_tp, tender.end_sf_tp);
         }
     }
     function calculateParent(node) {
@@ -169,6 +234,9 @@ const tenderListSpec = (function(){
             node.end_yf_tp = 0;
             node.advance_tp = 0;
             node.contract_price = 0;
+            node.sf_tp = 0;
+            node.end_sf_tp = 0;
+            node.wf_tp = 0;
             for (const c of node.children) {
                 calculateParent(c);
                 node.total_price = ZhCalc.add(node.total_price, c.total_price);
@@ -181,6 +249,9 @@ const tenderListSpec = (function(){
                 node.end_yf_tp = ZhCalc.add(node.end_yf_tp, c.end_yf_tp);
                 node.advance_tp = ZhCalc.add(node.advance_tp, c.advance_tp);
                 node.contract_price = ZhCalc.add(node.contract_price, c.contract_price);
+                node.sf_tp = ZhCalc.add(node.sf_tp, c.sf_tp);
+                node.end_sf_tp = ZhCalc.add(node.end_sf_tp, c.end_sf_tp);
+                node.wf_tp = ZhCalc.add(node.wf_tp, c.wf_tp);
             }
         }
     }

+ 1 - 0
app/router.js

@@ -160,6 +160,7 @@ module.exports = app => {
     app.post('/list/load2', sessionAuth, 'tenderController.listLoad2');
     app.get('/list/info', sessionAuth, 'tenderController.listInfo');
     app.get('/list/info/finish', sessionAuth, 'tenderController.listInfoFinish');
+    app.post('/list/info/col-set', sessionAuth, projectManagerCheck, 'projectController.colSet');
 
     // 计量进度
     app.get('/list/progress', sessionAuth, 'tenderController.listProgress');

+ 2 - 2
app/service/change.js

@@ -1286,8 +1286,6 @@ module.exports = app => {
                     },
                 };
                 await this.transaction.update(this.tableName, change_update, options);
-                await this.transaction.commit();
-                result = true;
                 const sms = new SMS(this.ctx);
                 const code = await sms.contentChange(changeData.code);
                 const shenpiUrl = await this.ctx.helper.urlToShort(
@@ -1317,6 +1315,8 @@ module.exports = app => {
                     template: wxConst.template.change,
                     wx_data: wechatData,
                 });
+                await this.transaction.commit();
+                result = true;
             } catch (error) {
                 console.log(error);
                 await this.transaction.rollback();

+ 24 - 15
app/service/project_account.js

@@ -453,11 +453,15 @@ module.exports = app => {
         }
 
         async addUsers(pid, users) {
+            const projectData = await this.ctx.service.project.getDataById(pid);
+            const maxUser = projectData.max_user;
             const paList = await this.getAllDataByCondition({ where: { project_id: pid } });
             const insertData = [];
             const create_time = Date.parse(new Date()) / 1000;
             // 判断新密码的强度
             const reg = /^(?![0-9]+$)(?![a-zA-Z]+$).{6,16}$/;
+            let userTotal = paList.length;
+            let overMax = false;
             for (const u of users) {
                 if (u.account === undefined || u.account === null || u.name === undefined || u.name === null ||
                     u.password === undefined || u.password === null || u.company === undefined || u.company === null ||
@@ -472,24 +476,29 @@ module.exports = app => {
                 u.company_id = companyInfo.id;
                 u.account_group = companyInfo.type;
                 if (this._.findIndex(paList, { account: u.account }) === -1 && this._.findIndex(insertData, { account: u.account }) === -1) {
-                    insertData.push({
-                        project_id: pid,
-                        account: u.account,
-                        name: u.name,
-                        password: crypto.createHmac('sha1', u.account).update(u.password)
-                            .digest().toString('base64'),
-                        account_group: u.account_group,
-                        company: u.company,
-                        company_id: companyInfo.id,
-                        role: u.role,
-                        mobile: u.mobile || '',
-                        telephone: u.telephone || '',
-                        create_time,
-                    });
+                    if (maxUser === 0 || userTotal < maxUser) {
+                        insertData.push({
+                            project_id: pid,
+                            account: u.account,
+                            name: u.name,
+                            password: crypto.createHmac('sha1', u.account).update(u.password)
+                                .digest().toString('base64'),
+                            account_group: u.account_group,
+                            company: u.company,
+                            company_id: companyInfo.id,
+                            role: u.role,
+                            mobile: u.mobile || '',
+                            telephone: u.telephone || '',
+                            create_time,
+                        });
+                        userTotal++;
+                    } else {
+                        overMax = true;
+                    }
                 }
             }
             if (insertData.length > 0) await this.db.insert(this.tableName, insertData);
-            return insertData.length;
+            return { insertNum: insertData.length, overMax };
         }
 
         /**

+ 75 - 0
app/service/project_col_set.js

@@ -0,0 +1,75 @@
+'use strict';
+
+/**
+ *
+ *
+ * @author Mai
+ * @date 2024/3/5
+ * @version
+ */
+
+const JsonFields = [ 'info' ];
+const ProjectSetting = require('../const/project_setting');
+
+module.exports = app => {
+
+    class ProjectColSet extends app.BaseService {
+
+        /**
+         * 构造函数
+         *
+         * @param {Object} ctx - egg全局变量
+         * @return {void}
+         */
+        constructor(ctx) {
+            super(ctx);
+            this.tableName = 'project_col_set';
+        }
+
+        _analysisData(data) {
+            if (!data) return;
+            JsonFields.forEach(jf => { if(data[jf]) data[jf] = JSON.parse(data[jf]); });
+        }
+
+        async loadProjectColSet(id) {
+            const result = await this.getDataById(id);
+            this._analysisData(result);
+            return result;
+        }
+
+        async initProjectColSet(id) {
+            const data = ProjectSetting.defaultColSet;
+            JsonFields.forEach(jf => { if(data[jf]) data[jf] = JSON.stringify(data[jf]); });
+            data.id = id;
+            await this.db.insert(this.tableName, data);
+        }
+
+        async getProjectColSet(id) {
+            const curSet = await this.loadProjectColSet(id);
+            if (curSet) return curSet;
+            await this.initProjectColSet(id);
+            return await this.loadProjectColSet(id);
+        }
+
+        async setProjectColSet(id, colSetType, colSet) {
+            const data = {id};
+            data[colSetType] = JSON.stringify(colSet);
+            await this.defaultUpdate(data);
+        }
+
+        analysisColSetWithDefine(colSetDefine, colSet) {
+            const result = [];
+            for (const csd of colSetDefine) {
+                const cs = colSet.find(x => { return x.field === csd.field });
+                if (cs) {
+                    result.push({...csd, ...cs});
+                } else {
+                    result.push({...csd});
+                }
+            }
+            return result;
+        }
+    }
+
+    return ProjectColSet;
+};

+ 52 - 21
app/service/project_spread.js

@@ -31,11 +31,14 @@ module.exports = app => {
             this.tableName = 'project_spread';
         }
 
-        async loadProjectSpread(id) {
-            const result = await this.getDataByCondition({ id });
-            if (result) {
-                JsonFields.forEach(jf => { if(result[jf]) result[jf] = JSON.parse(result[jf]); });
-            }
+        _analysisData(data) {
+            if (!data) return;
+            JsonFields.forEach(jf => { if(data[jf]) data[jf] = JSON.parse(data[jf]); });
+        }
+
+        async loadProjectSpread(id, code = '') {
+            const result = code ? await this.getDataByCondition({ pid: id, code }) : await this.getDataByCondition({ pid: id, is_default: 1 });
+            this._analysisData(result);
             return result;
         }
 
@@ -80,31 +83,59 @@ module.exports = app => {
         }
 
         async initProjectSpread(id) {
-            const data = JSON.parse(JSON.stringify(SpreadConst.ProjectSpreadTemplate));
-            [data.tz_ledger_bills_spread, data.tz_ledger_pos_spread] = this.generateRelaSpread('tz_ledger_set', data.tz_ledger_set);
-            [data.tz_stage_bills_spread, data.tz_stage_pos_spread] = this.generateRelaSpread('tz_stage_set', data.tz_stage_set);
-            [data.gcl_ledger_bills_spread, data.gcl_ledger_pos_spread] = this.generateRelaSpread('gcl_ledger_set', data.gcl_ledger_set);
-            [data.gcl_stage_bills_spread, data.gcl_stage_pos_spread] = this.generateRelaSpread('gcl_stage_set', data.gcl_stage_set);
-            data.id = id;
-            const updateData = { id };
-            JsonFields.forEach(jf => { if (data[jf]) updateData[jf] = JSON.stringify(data[jf]) });
-            const result = await this.db.insert(this.tableName, updateData);
-            if (result.insertId = data.id) return data;
+            for (const SpreadTemplate of SpreadConst.ProjectSpreadTemplate) {
+                const data = JSON.parse(JSON.stringify(SpreadTemplate.template));
+                [data.tz_ledger_bills_spread, data.tz_ledger_pos_spread] = this.generateRelaSpread('tz_ledger_set', data.tz_ledger_set);
+                [data.tz_stage_bills_spread, data.tz_stage_pos_spread] = this.generateRelaSpread('tz_stage_set', data.tz_stage_set);
+                [data.gcl_ledger_bills_spread, data.gcl_ledger_pos_spread] = this.generateRelaSpread('gcl_ledger_set', data.gcl_ledger_set);
+                [data.gcl_stage_bills_spread, data.gcl_stage_pos_spread] = this.generateRelaSpread('gcl_stage_set', data.gcl_stage_set);
+                const updateData = { pid: id, code: SpreadTemplate.code, name: SpreadTemplate.name, is_default: SpreadTemplate.isDefault };
+                JsonFields.forEach(jf => { if (data[jf]) updateData[jf] = JSON.stringify(data[jf]) });
+                await this.db.insert(this.tableName, updateData);
+            }
         }
 
-        async getProjectSpread(id) {
-            const curSet = await this.loadProjectSpread(id);
+        async getProjectSpread(id, code) {
+            const curSet = await this.loadProjectSpread(id, code);
             if (curSet) return curSet;
-            return await this.initProjectSpread(id);
+            await this.initProjectSpread(id);
+            return await this.loadProjectSpread(id, code);
+        }
+
+        async getProjectSpreadType(id) {
+            const result = await this.getAllDataByCondition({
+                columns: ['code', 'name', 'is_default'],
+                where: { pid: id },
+            });
+            if (result.length > 0) return result;
+
+            await this.initProjectSpread(id);
+            return await this.getAllDataByCondition({
+                columns: ['code', 'name', 'is_default'],
+                where: { pid: id },
+            });
         }
 
-        async updateProjectSet(id, colSetType, colSet) {
-            const updateData = { id };
+        async updateProjectSet(id, code, colSetType, colSet) {
+            const updateData = {};
+            const [billsSpread, posSpread] = this.generateRelaSpread(colSetType, colSet);
+            updateData[colSetType.replace('_set', '_bills_spread')] = JSON.stringify(billsSpread);
+            updateData[colSetType.replace('_set', '_pos_spread')] = JSON.stringify(posSpread);
+            updateData[colSetType] = JSON.stringify(colSet);
+            await this.defaultUpdate(updateData, { where: { pid: id, code } });
+        }
+
+        async resetProjectSet(id, code, colSetType, resetCode) {
+            const SpreadTemplate = SpreadConst.ProjectSpreadTemplate.find(x => { return x.code === resetCode; });
+            if (!SpreadTemplate) throw '选择模板不存在';
+
+            const colSet = SpreadTemplate.template[colSetType];
+            const updateData = {};
             const [billsSpread, posSpread] = this.generateRelaSpread(colSetType, colSet);
             updateData[colSetType.replace('_set', '_bills_spread')] = JSON.stringify(billsSpread);
             updateData[colSetType.replace('_set', '_pos_spread')] = JSON.stringify(posSpread);
             updateData[colSetType] = JSON.stringify(colSet);
-            await this.db.update(this.tableName, updateData);
+            await this.defaultUpdate(updateData, { where: { pid: id, code } });
         }
     }
 

+ 6 - 6
app/service/report_memory.js

@@ -393,7 +393,7 @@ module.exports = app => {
             const helper = this.ctx.helper;
             const tender = this.ctx.tender;
             const stage = this.ctx.stage;
-            const preBglData = stage.order > 1 ? await this.ctx.service.stageChangeFinal.getFinalChangeBills(tender.id, stage.order - 1) : [];
+            const preBglData = stage.preCheckedStage ? await this.ctx.service.stageChangeFinal.getFinalChangeBills(tender.id, stage.preCheckedStage.order) : [];
             for (const node of billsTree.nodes) {
                 node.pre_qc_bgl_code = '';
                 node.pre_qc_bgl_arr = [];
@@ -535,7 +535,7 @@ module.exports = app => {
                     }
                 }
                 if (this._checkFieldsExist(fields, billsFields.stageEnd)) {
-                    preStage = this.ctx.stage.order > 1 ? await this.ctx.service.stageBillsFinal.getFinalData(this.ctx.tender, this.ctx.stage.order - 1) : [];
+                    preStage = this.ctx.stage.preCheckedStage ? await this.ctx.service.stageBillsFinal.getFinalData(this.ctx.tender, this.ctx.stage.preCheckedStage.order) : [];
                 }
                 const bpcStage = await this.ctx.service.stageBillsPc.getAllDataByCondition({ where: { sid: this.ctx.stage.id } });
                 const endBpcStage = await this.ctx.service.stageBillsPc.getEndStageData(this.ctx.stage);
@@ -625,7 +625,7 @@ module.exports = app => {
                     }
                 }
                 if (this._checkFieldsExist(fields, posFields.stageEnd)) {
-                    prePosStage = this.ctx.stage.order > 1 ? await this.ctx.service.stagePosFinal.getFinalData(this.ctx.tender, this.ctx.stage.order - 1) : [];
+                    prePosStage = this.ctx.stage.preCheckedStage ? await this.ctx.service.stagePosFinal.getFinalData(this.ctx.tender, this.ctx.stage.preCheckedStage.order) : [];
                 }
                 const changeData = this._checkFieldsExistReg(fields, 'due_')
                     ? await this.ctx.service.changeAuditList.getPosSum(this.ctx.tender.id)
@@ -715,8 +715,8 @@ module.exports = app => {
 
                 const bpcStage = await this.ctx.service.stageBillsPc.getAllDataByCondition({ where: { sid: this.ctx.stage.id } });
                 const endBpcStage = await this.ctx.service.stageBillsPc.getEndStageData(this.ctx.stage);
-                const preStage = this._checkFieldsExist(fields, billsFields.stageEnd) && this.ctx.stage.order > 1
-                    ? await this.ctx.service.stageBillsFinal.getFinalData(this.ctx.tender, this.ctx.stage.order - 1)
+                const preStage = this._checkFieldsExist(fields, billsFields.stageEnd) && this.ctx.stage.preCheckedStage
+                    ? await this.ctx.service.stageBillsFinal.getFinalData(this.ctx.tender, this.ctx.stage.preCheckedStage.order)
                     : [];
 
                 this.ctx.helper.assignRelaData(billsData, [
@@ -779,7 +779,7 @@ module.exports = app => {
 
                 const allStagePos = await this.ctx.service.stagePos.getAllDataByCondition({where: {sid: sid}});
                 const posData = await this.ctx.service.pos.getAllDataByCondition({ where: {tid: this.ctx.tender.id }});
-                const prePosStage = this.ctx.stage.order > 1 ? await this.ctx.service.stagePosFinal.getFinalData(this.ctx.tender, this.ctx.stage.order - 1) : [];
+                const prePosStage = this.ctx.stage.preCheckedStage ? await this.ctx.service.stagePosFinal.getFinalData(this.ctx.tender, this.ctx.stage.preCheckedStage.order) : [];
                 this.ctx.helper.assignRelaData(posData, [
                     {data: prePosStage, fields: ['contract_qty', 'qc_qty', 'qc_minus_qty'], prefix: 'pre_', relaId: 'pid'}
                 ]);

+ 6 - 6
app/service/rpt_gather_memory.js

@@ -611,7 +611,7 @@ module.exports = app => {
                 const curStage = stage.readOnly
                     ? await this.ctx.service.stageBills.getAuditorStageData2(tender.id, stage.id, stage.curTimes, stage.curOrder)
                     : await this.ctx.service.stageBills.getLastestStageData2(tender.id, stage.id);
-                const preStage = hasPre && stage.order > 1 ? await this.ctx.service.stageBillsFinal.getFinalData(tender, stage.order - 1) : [];
+                const preStage = hasPre && stage.preCheckedStage ? await this.ctx.service.stageBillsFinal.getFinalData(tender, stage.preCheckedStage.order) : [];
                 const bpcStage = await this.ctx.service.stageBillsPc.getAllDataByCondition({ where: { sid: stage.id } });
                 this.ctx.helper.assignRelaData(billsData, [
                     { data: curStage, fields: ['contract_qty', 'contract_tp', 'qc_qty', 'qc_tp'], prefix: '', relaId: 'lid' },
@@ -622,7 +622,7 @@ module.exports = app => {
                 const curStagePos = stage.readOnly
                     ? await this.ctx.service.stagePos.getAuditorStageData2(tender.id, stage.id, stage.curTimes, stage.curOrder)
                     : await this.ctx.service.stagePos.getLastestStageData2(tender.id, stage.id);
-                const preStagePos = hasPre && stage.order > 1 ? await this.ctx.service.stagePosFinal.getFinalData(tender, stage.order - 1) : [];
+                const preStagePos = hasPre && stage.preCheckedStage ? await this.ctx.service.stagePosFinal.getFinalData(tender, stage.preCheckedStage.order) : [];
                 this.ctx.helper.assignRelaData(posData, [
                     { data: curStagePos, fields: ['contract_qty', 'qc_qty'], prefix: '', relaId: 'pid' },
                     { data: preStagePos, fields: ['contract_qty', 'qc_qty'], prefix: 'pre_', relaId: 'pid' },
@@ -1354,7 +1354,7 @@ module.exports = app => {
 
         async _gatherStageJgcl(tender, stage) {
             const data = await this.ctx.service.stageJgcl.getStageData(stage);
-            const preData = stage.order > 1 ? await this.ctx.service.stageJgcl.getPreStageData(stage.tid, stage.order) : 0;
+            const preData = stage.preCheckedStage ? await this.ctx.service.stageJgcl.getEndStageData(stage.tid, stage.preCheckedStage.order) : [];
             for (const d of data) {
                 const pd = this.ctx.helper._.find(preData, {uuid: d.uuid});
                 if (pd) {
@@ -1479,7 +1479,7 @@ module.exports = app => {
 
         async _gatherStageOther(tender, stage) {
             const data = await this.ctx.service.stageOther.getStageData(stage);
-            const preData = stage.order > 1 ? await this.ctx.service.stageOther.getPreStageData(stage.tid, stage.order) : [];
+            const preData = stage.preCheckedStage ? await this.ctx.service.stageOther.getEndStageData(stage.tid, stage.preCheckedStage.order) : [];
             for (const d of data) {
                 const pd = this.ctx.helper._.find(preData, {uuid: d.uuid});
                 if (pd) {
@@ -1539,7 +1539,7 @@ module.exports = app => {
 
         async _gatherStageSafeProd(tender, stage) {
             const data = await this.ctx.service.stageSafeProd.getStageData(stage);
-            const preData = stage.order > 1 ? await this.ctx.service.stageSafeProd.getPreStageData(stage.tid, stage.order) : [];
+            const preData = stage.preCheckedStage ? await this.ctx.service.stageSafeProd.getEndStageData(stage.tid, stage.preCheckedStage.order) : [];
             for (const d of data) {
                 const pd = this.ctx.helper._.find(preData, {uuid: d.uuid});
                 if (pd) {
@@ -1618,7 +1618,7 @@ module.exports = app => {
 
         async _gatherStageTempLand(tender, stage) {
             const data = await this.ctx.service.stageTempLand.getStageData(stage);
-            const preData = stage.order > 1 ? await this.ctx.service.stageTempLand.getPreStageData(stage.tid, stage.order) : [];
+            const preData = stage.preCheckedStage ? await this.ctx.service.stageTempLand.getEndStageData(stage.tid, stage.preCheckedStage.order) : [];
             for (const d of data) {
                 const pd = this.ctx.helper._.find(preData, {uuid: d.uuid});
                 if (pd) {

+ 1 - 1
app/service/settle.js

@@ -104,7 +104,7 @@ module.exports = app => {
         async addSettle(tenderId, date, period) {
             const settles = await this.getAllDataByCondition({
                 where: { tid: tenderId },
-                order: ['settle_order', 'asc'],
+                orders: [['settle_order', 'asc']],
             });
             const pre = settles[settles.length - 1];
             if (settles.length > 0 && pre.audit_status !== auditConst.settle.status.checked) {

+ 43 - 20
app/service/stage.js

@@ -80,6 +80,8 @@ module.exports = app => {
             stage.curAuditorIds = this._.map(stage.curAuditors, 'aid');
             stage.flowAuditors = stage.curAuditors.length > 0 ? stage.auditors.filter(x => { return x.order === stage.curAuditors[0].order; }) : []; // 当前流程中参与的审批人(包含会签时,审批通过的人)
             stage.flowAuditorIds = this._.map(stage.flowAuditors, 'aid');
+            stage.nextAuditors = stage.curAuditors.length > 0 ? stage.auditors.filter(x => { return x.order === stage.curAuditors[0].order + 1; }) : [];
+            stage.nextAuditorIds = this._.map(stage.nextAuditors, 'aid');
             stage.auditorGroups = this.ctx.helper.groupAuditors(stage.auditors);
             stage.userGroups = this.ctx.helper.groupAuditorsUniq(stage.auditorGroups);
             stage.userGroups.unshift([{
@@ -124,9 +126,23 @@ module.exports = app => {
             }
         }
 
+        async loadPreCheckedStage(stage) {
+            if (stage.order > 1) {
+                const preCheckedStages = await this.ctx.service.stage.getAllDataByCondition({
+                    where: { tid: stage.tid, status: auditConst.stage.status.checked },
+                    orders: [['order', 'desc']],
+                });
+                stage.preCheckedStage = preCheckedStages[0];
+            } else {
+                stage.preCheckedStage = undefined;
+            }
+            stage.isCheckFirst = stage.order > 1 ? (stage.preCheckedStage ? stage.preCheckedStage.order === stage.order - 1 : false) : true;
+        }
+
         async doCheckStage(stage, force = false) {
             const status = auditConst.stage.status;
             await this.loadStageUser(stage);
+            await this.loadPreCheckedStage(stage);
 
             const accountId = this.ctx.session.sessionUser.accountId, shareIds = [];
             const isTenderTourist = await this.service.tenderTourist.getDataByCondition({ tid: stage.tid, user_id: accountId });
@@ -408,12 +424,17 @@ module.exports = app => {
                     if (sf && s.readOnly) {
                         await this.ctx.service.stage.update({ sf_tp: sf.tp, pre_sf_tp: sf.pre_tp }, { id: s.id });
                     }
-                    s.sf_tp = sf.tp;
+                    s.sf_tp = sf ? sf.tp : 0;
                 }
             }
             return stages;
         }
 
+        async getNextStages(tenderId, order) {
+            const sql = 'SELECT * FROM ?? WHERE tid = ? AND `order` > ?';
+            return await this.db.query(sql, [this.tableName, tenderId, order]);
+        }
+
         async _getSumTp(condition, ...field) {
             const fieldSql = [];
             for (const f of field) {
@@ -434,12 +455,10 @@ module.exports = app => {
         async addStage(tenderId, date, period) {
             const stages = await this.getAllDataByCondition({
                 where: { tid: tenderId },
-                order: ['order'],
+                order: [['order', 'asc']],
             });
             const preStage = stages[stages.length - 1];
-            if (stages.length > 0 && stages[stages.length - 1].status !== auditConst.stage.status.checked) {
-                throw '上一期未审批通过,请等待上一期审批通过后,再新增数据';
-            }
+            const preCheckedStage = stages.find(x => { return x.status === auditConst.stage.status.checked; });
             const order = stages.length + 1;
             const newStage = {
                 sid: this.uuid.v4(),
@@ -460,16 +479,18 @@ module.exports = app => {
                 newStage.im_pre = preStage.im_pre;
                 newStage.im_gather = preStage.im_gather;
                 newStage.im_gather_node = preStage.im_gather_node;
-                newStage.pre_contract_tp = this.ctx.helper.sum([preStage.pre_contract_tp, preStage.contract_tp, preStage.contract_pc_tp]);
-                newStage.pre_qc_tp = this.ctx.helper.sum([preStage.pre_qc_tp, preStage.qc_tp, preStage.qc_pc_tp]);
-                newStage.pre_positive_qc_tp = this.ctx.helper.sum([preStage.pre_positive_qc_tp, preStage.positive_qc_tp, preStage.positive_qc_pc_tp]);
-                newStage.pre_negative_qc_tp = this.ctx.helper.sum([preStage.pre_negative_qc_tp, preStage.negative_qc_tp, preStage.negative_qc_pc_tp]);
-                newStage.pre_yf_tp = this.ctx.helper.add(preStage.pre_yf_tp, preStage.yf_tp);
-                if (preStage.order === 1 || preStage.pre_sf_tp) {
-                    newStage.pre_sf_tp = this.ctx.helper.add(preStage.pre_sf_tp, preStage.sf_tp);
-                } else {
-                    const sumTp = await this._getSumTp({tid: preStage.tid}, 'sf_tp');
-                    newStage.pre_sf_tp = sumTp.sf_tp || 0;
+                if (preCheckedStage) {
+                    newStage.pre_contract_tp = this.ctx.helper.sum([preCheckedStage.pre_contract_tp, preCheckedStage.contract_tp, preCheckedStage.contract_pc_tp]);
+                    newStage.pre_qc_tp = this.ctx.helper.sum([preCheckedStage.pre_qc_tp, preStage.qc_tp, preCheckedStage.qc_pc_tp]);
+                    newStage.pre_positive_qc_tp = this.ctx.helper.sum([preCheckedStage.pre_positive_qc_tp, preCheckedStage.positive_qc_tp, preCheckedStage.positive_qc_pc_tp]);
+                    newStage.pre_negative_qc_tp = this.ctx.helper.sum([preCheckedStage.pre_negative_qc_tp, preCheckedStage.negative_qc_tp, preCheckedStage.negative_qc_pc_tp]);
+                    newStage.pre_yf_tp = this.ctx.helper.add(preCheckedStage.pre_yf_tp, preStage.yf_tp);
+                    if (preCheckedStage.order === 1 || preCheckedStage.pre_sf_tp) {
+                        newStage.pre_sf_tp = this.ctx.helper.add(preCheckedStage.pre_sf_tp, preCheckedStage.sf_tp);
+                    } else {
+                        const sumTp = await this._getSumTp({tid: preCheckedStage.tid}, 'sf_tp');
+                        newStage.pre_sf_tp = sumTp.sf_tp || 0;
+                    }
                 }
             } else {
                 const projFunRela = await this.ctx.service.project.getFunRela(this.ctx.session.sessionProject.id);
@@ -498,16 +519,18 @@ module.exports = app => {
                 }
                 // 新增期其他台账数据
                 let pcTp = { contract_pc_tp: 0, qc_pc_tp: 0, pc_tp: 0, positive_qc_pc_tp: 0, negative_qc_pc_tp: 0 };
-                if (preStage) {
-                    const jgclResult = await this.ctx.service.stageJgcl.addInitialStageData(newStage, preStage, transaction);
+                if (preCheckedStage) {
+                    const jgclResult = await this.ctx.service.stageJgcl.addInitialStageData(newStage, preCheckedStage, transaction);
                     if (!jgclResult) throw '初始化甲供材料数据失败';
-                    const otherResult = await this.ctx.service.stageOther.addInitialStageData(newStage, preStage, transaction);
+                    const otherResult = await this.ctx.service.stageOther.addInitialStageData(newStage, preCheckedStage, transaction);
                     if (!otherResult) throw '初始化其他台账数据失败';
-                    const safeResult = await this.ctx.service.stageSafeProd.addInitialStageData(newStage, preStage, transaction);
+                    const safeResult = await this.ctx.service.stageSafeProd.addInitialStageData(newStage, preCheckedStage, transaction);
                     if (!safeResult) throw '初始化其他台账数据失败';
-                    const tempResult = await this.ctx.service.stageTempLand.addInitialStageData(newStage, preStage, transaction);
+                    const tempResult = await this.ctx.service.stageTempLand.addInitialStageData(newStage, preCheckedStage, transaction);
                     if (!tempResult) throw '初始化其他台账数据失败';
+                }
 
+                if (preStage && preCheckedStage && preStage.order === preCheckedStage.order) {
                     const priceCalc = new RevisePrice(this.ctx);
                     pcTp = await priceCalc.newStagePriceChange(newStage, preStage, transaction);
                 }

+ 21 - 3
app/service/stage_audit.js

@@ -461,7 +461,7 @@ module.exports = app => {
                 });
                 await this.ctx.service.noticeAgain.stopNoticeAgain(transaction, this.tableName, selfAudit.id);
                 // 计算并合同支付最终数据
-                const [yfPay, sfPay] = await this.ctx.service.stagePay.calcAllStagePays(this.ctx.stage, transaction);
+                const [yfPay, sfPay, stagePays] = await this.ctx.service.stagePay.calcAllStagePays(this.ctx.stage, transaction);
                 const stageTp = {
                     contract_tp: tpData.contract_tp,
                     qc_tp: tpData.qc_tp,
@@ -563,6 +563,20 @@ module.exports = app => {
 
                         await this.ctx.service.tenderCache.updateStageCache4Flow(transaction, this.ctx.stage, checkData.checkType, nextAudits, flowAudits, ledgerTp, stageTp);
                         await this.ctx.service.stagePay.cacheOrder(this.ctx.stage, transaction);
+                        // 当前期不是最新一起时
+                        if (this.ctx.stage.highOrder !== this.ctx.stage.order) {
+                            const nextStages = await this.ctx.service.stage.getNextStages(this.ctx.stage.tid, this.ctx.stage.order);
+                            await this.ctx.service.stagePay.refreshNextStagePreTp(transaction, nextStages, stagePays);
+                            const preStageTp = {
+                                pre_contract_tp: this.ctx.helper.sum([this.ctx.stage.pre_contract_tp, stageTp.contract_tp, stageTp.contract_pc_tp]),
+                                pre_qc_tp: this.ctx.helper.sum([this.ctx.stage.pre_qc_tp, stageTp.qc_tp, stageTp.qc_pc_tp]),
+                                pre_positive_qc_tp: this.ctx.helper.sum([this.ctx.stage.pre_positive_qc_tp, stageTp.positive_qc_tp, stageTp.positive_qc_pc_tp]),
+                                pre_negative_qc_tp: this.ctx.helper.sum([this.ctx.stage.pre_negative_qc_tp, stageTp.negative_qc_tp, stageTp.negative_qc_pc_tp]),
+                                pre_yf_tp: this.ctx.helper.add(this.ctx.stage.pre_yf_tp, stageTp.yf_tp),
+                                pre_sf_tp: this.ctx.helper.add(this.ctx.stage.pre_sf_tp, stageTp.sf_tp),
+                            };
+                            await transaction.update(this.ctx.service.stage.tableName, nextStages.map(x => { return { id: x.id, ...preStageTp }; }));
+                        }
 
                         // 添加短信通知-审批通过提醒功能
                         const auditList = await this.getAuditors(stageId, stageInfo.times);
@@ -1679,8 +1693,12 @@ module.exports = app => {
                 };
                 newAuditors.push(na);
             }
-            const result = await transaction.insert(this.tableName, newAuditors);
-            return (result.effectRows = auditors.length);
+            if (newAuditors.length > 0) {
+                const result = await transaction.insert(this.tableName, newAuditors);
+                return (result.effectRows = auditors.length);
+            } else {
+                return true;
+            }
         }
 
         /**

+ 23 - 4
app/service/stage_pay.js

@@ -95,8 +95,8 @@ module.exports = app => {
             }
             const stagePays = [];
             // 获取截止上期数据
-            if (stage.order > 1) {
-                const preStage = await this.ctx.service.stage.getDataByCondition({tid: stage.tid, order: stage.order - 1});
+            if (stage.preCheckedStage) {
+                const preStage = await this.ctx.service.stage.getDataByCondition({tid: stage.tid, order: stage.preCheckedStage.order});
                 if (!preStage) {
                     throw '标段数据有误';
                 }
@@ -263,7 +263,7 @@ module.exports = app => {
             }
             const yf = this._.find(stagePays, {ptype: payConst.payType.yf});
             const sf = this._.find(stagePays, {ptype: payConst.payType.sf});
-            return [yf, sf];
+            return [yf, sf, stagePays];
         }
 
         async getSpecialTotalPrice(stage) {
@@ -283,7 +283,7 @@ module.exports = app => {
             const stagePays = stage.status === auditConst.stage.status.checked
                 ? await this.getStageLastestPays(stage)
                 : await this.getStagePays(stage);
-            const sf = this._.find(stagePays, {ptype: payConst.payType.sf});
+            const sf = this._.find(stagePays, { ptype: payConst.payType.sf });
             return sf;
         }
 
@@ -505,6 +505,25 @@ module.exports = app => {
         async clearCacheOrder(stage, transaction) {
             await transaction.update(this.tableName, { porder: 0 }, { where: { sid: stage.id } });
         }
+
+        async refreshNextStagePreTp(transaction, nextStages, prePays) {
+            const updateData = [];
+            for (const s of nextStages) {
+                const curPays = await this.getStageLastestPays(s);
+                for (const cp of curPays) {
+                    const pp = prePays.find(x => { return x.pid === cp.pid });
+                    if (pp) {
+                        updateData.push({
+                            id: cp.id, pre_tp: pp.end_tp,
+                            pre_used: pp.pre_used || !this.ctx.helper.checkZero(pp.tp),
+                            pre_finish: pp.pre_finish || (pp.rprice ? pp.end_tp === pp.rprice : false),
+                            start_stage_order: pp.start_stage_order,
+                        });
+                    }
+                }
+            }
+            if (updateData.length > 0) await transaction.update(this.tableName, updateData);
+        }
     }
 
     return StagePay;

+ 4 - 0
app/service/tender_cache.js

@@ -227,6 +227,8 @@ module.exports = app => {
         }
 
         async updateStageCache4Start(transaction, stage, status, auditors, ledgerTp, stageTp) {
+            if (!stage.isCheckFirst) return;
+
             const orgCache = await this.getDataById(stage.tid);
             const data = { id: stage.tid, stage_status: status };
             if (ledgerTp) data.ledger_tp = JSON.stringify(ledgerTp);
@@ -248,6 +250,8 @@ module.exports = app => {
         }
 
         async updateStageCache4Flow(transaction, stage, status, auditors, preAuditors, ledgerTp, stageTp, pcTp) {
+            if (!stage.isCheckFirst) return;
+
             const orgCache = await this.getDataById(stage.tid);
             const data = { id: stage.tid, stage_status: status };
             if (ledgerTp) data.ledger_tp = JSON.stringify(ledgerTp);

+ 2 - 2
app/view/file/file.ejs

@@ -12,7 +12,7 @@
     <div class="content-wrap">
         <div class="c-body">
             <div class="sjs-height-0 row">
-                <div class="col-3">
+                <div class="col-3 border-right pr-0">
                     <div class="d-flex flex-row">
                         <div class="btn-group">
                             <button type="button" class="btn btn-sm  text-primary dropdown-toggle" data-toggle="dropdown" id="zhankai" aria-expanded="false">显示层级</button>
@@ -71,4 +71,4 @@
     const filing = JSON.parse(unescape('<%- escape(JSON.stringify(filing)) %>'));
     const category = JSON.parse(unescape('<%- escape(JSON.stringify(categoryData)) %>'));
     const whiteList = JSON.parse('<%- JSON.stringify(ctx.app.config.multipart.whitelist) %>');
-</script>
+</script>

+ 1 - 2
app/view/measure/stage.ejs

@@ -10,8 +10,7 @@
                 <% if (ctx.session.sessionProject.page_show.openSettle) { %>
                 <a href="/tender/<%= ctx.tender.id %>/settle" class="btn btn-primary btn-sm">计量结算</a>
                 <% } %>
-                <% if (ctx.session.sessionUser.accountId === ctx.tender.data.user_id && ctx.tender.data.ledger_status === auditConst.status.checked &&
-                        (stages.length === 0 || stages[0].status === auditConst.status.checked)) { %>
+                <% if (ctx.session.sessionUser.accountId === ctx.tender.data.user_id && ctx.tender.data.ledger_status === auditConst.status.checked) { %>
                     <% if (!ctx.session.sessionProject.page_show.close1stStageCheckDealParam && ctx.helper.checkZero(ctx.tender.info.deal_param.contractPrice) && stages.length === 0) { %>
                         <a href="#add-qi" data-toggle="modal" data-target="#tips" class="btn btn-primary btn-sm">开始新一期</a>
                     <% } else { %>

+ 1 - 2
app/view/measure/stage_modal.ejs

@@ -1,5 +1,4 @@
-<% if (ctx.session.sessionUser.accountId === ctx.tender.data.user_id && ctx.tender.data.ledger_status === auditConst.status.checked &&
-        (stages.length === 0 || stages[stages.length- 1].status === auditConst.status.checked)) { %>
+<% if (ctx.session.sessionUser.accountId === ctx.tender.data.user_id && ctx.tender.data.ledger_status === auditConst.status.checked) { %>
 <!--弹出填写合同参数-->
 <div class="modal fade" id="tips" data-backdrop="static">
     <div class="modal-dialog" role="document">

+ 31 - 19
app/view/setting/show.ejs

@@ -36,25 +36,37 @@
                         </div>
                         <div class-="form-group">
                             <h6>列显示</h6>
-                            <div class="row">
-                                <div class="col-6">
-                                    <label>0号台账模式</label>
-                                    <div class="card">
-                                        <ul class="list-group list-group-flush">
-                                            <li class="list-group-item">0号台账 <a href="/setting/spread?stype=tz_ledger_set" class="btn btn-primary btn-sm pull-right">配置</a></li>
-                                            <li class="list-group-item">计量台账 <a href="/setting/spread?stype=tz_stage_set" class="btn btn-primary btn-sm pull-right">配置</a></li>
-                                        </ul>
-                                    </div>
-                                </div>
-                                <div class="col-6">
-                                    <label>工程量清单模式</label>
-                                    <div class="card">
-                                        <ul class="list-group list-group-flush">
-                                            <li class="list-group-item">0号台账 <a href="/setting/spread?stype=gcl_ledger_set" class="btn btn-primary btn-sm pull-right">配置</a></li>
-                                            <li class="list-group-item">计量台账 <a href="/setting/spread?stype=gcl_stage_set" class="btn btn-primary btn-sm pull-right">配置</a></li>
-                                        </ul>
-                                    </div>
-                                </div>
+                            <div class="card">
+                                <ul class="list-group list-group-flush">
+                                    <% for (const ps of projectSpread) { %>
+                                    <li class="list-group-item">
+                                        <div>
+                                            <%- ps.name %>
+                                            <% if(ps.is_default) { %><span class="pull-right text-warning">默认</span><% } %>
+                                        </div>
+                                        <div class="row mt-1">
+                                            <div class="col-6">
+                                                <label>0号台账模式</label>
+                                                <div class="card">
+                                                    <ul class="list-group list-group-flush">
+                                                        <li class="list-group-item">0号台账 <a href="/setting/spread?stype=tz_ledger_set&code=<%- ps.code %>" class="btn btn-primary btn-sm pull-right">配置</a></li>
+                                                        <li class="list-group-item">计量台账 <a href="/setting/spread?stype=tz_stage_set&code=<%- ps.code %>" class="btn btn-primary btn-sm pull-right">配置</a></li>
+                                                    </ul>
+                                                </div>
+                                            </div>
+                                            <div class="col-6">
+                                                <label>工程量清单模式</label>
+                                                <div class="card">
+                                                    <ul class="list-group list-group-flush">
+                                                        <li class="list-group-item">0号台账 <a href="/setting/spread?stype=gcl_ledger_set&code=<%- ps.code %>" class="btn btn-primary btn-sm pull-right">配置</a></li>
+                                                        <li class="list-group-item">计量台账 <a href="/setting/spread?stype=gcl_stage_set&code=<%- ps.code %>" class="btn btn-primary btn-sm pull-right">配置</a></li>
+                                                    </ul>
+                                                </div>
+                                            </div>
+                                        </div>
+                                    </li>
+                                    <% } %>
+                                </ul>
                             </div>
                         </div>
                         <!--<div class="form-group">-->

+ 1 - 0
app/view/setting/spread.ejs

@@ -26,5 +26,6 @@
 <script>
     const BaseSetCol = JSON.parse('<%- JSON.stringify(BaseSetCol) %>');
     const sType = '<%- sType %>';
+    const sCode = '<%- code %>';
     const colSet = JSON.parse('<%- JSON.stringify(colSet) %>');
 </script>

+ 4 - 3
app/view/setting/user.ejs

@@ -4,11 +4,12 @@
         <div class="title-main">
             <h2>账号管理
                 <% if (projectData.max_user === 0 || projectData.max_user > user_total) { %>
-                    <a href="#ver" data-toggle="modal" data-target="#add-user" class="btn btn-primary btn-sm pull-right">添加账号</a>
+                    <a href="#ver" data-toggle="modal" data-target="#add-user" class="btn btn-primary btn-sm pull-right mr-2">添加账号</a>
+                    <a href="#add-batch" data-toggle="modal" data-target="#add-batch" class="btn btn-primary btn-sm pull-right mr-1">批量导入账号</a>
                 <% } else { %>
-                    <a href="#add-unpass" data-toggle="modal" data-target="#add-unpass" class="btn btn-primary btn-sm pull-right">添加账号(受限)</a>
+                    <a href="#add-unpass" data-toggle="modal" data-target="#add-unpass" class="btn btn-primary btn-sm pull-right mr-2">添加账号(受限)</a>
+                    <a href="#add-unpass" data-toggle="modal" data-target="#add-unpass" class="btn btn-primary btn-sm pull-right mr-1">批量导入账号(受限)</a>
                 <% } %>
-                <a href="#add-batch" data-toggle="modal" data-target="#add-batch" class="btn btn-primary btn-sm pull-right mr-1">批量导入账号</a>
             </h2>
         </div>
     </div>

+ 1 - 1
app/view/setting/user_add_modal.ejs

@@ -43,7 +43,7 @@
                     <select class="form-control form-control-sm" name="company" id="add_user_company">
                         <option>请选择</option>
                         <% for (const u of unitList) { %>
-                            <option><%- u.name %></option>
+                            <option <% if (company && company === u.name) { %>selected<% } %>><%- u.name %></option>
                         <% } %>
                     </select>
                 </div>

+ 4 - 3
app/view/setting/user_permission.ejs

@@ -5,11 +5,12 @@
         <div class="title-main">
             <h2>账号管理
                 <% if (projectData.max_user === 0 || projectData.max_user > user_total) { %>
-                    <a href="#ver" data-toggle="modal" data-target="#add-user" class="btn btn-primary btn-sm pull-right">添加账号</a>
+                    <a href="#ver" data-toggle="modal" data-target="#add-user" class="btn btn-primary btn-sm pull-right mr-2">添加账号</a>
+                    <a href="#add-batch" data-toggle="modal" data-target="#add-batch" class="btn btn-primary btn-sm pull-right mr-1">批量导入账号</a>
                 <% } else { %>
-                    <a href="#add-unpass" data-toggle="modal" data-target="#add-unpass" class="btn btn-primary btn-sm pull-right">添加账号(受限)</a>
+                    <a href="#add-unpass" data-toggle="modal" data-target="#add-unpass" class="btn btn-primary btn-sm pull-right mr-2">添加账号(受限)</a>
+                    <a href="#add-unpass" data-toggle="modal" data-target="#add-unpass" class="btn btn-primary btn-sm pull-right mr-1">批量导入账号(受限)</a>
                 <% } %>
-                <a href="#add-batch" data-toggle="modal" data-target="#add-batch" class="btn btn-primary btn-sm pull-right mr-1">批量导入账号</a>
             </h2>
         </div>
     </div>

+ 5 - 4
app/view/setting/user_unit.ejs

@@ -5,11 +5,12 @@
             <h2>账号管理
                 <a href="#add-company" data-toggle="modal" data-target="#add-company" class="btn btn-primary btn-sm pull-right">添加单位</a>
                 <% if (projectData.max_user === 0 || projectData.max_user > user_total) { %>
-                <a href="#ver" data-toggle="modal" data-target="#add-user" class="btn btn-primary btn-sm pull-right mr-2">添加账号</a>
+                    <a href="#ver" data-toggle="modal" data-target="#add-user" class="btn btn-primary btn-sm pull-right mr-2">添加账号</a>
+                    <a href="#add-batch" data-toggle="modal" data-target="#add-batch" class="btn btn-primary btn-sm pull-right mr-1">批量导入账号</a>
                 <% } else { %>
-                <a href="#add-unpass" data-toggle="modal" data-target="#add-unpass" class="btn btn-primary btn-sm pull-right mr-2">添加账号(受限)</a>
+                    <a href="#add-unpass" data-toggle="modal" data-target="#add-unpass" class="btn btn-primary btn-sm pull-right mr-2">添加账号(受限)</a>
+                    <a href="#add-unpass" data-toggle="modal" data-target="#add-unpass" class="btn btn-primary btn-sm pull-right mr-1">批量导入账号(受限)</a>
                 <% } %>
-                <a href="#add-batch" data-toggle="modal" data-target="#add-batch" class="btn btn-primary btn-sm pull-right mr-1">批量导入账号</a>
             </h2>
         </div>
     </div>
@@ -22,7 +23,7 @@
                     <a class="nav-item nav-link active" href="/setting/user/unit">参建单位</a>
                 </nav>
                 <div class="tab-content m-3">
-                    <div id="unit-list" class="tab-pane active">
+                    <div class="tab-pane active">
                         <div class="row">
                             <div class="col-6">
                                 <table class="table table-hover table-bordered table-sm">

+ 5 - 0
app/view/stage/audit_btn.ejs

@@ -1,15 +1,20 @@
 <div class="contarl-box">
     <% if (ctx.stage.status === auditConst.status.uncheck) { %>
     <% if (ctx.session.sessionUser.accountId === ctx.stage.user_id) { %>
+
+    <% if (ctx.stage.order > 1 && ctx.stage.preCheckedStage && ctx.stage.preCheckedStage.order === ctx.stage.order - 1) { %>
     <% if (!ctx.session.sessionProject.page_show.openStageStart || (ctx.session.sessionProject.page_show.openStageStart && ctx.stage.startPermission)) { %>
     <a id="sub-sp-btn" href="javascript: void(0);" data-toggle="modal" data-target="#sub-sp" class="btn btn-primary btn-sm btn-block">上报审批</a>
     <% } else { %>
     <a href="javascript:void(0);" data-toggle="tooltip" data-placement="right" class="btn btn-secondary btn-sm btn-block" data-original-title="不在上报时间范围内">上报审批</a>
     <% } %>
+    <% } %>
+
     <% if (ctx.session.sessionProject.page_show.openStageStart && ctx.stage.startPermission) { %><p class="text-warning text-center">截止:<%- ctx.stage.startEndDay %></p><% } %>
     <% } else { %>
     <a id="sub-sp-btn" href="javascript: void(0);" data-toggle="modal" data-target="#sub-sp" class="btn btn-outline-secondary btn-sm btn-block">上报中</a>
     <% } %>
+
     <% } else if (ctx.stage.status === auditConst.status.checking) { %>
         <% if (ctx.stage.curAuditorIds.indexOf(ctx.session.sessionUser.accountId) >= 0) { %>
             <a id="sp-done-btn" href="javascript: void(0);" data-toggle="modal" data-target="#sp-done" class="btn btn-success btn-sm btn-block">审批通过</a>

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

@@ -58,7 +58,7 @@
 <script>
     const tender = JSON.parse(unescape('<%- escape(JSON.stringify(tender)) %>'));
     const stage = JSON.parse(unescape('<%- escape(JSON.stringify(ctx.stage)) %>'));
-    const readOnly = <%- stage.readOnly || stage.revising %>;
+    const readOnly = <%- stage.readOnly || stage.revising || (stage.order > 1 && (!stage.preCheckedStage || stage.preCheckedStage.order < stage.order - 1)) %>;
     const dealPay = JSON.parse(unescape('<%- escape(JSON.stringify(dealPay)) %>'));
     const calcBase = JSON.parse('<%- JSON.stringify(calcBase) %>');
     const decimal = JSON.parse('<%- JSON.stringify(ctx.tender.info.decimal) %>');

+ 1 - 0
app/view/tender/detail.ejs

@@ -71,6 +71,7 @@
                             <a href="#bd-set-10" data-toggle="modal" data-target="#bd-set-10" class="dropdown-item">上报控制</a>
                             <a href="#bd-set-12" data-toggle="modal" data-target="#bd-set-12" class="dropdown-item">功能设置</a>
                             <a href="#bd-set-11" data-toggle="modal" data-target="#bd-set-11" class="dropdown-item">概况设置</a>
+                            <a href="#bd-set-13" data-toggle="modal" data-target="#bd-set-13" class="dropdown-item">标段类型</a>
                         </div>
                     </div>
                 <% } %>

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

@@ -824,10 +824,6 @@
                         <label class="custom-control-label" for="ledger-cl-qty">错漏增减</label>
                     </div>
                     <div class="custom-control custom-checkbox mb-2">
-                        <input type="checkbox" class="custom-control-input" id="ex-memo" checked="">
-                        <label class="custom-control-label" for="ex-memo">台账新增列</label>
-                    </div>
-                    <div class="custom-control custom-checkbox mb-2">
                         <input type="checkbox" class="custom-control-input" id="thousandth" checked="">
                         <label class="custom-control-label" for="thousandth">千分位</label>
                     </div>
@@ -1653,7 +1649,6 @@
         $('#ledger-deal')[0].checked = property.display.ledger.deal;
         $('#ledger-dgn-qty')[0].checked = property.display.ledger.dgnQty;
         $('#ledger-cl-qty')[0].checked = property.display.ledger.clQty;
-        $('#ex-memo')[0].checked = property.display.exMemo;
         $('#thousandth')[0].checked = property.display.thousandth;
         $('#stage-rc')[0].checked = property.display.stage.realComplete;
         $('#stage-priceDiff')[0].checked = property.display.stage.priceDiff;
@@ -1667,7 +1662,6 @@
         const prop = {
             display: {
                 ledger: { deal: $('#ledger-deal')[0].checked, dgnQty: $('#ledger-dgn-qty')[0].checked, clQty: $('#ledger-cl-qty')[0].checked, },
-                exMemo: $('#ex-memo')[0].checked,
                 thousandth: $('#thousandth')[0].checked,
                 stage: { realComplete: $('#stage-rc')[0].checked, correct: $('#stage-correct')[0].checked, priceDiff: $('#stage-priceDiff')[0].checked },
                 dayMode: $('#dayMode')[0].checked,
@@ -1863,6 +1857,37 @@
     }
 </script>
 <% if (ctx.session.sessionUser.is_admin) { %>
+<!--标段类型-->
+<div class="modal fade" id="bd-set-13" 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">
+                <div class="row">
+                    <div class="col-6 mb-2">
+                        <div class="input-group input-group-sm">
+                            <div class="input-group-prepend">
+                                <span class="input-group-text" style="width:90px">标段类型</span>
+                            </div>
+                            <select class="form-control" id="tender-s-type">
+                                <option value="">请选择</option>
+                                <% for (const ps of projectSpread) { %>
+                                <option value="<%- ps.code %>"><%- ps.name %></option>
+                                <% } %>
+                            </select>
+                        </div>
+                    </div>
+                </div>
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-sm btn-secondary" data-dismiss="modal">关闭</button>
+                <button type="button" class="btn btn-sm btn-primary" onclick="post13();">确认修改</button>
+            </div>
+        </div>
+    </div>
+</div>
 <!--游客账号-->
 <div class="modal fade" id="bd-set-9" data-backdrop="static">
     <div class="modal-dialog" role="document">
@@ -2069,6 +2094,24 @@
             $('#bd-set-12').modal('hide');
         });
     }
+
+    const loadSTypeProperty = function () {
+        $('#tender-s-type').val(property.s_type);
+    };
+
+    $('#bd-set-13').on('show.bs.modal', function () {
+        loadSTypeProperty();
+    });
+    function post13() {
+        const prop = {
+            s_type: $('#tender-s-type').val(),
+        }
+        const tenderId = window.location.pathname.split('/')[2];
+        postData('/tender/' + tenderId + '/save2', prop, function (data) {
+            property.s_type = data.s_type;
+            $('#bd-set-13').modal('hide');
+        });
+    }
     $(function () {
         // 投资进度
         let timer2 = null;

+ 60 - 1
app/view/tender/modal.ejs

@@ -72,6 +72,56 @@
         </div>
     </div>
 </div>
+<!--弹出列设置-->
+<div class="modal fade" id="col-set" 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">
+                <table class="table table-hover table-bordered">
+                    <thead><tr><th width="150px">列名</th><th width="150px">别名</th><th width="50px">显示</th></tr></thead>
+                    <tbody class="text-center">
+                    <% for (const cs of colSet) { %>
+                    <tr code="<%- cs.field %>">
+                        <td><%- cs.name %><% if (cs.hint) { %><i class="fa fa-question-circle text-primary ml-1" data-placement="bottom" data-toggle="tooltip" data-original-title="<%- cs.hint %>"></i><% } %></td>
+                        <% if (cs.fixed.indexOf('alias') >= 0) { %>
+                        <td class="disabled">-</td>
+                        <% } else {%>
+                        <td><input type="text" class="form-control form-control-sm" value="<%- cs.alias %>"></td>
+                        <% } %>
+                        <% if (cs.fixed.indexOf('show') >= 0 ) { %>
+                        <td>
+                            <div class="form-check form-check-inline">
+                                <input class="form-check-input" type="checkbox" id="inlineCheckbox-<%- cs.code %>" checked="" disabled="">
+                                <label class="form-check-label" for="inlineCheckbox-<%- cs.code %>"></label>
+                            </div>
+                        </td>
+                        <% } else { %>
+                        <td>
+                            <div class="form-check form-check-inline">
+                                <input class="form-check-input" type="checkbox" id="inlineCheckbox-<%- cs.code %>" <% if (cs.show) { %> checked <% } %> >
+                                <label class="form-check-label" for="inlineCheckbox-<%- cs.code %>"></label>
+                            </div>
+                        </td>
+                        <% } %>
+                    </tr>
+                    <% } %>
+                    </tbody>
+                </table>
+                <div class="text-danger">请勿全选(页面显示不下);谨慎修改别名(修改后,各页面概念将不一致)</div>
+            </div>
+            <form class="modal-footer" action="/list/info/col-set" method="post" onsubmit="return onSetCol();">
+                <input type="hidden" name="_csrf_j" value="<%= ctx.csrf %>">
+                <input type="hidden" name="col_set" value="">
+                <input type="hidden" name="col_type" value="info">
+                <button type="button" class="btn btn-secondary btn-sm" data-dismiss="modal">关闭</button>
+                <button type="submit" class="btn btn-primary btn-sm" id="add-bd-ok">确定修改</button>
+            </form>
+        </div>
+    </div>
+</div>
 <!--弹出计量模式选择-->
 <div class="modal fade" id="jlms" data-backdrop="static">
     <div class="modal-dialog modal-lg" role="document">
@@ -118,6 +168,15 @@
 </div>
 <script>
     const auditType = JSON.parse('<%- JSON.stringify(auditConst.auditType) %>');
+    const colSet = JSON.parse('<%- JSON.stringify(colSet) %>');
+    const onSetCol = function() {
+        const trs = $('tr[code]', '#col-set');
+        const colSet = [];
+        for (const tr of trs) {
+            colSet.push({ field: $(tr).attr('code'), show: $('input[type=checkbox]', tr)[0].checked, alias: $('input[type=text]', tr).val() || ''});
+        }
+        $('input[name=col_set]').val(JSON.stringify(colSet));
+    };
     $(document).ready(function () {
         const getAuditTypeText = function (type) {
             if (type === auditType.key.common) return '';
@@ -425,5 +484,5 @@
             }
             return `${year}<span class="${dayMode ? 'text-light' : ''}">${mon}-${day}</span><span class="${dayMode ? 'text-light' : ''}">${hour}:${minute}:${scond}</span>`;
         };
-    })
+    });
 </script>

+ 6 - 3
app/view/tender/sub_menu.ejs

@@ -36,11 +36,14 @@
                 <!--</div>-->
             <!--</div>-->
         </div>
-        <% if (ctx.app.config.is_debug) { %>
         <div>
-            <a href="/compare/tz" class="btn btn-sm btn-primary pull-right" target="_blank">统计分析</a>
+            <% if (ctx.app.config.is_debug) { %>
+            <a href="/compare/tz" class="btn btn-sm btn-primary" target="_blank">统计分析</a>
+            <% } %>
+            <% if (ctx.session.sessionUser.is_admin && ctx.url === '/list/info') { %>
+            <a href="#col-set" class="btn btn-sm btn-primary ml-1" data-toggle="modal" data-target="#col-set">列设置</a>
+            <% } %>
         </div>
-        <% } %>
         <div>
             <a href="/list/info/finish" class="btn btn-sm btn-primary pull-right ml-1" target="_blank">完工标段</a>
             <% if (userPermission !== null && userPermission.tender !== undefined && userPermission.tender.indexOf('1') !== -1) { %>

+ 39 - 33
db_script/project_spread.js

@@ -63,42 +63,49 @@ const InsertSql = function (tableName, data) {
 };
 
 const initProjectSpread = async function (project) {
-    const DefaultSet = JSON.parse(JSON.stringify(SpreadConst.ProjectSpreadTemplate));
-    const sjsRela = project.sjs_rela ? JSON.parse(project.sjs_rela) : null;
-    if (sjsRela) {
-        for (const prop in DefaultSet) {
-            const template = DefaultSet[prop];
-            for (const lc of sjsRela.ledgerCol) {
-                const col = template.find(x => { return x.key === lc.field; });
-                if (lc.show) col.valid = 1;
-                if (lc.alias) col.alias = lc.alias;
-                if (lc.pos === 'name') {
-                    const lColIndex = template.findIndex(x => { return x.key === lc.field; });
-                    const lCol = template[lColIndex];
-                    const preColIndex = template.findIndex(x => { return x.key === lc.pos; });
-                    const preCol = template[preColIndex];
-                    if (preCol && preColIndex !== lColIndex - 1) {
-                        template.splice(lColIndex, 1);
-                        template.splice(preColIndex + 1, 0, lCol);
-                    }
-                }
-            }
-        }
-    }
-    [DefaultSet.tz_ledger_bills_spread, DefaultSet.tz_ledger_pos_spread] = generateRelaSpread('tz_ledger_set', DefaultSet.tz_ledger_set);
-    [DefaultSet.tz_stage_bills_spread, DefaultSet.tz_stage_pos_spread] = generateRelaSpread('tz_stage_set', DefaultSet.tz_stage_set);
-    [DefaultSet.gcl_ledger_bills_spread, DefaultSet.gcl_ledger_pos_spread] = generateRelaSpread('gcl_ledger_set', DefaultSet.gcl_ledger_set);
-    [DefaultSet.gcl_stage_bills_spread, DefaultSet.gcl_stage_pos_spread] = generateRelaSpread('gcl_stage_set', DefaultSet.gcl_stage_set);
-    for (const prop in DefaultSet) {
-        DefaultSet[prop] = JSON.stringify(DefaultSet[prop]);
-    }
-    DefaultSet.id = project.id;
     const exist = await querySql('Select * From zh_project_spread WHERE id = ?', [project.id]);
     if (exist.length > 0) {
         await querySql('DELETE FROM zh_project_spread WHERE id = ?', [project.id]);
     }
-    const [sql, sqlParams] = InsertSql('zh_project_spread', DefaultSet);
-    await querySql(sql, sqlParams);
+
+    for (const SpreadTemplate of SpreadConst.ProjectSpreadTemplate) {
+        const DefaultSet = JSON.parse(JSON.stringify(SpreadTemplate.template));
+
+        const sjsRela = project.sjs_rela ? JSON.parse(project.sjs_rela) : null;
+        if (sjsRela) {
+            for (const prop in DefaultSet) {
+                const template = DefaultSet[prop];
+                for (const lc of sjsRela.ledgerCol) {
+                    const col = template.find(x => { return x.key === lc.field; });
+                    if (lc.show) col.valid = 1;
+                    if (lc.alias) col.alias = lc.alias;
+                    if (lc.pos === 'name') {
+                        const lColIndex = template.findIndex(x => { return x.key === lc.field; });
+                        const lCol = template[lColIndex];
+                        const preColIndex = template.findIndex(x => { return x.key === lc.pos; });
+                        const preCol = template[preColIndex];
+                        if (preCol && preColIndex !== lColIndex - 1) {
+                            template.splice(lColIndex, 1);
+                            template.splice(preColIndex + 1, 0, lCol);
+                        }
+                    }
+                }
+            }
+        }
+        [DefaultSet.tz_ledger_bills_spread, DefaultSet.tz_ledger_pos_spread] = generateRelaSpread('tz_ledger_set', DefaultSet.tz_ledger_set);
+        [DefaultSet.tz_stage_bills_spread, DefaultSet.tz_stage_pos_spread] = generateRelaSpread('tz_stage_set', DefaultSet.tz_stage_set);
+        [DefaultSet.gcl_ledger_bills_spread, DefaultSet.gcl_ledger_pos_spread] = generateRelaSpread('gcl_ledger_set', DefaultSet.gcl_ledger_set);
+        [DefaultSet.gcl_stage_bills_spread, DefaultSet.gcl_stage_pos_spread] = generateRelaSpread('gcl_stage_set', DefaultSet.gcl_stage_set);
+        for (const prop in DefaultSet) {
+            DefaultSet[prop] = JSON.stringify(DefaultSet[prop]);
+        }
+        DefaultSet.pid = project.id;
+        DefaultSet.code = SpreadTemplate.code;
+        DefaultSet.name = SpreadTemplate.name;
+        DefaultSet.is_default = SpreadTemplate.isDefault || 0;
+        const [sql, sqlParams] = InsertSql('zh_project_spread', DefaultSet);
+        await querySql(sql, sqlParams);
+    };
 };
 
 const doComplete = async function(projectCode) {
@@ -115,5 +122,4 @@ const doComplete = async function(projectCode) {
     BaseUtil.closePool();
 };
 
-
 doComplete(process.argv[3]);

+ 2 - 74
sql/update.sql

@@ -1,74 +1,2 @@
-ALTER TABLE `zh_tender`
-ADD COLUMN `settle_order` tinyint(4) NULL DEFAULT 0 COMMENT '结算期数(用于结算变更数据更新判断)' AFTER `material_col_show`;
-
-CREATE TABLE `zh_change_settle_list`  (
-  `id` int NOT NULL AUTO_INCREMENT,
-  `tid` int NULL COMMENT '标段id',
-  `cid` varchar(50) NULL COMMENT '变更id',
-  `gcl_id` varchar(255) NULL DEFAULT NULL COMMENT '项目节id',
-  `mx_id` varchar(255) NULL DEFAULT NULL COMMENT '计量单元id',
-  `amount` decimal(30, 8) NULL DEFAULT NULL COMMENT '终审数量',
-  PRIMARY KEY (`id`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT = '变更已结算清单表(用于修订和重审时生成,防止已结算变更清单被删除)';
-
-CREATE TABLE `zh_notice_again`  (
-  `id` int NOT NULL AUTO_INCREMENT,
-  `pid` int NOT NULL COMMENT '项目id',
-  `tid` int NOT NULL COMMENT '标段id',
-  `uid` int NOT NULL COMMENT '用户id',
-  `sp_type` varchar(30) NOT NULL COMMENT '审批类型',
-  `sp_id` int NOT NULL COMMENT '审批类型对应审核表的id',
-  `status` tinyint(2) NOT NULL DEFAULT 1 COMMENT '0为待执行,1为执行中,2为已审',
-  `table_name` varchar(255) NOT NULL COMMENT '对应的审批表名称',
-  `origin_url` json NOT NULL COMMENT 'url信息',
-  `sms_type` varchar(10) NOT NULL COMMENT '模版通知类型',
-  `template` tinyint(2) NOT NULL COMMENT '对应的微信通知模板id',
-  `wx_data` json NOT NULL COMMENT '微信通知的json',
-  `times` tinyint(3) NOT NULL DEFAULT 0 COMMENT '重复发送次数',
-  `in_time` datetime NULL COMMENT '添加时间',
-  `last_time` datetime NULL DEFAULT NULL COMMENT '上一次发送时间',
-  PRIMARY KEY (`id`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT = '审批信息重新发送表';
-
-ALTER TABLE `zh_project_account`
-ADD COLUMN `notice_again` json NULL DEFAULT NULL COMMENT '审批信息重新发送设置';
-
-ALTER TABLE `zh_project`
-ADD COLUMN `notice_setting` json NULL DEFAULT NULL COMMENT '重新发送通知设置';
-
-ALTER TABLE `zh_rpt_archive`
-ADD COLUMN `business_id` VARCHAR(45) NULL COMMENT '有其他业务情况,统一在这里标识(类uuid),要结合stage_id来看,如stage_id > 0,则是标段和期,< 0则是其他业务,如 -300 -> 变更令;-301 - 变更方案;-302 - 变更立项 -303 - 变更申请' AFTER `stage_id`,
-ADD COLUMN `tender_id` INT(11) NULL AFTER `business_id`,
-ADD INDEX `PRJ_STG_BZ` (`prj_id` ASC, `stage_id` ASC, `business_id` ASC);
-;
-
-ALTER TABLE `zh_rpt_archive_encryption`
-ADD COLUMN `business_id` VARCHAR(45) NULL COMMENT '有其他业务情况,统一在这里标识(类uuid),要结合stage_id来看,如stage_id > 0,则是标段和期,< 0则是其他业务,如 -300 -> 变更令;-301 - 变更方案;-302 - 变更立项 -303 - 变更申请' AFTER `stage_id`,
-ADD COLUMN `tender_id` INT(11) NULL AFTER `business_id`,
-ADD INDEX `PRJ_STG_BZ` (`prj_id` ASC, `stage_id` ASC, `business_id` ASC);
-;
-
-ALTER TABLE `zh_rpt_archive_encryption`
-ADD COLUMN `business_type` varchar(30) NOT NULL DEFAULT 'stage' COMMENT 'stage: 期;budget: 动态决算,payment_safe: 支付审批-安全生产费,change: 变更令,change_plan: 变更方案,change_project: 变更立项,change_apply: 变更申请' AFTER `stage_id`;
-
-ALTER TABLE `zh_rpt_archive`
-ADD COLUMN `business_type` varchar(30) NOT NULL DEFAULT 'stage' COMMENT 'stage: 期;budget: 动态决算,payment_safe: 支付审批-安全生产费,change: 变更令,change_plan: 变更方案,change_project: 变更立项,change_apply: 变更申请' AFTER `stage_id`;
-
-ALTER TABLE `zh_role_rpt_rel`
-ADD COLUMN `business_type` varchar(30) NOT NULL DEFAULT 'stage' COMMENT 'stage: 期;budget: 动态决算,payment_safe: 支付审批-安全生产费,change: 变更令,change_plan: 变更方案,change_project: 变更立项,change_apply: 变更申请' AFTER `sid`;
-
-ALTER TABLE `zh_role_rpt_rel`
-ADD COLUMN `business_id` VARCHAR(45) NULL AFTER `sid`,
-ADD INDEX `bz_idx` (`tender_id` ASC, `business_id` ASC);
-;
-
-update zh_rpt_archive A
-set A.tender_id = (select tid from zh_stage B where B.id = A.stage_id)
-where (A.stage_id is not null) && (A.stage_id > 0)
-;
-
-update zh_rpt_archive_encryption A
-set A.tender_id = (select tid from zh_stage B where B.id = A.stage_id)
-where (A.stage_id is not null) && (A.stage_id > 0)
-;
-
+ALTER TABLE `calculation`.`zh_tender_info`
+ADD COLUMN `s_type` varchar(20) NOT NULL DEFAULT '' COMMENT '标段类型(公路gl,房建fj,市政sz)' AFTER `dagl_info`;

+ 74 - 0
sql/update20240313.sql

@@ -0,0 +1,74 @@
+ALTER TABLE `zh_tender`
+ADD COLUMN `settle_order` tinyint(4) NULL DEFAULT 0 COMMENT '结算期数(用于结算变更数据更新判断)' AFTER `material_col_show`;
+
+CREATE TABLE `zh_change_settle_list`  (
+  `id` int NOT NULL AUTO_INCREMENT,
+  `tid` int NULL COMMENT '标段id',
+  `cid` varchar(50) NULL COMMENT '变更id',
+  `gcl_id` varchar(255) NULL DEFAULT NULL COMMENT '项目节id',
+  `mx_id` varchar(255) NULL DEFAULT NULL COMMENT '计量单元id',
+  `amount` decimal(30, 8) NULL DEFAULT NULL COMMENT '终审数量',
+  PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT = '变更已结算清单表(用于修订和重审时生成,防止已结算变更清单被删除)';
+
+CREATE TABLE `zh_notice_again`  (
+  `id` int NOT NULL AUTO_INCREMENT,
+  `pid` int NOT NULL COMMENT '项目id',
+  `tid` int NOT NULL COMMENT '标段id',
+  `uid` int NOT NULL COMMENT '用户id',
+  `sp_type` varchar(30) NOT NULL COMMENT '审批类型',
+  `sp_id` int NOT NULL COMMENT '审批类型对应审核表的id',
+  `status` tinyint(2) NOT NULL DEFAULT 1 COMMENT '0为待执行,1为执行中,2为已审',
+  `table_name` varchar(255) NOT NULL COMMENT '对应的审批表名称',
+  `origin_url` json NOT NULL COMMENT 'url信息',
+  `sms_type` varchar(10) NOT NULL COMMENT '模版通知类型',
+  `template` tinyint(2) NOT NULL COMMENT '对应的微信通知模板id',
+  `wx_data` json NOT NULL COMMENT '微信通知的json',
+  `times` tinyint(3) NOT NULL DEFAULT 0 COMMENT '重复发送次数',
+  `in_time` datetime NULL COMMENT '添加时间',
+  `last_time` datetime NULL DEFAULT NULL COMMENT '上一次发送时间',
+  PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT = '审批信息重新发送表';
+
+ALTER TABLE `zh_project_account`
+ADD COLUMN `notice_again` json NULL DEFAULT NULL COMMENT '审批信息重新发送设置';
+
+ALTER TABLE `zh_project`
+ADD COLUMN `notice_setting` json NULL DEFAULT NULL COMMENT '重新发送通知设置';
+
+ALTER TABLE `zh_rpt_archive`
+ADD COLUMN `business_id` VARCHAR(45) NULL COMMENT '有其他业务情况,统一在这里标识(类uuid),要结合stage_id来看,如stage_id > 0,则是标段和期,< 0则是其他业务,如 -300 -> 变更令;-301 - 变更方案;-302 - 变更立项 -303 - 变更申请' AFTER `stage_id`,
+ADD COLUMN `tender_id` INT(11) NULL AFTER `business_id`,
+ADD INDEX `PRJ_STG_BZ` (`prj_id` ASC, `stage_id` ASC, `business_id` ASC);
+;
+
+ALTER TABLE `zh_rpt_archive_encryption`
+ADD COLUMN `business_id` VARCHAR(45) NULL COMMENT '有其他业务情况,统一在这里标识(类uuid),要结合stage_id来看,如stage_id > 0,则是标段和期,< 0则是其他业务,如 -300 -> 变更令;-301 - 变更方案;-302 - 变更立项 -303 - 变更申请' AFTER `stage_id`,
+ADD COLUMN `tender_id` INT(11) NULL AFTER `business_id`,
+ADD INDEX `PRJ_STG_BZ` (`prj_id` ASC, `stage_id` ASC, `business_id` ASC);
+;
+
+ALTER TABLE `zh_rpt_archive_encryption`
+ADD COLUMN `business_type` varchar(30) NOT NULL DEFAULT 'stage' COMMENT 'stage: 期;budget: 动态决算,payment_safe: 支付审批-安全生产费,change: 变更令,change_plan: 变更方案,change_project: 变更立项,change_apply: 变更申请' AFTER `stage_id`;
+
+ALTER TABLE `zh_rpt_archive`
+ADD COLUMN `business_type` varchar(30) NOT NULL DEFAULT 'stage' COMMENT 'stage: 期;budget: 动态决算,payment_safe: 支付审批-安全生产费,change: 变更令,change_plan: 变更方案,change_project: 变更立项,change_apply: 变更申请' AFTER `stage_id`;
+
+ALTER TABLE `zh_role_rpt_rel`
+ADD COLUMN `business_type` varchar(30) NOT NULL DEFAULT 'stage' COMMENT 'stage: 期;budget: 动态决算,payment_safe: 支付审批-安全生产费,change: 变更令,change_plan: 变更方案,change_project: 变更立项,change_apply: 变更申请' AFTER `sid`;
+
+ALTER TABLE `zh_role_rpt_rel`
+ADD COLUMN `business_id` VARCHAR(45) NULL AFTER `sid`,
+ADD INDEX `bz_idx` (`tender_id` ASC, `business_id` ASC);
+;
+
+update zh_rpt_archive A
+set A.tender_id = (select tid from zh_stage B where B.id = A.stage_id)
+where (A.stage_id is not null) && (A.stage_id > 0)
+;
+
+update zh_rpt_archive_encryption A
+set A.tender_id = (select tid from zh_stage B where B.id = A.stage_id)
+where (A.stage_id is not null) && (A.stage_id > 0)
+;
+