OrderCouponLogic.php 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | LikeShop有特色的全开源社交分销电商系统
  4. // +----------------------------------------------------------------------
  5. // | 欢迎阅读学习系统程序代码,建议反馈是我们前进的动力
  6. // | 商业用途务必购买系统授权,以免引起不必要的法律纠纷
  7. // | 禁止对系统程序代码以任何目的,任何形式的再发布
  8. // | 微信公众号:好象科技
  9. // | 访问官网:http://www.likemarket.net
  10. // | 访问社区:http://bbs.likemarket.net
  11. // | 访问手册:http://doc.likemarket.net
  12. // | 好象科技开发团队 版权所有 拥有最终解释权
  13. // +----------------------------------------------------------------------
  14. // | Author: LikeShopTeam-段誉
  15. // +----------------------------------------------------------------------
  16. namespace app\shopapi\logic\Order;
  17. use app\common\enum\CouponEnum;
  18. use app\common\logic\BaseLogic;
  19. use app\common\model\Coupon;
  20. use app\common\model\GoodsCategoryIndex;
  21. /**
  22. * Class OrderCouponLogic
  23. * 订单优惠券逻辑
  24. * @package app\shopapi\logic
  25. */
  26. class OrderCouponLogic extends BaseLogic
  27. {
  28. /**
  29. * @notes 计算优惠券优惠金额
  30. * @param $goodsLists //商品列表
  31. * @param $couponListsId //优惠券id(用户的领取记录id,coupon_list_id)
  32. * @return array
  33. * @throws \Exception
  34. * @author 段誉
  35. * @date 2021/7/30 14:46
  36. */
  37. public static function calculateCouponDiscount($goodsLists, $couponListsId)
  38. {
  39. //获取优惠券信息
  40. $coupon = (new Coupon())->alias('c')
  41. ->field('c.*, cl.invalid_time, cl.status as cl_status')
  42. ->join('coupon_list cl', 'cl.coupon_id = c.id')
  43. ->where(['cl.id' => $couponListsId])
  44. ->findOrEmpty();
  45. //优惠券不存在或已过优惠券可使用时间
  46. if ($coupon->isEmpty()
  47. || time() > $coupon['invalid_time']
  48. || $coupon['cl_status'] != CouponEnum::USE_STATUS_NOT
  49. ) {
  50. throw new \Exception('优惠券不可使用');
  51. }
  52. $couponGoods = $coupon['use_goods_ids'];
  53. //可参与优惠的商品总金额和总数量
  54. $ableDiscount = self::ableDiscount($goodsLists, $coupon, $couponGoods);
  55. // 折扣券 计算商品可优惠金额 并加上最大优惠限制
  56. if ($coupon['condition_type'] == CouponEnum::CONDITION_TYPE_DISCOUNT) {
  57. $coupon['money'] = min($ableDiscount['price'] * (10 - $coupon['discount_ratio']) / 10, $coupon['discount_max_money']);
  58. }
  59. $totalDiscount = 0;
  60. $discountKey = 0;
  61. //计算优惠金额和每个商品项的可得优惠金额
  62. foreach ($goodsLists as &$goods) {
  63. //指定商品可用
  64. if ($coupon['use_goods_type'] == CouponEnum::USE_GOODS_TYPE_ALLOW && !in_array($goods['goods_id'], $couponGoods)) {
  65. continue;
  66. }
  67. //指定商品不可用
  68. if ($coupon['use_goods_type'] == CouponEnum::USE_GOODS_TYPE_BAN && in_array($goods['goods_id'], $couponGoods)) {
  69. continue;
  70. }
  71. // 指定分类可用
  72. if ($coupon['use_goods_type'] == CouponEnum::USE_GOODS_TYPE_CATEGORY) {
  73. $categoryIds = array_column($goods['goods_category_index2'] ?? [], 'category_id');
  74. if (! array_intersect($coupon['use_goods_category_ids'], $categoryIds)) {
  75. continue;
  76. }
  77. }
  78. //订单商品小计
  79. $sub_price = round($goods['sell_price'] * $goods['goods_num'], 2);
  80. //每个订单商品可以获得的优惠金额 (订单商品/可优惠商品总金额) * 优惠券金额
  81. $discount = $ableDiscount['price'] <= 0 ? 0 : round($sub_price / $ableDiscount['price'] * $coupon['money'], 2);
  82. //用于判断当前是否为最后一个商品
  83. if (($discountKey + 1) == $ableDiscount['count']) {
  84. $discount = round($coupon['money'] - $totalDiscount, 2);
  85. }
  86. //当前可获得优惠大于当前订单商品时
  87. $discount = ($discount > $sub_price) ? $sub_price : $discount;
  88. //每个商品优惠的金额
  89. $goods['discount_price'] = $discount;
  90. $discountKey += 1;
  91. $totalDiscount += $discount;
  92. }
  93. return [
  94. 'goods' => $goodsLists,
  95. 'discount' => round($totalDiscount, 2),
  96. ];
  97. }
  98. /**
  99. * @notes 可参与优惠券优惠的总金额和总数量
  100. * @param $goods //订单商品列表
  101. * @param $coupon //优惠券信息
  102. * @param $couponGoods //优惠券关联商品id
  103. * @return array
  104. * @throws \Exception
  105. * @author 段誉
  106. * @date 2021/7/30 14:44
  107. */
  108. public static function ableDiscount($goods, $coupon, $couponGoods)
  109. {
  110. $discountPrice = 0;
  111. $discountCount = 0;
  112. //1-全部商品;2-指定商品;3-指定商品不可用
  113. foreach ($goods as $good) {
  114. //全部商品
  115. if ($coupon['use_goods_type'] == CouponEnum::USE_GOODS_TYPE_NOT) {
  116. $discountPrice += $good['sell_price'] * $good['goods_num'];
  117. $discountCount += 1;
  118. }
  119. //指定商品
  120. if (($coupon['use_goods_type'] == CouponEnum::USE_GOODS_TYPE_ALLOW)
  121. && in_array($good['goods_id'], $couponGoods)
  122. ) {
  123. $discountPrice += $good['sell_price'] * $good['goods_num'];
  124. $discountCount += 1;
  125. }
  126. //指定商品不可用
  127. if ($coupon['use_goods_type'] == CouponEnum::USE_GOODS_TYPE_BAN
  128. && !in_array($good['goods_id'], $couponGoods)
  129. ) {
  130. $discountPrice += $good['sell_price'] * $good['goods_num'];
  131. $discountCount += 1;
  132. }
  133. // 指定分类可用
  134. if ($coupon['use_goods_type'] == CouponEnum::USE_GOODS_TYPE_CATEGORY) {
  135. $categoryIds = array_column($good['goods_category_index2'] ?? [], 'category_id');
  136. if ($categoryIds && array_intersect($coupon['use_goods_category_ids'], $categoryIds)) {
  137. $discountPrice += $good['sell_price'] * $good['goods_num'];
  138. $discountCount += 1;
  139. }
  140. }
  141. }
  142. if ($coupon['condition_type'] != CouponEnum::CONDITION_TYPE_NOT && $discountPrice < $coupon['condition_money'] ) {
  143. throw new \Exception('所结算的商品中未满足使用的金额');
  144. }
  145. return [
  146. 'count' => $discountCount,
  147. 'price' => $discountPrice
  148. ];
  149. }
  150. }