cart.js 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  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 CartService extends CrudService {
  8. constructor(ctx) {
  9. super(ctx, 'cart');
  10. this.model = this.ctx.model.Trade.Cart;
  11. this.goodsSpecModel = this.ctx.model.Shop.GoodsSpec;
  12. this.platformActModel = this.ctx.model.System.PlatformAct;
  13. this.gjaModel = this.ctx.model.Shop.GoodsJoinAct;
  14. }
  15. /**
  16. * 返回购物车需要的数据格式
  17. ** 添加促销部分:
  18. ** 买赠,特价,加价购: 需要查询每个商品是否参与了这三项活动,需要给出对应数据
  19. ** 满减/折:不需要在购物车出现
  20. ** 套装:最后下单时组合,购物车中不需要额外修改
  21. * @param {Object} query 查询条件
  22. * @param query.customer 顾客id
  23. * @return {Array}
  24. */
  25. async selfCart({ customer }) {
  26. assert(customer, '缺少顾客信息');
  27. let data = await this.model.find({ customer });
  28. if (data.length > 0) {
  29. data = JSON.parse(JSON.stringify(data));
  30. data = data.map(i => ({ ...i, cart_id: i._id }));
  31. }
  32. await this.getCartGoodsAct(data);
  33. const actList = await this.ctx.service.trade.order.getActList(data);
  34. const pageData = await this.ctx.service.trade.order.getPageData(data, actList);
  35. return pageData;
  36. }
  37. /**
  38. * 实时获取购物车内的商品参与的活动
  39. * @param {Array} data 购物车商品
  40. */
  41. async getCartGoodsAct(data) {
  42. // 实时匹配活动问题
  43. const platformActList = await this.platformActModel.find({ is_use: '0' });
  44. for (const cart of data) {
  45. const { goodsSpec: spec } = cart;
  46. const actList = [];
  47. for (const act of platformActList) {
  48. const { _id: platform_act } = act;
  49. const gjaNum = await this.gjaModel.count({
  50. platform_act,
  51. 'spec._id': spec,
  52. $or: [{ platform_act_type: '4', 'config.goods_type': 'basic' }, { platform_act_type: { $ne: '4' } }],
  53. });
  54. if (gjaNum > 0) actList.push(platform_act);
  55. }
  56. cart.act = actList;
  57. }
  58. }
  59. /**
  60. ** 创建购物车信息,若找到该店的该商品规格.进行库存校验
  61. ** 数量进行合并;
  62. ** 反之创建
  63. ** 添加促销活动部分:
  64. ** 买赠,特价,加价购: 不需要在创建时处理,而是在查询时实时处理,显示相关信息
  65. ** 满减/折:不需要在购物车出现
  66. ** 套装:只有套装需要记录在购物车中,以同一商品形式出现
  67. * @param {Object} body 请求参数
  68. * @param body.num 数量
  69. */
  70. async create({ num, ...body }) {
  71. const { customer, shop, goods, goodsSpec } = body;
  72. assert(customer, '缺少顾客信息');
  73. assert(shop, '缺少店铺信息');
  74. assert(goods, '缺少商品信息');
  75. assert(goodsSpec, '缺少商品规格信息');
  76. const query = _.pick(body, [ 'customer', 'shop', 'goods', 'goodsSpec' ]);
  77. const data = await this.model.findOne(query);
  78. if (data) {
  79. const buyNum = this.ctx.plus(data.num, num);
  80. const { enough } = await this.checkGoodsNum({ goodsSpecId: goodsSpec, num: buyNum });
  81. if (!enough) throw new BusinessError(ErrorCode.SERVICE_FAULT, '库存不足,无法添加至购物车');
  82. data.num = buyNum;
  83. await data.save();
  84. } else {
  85. const { enough } = await this.checkGoodsNum({ goodsSpecId: goodsSpec, num });
  86. if (!enough) throw new BusinessError(ErrorCode.SERVICE_FAULT, '库存不足,无法添加至购物车');
  87. await this.model.create({ num, ...body });
  88. }
  89. }
  90. /**
  91. * 检查商品规格的库存
  92. * @param {String} goodsSpecId 商品规格id
  93. * @param {String} cartId 购物车id
  94. * @param {Number} num 需要的库存数量
  95. * @param {Boolean} update 修改购物车
  96. * @return {Boolean} true:库存满足购物车条件;false:库存不满足条件
  97. */
  98. async checkGoodsNum({ cartId, goodsSpecId, num }, update = true) {
  99. const { populate } = this.ctx.service.shop.goodsSpec.getRefMods();
  100. const goodsSpec = await this.goodsSpecModel.findById(goodsSpecId).populate(populate);
  101. if (!goodsSpec) throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '未找到商品的规格数据');
  102. const goods = _.get(goodsSpec, 'goods');
  103. const shop = _.get(goods, 'shop');
  104. const shopRes = this.ctx.service.util.trade.checkShop(shop);
  105. if (shopRes.result !== true) throw new BusinessError(ErrorCode.DATA_INVALID, shopRes.msg);
  106. const goodsRes = this.ctx.service.util.trade.checkGoods(goods);
  107. if (goodsRes.result !== true) throw new BusinessError(ErrorCode.DATA_INVALID, goodsRes.msg);
  108. const gsRes = this.ctx.service.util.trade.checkGoodsSpec(goodsSpec, num);
  109. const { num: gsnum = 0 } = goodsSpec;
  110. if (gsRes.result !== true) {
  111. return { enough: false, total: gsnum, msg: gsRes.msg };
  112. }
  113. if (update && cartId) {
  114. await this.model.updateOne({ _id: cartId }, { num });
  115. }
  116. return { enough: true, total: gsnum };
  117. }
  118. }
  119. module.exports = CartService;