فهرست منبع

待办,提供合同支付数据

MaiXinRong 2 ماه پیش
والد
کامیت
3f0d7264de

+ 17 - 0
app/controller/dashboard_controller.js

@@ -43,6 +43,7 @@ module.exports = app => {
             const allAuditInspections = await ctx.service.qualityInspectionAudit.getAuditInspection(ctx.session.sessionUser.accountId);
             const allAuditSafeInspections = await ctx.service.safeInspectionAudit.getAuditInspection(ctx.session.sessionUser.accountId);
             const allAuditSafeStage = await ctx.service.safeStageAudit.getAuditStage(ctx.session.sessionUser.accountId);
+            const allAuditPhasePay = await ctx.service.phasePayAudit.getAuditStage(ctx.session.sessionUser.accountId);
             const pa = await ctx.service.projectAccount.getDataById(ctx.session.sessionUser.accountId);
             const auditShenpiTenders = await ctx.service.ledgerAudit.getDonesByAudit(ctx.session.sessionUser.accountId);
             const auditShenpiStages = await ctx.service.stageAudit.getDonesByAudit(ctx.session.sessionUser.accountId);
@@ -58,6 +59,7 @@ module.exports = app => {
             const auditShenpiInspection = await ctx.service.qualityInspectionAudit.getDonesByAudit(ctx.session.sessionUser.accountId);
             const auditShenpiSafeInspection = await ctx.service.safeInspectionAudit.getDonesByAudit(ctx.session.sessionUser.accountId);
             const auditShenpiSafeStage = await ctx.service.safeStageAudit.getDonesByAudit(ctx.session.sessionUser.accountId);
+            const auditShenpiPhasePay = await ctx.service.phasePayAudit.getDonesByAudit(ctx.session.sessionUser.accountId);
             const dashboardStatus = {
                 all: 0,
                 dashboard: 0,
@@ -78,6 +80,7 @@ module.exports = app => {
                     inspection: 0,
                     safeInspection: 0,
                     safeStage: 0,
+                    phasePay: 0,
                 },
             };
             let noticeList = [];
@@ -113,6 +116,8 @@ module.exports = app => {
                 noticeList.push(...ctx.helper.addKeyValue4ObjArray(spSafeInspection, 'shenpi_type', 'safeInspection'));
                 const spSafeStage = subProject.page_show.safeInspection ? ctx.helper._.filter(auditShenpiSafeStage, { spid: subProject.id }) : [];
                 noticeList.push(...ctx.helper.addKeyValue4ObjArray(spSafeStage, 'shenpi_type', 'safeStage'));
+                const spPhasePay = subProject.page_show.phasePay ? ctx.helper._.filter(auditShenpiPhasePay, { spid: subProject.id }) : [];
+                noticeList.push(...ctx.helper.addKeyValue4ObjArray(spPhasePay, 'shenpi_type', 'phasePay'));
             }
             const noticeDayList = [];
             noticeList = ctx.helper._.orderBy(noticeList, ['shenpi_time'], ['desc']);
@@ -152,6 +157,8 @@ module.exports = app => {
             dashboardShenpis.push(...auditSafeInspections);
             const auditSafeStage = await this.auditSet(ctx, allAuditSafeStage, subProjects, dashboardStatus, 'safeStage');
             dashboardShenpis.push(...auditSafeStage);
+            const auditPhasePay = await this.auditSet(ctx, allAuditPhasePay, subProjects, dashboardStatus, 'phasePay');
+            dashboardShenpis.push(...auditPhasePay);
             // console.log(ctx.helper._.orderBy(dashboardShenpis, ['start_audit', 'shenpi_time'], ['desc', 'desc']));
             const projectData = await ctx.service.project.getDataById(ctx.session.sessionProject.id);
             // 获取销售人员数据
@@ -184,6 +191,7 @@ module.exports = app => {
                 acFinancial: auditConst.financial,
                 acInspection: auditConst.inspection,
                 acSafeStage: auditConst.safeStage,
+                acPhasePay: auditConst.phasePay,
                 noticeList,
                 noticeDayList,
                 pushType: auditConst.pushType,
@@ -298,6 +306,10 @@ module.exports = app => {
                             if (!sp.page_show.safePayment) closeType = true;
                             calcTime = t.create_time;
                             break;
+                        case 'safeStage':
+                            if (!sp.page_show.phasePay) closeType = true;
+                            calcTime = t.create_time;
+                            break;
                         default:
                             closeType = true;
                     }
@@ -346,6 +358,7 @@ module.exports = app => {
             const auditInspections = ctx.subProject.page_show.qualityInspection ? await ctx.service.qualityInspectionAudit.getAuditInspection(ctx.session.sessionUser.accountId, ctx.subProject.id) : [];
             const auditSafeInspections = ctx.subProject.page_show.safeInspection ? await ctx.service.safeInspectionAudit.getAuditInspection(ctx.session.sessionUser.accountId, ctx.subProject.id) : [];
             const auditSafeStage = ctx.subProject.page_show.safePayment ? await ctx.service.safeStageAudit.getAuditStage(ctx.session.sessionUser.accountId, ctx.subProject.id) : [];
+            const auditPhasePay = ctx.subProject.page_show.phasePay ? await ctx.service.phasePayAudit.getAuditStage(ctx.session.sessionUser.accountId, ctx.subProject.id) : [];
             const pa = await ctx.service.projectAccount.getDataById(ctx.session.sessionUser.accountId);
             const noticeList = await ctx.service.noticePush.getNotice(ctx.session.sessionProject.id, pa.id, ctx.subProject.id);
             const projectData = await ctx.service.project.getDataById(ctx.session.sessionProject.id);
@@ -378,6 +391,7 @@ module.exports = app => {
             if (ctx.subProject.page_show.qualityInspection) shenpi_count.push({ count: await ctx.service.qualityInspectionAudit.getCountByChecked(ctx.session.sessionUser.accountId, ctx.subProject.id), name: '质量巡检' });
             if (ctx.subProject.page_show.safeInspection) shenpi_count.push({ count: await ctx.service.safeInspectionAudit.getCountByChecked(ctx.session.sessionUser.accountId, ctx.subProject.id), name: '安全巡检' });
             if (ctx.subProject.page_show.safePayment) shenpi_count.push({ count: await ctx.service.safeStageAudit.getCountByChecked(ctx.session.sessionUser.accountId, ctx.subProject.id), name: '安全计量' });
+            if (ctx.subProject.page_show.phasePay) shenpi_count.push({ count: await ctx.service.phasePayAudit.getCountByChecked(ctx.session.sessionUser.accountId, ctx.subProject.id), name: '合同支付' });
             // shenpi_count.push({ count: await ctx.service.advanceAudit.getCountByChecked(ctx.session.sessionUser.accountId), name: '预付款' });
             const total_count = ctx.app._.sumBy(shenpi_count, 'count');
             const shenpi_lastime = [
@@ -394,6 +408,7 @@ module.exports = app => {
                 ctx.subProject.page_show.qualityInspection ? await ctx.service.qualityInspectionAudit.getLastEndTimeByChecked(ctx.session.sessionUser.accountId, ctx.subProject.id) : null,
                 ctx.subProject.page_show.safeInspection ? await ctx.service.safeInspectionAudit.getLastEndTimeByChecked(ctx.session.sessionUser.accountId, ctx.subProject.id) : null,
                 ctx.subProject.page_show.safeInspection ? await ctx.service.safeStageAudit.getLastEndTimeByChecked(ctx.session.sessionUser.accountId, ctx.subProject.id) : null,
+                ctx.subProject.page_show.phasePay ? await ctx.service.phasePayAudit.getLastEndTimeByChecked(ctx.session.sessionUser.accountId, ctx.subProject.id) : null,
             ];
             const last_time = ctx.app._.max(shenpi_lastime);
             // console.log(ctx.app._.max(shenpi_lastime), ctx.helper.calcDayNum(last_time));
@@ -413,6 +428,7 @@ module.exports = app => {
                 auditInspections,
                 auditSafeInspections,
                 auditSafeStage,
+                auditPhasePay,
                 shenpi_count,
                 total_count,
                 last_day: ctx.helper.calcDayNum(last_time),
@@ -430,6 +446,7 @@ module.exports = app => {
                 acFinancial: auditConst.financial,
                 acInspection: auditConst.inspection,
                 acSafeStage: auditConst.safeStage,
+                acPhasePay: auditConst.phasePay,
                 noticeList,
                 pushType: auditConst.pushType,
                 projectData,

+ 6 - 0
app/public/css/main.css

@@ -1945,6 +1945,9 @@ overflow-y: auto;
 .bg-new-inspection{
     background: rgba(158, 88, 80, 0.08) !important;
 }
+.bg-new-phasepay{
+    background: rgba(200, 51, 6, 0.08) !important;
+}
 .text-new-advance{
   color: rgba(241, 82, 91, 1) !important;
 }
@@ -1981,6 +1984,9 @@ overflow-y: auto;
 .text-new-inspection{
     color: rgba(158, 58, 80, 1) !important;
 }
+.text-new-phasepay{
+    color: rgba(200, 51, 6, 1) !important;
+}
 .text-width{
   width: 66px;
   text-align: center;

+ 90 - 0
app/service/phase_pay_audit.js

@@ -13,6 +13,7 @@ const auditType = auditConst.auditType;
 const pushType = auditConst.pushType;
 const smsTypeConst = require('../const/sms_type');
 const wxConst = require('../const/wechat_template');
+const checkRelaStatus = [auditConst.common.status.checked, auditConst.common.status.checkNo, auditConst.common.status.checkNoPre];
 
 module.exports = app => {
     class PhasePayAudit extends app.BaseService {
@@ -114,6 +115,95 @@ module.exports = app => {
             const sqlParam = [tenderId];
             return this.db.query(sql, sqlParam);
         }
+        async getAuditStage(auditorId, spid = '') {
+            // 查询待审批的期
+            const spSql = spid ? ' and t.`spid` = "' + spid + '"' : '';
+            const sql =
+                'SELECT sa.`audit_id`, sa.`audit_times`, sa.`audit_order`, sa.active_order, sa.`tid`, sa.`phase_id`,' +
+                '    s.`phase_order`, s.`phase_date`, s.create_time,' +
+                '    t.`name`, t.`project_id`, t.`type`, t.`user_id`, t.`spid` ' +
+                `  FROM ${this.tableName} AS sa ` +
+                `    Left Join ${this.ctx.service.phasePay.tableName} AS s On sa.phase_id = s.id ` +
+                `    Left Join ${this.ctx.service.tender.tableName} As t ON sa.tid = t.id `+
+                '  WHERE sa.`audit_id` = ? and (sa.`audit_status` = ? or (sa.audit_times > 1 and sa.audit_status = ? and sa.audit_order = 0))' + spSql +
+                '  ORDER BY sa.`create_time` DESC';
+            const sqlParam = [auditorId, auditConst.common.status.checking, auditConst.common.status.uncheck];
+            const result = await this.db.query(sql, sqlParam);
+            for (const r of result) {
+                if (r.audit_order > 0) {
+                    const preAuditTime = await this.db.queryOne(`SELECT Max(audit_time) as audit_time FROM ${this.tableName} where phase_id = ? and audit_times = ? and active_order = ?`, [r.phase_id, r.audit_times, r.active_order - 1]);
+                    r.begin_time = preAuditTime.audit_time;
+                } else {
+                    const checkNoTime = await this.db.queryOne(`SELECT Max(audit_time) as audit_time FROM ${this.tableName} where phase_id = ? and audit_times = ? and audit_status = ?`, [r.phase_id, r.audit_times - 1, auditConst.common.status.checkNo]);
+                    r.begin_time = checkNoTime.audit_time;
+                }
+            }
+            return result;
+        }
+        /**
+         * 获取审核人已经审核过的审批信息(包括退回,通过,重新审批等)
+         *
+         * @param auditorId
+         * @return {Promise<*>}
+         */
+        async getDonesByAudit(auditorId, spid = '') {
+            const spSql = spid ? ' and t.`spid` = "' + spid + '"' : '';
+            const sql =
+                'SELECT ssa.audit_status, ssa.audit_time AS shenpi_time, ssa.phase_id, t.id, ss.phase_order, t.name, t.spid ' +
+                `  FROM ${this.tableName} AS ssa Left Join ${this.ctx.service.tender.tableName} AS t ON ssa.tid = t.id LEFT JOIN ${this.ctx.service.phasePay.tableName} AS ss ON ssa.phase_id = ss.id` +
+                '  WHERE ssa.audit_id = ? AND ssa.audit_status in (' + this.ctx.helper.getInArrStrSqlFilter(checkRelaStatus) + ')' + spSql +
+                '  ORDER BY ssa.audit_time DESC';
+            const sqlParam = [auditorId];
+            return await this.db.query(sql, sqlParam);
+        }
+        /**
+         * 获取最近一次审批结束时间
+         *
+         * @param auditorId
+         * @return {Promise<*>}
+         */
+        async getLastEndTimeByChecked(auditorId, spid = '') {
+            const sqSql = spid ? ' AND t.`spid` = "' + spid + '"' : '';
+            const status = [auditConst.common.status.checked, auditConst.common.status.checkNo, auditConst.common.status.checkNoPre];
+            const sql = `SELECT a.audit_time FROM ${this.tableName} AS a LEFT JOIN ${this.ctx.service.tender.tableName} AS t ON a.tid = t.id WHERE a.audit_id = ? ` +
+                'AND a.`audit_status` in (' + this.ctx.helper.getInArrStrSqlFilter(checkRelaStatus) + ')' + sqSql +
+                ' ORDER BY a.`audit_time` DESC';
+            const sqlParam = [auditorId];
+            const result = await this.db.queryOne(sql, sqlParam);
+            return result ? result.audit_time : null;
+        }
+        /**
+         * 获取审核人审核的次数
+         *
+         * @param auditorId
+         * @return {Promise<*>}
+         */
+        async getCountByChecked(auditorId, spid = '') {
+            if (spid) {
+                const sql = `SELECT count(*) AS count FROM ${this.tableName} AS a LEFT JOIN ${this.ctx.service.tender.tableName} AS t ON a.tid = t.id` +
+                    ' WHERE a.audit_id = ? AND a.audit_status in (' + this.ctx.helper.getInArrStrSqlFilter(checkRelaStatus) + ') AND t.`spid` = ?';
+                const sqlParam = [auditorId, spid];
+                const result = await this.db.queryOne(sql, sqlParam);
+                return result.count ? result.count : 0;
+            }
+            return await this.db.count(this.tableName, { audit_id: auditorId, status: checkRelaStatus });
+        }
+        // 获取审核比较 可查看的列表,它用不可修改
+        async getViewFlow(phasePay) {
+            const result = [];
+            if (phasePay.audit_status === auditConst.common.status.uncheck) return result;
+
+            const group = await this.getAuditorHistory(phasePay.id, phasePay.curTimes);
+            const latestGroup = group[group.length - 1];
+            latestGroup.forEach(x => {
+                if (x.audit_status === auditConst.common.status.checked) result.push(x);
+                if (x.audit_status === auditConst.common.status.checking && !phasePay.readOnly) {
+                    x.latest = true;
+                    result.push(x);
+                }
+            });
+            return result;
+        }
         // ***** 查询审批人相关
 
         // ***** 修改审批人相关

تفاوت فایلی نمایش داده نمی شود زیرا این فایل بسیار بزرگ است
+ 27 - 2
app/view/dashboard/index.ejs


+ 19 - 0
app/view/dashboard/workspace.ejs

@@ -142,6 +142,9 @@
                                             <% if (dashboardStatus.shenpi.safeStage !== 0) { %>
                                             <option value="safeInspection">安全计量(<%- dashboardStatus.shenpi.safeStage %>)</option>
                                             <% } %>
+                                            <% if (dashboardStatus.shenpi.phasePay !== 0) { %>
+                                            <option value="safeInspection">合同支付(<%- dashboardStatus.shenpi.phasePay %>)</option>
+                                            <% } %>
                                         </select>
                                     </div>
                                 </div>
@@ -458,6 +461,17 @@
                                                             <td><%- (am.begin_time ? ctx.moment(am.begin_time).format('YYYY/MM/DD HH:mm') : '') %></td>
                                                             <td><a href="/sp/<%- am.spid %>/safe/tender/<%- am.tid %>/stage/<%- am.stage_order %>/bills" class="btn btn-sm btn-table <%- (am.audit_order === 0 ? 'btn-outline-warning text-warning' : 'btn-outline-primary') %>" role="button"><%- (am.audit_order === 0 ? '重新上报' : '审批')%></a></td>
                                                         </tr>
+                                                    <% } else if (db.shenpi_type === 'phasePay') { %>
+                                                        <% const am = db; %>
+                                                        <tr data-type="phasePay">
+                                                            <% if (am.start_audit === 2) { %><td class="text-center text-danger"><i class="fa fa-exclamation-triangle"></i></td><% } else if (am.start_audit === 1) { %><td class="text-center text-warning"><i class="fa fa-bell"></i></td><% } else { %><td></td><% } %>
+                                                            <td><span class="bg-new-phasepay text-new-phasepay badge text-width">合同支付</span></td>
+                                                            <td><a href="/sp/<%- am.spid %>/dashboard"><%- am.sp_name %></a></td>
+                                                            <td><a href="/tender/<%- am.tid %>"><%- am.name %></a> <a href="/tender/<%- am.tid %>/pay/<%- am.phase_order %>/detail">第<%- am.phase_order %>期</a></td>
+                                                            <td>第<%- am.phase_order %>期</td>
+                                                            <td><%- (am.begin_time ? ctx.moment(am.begin_time).format('YYYY/MM/DD HH:mm') : '') %></td>
+                                                            <td><a href="/tender/<%- am.tid %>/pay/<%- am.phase_order %>/bills" class="btn btn-sm btn-table <%- (am.audit_order === 0 ? 'btn-outline-warning text-warning' : 'btn-outline-primary') %>" role="button"><%- (am.audit_order === 0 ? '重新上报' : '审批')%></a></td>
+                                                        </tr>
                                                     <% } %>
                                                 <% } %>
                                                 </tbody>
@@ -629,6 +643,7 @@
     const acChangePlan = JSON.parse(unescape('<%- escape(JSON.stringify(acChangePlan)) %>'));
     const acFinancial = JSON.parse(unescape('<%- escape(JSON.stringify(acFinancial)) %>'));
     const acInspection = JSON.parse(unescape('<%- escape(JSON.stringify(acInspection)) %>'));
+    const acPhasePay = JSON.parse(unescape('<%- escape(JSON.stringify(acPhasePay)) %>'));
     const typeColMap = JSON.parse(unescape('<%- escape(JSON.stringify(typeColMap)) %>'));
     const userMsgPermission = false;
 
@@ -890,6 +905,10 @@
                                         html.push(`<li class="list-group-item">
                                             <span class="${acInspection.auditStringClass[n.status]}">${acInspection.auditString[n.status]}</span> <a href="/sp/${n.spid}/safe/tender/${n.id}/inspection/${n.qiid}/information" target="_blank">${n.name}</a> 安全巡检 ${n.code}<span class="float-right">${moment(new Date(n.shenpi_time)).format('HH:mm:ss')}</span></li>`);
                                         break;
+                                    case 'phasePay':
+                                        html.push(`<li class="list-group-item">
+                                            <span class="${acPhasePay.auditStringClass[n.status]}">${acPhasePay.auditString[n.status]}</span> <a href="/tender/${n.id}/pay/${n.phase_order}/detail" target="_blank">${n.name}</a> 合同支付 ${n.name}<span class="float-right">${moment(new Date(n.shenpi_time)).format('HH:mm:ss')}</span></li>`);
+                                        break;
                                     default: continue;
                                 }
                             }