weapp_measure_controller.js 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. 'use strict';
  2. const auditConsts = require('../const/audit');
  3. const shenpiConst = require('../const/shenpi');
  4. const auditType = require('../const/audit').auditType;
  5. const _ = require('lodash');
  6. module.exports = app => {
  7. class WeappMeasureController extends app.BaseController {
  8. async stage(ctx) {
  9. try {
  10. const stages = await ctx.service.stage.getValidStages(ctx.tender.id, this.ctx.session.sessionUser.is_admin);
  11. for (const s of stages) {
  12. if (!s.final_auditor_str || s.status !== auditConsts.stage.status.checked) {
  13. if (s.status === auditConsts.stage.status.checkNoPre) s.status = auditConsts.stage.status.checking;
  14. if (s.status !== auditConsts.stage.status.checkNo) s.curAuditors = await ctx.service.stageAudit.getAuditorsByStatus(s.id, s.status, s.times);
  15. if (s.status === auditConsts.stage.status.checked) {
  16. const final_auditor_str = (s.curAuditors[0].audit_type === auditConsts.auditType.key.common)
  17. ? `${s.curAuditors[0].name}${(s.curAuditors[0].role ? '-' + s.curAuditors[0].role : '')}`
  18. : ctx.helper.transFormToChinese(s.curAuditors[0].audit_order) + '审';
  19. await ctx.service.stage.defaultUpdate({ id: s.id, final_auditor_str });
  20. }
  21. }
  22. }
  23. ctx.body = { code: 0, msg: '', data: stages };
  24. } catch (err) {
  25. this.log(err);
  26. ctx.body = { code: 1, msg: err.toString(), data: null };
  27. }
  28. }
  29. async auditCheck(ctx) {
  30. const stageId = ctx.request.query.stageId || ctx.request.body.stageId;
  31. const stageOrder = ctx.request.query.order || ctx.request.body.order;
  32. if (!stageId && !stageOrder) {
  33. ctx.body = { code: -1, msg: '计量期参数错误', data: null };
  34. return;
  35. }
  36. const stage = await ctx.service.stage.getDataByCondition({
  37. tid: ctx.tender.id,
  38. order: stageOrder,
  39. });
  40. if (!stage) {
  41. ctx.body = { code: -1, msg: '计量期不存在', data: null };
  42. return;
  43. }
  44. await ctx.service.stage.loadStageUser(stage);
  45. await ctx.service.stage.loadPreCheckedStage(stage);
  46. await ctx.service.stage.doCheckStage(stage);
  47. await ctx.service.stage.loadStageAuditViewData(stage);
  48. const tender = ctx.tender.data;
  49. const info = ctx.tender.info;
  50. // 历史台账
  51. if (stage.status === auditConsts.stage.status.checked) {
  52. stage.ledgerHis = await this.service.ledgerHistory.getDataById(stage.his_id);
  53. }
  54. // 获取最新的期
  55. stage.highOrder = await this.service.stage.count({
  56. tid: tender.id,
  57. });
  58. const materials = await this.service.material.getAllDataByCondition({ columns: ['stage_id', 's_order'], where: { tid: tender.id } });
  59. stage.hadMaterial = materials.find(function(item) {
  60. return item.s_order.split(',').indexOf(stage.highOrder.toString()) !== -1;
  61. });
  62. const phasePays = await this.service.phasePay.getAllDataByCondition({ columns: ['rela_stage'], where: { tid: tender.id } });
  63. stage.hadPhasePay = phasePays.find(function(pp) {
  64. pp.rela_stage = pp.rela_stage ? JSON.parse(pp.rela_stage) : [];
  65. return pp.rela_stage.find(x => { return x.stage_id === stage.id; });
  66. });
  67. // 权限相关
  68. // todo 校验权限 (标段参与人、分享、游客)
  69. const accountId = this.ctx.session.sessionUser.accountId;
  70. const shareIds = [];
  71. if (stage.status === auditConsts.stage.status.uncheck) {
  72. stage.readOnly = accountId !== stage.user_id && stage.userAssistIds.indexOf(accountId) < 0;
  73. if (!stage.readOnly) {
  74. stage.assist = stage.userAssists.find(x => { return x.ass_user_id === accountId; });
  75. }
  76. stage.curTimes = stage.times;
  77. stage.curOrder = 0;
  78. } else if (stage.status === auditConsts.stage.status.checkNo) {
  79. stage.readOnly = accountId !== stage.user_id && stage.userAssistIds.indexOf(accountId) < 0;
  80. const checkNoAudit = await this.service.stageAudit.getDataByCondition({
  81. sid: stage.id, times: stage.times - 1, status: auditConsts.stage.status.checkNo,
  82. });
  83. if (!stage.readOnly) {
  84. stage.assist = stage.userAssists.find(x => { return x.ass_user_id === accountId; });
  85. stage.curTimes = stage.times;
  86. stage.curOrder = 0;
  87. } else {
  88. stage.curTimes = stage.times - 1;
  89. stage.curOrder = checkNoAudit.order;
  90. }
  91. } else if (stage.status === auditConsts.stage.status.checked) {
  92. stage.readOnly = true;
  93. stage.curTimes = stage.times;
  94. stage.curOrder = _.max(_.map(stage.auditors, 'order'));
  95. } else {
  96. const ass = stage.auditAssists.find(x => { return stage.flowAuditorIds.indexOf(x.user_id) >= 0 && x.ass_user_id === accountId; });
  97. stage.readOnly = stage.flowAuditorIds.indexOf(accountId) < 0 && !ass;
  98. stage.curTimes = stage.times;
  99. if (!stage.readOnly) {
  100. stage.assist = ass;
  101. stage.curOrder = stage.curAuditors[0].order;
  102. } else {
  103. stage.curOrder = stage.curAuditors[0].order - 1;
  104. }
  105. if (!stage.readOnly) {
  106. if (stage.curAuditors[0].audit_type === auditType.key.and) {
  107. stage.readOnly = !_.isEqual(stage.flowAuditorIds, stage.curAuditorIds);
  108. stage.canCheck = true;
  109. } else if (stage.curAuditors[0].audit_type === auditType.key.union) {
  110. stage.readOnly = stage.relaAuditor.status === auditConsts.stage.status.checked;
  111. stage.canCheck = !stage.readOnly;
  112. }
  113. }
  114. }
  115. if (stage.readOnly) {
  116. stage.assist = accountId === stage.user_id || stage.auditorIds.indexOf(accountId) >= 0 ? null : stage.auditAssists.find(x => { return x.ass_user_id === accountId; });
  117. }
  118. const permission = this.ctx.session.sessionUser.permission;
  119. if (stage.userIds.indexOf(accountId) >= 0 || this.ctx.session.sessionUser.is_admin) {
  120. stage.filePermission = true;
  121. } else {
  122. if (shareIds.indexOf(accountId) !== -1 || (permission !== null && permission.tender !== undefined && permission.tender.indexOf('2') !== -1)) { // 分享人
  123. if (stage.status === auditConsts.status.uncheck) {
  124. throw '您无权查看该数据';
  125. }
  126. stage.filePermission = false;
  127. } else if (this.ctx.tender.isTourist || this.ctx.session.sessionUser.is_admin) {
  128. stage.filePermission = this.ctx.tender.touristPermission.file || stage.auditorIds.indexOf(accountId) !== -1;
  129. } else {
  130. throw '您无权查看该数据';
  131. }
  132. }
  133. // 判断stage流程可否撤回,是哪一种撤回
  134. // yield this.service.stage.doCheckStageCanCancel(stage);
  135. // 是否台账修订中
  136. const lastRevise = await this.service.ledgerRevise.getLastestRevise(this.ctx.tender.id);
  137. stage.revising = (lastRevise && lastRevise.status !== auditConsts.revise.status.checked) || false;
  138. // 根据状态判断是否需要更新审批人列表
  139. await this.service.stage.doCheckStageCanCancel(stage);
  140. stage.readySettle = await this.service.settle.getReadySettle(stage.tid);
  141. ctx.stage = stage;
  142. // 根据状态判断是否需要更新审批人列表
  143. if ((stage.status === auditConsts.stage.status.uncheck || stage.status === auditConsts.stage.status.checkNo) && this.ctx.tender.info.shenpi.stage !== shenpiConst.sp_status.sqspr) {
  144. const shenpi_status = this.ctx.tender.info.shenpi.stage;
  145. // 进一步比较审批流是否与审批流程设置的相同,不同则替换为固定审批流或固定的终审
  146. const auditList = await this.service.stageAudit.getAllDataByCondition({ where: { sid: stage.id, times: stage.times }, orders: [['order', 'asc']] });
  147. if (shenpi_status === shenpiConst.sp_status.gdspl) {
  148. // 判断并获取审批组
  149. const group = await this.service.shenpiGroup.getSelectGroupByStageType(this.ctx.tender.id, shenpiConst.sp_type.stage, stage.sp_group);
  150. if ((group && stage.sp_group !== group.id) || (!group && stage.sp_group !== 0)) {
  151. stage.sp_group = group ? group.id : 0;
  152. await this.service.stage.defaultUpdate({ sp_group: stage.sp_group }, { where: { id: stage.id } });
  153. }
  154. const condition = { tid: this.ctx.tender.id, sp_type: shenpiConst.sp_type.stage, sp_status: shenpi_status, sp_group: stage.sp_group };
  155. const shenpiList = await this.service.shenpiAudit.getAllDataByCondition({ where: condition, orders: [['audit_order', 'asc']] });
  156. // 判断2个id数组是否相同,不同则删除原审批流,切换成固定的审批流
  157. let sameAudit = auditList.length === shenpiList.length;
  158. if (sameAudit) {
  159. for (const audit of auditList) {
  160. const shenpi = shenpiList.find(x => { return x.audit_id === audit.aid; });
  161. if (!shenpi || shenpi.audit_order !== audit.audit_order || shenpi.audit_type !== audit.audit_type || shenpi.audit_ledger_id !== audit.audit_ledger_id) {
  162. sameAudit = false;
  163. break;
  164. }
  165. }
  166. }
  167. if (!sameAudit) {
  168. await this.service.stageAudit.updateNewAuditList(stage, shenpiList);
  169. await this.service.stage.loadStageUser(stage);
  170. }
  171. } else if (shenpi_status === shenpiConst.sp_status.gdzs) {
  172. const shenpiInfo = await this.service.shenpiAudit.getDataByCondition({ tid: stage.tid, sp_type: shenpiConst.sp_type.stage, sp_status: shenpi_status });
  173. // 判断最后一个id是否与固定终审id相同,不同则删除原审批流中如果存在的id和添加终审
  174. const lastAuditors = auditList.filter(x => { x.order === auditList[auditList.length - 1].order; });
  175. if (shenpiInfo && (lastAuditors.length === 0 || (lastAuditors.length > 1 || shenpiInfo.audit_id !== lastAuditors[0].aid))) {
  176. await this.service.stageAudit.updateLastAudit(stage, auditList, shenpiInfo.audit_id);
  177. await this.service.stage.loadStageUser(stage);
  178. } else if (!shenpiInfo) {
  179. // 不存在终审人的状态下这里恢复为授权审批人
  180. info.shenpi.stage = shenpiConst.sp_status.sqspr;
  181. }
  182. }
  183. }
  184. }
  185. async detail(ctx) {
  186. try {
  187. await this.auditCheck(ctx);
  188. ctx.stage.auditHistory = ctx.stage.auditHistory && ctx.stage.auditHistory.length && ctx.stage.auditHistory[ctx.stage.auditHistory.length - 1].reduce((prev, curr, idx) => {
  189. if (idx === 0) {
  190. const reportor = {
  191. audit_id: ctx.stage.user.id,
  192. audit_order: 0,
  193. audit_type: 1,
  194. status: ctx.stage.status === auditConsts.stage.status.uncheck ? auditConsts.stage.status.uncheck : auditConsts.stage.status.checked,
  195. times: ctx.stage.status === auditConsts.stage.status.checkNo ? ctx.stage.times - 1 : ctx.stage.times,
  196. begin_time: curr.begin_time,
  197. end_time: curr.begin_time,
  198. name: ctx.stage.user.name,
  199. company: ctx.stage.user.company,
  200. role: ctx.stage.user.role,
  201. mobile: '',
  202. opinion: '',
  203. };
  204. prev.push({
  205. name: '原报',
  206. status: reportor.status,
  207. audit_type: reportor.audit_type,
  208. auditors: [reportor],
  209. });
  210. }
  211. prev.push({
  212. name: curr.is_final ? '终审' : `${curr.audit_order}审`,
  213. audit_type: curr.audit_type,
  214. status: curr.status,
  215. auditors: curr.auditors,
  216. });
  217. return prev;
  218. }, []);
  219. if (!ctx.stage.final_auditor_str || ctx.stage.status !== auditConsts.stage.status.checked) {
  220. if (ctx.stage.status === auditConsts.stage.status.checkNoPre) {
  221. ctx.stage.status = auditConsts.stage.status.checking;
  222. }
  223. if (ctx.stage.status !== auditConsts.stage.status.checkNo) {
  224. ctx.stage.curAuditors = await ctx.service.stageAudit.getAuditorsByStatus(ctx.stage.id, ctx.stage.status, ctx.stage.times);
  225. }
  226. if (ctx.stage.status === auditConsts.stage.status.checked) {
  227. const final_auditor_str = (ctx.stage.curAuditors[0].audit_type === auditConsts.auditType.key.common)
  228. ? `${ctx.stage.curAuditors[0].name}${(ctx.stage.curAuditors[0].role ? '-' + ctx.stage.curAuditors[0].role : '')}`
  229. : ctx.helper.transFormToChinese(ctx.stage.curAuditors[0].audit_order) + '审';
  230. await ctx.service.stage.defaultUpdate({ id: ctx.stage.id, final_auditor_str });
  231. }
  232. }
  233. ctx.stage.tp = ctx.helper.sum([ctx.stage.contract_tp, ctx.stage.qc_tp, ctx.stage.pc_tp]);
  234. ctx.stage.pre_tp = ctx.helper.add(ctx.stage.pre_contract_tp, ctx.stage.pre_qc_tp);
  235. ctx.stage.end_tp = ctx.helper.add(ctx.stage.pre_tp, ctx.stage.tp);
  236. ctx.body = { code: 0, msg: '', data: ctx.stage };
  237. } catch (err) {
  238. this.log(err);
  239. ctx.body = { code: -1, msg: err.toString(), data: null };
  240. }
  241. }
  242. async checkAudit(ctx) {
  243. try {
  244. await this.auditCheck(ctx);
  245. if (ctx.stage.readOnly) {
  246. ctx.body = { code: -1, msg: '该计量期当前您无权操作', data: null };
  247. return;
  248. }
  249. if (ctx.stage.revising) {
  250. ctx.body = { code: -1, msg: '台账修订中,请勿修改提交期数据', data: null };
  251. return;
  252. }
  253. if (ctx.stage.assist && ctx.stage.assist.confirm) {
  254. ctx.body = { code: -1, msg: '协同数据已确认,如需修改,请撤销上报或重新审批', data: null };
  255. return;
  256. }
  257. if (ctx.stage.status !== auditConsts.stage.status.checking && ctx.stage.status !== auditConsts.stage.status.checkNoPre) {
  258. ctx.body = { code: -1, msg: '当前期数据有误', data: null };
  259. return;
  260. }
  261. if (ctx.stage.curAuditorIds && ctx.stage.curAuditorIds.indexOf(ctx.session.sessionUser.accountId) < 0) {
  262. ctx.body = { code: -1, msg: '您无权进行该操作', data: null };
  263. return;
  264. }
  265. const data = ctx.request.body.checkData;
  266. data.checkType = parseInt(data.checkType);
  267. if (!data.checkType || isNaN(data.checkType)) {
  268. ctx.body = { code: -1, msg: '提交数据错误', data: null };
  269. return;
  270. }
  271. await ctx.service.stageAudit.check(ctx.stage.id, data, ctx.stage.times);
  272. ctx.body = { code: 0, msg: '审批成功', data: null };
  273. } catch (err) {
  274. this.log(err);
  275. ctx.body = { code: -1, msg: err.toString() || '提交失败', data: null };
  276. ctx.session.postError = err.toString();
  277. }
  278. }
  279. }
  280. return WeappMeasureController;
  281. };