| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358 |
- <?php
- /**
- * Created by PhpStorm.
- * User: Administrator
- * Date: 2020/8/18
- * Time: 10:58
- */
- namespace app\frontend\modules\dispatch\freight;
- use app\backend\modules\goods\models\Dispatch;
- use app\common\models\goods\GoodsDispatch;
- use app\common\modules\orderGoods\OrderGoodsCollection;
- use app\frontend\models\OrderGoods;
- use app\frontend\modules\order\models\PreOrder;
- use app\frontend\modules\orderGoods\models\PreOrderGoods;
- class TemplateFreight
- {
- protected $code = 'template';
- protected $name = '运费模板';
- /**
- * @var PreOrder
- */
- protected $order;
- /**
- * 金额
- * @var float
- */
- protected $freightAmount;
- /*
- * 排序:数值越低权重越大
- */
- protected $weight;
- /**
- * BaseFreight constructor.
- * @param PreOrder $order
- * @param $weight
- */
- public function __construct(PreOrder $order, $weight = 0)
- {
- $this->order = $order;
- $this->weight = $weight;
- }
- /**
- * 返回运费金额
- * @return float|mixed
- */
- public function getAmount()
- {
- if (!isset($this->freightAmount)) {
- $this->freightAmount = $this->_getAmount();
- }
- return $this->freightAmount;
- }
- public function needDispatch()
- {
- // 虚拟物品不需要配送
- if ($this->order->is_virtual) {
- return false;
- }
- return true;
- }
- protected function _getAmount()
- {
- //去掉重复的OrderGoods
- $uniqueOrderGoods = $this->order->orderGoods->unique('goods_id');
- $dispatch_prices = [];
- $dispatch_ids = $this->getDispatchIds($uniqueOrderGoods);
- trace_log()->freight('订单模板运费模板id', json_encode($dispatch_ids));
- foreach ($dispatch_ids as $dispatch_id) {
- $dispatch_prices[] = $this->getDispatchPrice($dispatch_id, $uniqueOrderGoods);
- }
- return max($dispatch_prices);
- }
- /**
- * 通过订单商品集合 获取所用到的配送模版 ID 集
- *
- * @param $orderGoodsCollection
- * @return array
- */
- private function getDispatchIds(OrderGoodsCollection $orderGoodsCollection)
- {
- $dispatch_ids = [];
- foreach ($orderGoodsCollection as $aOrderGoods) {
- /**
- * @var OrderGoods $aOrderGoods
- */
- $goodsDispatch = $aOrderGoods->goods->hasOneGoodsDispatch;
- if ($goodsDispatch->dispatch_type == GoodsDispatch::TEMPLATE_TYPE) {
- $dispatch_id = $goodsDispatch->dispatch_id;
- if (empty($dispatch_id)) {
- //$goodsDispatch->dispatch_id = $this->getDefaultDispatchId();
- //todo 从order类获取,这样插件订单类好复写
- $goodsDispatch->dispatch_id = $this->order->getPluginDefaultDispatchId();
- }
- if (!in_array($dispatch_id, $dispatch_ids)) {
- $dispatch_ids[] = $goodsDispatch->dispatch_id;
- }
- }
- }
- return $dispatch_ids;
- }
- private function getDefaultDispatchId()
- {
- $defaultDispatch = Dispatch::getOneByDefault();
- //todo 如果没有默认配送模版 如何处理
- trace_log()->freight('订单模板运费','不存在默认的配送模板');
- return $defaultDispatch->id ?: 0;
- }
- private function getDispatchPrice($dispatch_id, $orderGoods)
- {
- $dispatch_good_total = 0;
- $dispatch_good_weight = 0;
- foreach ($orderGoods as $aOrderGoods) {
- /**
- * @var OrderGoods $aOrderGoods
- */
- //商品满额、满件减免运费
- if ($aOrderGoods->isFreeShipping()) {
- trace_log()->freight('订单模板运费','商品'.$aOrderGoods->goods_id.'免运费');
- continue;
- }
- $dispatchModel = $aOrderGoods->goods->hasOneGoodsDispatch;
- //配送模版不存在
- if (!isset($dispatchModel)) {
- trace_log()->freight('订单模板运费','商品'.$aOrderGoods->goods_id.'运费模板不存在');
- continue;
- }
- //如果是默认配送模版
- if (!$dispatchModel->dispatch_id) {
- $dispatchModel->dispatch_id = $this->getDefaultDispatchId();
- }
- if ($dispatchModel->dispatch_type != GoodsDispatch::TEMPLATE_TYPE) {
- trace_log()->freight('订单模板运费','商品'.$aOrderGoods->goods_id.'配送费计算方式不是运费模板');
- continue;
- }
- if ($dispatchModel->dispatch_id != $dispatch_id) {
- trace_log()->freight('订单模板运费','商品'.$aOrderGoods->goods_id.'配送模板('.$dispatchModel->dispatch_id.')不匹配'.$dispatch_id);
- continue;
- }
- $dispatch_good_total += $this->getGoodsTotalInOrder($aOrderGoods);
- $dispatch_good_weight += $this->getGoodsTotalWeightInOrder($aOrderGoods);
- }
- $amount = $this->calculation($dispatch_id, $dispatch_good_total, $dispatch_good_weight);
- trace_log()->freight('订单模板运费','配送费'.$amount.'元');
- return $amount;
- }
- /**
- * 累加订单中每个 同类型不同规格商品 的总数
- * @param PreOrderGoods $orderGoods
- * @return mixed
- */
- private function getGoodsTotalInOrder(PreOrderGoods $orderGoods)
- {
- $result = $orderGoods->order->orderGoods->where('goods_id', $orderGoods->goods_id)->sum(function ($orderGoods) {
- return $orderGoods->total;
- });
- return $result;
- }
- /**
- * 累加订单中每个 同类型不同规格商品 的总重量
- * @param PreOrderGoods $orderGoods
- * @return mixed
- */
- private function getGoodsTotalWeightInOrder(PreOrderGoods $orderGoods)
- {
- $result = $orderGoods->order->orderGoods->where('goods_id', $orderGoods->goods_id)->sum(function ($orderGoods) {
- return $orderGoods->total * $orderGoods->getWeight();
- });
- return $result;
- }
- private function calculation($dispatch_id, $dispatch_good_total, $dispatch_good_weight)
- {
- $price = 0;
- if (!$dispatch_id) {
- trace_log()->freight('订单模板运费','配送模板id'.$dispatch_id.'不存在');
- return $price;
- }
- $dispatchModel = Dispatch::getOne($dispatch_id);
- if (!$dispatch_id) {
- trace_log()->freight('订单模板运费','配送模板id'.$dispatch_id.'不存在');
- return $price;
- }
- switch ($dispatchModel->calculate_type) {
- case 1:
- $price = $this->calculationByPiece($dispatchModel, $dispatch_good_total);
- break;
- case 0:
- $price = $this->calculationByWeight($dispatchModel, $dispatch_good_weight);
- break;
- }
- $price = $this->verify($price);
- return $price;
- }
- private function verify($price)
- {
- if (empty($price)) {
- return 0;
- }
- return $price;
- }
- private function calculationByPiece($dispatchModel, $goods_total)
- {
- if (!$goods_total) {
- return 0;
- }
- $piece_data = unserialize($dispatchModel->piece_data);
- // 存在
- if ($piece_data) {
- $dispatch = '';
- // 根据配送地址匹配区域数据
- $city_id = isset($this->order->orderAddress->city_id) ? $this->order->orderAddress->city_id : 0;
- if (!$city_id) {
- return 0;
- }
- foreach ($piece_data as $key => $piece) {
- $area_ids = explode(';', $piece['area_ids']);
- if (in_array($this->order->orderAddress->city_id, $area_ids)) {
- $dispatch = $piece;
- break;
- }
- }
- if ($dispatch) {
- // 找到匹配的数量数据
- if ($goods_total > $dispatch['first_piece']) {
- $diff = $goods_total - $dispatch['first_piece'];
- $another_piece = $dispatch['another_piece_price'];
- if ($diff > 0) {
- $another_piece = ceil($diff / $dispatch['another_piece']) * $dispatch['another_piece_price'];
- }
- return $dispatch['first_piece_price'] + $another_piece;
- } else {
- return $dispatch['first_piece_price'];
- }
- }
- }
- // 默认件数
- if ($goods_total > $dispatchModel->first_piece) {
- $diff = $goods_total - $dispatchModel->first_piece;
- $another_piece = $dispatchModel->another_piece_price;
- if ($diff > 0) {
- $another_piece = ceil($diff / $dispatchModel->another_piece) * $dispatchModel->another_piece_price;
- }
- return $dispatchModel->first_piece_price + $another_piece;
- } else {
- return $dispatchModel->first_piece_price;
- }
- }
- private function calculationByWeight($dispatchModel, $weight_total)
- {
- if (!$weight_total) {
- return 0;
- }
- $weight_data = unserialize($dispatchModel->weight_data);
- // 存在重量数据
- if ($weight_data) {
- $dispatch = '';
- // 根据配送地址匹配区域数据
- $city_id = isset($this->order->orderAddress->city_id) ? $this->order->orderAddress->city_id : '';
- if (!$city_id) {
- return 0;
- }
- foreach ($weight_data as $key => $weight) {
- //dd($weight['area_ids']);
- $area_ids = explode(';', $weight['area_ids']);
- if (in_array($city_id, $area_ids)) {
- $dispatch = $weight;
- break;
- }
- }
- if ($dispatch) {
- // 找到匹配的重量数据
- if ($weight_total > $dispatch['first_weight']) {
- // 续重: 首重价格+(重量-首重)/续重*续重价格
- // 20 + (500 - 400)
- return $dispatch['first_weight_price'] + ceil(($weight_total - $dispatch['first_weight']) / $dispatch['another_weight']) * $dispatch['another_weight_price'];
- } else {
- return $dispatch['first_weight_price'];
- }
- }
- }
- // 默认全国重量运费
- if ($weight_total > $dispatchModel->first_weight) {
- return $dispatchModel->first_weight_price + ceil(($weight_total - $dispatchModel->first_weight) / $dispatchModel->another_weight) * $dispatchModel->another_weight_price;
- } else {
- return $dispatchModel->first_weight_price;
- }
- }
- }
|