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; } }