ExpressService.php 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. <?php
  2. namespace app\common\service\delivery;
  3. use app\common\library\helper;
  4. use app\common\model\settings\Setting as SettingModel;
  5. use app\common\enum\order\OrderTypeEnum;
  6. /**
  7. * 快递配送服务类
  8. */
  9. class ExpressService
  10. {
  11. private $appId; // 商城id
  12. private $cityId; // 用户收货城市id
  13. private $productList; // 订单商品列表
  14. private $orderType; // 订单类型 (主商城、拼团)
  15. /**
  16. * 配送服务类构造方法
  17. */
  18. public function __construct(
  19. $appId,
  20. $cityId,
  21. $productList,
  22. $orderType = OrderTypeEnum::MASTER
  23. )
  24. {
  25. $this->appId = $appId;
  26. $this->cityId = $cityId;
  27. $this->productList = $productList;
  28. $this->orderType = $orderType;
  29. }
  30. /**
  31. * 根据用户收货城市id 验证是否在商品配送规则中
  32. */
  33. public function getNotInRuleProduct()
  34. {
  35. if ($this->cityId) {
  36. foreach ($this->productList as $product) {
  37. if($product['is_virtual'] == 1){
  38. continue;
  39. }
  40. $cityIds = [];
  41. foreach ($product['delivery']['rule'] as $item)
  42. $cityIds = array_merge($cityIds, $item['region_data']);
  43. if (!in_array($this->cityId, $cityIds))
  44. return $product;
  45. }
  46. }
  47. return false;
  48. }
  49. /**
  50. * 设置订单商品的运费
  51. */
  52. public function setExpressPrice()
  53. {
  54. // 订单商品总金额
  55. $orderTotalPrice = helper::getArrayColumnSum($this->productList, 'total_price');
  56. $index = 0;
  57. foreach ($this->productList as &$product) {
  58. // 如果是虚拟物品,则为0
  59. if($product['is_virtual'] == 1){
  60. $product['express_price'] = 0;
  61. }else{
  62. $product['express_price'] = 0;
  63. if($index == 0){
  64. if($orderTotalPrice < 300){
  65. $product['express_price'] = 15;
  66. }else{
  67. $product['express_price'] = 0;
  68. }
  69. }
  70. //$product['express_price'] = $this->onCalcProductfreight($product, $orderTotalPrice);
  71. }
  72. $index++;
  73. }
  74. return true;
  75. }
  76. /**
  77. * 获取订单最终运费
  78. */
  79. public function getTotalFreight()
  80. {
  81. if (empty($this->productList)) {
  82. return 0.00;
  83. }
  84. // 所有商品的运费金额
  85. $expressPriceArr = helper::getArrayColumn($this->productList, 'express_price');
  86. if (empty($expressPriceArr)) {
  87. return 0.00;
  88. }
  89. // 计算最终运费
  90. return $this->freightRule($expressPriceArr);
  91. }
  92. /**
  93. * 计算商品的配送费用
  94. */
  95. private function onCalcProductfreight(&$product, $orderTotalPrice)
  96. {
  97. // 判断是否满足满额包邮条件
  98. if ($this->isFullFree($product['product_id'], $orderTotalPrice)) {
  99. return 0.00;
  100. }
  101. // 当前收货城市配送规则
  102. $rule = $this->getCityDeliveryRule($product);
  103. // 商品总重量
  104. $totalWeight = helper::bcmul($product['product_sku']['product_weight'], $product['total_num']);
  105. // 商品总数量or总重量
  106. $total = $product['delivery']['method']['value'] == 10 ? $product['total_num'] : $totalWeight;
  107. if ($total <= $rule['first']) {
  108. return helper::number2($rule['first_fee']);
  109. }
  110. // 续件or续重 数量
  111. $additional = $total - $rule['first'];
  112. if ($additional <= $rule['additional']) {
  113. return helper::number2(helper::bcadd($rule['first_fee'], $rule['additional_fee']));
  114. }
  115. // 计算续重/件金额
  116. if ($rule['additional'] < 1) {
  117. // 配送规则中续件为0
  118. $additionalFee = 0.00;
  119. } else {
  120. $additionalFee = helper::bcdiv($rule['additional_fee'], $rule['additional']) * $additional;
  121. }
  122. return helper::number2(helper::bcadd($rule['first_fee'], $additionalFee));
  123. }
  124. /**
  125. * 判断是否满足满额包邮条件
  126. */
  127. private function isFullFree($productId, $orderTotalPrice)
  128. {
  129. // 非商城主订单不参与满额包邮
  130. if ($this->orderType !== OrderTypeEnum::MASTER) {
  131. return false;
  132. }
  133. // 获取满额包邮设置
  134. $options = SettingModel::getItem('full_free', $this->appId);
  135. if (
  136. $options['is_open'] == false
  137. || $orderTotalPrice < $options['money']
  138. /*|| in_array($productId, $options['notin_product'])
  139. || in_array($this->cityId, $options['notin_region']['citys'])*/
  140. ) {
  141. return false;
  142. }
  143. return true;
  144. }
  145. /**
  146. * 根据城市id获取规则信息
  147. */
  148. private function getCityDeliveryRule($product)
  149. {
  150. foreach ($product['delivery']['rule'] as $item) {
  151. if (in_array($this->cityId, $item['region_data'])) {
  152. return $item;
  153. }
  154. }
  155. return false;
  156. }
  157. /**
  158. * 根据运费组合策略 计算最终运费
  159. */
  160. private function freightRule($expressPriceArr)
  161. {
  162. $expressPrice = 0.00;
  163. switch (SettingModel::getItem('trade', $this->appId)['freight_rule']) {
  164. case '10': // 策略1: 叠加
  165. $expressPrice = array_sum($expressPriceArr);
  166. break;
  167. case '20': // 策略2: 以最低运费结算
  168. $expressPrice = min($expressPriceArr);
  169. break;
  170. case '30': // 策略3: 以最高运费结算
  171. $expressPrice = max($expressPriceArr);
  172. break;
  173. }
  174. return $expressPrice;
  175. }
  176. }