bztang-admin/app/frontend/modules/dispatch/models/OrderFreight.php

239 lines
6.5 KiB
PHP

<?php
/**
* Created by PhpStorm.
* User: blank
* Date: 2022/4/12
* Time: 9:36
*/
namespace app\frontend\modules\dispatch\models;
use app\framework\Database\Eloquent\Collection;
use app\frontend\models\order\PreOrderDeduction;
use app\frontend\modules\dispatch\deduction\BaseFreightDeduction;
use app\frontend\modules\dispatch\deduction\CoinFreightDeduction;
use app\frontend\modules\dispatch\deduction\OrderFreightDeductManager;
use app\frontend\modules\dispatch\discount\BaseFreightDiscount;
use app\frontend\modules\dispatch\freight\BaseFreight;
use app\frontend\modules\dispatch\freight\pipes\OrderDeductionFreightPricePipe;
use app\frontend\modules\dispatch\freight\pipes\OrderFreightDeductionPricePipe;
use app\frontend\modules\dispatch\freight\pipes\OrderFreightDiscountPricePipe;
use app\frontend\modules\dispatch\freight\pipes\OrderInitialFreightPricePipe;
use app\frontend\modules\order\models\PreOrder;
use app\frontend\modules\order\PriceNode;
use app\frontend\modules\order\PriceNodeTrait;
class OrderFreight
{
use PriceNodeTrait;
/**
* @var BaseFreight
*/
public $priceCalculation;
/**
* @var PreOrder
*/
protected $order;
/**
* @var Collection
*/
protected $freightPrices;
/**
* @var float
*/
protected $initialAmount;
protected $discountWeight = 0;
protected static $deductionWeight = 0;
public function __construct(PreOrder $order)
{
$this->order = $order;
// 订单运费抵扣集合
$this->order->setRelation('orderFreightDeduction', new Collection());
}
public function getOrder()
{
return $this->order;
}
public function orderFreightDeduction()
{
return $this->order->orderFreightDeduction;
}
public function pushDeductionPricePipe(PreOrderDeduction $freightDeduction)
{
if (!$this->verifyPriceNodes($freightDeduction->getCode().'Deduction')) {
// self::$deductionWeight++;
$priceNode = new OrderFreightDeductionPricePipe($this, new CoinFreightDeduction($this->order, $freightDeduction), 5000 + self::$deductionWeight);
$this->getPriceNodes()->push($priceNode);
}
}
/**
* @return mixed
* @throws \app\common\exceptions\AppException
*/
public function _getPriceNodes()
{
// 订单节点
$nodes = collect([
new OrderInitialFreightPricePipe($this, 1000)
]);
//订单运费优惠节点
$discountNodes = $this->getDiscounts()->map(function (BaseFreightDiscount $discount) {
$this->discountWeight += 1;
return new OrderFreightDiscountPricePipe($this, $discount, 2000 + $this->discountWeight);
});
// 按照weight排序
$nodes = $nodes->merge($discountNodes)->sortBy(function (PriceNode $priceNode) {
return $priceNode->getWeight();
})->values();
return $nodes;
}
public function getDeductions()
{
return (new OrderFreightDeductManager($this->order))->getOrderFreightDeductions();
}
/**
* @return \Illuminate\Support\Collection
*/
public function getDiscounts()
{
$discounts = collect([]);
$configs = \app\common\modules\shop\ShopConfig::current()->get('shop-foundation.order-freight-discount');
$discountGroup = collect($configs)->groupBy('type');
foreach ($discountGroup as $group) {
$discount_items = $group->sortByDesc('priority');
foreach ($discount_items as $item) {
/**
* @var BaseFreightDiscount $discountClass
*/
$discountClass = call_user_func($item['class'], $this->order);
if ($discountClass->validate()) {
$discounts->push($discountClass);
break;
}
}
}
return $discounts;
}
/**
* 订单初始运费金额
*/
public function getInitialFreightAmount()
{
if (!isset($this->initialAmount)) {
if (is_null($this->order->getOrderDispatchType()) || !$this->order->getOrderDispatchType()->needFreight()) {
// 没选配送方式 或者 不需要配送不需要运费
return $this->initialAmount = 0;
}
if (is_null($this->getPriceCalculation())) {
return $this->initialAmount = 0;
}
$this->initialAmount = $this->getPriceCalculation()->getAmount();
$fullAmountFreeFreight = (new \app\frontend\modules\dispatch\models\fullAmountFreeFreight($this->order))->getAmount();
$this->initialAmount = max($this->initialAmount - $fullAmountFreeFreight, 0);
}
return $this->initialAmount;
}
/**
* 订单最终运费金额
*/
public function getFinalFreightAmount()
{
return max($this->getPriceAfter($this->getPriceNodes()->last()->getKey()), 0);
}
public function getPriceCalculation()
{
if (!isset($this->priceCalculation)) {
$this->priceCalculation = $this->getFreightClass();
}
return $this->priceCalculation;
}
public function getFreightClass()
{
$freightPrice = $this->getFreightPrices()->first(function ($freightPrice) {
return $freightPrice->getGroup() == 'third_party';
});
if (!$freightPrice) {
$freightPrice = $this->getFreightPrices()->first();
}
return $freightPrice;
}
public function getFreightPrices()
{
if (!isset($this->freightNodes)) {
$this->freightPrices = $this->_getFreightPrices();
}
return $this->freightPrices;
}
//订单运费集合
public function _getFreightPrices()
{
// 订单运费集合
$freightPrices = collect();
$freightConfig = \app\common\modules\shop\ShopConfig::current()->get('shop-foundation.order-freight');
foreach ($freightConfig as $configItem) {
$freightPrices->push(call_user_func($configItem['class'], $this->order, $configItem['weight']));
}
$freightPrices = $freightPrices->filter(function(BaseFreight $freightPrice) {
//过滤不能使用的运费计算方式
return $freightPrice->needDispatch();
})->sortBy(function (BaseFreight $freightPrice) {
// 按照weight排序
return $freightPrice->getWeight();
})->values();
return $freightPrices;
}
}