You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

202 lines
6.6 KiB

  1. <?php
  2. namespace api\logic;
  3. use backend\modules\goods\models\ars\Goods;
  4. use backend\modules\shop\models\ars\ExpressArea;
  5. use backend\modules\shop\models\ars\ExpressTemplate;
  6. use backend\modules\shop\models\ars\Order;
  7. use backend\modules\shop\models\ars\OrderGoods;
  8. use Yii;
  9. use yii\base\BaseObject;
  10. use yii\web\NotFoundHttpException;
  11. /**
  12. * @author iron
  13. * @email weiriron@gmail.com
  14. * @package api\logic
  15. */
  16. class ExpressLogic extends BaseObject
  17. {
  18. public $viewAction = 'view';
  19. /**
  20. * @var Order
  21. * 订单
  22. */
  23. public $order;
  24. /**
  25. * @param $order
  26. * @return float|int
  27. * @throws NotFoundHttpException
  28. * 计算运费
  29. */
  30. public function countShippingAmount($order)
  31. {
  32. if ($order->shipping_type == Order::SHIPPING_TYPE_PICKED_UP) {
  33. return 0;
  34. }
  35. $this->order = $order;
  36. $allGoods = $this->findDifferentExpressTypeGoods($order);/*获取不同运费计算模式的商品*/
  37. $uniformPostage = $this->countGoodsExpress($allGoods['uniformPostageGoods'], Goods::EXPRESS_TYPE_UNIFORM_POSTAGE);/*计算统一运费模式下所有商品运费*/
  38. $expressTemplate = $this->countGoodsExpress($allGoods['uniformPostageGoods'], Goods::EXPRESS_TYPE_UNIFORM_POSTATE);/*计算运费模板模式下所有商品的运费*/
  39. return $uniformPostage > $expressTemplate ? $uniformPostage : $expressTemplate;/*比较两种不同运费计算模式下,取金额大的值为最终收取运费*/
  40. }
  41. /*--------------------------------------------------------------------------------------*/
  42. /**
  43. * @param $order
  44. * @return array
  45. * @throws NotFoundHttpException
  46. *
  47. */
  48. private function findDifferentExpressTypeGoods($order)
  49. {
  50. $uniformPostage = $useTemplate = [];
  51. $allGoods = OrderGoods::findAll(['order_id' => $order->id, 'user_id' => Yii::$app->user->getId()]);
  52. foreach ($allGoods as $orderGoods) {
  53. $goods = Goods::findOne(['id' => $orderGoods->goods_id, 'is_sale' => Goods::IS_SALE_YES, 'is_delete' => Goods::IS_DELETE_NO]);
  54. if (!$goods) {
  55. throw new NotFoundHttpException('商品未找到');
  56. }
  57. $goodsArr['object'] = $goods;
  58. $goodsArr['count'] = $orderGoods->goods_count;
  59. $goodsArr['weight'] = $orderGoods->weight;
  60. if ($goods->is_express && $goods->express_type == Goods::EXPRESS_TYPE_UNIFORM_POSTAGE) {
  61. $uniformPostage[] = $goodsArr;
  62. }
  63. if ($goods->is_express && $goods->express_type == Goods::EXPRESS_TYPE_EXPRESS_TEMPLATE) {
  64. $useTemplate[] = $goodsArr;
  65. }
  66. }
  67. return ['uniformPostageGoods' => $uniformPostage, 'useTemplateGoods' => $useTemplate];
  68. }
  69. /**
  70. * @param $allGoods
  71. * @param $type
  72. * @return float|int
  73. * @throws NotFoundHttpException
  74. */
  75. private function countGoodsExpress($allGoods, $type)
  76. {
  77. if (!$type == Goods::EXPRESS_TYPE_UNIFORM_POSTAGE) {
  78. $amount = 0;
  79. foreach ($allGoods['object'] as $goods) {
  80. $amount = $goods->uniform_postage > $amount ? $goods->uniform_postage : $amount;
  81. }
  82. return $amount;
  83. } else {
  84. $extraPrice = 0;
  85. $areasIds = [];
  86. foreach ($allGoods['object'] as $k => $goods) {
  87. $extraPrice += $this->countExtraAmount($allGoods['count'][$k], $allGoods['weight'][$k], $goods->express_template);
  88. $areasIds[] = $this->getAreaId($goods->express_template);
  89. }
  90. $basic = $this->getBasicPriceAndAreaId($areasIds);
  91. return $basic['price'] + $extraPrice - $this->countSurplusPrice($basic['id']);
  92. }
  93. }
  94. /**
  95. * @param $areaId
  96. * @return float|int
  97. * @throws NotFoundHttpException
  98. * 计算多余(多算的)运费
  99. * 选定的作为基础运费的计费规则的对应商品基础数量内的扩展费用
  100. */
  101. private function countSurplusPrice($areaId)
  102. {
  103. $area = $this->findArea($areaId);
  104. return $area->extra_price * ceil($area->basic_count / $area->extra_count);
  105. }
  106. /**
  107. * @param $areaIds
  108. * @return array
  109. * @throws NotFoundHttpException
  110. * 获取基础运费
  111. */
  112. private function getBasicPriceAndAreaId($areaIds)
  113. {
  114. $basePrice = $id = 0;
  115. foreach ($areaIds as $areasId) {
  116. $area = $this->findArea($areasId);
  117. if (!$area->basic_price > $basePrice) {
  118. continue;
  119. }
  120. $basePrice = $area->basic_price;
  121. $id = $areasId;
  122. }
  123. return ['price' => $basePrice, 'id' => $id];
  124. }
  125. /**
  126. * @param $count
  127. * @param $weight
  128. * @param $templateId
  129. * @return float|int
  130. * @throws NotFoundHttpException
  131. * 计算扩展运费
  132. */
  133. private function countExtraAmount($count, $weight, $templateId)
  134. {
  135. $area = $this->findArea($this->getAreaId($templateId));
  136. $template = $this->findTemplate($templateId);
  137. if ($template->calculation_type == ExpressTemplate::CALCULATION_TYPE_WEIGHT) {
  138. $amount = $area->extra_price * ceil($weight / $area->extra_count);
  139. } else {
  140. $amount = $area->extra_price * ceil($count / $area->extra_count);
  141. }
  142. return $amount;
  143. }
  144. /**
  145. * @param $templateId
  146. * @return int
  147. * @throws NotFoundHttpException
  148. * 根据运费模板和收货地址获取区域
  149. */
  150. private function getAreaId($templateId)
  151. {
  152. $areas = ExpressArea::findALl(['express_template' => $templateId]);
  153. $city = $this->order->city;
  154. foreach ($areas as $area) {
  155. $allCity = explode(',', $area->city);
  156. if (in_array($city, $allCity)) {
  157. return $area->id;
  158. }
  159. }
  160. throw new NotFoundHttpException('超出配送范围(无对应地区运费计算规则)');
  161. }
  162. /**
  163. * @param $areaId
  164. * @return ExpressArea|null
  165. * @throws NotFoundHttpException
  166. * 获取对应区域
  167. */
  168. private function findArea($areaId)
  169. {
  170. $area = ExpressArea::findOne($areaId);
  171. if (!$area) {
  172. throw new NotFoundHttpException('模板地区未找到');
  173. }
  174. return $area;
  175. }
  176. /**
  177. * @param $templateId
  178. * @return ExpressTemplate|null
  179. * @throws NotFoundHttpException
  180. * 获取运费模板
  181. */
  182. private function findTemplate($templateId)
  183. {
  184. $template = ExpressTemplate::findOne($templateId);
  185. if (!$template) {
  186. throw new NotFoundHttpException('运费模板未找到');
  187. }
  188. return $template;
  189. }
  190. }