cart.js 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  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. }
  13. /**
  14. * 返回购物车需要的数据格式
  15. ** 添加促销部分:
  16. ** 买赠,特价,加价购: 需要查询每个商品是否参与了这三项活动,需要给出对应数据
  17. ** 满减/折:不需要在购物车出现
  18. ** 套装:将套装数据拿出来,归为主商品的商品下
  19. * @param {Object} query 查询条件
  20. * @param query.customer 顾客id
  21. * @return {Array}
  22. */
  23. async selfCart({ customer }) {
  24. assert(customer, '缺少顾客信息');
  25. const { populate } = this.getRefMods();
  26. let list = await this.model.find({ customer }).populate(populate);
  27. list = JSON.parse(JSON.stringify(list));
  28. list = list.map(i => {
  29. const obj = {};
  30. obj.shop_name = _.get(i.shop, 'name');
  31. obj.shop = _.get(i.shop, '_id');
  32. obj.goods = this.setCartGoodsData(i);
  33. return obj;
  34. });
  35. list = _.groupBy(list, 'shop');
  36. const arr = [];
  37. for (const key in list) {
  38. const shopGroup = list[key];
  39. const goods = shopGroup.reduce((p, n) => {
  40. p.push(n.goods);
  41. return p;
  42. }, []);
  43. const shop = _.omit(_.head(shopGroup), [ 'goods' ]);
  44. arr.push({ ...shop, goods });
  45. }
  46. return arr;
  47. }
  48. /**
  49. * 重组购物车商品
  50. * @param {Object} goods 商品
  51. * @param {Object} goodsSpec 商品规格
  52. * @param {Object} data 购物车数据
  53. */
  54. setCartGoodsData(data) {
  55. const { goods, goodsSpec, _id, num = 1 } = data;
  56. const obj = {};
  57. obj.cart_id = _id;
  58. obj.goods_id = _.get(goods, '_id');
  59. obj.goods_name = _.get(goods, 'name');
  60. obj.goodsSpec_id = _.get(goodsSpec, '_id');
  61. obj.goodsSpec_name = _.get(goodsSpec, 'name');
  62. obj.money = _.get(goodsSpec, 'sell_money');
  63. obj.num = num;
  64. obj.file = _.get(goods, 'file');
  65. return obj;
  66. }
  67. /**
  68. ** 创建购物车信息,若找到该店的该商品规格.进行库存校验
  69. ** 数量进行合并;
  70. ** 反之创建
  71. ** 添加促销活动部分:
  72. ** 买赠,特价,加价购: 不需要在创建时处理,而是在查询时实时处理,显示相关信息
  73. ** 满减/折:不需要在购物车出现
  74. ** 套装:只有套装需要记录在购物车中,以同一商品形式出现
  75. * @param {Object} body 请求参数
  76. * @param body.num 数量
  77. */
  78. async create({ num, ...body }) {
  79. const { customer, shop, goods, goodsSpec } = body;
  80. assert(customer, '缺少顾客信息');
  81. assert(shop, '缺少店铺信息');
  82. assert(goods, '缺少商品信息');
  83. assert(goodsSpec, '缺少商品规格信息');
  84. const data = await this.model.findOne(body);
  85. if (data) {
  86. const buyNum = this.ctx.plus(data.num, num);
  87. const { enough } = await this.checkGoodsNum({ goodsSpecId: goodsSpec, num: buyNum });
  88. if (!enough) throw new BusinessError(ErrorCode.SERVICE_FAULT, '库存不足,无法添加至购物车');
  89. data.num = buyNum;
  90. await data.save();
  91. } else {
  92. const { enough } = await this.checkGoodsNum({ goodsSpecId: goodsSpec, num });
  93. if (!enough) throw new BusinessError(ErrorCode.SERVICE_FAULT, '库存不足,无法添加至购物车');
  94. await this.model.create({ num, ...body });
  95. }
  96. }
  97. /**
  98. * 检查商品规格的库存
  99. * @param {String} goodsSpecId 商品规格id
  100. * @param {String} cartId 购物车id
  101. * @param {Number} num 需要的库存数量
  102. * @param {Boolean} update 修改购物车
  103. * @return {Boolean} true:库存满足购物车条件;false:库存不满足条件
  104. */
  105. async checkGoodsNum({ cartId, goodsSpecId, num }, update = true) {
  106. const { populate } = this.ctx.service.shop.goodsSpec.getRefMods();
  107. const goodsSpec = await this.goodsSpecModel.findById(goodsSpecId).populate(populate);
  108. if (!goodsSpec) throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '未找到商品的规格数据');
  109. const goods = _.get(goodsSpec, 'goods');
  110. const shop = _.get(goods, 'shop');
  111. const shopRes = this.ctx.service.util.trade.checkShop(shop);
  112. if (shopRes.result !== true) throw new BusinessError(ErrorCode.DATA_INVALID, shopRes.msg);
  113. const goodsRes = this.ctx.service.util.trade.checkGoods(goods);
  114. if (goodsRes.result !== true) throw new BusinessError(ErrorCode.DATA_INVALID, goodsRes.msg);
  115. const gsRes = this.ctx.service.util.trade.checkGoodsSpec(goodsSpec, num);
  116. const { num: gsnum = 0 } = goodsSpec;
  117. if (gsRes.result !== true) {
  118. return { enough: false, total: gsnum, msg: gsRes.msg };
  119. }
  120. if (update && cartId) {
  121. await this.model.updateOne({ _id: cartId }, { num });
  122. }
  123. return { enough: true, total: gsnum };
  124. }
  125. }
  126. module.exports = CartService;