financial_pay_audit.js 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542
  1. 'use strict';
  2. /**
  3. *
  4. *
  5. * @author Mai
  6. * @date 2019/2/27
  7. * @version
  8. */
  9. const auditConst = require('../const/audit').financial;
  10. const auditType = require('../const/audit').auditType;
  11. const shenpiConst = require('../const/shenpi');
  12. const pushType = require('../const/audit').pushType;
  13. module.exports = app => {
  14. class FinancialPayAudit extends app.BaseService {
  15. /**
  16. * 构造函数
  17. *
  18. * @param {Object} ctx - egg全局变量
  19. * @return {void}
  20. */
  21. constructor(ctx) {
  22. super(ctx);
  23. this.tableName = 'financial_pay_audit';
  24. }
  25. async getAuditorGroup(fpId, times) {
  26. const auditors = await this.getAuditors(fpId, times); // 全部参与的审批人
  27. return this.ctx.helper.groupAuditors(auditors, 'order', true);
  28. }
  29. async getUserGroup(fpId, times) {
  30. const group = await this.getAuditorGroup(fpId, times);
  31. const sql =
  32. 'SELECT pa.`id` As aid, pa.`name`, pa.`company`, pa.`role`, ? As times, ? As fpid, 0 As `order`, 1 As audit_type, 0 As audit_order' +
  33. ' FROM ' + this.ctx.service.financialPay.tableName + ' As s' +
  34. ' LEFT JOIN ' + this.ctx.service.projectAccount.tableName + ' As pa' +
  35. ' ON s.uid = pa.id' +
  36. ' WHERE s.id = ?';
  37. const sqlParam = [times, fpId, fpId];
  38. const user = await this.db.queryOne(sql, sqlParam);
  39. user.audit_order = 0;
  40. group.unshift([ user ]);
  41. return group;
  42. }
  43. async getUniqUserGroup(fpId, times) {
  44. const group = await this.getAuditorGroup(fpId, times);
  45. const sql =
  46. 'SELECT pa.`id` As aid, pa.`name`, pa.`company`, pa.`role`, ? As times, ? As fpid, 0 As `order`, 1 As audit_type, 0 As audit_order' +
  47. ' FROM ' + this.ctx.service.financialPay.tableName + ' As s' +
  48. ' LEFT JOIN ' + this.ctx.service.projectAccount.tableName + ' As pa' +
  49. ' ON s.uid = pa.id' +
  50. ' WHERE s.id = ?';
  51. const sqlParam = [times, fpId, fpId];
  52. const user = await this.db.queryOne(sql, sqlParam);
  53. user.audit_order = 0;
  54. group.unshift([ user ]);
  55. return this.ctx.helper.groupAuditorsUniq(group);
  56. }
  57. async getAuditorHistory(fpId, times, reverse = false) {
  58. const history = [];
  59. if (times >= 1) {
  60. for (let i = 1; i <= times; i++) {
  61. const auditors = await this.getAuditors(fpId, i);
  62. const group = this.ctx.helper.groupAuditors(auditors);
  63. const historyGroup = [];
  64. // 找出group里audit_order最大值
  65. const max_info = group.length > 0 ? this._.maxBy(group, function(item) {
  66. return item && item[0] && item[0].audit_order;
  67. }) : null;
  68. const max_order = max_info ? max_info[0].audit_order : -1;
  69. for (const g of group) {
  70. const his = {
  71. beginYear: '', beginDate: '', beginTime: '', endYear: '', endDate: '', endTime: '', begin_time: null, end_time: null,
  72. audit_type: g[0].audit_type, audit_order: g[0].audit_order,
  73. auditors: g,
  74. };
  75. if (his.audit_type === auditType.key.common) {
  76. his.name = g[0].name;
  77. } else {
  78. his.name = this.ctx.helper.transFormToChinese(his.audit_order) + '审';
  79. }
  80. his.is_final = his.audit_order === max_order;
  81. if (g[0].begin_time) {
  82. his.begin_time = g[0].begin_time;
  83. const beginTime = this.ctx.moment(g[0].begin_time);
  84. his.beginYear = beginTime.format('YYYY');
  85. his.beginDate = beginTime.format('MM-DD');
  86. his.beginTime = beginTime.format('HH:mm:ss');
  87. }
  88. let end_time;
  89. g.forEach(x => {
  90. if (x.status === auditConst.status.checkSkip) return;
  91. if (!his.status || x.status === auditConst.status.checking) his.status = x.status;
  92. if (x.end_time && (!end_time || x.end_time > end_time)) {
  93. end_time = x.end_time;
  94. if (his.status !== auditConst.status.checking) his.status = x.status;
  95. }
  96. });
  97. if (end_time) {
  98. his.end_time = end_time;
  99. const endTime = this.ctx.moment(end_time);
  100. his.endYear = endTime.format('YYYY');
  101. his.endDate = endTime.format('MM-DD');
  102. his.endTime = endTime.format('HH:mm:ss');
  103. }
  104. historyGroup.push(his);
  105. }
  106. if (reverse) {
  107. history.push(historyGroup.reverse());
  108. } else {
  109. history.push(historyGroup);
  110. }
  111. }
  112. }
  113. return history;
  114. }
  115. async getUniqAuditor(fpId, times) {
  116. const auditors = await this.getAuditors(fpId, times); // 全部参与的审批人
  117. const result = [];
  118. auditors.forEach(x => {
  119. if (result.findIndex(r => { return x.aid === r.aid && x.audit_order === r.audit_order; }) < 0) {
  120. result.push(x);
  121. }
  122. });
  123. return result;
  124. }
  125. /**
  126. * 获取 审核列表信息
  127. *
  128. * @param {Number} cpId - 变更立项id
  129. * @param {Number} times - 第几次审批
  130. * @return {Promise<*>}
  131. */
  132. async getAuditors(fpId, times = 1, order_sort = 'asc', noYB = false) {
  133. // const sql = 'SELECT la.`aid`, pa.`name`, pa.`company`, pa.`role`, pa.`mobile`, pa.`telephone`, la.`times`, la.`order`, la.`status`, la.`opinion`, la.`begin_time`, la.`end_time`, g.`sort` ' +
  134. // 'FROM ?? AS la, ?? AS pa, (SELECT t1.`aid`,(@i:=@i+1) as `sort` FROM (SELECT t.`aid`, t.`order` FROM (select `aid`, `order` from ?? WHERE `cpid` = ? AND `times` = ? ORDER BY `order` LIMIT 200) t GROUP BY t.`aid` ORDER BY t.`order`) t1, (select @i:=0) as it) as g ' +
  135. // 'WHERE la.`cpid` = ? and la.`times` = ? and la.`aid` = pa.`id` and g.`aid` = la.`aid` order by la.`order`';
  136. // const sqlParam = [this.tableName, this.ctx.service.projectAccount.tableName, this.tableName, cpId, times, cpId, times];
  137. // const result = await this.db.query(sql, sqlParam);
  138. // const sql2 = 'SELECT COUNT(a.`aid`) as num FROM (SELECT `aid` FROM ?? WHERE `cpid` = ? AND `times` = ? GROUP BY `aid`) as a';
  139. // const sqlParam2 = [this.tableName, cpId, times];
  140. // const count = await this.db.queryOne(sql2, sqlParam2);
  141. // for (const i in result) {
  142. // result[i].max_sort = count.num;
  143. // }
  144. const ybSql = noYB ? ' AND la.audit_order != 0' : '';
  145. const sql = 'SELECT la.id, la.aid, la.times, la.order, la.status, la.opinion, la.begin_time, la.end_time, la.audit_type, la.audit_order,' +
  146. ' pa.name, pa.company, pa.role, pa.mobile, pa.telephone' +
  147. ` FROM ${this.tableName} la LEFT JOIN ${this.ctx.service.projectAccount.tableName} pa ON la.aid = pa.id` +
  148. ' WHERE la.fpid = ? AND la.times = ?' + ybSql +
  149. ' ORDER BY la.order ' + order_sort;
  150. const sqlParam = [fpId, times];
  151. const result = await this.db.query(sql, sqlParam);
  152. const max_sort = this._.max(result.map(x => { return x.audit_order; }));
  153. for (const i in result) {
  154. result[i].max_sort = max_sort;
  155. }
  156. return result;
  157. }
  158. async getCurAuditors(fpId, times = 1) {
  159. const sql =
  160. 'SELECT la.`aid`, pa.`name`, pa.`company`, pa.`role`, pa.`mobile`, pa.`telephone`, la.`times`, la.`order`, la.`status`, la.`opinion`, la.`begin_time`, la.`end_time`, la.audit_type, la.audit_order ' +
  161. ' FROM ?? AS la Left Join ?? AS pa On la.`aid` = pa.`id`' +
  162. ' WHERE la.`fpid` = ? and la.`status` = ? and la.`times` = ?';
  163. const sqlParam = [this.tableName, this.ctx.service.projectAccount.tableName, fpId, auditConst.status.checking, times];
  164. return await this.db.query(sql, sqlParam);
  165. }
  166. /**
  167. * 获取审核人流程列表
  168. *
  169. * @param auditorId
  170. * @return {Promise<*>}
  171. */
  172. async getAuditGroupByList(fpId, times, transaction = false) {
  173. const sql = 'SELECT la.`aid`, pa.`name`, pa.`company`, pa.`role`, la.`times`, la.`fpid`, la.`aid`, la.`order`, la.`status`, la.audit_type, la.audit_order ' +
  174. ' FROM ?? AS la Left Join ?? AS pa On la.`aid` = pa.`id`' +
  175. ' WHERE la.`fpid` = ? and la.`times` = ? GROUP BY la.`aid` ORDER BY la.`order`';
  176. const sqlParam = [this.tableName, this.ctx.service.projectAccount.tableName, fpId, times];
  177. return transaction !== false ? await transaction.query(sql, sqlParam) : await this.db.query(sql, sqlParam);
  178. }
  179. async getAuditorsByStatus(fpId, status, times = 1) {
  180. let auditor = [];
  181. let sql = '';
  182. let sqlParam = '';
  183. let cur;
  184. switch (status) {
  185. case auditConst.status.checking :
  186. case auditConst.status.checked :
  187. case auditConst.status.cancelRevise :
  188. cur = await this.db.queryOne('SELECT * From ?? where fpid = ? AND times = ? AND status = ? ORDER By times DESC, `order` DESC', [this.tableName, fpId, times, status]);
  189. if (!cur) return [];
  190. sql = 'SELECT la.`aid`, pa.`name`, pa.`company`, pa.`role`, la.`times`, la.`fpid`, la.`order`, la.`status`, la.`audit_order`, la.`audit_type` ' +
  191. ' FROM ?? AS la Left Join ?? AS pa On la.`aid` = pa.`id` ' +
  192. ' WHERE la.`fpid` = ? and la.`order` = ? and times = ?';
  193. sqlParam = [this.tableName, this.ctx.service.projectAccount.tableName, fpId, cur.order, times];
  194. auditor = await this.db.query(sql, sqlParam);
  195. break;
  196. case auditConst.status.checkNo :
  197. cur = await this.db.queryOne('SELECT * From ?? where fpid = ? AND times = ? AND status = ? ORDER By times DESC, `order` DESC', [this.tableName, fpId, parseInt(times) - 1, status]);
  198. if (!cur) return [];
  199. sql = 'SELECT la.`aid`, pa.`name`, pa.`company`, pa.`role`, la.`times`, la.`fpid`, la.`order`, la.`status`, la.`audit_order`, la.`audit_type` ' +
  200. ' FROM ?? AS la Left Join ?? AS pa On la.`aid` = pa.`id` ' +
  201. ' WHERE la.`fpid` = ? and la.`order` = ? and la.`times` = ?';
  202. sqlParam = [this.tableName, this.ctx.service.projectAccount.tableName, fpId, cur.order, parseInt(times) - 1];
  203. auditor = await this.db.query(sql, sqlParam);
  204. break;
  205. case auditConst.status.uncheck:
  206. default:
  207. break;
  208. }
  209. return auditor;
  210. }
  211. /**
  212. * 获取审核人流程列表(包括原报)
  213. * @param {Number} materialId 调差id
  214. * @param {Number} times 审核次数
  215. * @return {Promise<Array>} 查询结果集(包括原报)
  216. */
  217. async getAuditorsWithOwner(fpId, times = 1) {
  218. const result = await this.getAuditGroupByList(fpId, times);
  219. const sql =
  220. 'SELECT pa.`id` As aid, pa.`name`, pa.`company`, pa.`role`, ? As times, ? As fpid, 0 As `order`' +
  221. ' FROM ' +
  222. this.ctx.service.financialPay.tableName +
  223. ' As s' +
  224. ' LEFT JOIN ' +
  225. this.ctx.service.projectAccount.tableName +
  226. ' As pa' +
  227. ' ON s.uid = pa.id' +
  228. ' WHERE s.id = ?';
  229. const sqlParam = [times, fpId, fpId];
  230. const user = await this.db.queryOne(sql, sqlParam);
  231. result.unshift(user);
  232. return result;
  233. }
  234. async updateNewAuditList(financialPay, newList) {
  235. const transaction = await this.db.beginTransaction();
  236. try {
  237. await this.updateNewAuditors(financialPay, newList, transaction);
  238. await transaction.commit();
  239. } catch (err) {
  240. await transaction.rollback();
  241. throw err;
  242. }
  243. }
  244. async updateNewAuditors(financialPay, newList, transaction) {
  245. // 先删除旧的审批流,再添加新的
  246. await transaction.delete(this.tableName, { fpid: financialPay.id, times: financialPay.times });
  247. const newAuditors = [];
  248. for (const auditor of newList) {
  249. newAuditors.push({
  250. spid: financialPay.spid, tid: financialPay.tid, fpid: financialPay.id, aid: auditor.audit_id,
  251. times: financialPay.times, order: auditor.audit_order, status: auditConst.status.uncheck,
  252. audit_type: auditor.audit_type, audit_order: auditor.audit_order,
  253. });
  254. }
  255. if (newAuditors.length > 0) await transaction.insert(this.tableName, newAuditors);
  256. }
  257. /**
  258. * 开始审批
  259. * @param {Number} cpId - 方案id
  260. * @param {Number} times - 第几次审批
  261. * @return {Promise<boolean>}
  262. */
  263. async start(fpId, times = 1) {
  264. const audits = await this.getAllDataByCondition({ where: { fpid: fpId, times, order: 1 } });
  265. if (audits.length === 0) {
  266. throw '请联系管理员添加审批人';
  267. }
  268. const transaction = await this.db.beginTransaction();
  269. try {
  270. const begin_time = new Date();
  271. const updateData = audits.map(x => {
  272. return {id: x.id, status: auditConst.status.checking, begin_time};
  273. });
  274. await transaction.updateRows(this.tableName, updateData);
  275. await transaction.update(this.ctx.service.financialPay.tableName, {
  276. id: fpId, status: auditConst.status.checking,
  277. // entities: await this.ctx.service.financialPayContract.getEntities(fpId),
  278. });
  279. // todo 更新标段tender状态 ?
  280. await transaction.commit();
  281. } catch (err) {
  282. await transaction.rollback();
  283. throw err;
  284. }
  285. return true;
  286. }
  287. /**
  288. * 审批
  289. * @param {Object} fp - 资金支付信息
  290. * @param {auditConst.status.checked|auditConst.status.checkNo} checkType - 审批结果
  291. * @return {Promise<void>}
  292. */
  293. async check(fp, checkData) {
  294. if (checkData.checkType !== auditConst.status.checked && checkData.checkType !== auditConst.status.checkNo) {
  295. throw '提交数据错误';
  296. }
  297. const pid = this.ctx.session.sessionProject.id;
  298. switch (checkData.checkType) {
  299. case auditConst.status.checked:
  300. await this._checked(pid, fp, checkData);
  301. break;
  302. case auditConst.status.checkNo:
  303. await this._checkNo(pid, fp, checkData);
  304. break;
  305. default:
  306. throw '无效审批操作';
  307. }
  308. }
  309. async _checked(pid, fp, checkData) {
  310. const accountId = this.ctx.session.sessionUser.accountId;
  311. const time = new Date();
  312. // 整理当前流程审核人状态更新
  313. const audits = fp.curAuditors;
  314. if (audits.length === 0) throw '审核数据错误';
  315. const selfAudit = audits.find(x => { return x.aid === accountId; });
  316. if (!selfAudit) throw '当前标段您无权审批';
  317. // const flowAudits = await this.getAllDataByCondition({ where: { cpid: cpId, times, order: selfAudit.order } });
  318. const nextAudits = fp.nextAuditors;
  319. const transaction = await this.db.beginTransaction();
  320. try {
  321. // 更新本人审批状态
  322. await transaction.update(this.tableName, {
  323. id: selfAudit.id,
  324. status: checkData.checkType,
  325. opinion: checkData.opinion,
  326. end_time: time,
  327. });
  328. // await this.ctx.service.noticeAgain.stopNoticeAgain(transaction, this.tableName, selfAudit.id);
  329. // 获取推送必要信息
  330. const noticeContent = await this.getNoticeContent(pid, fp.spid, fp.id, selfAudit.aid, checkData.opinion);
  331. // 添加推送
  332. const records = [];
  333. const auditors = await this.getAuditorsWithOwner(fp.id, fp.times);
  334. auditors.forEach(audit => {
  335. records.push({ pid, spid: fp.spid, type: pushType.financial, uid: audit.aid, status: auditConst.status.checked, content: noticeContent });
  336. });
  337. await transaction.insert('zh_notice', records);
  338. if (audits.length === 1 || selfAudit.audit_type !== auditType.key.and) {
  339. // 或签更新他人审批状态
  340. if (selfAudit.audit_type === auditType.key.or) {
  341. const updateOther = [];
  342. for (const audit of audits) {
  343. if (audit.aid === selfAudit.aid) continue;
  344. updateOther.push({
  345. id: audit.id,
  346. status: auditConst.status.checkSkip,
  347. opinion: '',
  348. end_time: time,
  349. });
  350. // await this.ctx.service.noticeAgain.stopNoticeAgain(transaction, this.tableName, audit.id);
  351. }
  352. if (updateOther.length > 0) transaction.updateRows(this.tableName, updateOther);
  353. }
  354. // 无下一审核人表示,审核结束
  355. if (nextAudits.length > 0) {
  356. // 流程至下一审批人
  357. const updateData = nextAudits.map(x => { return { id: x.id, status: auditConst.status.checking, begin_time: time }; });
  358. await transaction.updateRows(this.tableName, updateData);
  359. // 同步 期信息
  360. await transaction.update(this.ctx.service.financialPay.tableName, {
  361. id: fp.id, status: auditConst.status.checking,
  362. });
  363. } else {
  364. // 本期结束
  365. // 生成截止本期数据 final数据
  366. // 同步 期信息
  367. await transaction.update(this.ctx.service.financialPay.tableName, {
  368. id: fp.id, status: checkData.checkType,
  369. entities: await this.ctx.service.financialPayContract.getEntities(fp.id),
  370. });
  371. }
  372. } else {
  373. // 同步 期信息
  374. await transaction.update(this.ctx.service.financialPay.tableName, {
  375. id: fp.id,
  376. status: auditConst.status.checking,
  377. });
  378. }
  379. await transaction.commit();
  380. } catch (err) {
  381. await transaction.rollback();
  382. throw err;
  383. }
  384. }
  385. async _checkNo(pid, fp, checkData) {
  386. const accountId = this.ctx.session.sessionUser.accountId;
  387. const time = new Date();
  388. const audits = fp.curAuditors;
  389. if (!audits) throw '审核数据错误';
  390. const selfAudit = audits.find(x => { return x.aid === accountId; });
  391. if (!selfAudit) throw '当前标段您无权审批';
  392. const auditors = await this.getUniqAuditor(fp.id, fp.times); // 全部参与的审批人
  393. const newAuditors = auditors.map(x => {
  394. return {
  395. aid: x.aid, spid: fp.spid, tid: fp.tid, fpid: fp.id,
  396. times: fp.times + 1, order: x.audit_order, status: auditConst.status.uncheck,
  397. audit_type: x.audit_type, audit_order: x.audit_order,
  398. };
  399. });
  400. const transaction = await this.db.beginTransaction();
  401. try {
  402. const updateData = [];
  403. audits.forEach(x => {
  404. updateData.push({
  405. id: x.id,
  406. status: x.aid === selfAudit.aid ? checkData.checkType : auditConst.status.checkSkip,
  407. opinion: x.aid === selfAudit.aid ? checkData.opinion : '',
  408. end_time: x.aid === selfAudit.aid ? time : null,
  409. });
  410. });
  411. await transaction.updateRows(this.tableName, updateData);
  412. // 添加到消息推送表
  413. const noticeContent = await this.getNoticeContent(pid, fp.spid, fp.id, selfAudit.aid, checkData.opinion);
  414. const records = [{ pid, spid: fp.spid, type: pushType.financial, uid: fp.uid, status: auditConst.status.checkNo, content: noticeContent }];
  415. auditors.forEach(audit => {
  416. records.push({ pid, spid: fp.spid, type: pushType.financial, uid: audit.aid, status: auditConst.status.checkNo, content: noticeContent });
  417. });
  418. await transaction.insert(this.ctx.service.noticePush.tableName, records);
  419. // 同步期信息
  420. await transaction.update(this.ctx.service.financialPay.tableName, {
  421. id: fp.id, status: checkData.checkType,
  422. times: fp.times + 1,
  423. entities: '',
  424. });
  425. // 拷贝新一次审核流程列表
  426. await transaction.insert(this.tableName, newAuditors);
  427. await transaction.commit();
  428. } catch (err) {
  429. await transaction.rollback();
  430. throw err;
  431. }
  432. }
  433. /**
  434. * 获取审核人需要审核的期列表
  435. *
  436. * @param auditorId
  437. * @return {Promise<*>}
  438. */
  439. async getAuditFinancial(auditorId, spid = '') {
  440. const spSql = spid ? ' and ma.`spid` = "' + spid + '"' : '';
  441. const sql = 'SELECT ma.`aid`, ma.`times`, ma.`order`, ma.`begin_time`, ma.`end_time`, ma.`spid`, ma.`fpid`,' +
  442. ' m.`status` As `fpstatus`, m.`code` As `fpcode`,' +
  443. ' sp.`name`, sp.`project_id` ' +
  444. ' FROM ?? AS ma LEFT JOIN ?? AS m ON ma.`fpid` = m.`id` LEFT JOIN ?? As sp ON ma.`spid` = sp.`id`' +
  445. ' WHERE ((ma.`aid` = ? and ma.`status` = ?) OR (m.`uid` = ? and ma.`status` = ? and m.`status` = ? and ma.`times` = (m.`times`-1)))' + spSql +
  446. ' ORDER BY ma.`begin_time` DESC';
  447. const sqlParam = [this.tableName, this.ctx.service.financialPay.tableName, this.ctx.service.subProject.tableName, auditorId, auditConst.status.checking, auditorId, auditConst.status.checkNo, auditConst.status.checkNo];
  448. const result = await this.db.query(sql, sqlParam);
  449. // 过滤result中存在重复sid的值, 保留最新的一条
  450. const filterResult = [];
  451. const fpidArr = [];
  452. for (const r of result) {
  453. if (fpidArr.indexOf(r.fpid) === -1) {
  454. filterResult.push(r);
  455. fpidArr.push(r.fpid);
  456. }
  457. }
  458. return filterResult;
  459. }
  460. /**
  461. * 获取审核人审核的次数
  462. *
  463. * @param auditorId
  464. * @return {Promise<*>}
  465. */
  466. async getCountByChecked(auditorId, spid = '') {
  467. if (spid) {
  468. return await this.db.count(this.tableName, { spid, aid: auditorId, status: [auditConst.status.checked, auditConst.status.checkNo] });
  469. }
  470. return await this.db.count(this.tableName, { aid: auditorId, status: [auditConst.status.checked, auditConst.status.checkNo] });
  471. }
  472. /**
  473. * 获取最近一次审批结束时间
  474. *
  475. * @param auditorId
  476. * @return {Promise<*>}
  477. */
  478. async getLastEndTimeByChecked(auditorId, spid = '') {
  479. const spSql = spid ? ' and `spid` = "' + spid + '"' : '';
  480. const sql = 'SELECT `end_time` FROM ?? WHERE `aid` = ? ' +
  481. 'AND `status` in (' + this.ctx.helper.getInArrStrSqlFilter([auditConst.status.checked, auditConst.status.checkNo]) + ')' + spSql +
  482. ' ORDER BY `end_time` DESC';
  483. const sqlParam = [this.tableName, auditorId];
  484. const result = await this.db.queryOne(sql, sqlParam);
  485. return result ? result.end_time : null;
  486. }
  487. /**
  488. * 用于添加推送所需的content内容
  489. * @param {Number} pid 项目id
  490. * @param {Number} tid 台账id
  491. * @param {Number} cpId 方案id
  492. * @param {Number} uid 审批人id
  493. */
  494. async getNoticeContent(pid, spid, fpId, uid, opinion = '') {
  495. const noticeSql = 'SELECT * FROM (SELECT ' +
  496. ' sp.`id` As `spid`, ma.`fpid`, m.`code`, sp.`name`, pa.`name` As `su_name`, pa.role As `su_role`' +
  497. ' FROM (SELECT * FROM ?? WHERE `id` = ? ) As sp' +
  498. ' LEFT JOIN ?? As m On sp.`id` = m.`spid` AND m.`id` = ?' +
  499. ' LEFT JOIN ?? As ma ON m.`id` = ma.`fpid`' +
  500. ' LEFT JOIN ?? As pa ON pa.`id` = ?' +
  501. ' WHERE sp.`project_id` = ? ) as new_t GROUP BY new_t.`spid`';
  502. const noticeSqlParam = [this.ctx.service.subProject.tableName, spid, this.ctx.service.financialPay.tableName, fpId, this.tableName, this.ctx.service.projectAccount.tableName, uid, pid];
  503. const content = await this.db.query(noticeSql, noticeSqlParam);
  504. if (content.length) {
  505. content[0].opinion = opinion;
  506. }
  507. return content.length ? JSON.stringify(content[0]) : '';
  508. }
  509. }
  510. return FinancialPayAudit;
  511. };