contract.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257
  1. 'use strict';
  2. /**
  3. * Created by EllisRan on 2020/3/3.
  4. */
  5. const auditConst = require('../const/audit').contract;
  6. const auditType = require('../const/audit').auditType;
  7. const BaseService = require('../base/base_service');
  8. module.exports = app => {
  9. class Contract extends BaseService {
  10. /**
  11. * 构造函数
  12. *
  13. * @param {Object} ctx - egg全局变量
  14. * @return {void}
  15. */
  16. constructor(ctx) {
  17. const setting = {
  18. spid: 'spid',
  19. mid: 'tid',
  20. type: 'contract_type',
  21. kid: 'contract_id',
  22. pid: 'contract_pid',
  23. order: 'order',
  24. level: 'level',
  25. isLeaf: 'is_leaf',
  26. fullPath: 'full_path',
  27. keyPre: 'contract_maxLid:', // 换个名称,防止缓存导致旧数据出问题
  28. uuid: true,
  29. };
  30. super(ctx);
  31. this.setting = setting;
  32. this.tableName = 'contract';
  33. this.dataId = 'id';
  34. }
  35. async add(options, node, data) {
  36. if (!options[this.setting.type] || !node || !data) throw '参数有误';
  37. const insertId = data.cid || this.uuid.v4();
  38. const transaction = await this.db.beginTransaction();
  39. try {
  40. const add_key = ['c_code', 'name', 'tax', 'price', 'party_a', 'party_a_user', 'party_b', 'party_b_user', 'sign_date', 'address', 'entity', 'bank', 'bank_account', 'type', 'rela_tender', 'remark'];
  41. const maxId = await this.ctx.service.contractTree._getMaxLid(options);
  42. const insertData = {
  43. id: insertId,
  44. spid: options.spid || null,
  45. tid: options.tid || null,
  46. contract_type: options[this.setting.type],
  47. uid: this.ctx.session.sessionUser.accountId,
  48. contract_id: maxId + 1,
  49. contract_pid: !node.c_code ? node.contract_id : node.contract_pid,
  50. level: !node.c_code ? node.level + 1 : node.level,
  51. is_leaf: 1,
  52. // c_code: data.c_code,
  53. // name: data.name,
  54. // total_price: data.price ? parseFloat(data.price) : 0,
  55. // price: data.price ? parseFloat(data.price) : 0,
  56. // party_a: data.party_a,
  57. // party_b: data.party_b,
  58. // sign_date: data.sign_date,
  59. // remark: data.remark,
  60. // type: data.type,
  61. create_time: new Date(),
  62. need_shenpi: options.spid ? this.ctx.subProject.page_show.openContractSubProjectShenpi : this.ctx.subProject.page_show.openContractTenderShenpi,
  63. };
  64. for (const key of add_key) {
  65. if (key === 'price') {
  66. insertData[key] = data[key] ? parseFloat(data[key]) : 0;
  67. insertData.total_price = data[key] ? parseFloat(data[key]) : 0;
  68. continue;
  69. } else if (key === 'tax') {
  70. insertData[key] = data[key] ? parseFloat(data[key]) : null;
  71. continue;
  72. } else if (key === 'sign_date') {
  73. insertData[key] = data[key] ? new Date(data[key]) : null;
  74. continue;
  75. }
  76. insertData[key] = data[key] || '';
  77. }
  78. if (data.attribute_json) insertData.attribute_json = data.attribute_json;
  79. // 删除attachments
  80. if (!data.attach && data.fid) {
  81. const fileInfo = await this.ctx.service.contractAtt.getDataById(data.fid);
  82. if (fileInfo || Object.keys(fileInfo).length) {
  83. await this.ctx.app.fujianOss.delete(this.ctx.app.config.fujianOssFolder + fileInfo.filepath);
  84. await transaction.delete(this.ctx.service.contractAtt.tableName, { id: data.fid });
  85. }
  86. }
  87. insertData[this.setting.fullPath] = !node.c_code
  88. ? node[this.setting.fullPath] + '-' + insertData[this.setting.kid]
  89. : node[this.setting.fullPath].replace('-' + node[this.setting.kid], '-' + insertData[this.setting.kid]);
  90. const order = !node.c_code ? (!node.is_leaf ? await this.getMaxOrder(options, node.contract_id, transaction) : 1) : node.order + 1;
  91. insertData[this.setting.order] = order;
  92. await this.ctx.service.contractTree._updateChildrenOrder(options, insertData[this.setting.pid], insertData[this.setting.order], 1, transaction);
  93. await transaction.insert(this.tableName, insertData);
  94. if (!node.c_code && node.is_leaf) {
  95. await transaction.update(this.ctx.service.contractTree.tableName, { id: node.id, is_leaf: 0 });
  96. }
  97. this.ctx.service.contractTree._cacheMaxLid(options, maxId + 1);
  98. await this.ctx.service.contractSpAudit.makeAudits(transaction, options, insertData, 'contract', this.ctx.session.sessionUser.accountId);
  99. await transaction.commit();
  100. } catch (err) {
  101. await transaction.rollback();
  102. throw err;
  103. }
  104. const createData = await this.ctx.service.contract.getDataById(insertId);
  105. createData.username = this.ctx.session.sessionUser.name;
  106. const updateData = await this.ctx.service.contractTree.getNextsData(options, !node.c_code ? node.contract_id : node[this.setting.pid], node[this.setting.order] + 1);
  107. if (!node.c_code) {
  108. const parent = await this.ctx.service.contractTree.getDataById(node.id);
  109. updateData.push(parent);
  110. }
  111. return { create: createData, update: updateData };
  112. }
  113. /**
  114. * 提交数据 - 响应计算(增量方式计算)
  115. * @param {Number} tenderId
  116. * @param {Object} data
  117. * @return {Promise<*>}
  118. */
  119. async updateCalc(options, data) {
  120. const helper = this.ctx.helper;
  121. if (!data) {
  122. throw '提交数据错误';
  123. }
  124. const datas = data instanceof Array ? data : [data];
  125. const ids = [];
  126. for (const row of datas) {
  127. ids.push(row.id);
  128. }
  129. const transaction = await this.db.beginTransaction();
  130. try {
  131. const updateDatas = [];
  132. for (const row of datas) {
  133. const updateNode = await this.getDataById(row.id);
  134. if (!updateNode) {
  135. throw '提交数据错误';
  136. }
  137. updateDatas.push(row);
  138. }
  139. if (updateDatas.length > 0) await transaction.updateRows(this.tableName, updateDatas);
  140. await transaction.commit();
  141. } catch (err) {
  142. await transaction.rollback();
  143. throw err;
  144. }
  145. return { contract: await this.getDataById(ids), files: await this.ctx.service.contractAtt.getAtt(ids[0]) };
  146. }
  147. async getMaxOrder(options, pid, transaction) {
  148. const sql = 'SELECT MAX(`' + this.setting.order + '`) AS max_order FROM ?? WHERE ' + this.ctx.helper._getOptionsSql(options) + ' AND ' + this.setting.pid + ' = ?';
  149. const params = [this.tableName, pid];
  150. const result = await transaction.query(sql, params);
  151. const maxOrder = result[0].max_order || 0;
  152. const sql1 = 'SELECT MAX(`' + this.setting.order + '`) AS max_order FROM ?? WHERE ' + this.ctx.helper._getOptionsSql(options) + ' AND ' + this.setting.pid + ' = ?';
  153. const params1 = [this.ctx.service.contractTree.tableName, pid];
  154. const result1 = await transaction.query(sql1, params1);
  155. const maxOrder1 = result1[0].max_order || 0;
  156. return Math.max(maxOrder, maxOrder1) + 1;
  157. }
  158. async getListByUsers(options, user) {
  159. const _ = this._;
  160. const list = await this.getAllDataByCondition({ where: options });
  161. const userList = list.length > 0 ? await this.ctx.service.projectAccount.getAllDataByCondition({ where: { id: this._.map(list, 'uid') } }) : [];
  162. const shenpi_status = this.ctx.contract_tender ? this.ctx.subProject.page_show.openContractTenderShenpi : this.ctx.subProject.page_show.openContractSubProjectShenpi;
  163. for (const l of list) {
  164. const userInfo = userList.find(item => item.id === l.uid);
  165. l.username = userInfo ? userInfo.name : '';
  166. if (shenpi_status) {
  167. // await this.ctx.service.contractSpAudit.loadUser(l);
  168. // await this.ctx.service.contractSpAudit.loadAuditViewData(l);
  169. // await this.ctx.service.contractSpAudit.checkShenpi(l);
  170. if (l.status !== auditConst.status.checked || !l.final_auditor_str) {
  171. l.curAuditors2 = await this.ctx.service.contractSpAudit.getAuditorsByStatus(l, 'contract', l.status, l.times);
  172. if (l.status === auditConst.status.checked && !l.final_auditor_str) {
  173. const final_auditor_str = l.curAuditors2[0].audit_type === auditType.key.common
  174. ? l.curAuditors2[0].name + (l.curAuditors2[0].role ? '-' + l.curAuditors2[0].role : '')
  175. : this.ctx.helper.transFormToChinese(l.curAuditors2[0].audit_order) + '审';
  176. await this.defaultUpdate({ final_auditor_str, id: l.id });
  177. l.final_auditor_str = final_auditor_str;
  178. }
  179. }
  180. }
  181. }
  182. if (user.is_admin) {
  183. return list;
  184. }
  185. const userPermission = options.tid ? await this.ctx.service.contractAudit.getDataByCondition({ spid: options.spid || null, tid: options.tid || null, uid: user.accountId }) : await this.ctx.service.subProjPermission.getContractPermission(this.ctx.subProject.permission.contract_permission);
  186. if (!userPermission) return [];
  187. const cloneOptions = this._.cloneDeep(options);
  188. cloneOptions.uid = user.accountId;
  189. const userTreePermission = await this.ctx.service.contractTreeAudit.getAllDataByCondition({ where: cloneOptions });
  190. if (userTreePermission.length === 0) return list;
  191. const newList = this._.filter(list, { uid: user.accountId });
  192. // 审批的列表也要可显示
  193. const checkList = await this.ctx.service.contractSpAudit.getAuditList(options, user.accountId);
  194. // 用 checkList里的数组和list的id对比,存在则合并到newList中
  195. newList.push(...this._.filter(list, function(item) {
  196. return checkList.some(checkItem => checkItem.id === item.id && item.uid !== user.accountId);
  197. }));
  198. const userInfo = await this.ctx.service.projectAccount.getDataById(user.accountId);
  199. // const unit = userInfo.company ? await this.ctx.service.constructionUnit.getDataByCondition({ pid: userInfo.project_id, name: userInfo.company }) : null;
  200. const uids = await this.ctx.service.projectAccount.getAllDataByCondition({ columns: ['id'], where: { project_id: userInfo.project_id, company: userInfo.company } });
  201. for (const ut of userTreePermission) {
  202. if (userPermission.permission_show_node) {
  203. const nodes = this._.filter(list, { contract_pid: ut.contract_id });
  204. newList.push(...this._.filter(nodes, function(item) {
  205. return item.uid !== user.accountId;
  206. }));
  207. } else if (userPermission.permission_show_unit) {
  208. const nodes = this._.filter(list, function(item) {
  209. return item.contract_pid === ut.contract_id && _.includes(_.map(uids, 'id'), item.uid);
  210. });
  211. newList.push(...this._.filter(nodes, function(item) {
  212. return item.uid !== user.accountId;
  213. }));
  214. // } else {
  215. // const nodes = this._.filter(list, { contract_pid: ut.contract_id, uid: user.accountId });
  216. // newList.push(...nodes);
  217. }
  218. }
  219. return newList;
  220. }
  221. async savePageShow(spid, page_show) {
  222. const transaction = await this.db.beginTransaction();
  223. try {
  224. await this.ctx.service.subProject.updatePageshow(spid, page_show, transaction);
  225. // 同步更新所有pay和contract状态
  226. await transaction.update(this.tableName, { need_shenpi: page_show.openContractSubProjectShenpi }, { where: { spid } });
  227. await transaction.update(this.ctx.service.contractPay.tableName, { need_shenpi: page_show.openContractPaySubProjectShenpi }, { where: { spid } });
  228. const tenders = await this.ctx.service.tender.getAllDataByCondition({ columns: ['id'], where: { spid } });
  229. if (tenders.length > 0) {
  230. await transaction.update(this.tableName, { need_shenpi: page_show.openContractTenderShenpi }, { where: { tid: this._.map(tenders, 'id') } });
  231. await transaction.update(this.ctx.service.contractPay.tableName, { need_shenpi: page_show.openContractPayTenderShenpi }, { where: { tid: this._.map(tenders, 'id') } });
  232. }
  233. await transaction.commit();
  234. return true;
  235. } catch (err) {
  236. await transaction.rollback();
  237. throw err;
  238. }
  239. return false;
  240. }
  241. // async getCountByUser(stid, type, user) {
  242. //
  243. // }
  244. }
  245. return Contract;
  246. };