deal_bills.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305
  1. 'use strict';
  2. /**
  3. *
  4. *
  5. * @author Mai
  6. * @date 2018/5/8
  7. * @version
  8. */
  9. module.exports = app => {
  10. class DealBills extends app.BaseService {
  11. /**
  12. * 构造函数
  13. * @param ctx
  14. */
  15. constructor(ctx) {
  16. super(ctx);
  17. this.tableName = 'deal_bills';
  18. }
  19. async getSum(tenderId) {
  20. const sql = 'SELECT Sum(`total_price`) As `total_price` ' +
  21. ' From ' + this.tableName +
  22. ' WHERE `tender_id` = ? ';
  23. const sqlParam = [tenderId];
  24. return await this.db.queryOne(sql, sqlParam);
  25. }
  26. /**
  27. * 导入Excel数据(node-xlsx)
  28. *
  29. * @param {Array} sheet - Excel文件中的全部工作表
  30. * @param {Number} tenderId - 所属标段Id
  31. * @returns {Promise<boolean>}
  32. */
  33. async importData(sheet, tenderId) {
  34. let result = false;
  35. const transaction = await this.db.beginTransaction();
  36. try {
  37. const bills = [];
  38. // 识别表头导入
  39. let iCode = -1, iName = -1, iUnit = -1, iUp = -1, iQty = -1, iTp = -1, bCheckCol = false;
  40. for (let iRow = 0; iRow < sheet.data.length; iRow++) {
  41. const row = sheet.data[iRow];
  42. if (!bCheckCol) {
  43. for (let iCol = 0; iCol < row.length; iCol++) {
  44. let value = row[iCol];
  45. if (typeof value !== "string") { continue }
  46. value = this.ctx.helper._.trim(value);
  47. if (['清单编号', '子目号', '子目编号', '编号', '清单号'].indexOf(value) >= 0) iCode = iCol;
  48. if (['清单名称', '名称', '子目名称'].indexOf(value) >= 0) iName = iCol;
  49. if (value.indexOf('单位') >= 0) iUnit = iCol;
  50. if (value.indexOf('单价') >= 0) iUp = iCol;
  51. if (value.indexOf('数量') >= 0) iQty = iCol;
  52. if (value.indexOf('金额') >= 0 || value.indexOf('合价') >= 0) iTp = iCol;
  53. }
  54. bCheckCol = (iCode >= 0 && iName >= 0 && iUnit >= 0 && iUp >= 0 && iQty >= 0);
  55. if (!bCheckCol) {
  56. iCode = -1;
  57. iName = -1;
  58. iUnit = -1;
  59. iUp = -1;
  60. iQty = -1;
  61. }
  62. } else {
  63. const code = this.ctx.helper._.trim(row[iCode]);
  64. console.log(code);
  65. if (this.ctx.helper.validBillsCode(code)) {
  66. const data = {
  67. deal_id: bills.length + 1,
  68. tender_id: tenderId,
  69. code: code,
  70. name: row[iName],
  71. unit: row[iUnit],
  72. unit_price: row[iUp],
  73. quantity: row[iQty],
  74. };
  75. if ((data.unit_price && !this._.isNumber(data.unit_price)) || (data.quantity && !this._.isNumber(data.quantity))) {
  76. throw '导入的Excel的数据类型有误,请检查第' + (iRow + 1) + '行';
  77. }
  78. bills.push(data);
  79. }
  80. }
  81. }
  82. if (!bCheckCol) {
  83. throw '导入的Excel表头定义有误,请下载示例检查';
  84. }
  85. // 固定列,从第一行开始导入
  86. // let iCode = 0, iName = 1, iUnit = 2, iUp = 4, iQty = 3;
  87. // for (let iRow = 1; iRow < sheet.data.length; iRow++) {
  88. // const data = {
  89. // deal_id: bills.length + 1,
  90. // tender_id: tenderId,
  91. // code: row[iCode],
  92. // name: row[iName],
  93. // unit: row[iUnit],
  94. // unit_price: row[iUp],
  95. // quantity: row[iQty],
  96. // };
  97. // if (!data.code || data.code === '' || !data.name || data.name === '') continue;
  98. // if ((data.unit_price && !this._.isNumber(data.unit_price)) || (data.quantity && !this._.isNumber(data.quantity))) {
  99. // throw '导入的Excel的数据类型有误,请检查第' + (iRow + 1) + '行';
  100. // }
  101. // bills.push(data);
  102. // }
  103. if (bills.length > 0) {
  104. await transaction.delete(this.tableName, {tender_id: tenderId});
  105. const billsResult = await transaction.insert(this.tableName, bills);
  106. if (billsResult.affectedRows !== bills.length) {
  107. throw '导入签约清单数据出错';
  108. }
  109. } else {
  110. throw 'Excel文件中无签约清单数据';
  111. }
  112. await transaction.commit();
  113. result = true;
  114. } catch (err) {
  115. await transaction.rollback();
  116. throw err;
  117. }
  118. return result;
  119. }
  120. /**
  121. * 导入Excel数据(js-xlsx)
  122. *
  123. * @param {Array} sheet - Excel文件中的全部工作表
  124. * @param {Number} tenderId - 所属标段Id
  125. * @returns {Promise<boolean>}
  126. */
  127. async importDataJsXlsx(sheet, tenderId) {
  128. let result = false;
  129. // 整理数据
  130. const bills = [];
  131. let iCode = -1, iName = -1, iUnit = -1, iUp = -1, iQty = -1, iTp = -1, bCheckCol = false;
  132. for (let iRow = 0; iRow < sheet.rows.length; iRow++) {
  133. const row = sheet.rows[iRow];
  134. if (!bCheckCol) {
  135. for (let iCol = 0; iCol < row.length; iCol++) {
  136. let value = row[iCol];
  137. if (typeof value !== "string") { continue }
  138. value = this.ctx.helper._.trim(value);
  139. if (value === '子目号' || value === '清单编号') iCode = iCol;
  140. if (value.indexOf('名称') >= 0) iName = iCol;
  141. if (value.indexOf('单位') >= 0) iUnit = iCol;
  142. if (value.indexOf('单价') >= 0) iUp = iCol;
  143. if (value.indexOf('数量') >= 0) iQty = iCol;
  144. if (value.indexOf('金额') >= 0 || value.indexOf('合价') >= 0) iTp = iCol;
  145. }
  146. bCheckCol = (iCode >= 0 && iName >= 0 && iUnit >= 0 && iUp >= 0 && iQty >= 0 && iTp >= 0);
  147. if (!bCheckCol) {
  148. iCode = -1;
  149. iName = -1;
  150. iUnit = -1;
  151. iUp = -1;
  152. iQty = -1;
  153. iTp = -1;
  154. }
  155. } else {
  156. const code = this.ctx.helper.replaceReturn(this.ctx.helper._.trim(row[iCode]));
  157. //if (this.ctx.helper.validBillsCode(code)) {
  158. if (code) {
  159. const data = {
  160. id: this.uuid.v4(),
  161. order: bills.length + 1,
  162. tender_id: tenderId,
  163. code: code,
  164. name: this.ctx.helper.replaceReturn(row[iName]),
  165. unit: this.ctx.helper.replaceReturn(row[iUnit]),
  166. unit_price: (row[iUp] === undefined || row[iUp] === null) ? 0 : this._.toNumber(row[iUp]),
  167. quantity: (row[iQty] === undefined || row[iQty] === null) ? 0 : this._.toNumber(row[iQty]),
  168. total_price: (row[iTp] === undefined || row[iTp] === null) ? 0 : this._.toNumber(row[iTp]),
  169. };
  170. if (this._.isNaN(data.unit_price) || this._.isNaN(data.quantity) || this._.isNaN(data.total_price)) {
  171. throw '导入的Excel的数据类型有误,请检查第' + (iRow + 1) + '行';
  172. }
  173. bills.push(data);
  174. }
  175. }
  176. }
  177. if (!bCheckCol) {
  178. throw '导入的Excel表头定义有误,请下载示例检查';
  179. }
  180. // 写入数据
  181. const transaction = await this.db.beginTransaction();
  182. try {
  183. if (bills.length > 0) {
  184. await transaction.delete(this.tableName, {tender_id: tenderId});
  185. const billsResult = await transaction.insert(this.tableName, bills);
  186. if (billsResult.affectedRows !== bills.length) {
  187. throw '导入签约清单数据出错';
  188. }
  189. } else {
  190. throw 'Excel文件中无签约清单数据';
  191. }
  192. await transaction.commit();
  193. result = true;
  194. } catch (err) {
  195. await transaction.rollback();
  196. throw err;
  197. }
  198. return result;
  199. }
  200. /*
  201. * 报表用
  202. * @param {Number} tenderId - 所属标段Id
  203. */
  204. async getDataByTenderId(tenderId) {
  205. const sql = 'SELECT Bills.* FROM ' + this.tableName + ' As Bills WHERE tender_id = ? ORDER BY `order` ASC';
  206. const sqlParam = [tenderId];
  207. return await this.db.query(sql, sqlParam);
  208. // let rst = await this.getDataByCondition({tender_id: tenderId});
  209. // return rst;
  210. }
  211. async _addDatas(data) {
  212. const info = this.ctx.tender.info;
  213. const datas = data instanceof Array ? data : [data];
  214. const insertData = [];
  215. for (const d of datas) {
  216. if (!d.code || !d.order) throw '新增签约清单,提交的数据错误';
  217. const nd = { id: this.uuid.v4(), tender_id: this.ctx.tender.id };
  218. nd.code = d.code;
  219. nd.order = d.order;
  220. if (d.name) nd.name = d.name;
  221. if (d.unit) nd.unit = d.unit;
  222. if (d.unit_price) nd.unit_price = this.ctx.helper.round(d.unit_price, info.decimal.up);
  223. const precision = this.ctx.helper.findPrecision(info.precision, d.unit);
  224. if (d.quantity) {
  225. nd.quantity = this.ctx.helper.round(d.quantity, precision.value);
  226. nd.total_price = this.ctx.helper.mul(nd.unit_price, nd.quantity, info.decimal.tp);
  227. }
  228. insertData.push(nd);
  229. }
  230. const result = await this.db.insert(this.tableName, insertData);
  231. return insertData;
  232. }
  233. async _delDatas (data) {
  234. await this.db.delete(this.tableName, {id: data});
  235. return data;
  236. }
  237. async _updateDatas (data) {
  238. const info = this.ctx.tender.info;
  239. const datas = data instanceof Array ? data : [data];
  240. const orgDatas = await this.getAllDataByCondition({where: {id: this.ctx.helper._.map(datas, 'id')}});
  241. const uDatas = [];
  242. for (const d of datas) {
  243. const od = this.ctx.helper._.find(orgDatas, {id: d.id});
  244. if (!od) continue;
  245. const nd = {id: od.id};
  246. if (d.code !== undefined) nd.code = d.code;
  247. if (d.order !== undefined) nd.order = d.order;
  248. if (d.name !== undefined) nd.name = d.name;
  249. if (d.unit !== undefined) nd.unit = d.unit;
  250. nd.unit_price = d.unit_price !== undefined ? this.ctx.helper.round(d.unit_price, info.decimal.up) : od.unit_price;
  251. const precision = this.ctx.helper.findPrecision(info.precision, d.unit);
  252. if (d.quantity !== undefined) {
  253. nd.quantity = this.ctx.helper.round(d.quantity, precision.value);
  254. nd.total_price = this.ctx.helper.mul(nd.unit_price, nd.quantity, info.decimal.tp);
  255. } else {
  256. nd.quantity = this.ctx.helper.round(od.quantity, precision.value);
  257. nd.total_price = this.ctx.helper.mul(nd.unit_price, nd.quantity, info.decimal.tp);
  258. }
  259. uDatas.push(nd);
  260. }
  261. if (uDatas.length > 0) {
  262. await this.db.updateRows(this.tableName, uDatas);
  263. return uDatas;
  264. } else {
  265. return [];
  266. }
  267. }
  268. async updateDatas(data) {
  269. const result = {add: [], del: [], update: []};
  270. try {
  271. if (data.add) {
  272. result.add = await this._addDatas(data.add);
  273. }
  274. if (data.update) {
  275. result.update = await this._updateDatas(data.update);
  276. }
  277. if (data.del) {
  278. result.del = await this._delDatas(data.del);
  279. }
  280. return result;
  281. } catch (err) {
  282. if (err) result.err = err;
  283. return result;
  284. }
  285. }
  286. }
  287. return DealBills;
  288. }