payment_detail.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. 'use strict';
  2. const auditConst = require('../const/audit').stage;
  3. module.exports = app => {
  4. class PaymentDetail extends app.BaseService {
  5. constructor(ctx) {
  6. super(ctx);
  7. this.tableName = 'payment_detail';
  8. }
  9. async getValidDetails(tr_id) {
  10. const details = await this.db.select(this.tableName, {
  11. column: ['id', 'in_time', 'tr_id', 'uid', 'status', 'order', 'times', 'code', 's_time'],
  12. where: { tr_id },
  13. orders: [['order', 'desc']],
  14. });
  15. if (details.length !== 0) {
  16. const lastDetail = details[details.length - 1];
  17. if (lastDetail.status === auditConst.status.uncheck && lastDetail.uid !== this.ctx.session.sessionUser.accountId) {
  18. details.splice(details.length - 1, 1);
  19. }
  20. }
  21. // 最新一期计量(未审批完成),当前操作人的期详细数据,应实时计算
  22. if (details.length > 0 && details[0].status !== auditConst.status.checked) {
  23. const detail = details[0];
  24. const curAuditor = await this.ctx.service.paymentDetailAudit.getCurAuditor(detail.id, detail.times);
  25. const isActive = curAuditor ? curAuditor.id === this.ctx.session.sessionUser.accountId : detail.uid === this.ctx.session.sessionUser.accountId;
  26. if (isActive) {
  27. detail.curTimes = detail.times;
  28. detail.curOrder = curAuditor ? curAuditor.order : 0;
  29. }
  30. }
  31. return details;
  32. }
  33. async hadDetail(trId) {
  34. const result = await this.count({ tr_id: trId });
  35. return result !== 0;
  36. }
  37. async addDetail(trInfo, code, s_time) {
  38. const transaction = await this.db.beginTransaction();
  39. try {
  40. if (!(trInfo.is_del === 0 && trInfo.rpt_audit)) {
  41. throw '报表已删除或表单人员数据有误,无法新建';
  42. }
  43. const details = await this.getAllDataByCondition({
  44. where: { tr_id: trInfo.id },
  45. order: ['order'],
  46. });
  47. const preDetail = details[details.length - 1];
  48. if (details.length > 0 && details[details.length - 1].status !== auditConst.status.checked) {
  49. throw '上一期未审批通过,请等待上一期审批通过后,再新增';
  50. }
  51. if (this._.findIndex(details, { code }) !== -1) {
  52. throw '编号不能重复';
  53. }
  54. trInfo.rpt_audit = JSON.parse(trInfo.rpt_audit);
  55. if (this._.findIndex(trInfo.rpt_audit, { uid: null }) !== -1) {
  56. throw '未配置好表单角色,无法新建';
  57. }
  58. const rptTpl = await this.ctx.service.rptTpl.getDataById(trInfo.rpt_id);
  59. const pageRst = this.ctx.service.jpcReport.getAllPreviewPagesCommon(rptTpl, 'A4');
  60. const order = details.length + 1;
  61. const newDetail = {
  62. tender_id: this.ctx.tender.id,
  63. tr_id: trInfo.id,
  64. order,
  65. times: 1,
  66. status: auditConst.status.uncheck,
  67. uid: this.ctx.session.sessionUser.accountId,
  68. s_time,
  69. code,
  70. report_json: JSON.stringify(pageRst),
  71. in_time: new Date(),
  72. };
  73. const result = await transaction.insert(this.tableName, newDetail);
  74. if (result.affectedRows === 1) {
  75. newDetail.id = result.insertId;
  76. } else {
  77. throw '新增支付审批数据失败';
  78. }
  79. // 报表角色创建
  80. const insertRptAudit = [];
  81. for (const [i, r] of trInfo.rpt_audit.entries()) {
  82. insertRptAudit.push({
  83. tender_id: this.ctx.tender.id,
  84. tr_id: trInfo.id,
  85. td_id: newDetail.id,
  86. uid: r.uid,
  87. signature_index: i,
  88. signature_name: r.rpt_name,
  89. in_time: new Date(),
  90. });
  91. }
  92. if (insertRptAudit.length > 0) await transaction.insert(this.ctx.service.paymentRptAudit.tableName, insertRptAudit);
  93. // 存在上一期时,复制上一期审批流程
  94. if (preDetail) {
  95. const auditResult = await this.ctx.service.paymentDetailAudit.copyPreDetailAuditors(transaction, preDetail, newDetail);
  96. if (!auditResult) {
  97. throw '复制上一期审批流程失败';
  98. }
  99. }
  100. // 更新is_change值
  101. await transaction.update(this.ctx.service.paymentTenderRpt.tableName, { id: trInfo.id, is_change: 0 });
  102. await transaction.commit();
  103. return newDetail;
  104. } catch (err) {
  105. await transaction.rollback();
  106. throw err;
  107. }
  108. }
  109. async updateReportJson(id, report_json) {
  110. return await this.db.update(this.tableName, { id, report_json: JSON.stringify(report_json) });
  111. }
  112. async signOneSignatureData(report_json, signature_name, sign_msg) {
  113. // 签名签章
  114. const signCells = this._.find(report_json.items[0].signature_cells, { signature_name });
  115. if (signCells && (sign_msg.sign_path || sign_msg.company_stamp || sign_msg.stamp_path)) {
  116. const signArray = [];
  117. sign_msg.sign_path ? signArray.push('/public/upload/sign/' + sign_msg.sign_path) : signArray.push('');
  118. sign_msg.company_stamp ? signArray.push(sign_msg.company_stamp) : signArray.push('');
  119. sign_msg.stamp_path ? signArray.push(sign_msg.stamp_path) : signArray.push('');
  120. signCells.path = signArray.join('!;!');
  121. }
  122. // 日期
  123. const dateCells = this._.find(report_json.items[0].signature_date_cells, { signature_name: signature_name + '_签字日期' });
  124. if (dateCells && sign_msg.date) {
  125. dateCells.Value = sign_msg.date;
  126. }
  127. // 意见
  128. const contentCells = this._.find(report_json.items[0].signature_audit_cells, { signature_name: signature_name + '_审核意见' });
  129. if (contentCells && sign_msg.content) {
  130. contentCells.Value = sign_msg.content;
  131. }
  132. return report_json;
  133. }
  134. async clearOneSignatureData(report_json, rptAudit) {
  135. // 签名签章
  136. const signCells = this._.find(report_json.items[0].signature_cells, { signature_name: rptAudit.signature_name });
  137. if (signCells) {
  138. signCells.path = null;
  139. }
  140. // 日期
  141. const dateCells = this._.find(report_json.items[0].signature_date_cells, { signature_name: rptAudit.signature_name + '_签字日期' });
  142. if (dateCells) {
  143. dateCells.Value = '';
  144. }
  145. // 意见
  146. const contentCells = this._.find(report_json.items[0].signature_audit_cells, { signature_name: rptAudit.signature_name + '_审核意见' });
  147. if (contentCells) {
  148. contentCells.Value = '';
  149. }
  150. return report_json;
  151. }
  152. async clearAllSignatureData(report_json) {
  153. if (report_json.items[0].signature_cells.length > 0) {
  154. for (const cell of report_json.items[0].signature_cells) {
  155. cell.path = null;
  156. }
  157. }
  158. if (report_json.items[0].signature_audit_cells.length > 0) {
  159. for (const cell of report_json.items[0].signature_audit_cells) {
  160. cell.Value = '';
  161. }
  162. }
  163. if (report_json.items[0].signature_date_cells.length > 0) {
  164. for (const cell of report_json.items[0].signature_date_cells) {
  165. cell.Value = '';
  166. }
  167. }
  168. return report_json;
  169. }
  170. /**
  171. * 删除报表表单详情
  172. *
  173. * @param {Number} id - 期Id
  174. * @return {Promise<void>}
  175. */
  176. async deleteDetail(id) {
  177. const transaction = await this.db.beginTransaction();
  178. try {
  179. await transaction.delete(this.ctx.service.paymentDetailAudit.tableName, { td_id: id });
  180. await transaction.delete(this.ctx.service.paymentRptAudit.tableName, { td_id: id });
  181. await transaction.delete(this.tableName, { id });
  182. await transaction.commit();
  183. return true;
  184. } catch (err) {
  185. await transaction.rollback();
  186. throw err;
  187. }
  188. }
  189. async haveNotice2Tender(tid, uid) {
  190. const sql = 'SELECT count(pd.`id`) as count FROM ?? as pd LEFT JOIN ?? as pda' +
  191. ' ON pd.`id` = pda.`td_id` LEFT JOIN ?? as pra ON pd.`id` = pra.`td_id` WHERE pd.`tender_id` = ? AND ((pd.`uid` = ? AND (pd.`status` = ? OR pd.`status` = ?))' +
  192. ' OR ((pd.`status` = ? OR pd.`status` = ?) AND pda.aid = ? AND pda.`status` = ?)' +
  193. ' OR (pra.`uid` = ? AND pra.`signature_msg` is null AND pd.`status` != ? AND pd.`status` != ?))';
  194. const params = [this.tableName, this.ctx.service.paymentDetailAudit.tableName, this.ctx.service.paymentRptAudit.tableName, tid,
  195. uid, auditConst.status.uncheck, auditConst.status.checkNo,
  196. auditConst.status.checking, auditConst.status.checkNoPre, uid, auditConst.status.checking,
  197. uid, auditConst.status.uncheck, auditConst.status.checkNo];
  198. const result = await this.db.queryOne(sql, params);
  199. return result ? result.count : 0;
  200. }
  201. async haveNotice2TenderRpt(tr_id, uid) {
  202. const sql = 'SELECT count(pd.`id`) as count FROM ?? as pd LEFT JOIN ?? as pda' +
  203. ' ON pd.`id` = pda.`td_id` LEFT JOIN ?? as pra ON pd.`id` = pra.`td_id` WHERE pd.`tr_id` = ? AND ((pd.`uid` = ? AND (pd.`status` = ? OR pd.`status` = ?))' +
  204. ' OR ((pd.`status` = ? OR pd.`status` = ?) AND pda.aid = ? AND pda.`status` = ?)' +
  205. ' OR (pra.`uid` = ? AND pra.`signature_msg` is null AND pd.`status` != ? AND pd.`status` != ?))';
  206. const params = [this.tableName, this.ctx.service.paymentDetailAudit.tableName, this.ctx.service.paymentRptAudit.tableName, tr_id,
  207. uid, auditConst.status.uncheck, auditConst.status.checkNo,
  208. auditConst.status.checking, auditConst.status.checkNoPre, uid, auditConst.status.checking,
  209. uid, auditConst.status.uncheck, auditConst.status.checkNo];
  210. const result = await this.db.queryOne(sql, params);
  211. return result ? result.count : 0;
  212. }
  213. async haveDetail2Tender(tid) {
  214. return this.count({ tender_id: tid });
  215. }
  216. async getCountByPidType(pid, type = 1) {
  217. const sql = 'SELECT count(pd.`id`) as count FROM ?? as pd LEFT JOIN ?? as pt ON pd.`tender_id` = pt.`id` WHERE pid = ? AND type = ?';
  218. const params = [this.tableName, this.ctx.service.paymentTender.tableName, pid, type];
  219. const result = await this.db.queryOne(sql, params);
  220. return result ? result.count : 0;
  221. }
  222. async updateReport(transaction, tr_id, uid) {
  223. const details = await this.db.select(this.tableName, {
  224. column: ['id', 'in_time', 'tr_id', 'uid', 'status', 'order', 'times', 'code', 's_time'],
  225. where: { tr_id },
  226. orders: [['order', 'desc']],
  227. });
  228. if (details && details.length > 0) {
  229. const detailInfo = details[0];
  230. if (detailInfo.status === auditConst.status.uncheck || detailInfo.status === auditConst.status.checkNo) {
  231. // 判断该人是否在审批流程里,是则移除并调整order
  232. const result2 = await this.ctx.service.paymentDetailAudit.updateAuditByReport(transaction, detailInfo.id, detailInfo.times, uid);
  233. // 更新为上报人
  234. return await transaction.update(this.tableName, { id: detailInfo.id, uid });
  235. }
  236. }
  237. return true;
  238. }
  239. }
  240. return PaymentDetail;
  241. };