lrf 2 éve
szülő
commit
4673b6f3f8

+ 3 - 3
app/controller/trade/config/.order.js

@@ -1,6 +1,6 @@
 module.exports = {
   create: {
-    requestBody: ['inviter', 'type', 'group', 'customer', 'address', 'goods', 'total_detail', 'buy_time', 'pay', 'no', 'status', 'coupon'],
+    requestBody: ['plus_goods', 'inviter', 'type', 'group', 'customer', 'address', 'goods', 'total_detail', 'buy_time', 'pay', 'no', 'status', 'coupon'],
   },
   destroy: {
     params: ['!id'],
@@ -8,7 +8,7 @@ module.exports = {
   },
   update: {
     params: ['!id'],
-    requestBody: ['type', 'group', 'customer', 'address', 'goods', 'total_detail', 'buy_time', 'pay', 'no', 'status'],
+    requestBody: ['plus_goods', 'type', 'group', 'customer', 'address', 'goods', 'total_detail', 'buy_time', 'pay', 'no', 'status'],
   },
   show: {
     parameters: {
@@ -31,7 +31,7 @@ module.exports = {
         status: 'status',
         type: 'type',
         group: 'group',
-        goods:'%goods.goods.goods.name%'
+        goods: '%goods.goods.goods.name%',
       },
       // options: {
       //   "meta.state": 0 // 默认条件

+ 2 - 1
app/service/shop/goodsJoinAct.js

@@ -41,7 +41,7 @@ class GoodsJoinActService extends CrudService {
     const mq = {};
     if (platform_act) mq.platform_act = platform_act;
     if (platform_act_type) mq.platform_act_type = platform_act_type;
-    if (shop)mq.shop = shop;
+    if (shop) mq.shop = shop;
     if (goods) mq.goods = goods;
     if (goods_name) mq['goods.name'] = new RegExp(goods_name);
     if (spec) mq.spec = spec;
@@ -91,6 +91,7 @@ class GoodsJoinActService extends CrudService {
         sell_money: { $toString: '$spec.sell_money' },
         flow_money: { $toString: '$spec.flow_money' },
         platform_act_type: 1,
+        platform_act: 1,
         config: 1,
         status: 1,
       },

+ 40 - 63
app/service/trade/order.js

@@ -48,81 +48,53 @@ class OrderService extends CrudService {
         }
       }
       const orderData = {};
-      const goodsSpecs = [];
-      const actList = [];
       // 数据做快照处理
       // 1.地址快照
       const addressData = await this.addressModel.findById(address._id);
       if (!addressData) throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '未找到邮寄地址数据');
       // 2.商品快照
-      const goodsData = [];
-      // 商店不做快照,但是商品和商品对应的规格做快照
-      for (const i of goods) {
-        const { goods: goodsList, ...others } = i;
-        const qp = [];
-        for (const g of goodsList) {
-          const { goodsSpec_id, goods_id } = g;
-          // 需要的订单数据
-          const orderNeedData = _.pick(g, [ 'act', 'price', 'sp_price', 'num', 'cart_id' ]);
-          if (orderNeedData.num) {
-            orderNeedData.buy_num = orderNeedData.num;
-            delete orderNeedData.num;
-          }
-          let goodsSpec = await this.goodsSpecModel.findById(goodsSpec_id);
-          if (!goodsSpec) continue;
-          goodsSpec = JSON.parse(JSON.stringify(goodsSpec));
-          const goods = await this.goodsModel.findById(goods_id);
-          if (goods) goodsSpec.goods = JSON.parse(JSON.stringify(goods));
-          goodsSpec = { ...goodsSpec, ...orderNeedData };
-          qp.push(goodsSpec);
-          const ogs = _.pick(goodsSpec, [ '_id', 'buy_num', 'sell_money', 'price' ]);
-          if (ogs._id) {
-            ogs.id = ogs._id;
-            delete ogs._id;
-          }
-          goodsSpecs.push({ ...ogs, type });
-          // 将活动提取出来:只需要满减/折;买赠和特价跟着规格走,计算过程中已经处理;加价购是外面处理
-          const { act = [] } = goodsSpec;
-          let gAct = act.filter(f => f.platform_act_type === '5' || f.platform_act_type === '6');
-          gAct = gAct.map(i => ({ ...i, goodsSpec_id: goodsSpec._id }));
-          actList.push(...gAct);
-        }
-        goodsData.push({ ...others, goods: qp });
-      }
+      const res = await this.orderUtil.makeOrderGoodsData(goods);
+      // 活动和购物券计算数据不需要更改,而重组的商品列表需要进行数据的更改
+      const { actList, goodsSpecs } = res;
+      let { goodsData } = res;
+      // 3.商品总计明细.
+      // 加购不算在优惠内,所以先计算优惠券的明细
+      const discountDetail = await this.ctx.service.user.userCoupon.computedOrderCouponDiscount(coupon, goodsSpecs);
+      // 处理加购商品
+      goodsData = await this.orderUtil.addPlusGoods(goodsData, plus_goods);
+      // 计算价格
+      goodsData = this.orderUtil.computedShopDetail(goodsData);
       const total_detail = {
         goods_total: goodsData.reduce((p, n) => this.ctx.plus(p, n.goods_total), 0),
         freight_total: goodsData.reduce((p, n) => this.ctx.plus(p, n.freight_total), 0),
         act: actList,
       };
-      // 3.商品总计明细.
-      // 计算优惠券的明细
-      const discountDetail = await this.ctx.service.user.userCoupon.computedOrderCouponDiscount(coupon, goodsSpecs);
       const totalDetailData = { ...total_detail, discount_detail: JSON.parse(JSON.stringify(discountDetail)) };
-      // // 接下来组织订单数据
-      // orderData.address = addressData;
-      // orderData.goods = goodsData;
-      // orderData.total_detail = totalDetailData;
-      // // 1.用户数据
-      // orderData.customer = customer;
-      // // 2.下单时间
-      // orderData.buy_time = moment().format('YYYY-MM-DD HH:mm:ss');
-      // // 3.订单号
-      // const str = this.ctx.service.util.trade.createNonceStr();
-      // orderData.no = `${moment().format('YYYYMMDDHHmmss')}-${str}`;
-      // // 4.状态
-      // orderData.status = '0';
-      // // 5.返现部分:邀请人: 自己发链接自己买不行
-      // if (customer !== inviter && ObjectId.isValid(inviter)) orderData.inviter = inviter;
-      // // 生成数据
-      // const order_id = this.tran.insert('Order', orderData);
-      // // 处理库存,删除购物车
-      // await this.dealGoodsNum(goodsData);
-      // // 处理优惠券,改为使用过
-      // if (coupon.length > 0) await this.ctx.service.user.userCoupon.useCoupon(coupon, this.tran);
-      // await this.tran.run();
-      // // 创建定时任务(mq死信机制任务)
+      // 接下来组织订单数据
+      orderData.address = addressData;
+      orderData.goods = goodsData;
+      orderData.total_detail = totalDetailData;
+      // 1.用户数据
+      orderData.customer = customer;
+      // 2.下单时间
+      orderData.buy_time = moment().format('YYYY-MM-DD HH:mm:ss');
+      // 3.订单号
+      const str = this.ctx.service.util.trade.createNonceStr();
+      orderData.no = `${moment().format('YYYYMMDDHHmmss')}-${str}`;
+      // 4.状态
+      orderData.status = '0';
+      // 5.返现部分:邀请人: 自己发链接自己买不行
+      if (customer !== inviter && ObjectId.isValid(inviter)) orderData.inviter = inviter;
+      // 生成数据
+      const order_id = this.tran.insert('Order', orderData);
+      // 处理库存,删除购物车
+      await this.dealGoodsNum(goodsData);
+      // 处理优惠券,改为使用过
+      if (coupon.length > 0) await this.ctx.service.user.userCoupon.useCoupon(coupon, this.tran);
+      await this.tran.run();
+      // 创建定时任务(mq死信机制任务)
       // await this.toMakeTask(order_id);
-      // return order_id;
+      return order_id;
     } catch (error) {
       await this.tran.rollback();
       console.error(error);
@@ -195,6 +167,11 @@ class OrderService extends CrudService {
         const goodsSpec = await this.goodsSpecModel.findById(_id);
         const newNum = this.ctx.minus(goodsSpec.num, buy_num);
         this.tran.update('GoodsSpec', _id, { num: newNum });
+        // 活动相关:
+        // 买赠:不一定非要处理赠品,赠品可能不在库中;
+        // 特价,满减/折:没关系
+        // 加价购,作为另一个商品出现,一样会减少库存,不需要处理
+        // 先不处理活动库存问题.先有逻辑可以做到
         if (cart_id) this.tran.remove('Cart', cart_id);
       }
     }

+ 10 - 23
app/service/trade/orderDetail.js

@@ -60,6 +60,7 @@ class OrderDetailService extends CrudService {
     const shopMoneyDetail = this.ctx.service.util.order.shopMoneyDetail(order);
     // 分订单计数器
     let noTimes = 1;
+    // const list = [];
     for (const s of shopGoods) {
       const shop = _.get(s, 'shop');
       const remarks = _.get(s, 'remarks');
@@ -74,30 +75,14 @@ class OrderDetailService extends CrudService {
       }
       noTimes++;
       const obj = { ...orderDetailData, shop, goods: goodsList, no: detailNo, total_detail, remarks };
-      // #region 团购
-      const type = _.get(order, 'type');
-      let group = _.get(order, 'group');
-      if (type === '1') {
-        // 说明是团购,需要找订单中有没有团的id
-        obj.type = '1';
-        obj.group = group;
-        if (!group) {
-          // 需要创建团,这是团长支付的单子,开团;然后把id回补
-          group = await this.ctx.service.group.group.create(obj, tran);
-          obj.group = group;
-          tran.update('Order', order_id, { group, type: '1' });
-        } else {
-          // 需要参团操作,这是团员的单子,将人加入团中
-          await this.ctx.service.group.group.join(customer, group, tran);
-        }
-      }
-      // #endregion
-      const orderDetail_id = tran.insert('OrderDetail', obj);
-      // arr.push(obj);
+      // 测试用
+      obj.status = '1';
+      // list.push(obj);
+      tran.insert('OrderDetail', obj);
       // 添加该商品是否和平台活动有关,做记录
-      await this.ctx.service.trade.actOrder.create(orderDetail_id, obj, tran);
+      // await this.ctx.service.trade.actOrder.create(orderDetail_id, obj, tran);
     }
-    // await this.model.insertMany(arr);
+    // await this.model.insertMany(list);
   }
 
 
@@ -213,6 +198,8 @@ class OrderDetailService extends CrudService {
           group_config: 1,
           goods: { name: 1, file: 1 },
           file: 1,
+          act: 1,
+          price: 1,
         },
         shop: {
           _id: '$shopInfo._id',
@@ -254,7 +241,7 @@ class OrderDetailService extends CrudService {
         const q = { orderDetail, goodsSpec };
         const rate = await this.goodsRateModel.findOne(q, { _id: 1 });
         obj.rate = _.get(rate, '_id');
-
+        obj.price = _.get(obj, 'price', obj.sell_money);
       }
       // 售后
       const asum = await this.afterSaleModel.count({ order_detail: obj._id, status: { $nin: [ '0', '!1', '!2', '!3', '!4', '!5' ] } });

+ 113 - 21
app/service/util/order.js

@@ -11,6 +11,8 @@ class OrderService extends CrudService {
     this.orderModel = this.ctx.model.Trade.Order;
     this.platformActModel = this.ctx.model.System.PlatformAct;
     this.gjaModel = this.ctx.model.Shop.GoodsJoinAct;
+    this.goodsModel = this.ctx.model.Shop.Goods;
+    this.goodsSpecModel = this.ctx.model.Shop.GoodsSpec;
   }
 
   // #region 下单前计算函数
@@ -73,23 +75,27 @@ class OrderService extends CrudService {
   }
   /**
    * 计算需要支付的金额
-   * @param {Object} order 支付订单信息
-   * @return {Object} 返回:{
-   *  店铺id:金额
-   * }
+   * @param {Object} list 店铺-商品列表
    */
-  shopMoneyTotal(order) {
-    let priceKey;
-    if (_.get(order, 'type', '0') === '1') priceKey = 'ggrp';
-    else priceKey = 'grp';
-    const detail = this.moneyDetail(order);
-    const result = {};
-    for (const s in detail) {
-      const values = Object.values(_.get(detail, s, {}));
-      const realPay = values.reduce((p, n) => this.ctx.plus(p, n[priceKey]), 0);
-      result[s] = realPay;
+  computedShopDetail(list) {
+    for (const i of list) {
+      let goods_total = 0,
+        freight_total = 0,
+        discount = 0;
+      for (const g of i.goods) {
+        // 如果有特价,那就使用特价,没有特价就是用正常销售价
+        goods_total = this.ctx.plus(goods_total, this.ctx.multiply(_.get(g, 'price'), _.get(g, 'buy_num')));
+        freight_total = this.ctx.plus(freight_total, this.ctx.multiply(_.get(g, 'freight'), _.get(g, 'num')));
+        if (_.isArray(g.act)) {
+          const actDiscount = g.act.reduce((p, n) => this.ctx.plus(p, n.discount), 0);
+          discount = this.ctx.plus(discount, actDiscount);
+        }
+      }
+      i.goods_total = goods_total;
+      i.freight_total = freight_total;
+      i.discount = this.ctx.minus(0, discount);
     }
-    return result;
+    return list;
   }
   /**
    * 计算店铺的金额明细
@@ -113,6 +119,8 @@ class OrderService extends CrudService {
       const d = _.get(moneyDetail, s, {});
       obj.goods_total = Object.values(d).reduce((p, n) => this.ctx.plus(p, _.get(n, priceKey, 0)), 0);
       obj.freight_total = Object.values(d).reduce((p, n) => this.ctx.plus(p, _.get(n, 'ft', 0)), 0);
+      const act = Object.values(d).reduce((p, n) => [ ...p, ..._.get(n, 'ad', []) ], []);
+      obj.act = act.filter(f => f.platform_act_type === '5' || f.platform_act_type === '6');
       result[s] = obj;
     }
 
@@ -140,11 +148,6 @@ class OrderService extends CrudService {
    **         platform_act:活动金额
    **      }]
    **      at: 活动优惠总金额
-   **      grp:商品实际支付价格(goods_real_pay: gt - dt - at)
-   **      gsm:规格团购销售价格(group_sell_money)
-   **      gst: 规格团购销售总价(group_sell_total: gsm * bn)
-   **      ggt: 商品团购支付原价(goods_group_total: gst + ft)
-   **      ggrp: 商品团购实际支付价格(goods_group_real_pay: ggt - dt)
    **    }
    **  }
    ** }
@@ -177,13 +180,101 @@ class OrderService extends CrudService {
         // 活动部分
         const at = ad.reduce((p, n) => this.ctx.plus(p, n.discount), 0);
         const grp = this.ctx.minus(this.ctx.minus(gt, dt), at);
-        const obj = { sm, f, bn, st, ft, gt, dd, dt, grp };
+        const obj = { sm, f, bn, st, ft, gt, dd, dt, grp, ad, at };
         shopResult[_id] = obj;
       }
       result[shop] = shopResult;
     }
     return result;
   }
+  // #region 创建订单数据组织部分
+  /**
+   * 组织商品数据
+   * @param {Array} goods 商品列表
+   * @property {Array} actList 活动列表
+   * @property {Array} goodsSpec 后面优惠券使用有关计算的数据
+   * @property {Array} goodsData 组织新的商品数据
+   */
+  async makeOrderGoodsData(goods) {
+    // 商店不做快照,但是商品和商品对应的规格做快照
+    const actList = [],
+      goodsSpecs = [],
+      goodsData = [];
+    for (const i of goods) {
+      const { goods: goodsList, ...others } = i;
+      const qp = [];
+      for (const g of goodsList) {
+        const { goodsSpec_id, goods_id } = g;
+        // 需要的订单数据
+        const orderNeedData = _.pick(g, [ 'act', 'price', 'sp_price', 'num', 'cart_id', 'gift' ]);
+        if (orderNeedData.num) {
+          orderNeedData.buy_num = orderNeedData.num;
+          delete orderNeedData.num;
+        }
+        let goodsSpec = await this.goodsSpecModel.findById(goodsSpec_id);
+        if (!goodsSpec) continue;
+        goodsSpec = JSON.parse(JSON.stringify(goodsSpec));
+        const goods = await this.goodsModel.findById(goods_id);
+        if (goods) goodsSpec.goods = JSON.parse(JSON.stringify(goods));
+        goodsSpec = { ...goodsSpec, ...orderNeedData };
+        qp.push(goodsSpec);
+        const ogs = _.pick(goodsSpec, [ '_id', 'buy_num', 'sell_money', 'price' ]);
+        if (ogs._id) {
+          ogs.id = ogs._id;
+          delete ogs._id;
+        }
+        goodsSpecs.push({ ...ogs });
+        // 将活动提取出来:只需要满减/折;买赠和特价跟着规格走,计算过程中已经处理;加价购是外面处理
+        const { act = [] } = goodsSpec;
+        let gAct = act.filter(f => f.platform_act_type === '5' || f.platform_act_type === '6');
+        gAct = gAct.map(i => ({ ...i, goodsSpec_id: goodsSpec._id }));
+        actList.push(...gAct);
+      }
+      goodsData.push({ ...others, goods: qp });
+    }
+    return { actList, goodsSpecs, goodsData };
+  }
+  /**
+   * 将加购商品组织进商品数据中
+   * @param {Array} goodsData 上面组织过的数据
+   * @param {Array} plus_goods 加购商品
+   */
+  async addPlusGoods(goodsData, plus_goods) {
+    for (const i of plus_goods) {
+      const { shop, shop_name, goods: goods_id, spec: spec_id, _id, config, platform_act, platform_act_type } = i;
+      // 1,验证活动中是否有数据
+      let num = await this.platformActModel.count({ _id: platform_act });
+      // 没找到活动:下一个
+      if (num <= 0) continue;
+      num = await this.gjaModel.count({ _id });
+      // 没有商品数据:下一个
+      if (num <= 0) continue;
+      // 2.做商品,规格的快照
+      let goodsSpec = await this.goodsSpecModel.findById(spec_id);
+      if (!goodsSpec) continue;
+      goodsSpec = JSON.parse(JSON.stringify(goodsSpec));
+      const goods = await this.goodsModel.findById(goods_id);
+      if (goods) goodsSpec.goods = JSON.parse(JSON.stringify(goods));
+      // 3.向上面一样组织数据
+      const price = _.get(config, 'plus_money', _.get(goodsSpec, 'sell_money'));
+      const act = [{ platform_act, platform_act_type, goods: goods_id, spec: spec_id }];
+      goodsSpec.price = price;
+      goodsSpec.act = act;
+      // 商品数量固定为1
+      goodsSpec.buy_num = 1;
+      // 4.合并进goodsData
+      const r = goodsData.find(f => f.shop === shop);
+      if (r) r.goods.push(goodsSpec);
+      else {
+        goodsData.push({ shop, shop_name, goods: [ goodsSpec ] });
+      }
+    }
+
+    return goodsData;
+  }
+  // #endregion
+
+  // #region 活动部分
   /**
    * 检查商品是否满足加价购
    * @param {Array} goodsList 平铺的商品列表
@@ -380,6 +471,7 @@ class OrderService extends CrudService {
     }
     return range;
   }
+  // #endregion
 }
 
 module.exports = OrderService;

+ 8 - 15
app/service/util/orderDetail.js

@@ -43,11 +43,8 @@ class OrderDetailService extends CrudService {
    **      value:优惠价格
    **    },
    **    dt: 优惠总价(d_detail的value之和)
-   **    grp:商品实际支付价格(goods_real_pay: gt - dt)
-   **    gsm:规格团购销售价格(group_sell_money)
-   **    gst: 规格团购销售总价(group_sell_total: gsm * bn)
-   **    ggt: 商品团购支付原价(goods_group_total: gst + ft)
-   **    ggrp: 商品团购实际支付价格(goods_group_real_pay: ggt - dt)
+   **    ad:活动明细
+   **    at:活动优惠价格
    **  },
    **  at: 活动返现总价(act.reduce)
    ** }
@@ -59,7 +56,8 @@ class OrderDetailService extends CrudService {
     const goods = _.get(data, 'goods', []);
     const result = {};
     for (const g of goods) {
-      const { sell_money: sm, freight: f, buy_num: bn, group_config, _id } = g;
+      const { sell_money, freight: f, buy_num: bn, _id, act: ad = [] } = g;
+      const sm = _.get(g, 'price', sell_money);
       const st = this.ctx.multiply(sm, bn);
       const ft = this.ctx.multiply(f, bn);
       const gt = this.ctx.plus(st, ft);
@@ -70,15 +68,10 @@ class OrderDetailService extends CrudService {
         if (value) dd[uc_id] = value;
       }
       const dt = Object.values(dd).reduce((p, n) => this.ctx.plus(p, n), 0);
-      const grp = this.ctx.minus(gt, dt);
-      let obj = { sm, f, bn, st, ft, gt, dd, dt, grp };
-      const gsm = _.get(group_config, 'money');
-      if (gsm) {
-        const gst = this.ctx.multiply(gsm, bn);
-        const ggt = this.ctx.plus(gst, ft);
-        const ggrp = this.ctx.minus(ggt, dt);
-        obj = { ...obj, gsm, gst, ggt, ggrp };
-      }
+      // 活动部分
+      const at = ad.reduce((p, n) => this.ctx.plus(p, n.discount), 0);
+      const grp = this.ctx.minus(this.ctx.minus(gt, dt), at);
+      const obj = { sm, f, bn, st, ft, gt, dd, dt, grp, at, ad };
       result[_id] = obj;
     }
     const act = _.get(data, 'total_detail.act', []);