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.
 
 
 

222 lines
7.6 KiB

<?php
namespace api\logic;
use backend\modules\goods\models\ars\Goods;
use backend\modules\shop\models\ars\ExpressArea;
use backend\modules\shop\models\ars\ExpressTemplate;
use backend\modules\shop\models\ars\Order;
use backend\modules\shop\models\ars\OrderGoods;
use yii\base\BaseObject;
use yii\web\NotFoundHttpException;
/**
* @author iron
* @email weiriron@gmail.com
* @package api\logic
*/
class ExpressLogic extends BaseObject
{
/**
* @var Order
* 订单
*/
public $order;
/**
* @param $order
* @return float|int
* @throws NotFoundHttpException
* 计算运费
*/
public function countShippingAmount($order)
{
$this->order = $order;
$allGoods = $this->findDifferentExpressTypeGoods();/*获取不同运费计算模式的商品*/
$uniformPostage = $this->countGoodsExpress($allGoods['uniformPostageGoods'], Goods::EXPRESS_TYPE_UNIFORM_POSTAGE);/*计算统一运费模式下所有商品运费*/
$expressTemplate = $this->countGoodsExpress($allGoods['useTemplateGoods'], Goods::EXPRESS_TYPE_EXPRESS_TEMPLATE);/*计算运费模板模式下所有商品的运费*/
$amount = $uniformPostage > $expressTemplate ? $uniformPostage : $expressTemplate;/*比较两种不同运费计算模式下,取金额大的值为最终收取运费*/
return $amount / 100; /*将金额单位[分]转化为[元]*/
}
/*--------------------------------------------------------------------------------------*/
/**
* @return array
* @throws NotFoundHttpException
* 获取不同运费计算模式的商品
*/
private function findDifferentExpressTypeGoods()
{
$uniformPostage = $useTemplate = [];
$allGoods = OrderGoods::findAll(['order_id' => $this->order->id]);
foreach ($allGoods as $orderGoods) {
$goods = Goods::findOne(['id' => $orderGoods->goods_id, 'is_sale' => Goods::IS_SALE_YES, 'is_delete' => Goods::IS_DELETE_NO]);
if (!$goods) {
throw new NotFoundHttpException('商品未找到');
}
$goodsArr['object'] = $goods;
$goodsArr['count'] = $orderGoods->goods_count;
$goodsArr['weight'] = $orderGoods->weight;
if ($goods->is_express && $goods->express_type == Goods::EXPRESS_TYPE_UNIFORM_POSTAGE) {
$uniformPostage[] = $goodsArr;
}
if ($goods->is_express && $goods->express_type == Goods::EXPRESS_TYPE_EXPRESS_TEMPLATE) {
$useTemplate[] = $goodsArr;
}
}
return ['uniformPostageGoods' => $uniformPostage, 'useTemplateGoods' => $useTemplate];
}
/**
* @param $allGoods
* @param $type
* @return float|int
* @throws NotFoundHttpException
* 根据不同计费模式计算商品运费
*/
private function countGoodsExpress($allGoods, $type)
{
if ($type == Goods::EXPRESS_TYPE_UNIFORM_POSTAGE) {
$amount = 0;
foreach ($allGoods as $goods) {
$amount = $goods['object']->uniform_postage > $amount ? $goods['object']->uniform_postage : $amount;
}
return $amount;
} else {
$extraPrice = 0;
$areasIds = $basicGoods = [];
foreach ($allGoods as $goods) {
$areasIds[] = $this->getAreaId($goods['object']->express_template);/*获取所有配送区域的id*/
}
$basicId = $this->getBasicAreaId($areasIds);/*获取首重运费和对应的计费规则id*/
foreach ($allGoods as $k => $goods) {
$res = $this->countExtraAmount($goods, $basicId);/*判断商品绑定的是否为基础模板并计算非基础模板商品的增重运费*/
if (is_bool($res) && $res === true) {
$basicGoods[] = $allGoods[$k];
continue;
}
$extraPrice += $res;
}
$basicPrice = $this->countBasicPrice($basicGoods, $basicId);/*计算基础模板商品的运费*/
return $extraPrice + $basicPrice;
}
}
/**
* @param $allGoods
* @param $areaId
* @return float|int
* @throws NotFoundHttpException
* 计算基础模板商品的运费价格
*/
private function countBasicPrice($allGoods, $areaId)
{
$area = $this->findArea($areaId);
$count = $weight = 0;
$template = $this->findTemplate($area->express_template);
foreach ($allGoods as $goods) {
$count += $goods['count'];
$weight += $goods['weight'];
}
if ($template->calculation_type == ExpressTemplate::CALCULATION_TYPE_WEIGHT) {
$amount = $weight - $area->basic_count > 0 ? $weight - $area->basic_count : 0;
} else {
$amount = $weight - $area->basic_count > 0 ? $weight - $area->basic_count : 0;
}
return $area->basic_price + $area->extra_price * ceil($amount / $area->extra_count);
}
/**
* @param $areaIds
* @return int
* @throws NotFoundHttpException
* 获取基础运费的区域id
*/
private function getBasicAreaId($areaIds)
{
$basePrice = $id = 0;
foreach ($areaIds as $areasId) {
$area = $this->findArea($areasId);
if ($area->basic_price < $basePrice) {
continue;
}
$basePrice = $area->basic_price;
$id = $areasId;
}
return $id;
}
/**
* @param $goods
* @param $areaId
* @return bool|int
* @throws NotFoundHttpException
* 计算非使用基础运费模板的商品按增重运费计算运费
*/
private function countExtraAmount($goods, $areaId)
{
$count = $goods['count'];
$weight = $goods['weight'];
$area = $this->findArea($this->getAreaId($goods['object']->express_template));
$template = $this->findTemplate($goods['object']->express_template);
if ($area->id == $areaId) {
return true;
}
if ($template->calculation_type == ExpressTemplate::CALCULATION_TYPE_WEIGHT) {
$amount = $weight;
} else {
$amount = $count;
}
return $area->extra_price * ceil($amount / $area->extra_count);
}
/**
* @param $templateId
* @return int
* @throws NotFoundHttpException
* 根据收货地址获取配送区域id
*/
private function getAreaId($templateId)
{
$city = $this->order->city;
$areas = ExpressArea::findALl(['express_template' => $templateId]);
foreach ($areas as $area) {
$allCity = explode(',', $area->city);
if (in_array($city, $allCity)) {
return $area->id;
}
}
throw new NotFoundHttpException('超出配送范围(未找到对应地区运费计算规则)');
}
/**
* @param $areaId
* @return ExpressArea|null
* @throws NotFoundHttpException
* 获取对应区域
*/
private function findArea($areaId)
{
$area = ExpressArea::findOne($areaId);
if (!$area) {
throw new NotFoundHttpException('模板地区未找到');
}
return $area;
}
/**
* @param $templateId
* @return ExpressTemplate|null
* @throws NotFoundHttpException
* 获取运费模板
*/
private function findTemplate($templateId)
{
$template = ExpressTemplate::findOne($templateId);
if (!$template) {
throw new NotFoundHttpException('运费模板未找到');
}
return $template;
}
}