Quellcode durchsuchen

工作台、待办事项,成本报审,财务账面,成本分析,待审、审批记录等数据

MaiXinRong vor 1 Monat
Ursprung
Commit
1efaea3f2a

+ 1 - 1
app/controller/cost_controller.js

@@ -180,7 +180,7 @@ module.exports = app => {
                 }
 
                 if (!newStage) throw '新增期失败';
-                ctx.redirect(`/sp/${ctx.subProject.id}/cost/tender/${ctx.tender.id}/${stage_type}/${newStage.stage_order}`);
+                ctx.redirect(`/sp/${ctx.subProject.id}/cost/tender/${ctx.tender.id}/${stage_type}/${newStage.stage_order}/stage`);
             } catch (err) {
                 ctx.log(err);
                 ctx.postError(err, '新增期失败');

+ 43 - 0
app/controller/dashboard_controller.js

@@ -44,6 +44,9 @@ module.exports = app => {
             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 allAuditCostStageLedger = await ctx.service.costStageAudit.getAuditStage('ledger', ctx.session.sessionUser.accountId);
+            const allAuditCostStageBook = await ctx.service.costStageAudit.getAuditStage('book', ctx.session.sessionUser.accountId);
+            const allAuditCostStageAnalysis = await ctx.service.costStageAudit.getAuditStage('analysis', 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);
@@ -60,6 +63,9 @@ module.exports = app => {
             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 auditShenpiCostStageLedger = await ctx.service.costStageAudit.getDonesByAudit('ledger', ctx.session.sessionUser.accountId);
+            const auditShenpiCostStageBook = await ctx.service.costStageAudit.getDonesByAudit('book', ctx.session.sessionUser.accountId);
+            const auditShenpiCostStageAnalysis = await ctx.service.costStageAudit.getDonesByAudit('analysis', ctx.session.sessionUser.accountId);
             const dashboardStatus = {
                 all: 0,
                 dashboard: 0,
@@ -81,6 +87,9 @@ module.exports = app => {
                     safeInspection: 0,
                     safeStage: 0,
                     phasePay: 0,
+                    costStageLedger: 0,
+                    costStageBook: 0,
+                    costStageAnalysis: 0,
                 },
             };
             let noticeList = [];
@@ -118,6 +127,12 @@ module.exports = app => {
                 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 spCostStageLedger = subProject.page_show.cost ? ctx.helper._.filter(auditShenpiCostStageLedger, { spid: subProject.id }) : [];
+                noticeList.push(...ctx.helper.addKeyValue4ObjArray(spCostStageLedger, 'shenpi_type', 'costStageLedger'));
+                const spCostStageBook = subProject.page_show.cost ? ctx.helper._.filter(auditShenpiCostStageBook, { spid: subProject.id }) : [];
+                noticeList.push(...ctx.helper.addKeyValue4ObjArray(spCostStageBook, 'shenpi_type', 'costStageBook'));
+                const spCostStageAnalysis = subProject.page_show.cost ? ctx.helper._.filter(auditShenpiCostStageAnalysis, { spid: subProject.id }) : [];
+                noticeList.push(...ctx.helper.addKeyValue4ObjArray(spCostStageAnalysis, 'shenpi_type', 'costStageAnalysis'));
             }
             const noticeDayList = [];
             noticeList = ctx.helper._.orderBy(noticeList, ['shenpi_time'], ['desc']);
@@ -159,6 +174,12 @@ module.exports = app => {
             dashboardShenpis.push(...auditSafeStage);
             const auditPhasePay = await this.auditSet(ctx, allAuditPhasePay, subProjects, dashboardStatus, 'phasePay');
             dashboardShenpis.push(...auditPhasePay);
+            const auditCostStageLedger = await this.auditSet(ctx, allAuditCostStageLedger, subProjects, dashboardStatus, 'costStageLedger');
+            dashboardShenpis.push(...auditCostStageLedger);
+            const auditCostStageBook = await this.auditSet(ctx, allAuditCostStageBook, subProjects, dashboardStatus, 'costStageBook');
+            dashboardShenpis.push(...auditCostStageBook);
+            const auditCostStageAnalysis = await this.auditSet(ctx, allAuditCostStageAnalysis, subProjects, dashboardStatus, 'costStageAnalysis');
+            dashboardShenpis.push(...auditCostStageAnalysis);
             // console.log(ctx.helper._.orderBy(dashboardShenpis, ['start_audit', 'shenpi_time'], ['desc', 'desc']));
             const projectData = await ctx.service.project.getDataById(ctx.session.sessionProject.id);
             // 获取销售人员数据
@@ -192,6 +213,7 @@ module.exports = app => {
                 acInspection: auditConst.inspection,
                 acSafeStage: auditConst.safeStage,
                 acPhasePay: auditConst.phasePay,
+                acCostStage: auditConst.costStage,
                 noticeList,
                 noticeDayList,
                 pushType: auditConst.pushType,
@@ -310,6 +332,12 @@ module.exports = app => {
                             if (!sp.page_show.phasePay) closeType = true;
                             calcTime = t.create_time;
                             break;
+                        case 'costStageLedger':
+                        case 'costStageBook':
+                        case 'costStageAnalysis':
+                            if (!sp.page_show.cost) closeType = true;
+                            calcTime = t.create_time;
+                            break;
                         default:
                             closeType = true;
                     }
@@ -359,6 +387,9 @@ module.exports = app => {
             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 auditCostStageLedger = ctx.subProject.page_show.cost ? await ctx.service.costStageAudit.getAuditStage('ledger', ctx.session.sessionUser.accountId, ctx.subProject.id) : [];
+            const auditCostStageBook = ctx.subProject.page_show.cost ? await ctx.service.costStageAudit.getAuditStage('book', ctx.session.sessionUser.accountId, ctx.subProject.id) : [];
+            const auditCostStageAnalysis = ctx.subProject.page_show.cost ? await ctx.service.costStageAudit.getAuditStage('analysis', 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);
@@ -392,6 +423,11 @@ module.exports = app => {
             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: '合同支付' });
+            if (ctx.subProject.page_show.cost) {
+                shenpi_count.push({ count: await ctx.service.costStageAudit.getCountByChecked('ledger', ctx.session.sessionUser.accountId, ctx.subProject.id), name: '成本报审' });
+                shenpi_count.push({ count: await ctx.service.costStageAudit.getCountByChecked('book', ctx.session.sessionUser.accountId, ctx.subProject.id), name: '财务账面' });
+                shenpi_count.push({ count: await ctx.service.costStageAudit.getCountByChecked('analysis', 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 = [
@@ -409,6 +445,9 @@ module.exports = app => {
                 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,
+                ctx.subProject.page_show.cost ? await ctx.service.costStageAudit.getLastEndTimeByChecked('ledger', ctx.session.sessionUser.accountId, ctx.subProject.id) : null,
+                ctx.subProject.page_show.cost ? await ctx.service.costStageAudit.getLastEndTimeByChecked('book', ctx.session.sessionUser.accountId, ctx.subProject.id) : null,
+                ctx.subProject.page_show.cost ? await ctx.service.costStageAudit.getLastEndTimeByChecked('analysis', 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));
@@ -429,6 +468,9 @@ module.exports = app => {
                 auditSafeInspections,
                 auditSafeStage,
                 auditPhasePay,
+                auditCostStageLedger,
+                auditCostStageBook,
+                auditCostStageAnalysis,
                 shenpi_count,
                 total_count,
                 last_day: ctx.helper.calcDayNum(last_time),
@@ -447,6 +489,7 @@ module.exports = app => {
                 acInspection: auditConst.inspection,
                 acSafeStage: auditConst.safeStage,
                 acPhasePay: auditConst.phasePay,
+                acCostStage: auditConst.costStage,
                 noticeList,
                 pushType: auditConst.pushType,
                 projectData,

+ 1 - 1
app/middleware/cost_stage_check.js

@@ -41,7 +41,7 @@ module.exports = options => {
 
             // 读取原报、审核人数据
             yield this.service.costStage.doCheckStage(costStage);
-            costStage.latestOrder = yield this.service.costStage.count({ tid: this.tender.id });
+            costStage.latestOrder = yield this.service.costStage.count({ tid: this.tender.id, stage_type: stageType });
             costStage.isLatest = costStage.latestOrder === costStage.stage_order;
             if (stageType === 'book') costStage.relaStage = yield this.service.costStage.getStage(costStage.rela_stage.sid);
             yield this.service.costStage.checkShenpi(costStage);

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

@@ -1949,6 +1949,24 @@ overflow-y: auto;
 .bg-new-phasepay{
     background: rgba(200, 51, 6, 0.08) !important;
 }
+.bg-new-coststage{
+    background: rgba(0, 14, 126, 0.08) !important;
+}
+.bg-new-19{
+    background: rgba(23, 144, 180, 0.08) !important;
+}
+.bg-new-20{
+    background: rgba(120, 98, 83, 0.08) !important;
+}
+.bg-new-21{
+    background: rgba(196, 90, 101, 0.08) !important;
+}
+.bg-new-22{
+    background: rgba(211, 162, 55, 0.08) !important;
+}
+.bg-new-23{
+    background: rgba(46, 32, 29, 0.08) !important;
+}
 .text-new-advance{
   color: rgba(241, 82, 91, 1) !important;
 }
@@ -1988,6 +2006,30 @@ overflow-y: auto;
 .text-new-phasepay{
     color: rgba(200, 51, 6, 1) !important;
 }
+.text-new-coststage{
+    color: rgba(0, 14, 126, 1) !important;
+}
+/* 以下为待使用颜色, 使用时请修改名称 */
+.text-new-19{
+    /* 群青 */
+    color: rgba(23, 144, 180, 1) !important;
+}
+.text-new-20{
+    /* 沉香 */
+    color: rgba(120, 98, 83, 1) !important;
+}
+.text-new-21{
+    /* 梅红 */
+    color: rgba(196, 90, 101, 1) !important;
+}
+.text-new-22{
+    /* 鞠衣 */
+    color: rgba(211, 162, 55, 1) !important;
+}
+.text-new-23{
+    /* 玄天 */
+    color: rgba(46, 32, 29, 1) !important;
+}
 .text-width{
   width: 66px;
   text-align: center;

+ 38 - 36
app/service/cost_stage_audit.js

@@ -118,27 +118,27 @@ module.exports = app => {
             }
             return history;
         }
-        async getAllAuditors(tenderId) {
+        async getAllAuditors(tenderId, stage_type) {
             const sql =
                 'SELECT audit_id, tid FROM ' + this.tableName +
-                '  WHERE tid = ?' +
+                '  WHERE tid = ? AND stage_type = ?' +
                 '  GROUP BY audit_id';
-            const sqlParam = [tenderId];
+            const sqlParam = [tenderId, stage_type];
             return this.db.query(sql, sqlParam);
         }
-        async getAuditStage(auditorId, spid = '') {
+        async getAuditStage(stage_type, 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.`stage_id`,' +
-                '    s.`stage_order`, s.`stage_code`, s.`stage_date`, s.create_time,' +
+                '    s.`stage_order`, s.`stage_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.costStage.tableName} AS s On sa.stage_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 +
+                '  WHERE sa.`audit_id` = ? and sa.stage_type = ? 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 sqlParam = [auditorId, stage_type, 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) {
@@ -157,15 +157,16 @@ module.exports = app => {
          * @param auditorId
          * @return {Promise<*>}
          */
-        async getDonesByAudit(auditorId, spid = '') {
+        async getDonesByAudit(stage_type, auditorId, spid = '') {
             const spSql = spid ? ' and t.`spid` = "' + spid + '"' : '';
             const sql =
-                'SELECT ssa.audit_status, ssa.audit_time AS shenpi_time, ssa.stage_id, t.id, ss.stage_code, ss.stage_order, t.name, t.spid ' +
+                'SELECT ssa.audit_status, ssa.audit_time AS shenpi_time, ssa.stage_id, t.id, ss.stage_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.costStage.tableName} AS ss ON ssa.stage_id = ss.id` +
-                '  WHERE ssa.audit_id = ? AND ssa.audit_status in (' + this.ctx.helper.getInArrStrSqlFilter(checkRelaStatus) + ')' + spSql +
+                '  WHERE ssa.audit_id = ? AND ss.stage_type = ? 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);
+            const sqlParam = [auditorId, stage_type];
+            const result = await this.db.query(sql, sqlParam);
+            return result;
         }
         /**
          * 获取最近一次审批结束时间
@@ -173,13 +174,12 @@ module.exports = app => {
          * @param auditorId
          * @return {Promise<*>}
          */
-        async getLastEndTimeByChecked(auditorId, spid = '') {
+        async getLastEndTimeByChecked(stage_type, 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 = ? ` +
+            const sql = `SELECT a.audit_time, t.spid 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.stage_type = ? ` +
                 'AND a.`audit_status` in (' + this.ctx.helper.getInArrStrSqlFilter(checkRelaStatus) + ')' + sqSql +
                 ' ORDER BY a.`audit_time` DESC';
-            const sqlParam = [auditorId];
+            const sqlParam = [auditorId, stage_type];
             const result = await this.db.queryOne(sql, sqlParam);
             return result ? result.audit_time : null;
         }
@@ -189,11 +189,11 @@ module.exports = app => {
          * @param auditorId
          * @return {Promise<*>}
          */
-        async getCountByChecked(auditorId, spid = '') {
+        async getCountByChecked(stage_type, 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];
+                    ' WHERE a.audit_id = ? AND a.stage_type = ? AND a.audit_status in (' + this.ctx.helper.getInArrStrSqlFilter(checkRelaStatus) + ') AND t.`spid` = ?';
+                const sqlParam = [auditorId, stage_type, spid];
                 const result = await this.db.queryOne(sql, sqlParam);
                 return result.count ? result.count : 0;
             }
@@ -259,12 +259,13 @@ module.exports = app => {
             // 判断是否存在固定终审,存在则newOrder - 1并使终审order+1
             newOrder = is_gdzs === 1 ? newOrder - 1 : newOrder;
             newAuditOrder = is_gdzs === 1 ? newAuditOrder - 1 : newAuditOrder;
+            const costStage = await this.ctx.service.costStage.getStage(stageId);
 
             const transaction = await this.db.beginTransaction();
             try {
                 if (is_gdzs) await this._syncAuditOrder(transaction, stageId, newOrder, auditTimes, '+');
                 const data = {
-                    tid: this.ctx.tender.id, stage_id: stageId, audit_id: auditor.id,
+                    tid: this.ctx.tender.id, stage_id: stageId, stage_type: costStage.stage_type, audit_id: auditor.id,
                     name: auditor.name, company: auditor.company, role: auditor.role, mobile: auditor.mobile,
                     audit_times: auditTimes, active_order: newOrder, audit_status: auditConst.costStage.status.uncheck,
                     audit_order: newAuditOrder, audit_type: auditType.key.common,
@@ -318,7 +319,7 @@ module.exports = app => {
             // 添加原报
             const user = await this.ctx.service.projectAccount.getDataById(this.ctx.session.sessionUser.accountId);
             newAuditors.push({
-                tid: newStage.tid, stage_id: newStage.id,
+                tid: newStage.tid, stage_id: newStage.id, stage_type: newStage.stage_type,
                 audit_id: this.ctx.session.sessionUser.accountId,
                 audit_times: 1, audit_order: 0, audit_type: auditConst.auditType.key.common,
                 active_order: 0, audit_status: auditConst.costStage.status.uncheck,
@@ -328,7 +329,7 @@ module.exports = app => {
             for (const a of auditors) {
                 if (a.audit_order === 0) continue;
                 newAuditors.push({
-                    tid: newStage.tid, stage_id: newStage.id,
+                    tid: newStage.tid, stage_id: newStage.id, stage_type: newStage.stage_type,
                     audit_id: a.audit_id,
                     audit_times: 1, audit_order: a.audit_order, audit_type: a.audit_type,
                     active_order: a.audit_order, audit_status: auditConst.costStage.status.uncheck,
@@ -352,7 +353,7 @@ module.exports = app => {
                     const auditorInfo = newAuditsInfo.find(x => { return x.id === auditor.audit_id; });
                     if (!auditorInfo) throw '配置的审批人不存在';
                     newAuditors.push({
-                        tid: stage.tid, stage_id: stage.id, audit_id: auditor.audit_id,
+                        tid: stage.tid, stage_id: stage.id, audit_id: auditor.audit_id, stage_type: stage.stage_type,
                         name: auditorInfo.name, company: auditorInfo.company, role: auditorInfo.role, mobile: auditorInfo.mobile,
                         audit_times: stage.audit_times, active_order: auditor.audit_order, audit_status: auditConst.costStage.status.uncheck,
                         audit_type: auditor.audit_type, audit_order: auditor.audit_order,
@@ -408,7 +409,7 @@ module.exports = app => {
                 // 添加终审
                 if (lastUser) {
                     const newAuditor = {
-                        tid: stage.tid, stage_id: stage.id, audit_id: lastId,
+                        tid: stage.tid, stage_id: stage.id, stage_type: stage.stage_type, audit_id: lastId,
                         name: lastUser.name, company: lastUser.company, role: lastUser.role, mobile: lastUser.mobile,
                         audit_times: stage.audit_times, active_order: auditOrder, audit_status: auditConst.costStage.status.uncheck,
                         audit_type: auditType.key.common, audit_order: auditOrder,
@@ -543,6 +544,7 @@ module.exports = app => {
                 const noticeContent = await this._getNoticeContent(this.ctx.session.sessionProject.id, stage.tid, stage.id, accountId, opinion);
                 const defaultNoticeRecord = {
                     pid: this.ctx.session.sessionProject.id,
+                    spid: this.ctx.tender.spid,
                     tid: stage.tid,
                     type: pushType[stage.typeInfo.push_type],
                     status: auditConst.costStage.status.checked,
@@ -657,7 +659,7 @@ module.exports = app => {
             const auditors = await this.getUniqAuditors(stage); // 全部参与的审批人
             const newAuditors = auditors.map(x => {
                 return {
-                    tid: stage.tid, stage_id: stage.id, audit_id: x.audit_id,
+                    tid: stage.tid, stage_id: stage.id, stage_type: stage.stage_type, audit_id: x.audit_id,
                     audit_times: stage.audit_times + 1, audit_order: x.audit_order, audit_type: x.audit_type,
                     active_order: x.audit_order, audit_status: auditConst.costStage.status.uncheck,
                     name: x.name, company: x.company, role: x.role, mobile: x.mobile,
@@ -668,7 +670,7 @@ module.exports = app => {
             try {
                 // 添加提醒
                 const noticeContent = await this._getNoticeContent(pid, selfAudit.tid, stage.id, selfAudit.audit_id, opinion);
-                const defaultNoticeRecord = { pid, tid: selfAudit.tid, type: pushType[stage.typeInfo.push_type], status: auditConst.costStage.status.checkNo, content: noticeContent };
+                const defaultNoticeRecord = { pid, spid: this.ctx.tender.spid, tid: selfAudit.tid, type: pushType[stage.typeInfo.push_type], status: auditConst.costStage.status.checkNo, content: noticeContent };
                 const records = stage.userIds.map(x => {
                     return { uid: x, ...defaultNoticeRecord };
                 });
@@ -729,7 +731,7 @@ module.exports = app => {
                 // 添加通知
                 const noticeContent = await this._getNoticeContent(pid, stage.tid, stage.id, selfAudit.audit_id, opinion);
                 const defaultNoticeRecord = {
-                    pid, tid: stage.tid, type: pushType[stage.typeInfo.push_type], status: auditConst.costStage.status.checkNoPre, content: noticeContent,
+                    pid, spid: this.ctx.tender.spid, tid: stage.tid, type: pushType[stage.typeInfo.push_type], status: auditConst.costStage.status.checkNoPre, content: noticeContent,
                 };
                 const records = stage.userIds.map(x => {
                     return { uid: x, ...defaultNoticeRecord };
@@ -759,7 +761,7 @@ module.exports = app => {
                 const newAuditors = [], uncheckAuditors = [];
                 preAuditors.forEach(x => {
                     newAuditors.push({
-                        tid: x.tid, stage_id: x.stage_id, audit_id: x.audit_id,
+                        tid: x.tid, stage_id: x.stage_id, stage_type: x.stage_type, audit_id: x.audit_id,
                         audit_times: x.audit_times, audit_order: selfAudit.audit_order - 1,
                         audit_status: auditConst.costStage.status.checking,
                         audit_type: x.audit_type, active_order: selfAudit.active_order + 1,
@@ -773,7 +775,7 @@ module.exports = app => {
                 }
                 stage.flowAuditors.forEach(x => {
                     uncheckAuditors.push({
-                        tid: x.tid, stage_id: x.stage_id, audit_id: x.audit_id,
+                        tid: x.tid, stage_id: x.stage_id, stage_type: x.stage_type, audit_id: x.audit_id,
                         audit_times: x.audit_times, active_order: selfAudit.active_order + 2,
                         audit_status: auditConst.costStage.status.uncheck,
                         audit_type: x.audit_type, audit_order: x.audit_order,
@@ -855,7 +857,7 @@ module.exports = app => {
                 const checkAgainAuditors = [], checkingAuditors = [];
                 finalAudits.forEach(x => {
                     checkAgainAuditors.push({
-                        tid: x.tid, stage_id: x.stage_id, audit_id: x.audit_id,
+                        tid: x.tid, stage_id: x.stage_id, stage_type: x.stage_type, audit_id: x.audit_id,
                         audit_type: x.audit_type, audit_order: x.audit_order,
                         audit_times: x.audit_times, active_order: x.active_order + 1,
                         audit_status: x.audit_id === finalAudit.audit_id ? auditConst.costStage.status.checkAgain : auditConst.costStage.status.checkSkip,
@@ -865,7 +867,7 @@ module.exports = app => {
                 });
                 finalAudits.forEach(x => {
                     checkingAuditors.push({
-                        tid: x.tid, stage_id: x.stage_id, audit_id: x.audit_id,
+                        tid: x.tid, stage_id: x.stage_id, stage_type: x.stage_type, audit_id: x.audit_id,
                         audit_type: x.audit_type, audit_order: x.audit_order,
                         audit_times: x.audit_times, active_order: x.active_order + 2,
                         audit_status: auditConst.costStage.status.checking, audit_time: time, opinion: '',
@@ -990,7 +992,7 @@ module.exports = app => {
                 const checkCancelAuditors = [], checkingAuditors = [];
                 stage.preAuditors.forEach(x => {
                     checkCancelAuditors.push({
-                        tid: stage.tid, stage_id: stage.id, audit_id: x.audit_id,
+                        tid: stage.tid, stage_id: stage.id, stage_type: stage.stage_type, audit_id: x.audit_id,
                         audit_times: x.audit_times, active_order: x.active_order + 1,
                         audit_type: x.audit_type, audit_order: x.audit_order,
                         audit_status: x.audit_id === selfAuditor.audit_id ? auditConst.costStage.status.checkCancel : auditConst.costStage.status.checkSkip,
@@ -1000,7 +1002,7 @@ module.exports = app => {
                 });
                 stage.preAuditors.forEach(x => {
                     checkingAuditors.push({
-                        tid: stage.tid, stage_id: stage.id, audit_id: x.audit_id,
+                        tid: stage.tid, stage_id: stage.id, stage_type: stage.stage_type, audit_id: x.audit_id,
                         audit_times: x.audit_times, active_order: x.active_order + 2,
                         audit_type: x.audit_type, audit_order: x.audit_order,
                         audit_status: auditConst.costStage.status.checking,
@@ -1054,7 +1056,7 @@ module.exports = app => {
                 const newAuditors = [];
                 stage.preAuditors.forEach(x => {
                     newAuditors.push({
-                        tid: stage.tid, stage_id: stage.id, audit_id: x.audit_id,
+                        tid: stage.tid, stage_id: stage.id, stage_type: stage.stage_type, audit_id: x.audit_id,
                         audit_times: x.audit_times, active_order: x.active_order + 1,
                         audit_type: x.audit_type, audit_order: x.audit_order,
                         audit_status: x.audit_id === selfAuditor.audit_id ? auditConst.costStage.status.checkCancel : auditConst.costStage.status.checkSkip,
@@ -1105,7 +1107,7 @@ module.exports = app => {
                 const checkCancelAuditors = [], checkingAuditors = [];
                 stage.preAuditors.forEach(x => {
                     checkCancelAuditors.push({
-                        tid: stage.tid, stage_id: stage.id, audit_id: x.audit_id,
+                        tid: stage.tid, stage_id: stage.id, stage_type: stage.stage_type, audit_id: x.audit_id,
                         audit_times: x.audit_times, active_order: x.active_order + 1,
                         audit_type: x.audit_type, audit_order: x.audit_order,
                         audit_status: x.audit_id === selfAuditor.audit_id ? auditConst.costStage.status.checkCancel : auditConst.costStage.status.checkSkip,
@@ -1115,7 +1117,7 @@ module.exports = app => {
                 });
                 stage.preAuditors.forEach(x => {
                     checkingAuditors.push({
-                        tid: stage.tid, stage_id: stage.id, audit_id: x.audit_id,
+                        tid: stage.tid, stage_id: stage.id, stage_type: stage.stage_type, audit_id: x.audit_id,
                         audit_times: x.audit_times, active_order: x.active_order + 2,
                         audit_type: x.audit_type, audit_order: x.audit_order,
                         audit_status: auditConst.costStage.status.checking,

+ 1 - 1
app/service/notice_push.js

@@ -67,7 +67,7 @@ module.exports = app => {
             // });
             const uidSql = uid ? ' AND a.`uid` = ' + uid : '';
             const spidSql = spid ? ' AND (a.`spid` = "' + spid + '" OR t.`spid` = "' + spid + '")': '';
-            const sql = 'SELECT a.* FROM ?? AS a LEFT JOIN ?? AS t ON a.`tid` = t.`id` WHERE a.`pid` = ?' + uidSql + spidSql + ' ORDER BY a.`create_time` DESC LIMIT 0,30';
+            const sql = 'SELECT a.*, t.spid FROM ?? AS a LEFT JOIN ?? AS t ON a.`tid` = t.`id` WHERE a.`pid` = ?' + uidSql + spidSql + ' ORDER BY a.`create_time` DESC LIMIT 0,30';
             const params = [this.tableName, this.ctx.service.tender.tableName, pid];
             let notice = await this.db.query(sql, params);
             notice = notice.map(v => {

Datei-Diff unterdrückt, da er zu groß ist
+ 72 - 1
app/view/dashboard/index.ejs


+ 61 - 2
app/view/dashboard/workspace.ejs

@@ -145,6 +145,15 @@
                                             <% if (dashboardStatus.shenpi.phasePay !== 0) { %>
                                             <option value="phasePay">合同支付(<%- dashboardStatus.shenpi.phasePay %>)</option>
                                             <% } %>
+                                            <% if (dashboardStatus.shenpi.costStageLedger !== 0) { %>
+                                            <option value="costStageLedger">成本报审(<%- dashboardStatus.shenpi.costStageLedger %>)</option>
+                                            <% } %>
+                                            <% if (dashboardStatus.shenpi.costStageLedger !== 0) { %>
+                                            <option value="costStageBook">财务账面(<%- dashboardStatus.shenpi.costStageBook %>)</option>
+                                            <% } %>
+                                            <% if (dashboardStatus.shenpi.costStageLedger !== 0) { %>
+                                            <option value="costStageAnalysis">成本分析(<%- dashboardStatus.shenpi.costStageAnalysis %>)</option>
+                                            <% } %>
                                         </select>
                                     </div>
                                 </div>
@@ -472,6 +481,39 @@
                                                             <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 %>/detail" 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 === 'costStageLedger') { %>
+                                                        <% const am = db; %>
+                                                        <tr data-type="costStageLedger">
+                                                            <% 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-coststage text-new-coststage badge text-width">成本报审</span></td>
+                                                            <td><a href="/sp/<%- am.spid %>/dashboard"><%- am.sp_name %></a></td>
+                                                            <td><a href="/sp/<%- am.spid %>/cost/tender/<%- am.tid %>/ledger"><%- am.name %></a> <a href="/sp/<%- am.spid %>/cost/tender/<%- am.tid %>/ledger/<%- am.stage_order %>/stage">第<%- am.stage_order %>期</a></td>
+                                                            <td>第<%- am.stage_order %>期</td>
+                                                            <td><%- (am.begin_time ? ctx.moment(am.begin_time).format('YYYY/MM/DD HH:mm') : '') %></td>
+                                                            <td><a href="/sp/<%- am.spid %>/cost/tender/<%- am.tid %>/ledger/<%- am.stage_order %>/stage" 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 === 'costStageBook') { %>
+                                                        <% const am = db; %>
+                                                        <tr data-type="costStageBook">
+                                                            <% 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-coststage text-new-coststage badge text-width">财务账面</span></td>
+                                                            <td><a href="/sp/<%- am.spid %>/dashboard"><%- am.sp_name %></a></td>
+                                                            <td><a href="/sp/<%- am.spid %>/cost/tender/<%- am.tid %>/book"><%- am.name %></a> <a href="/sp/<%- am.spid %>/cost/tender/<%- am.tid %>/book/<%- am.stage_order %>/stage">第<%- am.stage_order %>期</a></td>
+                                                            <td>第<%- am.stage_order %>期</td>
+                                                            <td><%- (am.begin_time ? ctx.moment(am.begin_time).format('YYYY/MM/DD HH:mm') : '') %></td>
+                                                            <td><a href="/sp/<%- am.spid %>/cost/tender/<%- am.tid %>/book/<%- am.stage_order %>/stage" 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 === 'costStageAnalaysis') { %>
+                                                        <% const am = db; %>
+                                                        <tr data-type="costStageAnalysis">
+                                                            <% 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-coststage text-new-coststage badge text-width">成本分析</span></td>
+                                                            <td><a href="/sp/<%- am.spid %>/dashboard"><%- am.sp_name %></a></td>
+                                                            <td><a href="/sp/<%- am.spid %>/cost/tender/<%- am.tid %>/analysis"><%- am.name %></a> <a href="/sp/<%- am.spid %>/cost/tender/<%- am.tid %>/analysis/<%- am.stage_order %>/stage">第<%- am.stage_order %>期</a></td>
+                                                            <td>第<%- am.stage_order %>期</td>
+                                                            <td><%- (am.begin_time ? ctx.moment(am.begin_time).format('YYYY/MM/DD HH:mm') : '') %></td>
+                                                            <td><a href="/sp/<%- am.spid %>/cost/tender/<%- am.tid %>/analysis/<%- am.stage_order %>/stage" 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>
@@ -644,6 +686,8 @@
     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 acSafeStage = JSON.parse(unescape('<%- escape(JSON.stringify(acSafeStage)) %>'));
+    const acCostStage = JSON.parse(unescape('<%- escape(JSON.stringify(acCostStage)) %>'));
     const typeColMap = JSON.parse(unescape('<%- escape(JSON.stringify(typeColMap)) %>'));
     const userMsgPermission = false;
 
@@ -907,7 +951,23 @@
                                         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>`);
+                                            <span class="${acPhasePay.auditStringClass[n.audit_status]}">${acPhasePay.auditString[n.audit_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;
+                                    case 'safeStage':
+                                        html.push(`<li class="list-group-item">
+                                            <span class="${acSafeStage.auditStringClass[n.audit_status]}">${acSafeStage.auditString[n.audit_status]}</span> <a href="/sp/${n.spid}/safe/tender/${n.id}/stage/${n.stage_order}/bills" target="_blank">${n.name}</a> 安全计量 ${n.name}<span class="float-right">${moment(new Date(n.shenpi_time)).format('HH:mm:ss')}</span></li>`);
+                                        break;
+                                    case 'costStageLedger':
+                                        html.push(`<li class="list-group-item">
+                                            <span class="${acCostStage.auditStringClass[n.audit_status]}">${acCostStage.auditString[n.audit_status]}</span> <a href="/sp/${n.spid}/cost/tender/${n.id}/ledger/${n.stage_order}/stage" target="_blank">${n.name}</a> 成本报审 ${n.name}<span class="float-right">${moment(new Date(n.shenpi_time)).format('HH:mm:ss')}</span></li>`);
+                                        break;
+                                    case 'costStageBook':
+                                        html.push(`<li class="list-group-item">
+                                            <span class="${acCostStage.auditStringClass[n.audit_status]}">${acCostStage.auditString[n.audit_status]}</span> <a href="/sp/${n.spid}/cost/tender/${n.id}/book/${n.stage_order}/stage" target="_blank">${n.name}</a> 财务账面 ${n.name}<span class="float-right">${moment(new Date(n.shenpi_time)).format('HH:mm:ss')}</span></li>`);
+                                        break;
+                                    case 'costStageAnalyssi':
+                                        html.push(`<li class="list-group-item">
+                                            <span class="${acCostStage.auditStringClass[n.audit_status]}">${acCostStage.auditString[n.audit_status]}</span> <a href="/sp/${n.spid}/cost/tender/${n.id}/analysis/${n.stage_order}/stage" 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;
                                 }
@@ -980,7 +1040,6 @@
                 const params = _param && _param[0] ? _param[0] : null;
                 if (params !== null) {
                     const tender = tenders.filter(t => t.stage_count > 0)[params.dataIndex];
-                    console.log(tender);
                     window.open(`/sp/${tender.spid}/datacollect`);
                 }
             }

+ 1 - 0
sql/update.sql

@@ -73,6 +73,7 @@ CREATE TABLE `zh_cost_stage_audit`  (
   `id` bigint(20) NOT NULL AUTO_INCREMENT,
   `tid` int(11) UNSIGNED NOT NULL COMMENT '标段id',
   `stage_id` varchar(36) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL DEFAULT '' COMMENT '期id',
+  `stage_type` varchar(20) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT '期类型',
   `audit_id` int(11) UNSIGNED NOT NULL COMMENT '流程参与人id(含原报)',
   `name` varchar(30) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL DEFAULT '' COMMENT '参与人-姓名',
   `company` varchar(60) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL DEFAULT '' COMMENT '参与人-单位',