浏览代码

预付款增加重审功能

ellisran 1 年之前
父节点
当前提交
7c7b489e0b

+ 3 - 0
app/const/audit.js

@@ -569,6 +569,7 @@ const advance = (function() {
         checked: 3, // 审批通过
         checkNo: 4, // 审批退回原报
         checkNoPre: 5, // 审批退回上一人
+        checkAgain: 6, // 终审退回  --该状态仅可用于,终审退回时,修改原终审的审批状态,并同时新增一条新的终审审批中记录
     };
 
     const statusString = [];
@@ -577,6 +578,7 @@ const advance = (function() {
     statusString[status.checked] = '审批通过';
     statusString[status.checkNo] = '审批退回';
     statusString[status.checkNoPre] = '审批退回';
+    statusString[status.checkAgain] = '重新审批';
 
     const statusClass = [];
     statusClass[status.uncheck] = '';
@@ -584,6 +586,7 @@ const advance = (function() {
     statusClass[status.checked] = 'text-success';
     statusClass[status.checkNo] = 'text-warning';
     statusClass[status.checkNoPre] = 'text-warning';
+    statusClass[status.checkAgain] = 'text-warning';
 
     // 标段概况页
     // 描述文本

+ 53 - 2
app/controller/advance_controller.js

@@ -149,7 +149,7 @@ module.exports = app => {
             const advancePayTotal = ctx.tender.info.deal_param[`${typeConsts.typeColMap[ctx.advance.type].value}Advance`];
             try {
                 await this._checkCanEntry(ctx);
-                const { uncheck, checkNo } = auditConst.status;
+                const { uncheck, checkNo, checked } = auditConst.status;
                 const { status } = ctx.advance;
                 const isEdited = ctx.session.sessionUser.accountId === ctx.advance.uid && (status === uncheck || status === checkNo);
                 const renderData = await this._getDefaultRenderData(ctx);
@@ -175,6 +175,11 @@ module.exports = app => {
                     prev_total_amount = ctx.helper.formatMoney(ctx.advance.prev_total_amount, ',', isLimitMax ? s2.length : 2);
                 }
 
+                ctx.advance.finalAuditorId = status === checked && ctx.advance.auditors && ctx.advance.auditors.length > 0 ? ctx.advance.auditors[ctx.advance.auditors.length - 1].audit_id : false;
+                // 获取用户人验证手机号
+                const pa = await ctx.service.projectAccount.getDataById(ctx.session.sessionUser.accountId);
+                const auth_mobile = pa.auth_mobile;
+                renderData.authMobile = auth_mobile;
                 renderData.isEdited = isEdited;
                 renderData.advance = ctx.advance;
                 renderData.cur_amount = cur_amount;
@@ -361,7 +366,7 @@ module.exports = app => {
         async checkAudit(ctx) {
             try {
                 if (!ctx.advance || ctx.advance.status !== auditConst.status.checking) {
-                    throw '当前材料调差期数据有误';
+                    throw '当前预付款数据有误';
                 }
                 if (!ctx.advance.curAuditor || ctx.advance.curAuditor.audit_id !== ctx.session.sessionUser.accountId) {
                     throw '您无权进行该操作';
@@ -389,6 +394,52 @@ module.exports = app => {
             }
         }
 
+        /**
+         * 重新审批
+         * @param {Object} ctx - egg全局变量
+         * @return {void}
+         */
+        async checkAgain(ctx) {
+            try {
+                if (!ctx.advance || ctx.advance.status !== auditConst.status.checked) {
+                    throw '当前预付款数据有误';
+                }
+                const finalAuditorId = ctx.advance.auditors && ctx.advance.auditors.length > 0 ? ctx.advance.auditors[ctx.advance.auditors.length - 1].audit_id : false;
+                if (!finalAuditorId || finalAuditorId !== ctx.session.sessionUser.accountId) {
+                    throw '您无权进行该操作';
+                }
+                if (ctx.session.sessionUser.loginStatus === 0) {
+                    const code = ctx.request.body.code;
+                    const pa = await ctx.service.projectAccount.getDataById(ctx.session.sessionUser.accountId);
+                    if (!pa.auth_mobile) {
+                        throw '未绑定手机号';
+                    }
+                    const cacheKey = 'smsCode:' + ctx.session.sessionUser.accountId;
+                    const cacheCode = await app.redis.get(cacheKey);
+                    // console.log(cacheCode);
+                    if (cacheCode === null || code === undefined || cacheCode !== (code + pa.auth_mobile)) {
+                        throw '验证码不正确!';
+                    }
+                }
+                // 重新审批
+                const result = await ctx.service.advanceAudit.checkAgain(ctx.advance);
+                if (!result) {
+                    throw '重新审批失败';
+                }
+                ctx.body = {
+                    err: 0,
+                    url: ctx.request.header.referer,
+                    msg: '',
+                };
+            } catch (err) {
+                console.log(err);
+                ctx.body = {
+                    err: 1,
+                    msg: err,
+                };
+            }
+        }
+
         _checkAdvanceFileCanModify(ctx) {
             // 检查登录用户,是否可操作
             const accountId = ctx.session.sessionUser.accountId;

+ 1 - 0
app/middleware/advance_check.js

@@ -34,6 +34,7 @@ module.exports = () => {
     return function* advanceCheck(next) {
         try {
             // 读取预付款id
+            const cid = this.params.cid || this.request.body.cid;
             const id = parseInt(this.params.order);
             if (!id || id <= 0) {
                 throw '您访问的预付款期不存在';

+ 1 - 0
app/router.js

@@ -222,6 +222,7 @@ module.exports = app => {
     app.get('/tender/:id/advance/:order/file/:fid/download', sessionAuth, tenderCheck, 'advanceController.downloadFile');
     app.post('/tender/:id/advance/:order/file/del', sessionAuth, tenderCheck, advanceCheck, 'advanceController.deleteFile');
     app.post('/tender/:id/advance/:type/:order/auditors', sessionAuth, tenderCheck, advanceCheck, 'advanceController.getAuditors');
+    app.post('/tender/:id/advance/:order/check/again', sessionAuth, tenderCheck, uncheckTenderCheck, tenderBuildCheck, advanceCheck, 'advanceController.checkAgain');
 
     // 标段协作办公
     app.get('/tender/:id/cooperation', sessionAuth, tenderCheck, 'tenderController.tenderCooperation');

+ 60 - 1
app/service/advance_audit.js

@@ -175,7 +175,7 @@ module.exports = app => {
          */
         async getAuditors(vid, times = 1) {
             const sql =
-                'SELECT la.`audit_id`, pa.`name`, pa.`company`, pa.`role`, pa.`mobile`, pa.`telephone`, la.`times`, la.`order`, la.`status`, la.`opinion`, la.`create_time`, la.`end_time`, g.`sort` ' +
+                'SELECT la.`audit_id`, pa.`name`, pa.`company`, pa.`role`, pa.`mobile`, pa.`telephone`, la.`times`, la.`type`, la.`order`, la.`status`, la.`opinion`, la.`create_time`, la.`end_time`, g.`sort` ' +
                 'FROM ?? AS la, ?? AS pa, (SELECT t1.`audit_id`,(@i:=@i+1) as `sort` FROM (SELECT t.`audit_id`, t.`order` FROM (select `audit_id`, `order` from ?? WHERE `vid` = ? AND `times` = ? ORDER BY `order` LIMIT 200) t GROUP BY t.`audit_id` ORDER BY t.`order`) t1, (select @i:=0) as it) as g ' +
                 'WHERE la.`vid` = ? and la.`times` = ? and la.`audit_id` = pa.`id` and g.`audit_id` = la.`audit_id` order by la.`order`';
             const sqlParam = [this.tableName, this.ctx.service.projectAccount.tableName, this.tableName, vid, times, vid, times];
@@ -530,6 +530,65 @@ module.exports = app => {
         }
 
         /**
+         * 重新审批
+         * @param { string } cid - 查询的清单
+         * @return {Promise<*>} - 可用的变更令列表
+         */
+        async checkAgain(advance) {
+            const accountId = this.ctx.session.sessionUser.accountId;
+            // 初始化事务
+            const time = new Date();
+            const transaction = await this.db.beginTransaction();
+            let result = false;
+            try {
+                const maxOrder = advance.auditors[advance.auditors.length - 1].order;
+                const audits = advance.auditors.filter(x => { return x.order === maxOrder; });
+                if (!audits || audits.length === 0 || maxOrder < 1) throw '审核数据错误';
+                const selfAudit = audits.find(x => { return x.audit_id === accountId; });
+                if (!selfAudit) throw '当前标段您无权审批';
+                // 当前审批人2次添加至流程中
+                const checkAgainAuditors = [];
+                audits.forEach(x => {
+                    checkAgainAuditors.push({
+                        tid: advance.tid, vid: advance.id, audit_id: x.audit_id, type: x.type,
+                        times: x.times, order: maxOrder + 1,
+                        status: auditConst.status.checkAgain,
+                        create_time: time, end_time: time, opinion: '',
+                    });
+                });
+                const checkingAuditors = [];
+                audits.forEach(x => {
+                    checkingAuditors.push({
+                        tid: advance.tid, vid: advance.id, audit_id: x.audit_id, type: x.type,
+                        times: x.times, order: maxOrder + 2,
+                        status: auditConst.status.checking,
+                        create_time: time,
+                    });
+                });
+                await transaction.insert(this.tableName, checkAgainAuditors);
+                const checkingAuditors_result = await transaction.insert(this.tableName, checkingAuditors);
+                // 获取刚批量添加的所有list
+                // for (let j = 0; j < checkingAuditors.length; j++) {
+                //     checkingAuditors[j].id = checkingAuditors_result.insertId + j;
+                // }
+
+                // 设置审批中
+                await transaction.update(this.ctx.service.advance.tableName, {
+                    id: advance.id,
+                    status: auditConst.status.checking,
+                    end_time: null,
+                });
+                await transaction.commit();
+                result = true;
+            } catch (error) {
+                console.log(error);
+                await transaction.rollback();
+                result = false;
+            }
+            return result;
+        }
+
+        /**
          * 用于添加推送所需的content内容
          * @param {Number} pid 项目id
          * @param {Number} tid 台账id

+ 1 - 1
app/service/project_account.js

@@ -182,7 +182,7 @@ module.exports = app => {
                         loginStatus = 1;
                     }
                     // dev-qa下默认副密码登录,规避验证码
-                    if (this.ctx.app.config.is_debug) loginStatus = 1;
+                    // if (this.ctx.app.config.is_debug) loginStatus = 1;
                     // }
                 } else if (loginType === 3) {
                     // 查找项目数据

+ 4 - 0
app/view/advance/audit_btn.ejs

@@ -14,6 +14,10 @@
     <% } %>
 <% } else if (ctx.advance.status === auditConst.status.checked) { %>
     <a href="#sp-list" data-type="hide" data-toggle="modal" data-target="#sp-list" class="btn btn-outline-secondary btn-sm sp-list-btn">审批完成</a>
+    <% if (ctx.advance.finalAuditorId && ctx.advance.finalAuditorId === ctx.session.sessionUser.accountId) { %>
+        <!--重新审批-->
+        <a href="#sp-down-back" data-toggle="modal" data-target="#sp-down-back" class="btn btn-warning btn-sm ml-2">重新审批</a>
+    <% } %>
 <% } else if (ctx.advance.status === auditConst.status.checkNo) { %>
     <a href="#sp-list" data-type="hide" data-toggle="modal" data-target="#sp-list" class="btn btn-outline-warning btn-sm text-muted sp-list-btn">审批退回</a>
     <% if (ctx.session.sessionUser.accountId === ctx.advance.uid) { %>

+ 8 - 0
app/view/advance/detail.ejs

@@ -266,6 +266,10 @@
                                                     <div class="timeline-item-icon bg-warning text-light">
                                                         <i class="fa fa-level-up"></i>
                                                     </div>
+                                                    <% } else if(auditor.status === auditConst.status.checkAgain) {%>
+                                                        <div class="timeline-item-icon bg-warning text-light">
+                                                            <i class="fa fa-check"></i>
+                                                        </div>
                                                     <% } else if(auditor.status === auditConst.status.checking) { %>
                                                     <div class="timeline-item-icon bg-warning text-light">
                                                         <i class="fa fa-ellipsis-h"></i>
@@ -310,6 +314,10 @@
                                                     <div class="timeline-item-icon bg-warning text-light">
                                                         <i class="fa fa-level-up"></i>
                                                     </div>
+                                                    <% } else if(auditor.status === auditConst.status.checkAgain) {%>
+                                                        <div class="timeline-item-icon bg-warning text-light">
+                                                            <i class="fa fa-check"></i>
+                                                        </div>
                                                     <% } else if(auditor.status === auditConst.status.checking) { %>
                                                     <div class="timeline-item-icon bg-warning text-light">
                                                         <i class="fa fa-ellipsis-h"></i>

+ 144 - 0
app/view/advance/modal_audit.ejs

@@ -643,7 +643,151 @@
         </div>
     <% } %>
 <% } %>
+<% if (ctx.advance.finalAuditorId && ctx.advance.finalAuditorId === ctx.session.sessionUser.accountId) { %>
+    <% if (!authMobile && ctx.session.sessionUser.loginStatus === 0) { %>
+        <!--终审重新审批-->
+        <div class="modal fade" id="sp-down-back" data-backdrop="static">
+            <div class="modal-dialog" role="document">
+                <div class="modal-content">
+                    <div class="modal-header">
+                        <h5 class="modal-title">重新审批</h5>
+                    </div>
+                    <div class="modal-body">
+                        <h5>重新审批需要您的手机短信验证</h5>
+                        <h5>您目前还没设置认证手机,请先设置。</h5>
+                    </div>
+                    <div class="modal-footer">
+                        <button type="button" class="btn btn-sm btn-secondary" data-dismiss="modal">取消</button>
+                        <a href="/profile/sms" class="btn btn-sm btn-primary">去设置</a>
+                    </div>
+                </div>
+            </div>
+        </div>
+    <% } else { %>
+        <!--重新审批-->
+        <div class="modal fade" id="sp-down-back" data-backdrop="static">
+            <div class="modal-dialog" role="document">
+                <form id="againForm" class="modal-content" method="post" action="/tender/<%- ctx.tender.id %>/advance/<%- advance.id %>/check/again" onsubmit="return false;">
+                    <div class="modal-header">
+                        <h5 class="modal-title">重新审批</h5>
+                    </div>
+                    <div class="modal-body">
+                        <h5>确认由「终审」重新审批「第<%= advance.order %>期」?</h5>
+                        <% if (ctx.session.sessionUser.loginStatus === 0) { %>
+                            <div class="form-group">
+                                <label>重审需要验证码确认,验证码将发送至尾号<%- authMobile.slice(-4) %>的手机</label>
+                                <div class="input-group input-group-sm mb-3">
+                                    <input class="form-control" type="text" readonly="readonly" name="code" placeholder="输入短信中的6位验证码" />
+                                    <div class="input-group-append">
+                                        <button class="btn btn-outline-secondary get-code" type="button">获取验证码</button>
+                                    </div>
+                                </div>
+                            </div>
+                        <% } %>
+                    </div>
+                    <div class="modal-footer">
+                        <input type="hidden" name="vid" value="<%= advance.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="button" id="re-shenpi-btn" class="btn btn-warning btn-sm" <% if (ctx.session.sessionUser.loginStatus === 0) { %>disabled<% } %>>确定重审</button>
+                    </div>
+                </form>
+            </div>
+        </div>
+    <% } %>
+<script>
+    const csrf = '<%= ctx.csrf %>';
+    const authMobile = '<%= authMobile %>';
+    $(function () {
+        $('#re-shenpi-btn').click(function () {
+            const data = {
+            };
+            <% if (ctx.session.sessionUser.loginStatus === 0) { %>
+            const code = $("#againForm input[name='code']").val();
+            if ($(this).hasClass('disabled')) {
+                return false;
+            }
+            if (code.length < 6) {
+                // alert('请填写正确的验证码');
+                toastr.error('请填写正确的验证码');
+                return false;
+            }
+            data.code = code;
+            <% } %>
+            $.ajax({
+                url: '/tender/<%- ctx.tender.id %>/advance/<%- advance.id %>/check/again?_csrf_j=' + csrf,
+                type: 'post',
+                data: data,
+                dataTye: 'json',
+                success: function(response) {
+                    if (response.err === 0) {
+                        window.location.href = response.url;
+                    } else {
+                        toastr.error(response.msg);
+                    }
+                }
+            });
+        });
+        // 重新审批获取手机验证码
+        // 获取验证码
+        let isPosting = false;
+        $(".get-code").on('click', function() {
+            if (isPosting) {
+                return false;
+            }
+            const btn = $(this);
+
+            $.ajax({
+                url: '/profile/code?_csrf_j=' + csrf,
+                type: 'post',
+                data: { mobile: authMobile, type: 'shenpi' },
+                dataTye: 'json',
+                error: function() {
+                    isPosting = false;
+                },
+                beforeSend: function() {
+                    isPosting = true;
+                },
+                success: function(response) {
+                    isPosting = false;
+                    if (response.err === 0) {
+                        codeSuccess(btn);
+                        $("input[name='code']").removeAttr('readonly');
+                        $("#re-shenpi-btn").removeAttr('disabled');
+                    } else {
+                        toastr.error(response.msg);
+                    }
+                }
+            });
+        });
+    });
+    /**
+     * 获取成功后的操作
+     *
+     * @param {Object} btn - 点击的按钮
+     * @return {void}
+     */
+    function codeSuccess(btn) {
+        let counter = 60;
+        btn.addClass('disabled').text('重新获取 ' + counter + 'S');
+        btn.parent().siblings('input').removeAttr('readonly').attr('placeholder', '输入短信中的6位验证码');
+        const bindBtn = $("#bind-btn");
+        bindBtn.removeClass('btn-secondary disabled').addClass('btn-primary');
 
+        const countDown = setInterval(function() {
+            const countString = counter - 1 <= 0 ? '' : ' ' + (counter - 1) + 'S';
+            // 倒数结束后
+            if (countString === '') {
+                clearInterval(countDown);
+                btn.removeClass('disabled');
+            }
+            const text = '重新获取' + countString;
+            btn.text(text);
+            counter -= 1;
+        }, 1000);
+    }
+</script>
+<% } %>
 <script>
     $('.sp-list-btn').click(function () {
         const type = $(this).data('type')