lrf 2 年之前
父節點
當前提交
49b96840d9
共有 6 個文件被更改,包括 153 次插入21 次删除
  1. 1 0
      app/controller/trade/config/.cart.js
  2. 5 0
      app/controller/util.js
  3. 20 5
      app/service/trade/cart.js
  4. 46 3
      app/service/trade/order.js
  5. 77 12
      app/service/util/trade.js
  6. 4 1
      app/z_router/util.js

+ 1 - 0
app/controller/trade/config/.cart.js

@@ -48,6 +48,7 @@ module.exports = {
   checkGoodsNum: {
     parameters: {
       query: {
+        cartId: 'cartId',
         goodsSpecId: 'goodsSpecId',
         num: 'num',
       },

+ 5 - 0
app/controller/util.js

@@ -18,5 +18,10 @@ class UtilController extends Controller {
     const data = await this.tradeService.checkCanBuy(this.bodyObject);
     this.ctx.ok({ data });
   }
+
+  async checkCartBuy() {
+    const data = await this.tradeService.checkCartBuy(this.bodyObject);
+    this.ctx.ok({ data });
+  }
 }
 module.exports = CrudController(UtilController, {});

+ 20 - 5
app/service/trade/cart.js

@@ -92,17 +92,32 @@ class CartService extends CrudService {
   }
 
   /**
-   * 检查商品规格的库存 
-   * TODO 检查商品的是否满足销售条件 & 规格是否在销售中
+   * 检查商品规格的库存
    * @param {String} goodsSpecId 商品规格id
+   * @param {String} cartId 购物车id
    * @param {Number} num 需要的库存数量
+   * @param {Boolean} update 修改购物车
    * @return {Boolean} true:库存满足购物车条件;false:库存不满足条件
    */
-  async checkGoodsNum({ goodsSpecId, num }) {
-    const goodsSpec = await this.goodsSpecModel.findById(goodsSpecId);
+  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;
-    return { enough: gsnum >= num, total: gsnum };
+    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 };
   }
 }
 

+ 46 - 3
app/service/trade/order.js

@@ -14,6 +14,8 @@ class OrderService extends CrudService {
     this.goodsModel = this.ctx.model.Shop.Goods;
     this.goodsSpecModel = this.ctx.model.Shop.GoodsSpec;
     this.addressModel = this.ctx.model.User.Address;
+
+    this.cartModel = this.ctx.model.Trade.Cart;
   }
   /**
    * 进入下单页面
@@ -25,14 +27,22 @@ class OrderService extends CrudService {
     let data = await this.redis.get(key);
     if (!data) throw new BusinessError(ErrorCode.SERVICE_FAULT, '请求超时,请重新进入下单页');
     data = JSON.parse(data);
-    const { populate } = this.ctx.service.shop.goodsSpec.getRefMods();
+    console.log(data);
     let specsData = [];
     if (_.isArray(data)) {
       // 购物车来的: 1.循环校验 规格商品; 2.按店铺分组
+      const { populate } = this.ctx.service.trade.cart.getRefMods();
+      const carts = await this.cartModel.find({ _id: data }).populate(populate);
+      for (const cart of carts) {
+        const { result, msg } = await this.ctx.service.util.trade.checkCanBuy(cart, false);
+        if (!result) throw new BusinessError(ErrorCode.DATA_INVALID, msg);
+      }
+      specsData = this.setCartsGoodsToPageData(carts);
     } else if (_.isObject(data)) {
       // 商品页单独买: 1.校验规格商品; 2:按店铺分组
       const { result, msg } = await this.ctx.service.util.trade.checkCanBuy(data, false);
       if (!result) throw new BusinessError(ErrorCode.DATA_INVALID, msg);
+      const { populate } = this.ctx.service.shop.goodsSpec.getRefMods();
       const list = await this.goodsSpecModel.find({ _id: data.goodsSpec }).populate(populate);
       specsData = this.setGoodsToPageData(list, data.num);
     } else throw new BusinessError(ErrorCode.DATA_INVALID, '数据不正确,请重新下单');
@@ -44,7 +54,7 @@ class OrderService extends CrudService {
     // 找到默认地址
     const address = await this.addressModel.findOne({ customer, is_default: '1' });
     pageData.address = address;
-    // 商品总价,各店铺的价格明细
+    // // 商品总价,各店铺的价格明细
     specsData = this.computedShopTotal(specsData);
     const shopTotalDetail = this.computedAllTotal(specsData);
     pageData.goodsData = specsData;
@@ -59,6 +69,7 @@ class OrderService extends CrudService {
     for (const i of list) {
       i.goods_total = i.goods.reduce((p, n) => p + (n.money || 0) * (n.num || 0), 0);
       i.freight_total = i.goods.reduce((p, n) => p + (n.freight || 0) * (n.num || 0), 0);
+      console.log(i);
     }
     return list;
   }
@@ -76,7 +87,7 @@ class OrderService extends CrudService {
   }
 
   /**
-   * 单商品整理数据,需要商品与规格的快照,剩下的可以简略
+   * 单商品整理数据,剩下的可以简略
    * @param {Array} list 规格数组
    * @param num 购买数量
    */
@@ -101,6 +112,38 @@ class OrderService extends CrudService {
     }
     return arr;
   }
+  /**
+   *购物车数据整理
+   * @param {Array} list 规格数组
+   */
+  setCartsGoodsToPageData(list) {
+    const arr = [];
+    list = _.groupBy(list, 'shop._id');
+    for (const key in list) {
+      const data = list[key];
+      const shopData = _.get(_.head(data), 'shop');
+      const obj = {};
+      obj.shop = _.get(shopData, '_id');
+      obj.shop_name = _.get(shopData, 'name');
+      const goodsList = [];
+      for (const i of data) {
+        const goods = {};
+        goods.cart_id = _.get(i, '_id');
+        goods.goods_id = _.get(i.goods, '_id');
+        goods.goods_name = _.get(i.goods, 'name');
+        goods.goodsSpec_id = _.get(i.goodsSpec, '_id');
+        goods.goodsSpec_name = _.get(i.goodsSpec, 'name');
+        goods.freight = _.get(i.goodsSpec, 'freight');
+        goods.money = _.get(i.goodsSpec, 'sell_money');
+        goods.num = _.get(i, 'num');
+        goods.file = _.get(i.goods, 'file', []);
+        goodsList.push(goods);
+      }
+      obj.goods = goodsList;
+      arr.push(obj);
+    }
+    return arr;
+  }
 
   /**
    * 重组购物车商品

+ 77 - 12
app/service/util/trade.js

@@ -14,7 +14,33 @@ class TradeService extends CrudService {
     this.shopModel = this.ctx.model.Shop.Shop;
     this.goodsModel = this.ctx.model.Shop.Goods;
     this.goodsSpecModel = this.ctx.model.Shop.GoodsSpec;
+    this.cartModel = this.ctx.model.Trade.Cart;
   }
+  /**
+   * 检查选中的购物车是否符合购买的条件
+   * @param {Object} body 请求体
+   * @param body.cartIds 选中的购物车id列表
+   * @param {Boolean} makeCache 生成缓存
+   */
+  async checkCartBuy({ cartIds }, makeCache = true) {
+    const list = await this.cartModel.find({ _id: cartIds });
+    let result = { result: true };
+    for (const i of list) {
+      const res = await this.checkCanBuy(i, false);
+      if (res.result !== true) {
+        result = res;
+        break;
+      }
+    }
+
+    if (makeCache) {
+      const key = await this.makeOrderKey(cartIds);
+      result.key = key;
+    }
+
+    return result;
+  }
+
   /**
    * 检测是否可以购买该物品
    * @param {Object} param 查询条件
@@ -32,6 +58,29 @@ class TradeService extends CrudService {
     const result = { result: true };
     // 1.检查商店是否正常运行
     const shopData = await this.shopModel.findById(shop);
+    const shopRes = this.checkShop(shopData);
+    if (shopRes.result !== true) return shopRes;
+    // 2.检查商品是否可以购买
+    const goodsData = await this.goodsModel.findById(goods);
+    const goodsRes = this.checkGoods(goodsData);
+    if (shopRes.result !== true) return goodsRes;
+    // 3.检验该规格是否可以购买
+    const goodsSpecData = await this.goodsSpecModel.findById(goodsSpec);
+    const gsRes = this.checkGoodsSpec(goodsSpecData);
+    if (gsRes.result !== true) return gsRes;
+    if (makeCache) {
+      const key = await this.makeOrderKey({ shop, goods, goodsSpec, num });
+      result.key = key;
+    }
+
+    return result;
+  }
+  /**
+   * 检查商店是否满足条件
+   * @param {Object} shopData 店铺数据
+   */
+  checkShop(shopData) {
+    const result = { result: true };
     if (!shopData) {
       result.msg = '未找到店铺';
       result.result = false;
@@ -42,8 +91,15 @@ class TradeService extends CrudService {
       result.result = false;
       return result;
     }
-    // 2.检查商品是否可以购买
-    const goodsData = await this.goodsModel.findById(goods);
+    return result;
+  }
+
+  /**
+   * 检查商品是否满足条件
+   * @param {Object} goodsData 商品数据
+   */
+  checkGoods(goodsData) {
+    const result = { result: true };
     if (!goodsData) {
       result.msg = '未找到商品';
       result.result = false;
@@ -54,8 +110,15 @@ class TradeService extends CrudService {
       result.result = false;
       return result;
     }
-    // 3.检验该规格是否可以购买
-    const goodsSpecData = await this.goodsSpecModel.findById(goodsSpec);
+    return result;
+  }
+  /**
+   * 检查商品的规格是否满足购买条件
+   * @param {Object} goodsSpecData 商品规格的数据
+   * @param {Number} num 购买数量
+   */
+  checkGoodsSpec(goodsSpecData, num) {
+    const result = { result: true };
     if (!goodsSpecData) {
       result.msg = '未找到商品的指定规格';
       result.result = false;
@@ -71,20 +134,22 @@ class TradeService extends CrudService {
       result.result = false;
       return result;
     }
-    if (makeCache) {
-      const str = this.createNonceStr();
-      const key = `${this.redisKey.orderKeyPrefix}${str}`;
-      const value = JSON.stringify({ shop, goods, goodsSpec, num });
-      await this.redis.set(key, value, 'EX', this.redisTimeout);
-      result.key = str;
-    }
-
     return result;
   }
+
   // 随机字符串产生函数
   createNonceStr() {
     return Math.random().toString(36).substr(2, 15);
   }
+
+  // 生成key
+  async makeOrderKey(data) {
+    const str = this.createNonceStr();
+    const key = `${this.redisKey.orderKeyPrefix}${str}`;
+    const value = JSON.stringify(data);
+    await this.redis.set(key, value, 'EX', this.redisTimeout);
+    return str;
+  }
 }
 
 module.exports = TradeService;

+ 4 - 1
app/z_router/util.js

@@ -6,7 +6,10 @@ const routerRegister = require(regPath);
 const rkey = 'util';
 const ckey = 'util';
 const keyZh = '工具接口';
-const routes = [{ method: 'post', path: `${rkey}/checkCanBuy`, controller: `${ckey}.checkCanBuy`, zh: `${keyZh}-检查是否可以购买商品` }];
+const routes = [
+  { method: 'post', path: `${rkey}/checkCanBuy`, controller: `${ckey}.checkCanBuy`, zh: `${keyZh}-检查是否可以购买商品` },
+  { method: 'post', path: `${rkey}/checkCartBuy`, controller: `${ckey}.checkCartBuy`, zh: `${keyZh}-检查选中的购物车商品是否可以购买` },
+];
 
 module.exports = app => {
   routerRegister(app, routes, keyZh, rkey, ckey);