goods.js 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. 'use strict';
  2. const { CrudService } = require('naf-framework-mongoose-free/lib/service');
  3. const { BusinessError, ErrorCode } = require('naf-core').Error;
  4. const _ = require('lodash');
  5. const assert = require('assert');
  6. const Transaction = require('mongoose-transactions');
  7. //
  8. class GoodsService extends CrudService {
  9. constructor(ctx) {
  10. super(ctx, 'goods');
  11. this.model = this.ctx.model.Shop.Goods;
  12. this.goodsSpecmodel = this.ctx.model.Shop.GoodsSpec;
  13. this.tran = new Transaction();
  14. }
  15. async beforeCreate(data) {
  16. // 为商品随机生成不重复的code
  17. if (!data.code) data.code = await this.makeCode();
  18. await this.checkCode(data.code);
  19. return data;
  20. }
  21. async beforeUpdate(filter, update) {
  22. const id = _.get(filter, 'id', _.get(filter, '_id'));
  23. const code = _.get(update, 'code');
  24. await this.checkCode(code, id);
  25. return { filter, update };
  26. }
  27. async query(filter, { skip = 0, limit, sort, desc, projection } = {}) {
  28. // 处理排序
  29. let condition = _.cloneDeep(filter);
  30. condition = this.dealFilter(condition);
  31. const pipeline = this.getQueryPipeline(condition);
  32. if (parseInt(skip)) pipeline.push({ $skip: parseInt(skip) });
  33. if (parseInt(limit)) pipeline.push({ $limit: parseInt(limit) });
  34. const rs = await this.model.aggregate(pipeline);
  35. return rs;
  36. }
  37. async count(filter) {
  38. let condition = _.cloneDeep(filter);
  39. condition = this.dealFilter(condition);
  40. const pipeline = this.getQueryPipeline(condition);
  41. pipeline.push({ $count: 'total' });
  42. const total = await this.model.aggregate(pipeline);
  43. return _.get(_.head(total), 'total', 0);
  44. }
  45. getQueryPipeline(filter) {
  46. const pipeline = [];
  47. const { tags, spec_name, ...others } = filter;
  48. const $match = { ...others };
  49. if (tags) {
  50. $match.tags = { $elemMatch: { $elemMatch: { $eq: tags } } };
  51. }
  52. pipeline.push({ $match });
  53. if (spec_name) {
  54. const $addFields = { goods_id: { $toString: '$_id' } };
  55. const $lookup = {
  56. from: 'goodsSpec',
  57. localField: 'goods_id',
  58. foreignField: 'goods',
  59. pipeline: [{ $match: { name: new RegExp(spec_name) } }],
  60. as: 'sp',
  61. };
  62. const $unwind = '$sp';
  63. const $project = { sp: 0, goods_id: 0 };
  64. pipeline.push({ $addFields }, { $lookup }, { $unwind }, { $project });
  65. }
  66. pipeline.push({ $sort: { sort: -1 } });
  67. return pipeline;
  68. }
  69. /**
  70. * 检查商品编码是否唯一,若传id,则将该id排除在外
  71. * @param {String} code 商品唯一编码
  72. * @param {String} id 商品id
  73. */
  74. async checkCode(code, id) {
  75. if (!code) return;
  76. const query = { code };
  77. if (id) query.id = { $ne: id };
  78. const num = await this.model.find(query);
  79. if (num > 0) throw new BusinessError(ErrorCode.DATA_EXISTED, '该编码已被其他商品使用');
  80. return;
  81. }
  82. // 生成商品编码
  83. async makeCode() {
  84. let code = '';
  85. let is_has = false;
  86. do {
  87. code = Math.random().toString(36).substring(3, 11);
  88. const num = await this.model.find({ code });
  89. is_has = num > 0;
  90. } while (is_has);
  91. return code;
  92. }
  93. async toDuplicate({ id }) {
  94. const data = await this.model.findById(id);
  95. if (!data) throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '未找到数据');
  96. let specList = await this.goodsSpecmodel.find({ goods: id });
  97. if (specList.length > 0) specList = JSON.parse(JSON.stringify(specList));
  98. const nd = JSON.parse(JSON.stringify(data));
  99. nd.name = `${nd.name}-复制-${new Date().getTime()}`;
  100. delete nd.id;
  101. delete nd._id;
  102. delete nd.meta;
  103. delete nd.__v;
  104. try {
  105. const id = this.tran.insert('Goods', nd);
  106. specList = specList.map(i => {
  107. delete i.id;
  108. delete i._id;
  109. delete i.meta;
  110. delete i.__v;
  111. i.goods = id;
  112. return i;
  113. });
  114. for (const i of specList) this.tran.insert('GoodsSpec', i);
  115. await this.tran.run();
  116. } catch (error) {
  117. console.log(error);
  118. await this.tran.rollback();
  119. } finally {
  120. this.tran.clean();
  121. }
  122. }
  123. }
  124. module.exports = GoodsService;