OrderFreight.php 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. <?php
  2. /**
  3. * Created by PhpStorm.
  4. * User: blank
  5. * Date: 2022/4/12
  6. * Time: 9:36
  7. */
  8. namespace app\frontend\modules\dispatch\models;
  9. use app\framework\Database\Eloquent\Collection;
  10. use app\frontend\models\order\PreOrderDeduction;
  11. use app\frontend\modules\dispatch\deduction\BaseFreightDeduction;
  12. use app\frontend\modules\dispatch\deduction\CoinFreightDeduction;
  13. use app\frontend\modules\dispatch\deduction\OrderFreightDeductManager;
  14. use app\frontend\modules\dispatch\discount\BaseFreightDiscount;
  15. use app\frontend\modules\dispatch\freight\BaseFreight;
  16. use app\frontend\modules\dispatch\freight\pipes\OrderDeductionFreightPricePipe;
  17. use app\frontend\modules\dispatch\freight\pipes\OrderFreightDeductionPricePipe;
  18. use app\frontend\modules\dispatch\freight\pipes\OrderFreightDiscountPricePipe;
  19. use app\frontend\modules\dispatch\freight\pipes\OrderInitialFreightPricePipe;
  20. use app\frontend\modules\order\models\PreOrder;
  21. use app\frontend\modules\order\PriceNode;
  22. use app\frontend\modules\order\PriceNodeTrait;
  23. class OrderFreight
  24. {
  25. use PriceNodeTrait;
  26. /**
  27. * @var BaseFreight
  28. */
  29. public $priceCalculation;
  30. /**
  31. * @var PreOrder
  32. */
  33. protected $order;
  34. /**
  35. * @var Collection
  36. */
  37. protected $freightPrices;
  38. /**
  39. * @var float
  40. */
  41. protected $initialAmount;
  42. protected $discountWeight = 0;
  43. protected static $deductionWeight = 0;
  44. public function __construct(PreOrder $order)
  45. {
  46. $this->order = $order;
  47. // 订单运费抵扣集合
  48. $this->order->setRelation('orderFreightDeduction', new Collection());
  49. }
  50. public function getOrder()
  51. {
  52. return $this->order;
  53. }
  54. public function orderFreightDeduction()
  55. {
  56. return $this->order->orderFreightDeduction;
  57. }
  58. public function pushDeductionPricePipe(PreOrderDeduction $freightDeduction)
  59. {
  60. if (!$this->verifyPriceNodes($freightDeduction->getCode().'Deduction')) {
  61. // self::$deductionWeight++;
  62. $priceNode = new OrderFreightDeductionPricePipe($this, new CoinFreightDeduction($this->order, $freightDeduction), 5000 + self::$deductionWeight);
  63. $this->getPriceNodes()->push($priceNode);
  64. }
  65. }
  66. /**
  67. * @return mixed
  68. * @throws \app\common\exceptions\AppException
  69. */
  70. public function _getPriceNodes()
  71. {
  72. // 订单节点
  73. $nodes = collect([
  74. new OrderInitialFreightPricePipe($this, 1000)
  75. ]);
  76. //订单运费优惠节点
  77. $discountNodes = $this->getDiscounts()->map(function (BaseFreightDiscount $discount) {
  78. $this->discountWeight += 1;
  79. return new OrderFreightDiscountPricePipe($this, $discount, 2000 + $this->discountWeight);
  80. });
  81. // 按照weight排序
  82. $nodes = $nodes->merge($discountNodes)->sortBy(function (PriceNode $priceNode) {
  83. return $priceNode->getWeight();
  84. })->values();
  85. return $nodes;
  86. }
  87. public function getDeductions()
  88. {
  89. return (new OrderFreightDeductManager($this->order))->getOrderFreightDeductions();
  90. }
  91. /**
  92. * @return \Illuminate\Support\Collection
  93. */
  94. public function getDiscounts()
  95. {
  96. $discounts = collect([]);
  97. $configs = \app\common\modules\shop\ShopConfig::current()->get('shop-foundation.order-freight-discount');
  98. $discountGroup = collect($configs)->groupBy('type');
  99. foreach ($discountGroup as $group) {
  100. $discount_items = $group->sortByDesc('priority');
  101. foreach ($discount_items as $item) {
  102. /**
  103. * @var BaseFreightDiscount $discountClass
  104. */
  105. $discountClass = call_user_func($item['class'], $this->order);
  106. if ($discountClass->validate()) {
  107. $discounts->push($discountClass);
  108. break;
  109. }
  110. }
  111. }
  112. return $discounts;
  113. }
  114. /**
  115. * 订单初始运费金额
  116. */
  117. public function getInitialFreightAmount()
  118. {
  119. if (!isset($this->initialAmount)) {
  120. if (is_null($this->order->getOrderDispatchType()) || !$this->order->getOrderDispatchType()->needFreight()) {
  121. // 没选配送方式 或者 不需要配送不需要运费
  122. return $this->initialAmount = 0;
  123. }
  124. $this->initialAmount = $this->getPriceCalculation()->getAmount();
  125. $fullAmountFreeFreight = (new \app\frontend\modules\dispatch\models\fullAmountFreeFreight($this->order))->getAmount();
  126. $this->initialAmount = max($this->initialAmount - $fullAmountFreeFreight, 0);
  127. }
  128. return $this->initialAmount;
  129. }
  130. /**
  131. * 订单最终运费金额
  132. */
  133. public function getFinalFreightAmount()
  134. {
  135. return max($this->getPriceAfter($this->getPriceNodes()->last()->getKey()), 0);
  136. }
  137. public function getPriceCalculation()
  138. {
  139. if (!isset($this->priceCalculation)) {
  140. $this->priceCalculation = $this->getFreightClass();
  141. }
  142. return $this->priceCalculation;
  143. }
  144. public function getFreightClass()
  145. {
  146. $freightPrice = $this->getFreightPrices()->first(function ($freightPrice) {
  147. return $freightPrice->getGroup() == 'third_party';
  148. });
  149. if (!$freightPrice) {
  150. $freightPrice = $this->getFreightPrices()->first();
  151. }
  152. return $freightPrice;
  153. }
  154. public function getFreightPrices()
  155. {
  156. if (!isset($this->freightNodes)) {
  157. $this->freightPrices = $this->_getFreightPrices();
  158. }
  159. return $this->freightPrices;
  160. }
  161. //订单运费集合
  162. public function _getFreightPrices()
  163. {
  164. // 订单运费集合
  165. $freightPrices = collect();
  166. $freightConfig = \app\common\modules\shop\ShopConfig::current()->get('shop-foundation.order-freight');
  167. foreach ($freightConfig as $configItem) {
  168. $freightPrices->push(call_user_func($configItem['class'], $this->order, $configItem['weight']));
  169. }
  170. $freightPrices = $freightPrices->filter(function(BaseFreight $freightPrice) {
  171. //过滤不能使用的运费计算方式
  172. return $freightPrice->needDispatch();
  173. })->sortBy(function (BaseFreight $freightPrice) {
  174. // 按照weight排序
  175. return $freightPrice->getWeight();
  176. })->values();
  177. return $freightPrices;
  178. }
  179. }