cart.js 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  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. * @param {Object} query 查询条件
  16. * @param query.customer 顾客id
  17. * @return {Array}
  18. */
  19. async selfCart({ customer }) {
  20. assert(customer, '缺少顾客信息');
  21. const { populate } = this.getRefMods();
  22. let list = await this.model.find({ customer }).populate(populate);
  23. list = JSON.parse(JSON.stringify(list));
  24. list = list.map(i => {
  25. const obj = {};
  26. obj.shop_name = _.get(i.shop, 'name');
  27. obj.shop = _.get(i.shop, '_id');
  28. obj.goods = this.setCartGoodsData(i);
  29. return obj;
  30. });
  31. list = _.groupBy(list, 'shop');
  32. const arr = [];
  33. for (const key in list) {
  34. const shopGroup = list[key];
  35. const goods = shopGroup.reduce((p, n) => {
  36. p.push(n.goods);
  37. return p;
  38. }, []);
  39. const shop = _.omit(_.head(shopGroup), [ 'goods' ]);
  40. arr.push({ ...shop, goods });
  41. }
  42. return arr;
  43. }
  44. /**
  45. * 重组购物车商品
  46. * @param {Object} goods 商品
  47. * @param {Object} goodsSpec 商品规格
  48. * @param {Object} data 购物车数据
  49. */
  50. setCartGoodsData(data) {
  51. const { goods, goodsSpec, _id, num = 1 } = data;
  52. const obj = {};
  53. obj.cart_id = _id;
  54. obj.goods_id = _.get(goods, '_id');
  55. obj.goods_name = _.get(goods, 'name');
  56. obj.goodsSpec_id = _.get(goodsSpec, '_id');
  57. obj.goodsSpec_name = _.get(goodsSpec, 'name');
  58. obj.money = _.get(goodsSpec, 'sell_money');
  59. obj.num = num;
  60. obj.file = _.get(goods, 'file');
  61. return obj;
  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 data = await this.model.findOne(body);
  77. if (data) {
  78. const buyNum = this.ctx.plus(data.num, num);
  79. const { enough } = await this.checkGoodsNum({ goodsSpecId: goodsSpec, num: buyNum });
  80. if (!enough) throw new BusinessError(ErrorCode.SERVICE_FAULT, '库存不足,无法添加至购物车');
  81. data.num = buyNum;
  82. await data.save();
  83. } else {
  84. const { enough } = await this.checkGoodsNum({ goodsSpecId: goodsSpec, num });
  85. if (!enough) throw new BusinessError(ErrorCode.SERVICE_FAULT, '库存不足,无法添加至购物车');
  86. await this.model.create({ num, ...body });
  87. }
  88. }
  89. /**
  90. * 检查商品规格的库存
  91. * @param {String} goodsSpecId 商品规格id
  92. * @param {String} cartId 购物车id
  93. * @param {Number} num 需要的库存数量
  94. * @param {Boolean} update 修改购物车
  95. * @return {Boolean} true:库存满足购物车条件;false:库存不满足条件
  96. */
  97. async checkGoodsNum({ cartId, goodsSpecId, num }, update = true) {
  98. const { populate } = this.ctx.service.shop.goodsSpec.getRefMods();
  99. const goodsSpec = await this.goodsSpecModel.findById(goodsSpecId).populate(populate);
  100. if (!goodsSpec) throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '未找到商品的规格数据');
  101. const goods = _.get(goodsSpec, 'goods');
  102. const shop = _.get(goods, 'shop');
  103. const shopRes = this.ctx.service.util.trade.checkShop(shop);
  104. if (shopRes.result !== true) throw new BusinessError(ErrorCode.DATA_INVALID, shopRes.msg);
  105. const goodsRes = this.ctx.service.util.trade.checkGoods(goods);
  106. if (goodsRes.result !== true) throw new BusinessError(ErrorCode.DATA_INVALID, goodsRes.msg);
  107. const gsRes = this.ctx.service.util.trade.checkGoodsSpec(goodsSpec, num);
  108. const { num: gsnum = 0 } = goodsSpec;
  109. if (gsRes.result !== true) {
  110. return { enough: false, total: gsnum, msg: gsRes.msg };
  111. }
  112. if (update && cartId) {
  113. await this.model.updateOne({ _id: cartId }, { num });
  114. }
  115. return { enough: true, total: gsnum };
  116. }
  117. }
  118. module.exports = CartService;