Forráskód Böngészése

Merge branch 'uat'

MaiXinRong 2 éve
szülő
commit
d86aa3d961

+ 31 - 5
app/controller/login_controller.js

@@ -26,6 +26,18 @@ module.exports = app => {
                 ctx.redirect('/wap');
                 return;
             }
+            let projectData = null;
+
+            // 判断是否有编号且存在
+            if (ctx.params.code) {
+                const projectInfo = await ctx.service.project.getProjectByCode(ctx.params.code.toString().trim());
+                if (projectInfo) {
+                    projectData = projectInfo;
+                } else {
+                    ctx.redirect('/');
+                    return;
+                }
+            }
 
             const errorMessage = ctx.session.loginError;
             // 显示完删除
@@ -37,6 +49,7 @@ module.exports = app => {
                 await ctx.service.maintain.syncMaintainData();
             }
             const renderData = {
+                projectData,
                 maintainData,
                 maintainConst,
                 errorMessage,
@@ -178,7 +191,11 @@ module.exports = app => {
             } catch (error) {
                 this.log(error);
                 ctx.session.loginError = error;
-                ctx.redirect('/login');
+                if (ctx.request.body && ctx.request.body.project && parseInt(ctx.request.body.hide_code)) {
+                    ctx.redirect('/login/' + ctx.request.body.project);
+                } else {
+                    ctx.redirect('/login');
+                }
             }
         }
 
@@ -190,8 +207,13 @@ module.exports = app => {
          */
         async logout(ctx) {
             // 删除session并跳转
+            const code = ctx.session.sessionProject.code ? ctx.session.sessionProject.code : null;
             ctx.session = null;
-            ctx.redirect('/');
+            if (code) {
+                ctx.redirect('/login/' + code);
+            } else {
+                ctx.redirect('/');
+            }
         }
 
         /**
@@ -364,7 +386,11 @@ module.exports = app => {
             } catch (error) {
                 this.log(error);
                 ctx.session.loginError = error;
-                ctx.redirect('/login');
+                if (ctx.request.body && ctx.request.body.code) {
+                    ctx.redirect('/login/' + ctx.request.body.code);
+                } else {
+                    ctx.redirect('/login');
+                }
             }
         }
 
@@ -482,7 +508,7 @@ module.exports = app => {
           }
           ctx.body = response;
         }
-        
+
         /**
          * 项目管理授权页面
          *
@@ -558,7 +584,7 @@ module.exports = app => {
           }
           ctx.body = response
         }
-      
+
     }
 
     return LoginController;

+ 42 - 0
app/controller/stage_controller.js

@@ -197,6 +197,7 @@ module.exports = app => {
                 // 收方单附件删除权限
                 renderData.sfAttDelPower = ctx.session.sessionUser.accountId === ctx.stage.user_id || ctx.helper._.findIndex(ctx.stage.auditors2, { aid: ctx.session.sessionUser.accountId }) !== -1;
                 renderData.hintOver = projectFunInfo.hintOver && ctx.tender.info.fun_rela.hintOver;
+                renderData.hintMinusCb = projectFunInfo.banMinusChangeBills;
                 renderData.categoryData = await this.ctx.service.category.getAllCategory(this.ctx.session.sessionProject.id);
                 await this.layout('stage/index.ejs', renderData, 'stage/modal.ejs');
             } catch (err) {
@@ -429,6 +430,15 @@ module.exports = app => {
                     { qty: 'contract_qty', tp: 'contract_tp' }, { qty: 'qc_qty', tp: 'qc_tp' },
                 ], this.ctx.tender.info.decimal, x => { return x.is_tp; });
                 checkData.checkBillsQty(['contract_qty', 'qc_qty']);
+                if (projRela.banMinusChangeBills) {
+                    const change = await this.ctx.service.change.getAllChangeHasMinus(ctx.tender.id);
+                    if (change.length > 0) {
+                        const cid = change.map(x => { return x.cid; });
+                        const changeBills = await this.ctx.service.changeAuditList.getAllDataByCondition({ where: { cid } });
+                        const endStageChange = await this.ctx.service.stageChange.getFinalUsedData(ctx.tender.id, cid);
+                        checkData.checkMinusChangeBills(change, changeBills, endStageChange);
+                    }
+                }
                 ctx.body = { err: 0, msg: '', data: checkData.checkResult };
             } catch (err) {
                 this.log(err);
@@ -436,6 +446,38 @@ module.exports = app => {
             }
         }
 
+        async _checkMinusChangeBills(ctx) {
+            const checkDataModel = require('../lib/ledger').checkData;
+            const checkData = new checkDataModel(ctx, measureType);
+            const change = await this.ctx.service.change.getAllChangeHasMinus(ctx.tender.id);
+            if (change.length > 0) {
+                const cid = change.map(x => { return x.cid; });
+                const changeBills = await this.ctx.service.changeAuditList.getAllDataByCondition({ where: { cid } });
+                const endStageChange = await this.ctx.service.stageChange.getFinalUsedData(ctx.tender.id, cid);
+                checkData.checkMinusChangeBills(change, changeBills, endStageChange);
+            }
+            return checkData.checkResult.error;
+        }
+
+        async stageCheck(ctx) {
+            try {
+                if (!ctx.query.type) throw '参数错误';
+                const type = ctx.query.type.split(',');
+                const result = {};
+                for (const t of type) {
+                    switch (t) {
+                        case 'minus_cb':
+                            result.minus_cb = await this._checkMinusChangeBills(ctx);
+                            break;
+                    }
+                }
+                ctx.body = { err: 0, msg: '', data: result };
+            } catch (err) {
+                this.log(err);
+                ctx.body = this.ajaxErrorBody(err, '检查数据错误');
+            }
+        }
+
         /**
          * 获取期数据(截止上期 & 本期) (Ajax)
          * @param ctx

+ 39 - 1
app/lib/ledger.js

@@ -564,6 +564,10 @@ class pos {
         }
     }
 
+    getPos(id) {
+        return this.items[itemsPre + id];
+    }
+
     getLedgerPos(mid) {
         return this.ledgerPos[itemsPre + mid];
     }
@@ -648,7 +652,6 @@ class checkData {
         return sc ? sc.ratio : null;
     }
 
-
     _getValid = function (type, status, limit) {
         if (limit) {
             const statusConst = type === 'gxby' ? this.ctx.session.sessionProject.gxby_status : this.ctx.session.sessionProject.dagl_status;
@@ -942,6 +945,41 @@ class checkData {
             }
         }
     }
+
+    checkMinusChangeBills(change, changeBills, finalStageChange) {
+        const error = this.checkResult.error;
+        const helper = this.ctx.helper;
+        const changeIndex = {};
+        change.forEach(c => {
+            changeIndex[c.cid] = c;
+            c.bills = [];
+            c.billsIndex = {};
+            c.stageChange = [];
+        });
+        changeBills.forEach(cb => {
+            const c = changeIndex[cb.cid];
+            if (c) c.bills.push(cb);
+            c.billsIndex[cb.id] = cb;
+            cb.used_qty = 0;
+            cb.qty = parseFloat(cb.samount);
+        });
+        finalStageChange.forEach(sc => {
+            if (!sc.qty) return;
+            const c = changeIndex[sc.cid];
+            if (c) {
+                c.used = true;
+                const cb = c.billsIndex[sc.cbid];
+                if (cb) cb.used_qty = helper.add(cb.used_qty, sc.qty);
+            }
+        });
+        change.forEach(c => {
+            if (!c.used) return;
+            c.bills.forEach(b => {
+                if (b.qty >= 0) return;
+                if (!helper.numEqual(b.used_qty, b.qty)) error.push({ b_code: b.code, name: b.name, errorType: 'minus_cb', memo: c.code });
+            });
+        });
+    }
 }
 
 class reviseTree extends billsTree {

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

@@ -2578,20 +2578,21 @@ $(document).ready(() => {
     });
 
     $('#ledger-check2').click(() => {
-        const result = ledgerCheck2({
+        ledgerCheck2({
             ledgerTree: billsTree,
             ledgerPos: pos,
             checkList: checkList,
             decimal: decimal,
             checkOption: checkOption,
+        }).then(result => {
+            check2Viewing({
+                extra: ZhCalc.div(billsTree.datas.length + pos.datas.length, 10000, 0),
+                randomWait: true,
+                prefix: 'check2-',
+                checks: result,
+                checkList: checkList,
+            });
         });
-        check2Viewing({
-            extra: ZhCalc.div(billsTree.datas.length + pos.datas.length, 10000, 0),
-            randomWait: true,
-            prefix: 'check2-',
-            checks: result,
-            checkList: checkList,
-        })
     });
 });
 

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

@@ -291,7 +291,7 @@ const postDataAsync = function (url, data, showWaiting = true) {
         }, err => {
             reject(err);
         }, showWaiting);
-    });
+    }).catch((e) => { console.log(e) });
 };
 
 /**

+ 9 - 8
app/public/js/ledger.js

@@ -3511,20 +3511,21 @@ $(document).ready(function() {
     });
 
     $('#ledger-check2').click(() => {
-        const result = ledgerCheck2({
+        ledgerCheck2({
             ledgerTree: ledgerTree,
             ledgerPos: pos,
             checkList: checkList,
             decimal: tenderInfo.decimal,
             checkOption: checkOption,
+        }).then(result => {
+            check2Viewing({
+                extra: ZhCalc.div(ledgerTree.datas.length + pos.datas.length, 10000, 0),
+                randomWait: true,
+                prefix: 'check2-',
+                checks: result,
+                checkList: checkList,
+            });
         });
-        check2Viewing({
-            extra: ZhCalc.div(ledgerTree.datas.length + pos.datas.length, 10000, 0),
-            randomWait: true,
-            prefix: 'check2-',
-            checks: result,
-            checkList: checkList,
-        })
     });
 
     // 切换附件里节点和所有附件

+ 19 - 7
app/public/js/ledger_check.js

@@ -26,6 +26,7 @@ const ledgerCheckType = {
             { value: 11, text: '遗漏计量(档案管理)', key: 'daglLost', type: 'dagl', },
         ]
     },
+    minus_cb: { value: 12, text: '负变更清单漏计', url: window.location.pathname + '/stageCheck?type=minus_cb' },
 };
 const ledgerCheckUtil = {
     checkSibling: function (ledgerTree, ledgerPos, decimal, option) {
@@ -291,7 +292,7 @@ const ledgerCheckUtil = {
     },
 };
 
-const ledgerCheck2 = function (setting) {
+const ledgerCheck2 = async function (setting) {
     const ledger = setting.ledgerTree, ledgerPos = setting.ledgerPos, decimal = setting.decimal;
     const checkOption = setting.checkOption;
 
@@ -315,17 +316,28 @@ const ledgerCheck2 = function (setting) {
     for (const prop in ledgerCheckType) {
         if (!checkOption[prop] || !checkOption[prop].enable) continue;
 
-        if (ledgerCheckType[prop].items) {
-            const errors = ledgerCheckUtil[ledgerCheckType[prop].fun](ledger, ledgerPos, decimal, checkOption[prop]) || {};
-            for (const i of ledgerCheckType[prop].items) {
+        const checkInfo = ledgerCheckType[prop];
+        if (checkInfo.items) {
+            const errors = ledgerCheckUtil[checkInfo.fun](ledger, ledgerPos, decimal, checkOption[prop]) || {};
+            for (const i of checkInfo.items) {
                 if (checkOption[prop].checkType.indexOf(i.type) < 0) continue;
                 assignWarningData(errors[i.key], i.value, checkData.warning_data);
                 progressData.push({key: prop + i.key, caption: i.text, error: errors[i.key].length});
             }
+        } else if (checkInfo.url) {
+            const errors = await postDataAsync(checkInfo.url, {}, false);
+            if (errors && errors.minus_cb) {
+                errors.minus_cb.forEach(mcb => {
+                    checkData.warning_data.push({
+                        type: checkInfo.value, code: mcb.memo, b_code: mcb.b_code, name: mcb.name,
+                    });
+                });
+            }
+            progressData.push({key: prop, caption: checkInfo.text, error: errors && errors.minus_cb ? errors.minus_cb.length : 0});
         } else {
-            const errors = ledgerCheckUtil[ledgerCheckType[prop].fun](ledger, ledgerPos, decimal, checkOption[prop]) || [];
-            assignWarningData(errors, ledgerCheckType[prop].value, checkData.warning_data);
-            progressData.push({key: prop, caption: ledgerCheckType[prop].text, error: errors.length});
+            const errors = ledgerCheckUtil[checkInfo.fun](ledger, ledgerPos, decimal, checkOption[prop]) || [];
+            assignWarningData(errors, checkInfo.value, checkData.warning_data);
+            progressData.push({key: prop, caption: checkInfo.text, error: errors.length});
         }
     }
     setting.checkList.clearCheckData();

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

@@ -413,5 +413,5 @@ $(document).ready(() => {
         posSpread.refresh();
         gclSpread.refresh();
         leafXmjSpread.refresh();
-    })
+    });
 });

+ 9 - 8
app/public/js/revise.js

@@ -2791,20 +2791,21 @@ $(document).ready(() => {
     });
 
     $('#ledger-check2').click(() => {
-        const result = ledgerCheck2({
+        ledgerCheck2({
             ledgerTree: billsTree,
             ledgerPos: pos,
             checkList: checkList,
             decimal: decimal,
             checkOption: checkOption,
+        }).then(result => {
+            check2Viewing({
+                extra: ZhCalc.div(billsTree.datas.length + pos.datas.length, 10000, 0),
+                randomWait: true,
+                prefix: 'check2-',
+                checks: result,
+                checkList: checkList,
+            });
         });
-        check2Viewing({
-            extra: ZhCalc.div(billsTree.datas.length + pos.datas.length, 10000, 0),
-            randomWait: true,
-            prefix: 'check2-',
-            checks: result,
-            checkList: checkList,
-        })
     });
 
     $('[name=revise-start]').submit(function (e) {

+ 8 - 6
app/public/js/shares/cs_tools.js

@@ -68,9 +68,9 @@ const showSelectTab = function(select, spread, afterShow) {
         if (!setting.spreadSetting) {
             setting.spreadSetting = {
                 cols: [
-                    {title: '行号', field: 'serialNo', width: 50, formatter: '@'},
+                    {title: '行号', field: 'serialNo', width: 50, formatter: '@', hAlign: 1},
                     {
-                        title: '错误类型', field: 'errorType', width: 60, formatter: '@',
+                        title: '错误类型', field: 'errorType', width: 85, formatter: '@',
                         getValue: function (x) {
                             switch (x.errorType) {
                                 case 'gather': return '汇总错误';
@@ -83,12 +83,14 @@ const showSelectTab = function(select, spread, afterShow) {
                                 case 's2b_over_dagl': return '违规计量(档案管理)';
                                 case 's2b_lost_gxby': return '遗漏计量(工序报验)';
                                 case 's2b_lost_dagl': return '遗漏计量(档案管理)';
+                                case 'minus_cb': return '负变更清单漏计';
                                 default: return '';
                             }
                         }
                     },
-                    {title: '清单编号', field: 'b_code', width: 135, formatter: '@'},
-                    {title: '清单名称', field: 'name', width: 215, formatter: '@'},
+                    {title: '清单编号', field: 'b_code', width: 85, formatter: '@'},
+                    {title: '清单名称', field: 'name', width: 165, formatter: '@'},
+                    {title: '备注', field: 'memo', width: 100, formatter: '@'},
                 ],
                 emptyRows: 0,
                 headRows: 1,
@@ -146,7 +148,7 @@ const showSelectTab = function(select, spread, afterShow) {
                     d.serialNo = sourceTree.getNodeIndex(sourceTree.getItems(d.ledger_id)) + 1;
                 }
                 data.sort(function (a, b) {
-                    return a.serialNo - b.serialNo;
+                    return a.serialNo ? (b.serialNo ? a.serialNo - b.serialNo : 1) : 1;
                 });
 
                 SpreadJsObj.loadSheetData(sheet, SpreadJsObj.DataType.Data, data);
@@ -221,7 +223,7 @@ const showSelectTab = function(select, spread, afterShow) {
                         }
                     },
                     {title: '行号', field: 'serialNo', hAlign: 1, width: 40, formatter: '@'},
-                    {title: '项目节编号', field: 'code', width: 80, formatter: '@'},
+                    {title: '项目节编号\n(变更令号)', field: 'code', width: 80, formatter: '@'},
                     {title: '清单编号', field: 'b_code', width: 80, formatter: '@'},
                     {title: '名称', field: 'name', width: 150, formatter: '@'},
                 ],

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

@@ -239,12 +239,9 @@ $(document).ready(() => {
                 return node.is_tp;
             }
         },
-        over: {
-            enable: 1, isTz: checkTzMeasureType(),
-        },
-        limit3f: {
-            enable: 1, checkType: [], status: thirdParty,
-        }
+        over: { enable: 1, isTz: checkTzMeasureType(), },
+        limit3f: { enable: 1, checkType: [], status: thirdParty, },
+        minus_cb: { enable: hintMinusCb },
     };
     if (tender.s2b_gxby_check) checkOption.limit3f.checkType.push('gxby');
     if (tender.s2b_dagl_check) checkOption.limit3f.checkType.push('dagl');
@@ -3799,6 +3796,8 @@ $(document).ready(() => {
                                 }
                             } else if (changeBills.gcl_id) {
                                 const node = stageTree.nodes.find(x => {return x.id === changeBills.gcl_id});
+                                if (!node) return;
+
                                 SpreadJsObj.locateTreeNode(slSpread.getActiveSheet(), node.ledger_id, true);
                                 SpreadJsObj.resetTopAndSelect(spSpread.getActiveSheet());
                                 stagePosSpreadObj.loadCurPosData();
@@ -4542,14 +4541,15 @@ $(document).ready(() => {
         );
     }
     $('#ledger-check2').click(() => {
-        const result = ledgerCheck2(stageCheckerSetting);
-        check2Viewing({
-            extra: ZhCalc.div(stageTree.datas.length + stagePos.datas.length, 10000, 0),
-            randomWait: true,
-            prefix: 'check2-',
-            checks: result,
-            checkList: checkList,
-        })
+        ledgerCheck2(stageCheckerSetting).then(result => {
+            check2Viewing({
+                extra: ZhCalc.div(stageTree.datas.length + stagePos.datas.length, 10000, 0),
+                randomWait: true,
+                prefix: 'check2-',
+                checks: result,
+                checkList: checkList,
+            });
+        });
     });
 
     const dataChecker = DataChecker({

+ 2 - 0
app/router.js

@@ -40,6 +40,7 @@ module.exports = app => {
     const budgetCheck = app.middlewares.budgetCheck();
     // 登入登出相关
     app.get('/login', 'loginController.index');
+    app.get('/login/:code', 'loginController.index');
     app.get('/login/port', api2otherCheck, 'loginController.port');
     app.get('/', 'loginController.index');
     app.get('/logout', 'loginController.logout');
@@ -287,6 +288,7 @@ module.exports = app => {
     app.post('/tender/:id/measure/stage/:order/use-change', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageController.useChange');
     app.post('/tender/:id/measure/stage/:order/auto-use-change', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageController.autoUseChange');
     app.post('/tender/:id/measure/stage/:order/check', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageController.check');
+    app.post('/tender/:id/measure/stage/:order/stageCheck', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageController.stageCheck');
     app.post('/tender/:id/measure/stage/:order/save/cooperation', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageController.saveCooperationData');
     app.post('/tender/:id/measure/stage/:order/im-file/upload', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageController.uploadImFile');
     app.post('/tender/:id/measure/stage/:order/im-file/del', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'stageController.deleteImFile');

+ 5 - 0
app/service/change.js

@@ -1690,6 +1690,11 @@ module.exports = app => {
                 throw err;
             }
         }
+
+        async getAllChangeHasMinus(tenderId) {
+            const sql = `SELECT * FROM ${this.tableName} WHERE tid = ? AND negative_tp < 0 ORDER BY code asc`;
+            return this.db.query(sql, [tenderId]);
+        }
     }
 
     return Change;

+ 3 - 1
app/service/project.js

@@ -11,6 +11,7 @@ const imType = require('../const/tender').imType;
 const defaultFunRela = {
     banOver: true,
     hintOver: true,
+    banMinusChangeBills: false,
     minusNoValue: true,
     imType: imType.zl.value,
     needGcl: false,
@@ -63,6 +64,7 @@ module.exports = app => {
                         imType: {type: 'enum', values: [imType.tz.value, imType.zl.value, imType.bb.value, imType.bw.value], required: true},
                         banOver: {type: 'bool', required: true,},
                         hintOver: {type: 'bool', required: true,},
+                        banMinusChangeBills: {type: 'bool', required: true,},
                         minusNoValue: {type: 'bool', required: true,}
                     };
                     break;
@@ -169,7 +171,7 @@ module.exports = app => {
         async updateFunRela(id, data) {
             const result = await this.db.update(this.tableName, {
                 id: id, fun_rela: JSON.stringify({
-                    banOver: data.banOver, hintOver: data.hintOver,
+                    banOver: data.banOver, hintOver: data.hintOver, banMinusChangeBills: data.banMinusChangeBills,
                     imType: data.imType, needGcl: data.needGcl, minusNoValue: data.minusNoValue,
                 }),
             });

+ 63 - 0
app/service/rpt_gather_memory.js

@@ -156,6 +156,68 @@ const gatherUtils = {
         gatherNode[prefix + "dgn_qty1"] = helper.add(gatherNode[prefix + "dgn_qty1"], sourceNode.dgn_qty1);
         gatherNode[prefix + "dgn_qty2"] = helper.add(gatherNode[prefix + "dgn_qty2"], sourceNode.dgn_qty2);
     },
+    gatherStagePos: function (tender, gatherNode, sourceNode, prefix, helper) {
+        gatherNode[prefix + 'id'] = tender.id;
+        gatherNode[prefix + 'name'] = tender.name;
+        gatherNode[prefix + 'category'] = tender.category;
+
+        gatherNode[prefix + "qty"] = helper.add(gatherNode[prefix + "qty"], sourceNode.quantity);
+
+        gatherNode[prefix + "contract_qty"] = helper.add(gatherNode[prefix + "contract_qty"], sourceNode.contract_qty);
+        gatherNode[prefix + "qc_qty"] = helper.add(gatherNode[prefix + "qc_qty"], sourceNode.qc_qty);
+        gatherNode[prefix + "gather_qty"] = helper.add(gatherNode[prefix + "gather_qty"], sourceNode.gather_qty);
+
+        gatherNode[prefix + "pre_contract_qty"] = helper.add(gatherNode[prefix + "pre_contract_qty"], sourceNode.pre_contract_qty);
+        gatherNode[prefix + "pre_qc_qty"] = helper.add(gatherNode[prefix + "pre_qc_qty"], sourceNode.pre_qc_qty);
+        gatherNode[prefix + "pre_gather_qty"] = helper.add(gatherNode[prefix + "pre_gather_qty"], sourceNode.pre_gather_qty);
+
+        gatherNode[prefix + "end_contract_qty"] = helper.add(gatherNode[prefix + "end_contract_qty"], sourceNode.end_contract_qty);
+        gatherNode[prefix + "end_qc_qty"] = helper.add(gatherNode[prefix + "end_qc_qty"], sourceNode.end_qc_qty);
+        gatherNode[prefix + "end_gather_qty"] = helper.add(gatherNode[prefix + "end_gather_qty"], sourceNode.end_gather_qty);
+
+        gatherNode.s_qty = helper.add(gatherNode.s_qty, sourceNode.quantity);
+
+        gatherNode.s_contract_qty = helper.add(gatherNode.s_contract_qty, sourceNode.contract_qty);
+        gatherNode.s_qc_qty = helper.add(gatherNode.s_qc_qty, sourceNode.qc_qty);
+        gatherNode.s_gather_qty = helper.add(gatherNode.s_gather_qty, sourceNode.gather_qty);
+
+        gatherNode.s_pre_contract_qty = helper.add(gatherNode.s_pre_contract_qty, sourceNode.pre_contract_qty);
+        gatherNode.s_pre_qc_qty = helper.add(gatherNode.s_pre_qc_qty, sourceNode.pre_qc_qty);
+        gatherNode.s_pre_gather_qty = helper.add(gatherNode.s_pre_gather_qty, sourceNode.pre_gather_qty);
+
+        gatherNode.s_end_contract_qty = helper.add(gatherNode.s_end_contract_qty, sourceNode.end_contract_qty);
+        gatherNode.s_end_qc_qty = helper.add(gatherNode.s_end_qc_qty, sourceNode.end_qc_qty);
+        gatherNode.s_end_gather_qty = helper.add(gatherNode.s_end_gather_qty, sourceNode.end_gather_qty);
+    },
+    gatherZonePos: function (tender, gatherNode, sourceNode, prefix, helper) {
+        gatherNode[prefix + 'id'] = tender.id;
+        gatherNode[prefix + 'name'] = tender.name;
+        gatherNode[prefix + 'category'] = tender.category;
+
+        gatherNode[prefix + "qty"] = helper.add(gatherNode[prefix + "qty"], sourceNode.quantity);
+
+        gatherNode[prefix + "contract_qty"] = helper.add(gatherNode[prefix + "contract_qty"], sourceNode.contract_qty);
+        gatherNode[prefix + "qc_qty"] = helper.add(gatherNode[prefix + "qc_qty"], sourceNode.qc_qty);
+        gatherNode[prefix + "gather_qty"] = helper.add(gatherNode[prefix + "gather_qty"], sourceNode.gather_qty);
+
+        gatherNode.s_qty = helper.add(gatherNode.s_qty, sourceNode.quantity);
+
+        gatherNode.s_contract_qty = helper.add(gatherNode.s_contract_qty, sourceNode.contract_qty);
+        gatherNode.s_qc_qty = helper.add(gatherNode.s_qc_qty, sourceNode.qc_qty);
+        gatherNode.s_gather_qty = helper.add(gatherNode.s_gather_qty, sourceNode.gather_qty);
+    },
+    gatherPos: function (tender, gatherNode, sourceNode, prefix, helper) {
+        gatherNode[prefix + 'id'] = tender.id;
+        gatherNode[prefix + 'name'] = tender.name;
+        gatherNode[prefix + 'category'] = tender.category;
+
+        gatherNode[prefix + "qty"] = helper.add(gatherNode[prefix + "qty"], sourceNode.quantity);
+
+        gatherNode.s_qty = helper.add(gatherNode.s_qty, sourceNode.quantity);
+    },
+    gatherSpecialPos: function (gatherNode, sourceNode, prefix, helper) {
+        gatherNode[prefix + "qty"] = helper.add(gatherNode[prefix + "qty"], sourceNode.quantity);
+    },
 };
 
 module.exports = app => {
@@ -176,6 +238,7 @@ module.exports = app => {
                 level: 'level',
                 rootId: -1
             });
+            this.resultPos = new Ledger.pos({ id: 'id', ledgerId: 'lid' });
             this.resultTenderInfo = [];
             this.resultDealPay = [];
             this.resultDealBills = [];

+ 1 - 1
app/service/stage_bills_final.js

@@ -136,7 +136,7 @@ module.exports = app => {
                     curPc.splice(curPc.indexOf(cp), 1);
                 }
                 if (!p.unit_price) {
-                    const bills = await this.ctx.service.ledger.getDataById(c.lid);
+                    const bills = await this.ctx.service.ledger.getDataById(p.lid);
                     p.unit_price = bills ? bills.unit_price || 0 : 0;
                 }
             }

+ 8 - 8
app/service/stage_change.js

@@ -484,17 +484,17 @@ module.exports = app => {
                 const sql = 'SELECT scf.* ' +
                     '  FROM ' + this.ctx.service.stageChangeFinal.tableName + ' scf ' +
                     '  LEFT JOIN ' + this.ctx.service.stage.tableName + ' s ON scf.sid = s.id' +
-                    '  WHERE scf.tid = ? And scf.cid = ? And s.order <= ?';
-                const result = await this.db.query(sql, [tid, cid, stage.order]);
+                    this.ctx.helper.whereSql({ tid, cid }, 'scf') + ' And s.order <= ?';
+                const result = await this.db.query(sql, [stage.order]);
                 return result;
             } else {
                 const preSql = 'SELECT scf.* ' +
                     '  FROM ' + this.ctx.service.stageChangeFinal.tableName + ' scf ' +
                     '  LEFT JOIN ' + this.ctx.service.stage.tableName + ' s ON scf.sid = s.id' +
-                    '  WHERE scf.tid = ? And scf.cid = ? And s.order < ?';
-                const pre = await this.db.query(preSql, [tid, cid, stage.order]);
-                const sql = 'SELECT * FROM ' + this.tableName + ' WHERE sid = ? and cid = ?';
-                const curAll = await this.db.query(sql, [stage.id, cid]);
+                    this.ctx.helper.whereSql({ tid, cid }, 'scf') + ' And s.order < ?';
+                const pre = await this.db.query(preSql, [stage.order]);
+                const sql = 'SELECT * FROM ' + this.tableName + this.ctx.helper.whereSql({ sid: stage.id, cid });
+                const curAll = await this.db.query(sql);
                 const cur = this.ctx.helper.filterLastestData(curAll, ['lid', 'pid', 'cbid', 'no_value'], 'stimes', 'sorder');
                 return [...pre, ...cur];
             }
@@ -590,7 +590,7 @@ module.exports = app => {
             return result;
         }
 
-        async _getChangeBillsWithUsedInfo(stage) {
+        async getChangeBillsWithUsedInfo(stage) {
             if (stage.status === audit.stage.status.checked) {
                 const sql = 'SELECT scf.* ' +
                     '  FROM ' + this.ctx.service.stageChangeFinal.tableName + ' scf ' +
@@ -627,7 +627,7 @@ module.exports = app => {
                 if (!changeBillsPart[cb.cid]) changeBillsPart[cb.cid] = [];
                 changeBillsPart[cb.cid].push(cb);
             }
-            const stageChangeBills = await this._getChangeBillsWithUsedInfo(stage);
+            const stageChangeBills = await this.getChangeBillsWithUsedInfo(stage);
             for (const scb of stageChangeBills) {
                 if (!scb.qty) continue;
 

+ 18 - 7
app/view/login/login.ejs

@@ -9,6 +9,7 @@
     <link rel="stylesheet" href="/public/css/main.css">
     <link rel="stylesheet" href="/public/css/toast.css">
     <link rel="stylesheet" href="/public/css/font-awesome/font-awesome.min.css">
+    <link rel="stylesheet" type="text/css" href="/public/css/jquery-ui/jquery-ui.min.css">
     <link rel="shortcut icon" href="/public/images/favicon.ico">
     <style>
         html{height:100%;}
@@ -31,7 +32,7 @@
         <div class="left-login text-white pt-5 px-5">
             <h2>Hi,您好!</h2>
             <div class="login-border my-4"></div>
-            <div class="left-login-title" id="project_name">纵横捭阖  数“智”管家</div>
+            <div class="left-login-title" id="project_name"><% if (projectData) { %><%- projectData.name %><% } else { %>纵横捭阖  数“智”管家<% } %></div>
         </div>
         <% if (maintainData.status === maintainConst.status.ongoing) { %>
         <form class="right-login position-relative text-center">
@@ -42,14 +43,14 @@
         </form>
         <% } else { %>
         <form method="post" action="/login" id="normal-form" class="right-login position-relative text-center" style="min-width: 360px;">
-            <h3 class="mt-5 mb-4">欢迎登录</h3>
+            <h3 class="mt-5 <% if (projectData) { %>mb-5<% } else { %>mb-4<% } %>">欢迎登录</h3>
             <div class="position-absolute"><a href="javascript:void(0);" class="change-form" data-toggle="tooltip" data-placement="left" title="微信登录"><img alt="微信扫码登录" src="/public/images/icon_login_qr.png"></a></div>
             <div class="mx-4">
-                <div class="input-group mb-4 <% if (errorMessage !== undefined && errorMessage !== null) { %>has-danger<% } %>">
+                <div <% if (projectData) { %>style="display: none"<% } %> class="input-group mb-4 <% if (errorMessage !== undefined && errorMessage !== null) { %>has-danger<% } %>">
                     <div class="input-group-prepend">
                         <div class="input-group-text"><img src="/public/images/icon_login_folder.png"></div>
                     </div>
-                    <input type="text" id="project" class="form-control" name="project" placeholder="项目编号" autofocus="">
+                    <input type="text" id="project" class="form-control" name="project" value="<% if (projectData) { %><%- projectData.code %><% } %>" placeholder="项目编号" autofocus="">
                 </div>
                 <div class="input-group mb-4 <% if (errorMessage !== undefined && errorMessage !== null) { %>has-danger<% } %>">
                     <div class="input-group-prepend">
@@ -63,7 +64,7 @@
                     </div>
                     <input type="password" id="project-password" name="project_password" class="form-control" placeholder="密码">
                 </div>
-                <div class="form-group mb-4">
+                <div class="form-group <% if (projectData) { %>mb-5<% } else { %>mb-4<% } %>">
                     <div class="form-check d-flex justify-content-start pl-0">
                         <label class="form-check-label" for="exampleCheck1"><a href="#fg-password" data-toggle="modal" data-target="#fg-password">忘记密码?</a></label>
                     </div>
@@ -74,6 +75,7 @@
                 </div>
                 <input type="hidden" name="_csrf_j" value="<%= ctx.csrf %>" />
                 <input type="hidden" name="type" value="2" />
+                <input type="hidden" name="hide_code" value="<% if (projectData) { %>1<% } else { %>0<% } %>" />
             </div>
         </form>
         <form id="code-form" class="right-login position-relative text-center" style="min-width: 360px;display: none">
@@ -96,7 +98,7 @@
             <div class="modal-body">
                 <div class="form-group">
                     <label>项目编号</label>
-                    <input class="form-control" id="forget-project" placeholder="输入项目编号">
+                    <input class="form-control" id="forget-project" placeholder="输入项目编号" <% if (projectData) { %>readonly<% } %>>
                     <div class="invalid-feedback"></div>
                 </div>
                 <div class="form-group">
@@ -137,10 +139,19 @@
 <script src="/public/js/jquery/jquery-3.2.1.min.js"></script>
 <script src="/public/js/popper/popper.min.js"></script>
 <script src="/public/js/bootstrap/bootstrap.min.js"></script>
+<script src="/public/js/jquery/jquery-ui.js"></script>
 <script src="/public/js/global.js"></script>
 <script>
-    const csrf = '<%= ctx.csrf %>'
+    const csrf = '<%= ctx.csrf %>';
 </script>
+<% if (projectData) { %>
+    <script>
+        $(document).ready(function() {
+            setLocalCache('project_name', '<%- projectData.name %>');
+            setLocalCache('project_code', '<%- projectData.code %>');
+        });
+    </script>
+<% } %>
 <script src="/public/js/login.js"></script>
 <script src="https://res.wx.qq.com/connect/zh_CN/htmledition/js/wxLogin.js"></script>
 <script>

+ 2 - 0
app/view/login/login_management.ejs

@@ -9,6 +9,7 @@
     <link rel="stylesheet" href="/public/css/main.css">
     <link rel="stylesheet" href="/public/css/toast.css">
     <link rel="stylesheet" href="/public/css/font-awesome/font-awesome.min.css">
+    <link rel="stylesheet" type="text/css" href="/public/css/jquery-ui/jquery-ui.min.css">
     <link rel="shortcut icon" href="/public/images/favicon.ico">
     <style>
         html{height:100%;}
@@ -58,6 +59,7 @@
 <script src="/public/js/jquery/jquery-3.2.1.min.js"></script>
 <script src="/public/js/popper/popper.min.js"></script>
 <script src="/public/js/bootstrap/bootstrap.min.js"></script>
+<script src="/public/js/jquery/jquery-ui.js"></script>
 <script src="/public/js/global.js"></script>
 <% if (projectData) { %>
 <script>

+ 2 - 0
app/view/login/login_port.ejs

@@ -9,6 +9,7 @@
     <link rel="stylesheet" href="/public/css/main.css">
     <link rel="stylesheet" href="/public/css/toast.css">
     <link rel="stylesheet" href="/public/css/font-awesome/font-awesome.min.css">
+    <link rel="stylesheet" type="text/css" href="/public/css/jquery-ui/jquery-ui.min.css">
     <link rel="shortcut icon" href="/public/images/favicon.ico">
     <style>
         html{height:100%;}
@@ -79,6 +80,7 @@
 <script src="/public/js/jquery/jquery-3.2.1.min.js"></script>
 <script src="/public/js/popper/popper.min.js"></script>
 <script src="/public/js/bootstrap/bootstrap.min.js"></script>
+<script src="/public/js/jquery/jquery-ui.js"></script>
 <script src="/public/js/global.js"></script>
 <% if (projectData) { %>
 <script>

+ 2 - 0
app/view/login/wxproject.ejs

@@ -9,6 +9,7 @@
     <link rel="stylesheet" href="/public/css/wap/main.css">
     <link rel="stylesheet" href="/public/css/toast.css">
     <link rel="stylesheet" href="/public/css/font-awesome/font-awesome.min.css">
+    <link rel="stylesheet" type="text/css" href="/public/css/jquery-ui/jquery-ui.min.css">
     <link rel="shortcut icon" href="/public/images/favicon.ico">
 </head>
 <body>
@@ -69,6 +70,7 @@
 <script src="/public/js/jquery/jquery-3.2.1.min.js"></script>
 <script src="/public/js/popper/popper.min.js"></script>
 <script src="/public/js/bootstrap/bootstrap.min.js"></script>
+<script src="/public/js/jquery/jquery-ui.js"></script>
 <script src="/public/js/wap/global.js"></script>
 </body>
 </html>

+ 32 - 11
app/view/setting/fun.ejs

@@ -10,18 +10,38 @@
             <div class="sjs-height-0">
                 <div class="row m-0 mt-3">
                     <div class="col-7">
-                        <div class="card mb-3">
-                            <div class="card-body">
-                                <h5 class="card-title">超计控制</h5>
-                                <div class="form-group mb-4">
-                                    <div>
-                                        <div class="form-check form-check-inline">
-                                            <input class="form-check-input" type="checkbox" id="ban_over" name="ban_over" <% if (funRela.banOver) { %>checked<% } %> onchange="updateSetting();">
-                                            <label class="form-check-label" for="ban_over">超计时限制上报审批/审批通过</label>
+                        <div class="row">
+                            <div class="col-6">
+                                <div class="card mb-3">
+                                    <div class="card-body">
+                                        <h5 class="card-title">超计控制</h5>
+                                        <div class="form-group mb-4">
+                                            <div>
+                                                <div class="form-check">
+                                                    <input class="form-check-input" type="checkbox" id="ban_over" name="ban_over" <% if (funRela.banOver) { %>checked<% } %> onchange="updateSetting();">
+                                                    <label class="form-check-label" for="ban_over">超计时限制上报审批/审批通过</label>
+                                                </div>
+                                                <div class="form-check">
+                                                    <input class="form-check-input" type="checkbox" id="hint_over" name="hint_over" <% if (funRela.hintOver) { %>checked<% } %> onchange="updateSetting();">
+                                                    <label class="form-check-label" for="hint_over">超计时标红显示</label>
+                                                </div>
+                                            </div>
                                         </div>
-                                        <div class="form-check form-check-inline">
-                                            <input class="form-check-input" type="checkbox" id="hint_over" name="hint_over" <% if (funRela.hintOver) { %>checked<% } %> onchange="updateSetting();">
-                                            <label class="form-check-label" for="hint_over">超计时标红显示</label>
+                                    </div>
+                                </div>
+                            </div>
+                            <div class="col-6">
+                                <div class="card mb-3">
+                                    <div class="card-body">
+                                        <h5 class="card-title">变更令调用控制</h5>
+                                        <div class="form-group mb-4">
+                                            <div>
+                                                <div class="form-check form-check-inline">
+                                                    <input class="form-check-input" type="checkbox" id="ban_minus_cb" name="ban_minus_cb" <% if (funRela.banMinusChangeBills) { %>checked<% } %> onchange="updateSetting();">
+                                                    <label class="form-check-label" for="ban_minus_cb">强制调用负变更(限制上报审批/审批通过)</label>
+                                                </div>
+                                                <div class="alert-warning p-1"><i class="fa Example of exclamation-circle fa-exclamation-circle "></i> 变更令开始调用后,负变更清单必须在本期全部调用</div>
+                                            </div>
                                         </div>
                                     </div>
                                 </div>
@@ -267,6 +287,7 @@
             imType: parseInt($('[name=im_type]:checked').val()),
             banOver: $('[name=ban_over]')[0].checked,
             hintOver: $('#hint_over')[0].checked,
+            banMinusChangeBills: $('[name=ban_minus_cb]')[0].checked,
             minusNoValue: $('[name=minusNoValue]')[0].checked,
             needGcl: $('#need_gcl')[0].checked,
             openChangeProject: $('#openChangeProject')[0].checked,

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

@@ -537,6 +537,7 @@
     const sfAttDelPower = <%- sfAttDelPower %>;
     let sfData = JSON.parse(unescape('<%- escape(JSON.stringify(sfData)) %>'));
     const hintOver = <%- hintOver %>;
+    const hintMinusCb = <%- hintMinusCb %>;
     let currPageFileData = [];
 </script>
 <style>

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

@@ -15,7 +15,7 @@
                         <div class="input-group-prepend">
                             <span class="input-group-text" id="basic-addon1">表达式</span>
                         </div>
-                        <input type="text" class="form-control m-0" <% if (stage.readOnly) { %> readonly="" <% } %> id="expr" onpaste="pasteExpr(event, this);">
+                        <input type="text" class="form-control m-0" <% if (stage.readOnly) { %> readonly="" <% } %> id="expr" onpaste="pasteExpr(event, this);" style="width: 270px">
                     </div>
                 </div>
             </div>

sql/update.sql → sql/update20221010.sql