'use strict'; const { CrudService } = require('naf-framework-mongoose-free/lib/service'); const { BusinessError, ErrorCode } = require('naf-core').Error; const _ = require('lodash'); const assert = require('assert'); // class CartService extends CrudService { constructor(ctx) { super(ctx, 'cart'); this.model = this.ctx.model.Trade.Cart; this.goodsSpecModel = this.ctx.model.Shop.GoodsSpec; } /** * 返回购物车需要的数据格式 * @param {Object} query 查询条件 * @param query.customer 顾客id * @return {Array} */ async selfCart({ customer }) { assert(customer, '缺少顾客信息'); const { populate } = this.getRefMods(); let list = await this.model.find({ customer }).populate(populate); list = JSON.parse(JSON.stringify(list)); list = list.map(i => { const obj = {}; obj.shop_name = _.get(i.shop, 'name'); obj.shop = _.get(i.shop, '_id'); obj.goods = this.setCartGoodsData(i); return obj; }); list = _.groupBy(list, 'shop'); const arr = []; for (const key in list) { const shopGroup = list[key]; const goods = shopGroup.reduce((p, n) => { p.push(n.goods); return p; }, []); const shop = _.omit(_.head(shopGroup), [ 'goods' ]); arr.push({ ...shop, goods }); } return arr; } /** * 重组购物车商品 * @param {Object} goods 商品 * @param {Object} goodsSpec 商品规格 * @param {Object} data 购物车数据 */ setCartGoodsData(data) { const { goods, goodsSpec, _id, num = 1 } = data; const obj = {}; obj.cart_id = _id; obj.goods_id = _.get(goods, '_id'); obj.goods_name = _.get(goods, 'name'); obj.goodsSpec_id = _.get(goodsSpec, '_id'); obj.goodsSpec_name = _.get(goodsSpec, 'name'); obj.money = _.get(goodsSpec, 'sell_money'); obj.num = num; obj.file = _.get(goods, 'file'); return obj; } /** * 创建购物车信息,若找到该店的该商品规格.进行库存校验 * 数量进行合并; * 反之创建 * @param {Object} body 请求参数 * @param body.num 数量 */ async create({ num, ...body }) { const { customer, shop, goods, goodsSpec } = body; assert(customer, '缺少顾客信息'); assert(shop, '缺少店铺信息'); assert(goods, '缺少商品信息'); assert(goodsSpec, '缺少商品规格信息'); const data = await this.model.findOne(body); if (data) { const buyNum = this.ctx.plus(data.num, num); const { enough } = await this.checkGoodsNum({ goodsSpecId: goodsSpec, num: buyNum }); if (!enough) throw new BusinessError(ErrorCode.SERVICE_FAULT, '库存不足,无法添加至购物车'); data.num = buyNum; await data.save(); } else { const { enough } = await this.checkGoodsNum({ goodsSpecId: goodsSpec, num }); if (!enough) throw new BusinessError(ErrorCode.SERVICE_FAULT, '库存不足,无法添加至购物车'); await this.model.create({ num, ...body }); } } /** * 检查商品规格的库存 * @param {String} goodsSpecId 商品规格id * @param {String} cartId 购物车id * @param {Number} num 需要的库存数量 * @param {Boolean} update 修改购物车 * @return {Boolean} true:库存满足购物车条件;false:库存不满足条件 */ async checkGoodsNum({ cartId, goodsSpecId, num }, update = true) { const { populate } = this.ctx.service.shop.goodsSpec.getRefMods(); const goodsSpec = await this.goodsSpecModel.findById(goodsSpecId).populate(populate); if (!goodsSpec) throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '未找到商品的规格数据'); const goods = _.get(goodsSpec, 'goods'); const shop = _.get(goods, 'shop'); const shopRes = this.ctx.service.util.trade.checkShop(shop); if (shopRes.result !== true) throw new BusinessError(ErrorCode.DATA_INVALID, shopRes.msg); const goodsRes = this.ctx.service.util.trade.checkGoods(goods); if (goodsRes.result !== true) throw new BusinessError(ErrorCode.DATA_INVALID, goodsRes.msg); const gsRes = this.ctx.service.util.trade.checkGoodsSpec(goodsSpec, num); const { num: gsnum = 0 } = goodsSpec; if (gsRes.result !== true) { return { enough: false, total: gsnum, msg: gsRes.msg }; } if (update && cartId) { await this.model.updateOne({ _id: cartId }, { num }); } return { enough: true, total: gsnum }; } } module.exports = CartService;