Przeglądaj źródła

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

Tony Kang 1 rok temu
rodzic
commit
1e13f3f40b
49 zmienionych plików z 801 dodań i 163 usunięć
  1. 4 2
      app/const/source_type.js
  2. 16 3
      app/const/spec_3f.js
  3. 51 43
      app/const/tender_info.js
  4. 8 2
      app/controller/file_controller.js
  5. 2 0
      app/controller/revise_controller.js
  6. 4 3
      app/controller/settle_controller.js
  7. 1 1
      app/controller/stage_controller.js
  8. 3 3
      app/lib/ledger.js
  9. 1 1
      app/lib/revise_price.js
  10. 96 0
      app/lib/rm/change.js
  11. 80 0
      app/lib/rm/change_apply.js
  12. 92 0
      app/lib/rm/change_plan.js
  13. 61 0
      app/lib/rm/change_project.js
  14. 3 3
      app/lib/settle.js
  15. 11 0
      app/lib/sum_load.js
  16. 1 1
      app/middleware/change_check.js
  17. 38 5
      app/public/js/file_detail.js
  18. 1 0
      app/public/js/global.js
  19. 2 2
      app/public/js/revise.js
  20. 1 1
      app/public/js/revise_price.js
  21. 1 0
      app/public/js/settle_ledger.js
  22. 5 4
      app/public/js/settle_select.js
  23. 10 2
      app/public/js/shares/tools_att.js
  24. 40 10
      app/public/js/stage.js
  25. 1 1
      app/public/netcasign/ui/css/common.css
  26. 9 9
      app/public/report/js/rpt_archive.js
  27. 12 0
      app/service/advance_audit.js
  28. 12 1
      app/service/change_apply_audit.js
  29. 9 0
      app/service/change_plan_audit.js
  30. 12 0
      app/service/change_project_audit.js
  31. 1 1
      app/service/file.js
  32. 1 1
      app/service/ledger_history.js
  33. 14 1
      app/service/material_audit.js
  34. 35 0
      app/service/report.js
  35. 6 4
      app/service/settle.js
  36. 3 1
      app/service/settle_audit.js
  37. 33 3
      app/service/spec_msg.js
  38. 30 4
      app/service/stage_change.js
  39. 19 5
      app/service/stage_stash.js
  40. 2 2
      app/view/file/file.ejs
  41. 2 2
      app/view/report/index_archive.ejs
  42. 2 2
      app/view/report/index_sign.ejs
  43. 2 2
      app/view/settle/audit_btn.ejs
  44. 2 2
      app/view/settle/audit_modal.ejs
  45. 4 1
      app/view/settle/index.ejs
  46. 34 31
      app/view/settle/select.ejs
  47. 2 2
      app/view/tender/detail_modal.ejs
  48. 9 2
      db_script/test_query.js
  49. 13 0
      sql/update.sql

+ 4 - 2
app/const/source_type.js

@@ -4,14 +4,16 @@ const sourceTypeData = [
     { id: 1, name: '标段&期', key: 'tender' },
     { id: 10, name: '预付款', key: 'advance' },
     { id: 20, name: '变更令', key: 'change' },
-    { id: 21, name: '变更计划', key: 'change_plan' },
-    { id: 22, name: '变更项', key: 'change_project' },
+    { id: 21, name: '变更方案', key: 'change_plan' },
+    { id: 22, name: '变更项', key: 'change_project' },
     { id: 23, name: '变更申请', key: 'change_apply' },
     { id: 30, name: '材料调差', key: 'material' },
     { id: 100, name: '支付审批', key: 'payment' },
     { id: 101, name: '安全生产费', key: 'payment_safe' },
     { id: 200, name: '动态投资', key: 'budget' },
 ];
+
+// sourceType = { tender: 1, advance: 10, ... };
 const sourceType = (function (data){
     const result = {};
     for (const d of data) {

+ 16 - 3
app/const/spec_3f.js

@@ -9,13 +9,26 @@
  */
 
 const pushTiming = [
+    { value:'ledger.flow', name: '台账-上报/审批' },
     { value:'ledger.checked', name: '台账-审批通过' },
-    { value:'stage.checked', name: '期-审批通过' },
+    { value:'revise.flow', name: '台账修订-上报/审批' },
+    { value:'revise.checked', name: '台账修订-审批通过' },
+    { value:'advance.flow', name: '预付款-上报/审批' },
+    { value:'advance.checked', name: '预付款-审批通过' },
     { value:'stage.flow', name: '期-上报/审批' },
-    { value:'settle.checked', name: '结算期-审批通过' },
+    { value:'stage.checked', name: '期-审批通过' },
+    { value:'material.flow', name: '材差-上报/审批' },
+    { value:'material.checked', name: '材差-审批通过' },
     { value:'settle.flow', name: '结算期-上报/审批' },
-    { value:'revise.checked', name: '台账修订-审批通过' },
+    { value:'settle.checked', name: '结算期-审批通过' },
+    { value:'change.flow', name: '变更令-上报/审批' },
     { value:'change.checked', name: '变更令-审批通过' },
+    { value:'change_apply.flow', name: '变更申请-上报/审批' },
+    { value:'change_apply.checked', name: '变更申请-审批通过' },
+    { value:'change_plan.flow', name: '变更方案-上报/审批' },
+    { value:'change_plan.checked', name: '变更方案-审批通过' },
+    { value:'change_project.flow', name: '变更立项-上报/审批' },
+    { value:'change_project.checked', name: '变更立项-审批通过' },
     { value:'report.file', name: '报表-推送归档' },
 ];
 

+ 51 - 43
app/const/tender_info.js

@@ -13,26 +13,29 @@ const arrayInfo = ['chapter'];
 const defaultInfo = {
     // 合同信息
     deal_info: {
-        buildName: '',
-        dealCode: '',
-        dealName: '',
-        projectType: '',
-        dealType: '',
-        finalCode: '',
-        budgetApprovalCode: '',
+        buildName: '', // 建设项目名称
+        dealCode: '', // 合同编号
+        dealName: '', // 合同名称
+        projectType: '', // 工程类别
+        dealType: '', // 合同类别
+        finalCode: '', // 结算书编号
+        budgetApprovalCode: '', // 概算批复编号
     },
     // 参建单位
     construction_unit: {
+        // 建设
         build: {
-            company: '',
-            corporation: '',
-            date: '',
+            company: '', // 单位名称
+            corporation: '', // 法人代表
+            date: '', // 签订日期
         },
+        // 代建
         sub_build: {
             company: '',
             corporation: '',
             date: '',
         },
+        // 承包
         contract1: {
             company: '',
             corporation: '',
@@ -44,6 +47,7 @@ const defaultInfo = {
             corporation: '',
             date: '',
         },
+        // 监理
         supervision1: {
             company: '',
             corporation: '',
@@ -54,11 +58,13 @@ const defaultInfo = {
             corporation: '',
             date: '',
         },
+        // 检测
         detect: {
             company: '',
             corporation: '',
             date: '',
         },
+        // 审计
         audit: {
             company: '',
             corporation: '',
@@ -67,26 +73,27 @@ const defaultInfo = {
     },
     // 技术参数
     tech_param: {
-        loadLevel: 0,
-        loadLength: 0,
-        startPeg: '',
-        endPeg: '',
-        laneCount: 0,
-        dealPeriod: '',
-        startDate: '',
-        planEndDate: '',
-        realStartDate: '',
-        realEndDate: '',
-        structureScale: '',
-        mainContent: '',
+        loadLevel: 0, // 公路等级
+        loadLength: 0, // 长度
+        startPeg: '', // 起始桩号
+        endPeg: '', // 终止桩号
+        laneCount: 0, // 车道数
+        dealPeriod: '', // 合同工期
+        startDate: '', // 开工日期
+        planEndDate: '', // 计划完工日期
+        realStartDate: '', // 实际开工日期
+        realEndDate: '', // 实际完工日期
+        structureScale: '', // 构造物规模
+        mainContent: '', // 主要工作内容
     },
+    // 中标信息
     bid_info: {
-        controlPrice: 0,
-        bidPrice: 0,
-        bidStartDate: '',
-        bidType: '公开招标',
-        dealCalcType: '单价合同',
-        bidYuPrice: 0,
+        controlPrice: 0, // 业主控制价
+        bidPrice: 0, // 中标价
+        bidStartDate: '', // 开标日期
+        bidType: '公开招标', // 招标方式
+        dealCalcType: '单价合同', // 合同计价方式
+        bidYuPrice: 0, // 招标清单预算
     },
     // 小数位数
     decimal: {
@@ -115,12 +122,12 @@ const defaultInfo = {
     },
     // 合同参数
     deal_param: {
-        contractPrice: 0,
-        zanLiePrice: 0,
-        startAdvance: 0,
-        materialAdvance: 0,
-        safeAdvance: 0,
-        dustAdvance: 0,
+        contractPrice: 0, // 签约合同价
+        zanLiePrice: 0, // 暂列金额
+        startAdvance: 0, // 开工预付款
+        materialAdvance: 0, // 材料预付款
+        safeAdvance: 0, // 安全生产预付款
+        dustAdvance: 0, // 扬尘污染预付款
     },
     // 显示设置
     display: {
@@ -153,17 +160,18 @@ const defaultInfo = {
         {code: '1200', name: '消防系统'},
         {code: '1300', name: '供配电及照明系统'},
     ],
+    // 付款账号
     pay_account: {
-        project: {
-            name: '',
-            bank: '',
-            account: '',
-            rate: '',
-            contact: '',
-            phone: '',
-            num: '',
+        project: { // 工程款
+            name: '',  // 开户名称
+            bank: '', // 开户银行
+            account: '', // 开户账号
+            rate: '', // 分账划拨比例
+            contact: '', // 联系人
+            phone: '', // 联系电话
+            num: '', // 行号
         },
-        worker: {
+        worker: { // 农民工
             name: '',
             bank: '',
             account: '',

+ 8 - 2
app/controller/file_controller.js

@@ -126,11 +126,17 @@ module.exports = app => {
         async loadFile(ctx) {
             try {
                 const data = JSON.parse(ctx.request.body.data);
+                const order = data.order.split('|');
+                if (order.length !== 2) throw '加载文件错误';
+                if (order[0] !== 'filename' && order[0] !== 'create_time') throw '加载文件错误';
+                if (order[1] !== 'asc' && order[1] !== 'desc') throw '加载文件错误';
+
                 const result = await ctx.service.file.getFiles({
                     where: { filing_id: data.filing_id, is_deleted: 0 },
+                    orders: [order],
                     limit: data.count,
-                    offset: (data.page-1)*data.count
-                });
+                    offset: (data.page-1)*data.count,
+                }, order);
                 ctx.body = { err: 0, msg: '', data: result };
             } catch (err) {
                 ctx.log(err);

+ 2 - 0
app/controller/revise_controller.js

@@ -227,6 +227,7 @@ module.exports = app => {
                     throw '修订已审批通过,不可作废';
                 }
                 if (revise.valid) {
+                    revise.readySettle = await this.service.settle.getReadySettle(revise.tid);
                     const result = await ctx.service.ledgerRevise.cancelRevise(revise);
                 }
 
@@ -825,6 +826,7 @@ module.exports = app => {
                     throw '未填写修订内容,请先填写并保存修订内容';
                 }
                 if (revise.uid !== ctx.session.sessionUser.accountId) throw '上报失败';
+                revise.readySettle = await this.service.settle.getReadySettle(revise.tid);
 
                 await ctx.service.reviseAudit.start(revise, revise.times);
                 ctx.body = { err: 0, msg: '', data: {} };

+ 4 - 3
app/controller/settle_controller.js

@@ -94,7 +94,7 @@ module.exports = app => {
 
         async add(ctx) {
             try {
-                if (ctx.session.sessionUser.accountId !== ctx.tender.data.user_id) throw '您无权创建计量期';
+                if (ctx.session.sessionUser.accountId !== ctx.tender.data.user_id) throw '您无权创建结算期';
 
                 const date = ctx.request.body.date;
                 const period = ctx.request.body.period;
@@ -140,10 +140,11 @@ module.exports = app => {
                 const settle = await ctx.service.settle.getDataById(sid);
                 const settleCount = await ctx.service.settle.count({ tid: ctx.tender.id });
                 if (!settle || settle.tid !== ctx.tender.id) throw '选择的结算期已不存在';
-                if (settleCount === settle.settle_order) throw '选择的结算期无法删除';
+                if (settleCount !== settle.settle_order) throw '选择的结算期无法删除';
+
                 if (ctx.session.sessionUser.accountId !== settle.user_id && !ctx.session.sessionUser.is_admin) throw '您无权删除结算期';
 
-                await ctx.service.deleteSettle(sid);
+                await ctx.service.settle.deleteSettle(sid);
                 ctx.redirect('/tender/' + ctx.tender.id + '/settle/');
             } catch (err) {
                 ctx.log(err);

+ 1 - 1
app/controller/stage_controller.js

@@ -436,7 +436,7 @@ module.exports = app => {
                         checkData.checkMinusChangeBills(change, changeBills, endStageChange);
                     }
                 }
-                checkData.checkSettle();
+                if (ctx.stage.readySettle) checkData.checkSettle();
                 ctx.body = { err: 0, msg: '', data: checkData.checkResult };
             } catch (err) {
                 this.log(err);

+ 3 - 3
app/lib/ledger.js

@@ -1084,8 +1084,11 @@ class checkData {
         const settleStatus = this.ctx.service.settle.settleStatus;
         for (const b of this.checkBills.nodes) {
             if (b.children && b.children.length > 0) continue;
+            if (!b.settleStatus) continue;
+
             const pr = this.checkPos.getLedgerPos(b.id);
             if (!pr || pr.length === 0) {
+                if (b.settleStatus !== settleStatus.finish) continue;
                 if (b.contract_qty || b.contract_tp || b.qc_qty || b.qc_minus_qty || b.positive_qc_qty || b.negative_qc_qty) {
                     this.checkResult.error.push({
                         ledger_id: b.ledger_id,
@@ -1095,9 +1098,6 @@ class checkData {
                     });
                     if (!this.checkResult.source.bills.find(x => {return x.ledger_id === b.ledger_id})) {
                         this.checkResult.source.bills.push(b);
-                        for (const p of pr) {
-                            this.checkResult.source.pos.push(p);
-                        }
                     }
                 }
             } else {

+ 1 - 1
app/lib/revise_price.js

@@ -379,7 +379,7 @@ class revisePriceCalc {
 
         this.price = await this.ctx.service.revisePrice.getAllDataByCondition({ where: { rid: revise.id } });
         this.settleStatus = this.ctx.service.settle.settleStatus;
-        this.settleBills = revise.readySettle ? await this.ctx.service.settleBills.getAllDataByCondition({ where: { settle_id: revise.readySettle.id, settle_status: settleStatus.finish } }) : [];
+        this.settleBills = revise.readySettle ? await this.ctx.service.settleBills.getAllDataByCondition({ where: { settle_id: revise.readySettle.id, settle_status: this.settleStatus.finish } }) : [];
         this.settlePos = revise.readySettle ? await this.ctx.service.settlePos.getAllDataByCondition({ where: { settle_id: revise.readySettle.id }}) : [];
         const pcTp = await this.calcReviseLedger(revise, transaction);
         // 引用到所有工程变更

+ 96 - 0
app/lib/rm/change.js

@@ -0,0 +1,96 @@
+'use strict';
+
+/**
+ *
+ *
+ * @author Mai
+ * @date
+ * @version
+ */
+
+const RptMemBase = require('./base');
+const bindData = {};
+const changeConst = require('../const/change');
+
+class rptMemChange extends RptMemBase {
+    constructor(ctx) {
+        super(ctx, bindData);
+    }
+
+    async _anaylisChange(change) {
+        const types = ctx.helper._.map(change.type.split(','), function (t) {
+            return self._getChangeConstName(changeConst.type, ctx.helper._.toInteger(t));
+        });
+        change.type = types.join(';');
+        change.class = this._getChangeConstName(changeConst.class, change.class);
+        change.quality = this._getChangeConstName(changeConst.quality, change.quality);
+        change.charge = this._getChangeConstName(changeConst.charge, change.charge);
+    }
+
+    async doCheckChange(changeId) {
+        if (this.ctx.change) return;
+        this.ctx.change = await this.ctx.service.change.getDataByCondition({ where: { cid: changeId }});
+        this._anaylisChange(this.ctx.change);
+    }
+
+    async doCheckTender(tenderId) {
+        if (this.ctx.tender) return;
+        this.ctx.tender = { id: tenderId };
+        this.ctx.tender.data = await this.ctx.service.getTender(tenderId);
+        this.ctx.tender.info = await this.ctx.service.tenderInfo.getTenderInfo(tenderId);
+    }
+
+    async doBeforeLoadReport(params) {
+        await this.doCheckChange(params.change_id);
+        await this.doCheckTender(this.ctx.change.tid);
+    }
+
+    async _getChangeBills() {
+        const changeBills = await this.ctx.service.changeAuditList.getAllDataByCondition({ where: { cid: this.ctx.change.cid} });
+        for (const d of changeBills) {
+            d.o_qty = d.oamount;
+            d.o_tp = this.ctx.helper.mul(d.o_qty, d.unit_price, decimal.tp);
+            d.c_qty = d.camount;
+            d.c_tp = this.ctx.helper.mul(d.c_qty, d.unit_price, decimal.tp);
+            d.s_qty = d.samount ? parseFloat(d.samount) : 0;
+            d.s_tp = this.ctx.helper.mul(d.s_qty, d.unit_price, decimal.tp);
+            d.sp_qty = d.spamount;
+            d.sp_tp = this.ctx.helper.mul(d.sp_qty, d.unit_price, decimal.tp);
+
+            const auditAmount = d.audit_amount ? d.audit_amount.split(',') : [];
+            const relaChange = ctx.helper._.find(change, {cid: d.cid});
+            for (const [i, aa] of auditAmount.entries()) {
+                const amountField = 'qty_' + (i+1), tpField = 'tp_' + (i+1);
+                d[amountField] = aa ? parseFloat(aa) : 0;
+                d[tpField] = ctx.helper.mul(d[amountField], d.unit_price, decimal.tp);
+                if (relaChange) {
+                    relaChange[tpField] = ctx.helper.add(relaChange[tpField], d[tpField]);
+                }
+            }
+        }
+        return changeBills;
+    }
+
+    getCommonData(params, tableName, fields, customDefine, customSelect) {
+        switch (tableName) {
+            case 'mem_change':
+                return this.ctx.change;
+            case 'mem_change_bills':
+                return this._getChangeBills();
+            case 'mem_change_audit':
+                return this.ctx.service.changeAudit.getListGroupByTimes(this.ctx.change.cid, this.ctx.change.times);
+            case 'mem_change_att':
+                return this.ctx.service.changeAtt.getChangeAttachment(this.ctx.change.cid);
+            case 'mem_project':
+                return this.ctx.service.project.getDataByCondition({ id: this.ctx.session.sessionProject.id });
+            case 'mem_tender':
+                return this.ctx.tender.data;
+            case 'mem_tender_info':
+                return this.ctx.tender.info;
+            default:
+                return [];
+        }
+    }
+}
+
+module.exports = rptMemChange;

+ 80 - 0
app/lib/rm/change_apply.js

@@ -0,0 +1,80 @@
+'use strict';
+
+/**
+ * 变更申请
+ *
+ * @author Mai
+ * @date
+ * @version
+ */
+
+const RptMemBase = require('./base');
+const bindData = {};
+
+class rptMemChange extends RptMemBase {
+    constructor(ctx) {
+        super(ctx, bindData);
+    }
+
+    async doCheckChangeApply(id) {
+        if (this.ctx.change_apply) return;
+        this.ctx.change_apply = await this.ctx.service.change.getDataById(id);
+    }
+
+    async doCheckTender(tenderId) {
+        if (this.ctx.tender) return;
+        this.ctx.tender = { id: tenderId };
+        this.ctx.tender.data = await this.ctx.service.getTender(tenderId);
+        this.ctx.tender.info = await this.ctx.service.tenderInfo.getTenderInfo(tenderId);
+    }
+
+    async doBeforeLoadReport(params) {
+        await this.doCheckChangeApply(params.change_apply_id);
+        await this.doCheckTender(this.ctx.change_apply.tid);
+    }
+
+    async _getChangeApplyBills() {
+        const helper = this.ctx.helper;
+        const decimal = this.ctx.tender.info.decimal;
+        const apply = this.ctx.change_apply;
+
+        const bills = await this.ctx.service.changeApplyList.getAllDataByCondition({ where: { caid: apply.id} });
+        bills.forEach(x => {
+            const a_decimal = apply.decimal ? JSON.stringify(apply.decimal) : { tp: decimal.tp, up: decimal.up };
+            x.o_tp = helper.mul(x.oamount, x.unit_price, a_decimal.tp);
+            x.c_tp = helper.mul(x.camount, x.unit_price, a_decimal.tp);
+        });
+        bills.sort(function(a, b ) {
+            return helper.compareCode(a.code, b.code);
+        });
+        return bills;
+    }
+
+    async _getChangeApplyAudit() {
+        const changeAudit = await this.ctx.service.changeApplyAudit.getAllDataByCondition({ where: { caid: this.ctx.change_apply.id, times: this.ctx.change_apply.times }});
+        return this.ctx.helper.filterLastestData(changeAudit, ['aid']);
+    }
+
+    getCommonData(params, tableName, fields, customDefine, customSelect) {
+        switch (tableName) {
+            case 'mem_change_apply':
+                return this.ctx.change_apply;
+            case 'mem_change_apply_bills':
+                return this._getChangeApplyBills();
+            case 'mem_change_apply_audit':
+                return this._getChangeApplyAudit();
+            case 'mem_change_apply_att':
+                return this.ctx.service.changeApplyAtt.getChangeAttachment(this.ctx.change_apply.id);
+            case 'mem_project':
+                return this.ctx.service.project.getDataByCondition({ id: this.ctx.session.sessionProject.id });
+            case 'mem_tender':
+                return this.ctx.tender.data;
+            case 'mem_tender_info':
+                return this.ctx.tender.info;
+            default:
+                return [];
+        }
+    }
+}
+
+module.exports = rptMemChange;

+ 92 - 0
app/lib/rm/change_plan.js

@@ -0,0 +1,92 @@
+'use strict';
+
+/**
+ * 变更方案
+ *
+ * @author Mai
+ * @date
+ * @version
+ */
+
+const RptMemBase = require('./base');
+const bindData = {};
+
+class rptMemChange extends RptMemBase {
+    constructor(ctx) {
+        super(ctx, bindData);
+    }
+
+    async doCheckChangePlan(id) {
+        if (this.ctx.change_plan) return;
+        this.ctx.change_plan = await this.ctx.service.change.getDataById(id);
+    }
+
+    async doCheckTender(tenderId) {
+        if (this.ctx.tender) return;
+        this.ctx.tender = { id: tenderId };
+        this.ctx.tender.data = await this.ctx.service.getTender(tenderId);
+        this.ctx.tender.info = await this.ctx.service.tenderInfo.getTenderInfo(tenderId);
+    }
+
+    async doBeforeLoadReport(params) {
+        await this.doCheckChangePlan(params.change_plan_id);
+        await this.doCheckTender(this.ctx.change_plan.tid);
+    }
+
+    async _getChangePlanBills() {
+        const helper = this.ctx.helper;
+        const decimal = this.ctx.tender.info.decimal;
+        const plan = this.ctx.change_plan;
+
+        const bills = await this.ctx.service.changePlanList.getAllDataByCondition({ where: { cpid: this.ctx.change_plan.id} });
+        bills.forEach(x => {
+            const p_decimal = plan.decimal ? JSON.stringify(plan.decimal) : { tp: decimal.tp, up: decimal.up };
+            x.o_tp = helper.mul(x.oamount, x.unit_price, p_decimal.tp);
+            x.c_tp = helper.mul(x.camount, x.unit_price, p_decimal.tp);
+            x.s_tp = helper.mul(x.samount, x.unit_price, p_decimal.tp);
+            x.sp_tp = helper.mul(x.spamount, x.unit_price, p_decimal.tp);
+
+            const auditAmount = x.audit_amount ? x.audit_amount.split(',') : [];
+            for (const [i, aa] of auditAmount.entries()) {
+                const amountField = 'qty_' + (i+1), tpField = 'tp_' + (i+1);
+                x[amountField] = aa ? parseFloat(aa) : 0;
+                x[tpField] = helper.mul(x[amountField], x.unit_price, p_decimal.tp);
+                if (plan) {
+                    plan[tpField] = helper.add(plan[tpField], x[tpField]);
+                }
+            }
+        });
+        bills.sort(function(a, b) {
+            return helper.compareCode(a.code, b.code);
+        });
+        return bills;
+    }
+
+    async _getChangePlanAudit() {
+        const changeAudit = await this.ctx.service.changePlanAudit.getAllDataByCondition({ where: { cpid: this.ctx.change_plan.id, times: this.ctx.change_plan.times }});
+        return this.ctx.helper.filterLastestData(changeAudit, ['aid']);
+    }
+
+    getCommonData(params, tableName, fields, customDefine, customSelect) {
+        switch (tableName) {
+            case 'mem_change_plan':
+                return this.ctx.change_plan;
+            case 'mem_change_plan_bills':
+                return this._getChangePlanBills();
+            case 'mem_change_plan_audit':
+                return this._getChangePlanAudit();
+            case 'mem_change_plan_att':
+                return this.ctx.service.changePlanAtt.getChangeAttachment(this.ctx.change_plan.id);
+            case 'mem_project':
+                return this.ctx.service.project.getDataByCondition({ id: this.ctx.session.sessionProject.id });
+            case 'mem_tender':
+                return this.ctx.tender.data;
+            case 'mem_tender_info':
+                return this.ctx.tender.info;
+            default:
+                return [];
+        }
+    }
+}
+
+module.exports = rptMemChange;

+ 61 - 0
app/lib/rm/change_project.js

@@ -0,0 +1,61 @@
+'use strict';
+
+/**
+ * 变更立项
+ *
+ * @author Mai
+ * @date
+ * @version
+ */
+
+const RptMemBase = require('./base');
+const bindData = {};
+
+class rptMemChange extends RptMemBase {
+    constructor(ctx) {
+        super(ctx, bindData);
+    }
+
+    async doCheckChangeProject(id) {
+        if (this.ctx.change_project) return;
+        this.ctx.change_project = await this.ctx.service.change.getDataById(id);
+    }
+
+    async doCheckTender(tenderId) {
+        if (this.ctx.tender) return;
+        this.ctx.tender = { id: tenderId };
+        this.ctx.tender.data = await this.ctx.service.getTender(tenderId);
+        this.ctx.tender.info = await this.ctx.service.tenderInfo.getTenderInfo(tenderId);
+    }
+
+    async doBeforeLoadReport(params) {
+        await this.doCheckChangeProject(params.change_project_id);
+        await this.doCheckTender(this.ctx.change_project.tid);
+    }
+
+    async _getChangeProjectAudit() {
+        const changeAudit = await this.ctx.service.changeProjectAudit.getAllDataByCondition({ where: { cpid: this.ctx.change_project.id, times: this.ctx.change_project.times }});
+        return this.ctx.helper.filterLastestData(changeAudit, ['aid']);
+    }
+
+    getCommonData(params, tableName, fields, customDefine, customSelect) {
+        switch (tableName) {
+            case 'mem_change_project':
+                return this.ctx.change_project;
+            case 'mem_change_project_audit':
+                return this._getChangeProjectAudit();
+            case 'mem_change_project_att':
+                return this.ctx.service.changeProjectAtt.getChangeAttachment(this.ctx.change_project.id);
+            case 'mem_project':
+                return this.ctx.service.project.getDataByCondition({ id: this.ctx.session.sessionProject.id });
+            case 'mem_tender':
+                return this.ctx.tender.data;
+            case 'mem_tender_info':
+                return this.ctx.tender.info;
+            default:
+                return [];
+        }
+    }
+}
+
+module.exports = rptMemChange;

+ 3 - 3
app/lib/settle.js

@@ -119,7 +119,7 @@ class Settle {
                 sb.is_org_settle = pb.is_org_settle;
             }
         }
-        this.stageTree.initNodeData('settle_status', this.settleStatus.non, values => { return values.length === 1 ? values[0] : this.settleStatus.part});
+        // this.stageTree.initNodeData('settle_status', this.settleStatus.non, values => { return values.length === 1 ? values[0] : this.settleStatus.part});
     }
 
     calculateSettle() {
@@ -127,7 +127,7 @@ class Settle {
         const settle = this.settle;
         const settleStatus = this.settleStatus;
         this.stagePos.calculateAll(function(p) {
-            if (p.is_settle || !p.pre_settle) {
+            if (p.is_settle && !p.pre_settle) {
                 p.cur_contract_qty = p.settle_contract_qty;
                 p.cur_qc_qty = p.settle_qc_qty;
                 p.cur_qc_minus_qty = p.settle_qc_minus_qty;
@@ -171,7 +171,6 @@ class Settle {
                 b.end_qc_tp = helper.add(b.cur_qc_tp, b.pre_qc_tp);
                 b.end_qc_minus_qty = helper.add(b.cur_qc_minus_qty, b.pre_qc_minus_qty);
             }
-            //if (b.is_tp) {
             if (!b.end_contract_qty) {
                 if (helper.numEqual(b.end_contract_tp, b.total_price)) {
                     b.settle_status = settleStatus.finish;
@@ -188,6 +187,7 @@ class Settle {
                 }
             }
         });
+        this.stageTree.initNodeData('settle_status', this.settleStatus.non, values => { return values.length === 1 ? values[0] : this.settleStatus.part});
     }
 
     getSettleData() {

+ 11 - 0
app/lib/sum_load.js

@@ -319,6 +319,7 @@ class gatherStageGclTree extends loadGclBaseTree {
     constructor(ctx, setting) {
         super(ctx, setting);
         this.cover = setting.cover;
+        this.settleStatus = this.ctx.service.settle.settleStatus;
     }
     loadBase(datas, pos) {
         datas.sort((x, y) => { return x.level === y.level ? x.order - y.order : x.level - y.level; });
@@ -378,6 +379,8 @@ class gatherStageGclTree extends loadGclBaseTree {
             return (source.is_tp && node.is_tp) || (!source.is_tp && !node.is_tp);
         };
         const node = this.ignoreParent ? this.addNodeWithoutParent(source, checkFun) : this.addNode(source, parent, checkFun);
+        if (node.settle_status === this.settleStatus.finish) return node;
+
         if (node.is_tp) {
             node.contract_tp = this.ctx.helper.add(node.contract_tp, source.contract_tp);
         } else {
@@ -522,6 +525,7 @@ class sumLoad {
         for (const csb of curStageBills) {
             const b = billsIndex[csb.lid];
             if (!b) continue;
+
             b.contract_qty = csb.contract_qty;
             b.contract_tp = csb.contract_tp;
             b.qc_qty = csb.qc_qty;
@@ -534,6 +538,7 @@ class sumLoad {
 
             const b = billsIndex[csc.lid];
             if (!b) continue;
+
             if (!b.change_detail) b.change_detail = [];
             let c = b.change_detail.find(x => { return x.cbid === csc.cbid });
             if (!c) {
@@ -553,12 +558,18 @@ class sumLoad {
         const extraData = await this.ctx.service.ledgerExtra.getData(this.ctx.tender.id, ['is_tp']);
         const stageBills = await this.ctx.service.stageBills.getLastestStageData2(this.ctx.tender.id, this.ctx.stage.id);
         const importLid = await this.ctx.service.stageImportChange.getLeafXmjImportLid(this.ctx.stage.id, select.id);
+        const settleStatusBills = this.ctx.stage.readySettle ? await this.ctx.service.settleBills.getAllDataByCondition({ where: { settle_id: this.ctx.stage.readySettle.id }}) : [];
         this.ctx.helper.assignRelaData(posterity, [
             { data: extraData, fields: ['is_tp'], prefix: '', relaId: 'id' },
             { data: importLid, fields: ['is_import'], prefix: '', relaId: 'lid' },
             { data: stageBills, fields: ['contract_qty', 'contract_tp', 'qc_qty', 'qc_tp', 'qc_minus_qty', 'positive_qc_qty', 'positive_qc_tp', 'negative_qc_qty', 'negative_qc_tp'], prefix: '', relaId: 'lid' },
+            { data: settleStatusBills, fields: ['settle_status'], prefix: '', relaId: 'lid' },
         ]);
         const pos = await this.ctx.service.pos.getAllDataByCondition({ where: { tid: this.ctx.tender.id } });
+        const settleStatusPos = this.ctx.stage.readySettle ? await this.ctx.service.settlePos.getAllDataByCondition({ where: { settle_id: this.ctx.stage.readySettle.id }}) : [];
+        this.ctx.helper.assignRelaData(pos, [
+            { data: settleStatusPos, fields: ['settle_status'], prefix: '', relaId: 'pid' },
+        ]);
         this.loadTree.loadBase(posterity, pos);
 
         for (const tender of tenders) {

+ 1 - 1
app/middleware/change_check.js

@@ -68,7 +68,7 @@ module.exports = options => {
             } else { // 其他不可见
                 throw '您无权查看该数据';
             }
-            change.readySettle = yield this.service.settle.getReadySettle(revise.tid);
+            change.readySettle = yield this.service.settle.getReadySettle(change.tid);
             this.change = change;
             if ((change.status === status.uncheck || change.status === status.back || change.status === status.revise) && change.tp_decimal !== this.tender.info.decimal.tp) {
                 this.change.tp_decimal = this.tender.info.decimal.tp;

+ 38 - 5
app/public/js/file_detail.js

@@ -20,6 +20,21 @@ $(document).ready(function() {
             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());
+            this.fileOrderKey = 'fileOrder';
+            this.fileOrder = getLocalCache(this.fileOrderKey) || 'create_time|desc';
+        }
+        refreshFileOrderButton() {
+            const orderBy = this.fileOrder.split('|');
+            const field = orderBy[0], sort = orderBy[1];
+            const buttons = $('[name=file-sort]');
+            for (const b of buttons) {
+                const curField = b.getAttribute('field');
+                if (curField === field) {
+                    $(b).html(`<i class="fa fa-sort-amount-${sort}" aria-hidden="true"></i>`).attr('tag', `${curField}|${sort === 'asc' ? 'desc' : 'asc'}`);
+                } else {
+                    $(b).html('<i class="fa fa-sort" aria-hidden="true">').attr('tag', `${curField}|desc`);
+                }
+            }
         }
         calcTotalFileCount() {
             this.dragTree.recursiveFun(this.dragTree.children, x => {
@@ -135,7 +150,7 @@ $(document).ready(function() {
             const needFiles = Math.min(page*this.pageCount, node.source_node.file_count);
             if (node.source_node.files && needFiles <= node.source_node.files.length) return;
 
-            const files = await postDataAsync('file/load', { filing_id: node.id, page, count: this.pageCount });
+            const files = await postDataAsync('file/load', { filing_id: node.id, page, count: this.pageCount, order: this.fileOrder });
             files.forEach(x => {
                 const file = node.source_node.files.find(f => {return x.id === f.id; });
                 if (file) {
@@ -144,9 +159,9 @@ $(document).ready(function() {
                     node.source_node.files.push(x);
                 }
             });
-            node.source_node.files.sort((x, y) => {
-                return x.create_time - y.create_time;
-            });
+            // node.source_node.files.sort((x, y) => {
+            //     return x.create_time - y.create_time;
+            // });
         }
         addSiblingFiling(node) {
             const self = this;
@@ -226,8 +241,8 @@ $(document).ready(function() {
                 formData.append('file[]', file);
             }
             postDataWithFile('file/upload', formData, function (data) {
-                filingObj.curFiling.source_node.files.unshift(...data.files);
                 filingObj.updateFilingFileCount(filingObj.curFiling, data.filing.file_count);
+                filingObj.curFiling.source_node.files.unshift(...data.files);
                 filingObj.refreshPages();
                 filingObj.refreshFilesTable();
                 if (callback) callback();
@@ -389,6 +404,20 @@ $(document).ready(function() {
                 }
             });
         }
+        _clearAllFileCache() {
+            const nodes = this.filingTree.getNodes();
+            for (const node of nodes) {
+                if (node.children && node.children.length > 0) continue;
+                if (node.source_node.files) node.source_node.files.length = 0;
+            }
+        }
+        changeFileOrder(fileOrder) {
+            this.fileOrder = fileOrder;
+            setLocalCache(this.fileOrderKey, fileOrder);
+            this.refreshFileOrderButton();
+            this._clearAllFileCache();
+            this.setCurFiling(this.curFiling);
+        }
     }
     const levelTreeSetting = {
         treeId: 'filing',
@@ -516,6 +545,10 @@ $(document).ready(function() {
 
         filingObj.addChildFiling(filingObj.curFiling);
     });
+    $('[name=file-sort]').click(function() {
+        const tag = this.getAttribute('tag');
+        filingObj.changeFileOrder(tag);
+    });
     // $('#del-filing-btn').click(() => {
     //     if (!filingObj.curFiling) return;
     //     if (filingObj.curFiling.source_node.is_fixed) {

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

@@ -1195,6 +1195,7 @@ const spreadColor = {
     stage: {
         over: '#FF9595', //'#ff6f5c', '#f8d7da'
         differ: '#FF9595', // '#F2DEDE',
+        settle: '#f2f2f2',
     },
     gcl: {
         differ: '#FFE699', // 同编号时,名称、单位、单价存在不同

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

@@ -304,7 +304,7 @@ $(document).ready(() => {
             setObjEnable($('a[name=base-opr][type=down-move]'), valid && first && sameParent && first.level > 1 && !tree.isLastSibling(last));
             const posRange = last ? pos.getLedgerPos(last.id) : [];
             setObjEnable($('a[name=base-opr][type=up-level]'), valid && first && sameParent && tree.getParent(first)
-                && first.level > 2 && ((!posRange || posRange.length === 0) || tree.isLastSibling(last)) && last.settle_status !== settleStatus.finish);
+                && first.level > 2 && ((!posRange || posRange.length === 0) || tree.isLastSibling(last)) && (last.settle_status !== settleStatus.finish || tree.isLastSibling(last)));
             const preNodePosRange = preNode ? pos.getLedgerPos(preNode.id) : [];
             setObjEnable($('a[name=base-opr][type=down-level]'), valid && first && sameParent
                 && first.level > 1 && preNode && (!preNodePosRange || preNodePosRange.length === 0) && !preNode.used && preNode.settle_status !== settleStatus.finish);
@@ -414,7 +414,7 @@ $(document).ready(() => {
                     toastr.warning('选中的节点已计量,不可升级');
                     return;
                 }
-                if (lastSelect.settle_status === settleStatus.finish) {
+                if (lastSelect.settle_status === settleStatus.finish && (children.length > index + count)) {
                     toastr.warning('选中的节点已结算,不可升级');
                     return;
                 }

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

@@ -629,7 +629,7 @@ $(document).ready(() => {
                                 const datas = [];
                                 const sel = self.sheet.getSelections()[0];
                                 const node = self.sheet.zh_data[sel.row];
-                                if (node.settleStatus !== settleStatus.finish) datas.push(node);
+                                if (node.settle_status !== settleStatus.finish) datas.push(node);
                                 if (sel.rowCount > 1) {
                                     for (let r = 1; r < sel.rowCount; r++) {
                                         const rNode = self.sheet.zh_data[sel.row + r];

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

@@ -353,6 +353,7 @@ $(document).ready(() => {
             slSpread.refresh();
             spSpread.refresh();
             window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty();
+            if (searchLedger) searchLedger.spread.refresh();
         }
     });
 

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

@@ -243,7 +243,7 @@ $(document).ready(() => {
                 for (const p of posterity) {
                     if (p.selected) {
                         if (!update.del) update.del = [];
-                        update.del.push({ lid: node.id });
+                        update.del.push({ lid: p.id });
                     }
                     if (!p.children || p.children.length === 0) {
                         const posRange = settlePos.getLedgerPos(p.id);
@@ -262,8 +262,8 @@ $(document).ready(() => {
             }
             postData(window.location.pathname + '/update', update, result => {
                 node.selected = !node.selected;
+                let refreshRow = [info.row], refreshPos = false;
                 if (result.del) {
-                    let refreshRow = [], refreshPos = false;
                     for (const d of result.del) {
                         if (d.lid) {
                             const sbi = settleTree.nodes.findIndex(x => { return x.id === d.lid; });
@@ -277,9 +277,9 @@ $(document).ready(() => {
                             }
                         }
                     }
-                    if (refreshRow.length > 0) SpreadJsObj.reLoadRowsData(info.sheet, refreshRow);
-                    if (refreshPos) settlePosObj.loadCurPosData();
                 }
+                if (refreshRow.length > 0) SpreadJsObj.reLoadRowsData(info.sheet, refreshRow);
+                if (refreshPos) settlePosObj.loadCurPosData();
             }, () => {
                 SpreadJsObj.reLoadRowData(info.sheet, info.row);
             });
@@ -480,6 +480,7 @@ $(document).ready(() => {
             slSpread.refresh();
             spSpread.refresh();
             window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty();
+            if (searchLedger) searchLedger.spread.refresh();
         }
     });
 

+ 10 - 2
app/public/js/shares/tools_att.js

@@ -74,7 +74,7 @@
         };
         const refreshCurAttHtml = function () {
             const html = [];
-            const atts = (nodeIndexes[curNode[setting.key]]) || [];
+            const atts = curNode ? (nodeIndexes[curNode[setting.key]]) || [] : [];
             for (const att of atts) {
                 html.push(getAttHtml(att));
             }
@@ -103,7 +103,11 @@
         };
         const getCurAttHtml = function (node) {
             curNode = node;
-            $('#att-cur-hint').text(`${curNode.code || curNode.b_code || ''}/${curNode.name || ''}`);
+            if (curNode) {
+                $('#att-cur-hint').text(`${curNode.code || curNode.b_code || ''}/${curNode.name || ''}`);
+            } else {
+                $('#att-cur-hint').text('');
+            }
             refreshCurAttHtml();
         };
 
@@ -178,6 +182,10 @@
         });
         // 上传附件
         $('#upload-file-btn').click(function () {
+            if (!curNode) {
+                toastr.error('请先选择台账节点');
+                return false;
+            }
             const files = $('#upload-file')[0].files;
             const formData = new FormData();
             formData.append('lid', curNode[setting.key]);

+ 40 - 10
app/public/js/stage.js

@@ -734,6 +734,10 @@ $(document).ready(() => {
                 if (def && def.color) return def.color;
             }
 
+
+            if (data.settle_status === settleStatus.finish) {
+                return spreadColor.stage.settle;
+            }
             return hintOver && checkUtils.billsOver(data, checkTzMeasureType(), stagePos) ? spreadColor.stage.over : defaultColor;
         } else {
             return defaultColor;
@@ -825,6 +829,9 @@ $(document).ready(() => {
                 if (def && def.color) return def.color;
             }
         }
+        if (data.settle_status === settleStatus.finish) {
+            return spreadColor.stage.settle;
+        }
         if (checkTzMeasureType()) {
             return hintOver && checkUtils.posOver(data)  ? spreadColor.stage.over : defaultColor;
         }
@@ -1064,9 +1071,9 @@ $(document).ready(() => {
                                 if (node.b_code && node.b_code !== '') continue;
                             } else if (['postil', 'memo', 'ex_memo1', 'ex_memo2', 'ex_memo3'].indexOf(colSetting.field) < 0) {
                                 if (colSetting.field === 'contract_qty') {
-                                    if (node.is_tp || node.settle_status !== settleStatus.finish) continue;
+                                    if (node.is_tp || node.settle_status === settleStatus.finish) continue;
                                 } else if (colSetting.field === 'contract_tp') {
-                                    if (!node.is_tp || node.settle_status !== settleStatus.finish) continue;
+                                    if (!node.is_tp || node.settle_status === settleStatus.finish) continue;
                                 }
                                 if (node.children && node.children.length > 0) {
                                     continue;
@@ -1148,9 +1155,9 @@ $(document).ready(() => {
                         const curCol = info.cellRange.col + iCol;
                         const col = info.sheet.zh_setting.cols[curCol];
                         if (col.field === 'contract_tp') {
-                            if (!node.is_tp || node.settle_status !== settleStatus.finish) continue;
+                            if (!node.is_tp || node.settle_status === settleStatus.finish) continue;
                         } else if (col.field === 'contract_qty') {
-                            if (node.is_tp || node.settle_status !== settleStatus.finish) continue;
+                            if (node.is_tp || node.settle_status === settleStatus.finish) continue;
                         }
 
                         if (setting.dgnUpFields.indexOf(col.field) !== -1) {
@@ -1300,10 +1307,10 @@ $(document).ready(() => {
                 case 'contract_qty':
                 case 'qc_qty':
                 case 'qc_minus_qty':
-                    info.cancel = node.is_tp || node.settle_status !== settleStatus.finish;
+                    info.cancel = node.is_tp || node.settle_status === settleStatus.finish;
                     break;
                 case 'contract_tp':
-                    info.cancel = !node.is_tp || node.settle_status !== settleStatus.finish;
+                    info.cancel = !node.is_tp || node.settle_status === settleStatus.finish;
                     break;
                 case 'is_tp':
                     info.cancel = true;
@@ -1975,7 +1982,7 @@ $(document).ready(() => {
                 case 'contract_qty':
                 case 'qc_qty':
                 case 'qc_minus_qty':
-                    info.cancel = node.settle_status !== settleStatus.finish;
+                    info.cancel = node.settle_status === settleStatus.finish;
                     break;
             }
         },
@@ -2163,7 +2170,7 @@ $(document).ready(() => {
                                 toastr.error('部位名称不能为空');
                                 return;
                             }
-                            if (colSetting.Type === 'Number' && node.settle_status !== settleStatus.finish) {
+                            if (colSetting.Type === 'Number' && node.settle_status === settleStatus.finish) {
                                 toastr.error('已结算节点不可计量');
                                 return;
                             }
@@ -4121,6 +4128,10 @@ $(document).ready(() => {
                                 const billsPos = self.findBillsPos(curChange, cb);
                                 if (billsPos) data.bills.push({ ...billsPos, cid: cb.cid, cbid: cb.id })
                             }
+                            if (data.bills.length === 0) {
+                                toastr.warning('无可调用的清单或计量单元');
+                                return;
+                            }
                             postData(window.location.pathname + '/auto-use-change', data, function(result) {
                                 if (result.pos) {
                                     stagePos.loadCurStageData(result.pos.curStageData);
@@ -4255,9 +4266,20 @@ $(document).ready(() => {
                 return null;
             } else if (changeBills.gcl_id) {
                 const node = stageTree.nodes.find(x => {return x.id === changeBills.gcl_id});
+                if (node.settle_status === settleStatus.finish) return null;
+
                 posData = stagePos.getLedgerPos(node.id) || [];
                 const changePos = posData.find(x => { return x.name === changeBills.bwmx; });
-                return { lid: node.id, pid: changePos ? changePos.id : (posData.length > 0 ? posData[0].id : '-1') };
+                if (changePos.settle_status) return null;
+
+                let defaultPos;
+                if (posData.length > 0) {
+                    defaultPos = posData.length > 0 ? posData.find(x => { return !x.settle_status}) : null;
+                    if (!defaultPos) return null;
+                } else {
+                    defaultPos = { id: '-1' };
+                }
+                return { lid: node.id, pid: changePos ? changePos.id : defaultPos.id };
             } else {
                 const cb = {
                     b_code: changeBills.code || '',
@@ -4267,6 +4289,7 @@ $(document).ready(() => {
                 };
                 for (const node of stageTree.nodes) {
                     if (node.children && node.children.length > 0) continue;
+                    if (node.settle_status === settleStatus.finish) return null;
 
                     const b = {
                         b_code: node.b_code || '',
@@ -4276,7 +4299,14 @@ $(document).ready(() => {
                     };
                     if (_.isMatch(cb, b)) {
                         posData = stagePos.getLedgerPos(node.id) || [];
-                        return { lid: node.id, pid: posData.length > 0 ? posData[0].id : '-1' };
+                        let defaultPos;
+                        if (posData.length > 0) {
+                            defaultPos = posData.length > 0 ? posData.find(x => { return !x.settle_status}) : null;
+                            if (!defaultPos) return null;
+                        } else {
+                            defaultPos = { id: '-1' };
+                        }
+                        return { lid: node.id, pid: defaultPos.id };
                     }
                 }
                 return null;

+ 1 - 1
app/public/netcasign/ui/css/common.css

@@ -1,7 +1,7 @@
 /*viewer*/
 #netcasignpdf{
     width:100%;
-    height:750px;
+    height:100%;
     display: none;
 }
 

+ 9 - 9
app/public/report/js/rpt_archive.js

@@ -197,14 +197,14 @@ let rptArchiveObj = {
                     }
                     postData('/tender/'+ TENDER_ID +'/signReport/post', {type: 'pdfIsExist', uuid: me.currentArchiveUuid}, function (result) {
                         me.currentArchivePdfPath = result ? oss_path + '/sign/'+ me.currentArchiveUuid +'.PDF' + (uSignLogList.length !== 0 ? '?' + uSignLogList[uSignLogList.length-1].versionid : '') : oss_path + '/'+ me.currentArchiveUuid +'.PDF?' + new Date(me.currentArchiveDateStr.slice(3).replace(/-/g, '/')).getTime();
-                        $('#iframe_made').html('<iframe src="/archive/pdf/show?file=' + me.currentArchivePdfPath + '" height="750px" width="100%" style="border: none;"></iframe>');
+                        $('#iframe_made').html('<iframe src="/archive/pdf/show?file=' + me.currentArchivePdfPath + '" height="100%" width="100%" style="border: none;"></iframe>');
                     }, function () {
                         me.currentArchivePdfPath = oss_path + '/'+ me.currentArchiveUuid +'.PDF?' + new Date(me.currentArchiveDateStr.slice(3).replace(/-/g, '/')).getTime();
-                        $('#iframe_made').html('<iframe src="/archive/pdf/show?file=' + me.currentArchivePdfPath + '" height="750px" width="100%" style="border: none;"></iframe>');
+                        $('#iframe_made').html('<iframe src="/archive/pdf/show?file=' + me.currentArchivePdfPath + '" height="100%" width="100%" style="border: none;"></iframe>');
                     })
                 } else {
                     me.currentArchivePdfPath = oss_path + '/'+ me.currentArchiveUuid +'.PDF?' + new Date(me.currentArchiveDateStr.slice(3).replace(/-/g, '/')).getTime();
-                    $('#iframe_made').html('<iframe src="/archive/pdf/show?file=' + me.currentArchivePdfPath + '" height="750px" width="100%" style="border: none;"></iframe>');
+                    $('#iframe_made').html('<iframe src="/archive/pdf/show?file=' + me.currentArchivePdfPath + '" height="100%" width="100%" style="border: none;"></iframe>');
                     console.log(me.currentArchivePdfPath);
                 }
                 // let uuIdUrl =  "/getArchivedFileByUUID/" + me.currentArchiveUuid + "/" + stringUtil.replaceAll(me.currentNode.name, "#", "_");
@@ -245,11 +245,11 @@ let rptArchiveObj = {
             postData('/tender/'+ TENDER_ID +'/signReport/post', {type: 'pdfIsExist', uuid: me.currentArchiveUuid}, function (result) {
                 const uSignLogList = _.filter(signLogList, { uuid: me.currentArchiveUuid });
                 me.currentArchivePdfPath = result ? oss_path + '/sign/'+ me.currentArchiveUuid +'.PDF' + (uSignLogList.length !== 0 ? '?' + uSignLogList[uSignLogList.length-1].versionid : '') : oss_path + '/'+ me.currentArchiveUuid +'.PDF?' + new Date(me.currentArchiveDateStr.slice(3).replace(/-/g, '/')).getTime();
-                $('#iframe_made').html('<iframe src="/archive/pdf/show?file=' + me.currentArchivePdfPath + '" height="750px" width="100%" style="border: none;"></iframe>');
+                $('#iframe_made').html('<iframe src="/archive/pdf/show?file=' + me.currentArchivePdfPath + '" height="100%" width="100%" style="border: none;"></iframe>');
                 me._buildeArchiveDateSelect();
             }, function () {
                 me.currentArchivePdfPath = oss_path + '/'+ me.currentArchiveUuid +'.PDF?' + new Date(me.currentArchiveDateStr.slice(3).replace(/-/g, '/')).getTime();
-                $('#iframe_made').html('<iframe src="/archive/pdf/show?file=' + me.currentArchivePdfPath + '" height="750px" width="100%" style="border: none;"></iframe>');
+                $('#iframe_made').html('<iframe src="/archive/pdf/show?file=' + me.currentArchivePdfPath + '" height="100%" width="100%" style="border: none;"></iframe>');
                 me._buildeArchiveDateSelect();
             });
             // me._updateSignHtmlAndFrame();
@@ -257,7 +257,7 @@ let rptArchiveObj = {
             me._iniArchiveItemForDeleteShow();
         } else {
             me.currentArchivePdfPath = oss_path + '/'+ me.currentArchiveUuid +'.PDF?' + new Date(me.currentArchiveDateStr.slice(3).replace(/-/g, '/')).getTime();
-            $('#iframe_made').html('<iframe src="/archive/pdf/show?file=' + me.currentArchivePdfPath + '" height="750px" width="100%" style="border: none;"></iframe>');
+            $('#iframe_made').html('<iframe src="/archive/pdf/show?file=' + me.currentArchivePdfPath + '" height="100%" width="100%" style="border: none;"></iframe>');
             me._buildeArchiveDateSelect();
             me._iniArchiveItemForDeleteShow();
         }
@@ -309,7 +309,7 @@ let rptArchiveObj = {
         $('#page-list').html(pagetr);
         if (needFrame) {
             me.currentArchivePdfPath = uSignLogList.length > 0 ? oss_path + '/sign/'+ me.currentArchiveUuid +'.PDF' : oss_path + '/'+ me.currentArchiveUuid +'.PDF?' + new Date(me.currentArchiveDateStr.slice(3).replace(/-/g, '/')).getTime();
-            $('#iframe_made').html('<iframe src="/archive/pdf/show?file=' + me.currentArchivePdfPath + (uSignLogList.length !== 0 ? '?' + uSignLogList[uSignLogList.length-1].versionid : '') + '" height="750px" width="100%" style="border: none;"></iframe>');
+            $('#iframe_made').html('<iframe src="/archive/pdf/show?file=' + me.currentArchivePdfPath + (uSignLogList.length !== 0 ? '?' + uSignLogList[uSignLogList.length-1].versionid : '') + '" height="100%" width="100%" style="border: none;"></iframe>');
         }
         $('#dateStr').html(me.currentArchiveDateStr);
         $('#sign_num').text(uSignLogList.length);
@@ -737,7 +737,7 @@ let rptArchiveObj = {
                         let archiveUrl = `/tender/report_api/updateArchive/${PROJECT_ID}/${current_stage_id}/${currentNode.refId}/${orgName}`;
                         if (currentRptPageRst.splitArcPages && currentRptPageRst.splitArcPages.length > 0) {
                             // archiveUrl = `/tender/report_api/addParentChildrenArchive/${PROJECT_ID}/${current_stage_id}/${currentNode.refId}/${orgName}`;
-                            archiveUrl = `/tender/report_api/addParentChildrenArchive/${PROJECT_ID}/${current_stage_id}/${currentNode.refId}/${JSON.stringify(currentRptPageRst.splitArcPages)};${JSON.stringify(currentRptPageRst.splitArcPagesInfo)};${currentRptPageRst.items.length}`; // 分页方式不需要 orgName 
+                            archiveUrl = `/tender/report_api/addParentChildrenArchive/${PROJECT_ID}/${current_stage_id}/${currentNode.refId}/${JSON.stringify(currentRptPageRst.splitArcPages)};${JSON.stringify(currentRptPageRst.splitArcPagesInfo)};${currentRptPageRst.items.length}`; // 分页方式不需要 orgName
                         }
                         postDataWithFile(archiveUrl, formData, function (result) {
                         // postDataWithFile('/tender/report_api/updateArchive/' + PROJECT_ID + '/' + current_stage_id + '/' + currentNode.refId + '/' + orgName, formData, function (result) {
@@ -803,7 +803,7 @@ let rptArchiveObj = {
             alert('请选择打开一个报表!');
         }
     },
-    
+
     _getOneValidLeafNode: function(node) {
         let rst = null;
         let me = rptArchiveObj;

+ 12 - 0
app/service/advance_audit.js

@@ -3,6 +3,7 @@
 const auditConst = require('../const/audit').advance;
 const shenpiConst = require('../const/shenpi');
 const pushType = require('../const/audit').pushType;
+const pushOperate = require('../const/spec_3f').pushOperate;
 const smsTypeConst = require('../const/sms_type');
 const wxConst = require('../const/wechat_template.js');
 const advanceConst = require('../const/advance');
@@ -241,6 +242,8 @@ module.exports = app => {
                     code: this.ctx.session.sessionProject.code,
                 };
                 await this.ctx.helper.sendWechat(audit.audit_id, smsTypeConst.const.YFK, smsTypeConst.judge.approval.toString(), wxConst.template.advance, wechatData);
+                // 审批通过 - 检查三方特殊推送
+                await this.ctx.service.specMsg.addAdvanceMsg(transaction, pid, advanceInfo, pushOperate.advance.flow);
                 await transaction.commit();
             } catch (err) {
                 await transaction.rollback();
@@ -302,6 +305,8 @@ module.exports = app => {
                         code: this.ctx.session.sessionProject.code,
                     };
                     await this.ctx.helper.sendWechat(nextAudit.audit_id, smsTypeConst.const.YFK, smsTypeConst.judge.approval.toString(), wxConst.template.advance, wechatData);
+                    // 审批通过 - 检查三方特殊推送
+                    await this.ctx.service.specMsg.addAdvanceMsg(transaction, pid, advanceInfo, pushOperate.advance.flow);
                 } else {
                     await transaction.update(this.ctx.service.advance.tableName, {
                         id: advanceId,
@@ -320,6 +325,9 @@ module.exports = app => {
                         code: this.ctx.session.sessionProject.code,
                     };
                     await this.ctx.helper.sendWechat(users, smsTypeConst.const.YFK, smsTypeConst.judge.result.toString(), wxConst.template.advance, wechatData);
+                    // 审批通过 - 检查三方特殊推送
+                    await this.ctx.service.specMsg.addAdvanceMsg(transaction, pid, advanceInfo, pushOperate.advance.flow);
+                    await this.ctx.service.specMsg.addAdvanceMsg(transaction, pid, advanceInfo, pushOperate.advance.checked);
                 }
                 await transaction.commit();
                 if (!nextAudit) this.ctx.service.tenderCache.updateAdvanceCache(audit.tid);
@@ -381,6 +389,8 @@ module.exports = app => {
                 await this.ctx.helper.sendWechat(users, smsTypeConst.const.YFK, smsTypeConst.judge.result.toString(), wxConst.template.advance, wechatData);
                 // 拷贝新一次审核流程列表
                 await transaction.insert(this.tableName, auditors);
+                // 检查三方特殊推送
+                await this.ctx.service.specMsg.addAdvanceMsg(transaction, pid, advanceInfo, pushOperate.advance.flow);
                 await transaction.commit();
             } catch (err) {
                 await transaction.rollback();
@@ -451,6 +461,8 @@ module.exports = app => {
                 };
                 await this.ctx.helper.sendWechat(preAuditor.audit_id, smsTypeConst.const.YFK, smsTypeConst.judge.approval.toString(), wxConst.template.advance, wechatData);
                 await transaction.insert(this.tableName, newAuditors);
+                // 检查三方特殊推送
+                await this.ctx.service.specMsg.addAdvanceMsg(transaction, pid, advanceInfo, pushOperate.advance.flow);
                 await transaction.commit();
             } catch (error) {
                 await transaction.rollback();

+ 12 - 1
app/service/change_apply_audit.js

@@ -10,6 +10,7 @@
 
 const auditConst = require('../const/audit').changeApply;
 const pushType = require('../const/audit').pushType;
+const pushOperate = require('../const/spec_3f').pushOperate;
 const shenpiConst = require('../const/shenpi');
 const smsTypeConst = require('../const/sms_type');
 const SMS = require('../lib/sms');
@@ -288,6 +289,8 @@ module.exports = app => {
                 await this.ctx.helper.sendWechat(audit.aid, smsTypeConst.const.BG, smsTypeConst.judge.approval.toString(), wxConst.template.change, wechatData);
                 await transaction.delete(this.ctx.service.changeApplyHistory.tableName, { caid: caId });
                 // todo 更新标段tender状态 ?
+                //  检查三方特殊推送
+                await this.ctx.service.specMsg.addChangeApplyMsg(transaction, pid, this.ctx.change, pushOperate.change_apply.flow);
                 await transaction.commit();
             } catch (err) {
                 await transaction.rollback();
@@ -433,6 +436,8 @@ module.exports = app => {
                         c_name: this.ctx.change.name,
                     };
                     await this.ctx.helper.sendWechat(nextAudit.aid, smsTypeConst.const.BG, smsTypeConst.judge.approval.toString(), wxConst.template.change, wechatData);
+                    //  检查三方特殊推送
+                    await this.ctx.service.specMsg.addChangeApplyMsg(transaction, pid, this.ctx.change, pushOperate.change_apply.flow);
                 } else {
                     // 本期结束
                     // 生成截止本期数据 final数据
@@ -454,6 +459,9 @@ module.exports = app => {
                         c_name: this.ctx.change.name,
                     };
                     await this.ctx.helper.sendWechat(users, smsTypeConst.const.BG, smsTypeConst.judge.result.toString(), wxConst.template.change, wechatData);
+                    //  检查三方特殊推送
+                    await this.ctx.service.specMsg.addChangeApplyMsg(transaction, pid, this.ctx.change, pushOperate.change_apply.flow);
+                    await this.ctx.service.specMsg.addChangeApplyMsg(transaction, pid, this.ctx.change, pushOperate.change_apply.checked);
                 }
                 await transaction.commit();
             } catch (err) {
@@ -528,6 +536,8 @@ module.exports = app => {
                     where: { caid: caId },
                 });
                 await this.ctx.service.changeApplyHistory.saveHistory(transaction, changeData, changeList);
+                //  检查三方特殊推送
+                await this.ctx.service.specMsg.addChangeApplyMsg(transaction, pid, this.ctx.change, pushOperate.change_apply.flow);
                 await transaction.commit();
             } catch (err) {
                 await transaction.rollback();
@@ -832,7 +842,6 @@ module.exports = app => {
                     status: auditConst.status.revise,
                     times: change.times + 1,
                 });
-
                 await transaction.commit();
                 result = true;
             } catch (error) {
@@ -946,6 +955,8 @@ module.exports = app => {
                     notice_uid: null,
                     decimal: null,
                 });
+                //  检查三方特殊推送
+                await this.ctx.service.specMsg.addChangeApplyMsg(transaction, pid, this.ctx.change, pushOperate.change_apply.flow);
                 await transaction.commit();
                 result = true;
             } catch (error) {

+ 9 - 0
app/service/change_plan_audit.js

@@ -10,6 +10,7 @@
 
 const auditConst = require('../const/audit').changePlan;
 const pushType = require('../const/audit').pushType;
+const pushOperate = require('../const/spec_3f').pushOperate;
 const shenpiConst = require('../const/shenpi');
 const smsTypeConst = require('../const/sms_type');
 const SMS = require('../lib/sms');
@@ -290,6 +291,8 @@ module.exports = app => {
                     c_name: this.ctx.change.name,
                 };
                 await this.ctx.helper.sendWechat(audit.aid, smsTypeConst.const.BG, smsTypeConst.judge.approval.toString(), wxConst.template.change, wechatData);
+                //  检查三方特殊推送
+                await this.ctx.service.specMsg.addChangePlanMsg(transaction, pid, this.ctx.change, pushOperate.change_plan.flow);
                 await transaction.delete(this.ctx.service.changePlanHistory.tableName, { cpid: cpId });
                 // todo 更新标段tender状态 ?
                 await transaction.commit();
@@ -444,6 +447,8 @@ module.exports = app => {
                         c_name: this.ctx.change.name,
                     };
                     await this.ctx.helper.sendWechat(nextAudit.aid, smsTypeConst.const.BG, smsTypeConst.judge.approval.toString(), wxConst.template.change, wechatData);
+                    //  检查三方特殊推送
+                    await this.ctx.service.specMsg.addChangePlanMsg(transaction, pid, this.ctx.change, pushOperate.change_plan.flow);
                 } else {
                     // 本期结束
                     // 生成截止本期数据 final数据
@@ -467,6 +472,8 @@ module.exports = app => {
                         c_name: this.ctx.change.name,
                     };
                     await this.ctx.helper.sendWechat(users, smsTypeConst.const.BG, smsTypeConst.judge.result.toString(), wxConst.template.change, wechatData);
+                    //  检查三方特殊推送
+                    await this.ctx.service.specMsg.addChangePlanMsg(transaction, pid, this.ctx.change, pushOperate.change_plan.flow);
                 }
                 await transaction.commit();
             } catch (err) {
@@ -536,6 +543,8 @@ module.exports = app => {
                     c_name: this.ctx.change.name,
                 };
                 await this.ctx.helper.sendWechat(users, smsTypeConst.const.BG, smsTypeConst.judge.result.toString(), wxConst.template.change, wechatData);
+                //  检查三方特殊推送
+                await this.ctx.service.specMsg.addChangePlanMsg(transaction, pid, this.ctx.change, pushOperate.change_plan.flow);
                 // 生成内容保存表至zh_change_project_history中,用于撤回
                 // 回退spamount值数据
                 const changeList = await this.ctx.service.changePlanList.getAllDataByCondition({

+ 12 - 0
app/service/change_project_audit.js

@@ -10,6 +10,7 @@
 
 const auditConst = require('../const/audit').changeProject;
 const pushType = require('../const/audit').pushType;
+const pushOperate = require('../const/spec_3f').pushOperate;
 const shenpiConst = require('../const/shenpi');
 const smsTypeConst = require('../const/sms_type');
 const SMS = require('../lib/sms');
@@ -290,6 +291,8 @@ module.exports = app => {
                 await this.ctx.helper.sendWechat(audit.aid, smsTypeConst.const.BG, smsTypeConst.judge.approval.toString(), wxConst.template.change, wechatData);
                 await transaction.delete(this.ctx.service.changeProjectHistory.tableName, { cpid: cpId });
                 // todo 更新标段tender状态 ?
+                //  检查三方特殊推送
+                await this.ctx.service.specMsg.addChangeProjectMsg(transaction, pid, this.ctx.change, pushOperate.change_project.flow);
                 await transaction.commit();
             } catch (err) {
                 await transaction.rollback();
@@ -438,6 +441,8 @@ module.exports = app => {
                         c_name: this.ctx.change.name,
                     };
                     await this.ctx.helper.sendWechat(nextAudit.aid, smsTypeConst.const.BG, smsTypeConst.judge.approval.toString(), wxConst.template.change, wechatData);
+                    //  检查三方特殊推送
+                    await this.ctx.service.specMsg.addChangeProjectMsg(transaction, pid, this.ctx.change, pushOperate.change_project.flow);
                 } else {
                     // 本期结束
                     // 生成截止本期数据 final数据
@@ -456,6 +461,9 @@ module.exports = app => {
                         c_name: this.ctx.change.name,
                     };
                     await this.ctx.helper.sendWechat(users, smsTypeConst.const.BG, smsTypeConst.judge.result.toString(), wxConst.template.change, wechatData);
+                    //  检查三方特殊推送
+                    await this.ctx.service.specMsg.addChangeProjectMsg(transaction, pid, this.ctx.change, pushOperate.change_project.flow);
+                    await this.ctx.service.specMsg.addChangeProjectMsg(transaction, pid, this.ctx.change, pushOperate.change_project.checked);
                 }
                 await transaction.commit();
             } catch (err) {
@@ -522,6 +530,8 @@ module.exports = app => {
                 await this.ctx.helper.sendWechat(users, smsTypeConst.const.BG, smsTypeConst.judge.result.toString(), wxConst.template.change, wechatData);
                 // 生成内容保存表至zh_change_project_history中,用于撤回
                 await this.ctx.service.changeProjectHistory.saveHistory(transaction, changeData);
+                //  检查三方特殊推送
+                await this.ctx.service.specMsg.addChangeProjectMsg(transaction, pid, this.ctx.change, pushOperate.change_project.flow);
                 await transaction.commit();
             } catch (err) {
                 await transaction.rollback();
@@ -571,6 +581,8 @@ module.exports = app => {
                     c_name: this.ctx.change.name,
                 };
                 await this.ctx.helper.sendWechat(users, smsTypeConst.const.BG, smsTypeConst.judge.result.toString(), wxConst.template.change, wechatData);
+                //  检查三方特殊推送
+                await this.ctx.service.specMsg.addChangeProjectMsg(transaction, pid, this.ctx.change, pushOperate.change_project.flow);
                 await transaction.commit();
             } catch (err) {
                 await transaction.rollback();

+ 1 - 1
app/service/file.js

@@ -38,7 +38,7 @@ module.exports = app => {
         }
 
         async getFiles(condition) {
-            condition.orders = [['create_time', 'desc']];
+            // condition.orders = [['create_time', 'desc']];
             const result = await this.getAllDataByCondition(condition);
             this.analysisFiles(result);
             return result;

+ 1 - 1
app/service/ledger_history.js

@@ -124,7 +124,7 @@ module.exports = app => {
                 await this.ctx.hisOss.put(this.ctx.hisOssPath + billsHis, Buffer.from(JSON.stringify(bills), 'utf8'));
                 await this.ctx.hisOss.put(this.ctx.hisOssPath + posHis, Buffer.from(JSON.stringify(pos), 'utf8'));
             } else {
-                const settleStatusBills = revise.readySettle ? await ctx.service.settleBills.getAllDataByCondition({ where: { settle_id: revise.readySettle.id }}): [];
+                const settleStatusBills = revise.readySettle ? await this.ctx.service.settleBills.getAllDataByCondition({ where: { settle_id: revise.readySettle.id }}): [];
                 this.ctx.helper.assignRelaData(bills, [
                     { data: settleStatusBills, fields: ['settle_status'], prefix: '', relaId: 'lid' },
                 ]);

+ 14 - 1
app/service/material_audit.js

@@ -10,6 +10,7 @@
 
 const auditConst = require('../const/audit').material;
 const pushType = require('../const/audit').pushType;
+const pushOperate = require('../const/spec_3f').pushOperate;
 const smsTypeConst = require('../const/sms_type');
 const wxConst = require('../const/wechat_template');
 const shenpiConst = require('../const/shenpi');
@@ -291,6 +292,8 @@ module.exports = app => {
                 // }
 
                 // todo 更新标段tender状态 ?
+                // 检查三方特殊推送
+                await this.ctx.service.specMsg.addMaterialMsg(transaction, pid, materialInfo, pushOperate.material.flow);
                 await transaction.commit();
             } catch (err) {
                 await transaction.rollback();
@@ -358,7 +361,8 @@ module.exports = app => {
                         hs_m_tp: this.ctx.helper.add(this.ctx.helper.round(this.ctx.helper.mul(materialInfo.m_tp, 1+materialInfo.rate/100), material_decimal.tp), this.ctx.helper.round(this.ctx.helper.mul(materialInfo.ex_tp, 1+materialInfo.exponent_rate/100), material_decimal.tp)),
                     };
                     await this.ctx.helper.sendWechat(nextAudit.aid, smsTypeConst.const.TC, smsTypeConst.judge.approval.toString(), wxConst.template.material, wechatData);
-
+                    // 检查三方特殊推送
+                    await this.ctx.service.specMsg.addMaterialMsg(transaction, pid, materialInfo, pushOperate.material.flow);
 
                     // 添加短信通知-需要审批提醒功能
                     // const smsUser = await this.ctx.service.projectAccount.getDataById(nextAudit.aid);
@@ -445,6 +449,9 @@ module.exports = app => {
                         hs_m_tp: this.ctx.helper.add(this.ctx.helper.round(this.ctx.helper.mul(materialInfo.m_tp, 1+materialInfo.rate/100), material_decimal.tp), this.ctx.helper.round(this.ctx.helper.mul(materialInfo.ex_tp, 1+materialInfo.exponent_rate/100), material_decimal.tp)),
                     };
                     await this.ctx.helper.sendWechat(users, smsTypeConst.const.TC, smsTypeConst.judge.result.toString(), wxConst.template.material, wechatData);
+                    // 检查三方特殊推送
+                    await this.ctx.service.specMsg.addMaterialMsg(transaction, pid, materialInfo, pushOperate.material.flow);
+                    await this.ctx.service.specMsg.addMaterialMsg(transaction, pid, materialInfo, pushOperate.material.checked);
 
                     // 添加短信通知-审批通过提醒功能
                     // const mobile_array = [];
@@ -545,6 +552,8 @@ module.exports = app => {
                     hs_m_tp: this.ctx.helper.add(this.ctx.helper.round(this.ctx.helper.mul(materialInfo.m_tp, 1+materialInfo.rate/100), material_decimal.tp), this.ctx.helper.round(this.ctx.helper.mul(materialInfo.ex_tp, 1+materialInfo.exponent_rate/100), material_decimal.tp)),
                 };
                 await this.ctx.helper.sendWechat(users, smsTypeConst.const.TC, smsTypeConst.judge.result.toString(), wxConst.template.material, wechatData);
+                // 检查三方特殊推送
+                await this.ctx.service.specMsg.addMaterialMsg(transaction, pid, materialInfo, pushOperate.material.flow);
 
                 // 添加短信通知-审批退回提醒功能
                 // const mobile_array = [];
@@ -640,6 +649,8 @@ module.exports = app => {
                     hs_m_tp: this.ctx.helper.add(this.ctx.helper.round(this.ctx.helper.mul(materialInfo.m_tp, 1+materialInfo.rate/100), material_decimal.tp), this.ctx.helper.round(this.ctx.helper.mul(materialInfo.ex_tp, 1+materialInfo.exponent_rate/100), material_decimal.tp)),
                 };
                 await this.ctx.helper.sendWechat(preAuditor.aid, smsTypeConst.const.TC, smsTypeConst.judge.approval.toString(), wxConst.template.material, wechatData);
+                // 检查三方特殊推送
+                await this.ctx.service.specMsg.addMaterialMsg(transaction, pid, materialInfo, pushOperate.material.flow);
 
                 await transaction.insert(this.tableName, newAuditors);
                 await transaction.commit();
@@ -748,6 +759,8 @@ module.exports = app => {
                     hs_m_tp: this.ctx.helper.add(this.ctx.helper.round(this.ctx.helper.mul(materialInfo.m_tp, 1+materialInfo.rate/100), material_decimal.tp), this.ctx.helper.round(this.ctx.helper.mul(materialInfo.ex_tp, 1+materialInfo.exponent_rate/100), material_decimal.tp)),
                 };
                 await this.ctx.helper.sendWechat(audit.aid, smsTypeConst.const.TC, smsTypeConst.judge.approval.toString(), wxConst.template.material, wechatData);
+                // 检查三方特殊推送
+                await this.ctx.service.specMsg.addMaterialMsg(transaction, pid, materialInfo, pushOperate.material.flow);
                 await transaction.commit();
             } catch (err) {
                 await transaction.rollback();

+ 35 - 0
app/service/report.js

@@ -533,6 +533,7 @@ module.exports = app => {
             return rst;
         }
 
+        // params = { tender_id: int, detail_id: int }
         async payment_safe(params, sourceFilters, memFieldKeys, customDefine, customSelect) {
             const RptPaymentSafe = require('../lib/rm/payment_safe');
             const rptPaymentSafe = new RptPaymentSafe(this.ctx);
@@ -540,6 +541,7 @@ module.exports = app => {
             return rptPaymentSafe.getReportData(params, sourceFilters, memFieldKeys, customDefine, customSelect);
         }
 
+        // params = { tender_id: int, detail_id: int }
         async payment(params, sourceFilters, memFieldKeys, customDefine, customSelect) {
             const RptPayment = require('../lib/rm/payment');
             const rptPayment = new RptPayment(this.ctx);
@@ -547,6 +549,7 @@ module.exports = app => {
             return rptPayment.getReportData(params, sourceFilters, memFieldKeys, customDefine, customSelect);
         }
 
+        // params = { sp_id: int, budget_id: int }
         async budget(params, sourceFilters, memFieldKeys, customDefine, customSelect) {
             const RptPayment = require('../lib/rm/budget');
             const rptPayment = new RptPayment(this.ctx);
@@ -554,6 +557,38 @@ module.exports = app => {
             return rptPayment.getReportData(params, sourceFilters, memFieldKeys, customDefine, customSelect);
         }
 
+        // params = { change_id: uuid }
+        async change(params, sourceFilters, memFieldKeys, customDefine, customSelect) {
+            const RptPayment = require('../lib/rm/change');
+            const rptPayment = new RptPayment(this.ctx);
+
+            return rptPayment.getReportData(params, sourceFilters, memFieldKeys, customDefine, customSelect);
+        }
+
+        // params = { change_plan_id: int }
+        async changePlan(params, sourceFilters, memFieldKeys, customDefine, customSelect) {
+            const RptPayment = require('../lib/rm/change_plan');
+            const rptPayment = new RptPayment(this.ctx);
+
+            return rptPayment.getReportData(params, sourceFilters, memFieldKeys, customDefine, customSelect);
+        }
+
+        // params = { change_project_id: int }
+        async changeProject(params, sourceFilters, memFieldKeys, customDefine, customSelect) {
+            const RptPayment = require('../lib/rm/change_project');
+            const rptPayment = new RptPayment(this.ctx);
+
+            return rptPayment.getReportData(params, sourceFilters, memFieldKeys, customDefine, customSelect);
+        }
+
+        // params = { change_apply_id: int }
+        async changeApply(params, sourceFilters, memFieldKeys, customDefine, customSelect) {
+            const RptPayment = require('../lib/rm/change_apply');
+            const rptPayment = new RptPayment(this.ctx);
+
+            return rptPayment.getReportData(params, sourceFilters, memFieldKeys, customDefine, customSelect);
+        }
+
         async getReportData(source_type, params, sourceFilters, memFieldKeys, customDefine, customSelect) {
             const sourceType = sourceTypeConst.sourceTypeData.find(x => { return x.id === source_type; });
             if (!sourceType && !this[sourceType.key]) return {};

+ 6 - 4
app/service/settle.js

@@ -174,8 +174,10 @@ module.exports = app => {
             try {
                 const settleInfo = await this.getDataById(id);
                 await transaction.delete(this.tableName, { id });
-                await transaction.delete(this.ctx.service.settleAudit.tableName, { sid: id });
-                // await transaction.delete(this.ctx.service.settleAuditAss.tableName, { sid: id });
+                await transaction.delete(this.ctx.service.settleAudit.tableName, { settle_id: id });
+                await transaction.delete(this.ctx.service.settleBills.tableName, { settle_id: id });
+                await transaction.delete(this.ctx.service.settlePos.tableName, { settle_id: id });
+                await transaction.delete(this.ctx.service.settleSelect.tableName, { settle_id: id });
                 // 记录删除日志
                 await this.ctx.service.projectLog.addProjectLog(transaction, projectLogConst.type.settle, projectLogConst.status.delete, `第${settleInfo.settle_order}期`);
                 await transaction.commit();
@@ -399,9 +401,9 @@ module.exports = app => {
             const settleObj = new SettleObj(this.ctx);
             const [settleBills, settlePos, settleSum] = await settleObj.doSettle(settle);
             await transaction.delete(this.ctx.service.settleBills.tableName, { settle_id: settle.id });
-            await transaction.insert(this.ctx.service.settleBills.tableName, settleBills);
+            if (settleBills.length > 0) await transaction.insert(this.ctx.service.settleBills.tableName, settleBills);
             await transaction.delete(this.ctx.service.settlePos.tableName, { settle_id: settle.id });
-            await transaction.insert(this.ctx.service.settlePos.tableName, settlePos);
+            if (settlePos.length > 0) await transaction.insert(this.ctx.service.settlePos.tableName, settlePos);
             return settleSum;
         }
     }

+ 3 - 1
app/service/settle_audit.js

@@ -238,6 +238,7 @@ module.exports = app => {
             });
             // 添加其他参与人
             for (const a of auditors) {
+                if (a.audit_order === 0) continue;
                 newAuditors.push({
                     tid: newSettle.tid, settle_id: newSettle.id,
                     audit_id: a.id,
@@ -762,7 +763,7 @@ module.exports = app => {
                 const updateData = settle.curAuditors.map(x => {
                     return {
                         id: x.id, audit_status: auditConst.settle.status.uncheck,
-                        audit_time: null, opinion: null,
+                        audit_time: null, opinion: '',
                     }
                 });
                 await transaction.updateRows(this.tableName, updateData);
@@ -986,6 +987,7 @@ module.exports = app => {
             // 3.审批人撤回审批退回上一人,并删除退回人,增加流程,并回到它审批中,并更新计量期状态为审批中
             // 4.审批人撤回退回原报操作,删除新增的审批流,增加流程,回滚到它审批中
             // 5.会签审批人撤回审批通过(还有其他审批人未审批通过),仅修改本人流程状态
+            console.log(settle.cancancel);
             if (settle.cancancel === 5) {
                 await this._auditCheckCancelAnd(settle);
             } else {

+ 33 - 3
app/service/spec_msg.js

@@ -59,6 +59,18 @@ module.exports = app => {
             await transaction.insert(this.tableName, { pid, tid: stage.tid, sid: stage.id, timing });
         }
 
+        async addAdvanceMsg(transaction, pid, advance, timing) {
+            const needMsg = await this.tenderNeedMsg(pid, advance.id, timing);
+            if (!needMsg) return;
+            await transaction.insert(this.tableName, { pid, tid: advance.tid, advance_id: advance.id, timing });
+        }
+
+        async addMaterialMsg(transaction, pid, material, timing) {
+            const needMsg = await this.tenderNeedMsg(pid, material.tid, timing);
+            if (!needMsg) return;
+            await transaction.insert(this.tableName, { pid, tid: material.tid, material_id: material.id, timing });
+        }
+
         async addSettleMsg(transaction, pid, settle, timing) {
             const needMsg = await this.tenderNeedMsg(pid, settle.tid, timing);
             if (!needMsg) return;
@@ -71,13 +83,31 @@ module.exports = app => {
             await transaction.insert(this.tableName, { pid, tid: change.tid, cid: change.cid, timing });
         }
 
-        async addReportMsg(transaction, pid, tender, stage, timing) {
+        async addChangeApplyMsg(transaction, pid, change_apply, timing) {
+            const needMsg = await this.tenderNeedMsg(pid, change_apply.tid, timing);
+            if (!needMsg) return;
+            await transaction.insert(this.tableName, { pid, tid: change_apply.tid, c_apply_id: change_apply.id, timing });
+        }
+
+        async addChangeProjectMsg(transaction, pid, change_project, timing) {
+            const needMsg = await this.tenderNeedMsg(pid, change_project.tid, timing);
+            if (!needMsg) return;
+            await transaction.insert(this.tableName, { pid, tid: change_project.tid, c_proj_id: change_project.id, timing });
+        }
+
+        async addChangePlanMsg(transaction, pid, change_plan, timing) {
+            const needMsg = await this.tenderNeedMsg(pid, change_plan.tid, timing);
+            if (!needMsg) return;
+            await transaction.insert(this.tableName, { pid, tid: change_plan.tid, c_plan_id: change_plan.id, timing });
+        }
+
+        async addReportMsg(transaction, pid, tender, stage, timing, subInfo) {
             const needMsg = await this.tenderNeedMsg(pid, stage.tid, timing);
             if (!needMsg) return;
             if (transaction) {
-                await transaction.insert(this.tableName, { pid, tid: tender.id, sid: stage ? stage.id : 0, timing });
+                await transaction.insert(this.tableName, { pid, tid: tender.id, sid: stage ? stage.id : 0, timing, extra_info: JSON.stringify(subInfo || {}) });
             } else {
-                await this.db.insert(this.tableName, { pid, tid: tender.id, sid: stage ? stage.id : 0, timing });
+                await this.db.insert(this.tableName, { pid, tid: tender.id, sid: stage ? stage.id : 0, timing, extra_info: JSON.stringify(subInfo || {}) });
             }
         }
     }

+ 30 - 4
app/service/stage_change.js

@@ -14,10 +14,11 @@ const timesLen = audit.stage.timesLen;
 const changeConst = require('../const/change');
 
 class autoUseChange {
-    constructor(helper, info) {
+    constructor(helper, info, settleStatus) {
         this.helper = helper;
         this.precision = info.precision;
         this.decimal = info.decimal;
+        this.settleStatus = settleStatus;
 
         this.insertBills = [];
         this.insertPos = [];
@@ -50,9 +51,20 @@ class autoUseChange {
     findBillsPos(changeBills){
         if (changeBills.gcl_id) {
             const node = this.ledgerTree.datas.find(x => {return x.id === changeBills.gcl_id});
+            if (node.settle_status === this.settleStatus.finish) return null;
+
             const posData = this.pos.getLedgerPos(node.id) || [];
             const changePos = posData.find(x => { return x.name === changeBills.bwmx; });
-            return { bills: node, lid: node.id, pid: changePos ? changePos.id : (posData.length > 0 ? posData[0].id : '-1') };
+            if (changePos.settle_status) return null;
+
+            let defaultPos;
+            if (posData.length > 0) {
+                defaultPos = posData.length > 0 ? posData.find(x => { return !x.settle_status}) : null;
+                if (!defaultPos) return null;
+            } else {
+                defaultPos = { id: '-1' };
+            }
+            return { bills: node, lid: node.id, pid: changePos ? changePos.id : defaultPos.id };
         } else {
             const cb = {
                 b_code: changeBills.code || '',
@@ -63,6 +75,7 @@ class autoUseChange {
             };
             for (const node of this.ledgerTree.nodes) {
                 if (node.children && node.children.length > 0) continue;
+                if (node.settle_status === this.settleStatus.finish) return null;
 
                 const b = {
                     b_code: node.b_code || '',
@@ -73,7 +86,14 @@ class autoUseChange {
                 };
                 if (this.helper._.isMatch(cb, b)) {
                     const posData = this.pos.getLedgerPos(node.id) || [];
-                    return { bills: node, lid: node.id, pid: posData.length > 0 ? posData[0].id : '-1' };
+                    let defaultPos;
+                    if (posData.length > 0) {
+                        defaultPos = posData.length > 0 ? posData.find(x => { return !x.settle_status}) : null;
+                        if (!defaultPos) return null;
+                    } else {
+                        defaultPos = { id: '-1' };
+                    }
+                    return { bills: node, lid: node.id, pid: defaultPos.id };
                 }
             }
             return null;
@@ -795,17 +815,23 @@ module.exports = app => {
                 where: { tender_id: stage.tid },
             });
             const extraData = await this.ctx.service.ledgerExtra.getData(this.ctx.tender.id, ['is_tp']);
+            const settleStatusBills = stage.readySettle ? await this.ctx.service.settleBills.getAllDataByCondition({ where: { settle_id: stage.readySettle.id }}) : [];
             this.ctx.helper.assignRelaData(ledgerData, [
                 { data: extraData, fields: ['is_tp'], prefix: '', relaId: 'id' },
+                { data: settleStatusBills, fields: ['settle_status'], prefix: '', relaId: 'lid' },
             ]);
 
             const posData = await this.ctx.service.pos.getAllDataByCondition({
                 columns: ['id', 'lid', 'name', 'porder'],
                 where: { tid: stage.tid },
             });
+            const settleStatusPos = stage.readySettle ? await this.ctx.service.settlePos.getAllDataByCondition({ where: { settle_id: stage.readySettle.id }}) : [];
+            this.ctx.helper.assignRelaData(posData, [
+                { data: settleStatusPos, fields: ['settle_status'], prefix: '', relaId: 'pid' },
+            ]);
             const stageBills = await this.ctx.service.stageBills.getAllDataByCondition({ where: { sid: stage.id } });
             const stagePos = await this.ctx.service.stagePos.getAllDataByCondition({ where: { sid: stage.id } });
-            const useModal = new autoUseChange(this.ctx.helper, tender.info);
+            const useModal = new autoUseChange(this.ctx.helper, tender.info, this.ctx.service.settle.settleStatus);
             useModal.use({ledgerData, posData, stageBills, stagePos, default: { tid: stage.tid, sid: stage.id, said: this.ctx.session.sessionUser.accountId } }, validChangeBills);
 
             // if (useModal.insertChange.length === 0) return '无可调用的清单或计量单元';

+ 19 - 5
app/service/stage_stash.js

@@ -13,6 +13,7 @@ class loadStageExcelTree {
         this.ctx = ctx;
 
         this.decimal = ctx.tender.info.decimal;
+        this.settleStatus === ctx.service.settle.settleStatus;
 
         this.insertBills = [];
         this.insertPos = [];
@@ -66,7 +67,7 @@ class loadStageExcelTree {
             for (const p of node.pos) {
                 if (!p.contract_qty) continue;
                 const sp = sourcePos.find(x => { return x.name === p.name; });
-                if (!sp) continue;
+                if (!sp || sp.settle_status === this.settleStatus.finish) continue;
 
                 contract_qty = this.ctx.helper.add(contract_qty, p.contract_qty);
                 let ssp = sourceStagePos.find(x => { return x.pid === sp.id; });
@@ -123,7 +124,7 @@ class loadStageExcelTree {
         node.is_leaf = !node.children || node.children.length === 0 ? 1 : 0;
         node.has_pos = node.pos && node.pos.length > 0;
         const cur = this.findNode(node, parent);
-        if (!cur) return;
+        if (!cur || cur.settle_status === this.settleStatus.finish) return;
 
         if (cur) {
             if (!node.b_code) this.loadDgn(node, cur);
@@ -226,18 +227,25 @@ module.exports = app => {
         async reCalcStashData(stage, data) {
             const decimal = this.ctx.tender.info.decimal;
             const insertBillsData = [], insertPosData = [], insertChangeData = [];
+            const settleStatus = this.ctx.service.settle.settleStatus;
 
             const bills = await this.ctx.service.ledger.getAllDataByCondition({ where: { tender_id: stage.tid, is_leaf: true } });
             const extraData = await this.ctx.service.ledgerExtra.getData(stage.tid, ['id', 'is_tp']);
+            const settleStatusBills = stage.readySettle ? await this.ctx.service.settleBills.getAllDataByCondition({ where: { settle_id: stage.readySettle.id }}) : [];
             this.ctx.helper.assignRelaData(bills, [
                 { data: extraData, fields: ['is_tp'], prefix: '', relaId: 'id' },
+                { data: settleStatusBills, fields: ['settle_status'], prefix: '', relaId: 'lid' },
             ]);
             const pos = await this.ctx.service.pos.getAllDataByCondition({ where: { tid: stage.tid } });
+            const settleStatusPos = stage.readySettle ? await this.ctx.service.settlePos.getAllDataByCondition({ where: { settle_id: stage.readySettle.id }}) : [];
+            this.ctx.helper.assignRelaData(pos, [
+                { data: settleStatusPos, fields: ['settle_status'], prefix: '', relaId: 'pid' },
+            ]);
 
             const said = this.ctx.session.sessionUser.accountId;
             for (const d of data) {
                 const b = bills.find(x => { return x.id === d.lid });
-                if (!b) continue;
+                if (!b || b.settle_status === settleStatus.finish) continue;
 
                 const nbs = {
                     tid: stage.tid, sid: stage.id, said, lid: b.id, times: 1, order: 0,
@@ -247,7 +255,7 @@ module.exports = app => {
                 if (d.pos) {
                     for (const bp of d.pos) {
                         const p = pos.find(x => { return x.id === bp.pid});
-                        if (!p) continue;
+                        if (!p || p.settle_status === settleStatus.finish) continue;
 
                         const nps = { tid: stage.tid, sid: stage.id, said, lid: b.id, pid: p.id, times: 1, order: 0 };
                         nps.contract_qty = this.ctx.helper.round(bp.contract_qty, decimal.qty);
@@ -366,19 +374,25 @@ module.exports = app => {
                     where: { tender_id: stage.tid},
                 });
                 const extraData = await this.ctx.service.ledgerExtra.getData(this.ctx.tender.id, ['is_tp']);
+                const settleStatusBills = stage.readySettle ? await this.ctx.service.settleBills.getAllDataByCondition({ where: { settle_id: stage.readySettle.id }}) : [];
                 this.ctx.helper.assignRelaData(ledgerData, [
                     { data: extraData, fields: ['is_tp'], prefix: '', relaId: 'id' },
+                    { data: settleStatusBills, fields: ['settle_status'], prefix: '', relaId: 'lid' },
                 ]);
                 const posData = await this.ctx.service.pos.getAllDataByCondition({
                     columns: ['id', 'lid', 'name', 'porder'],
                     where: { tid: stage.tid },
                 });
+                const settleStatusPos = stage.readySettle ? await this.ctx.service.settlePos.getAllDataByCondition({ where: { settle_id: stage.readySettle.id }}) : [];
+                this.ctx.helper.assignRelaData(posData, [
+                    { data: settleStatusPos, fields: ['settle_status'], prefix: '', relaId: 'pid' },
+                ]);
                 const stageBills = await this.ctx.service.stageBills.getAllDataByCondition({ where: { sid: stage.id } });
                 const stagePos = await this.ctx.service.stagePos.getAllDataByCondition({ where: { sid: stage.id } });
                 const stageBillsDgn = await this.ctx.service.stageBillsDgn.getAllDataByCondition({ where: { tid: stage.tid } });
 
                 const loadModal = new loadStageExcelTree(this.ctx);
-                loadModal.load(cacheTree, {ledgerData, posData, stageBills, stagePos, stageBillsDgn, default: { tid: stage.tid, sid: stage.id, said: this.ctx.session.sessionUser.accountId } });
+                loadModal.load(cacheTree, { ledgerData, posData, stageBills, stagePos, stageBillsDgn, default: { tid: stage.tid, sid: stage.id, said: this.ctx.session.sessionUser.accountId } });
 
                 const conn = await this.db.beginTransaction();
                 try {

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

@@ -52,9 +52,9 @@
                         <thead>
                         <tr class="text-center">
                             <th width="60px">选择</th>
-                            <th>文件名称</th>
+                            <th>文件名称 <span name="file-sort" field="filename" tag="filename|desc"><i class="fa fa-sort" aria-hidden="true"></i></span></th>
                             <th width="10%">上传人</th>
-                            <th width="20%">上传时间</th>
+                            <th width="20%">上传时间 <span name="file-sort" field="create_time" tag="create_time|asc"><i class="fa fa-sort-amount-desc" aria-hidden="true"></i></span></th>
                             <th width="10%">文件类型</th>
                         </tr>
                         </thead>

+ 2 - 2
app/view/report/index_archive.ejs

@@ -96,8 +96,8 @@
                         </div>
                     </div>
                     <div class="print-view form-view">
-                        <div class="pageContainer" id="iframe_made">
-                            <iframe src="/archive/pdf/show"  class="sjs-height-0 border-0" width="100%"></iframe>
+                        <div class="pageContainer sjs-height-1" id="iframe_made">
+                            <iframe src="/archive/pdf/show" class="border-0" height="100%" width="100%"></iframe>
                         </div>
                     </div>
                 </div>

+ 2 - 2
app/view/report/index_sign.ejs

@@ -91,8 +91,8 @@
                         </div>
                     </div>
                     <div class="print-view form-view">
-                        <div class="pageContainer" id="iframe_made">
-                            <iframe src="/archive/pdf/show"  class="sjs-height-0 border-0" width="100%"></iframe>
+                        <div class="pageContainer sjs-height-1" id="iframe_made">
+                            <iframe src="/archive/pdf/show" class="border-0" height="100%" width="100%"></iframe>
                         </div>
                     </div>
                 </div>

+ 2 - 2
app/view/settle/audit_btn.ejs

@@ -2,7 +2,7 @@
     <% if (ctx.settle.audit_status === auditConst.status.uncheck) { %>
         <% if (ctx.session.sessionUser.accountId === ctx.settle.user_id) { %>
             <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>
-            <% if (ctx.settle.order === ctx.settle.highOrder) { %>
+            <% if (ctx.settle.settle_order === ctx.settle.highOrder) { %>
                 <a href="#del-qi" data-toggle="modal" data-target="#del-qi" class="btn btn-outline-danger btn-sm btn-block mt-5">删除本期</a>
             <% } %>
         <% } else { %>
@@ -31,7 +31,7 @@
         <a href="#sp-list"  data-type="hide" data-toggle="modal" data-target="#sp-list" class="btn btn-outline-warning btn-sm btn-block text-muted sp-list-btn">审批退回</a>
         <% if (ctx.session.sessionUser.accountId === ctx.settle.user_id) { %>
             <a href="#sp-list" data-type="show" data-toggle="modal" data-target="#sp-list"  class="btn btn-primary btn-sm btn-block sp-list-btn">重新上报</a>
-            <% if (ctx.settle.order === ctx.settle.highOrder) { %>
+            <% if (ctx.settle.settle_order === ctx.settle.highOrder) { %>
                 <a href="#del-qi" data-toggle="modal" data-target="#del-qi" class="btn btn-outline-danger btn-sm btn-block mt-5">删除本期</a>
             <% } %>
         <% } %>

+ 2 - 2
app/view/settle/audit_modal.ejs

@@ -573,11 +573,11 @@
                 <h5 class="modal-title">删除期</h5>
             </div>
             <div class="modal-body">
-                <h5>确认删除「第<%= ctx.settle.order %>期」?</h5>
+                <h5>确认删除「第<%= ctx.settle.settle_order %>期」?</h5>
                 <h5>删除后,数据无法恢复,请谨慎操作。</h5>
             </div>
             <div class="modal-footer">
-                <input type="hidden" name="stage_id" value="<%= ctx.settle.id %>">
+                <input type="hidden" name="settle_id" value="<%= ctx.settle.id %>">
                 <input type="hidden" name="_csrf_j" value="<%= ctx.csrf %>" />
                 <button type="button" class="btn btn-secondary btn-sm" data-dismiss="modal">取消</button>
                 <button type="submit" class="btn btn-danger btn-sm">确定删除</button>

+ 4 - 1
app/view/settle/index.ejs

@@ -114,7 +114,10 @@
     const settleStatusColor = JSON.parse('<%- JSON.stringify(settleStatusColor )%>');
     const billsSpreadSetting = {
         cols: [
-            {title: '结算状态', colSpan: '1', rowSpan: '2', field: 'settle_status', hAlign: 1, width: 60, formatter: '@', readOnly: true, getValue: function(data) { return data.b_code ? '' : settleStatusHint[data.settle_status] || '' }},
+            {title: '结算状态', colSpan: '1', rowSpan: '2', field: 'settle_status', hAlign: 1, width: 60, formatter: '@', readOnly: true, getValue: function(data) {
+                // return data.b_code ? '' : settleStatusHint[data.settle_status] || ''
+                return settleStatusHint[data.settle_status] || '';
+            }},
             {title: '项目节编号', colSpan: '1', rowSpan: '2', field: 'code', hAlign: 0, width: 145, formatter: '@', readOnly: true, cellType: 'tree'},
             {title: '清单编号', colSpan: '1', rowSpan: '2', field: 'b_code', hAlign: 0, width: 70, formatter: '@', readOnly: true},
             {title: '名称', colSpan: '1', rowSpan: '2', field: 'name', hAlign: 0, width: 185, formatter: '@', readOnly: true},

+ 34 - 31
app/view/settle/select.ejs

@@ -47,7 +47,7 @@
                 </div>
             </div>
             <div id="right-view" class="c-body" style="display: none; width: 33%;">
-                <div class="resize-x" id="right-spr" r-Type="width" div1="#left-view" div2="#right-view" title="调整大小" a-type="percent"><!--调整左右高度条--></div>
+                <div class="resize-x" id="right-spr" r-Type="width" div1="#left-view" div2="#right-view" title="调整大小" a-type="percent"></div>
                 <div class="tab-content">
                     <!--查找定位-->
                     <div id="search" class="tab-pane tab-select-show">
@@ -100,28 +100,31 @@
     const billsSpreadSetting = {
         cols: [
             {title: '选择', colSpan: '1', rowSpan: '2', field: 'selected', hAlign: 1, width: 30, formatter: '@', cellType: 'checkbox'},
-            {title: '结算状态', colSpan: '1', rowSpan: '2', field: 'settle_status', hAlign: 1, width: 60, formatter: '@', readOnly: true, getValue: function(data) { return data.b_code ? '' : (settleStatusHint[data.settle_status] || '') }},
-            {title: '项目节编号', colSpan: '1', rowSpan: '2', field: 'code', hAlign: 0, width: 145, formatter: '@', readOnly: true, cellType: 'tree'},
-            {title: '清单编号', colSpan: '1', rowSpan: '2', field: 'b_code', hAlign: 0, width: 70, formatter: '@', readOnly: true},
-            {title: '名称', colSpan: '1', rowSpan: '2', field: 'name', hAlign: 0, width: 185, formatter: '@', readOnly: true},
-            {title: '单位', colSpan: '1', rowSpan: '2', field: 'unit', hAlign: 1, width: 60, formatter: '@', readOnly: true, cellType: 'unit'},
-            {title: '单价', colSpan: '1', rowSpan: '2', field: 'unit_price', hAlign: 2, width: 60, readOnly: true, type: 'Number'},
-            {title: '台账|数量', colSpan: '2|1', rowSpan: '1|1', field: 'quantity', hAlign: 2, width: 60, readOnly: true, type: 'Number'},
-            {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'total_price', hAlign: 2, width: 60, readOnly: true, type: 'Number'},
-            {title: '累计合同计量|数量', colSpan: '2|1', rowSpan: '1|1', field: 'end_contract_qty', hAlign: 2, width: 60, readOnly: true, type: 'Number'},
-            {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'end_contract_tp', hAlign: 2, width: 60, readOnly: true, type: 'Number'},
-            {title: '累计数量变更|数量', colSpan: '2|1', rowSpan: '1|1', field: 'end_qc_qty', hAlign: 2, width: 60, readOnly: true, type: 'Number'},
-            {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'end_qc_tp', hAlign: 2, width: 60, readOnly: true, type: 'Number'},
-            {title: '累计完成计量|数量', colSpan: '3|1', rowSpan: '1|1', field: 'end_gather_qty', hAlign: 2, width: 60, readOnly: true, type: 'Number'},
-            {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'end_gather_tp', hAlign: 2, width: 60, readOnly: true, type: 'Number'},
-            {title: '|完成率(%)', colSpan: '1', rowSpan: '|1', field: 'end_final_1_percent', hAlign: 2, width: 80, readOnly: true, type: 'Number'},
-            {title: '图(册)号', colSpan: '1', rowSpan: '2', field: 'drawing_code', hAlign: 0, width: 80, formatter: '@', readOnly: true},
-            {title: '备注', colSpan: '1', rowSpan: '2', field: 'memo', hAlign: 0, width: 100, formatter: '@', cellType: 'ellipsisAutoTip', readOnly: true},
+            {title: '结算状态', colSpan: '1', rowSpan: '2', field: 'settle_status', hAlign: 1, width: 60, formatter: '@', getValue: function(data) {
+                //return data.b_code ? '' : (settleStatusHint[data.settle_status] || '')
+                return settleStatusHint[data.settle_status] || '';
+            }},
+            {title: '项目节编号', colSpan: '1', rowSpan: '2', field: 'code', hAlign: 0, width: 145, formatter: '@', cellType: 'tree'},
+            {title: '清单编号', colSpan: '1', rowSpan: '2', field: 'b_code', hAlign: 0, width: 70, formatter: '@'},
+            {title: '名称', colSpan: '1', rowSpan: '2', field: 'name', hAlign: 0, width: 185, formatter: '@'},
+            {title: '单位', colSpan: '1', rowSpan: '2', field: 'unit', hAlign: 1, width: 60, formatter: '@', cellType: 'unit'},
+            {title: '单价', colSpan: '1', rowSpan: '2', field: 'unit_price', hAlign: 2, width: 60, type: 'Number'},
+            {title: '台账|数量', colSpan: '2|1', rowSpan: '1|1', field: 'quantity', hAlign: 2, width: 60, type: 'Number'},
+            {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'total_price', hAlign: 2, width: 60, type: 'Number'},
+            {title: '累计合同计量|数量', colSpan: '2|1', rowSpan: '1|1', field: 'end_contract_qty', hAlign: 2, width: 60, type: 'Number'},
+            {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'end_contract_tp', hAlign: 2, width: 60, type: 'Number'},
+            {title: '累计数量变更|数量', colSpan: '2|1', rowSpan: '1|1', field: 'end_qc_qty', hAlign: 2, width: 60, type: 'Number'},
+            {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'end_qc_tp', hAlign: 2, width: 60, type: 'Number'},
+            {title: '累计完成计量|数量', colSpan: '3|1', rowSpan: '1|1', field: 'end_gather_qty', hAlign: 2, width: 60, type: 'Number'},
+            {title: '|金额', colSpan: '|1', rowSpan: '|1', field: 'end_gather_tp', hAlign: 2, width: 60, type: 'Number'},
+            {title: '|完成率(%)', colSpan: '1', rowSpan: '|1', field: 'end_final_1_percent', hAlign: 2, width: 80, type: 'Number'},
+            {title: '图(册)号', colSpan: '1', rowSpan: '2', field: 'drawing_code', hAlign: 0, width: 80, formatter: '@'},
+            {title: '备注', colSpan: '1', rowSpan: '2', field: 'memo', hAlign: 0, width: 100, formatter: '@', cellType: 'ellipsisAutoTip'},
             <% if (ctx.session.sessionProject.gxby) { %>
-            {title: '工序报验', colSpan: '1', rowSpan: '2', field: 'gxby', hAlign: 1, width: 80, formatter: '@', readOnly: true},
+            {title: '工序报验', colSpan: '1', rowSpan: '2', field: 'gxby', hAlign: 1, width: 80, formatter: '@'},
             <% } %>
             <% if (ctx.session.sessionProject.dagl) { %>
-            {title: '档案管理', colSpan: '1', rowSpan: '2', field: 'dagl', hAlign: 1, width: 80, formatter: '@', readOnly: true},
+            {title: '档案管理', colSpan: '1', rowSpan: '2', field: 'dagl', hAlign: 1, width: 80, formatter: '@'},
             <% } %>
         ],
         emptyRows: 0,
@@ -132,7 +135,7 @@
         font: '12px 微软雅黑',
         frozenColCount: 5,
         frozenLineColor: '#93b5e4',
-        readOnly,
+        readOnly: true,
         getForeColor: function(sheet, data, row, col, foreColor) {
             if (col.field === 'settle_status') {
                 return data ? settleStatusColor[data.settle_status] || foreColor : foreColor;
@@ -144,19 +147,19 @@
     const posSpreadSetting = {
         cols: [
             {title: '选择', colSpan: '1', rowSpan: '2', field: 'selected', hAlign: 0, width: 30, formatter: '@', cellType: 'checkbox'},
-            {title: '结算状态', colSpan: '1', rowSpan: '2', field: 'settle_status', hAlign: 1, width: 60, formatter: '@', readOnly: true, getValue: function(data) { return settleStatusHint[data.settle_status] || '' }},
-            {title: '计量单元', colSpan: '1', rowSpan: '2', field: 'name', hAlign: 0, width: 180, formatter: '@', readOnly: true},
-            {title: '位置', colSpan: '1', rowSpan: '2', field: 'position', hAlign: 0, width: 60, formatter: '@', readOnly: true},
-            {title: '台账数量', colSpan: '1', rowSpan: '2', field: 'quantity', hAlign: 2, width: 60, formatter: '@', readOnly: true},
-            {title: '累计计量|合同', colSpan: '3|1', rowSpan: '1|1', field: 'end_contract_qty', hAlign: 2, width: 60, type: 'Number', readOnly: true},
-            {title: '|数量变更', colSpan: '|1', rowSpan: '|1', field: 'end_qc_qty', hAlign: 2, width: 80, type: 'Number', readOnly: true},
-            {title: '|完成', colSpan: '|1', rowSpan: '|1', field: 'end_gather_qty', hAlign: 2, width: 60, type: 'Number', readOnly: true},
+            {title: '结算状态', colSpan: '1', rowSpan: '2', field: 'settle_status', hAlign: 1, width: 60, formatter: '@', getValue: function(data) { return settleStatusHint[data.settle_status] || '' }},
+            {title: '计量单元', colSpan: '1', rowSpan: '2', field: 'name', hAlign: 0, width: 180, formatter: '@'},
+            {title: '位置', colSpan: '1', rowSpan: '2', field: 'position', hAlign: 0, width: 60, formatter: '@'},
+            {title: '台账数量', colSpan: '1', rowSpan: '2', field: 'quantity', hAlign: 2, width: 60, formatter: '@'},
+            {title: '累计计量|合同', colSpan: '3|1', rowSpan: '1|1', field: 'end_contract_qty', hAlign: 2, width: 60, type: 'Number'},
+            {title: '|数量变更', colSpan: '|1', rowSpan: '|1', field: 'end_qc_qty', hAlign: 2, width: 80, type: 'Number'},
+            {title: '|完成', colSpan: '|1', rowSpan: '|1', field: 'end_gather_qty', hAlign: 2, width: 60, type: 'Number'},
             {title: '图册号', colSpan: '1', rowSpan: '2', field: 'drawing_code', hAlign: 0, width: 80, formatter: '@'},
             <% if (ctx.session.sessionProject.gxby) { %>
-            {title: '工序报验', colSpan: '1', rowSpan: '2', field: 'gxby', hAlign: 1, width: 80, formatter: '@', readOnly: true},
+            {title: '工序报验', colSpan: '1', rowSpan: '2', field: 'gxby', hAlign: 1, width: 80, formatter: '@'},
             <% } %>
             <% if (ctx.session.sessionProject.dagl) { %>
-            {title: '档案管理', colSpan: '1', rowSpan: '2', field: 'dagl', hAlign: 1, width: 80, formatter: '@', readOnly: true},
+            {title: '档案管理', colSpan: '1', rowSpan: '2', field: 'dagl', hAlign: 1, width: 80, formatter: '@'},
             <% } %>
         ],
         emptyRows: 0,
@@ -166,7 +169,7 @@
         defaultRowHeight: 21,
         headerFont: '12px 微软雅黑',
         font: '12px 微软雅黑',
-        readOnly,
+        readOnly: true,
         getForeColor: function(sheet, data, row, col, foreColor) {
             if (col.field === 'settle_status') {
                 return data ? settleStatusColor[data.settle_status] || foreColor : foreColor;

+ 2 - 2
app/view/tender/detail_modal.ejs

@@ -448,7 +448,7 @@
                                     <div class="col-12 mb-2">
                                         <div class="input-group input-group-sm">
                                             <div class="input-group-prepend">
-                                                <span class="input-group-text">业主控制价</span>
+                                                <span class="input-group-text">招标清单预算</span>
                                             </div>
                                             <input type="number" class="form-control nospin" value="" id="control-price" onchange="checkNumberValid(this)">
                                             <a class="ml-1 btn btn-sm btn-primary" href="/tender/<%= ctx.tender.id %>/ctrl-price"><i class="fa fa-list"></i></a>
@@ -495,7 +495,7 @@
                                     <div class="col-12 mb-2">
                                         <div class="input-group input-group-sm">
                                             <div class="input-group-prepend">
-                                                <span class="input-group-text">招标清单预算</span>
+                                                <span class="input-group-text">标底或最高投标限价</span>
                                             </div>
                                             <input type="number" class="form-control nospin" value="" id="bid-yu-price" onchange="checkNumberValid(this)">
                                         </div>

+ 9 - 2
db_script/test_query.js

@@ -12,8 +12,8 @@ const saveJSON = async function(obj, file) {
 
 const loadReportArchiveData = async function() {
     //const tid = 4417, sOrder = 2;
-    // const tid = 3698, sOrder = 7;
-    const tid = 5161, sOrder = 11;
+    const tid = 3698, sOrder = 7;
+    // const tid = 5161, sOrder = 11;
     const stage = await querySql('SELECT * FROM zh_stage where tid = ? and `order` = ?', [tid, sOrder]);
     const rptArchive = await querySql('SELECT * FROM zh_rpt_archive where stage_id = ?', [stage[0].id]);
     for (const ra of rptArchive) {
@@ -29,6 +29,12 @@ const loadReportArchiveData = async function() {
         //     }
         // }
         // await saveJSON(roleContent, BaseUtil.getFileName('roleContent.json'));
+        if (rptArchive.indexOf(ra) === 0) {
+            const rptTpl = await querySql('SELECT * FROM zh_rpt_tpl where id = ?', [ra.content[0].rpt_id]);
+            rptTpl[0].rpt_content = rptTpl[0].rpt_content ? JSON.parse(rptTpl[0].rpt_content) : {};
+            console.log('rptTpl.json');
+            await saveJSON(rptTpl[0], BaseUtil.getFileName('rptTpl.json'));
+        }
     }
     const roleContent = [];
     const rptRole = await querySql('SELECT * FROM zh_role_rpt_rel WHERE sid = ?', [stage[0].id]);
@@ -37,6 +43,7 @@ const loadReportArchiveData = async function() {
     }
     await saveJSON(roleContent, BaseUtil.getFileName('roleContent.json'));
 
+
     const rptSign = await querySql('SELECT * FROM zh_rpt_archive_encryption where stage_id = ?', [stage[0].id]);
     for (const rs of rptSign) {
         rs.content = rs.content ? JSON.parse(rs.content) : [];

+ 13 - 0
sql/update.sql

@@ -31,3 +31,16 @@ ADD COLUMN `settle_order`  tinyint(4) NOT NULL DEFAULT -1 AFTER `settle_id`;
 ALTER TABLE `zh_ledger_attachment`
 ADD COLUMN `settle_id`  int(11) NOT NULL DEFAULT -1 COMMENT '结算id' AFTER `tid`,
 ADD COLUMN `settle_order`  tinyint(4) NOT NULL DEFAULT -1 COMMENT '结算期序号' AFTER `settle_id`;
+
+ALTER TABLE `zh_s2b_spec_msg`
+ADD COLUMN `advance_id`  int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '预付款期id' AFTER `rid`,
+ADD COLUMN `material_id`  int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '材差期id' AFTER `advance_id`,
+ADD COLUMN `c_apply_id`  int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '变更申请id' AFTER `material_id`,
+ADD COLUMN `c_proj_id`  int(11) UNSIGNED NOT NULL COMMENT '变更立项id' AFTER `c_apply_id`,
+ADD COLUMN `c_plan_id`  int(11) UNSIGNED NOT NULL COMMENT '变更方案id' AFTER `c_proj_id`,
+ADD COLUMN `extra_info`  varchar(1000) NOT NULL DEFAULT '' COMMENT '附加信息(主要用于报表)' AFTER `timing`;
+
+ALTER TABLE `zh_s2b_spec_push_log`
+ADD COLUMN `push_3f_id`  varchar(255) NOT NULL DEFAULT '' COMMENT '3方交互key(对方id)' AFTER `multi_content`,
+ADD COLUMN `push_3f_res`  text NULL COMMENT '3方交互,确认结果(对方推送)' AFTER `push_3f_id`,
+ADD COLUMN `push_3f_tag`  varchar(50) NOT NULL DEFAULT '' COMMENT '3方交互标记(关键信息,通过/拒签/过期等)' AFTER `push_3f_res`;