|
@@ -62,7 +62,8 @@ module.exports = app => {
|
|
|
async getAuditorsByStatus(qiId, status, times = 1) {
|
|
async getAuditorsByStatus(qiId, status, times = 1) {
|
|
|
const inspection = await this.ctx.service.qualityInspection.getDataById(qiId);
|
|
const inspection = await this.ctx.service.qualityInspection.getDataById(qiId);
|
|
|
if (inspection && inspection.flow_version === 1) {
|
|
if (inspection && inspection.flow_version === 1) {
|
|
|
- const auditors = await this.getAuditors(qiId, inspection.times);
|
|
|
|
|
|
|
+ let auditors = await this.getAuditors(qiId, inspection.times);
|
|
|
|
|
+ if (await this.prepareSequentialFlow(inspection, auditors)) auditors = await this.getAuditors(qiId, inspection.times);
|
|
|
return auditors.filter(x => !x.is_old && x.flow_stage === inspection.flow_stage && x.stage_round === inspection.stage_round && [2, 12].includes(x.status) && [2, 6, 12].includes(inspection.status));
|
|
return auditors.filter(x => !x.is_old && x.flow_stage === inspection.flow_stage && x.stage_round === inspection.stage_round && [2, 12].includes(x.status) && [2, 6, 12].includes(inspection.status));
|
|
|
}
|
|
}
|
|
|
let auditor = [];
|
|
let auditor = [];
|
|
@@ -1351,14 +1352,17 @@ module.exports = app => {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
async activateFlow(transaction, inspection, stage) {
|
|
async activateFlow(transaction, inspection, stage) {
|
|
|
- const records = await transaction.select(this.tableName, { where: { qiid: inspection.id, times: inspection.times, flow_stage: stage, stage_round: inspection.stage_round, is_old: 0, status: 1 }, orders: [['order', 'asc']] });
|
|
|
|
|
|
|
+ let records = await transaction.select(this.tableName, { where: { qiid: inspection.id, times: inspection.times, flow_stage: stage, stage_round: inspection.stage_round, is_old: 0 }, orders: [['order', 'asc'], ['id', 'asc']] });
|
|
|
|
|
+ if (stage === 2) await this.normalizeRectificationFlow(transaction, inspection, records, false);
|
|
|
|
|
+ records = records.filter(x => x.status === 1).sort((a, b) => a.order - b.order || a.id - b.id);
|
|
|
if (!records.length) throw '请先设置' + auditConst.stageString[stage] + '人员';
|
|
if (!records.length) throw '请先设置' + auditConst.stageString[stage] + '人员';
|
|
|
- const active = stage === 2 ? records : records.filter(x => x.order === records[0].order);
|
|
|
|
|
|
|
+ const active = stage === 2 ? records.slice(0, 1) : records.filter(x => x.order === records[0].order);
|
|
|
const status = stage === 2 ? 12 : 2;
|
|
const status = stage === 2 ? 12 : 2;
|
|
|
const begin_time = new Date();
|
|
const begin_time = new Date();
|
|
|
await transaction.updateRows(this.tableName, active.map(x => ({ id: x.id, status, begin_time })));
|
|
await transaction.updateRows(this.tableName, active.map(x => ({ id: x.id, status, begin_time })));
|
|
|
- await transaction.update(this.ctx.service.qualityInspection.tableName, { id: inspection.id, flow_stage: stage, stage_round: inspection.stage_round, status });
|
|
|
|
|
- Object.assign(inspection, { flow_stage: stage, status });
|
|
|
|
|
|
|
+ const update = { id: inspection.id, flow_stage: stage, stage_round: inspection.stage_round, status };
|
|
|
|
|
+ await transaction.update(this.ctx.service.qualityInspection.tableName, update);
|
|
|
|
|
+ Object.assign(inspection, update);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
async processFlow(inspection, data) {
|
|
async processFlow(inspection, data) {
|
|
@@ -1370,6 +1374,7 @@ module.exports = app => {
|
|
|
const uid = this.ctx.session.sessionUser.accountId;
|
|
const uid = this.ctx.session.sessionUser.accountId;
|
|
|
const ownerEdit = current.uid === uid && [1, 5].includes(current.status);
|
|
const ownerEdit = current.uid === uid && [1, 5].includes(current.status);
|
|
|
const records = await transaction.select(this.tableName, { where: { qiid: current.id, times: current.times, is_old: 0 }, orders: [['order', 'asc'], ['id', 'asc']] });
|
|
const records = await transaction.select(this.tableName, { where: { qiid: current.id, times: current.times, is_old: 0 }, orders: [['order', 'asc'], ['id', 'asc']] });
|
|
|
|
|
+ await this.normalizeRectificationFlow(transaction, current, records);
|
|
|
const active = records.filter(x => x.flow_stage === current.flow_stage && x.stage_round === current.stage_round && [2, 12].includes(x.status));
|
|
const active = records.filter(x => x.flow_stage === current.flow_stage && x.stage_round === current.stage_round && [2, 12].includes(x.status));
|
|
|
const self = [2, 6, 12].includes(current.status) ? active.find(x => x.aid === uid) : null;
|
|
const self = [2, 6, 12].includes(current.status) ? active.find(x => x.aid === uid) : null;
|
|
|
const report = records.filter(x => x.flow_stage === 1);
|
|
const report = records.filter(x => x.flow_stage === 1);
|
|
@@ -1415,13 +1420,13 @@ module.exports = app => {
|
|
|
if (stageRecords.some(x => x.aid === id)) throw '该人员已存在';
|
|
if (stageRecords.some(x => x.aid === id)) throw '该人员已存在';
|
|
|
const users = await this.ctx.service.projectAccount.getAllSubProjectAccount(this.ctx.subProject);
|
|
const users = await this.ctx.service.projectAccount.getAllSubProjectAccount(this.ctx.subProject);
|
|
|
if (!users.some(x => x.id === id)) throw '该用户不在当前项目中';
|
|
if (!users.some(x => x.id === id)) throw '该用户不在当前项目中';
|
|
|
- let order = stage === 2 ? 1 : stageRecords.reduce((n, x) => Math.max(n, x.order), 0) + 1;
|
|
|
|
|
|
|
+ let order = stageRecords.reduce((n, x) => Math.max(n, x.order), 0) + 1;
|
|
|
if (stage === 1 && mode === shenpiConst.sp_status.gdzs && stageRecords.length) {
|
|
if (stage === 1 && mode === shenpiConst.sp_status.gdzs && stageRecords.length) {
|
|
|
const last = stageRecords[stageRecords.length - 1];
|
|
const last = stageRecords[stageRecords.length - 1];
|
|
|
order = last.order;
|
|
order = last.order;
|
|
|
await transaction.update(this.tableName, { id: last.id, order: order + 1, audit_order: order + 1 });
|
|
await transaction.update(this.tableName, { id: last.id, order: order + 1, audit_order: order + 1 });
|
|
|
}
|
|
}
|
|
|
- await transaction.insert(this.tableName, this.flowRecord(current, { aid: id, flow_stage: stage, order, audit_order: order, audit_type: stage === 2 ? 2 : 1 }));
|
|
|
|
|
|
|
+ await transaction.insert(this.tableName, this.flowRecord(current, { aid: id, flow_stage: stage, order, audit_order: order, audit_type: 1 }));
|
|
|
await this.grantFlowPermission(transaction, [id]);
|
|
await this.grantFlowPermission(transaction, [id]);
|
|
|
} else {
|
|
} else {
|
|
|
const target = stageRecords.find(x => x.aid === id);
|
|
const target = stageRecords.find(x => x.aid === id);
|
|
@@ -1451,6 +1456,7 @@ module.exports = app => {
|
|
|
break;
|
|
break;
|
|
|
}
|
|
}
|
|
|
case 'flow-save-rectification':
|
|
case 'flow-save-rectification':
|
|
|
|
|
+ case 'flow-return-rectification':
|
|
|
case 'flow-complete-rectification': {
|
|
case 'flow-complete-rectification': {
|
|
|
if (!self || current.flow_stage !== 2 || self.status !== 12 || Number(data.auditId) !== self.id) throw '您没有待处理的整改任务';
|
|
if (!self || current.flow_stage !== 2 || self.status !== 12 || Number(data.auditId) !== self.id) throw '您没有待处理的整改任务';
|
|
|
const item = typeof data.rectification_item === 'string' ? data.rectification_item.trim() : '';
|
|
const item = typeof data.rectification_item === 'string' ? data.rectification_item.trim() : '';
|
|
@@ -1459,12 +1465,24 @@ module.exports = app => {
|
|
|
if (item.length > 1000 || opinion.length > 1000) throw '整改内容和意见最多1000字';
|
|
if (item.length > 1000 || opinion.length > 1000) throw '整改内容和意见最多1000字';
|
|
|
if (date && (typeof date !== 'string' || !moment(date, 'YYYY-MM-DD', true).isValid())) throw '整改日期格式错误';
|
|
if (date && (typeof date !== 'string' || !moment(date, 'YYYY-MM-DD', true).isValid())) throw '整改日期格式错误';
|
|
|
const done = data.type === 'flow-complete-rectification';
|
|
const done = data.type === 'flow-complete-rectification';
|
|
|
|
|
+ const returned = data.type === 'flow-return-rectification';
|
|
|
|
|
+ if (returned && !opinion) throw '请填写退回意见';
|
|
|
if (done && (!item || !date)) throw '请填写整改内容和整改日期';
|
|
if (done && (!item || !date)) throw '请填写整改内容和整改日期';
|
|
|
|
|
+ const shared = this.ctx.service.qualityInspection.getFlowRectification(current, rectifiers);
|
|
|
|
|
+ if (data.rectificationOriginal !== undefined && (!data.rectificationOriginal || data.rectificationOriginal.rectification_item !== shared.rectification_item || data.rectificationOriginal.rectification_date !== shared.rectification_date)) {
|
|
|
|
|
+ throw '整改单已被其他整改人更新,请刷新页面后重试';
|
|
|
|
|
+ }
|
|
|
|
|
+ await transaction.update(this.ctx.service.qualityInspection.tableName, { id: current.id, rectification_item: item, rectification_date: date, rectification_uid: uid });
|
|
|
const update = { id: self.id, rectification_item: item, rectification_date: date, opinion };
|
|
const update = { id: self.id, rectification_item: item, rectification_date: date, opinion };
|
|
|
if (done) Object.assign(update, { status: 3, end_time: new Date() });
|
|
if (done) Object.assign(update, { status: 3, end_time: new Date() });
|
|
|
await transaction.update(this.tableName, update);
|
|
await transaction.update(this.tableName, update);
|
|
|
- // 所有提交都先锁巡检主记录,再检查本轮其他人的结果。
|
|
|
|
|
- if (done && rectifiers.every(x => x.id === self.id || x.status === 3)) await this.activateFlow(transaction, current, 3);
|
|
|
|
|
|
|
+ Object.assign(self, update);
|
|
|
|
|
+ // 只有当前整改人可提交;通过后激活下一人,最后一人通过才进入批复。
|
|
|
|
|
+ if (done) await this.activateFlow(transaction, current, rectifiers.some(x => x.status === 1) ? 2 : 3);
|
|
|
|
|
+ if (returned) {
|
|
|
|
|
+ await this.returnRectificationFlow(transaction, current, records, self, opinion);
|
|
|
|
|
+ await this.noticeFlow(transaction, current, records, 6, opinion, 2);
|
|
|
|
|
+ }
|
|
|
if (done) await this.noticeFlow(transaction, current, records, 3, opinion, 2);
|
|
if (done) await this.noticeFlow(transaction, current, records, 3, opinion, 2);
|
|
|
break;
|
|
break;
|
|
|
}
|
|
}
|
|
@@ -1520,23 +1538,30 @@ module.exports = app => {
|
|
|
inspection.status = 4;
|
|
inspection.status = 4;
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
- if (inspection.flow_stage === 3) {
|
|
|
|
|
- // 批复退回:原轮次保留,所有整改人同时开始新一轮整改。
|
|
|
|
|
- const previous = records.filter(x => [2, 3].includes(x.flow_stage) && x.stage_round === inspection.stage_round);
|
|
|
|
|
- inspection.stage_round += 1;
|
|
|
|
|
- const copies = previous.map(x => this.flowRecord(inspection, x));
|
|
|
|
|
- if (copies.length) await transaction.insert(this.tableName, copies);
|
|
|
|
|
- await this.activateFlow(transaction, inspection, 2);
|
|
|
|
|
- return;
|
|
|
|
|
- }
|
|
|
|
|
if (result === 5) {
|
|
if (result === 5) {
|
|
|
- const templates = records.filter(x => x.flow_stage === 1 || x.flow_stage === 3 && x.stage_round === inspection.stage_round);
|
|
|
|
|
|
|
+ const fromReply = inspection.flow_stage === 3;
|
|
|
|
|
+ const shared = fromReply ? this.ctx.service.qualityInspection.getFlowRectification(inspection, records) : null;
|
|
|
|
|
+ const templates = records.filter(x => x.flow_stage === 1 || (x.flow_stage === 3 || fromReply && x.flow_stage === 2) && x.stage_round === inspection.stage_round);
|
|
|
inspection.times += 1;
|
|
inspection.times += 1;
|
|
|
inspection.stage_round = 1;
|
|
inspection.stage_round = 1;
|
|
|
const copies = templates.map(x => this.flowRecord(inspection, x));
|
|
const copies = templates.map(x => this.flowRecord(inspection, x));
|
|
|
if (copies.length) await transaction.insert(this.tableName, copies);
|
|
if (copies.length) await transaction.insert(this.tableName, copies);
|
|
|
- await transaction.update(this.ctx.service.qualityInspection.tableName, { id: inspection.id, times: inspection.times, stage_round: 1, flow_stage: 1, status: 5 });
|
|
|
|
|
- inspection.status = 5;
|
|
|
|
|
|
|
+ const update = { id: inspection.id, times: inspection.times, stage_round: 1, flow_stage: 1, status: 5 };
|
|
|
|
|
+ if (shared) Object.assign(update, shared, { rectification_date: shared.rectification_date || null });
|
|
|
|
|
+ await transaction.update(this.ctx.service.qualityInspection.tableName, update);
|
|
|
|
|
+ Object.assign(inspection, update);
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (inspection.flow_stage === 3) {
|
|
|
|
|
+ const target = this.getReplyReturnTarget(inspection, records, self);
|
|
|
|
|
+ if (!target) throw '未找到上一审批人或整改人,请刷新页面后重试';
|
|
|
|
|
+ const shared = this.ctx.service.qualityInspection.getFlowRectification(inspection, records);
|
|
|
|
|
+ const replaced = records.filter(x => x.stage_round === inspection.stage_round && (x.id === target.id || x.flow_stage === 3 && (target.flow_stage === 2 || x.order >= target.order)));
|
|
|
|
|
+ // 从退回对象重新流转,保留更早的审批结果,原意见及处理时间留作历史。
|
|
|
|
|
+ await transaction.updateRows(this.tableName, replaced.map(x => ({ id: x.id, is_old: 1 })));
|
|
|
|
|
+ await transaction.insert(this.tableName, replaced.map(x => this.flowRecord(inspection, x)));
|
|
|
|
|
+ await transaction.update(this.ctx.service.qualityInspection.tableName, Object.assign({ id: inspection.id }, shared, { rectification_date: shared.rectification_date || null }));
|
|
|
|
|
+ await this.activateFlow(transaction, inspection, target.flow_stage);
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
const report = records.filter(x => x.flow_stage === 1);
|
|
const report = records.filter(x => x.flow_stage === 1);
|
|
@@ -1561,6 +1586,96 @@ module.exports = app => {
|
|
|
const users = this._.uniq([inspection.uid].concat(records.map(x => x.aid)));
|
|
const users = this._.uniq([inspection.uid].concat(records.map(x => x.aid)));
|
|
|
await transaction.insert('zh_notice', users.map(uid => ({ pid: this.ctx.session.sessionProject.id, tid: inspection.tid, type: pushType.inspection, uid, status: result, content: JSON.stringify(content) })));
|
|
await transaction.insert('zh_notice', users.map(uid => ({ pid: this.ctx.session.sessionProject.id, tid: inspection.tid, type: pushType.inspection, uid, status: result, content: JSON.stringify(content) })));
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ getRectificationSequence(inspection, records) {
|
|
|
|
|
+ return records.filter(x => !x.is_old && x.times === inspection.times && x.flow_stage === 2 && x.stage_round === inspection.stage_round)
|
|
|
|
|
+ .sort((a, b) => a.audit_order - b.audit_order || a.order - b.order || a.id - b.id);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ getRectificationUpdates(inspection, records, reconcileActive = true) {
|
|
|
|
|
+ if (inspection.flow_version !== 1 || [3, 4].includes(inspection.status)) return [];
|
|
|
|
|
+ const sequence = this.getRectificationSequence(inspection, records);
|
|
|
|
|
+ const current = sequence.find(x => [1, 12].includes(x.status));
|
|
|
|
|
+ const updates = [];
|
|
|
|
|
+ sequence.forEach((record, index) => {
|
|
|
|
|
+ const update = { id: record.id };
|
|
|
|
|
+ if (record.order !== index + 1 || record.audit_order !== index + 1 || record.audit_type !== 1) {
|
|
|
|
|
+ Object.assign(update, { order: index + 1, audit_order: index + 1, audit_type: 1 });
|
|
|
|
|
+ }
|
|
|
|
|
+ if (reconcileActive && inspection.flow_stage === 2 && inspection.status === 12 && [1, 12].includes(record.status)) {
|
|
|
|
|
+ const status = record === current ? 12 : 1;
|
|
|
|
|
+ if (record.status !== status) {
|
|
|
|
|
+ update.status = status;
|
|
|
|
|
+ if (status === 12) update.begin_time = new Date();
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if (Object.keys(update).length > 1) updates.push(update);
|
|
|
|
|
+ });
|
|
|
|
|
+ return updates;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ async normalizeRectificationFlow(transaction, inspection, records, reconcileActive = true) {
|
|
|
|
|
+ const updates = this.getRectificationUpdates(inspection, records, reconcileActive);
|
|
|
|
|
+ if (updates.length) {
|
|
|
|
|
+ await transaction.updateRows(this.tableName, updates);
|
|
|
|
|
+ for (const update of updates) Object.assign(records.find(x => x.id === update.id), update);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ async prepareSequentialFlow(inspection, records) {
|
|
|
|
|
+ if (!this.getRectificationUpdates(inspection, records).length) return false;
|
|
|
|
|
+ const transaction = await this.db.beginTransaction();
|
|
|
|
|
+ try {
|
|
|
|
|
+ const current = await this.lockFlow(transaction, inspection.id);
|
|
|
|
|
+ const audits = await transaction.select(this.tableName, { where: { qiid: current.id, times: current.times, is_old: 0 }, orders: [['order', 'asc'], ['id', 'asc']] });
|
|
|
|
|
+ await this.normalizeRectificationFlow(transaction, current, audits);
|
|
|
|
|
+ await transaction.commit();
|
|
|
|
|
+ Object.assign(inspection, current);
|
|
|
|
|
+ return true;
|
|
|
|
|
+ } catch (err) {
|
|
|
|
|
+ await transaction.rollback();
|
|
|
|
|
+ throw err;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ getRectificationReturnTarget(inspection, records, self) {
|
|
|
|
|
+ if (!self || self.flow_stage !== 2) return null;
|
|
|
|
|
+ const sequence = this.getRectificationSequence(inspection, records);
|
|
|
|
|
+ const index = sequence.findIndex(x => x.id === self.id);
|
|
|
|
|
+ if (index < 0) return null;
|
|
|
|
|
+ if (index > 0) return sequence[index - 1].status === 3 ? sequence[index - 1] : null;
|
|
|
|
|
+ // 会签/或签终审取实际最后通过的人,其他已通过人的结果继续保留。
|
|
|
|
|
+ const report = records.filter(x => !x.is_old && x.times === inspection.times && x.flow_stage === 1 && x.status === 3);
|
|
|
|
|
+ report.sort((a, b) => b.audit_order - a.audit_order || new Date(b.end_time).getTime() - new Date(a.end_time).getTime() || b.id - a.id);
|
|
|
|
|
+ return report[0] || null;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ async returnRectificationFlow(transaction, inspection, records, self, opinion) {
|
|
|
|
|
+ const target = this.getRectificationReturnTarget(inspection, records, self);
|
|
|
|
|
+ if (!target) throw '未找到上一审批人,请刷新页面后重试';
|
|
|
|
|
+ await transaction.update(this.tableName, { id: self.id, status: 6, opinion, end_time: new Date() });
|
|
|
|
|
+ const sequence = this.getRectificationSequence(inspection, records);
|
|
|
|
|
+ const replaced = sequence.filter(x => target.flow_stage === 1 || x.audit_order >= target.audit_order);
|
|
|
|
|
+ if (target.flow_stage === 1) replaced.push(target);
|
|
|
|
|
+ // 原处理记录留作历史,新建待办,避免旧页面请求操作重新激活的任务。
|
|
|
|
|
+ await transaction.updateRows(this.tableName, replaced.map(x => ({ id: x.id, is_old: 1 })));
|
|
|
|
|
+ await transaction.insert(this.tableName, replaced.map(x => this.flowRecord(inspection, x)));
|
|
|
|
|
+ await this.activateFlow(transaction, inspection, target.flow_stage);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ getReplyReturnTarget(inspection, records, self) {
|
|
|
|
|
+ if (inspection.flow_stage !== 3 || !self) return null;
|
|
|
|
|
+ const earlier = records.filter(x => !x.is_old && x.times === inspection.times && x.flow_stage === 3 && x.stage_round === inspection.stage_round && x.order < self.order);
|
|
|
|
|
+ if (earlier.length) {
|
|
|
|
|
+ const previousOrder = Math.max(...earlier.map(x => x.order));
|
|
|
|
|
+ const previous = earlier.filter(x => x.order === previousOrder);
|
|
|
|
|
+ const approved = previous.find(x => x.status === 3);
|
|
|
|
|
+ return approved ? Object.assign({}, approved, { name: previous.map(x => x.name).join('、') }) : null;
|
|
|
|
|
+ }
|
|
|
|
|
+ const sequence = this.getRectificationSequence(inspection, records);
|
|
|
|
|
+ const last = sequence[sequence.length - 1];
|
|
|
|
|
+ return last && last.status === 3 ? last : null;
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
return QualityInspectionAudit;
|
|
return QualityInspectionAudit;
|