lrf 2 年之前
父节点
当前提交
b33be7738a

+ 3 - 2
app/controller/user/config/.userCoupon.js

@@ -1,6 +1,6 @@
 module.exports = {
   create: {
-    requestBody: ['customer', 'coupon', 'status'],
+    requestBody: ['customer', 'coupon', 'shop', 'status'],
   },
   destroy: {
     params: ['!id'],
@@ -8,7 +8,7 @@ module.exports = {
   },
   update: {
     params: ['!id'],
-    requestBody: ['customer', 'coupon', 'status'],
+    requestBody: ['customer', 'coupon', 'shop', 'status'],
   },
   show: {
     parameters: {
@@ -22,6 +22,7 @@ module.exports = {
         'meta.createdAt@start': 'meta.createdAt@start',
         'meta.createdAt@end': 'meta.createdAt@end',
         customer: 'customer',
+        shop: 'shop',
         coupon: 'coupon',
         status: 'status',
       },

+ 2 - 0
app/model/user/userCoupon.js

@@ -5,6 +5,7 @@ const metaPlugin = require('naf-framework-mongoose-free/lib/model/meta-plugin');
 // 领劵记录
 const userCoupon = {
   customer: { type: String, required: false, zh: '顾客', ref: 'User.User' }, //
+  shop: { type: String, required: false, zh: '发行店铺', ref: 'Shop.Shop' }, //
   coupon: { type: String, required: false, zh: '优惠券', ref: 'Trade.Coupon' }, //
   status: { type: String, required: false, default: '0', zh: '是否使用' }, //
 };
@@ -12,6 +13,7 @@ const schema = new Schema(userCoupon, { toJSON: { getters: true, virtuals: true
 schema.index({ id: 1 });
 schema.index({ 'meta.createdAt': 1 });
 schema.index({ customer: 1 });
+schema.index({ shop: 1 });
 schema.index({ coupon: 1 });
 schema.index({ status: 1 });
 

+ 43 - 20
app/service/trade/afterSale.js

@@ -89,11 +89,7 @@ class AfterSaleService extends CrudService {
       let discountMoney = 0;
       for (const uc_id in discount_detail) {
         const detail = discount_detail[uc_id];
-        const gd = detail[goods_id];
-        if (gd && !_.get(gd, 'refund', false)) {
-          discountMoney = this.ctx.plus(discountMoney, gd.discountMoney);
-          gd.refund = true;
-        }
+        discountMoney = this.ctx.plus(discountMoney, detail[goods_id]);
       }
       money = this.ctx.minus(money, discountMoney);
     }
@@ -108,26 +104,53 @@ class AfterSaleService extends CrudService {
     await this.ctx.service.trade.pay.refund(obj);
 
     // 检查优惠券是否都退了
-    let allRefund = true;
-    for (const dd of discount_detail) {
-      for (const d in dd) {
-        if (!_.get(d, 'refund')) {
-          allRefund = false;
-          break;
+    // TODO: 查看支付订单-优惠明细中,该优惠券影响的商品是否都有退款/退货成功的记录
+    // 如果有,就说明该优惠券可以退了,没有影响任何一单了
+    const payOrder = _.get(orderDetail, 'order');
+    await this.checkToReturnUserCoupon(payOrder, tran);
+    // tran.update('UserCoupon', id, { status: '0' });
+
+    // 修改订单详情的优惠券标记
+    // tran.update('OrderDetail', orderDetail._id, { 'total_detail.discount_detail': discount_detail });
+  }
+
+  /**
+   * 检查订单的优惠券并退优惠券
+   * @param {Object} order 订单信息
+   * @param {Transaction} tran 事务的实例
+   */
+  async checkToReturnUserCoupon(order, tran) {
+    // 该支付订单下所有拆分的子订单
+    const orderDetailList = await this.orderDetailModel.find({ order: order._id });
+    // 已退款记录
+    const goodsRefundList = [];
+    for (const od of orderDetailList) {
+      const { goods, _id: order_detail } = od;
+      // 组合成查售后的条件
+      // 然后查这些商品有没有退款审核成功的记录
+      const afterSaleQuerys = goods.map(i => ({ order_detail, 'goods._id': i._id, status: '-1' }));
+      for (const asq of afterSaleQuerys) {
+        const num = await this.model.count(asq);
+        if (num > 0) {
+          // 商品有退款审核通过的记录,添加到已退款的列表中
+          goodsRefundList.push(asq);
         }
       }
     }
-
-    if (allRefund) {
-      // 优惠券部分全都退了,那就把优惠券退了
-      const couponIds = Object.keys(discount_detail);
-      for (const id of couponIds) {
-        tran.update('UserCoupon', id, { status: '0' });
+    // 获取支付单的优惠明细
+    const dd = _.get(order, 'total_detail.discount_detail', {});
+    for (const uc_id in dd) {
+      // uc_id 用户领取优惠券的id
+      // 该优惠券影响的商品id列表
+      const goodsIds = Object.keys(_.get(dd, uc_id, {}));
+      // 然后在已退款记录中找,这个优惠券影响的商品是否都退款了.都退款
+      const r = goodsIds.every(i => goodsRefundList.find(f => i === f['goods._id']));
+      if (r) {
+        // 说明这个优惠券影响的商品都退了,这个优惠券也就能退了
+        tran.update('UserCoupon', uc_id, { status: '0' });
       }
-    }
 
-    // 修改订单详情的优惠券标记
-    tran.update('OrderDetail', orderDetail._id, { 'total_detail.discount_detail': discount_detail });
+    }
   }
 
   async fetch(filter) {

+ 2 - 1
app/service/trade/order.js

@@ -33,6 +33,7 @@ class OrderService extends CrudService {
       const customer = _.get(user, '_id');
       if (!customer) throw new BusinessError(ErrorCode.NOT_LOGIN, '未找到用户信息');
       const { address, goods, total_detail, coupon = [] } = body;
+      if (coupon.length > 1) throw new BusinessError(ErrorCode.DATA_INVALID, '目前只允许使用1张优惠券');
       // 检测商品是否可以下单
       for (const i of goods) {
         const { shop } = i;
@@ -67,7 +68,7 @@ class OrderService extends CrudService {
           if (cart_id) obj.cart_id = cart_id;
           qp.push(obj);
 
-          goodsSpecs.push({ id: goodsSpec_id, buy_num: num });
+          goodsSpecs.push({ id: goodsSpec_id, buy_num: num, sell_money: obj.sell_money });
         }
         goodsData.push({ ...others, goods: qp });
       }

+ 1 - 7
app/service/trade/pay.js

@@ -188,13 +188,7 @@ class PayService extends CrudService {
         // detail: 该优惠券下的明细
         const detail = discount_detail[uc];
         if (!detail) continue;
-        for (const gsid in detail) {
-          // gsid:商品规格的id
-          // gs:该商品的价格明细,只取出discountMoney就行
-          const gs = detail[gsid];
-          const dm = _.get(gs, 'discountMoney', 0);
-          totalDiscount = this.ctx.plus(totalDiscount, dm);
-        }
+        totalDiscount = this.ctx.plus(totalDiscount, Object.values(detail).reduce((p, n) => this.ctx.plus(p, n), 0));
       }
       total = this.ctx.minus(total, totalDiscount);
     }

+ 22 - 29
app/service/user/userCoupon.js

@@ -36,17 +36,17 @@ class UserCouponService extends CrudService {
   async getCoupon({ coupon_id }) {
     const coupon = await this.couponModel.findById(coupon_id);
     if (!coupon) throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '未找到优惠券');
-    const canGet = parseInt(coupon.num) - 1 < 0;
+    const canGet = this.ctx.minus(coupon.num, 1) < 0;
     if (canGet) throw new BusinessError(ErrorCode.DATA_NOT_EXIST, '您手慢了,没抢到');
     const res = await this.checkCouponCanGet(coupon);
     if (!res.result) return res;
     const customer = _.get(this.ctx, 'user._id');
     if (!customer) throw new BusinessError(ErrorCode.NOT_LOGIN, '未找到用户信息');
-    const data = { coupon: coupon_id, customer };
+    const data = { coupon: coupon_id, customer, shop: _.get(coupon, 'shop') };
     try {
       // 领券=>减券库存
       this.tran.insert('UserCoupon', data);
-      this.tran.update('Coupon', coupon_id, { num: parseInt(coupon.num) - 1 });
+      this.tran.update('Coupon', coupon_id, { num: this.ctx.minus(coupon.num, 1) });
       await this.tran.run();
     } catch (error) {
       console.log(error);
@@ -263,7 +263,7 @@ class UserCouponService extends CrudService {
     const { discount_type, discount_config } = coupon;
     const { limit, min, max } = discount_config;
     // 符合条件的商品的总价
-    const goodsTotal = goodsList.reduce((p, n) => p + (parseFloat(n.goods_total) || 0), 0);
+    const goodsTotal = goodsList.reduce((p, n) => this.ctx.plus(p, n.goods_total), 0);
     if (limit !== 'nolimit') {
       // 有最低消费的限制,就需要看看下满足条件的商品够不够这个金额
       // 消费下限 大于 满足优惠券使用的商品的消费总额,则不能使用这个券,消费的钱不够
@@ -285,11 +285,12 @@ class UserCouponService extends CrudService {
       if (!max) outLimit = false;
       else {
         // 有上限,则需要计算
-        const percent = 1 - parseFloat(min) / 10;
+        // const percent = 1 - parseFloat(min) / 10;
+        const percent = this.ctx.minus(1, this.ctx.divide(min, 10));
         // 计算实际折扣 减了 多少钱
-        const discountMoney = _.floor(goodsTotal * percent, 2);
+        const discountMoney = this.ctx.multiply(goodsTotal, percent);
         // 最后看下 不限制减的钱 是不是 超过了 上限
-        outLimit = discountMoney > parseFloat(max);
+        outLimit = this.ctx.minus(discountMoney, max) > 0;
         // 超过了,就将上限的金额拿去按比例分配
         if (outLimit) discountRealMoney = parseFloat(max);
       }
@@ -316,23 +317,19 @@ class UserCouponService extends CrudService {
       const g = goodsList[i];
       const { goods_total } = g;
       const id = _.get(g, 'goodsSpec._id');
-      const obj = { original: goods_total };
+      let dm = 0;
+      console.log(goods_total, goodsTotal);
       // 除了最后一个商品,其余的商品均按比例分配
       if (i < goodsList.length - 1) {
-        const percent = _.floor(goods_total / goodsTotal);
-        const discountMoney = _.floor(discountRealMoney * percent, 2);
-        const realPay = _.floor(goods_total - discountMoney, 2);
-        obj.realPay = realPay;
-        obj.discountMoney = discountMoney;
-        allReadyDiscount += discountMoney;
+        const percent = this.ctx.divide(goods_total, goodsTotal);
+        dm = this.ctx.multiply(discountRealMoney, percent);
+        allReadyDiscount += dm;
       } else {
         // 最后一个商品是剩余的可分配的钱
-        const discountMoney = _.floor(discountRealMoney - allReadyDiscount, 2);
-        const realPay = _.floor(goods_total - discountMoney, 2);
-        obj.realPay = realPay;
-        obj.discountMoney = discountMoney;
+        dm = this.ctx.minus(discountRealMoney, allReadyDiscount);
       }
-      result[id] = obj;
+      console.log(dm);
+      result[id] = dm;
     }
     return result;
   }
@@ -345,19 +342,15 @@ class UserCouponService extends CrudService {
   discountPercentForEachGoods(coupon, goodsList) {
     const { discount_config } = coupon;
     const { min } = discount_config;
-    const percent = parseFloat(min) / 10;
+    const percent = this.ctx.multiply(min, 10);
     const result = {};
     for (const g of goodsList) {
       const { goods_total } = g;
       const id = _.get(g, 'goodsSpec._id');
-      const realPay = _.floor(goods_total * percent, 2);
-      const discountMoney = goods_total - realPay;
-      const obj = {
-        original: goods_total,
-        realPay,
-        discountMoney,
-      };
-      result[id] = obj;
+      const realPay = this.ctx.multiply(goods_total, percent);
+      const discountMoney = this.ctx.minus(goods_total, realPay);
+      console.log(discountMoney);
+      result[id] = discountMoney;
     }
     return result;
   }
@@ -397,7 +390,7 @@ class UserCouponService extends CrudService {
       const r = orderInfo.find(f => ObjectId(f.id).equals(goodsSpec._id));
       if (r) obj.buy_num = r.buy_num;
       if (obj.buy_num) {
-        obj.goods_total = parseInt(obj.buy_num) * parseFloat(_.get(obj.goodsSpec, 'sell_money'));
+        obj.goods_total = this.ctx.multiply(obj.buy_num, _.get(obj.goodsSpec, 'sell_money'));
       }
       return obj;
     });