FreeShippingMarketing.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. <?php
  2. namespace addons\UpgradeGift\common\logic\order\marketing;
  3. use common\enums\GoodsTypeEnum;
  4. use common\enums\ShippingTypeEnum;
  5. use common\models\goods\FreeShippingRules;
  6. use common\models\goods\FreightRules;
  7. use common\models\goods\Goods;
  8. use common\models\user\UserAddress;
  9. use Yii;
  10. use yii\helpers\Json;
  11. /**
  12. * 运费减免计算
  13. * @Author bing
  14. * @DateTime 2021-09-27 19:07:32
  15. * @copyright: Copyright (c) 2020 广东七件事集团
  16. */
  17. class FreeShippingMarketing extends BaseMarketing{
  18. public function execute( $form){}
  19. /**
  20. * 计算运费
  21. * @Author: lun
  22. * @DateTime: 2021/10/6 0006 10:37
  23. * @Copyright: copyright (c) 2021 广东七件事集团
  24. * @param $item
  25. * @param $form
  26. * @param $extra
  27. * @return mixed
  28. */
  29. public static function compute($item, &$form, &$extra)
  30. {
  31. if (isset($form->data['shipping_type']) && $form->data['shipping_type']==ShippingTypeEnum::PICKUP){
  32. return $item;
  33. }
  34. // 获取用户收货地址信息
  35. if (empty($extra['address'])) {
  36. $address = UserAddress::getOne([['id' => $form['address_id']], ['user_id' => $form['user_id']]], true);
  37. $extra['address'] = $address;
  38. } else {
  39. $address = $extra['address'];
  40. }
  41. // 收货地址
  42. if(empty($address)){
  43. $address['province_id'] = $address['city_id'] = $address['district_id'] = $address['town_id'] = $address['community_id'] = 0;
  44. $address['province'] = $address['city'] = $address['district'] = $address['town'] = $address['community'] = $address['detail'] = $address['name'] = $address['mobile'] ='';
  45. }
  46. // 收货地址
  47. $item['mch_order_info']['province'] = $address['province_id'];
  48. $item['mch_order_info']['city'] = $address['city_id'];
  49. $item['mch_order_info']['area'] = $address['district_id'];
  50. $item['mch_order_info']['town'] = $address['town_id'];
  51. $item['mch_order_info']['community'] = $address['community_id'];
  52. $item['mch_order_info']['region_name'] = $address['province'] .' '. $address['city'] .' '. $address['district'].' '.$address['town'].' '.$address['community'];
  53. $item['mch_order_info']['address'] = $address['detail'];
  54. $item['mch_order_info']['receiver_name'] = $address['name'];
  55. $item['mch_order_info']['mobile'] = $address['mobile'];
  56. $shipping_fee = 0;// 订单总运费初始化
  57. $group_order_fee = 0;// 单个商户订单运费
  58. $is_free = false;// 是否免邮
  59. $compute_shipping = [];// 运费计算,配合运费规则compute_type == 2使用
  60. // 获取包邮地区
  61. $feeShippingRules = FreeShippingRules::getFreeShippingRulesArea($item['mch_order_info']['mall_id'], $item['mch_order_info']['mch_id']);
  62. // 获取运费模板
  63. $freightRules = FreightRules::getFreightRulesArea($item['mch_order_info']['mall_id'], $item['mch_order_info']['mch_id']);
  64. // 包邮计算
  65. foreach ($feeShippingRules as $fee) {
  66. // 如果包邮金额<=购买商品金额,并且地区符合收货地址则免邮
  67. if ($fee['money'] <= $item['mch_order_info']['goods_price'] && self::isInArea($address, $fee['district_ids'])) {
  68. $is_free = true;
  69. continue;
  70. }
  71. }
  72. // 不免邮处理
  73. if ($is_free == false) {
  74. foreach ($item['goods'] as $good_id => $good) {
  75. $good_info = Goods::findOne(['id' => $good_id]);
  76. if($good_info['goods_type'] == GoodsTypeEnum::GoodsTypeVirtual) continue;
  77. $good_num = 0;// 第N个商品
  78. if ($good['num'] > 1) {
  79. $good_num+= $good['num'];
  80. } else {
  81. $good_num++;
  82. }
  83. // 物流方式
  84. if (!in_array(ShippingTypeEnum::LOGISTICS, explode(',', $form['sku'][$good_id]['goods']['freight_type']))) continue;
  85. // 计算满件包邮
  86. if ($form['sku'][$good_id]['goods']['free_shipping_num'] > 0 && $good['num'] >= $form['sku'][$good_id]['goods']['free_shipping_num']) continue;
  87. // 计算满元包邮
  88. if ($form['sku'][$good_id]['goods']['free_shipping_money'] > 0 && $good['goods_price'] >= $form['sku'][$good_id]['goods']['free_shipping_money']) continue;
  89. // 运费规则
  90. if ($form['sku'][$good_id]['goods']['freight_rules_type'] == 1) {
  91. // 根据商品id获取对应的规则
  92. $thisRules = isset($freightRules[$form['sku'][$good_id]['goods']['freight_id']])
  93. ? $freightRules[$form['sku'][$good_id]['goods']['freight_id']]
  94. : [];
  95. // 运费模板ID
  96. $rule_id = $thisRules['id'] ?? 0;
  97. if(!empty($thisRules['rule'])){
  98. foreach ($thisRules['rule'] as $rule) {
  99. // 获取该模板的所有地区id
  100. $areaArr = array_column($rule['list'], 'id');
  101. // 判断收货地址是否在模板中
  102. if (self::isInArea($address, $areaArr)) {
  103. if ($thisRules['type'] == 1) {// 按重计费
  104. $new_num_weight = $form['sku'][$good_id]['weight'] * $good['num'];
  105. } else {// 按件计费
  106. $new_num_weight = $good['num'];
  107. }
  108. // 计算[首件/首重]收费,只要商品有重量并且运费有首重设置就需要给运费
  109. if ($new_num_weight > 0 && $rule['first'] > 0) {
  110. if ($thisRules['compute_type'] == 1) {
  111. $group_order_fee += $rule['firstPrice'];
  112. $shipping_fee += $rule['firstPrice'];
  113. }
  114. }
  115. if ($thisRules['type'] == 1) {// 计算续重收费
  116. if ($thisRules['compute_type'] == 2) {// 按同件商品计算,扣除首重后,剩余不同商品都按续重计算
  117. self::getShopFee($rule_id, $thisRules['type'], $rule, $new_num_weight, $compute_shipping);
  118. } else {
  119. $surplus_weight = $new_num_weight - $rule['first'];// 剩余重量 = 总重量 - 首重重量
  120. // 续重运费 = (剩余重量 / 续件重量)[向上取整] * 续重费用 [向下取整]
  121. if($surplus_weight > 0 && isset($rule['second'])&&$rule['second']>0) {
  122. $fee = floor(ceil($surplus_weight / $rule['second']) * $rule['secondPrice']);
  123. $shipping_fee += $fee;
  124. $group_order_fee += $fee;
  125. }
  126. }
  127. } else {// 计算续件收费
  128. if ($thisRules['compute_type'] == 2) {// 按同件商品计算,扣除首件后,剩余不同商品都按续件计算
  129. self::getShopFee($rule_id, $thisRules['type'], $rule, $new_num_weight, $compute_shipping);
  130. } else {
  131. $surplus_num = $good_num - $rule['first'];// 减扣首件数量
  132. if ($surplus_num > 0 && $rule['second'] > 0) {
  133. // 续费 * (减扣首件数量 / 续件数量)[向下取整]
  134. if(isset($rule['second']) && $rule['second'] > 0){
  135. $fee = $rule['secondPrice'] * floor($surplus_num / $rule['second']);
  136. $shipping_fee += $fee;
  137. $group_order_fee += $fee;
  138. }
  139. }
  140. }
  141. }
  142. continue;// 已计算好运费则跳出循环
  143. }
  144. }
  145. }
  146. } else {
  147. // 自定义运费
  148. if ($form['sku'][$good_id]['goods']['shipping_fee'] >= 0) {
  149. $shipping_fee+= $form['sku'][$good_id]['goods']['shipping_fee'];
  150. $group_order_fee+= $form['sku'][$good_id]['goods']['shipping_fee'];
  151. }
  152. }
  153. }
  154. // 按同件商品运费计算
  155. if ($compute_shipping) {
  156. $shop_fee_assignment = self::shopFeeAssignment($compute_shipping);
  157. $shipping_fee += $shop_fee_assignment['shipping_fee'] ?? 0;
  158. $group_order_fee += $shop_fee_assignment['group_order_fee'] ?? 0;
  159. }
  160. // 单个商户订单运费计算
  161. $item['mch_order_info']['shipping_type'] = $form['data']['shipping_type'] ?? ShippingTypeEnum::LOGISTICS;
  162. $item['mch_order_info']['shipping_money'] = $group_order_fee;
  163. }
  164. // 运费赋值
  165. $item['mch_order_info']['pay_money'] = $item['mch_order_info']['pay_money'] + $shipping_fee;
  166. $prev_shipping_fee = $form->marketing['deduct']['shipping_fee']['money'] ?? 0;
  167. $form->marketing['deduct']['shipping_fee'] = ['name' => '运费', 'money' => $prev_shipping_fee + $shipping_fee];
  168. return $item;
  169. }
  170. /**
  171. * 判断收货地址是否在地区中
  172. * @Author: lun
  173. * @DateTime: 2021/9/30 0030 14:45
  174. * @Copyright: copyright (c) 2021 广东七件事集团
  175. * @param $address
  176. * @param $areaArr
  177. * @return bool
  178. */
  179. private static function isInArea($address, $areaArr)
  180. {
  181. $return = false;
  182. if(in_array($address['province_id'], $areaArr) || in_array($address['city_id'], $areaArr) || in_array($address['district_id'], $areaArr)) $return = true;
  183. return $return;
  184. }
  185. /**
  186. * 运费模板为:按同件商品计算
  187. * 目的:不同商品使用不同的模板情况下的混合计算,主要算出:首件/重 + 续件/重 运费费用
  188. * @Author: lun
  189. * @DateTime: 2023/8/12 0012 17:11
  190. * @Copyright: copyright (c) 2021 广东七件事集团
  191. * @param $rule_id
  192. * @param $rule
  193. * @param $goods_weight_or_num
  194. * @param array $data
  195. */
  196. private static function getShopFee($rule_id, $type, $rule, $goods_weight_or_num, &$data = [])
  197. {
  198. $data[$rule_id]['total_weight_or_num'] = empty($data[$rule_id]['total_weight_or_num']) ? $goods_weight_or_num : $data[$rule_id]['total_weight_or_num'] + $goods_weight_or_num;
  199. if (empty($data[$rule_id]['first_fee'])) $data[$rule_id]['first_fee'] = $rule['firstPrice'];// 首重/件 费用
  200. if (empty($data[$rule_id]['group_first_fee'])) $data[$rule_id]['group_first_fee'] = $rule['firstPrice'];// 首重/件 费用
  201. if (empty($data[$rule_id]['first_weight_or_num'])) $data[$rule_id]['first_weight_or_num'] = $rule['first'];// 同模板商品首重
  202. if (empty($data[$rule_id]['renew_price'])) $data[$rule_id]['renew_price'] = 0;// 续重/件 费用
  203. $surplus_weight_or_num = $data[$rule_id]['total_weight_or_num'] - $data[$rule_id]['first_weight_or_num'];// 总重量/总数量 - 首重/件 = 续重/件
  204. // 续重/件运费 = (剩余重量 / 续件重量)[向上取整] * 续重费用 [向下取整]
  205. if($surplus_weight_or_num > 0 && isset($rule['second']) && $rule['second'] > 0) {
  206. if ($type == 2) {// 按件计费
  207. $fee = $rule['secondPrice'] * floor($surplus_weight_or_num / $rule['second']);
  208. } else {// 按重计费
  209. $fee = floor(ceil($surplus_weight_or_num / $rule['second']) * $rule['secondPrice']);
  210. }
  211. $data[$rule_id]['renew_price'] = $fee;// 每次都覆盖之前的值,为了重新算出最后的续重/件费用
  212. }
  213. }
  214. /**
  215. * 将计算好的不同运费模板运费加起来
  216. * @Author: lun
  217. * @DateTime: 2023/8/12 0012 17:13
  218. * @Copyright: copyright (c) 2021 广东七件事集团
  219. * @param $shopFeeList
  220. * @return array
  221. */
  222. private static function shopFeeAssignment($shopFeeList)
  223. {
  224. $shop_fee = 0;
  225. $group_order_fee = 0;
  226. foreach ($shopFeeList as $item) {
  227. $shop_fee += $item['first_fee'] + $item['renew_price'];
  228. $group_order_fee += $item['group_first_fee'] + $item['renew_price'];
  229. }
  230. return ['shipping_fee' => $shop_fee, 'group_order_fee' => $group_order_fee];
  231. }
  232. }