trade.js 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  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. //
  7. class TradeService extends CrudService {
  8. constructor(ctx) {
  9. super(ctx, 'trade');
  10. this.redis = this.app.redis;
  11. this.redisKey = this.app.config.redisKey;
  12. this.redisTimeout = this.app.config.redisTimeout;
  13. this.shopModel = this.ctx.model.Shop.Shop;
  14. this.goodsModel = this.ctx.model.Shop.Goods;
  15. this.goodsSpecModel = this.ctx.model.Shop.GoodsSpec;
  16. this.cartModel = this.ctx.model.Trade.Cart;
  17. }
  18. /**
  19. * 检查选中的购物车是否符合购买的条件
  20. * @param {Object} body 请求体
  21. * @param body.cartIds 选中的购物车id列表
  22. * @param {Boolean} makeCache 生成缓存
  23. */
  24. async checkCartBuy({ cartIds }, makeCache = true) {
  25. const list = await this.cartModel.find({ _id: cartIds });
  26. let result = { result: true };
  27. for (const i of list) {
  28. const res = await this.checkCanBuy(i, false);
  29. if (res.result !== true) {
  30. result = res;
  31. break;
  32. }
  33. }
  34. if (makeCache) {
  35. const key = await this.makeOrderKey(cartIds);
  36. result.key = key;
  37. }
  38. return result;
  39. }
  40. /**
  41. * 检测是否可以购买该物品
  42. * @param {Object} param 查询条件
  43. * @param param.shop 商店id
  44. * @param param.goods 商品id
  45. * @param param.goodsSpec 商品规格id
  46. * @param param.num 购买数量
  47. * @param param.type 订单类型: 0:常规单 1:团购单,需要按团购价计算
  48. * @param param.group 团id
  49. * @param param.inviter 邀请用户id 返现部分
  50. * @param makeCache 生成缓存
  51. */
  52. async checkCanBuy({ shop, goods, goodsSpec, num, type = '0', group, inviter }, makeCache = true) {
  53. assert(shop, '缺少店铺信息');
  54. assert(goods, '缺少商品信息');
  55. assert(goodsSpec, '缺少商品规格信息');
  56. assert(num, '缺少购买数量');
  57. const result = { result: true };
  58. // 1.检查商店是否正常运行
  59. const shopData = await this.shopModel.findById(shop);
  60. const shopRes = this.checkShop(shopData);
  61. if (shopRes.result !== true) return shopRes;
  62. // 2.检查商品是否可以购买
  63. const goodsData = await this.goodsModel.findById(goods);
  64. const goodsRes = this.checkGoods(goodsData);
  65. if (shopRes.result !== true) return goodsRes;
  66. // 3.检验该规格是否可以购买
  67. const goodsSpecData = await this.goodsSpecModel.findById(goodsSpec);
  68. const gsRes = this.checkGoodsSpec(goodsSpecData, num);
  69. if (gsRes.result !== true) return gsRes;
  70. // #region 团购部分
  71. // 4.检查是否是团购单
  72. if (type === '1' && group) {
  73. // 为团购单,但是没有团id,团长开团.不需要检查
  74. // 为团购单,且有团id: 团员参团
  75. const groupRes = await this.ctx.service.group.group.checkGroupCanJoin({ id: group });
  76. if (groupRes.result !== true) return groupRes;
  77. }
  78. // #endregion
  79. if (makeCache) {
  80. const key = await this.makeOrderKey({ shop, goods, goodsSpec, num, type, group, inviter });
  81. result.key = key;
  82. }
  83. return result;
  84. }
  85. /**
  86. * 检查商店是否满足条件
  87. * @param {Object} shopData 店铺数据
  88. */
  89. checkShop(shopData) {
  90. const result = { result: true };
  91. if (!shopData) {
  92. result.msg = '未找到店铺';
  93. result.result = false;
  94. return result;
  95. }
  96. if (shopData.status !== '1') {
  97. result.msg = '店铺不处于营业状态';
  98. result.result = false;
  99. return result;
  100. }
  101. return result;
  102. }
  103. /**
  104. * 检查商品是否满足条件
  105. * @param {Object} goodsData 商品数据
  106. */
  107. checkGoods(goodsData) {
  108. const result = { result: true };
  109. if (!goodsData) {
  110. result.msg = '未找到商品';
  111. result.result = false;
  112. return result;
  113. }
  114. if (goodsData.status === '0') {
  115. result.msg = '该商品已下架';
  116. result.result = false;
  117. return result;
  118. }
  119. return result;
  120. }
  121. /**
  122. * 检查商品的规格是否满足购买条件
  123. * @param {Object} goodsSpecData 商品规格的数据
  124. * @param {Number} num 购买数量
  125. */
  126. checkGoodsSpec(goodsSpecData, num) {
  127. const result = { result: true };
  128. if (!goodsSpecData) {
  129. result.msg = '未找到商品的指定规格';
  130. result.result = false;
  131. return result;
  132. }
  133. if (goodsSpecData.status !== '0') {
  134. result.msg = '该规格的商品已下架';
  135. result.result = false;
  136. return result;
  137. }
  138. if (goodsSpecData.num < num) {
  139. result.msg = '库存量不足';
  140. result.result = false;
  141. return result;
  142. }
  143. return result;
  144. }
  145. // 随机字符串产生函数
  146. createNonceStr() {
  147. return Math.random().toString(36).substr(2, 15);
  148. }
  149. // 生成key
  150. async makeOrderKey(data) {
  151. const str = this.createNonceStr();
  152. const key = `${this.redisKey.orderKeyPrefix}${str}`;
  153. const value = JSON.stringify(data);
  154. await this.redis.set(key, value, 'EX', this.redisTimeout);
  155. return str;
  156. }
  157. }
  158. module.exports = TradeService;