文件
mashangyoujiu/Application/Api/Controller/CostCalculationController.class.php

374 行
14 KiB
PHP
可执行文件

<?php
/**
* Created by PhpStorm.
* User: dcy
* Date: 2020/3/23
* Time: 11:43
*/
namespace Api\Controller;
use Common\Model\TemplateAreaModel;
use think\console\input\Argument;
use Think\Controller;
//[1.4.70]
/**
* 门店商品;配送费计算
* Class CostCalculationController
* @package Api\Controller
*/
class CostCalculationController extends Controller
{
/**
* 获取配送费
* @param $goodsData 商品信息 必须包含模板ID(delivery_template_id),商品数量(num)
* @param $store_id 门店ID
* @param $province 用户地址的省
* @param $city 用户地址的市
* @param $area 用户地址的区
* @return mixed
*/
public function getFreight($goodsData, $store_id, $province, $city, $area)
{
//直辖市处理
$direct = array('北京市', '天津市', '上海市', '重庆市');
if (in_array($province, $direct)) {
$province = str_replace('市', '', $province);
}
$goodsData = json_decode($goodsData, true);
//获取模板id
$tempIds = $this->getTempIds($goodsData);
//获取模板对应的区域信息
$TemplateAreaModel = new TemplateAreaModel();
$areaData = $TemplateAreaModel->getTemplateAreas($tempIds);
//获取用户地址省市区对应的区域信息
$userAreaData = D('Citys')->getCityDataByCityName($province, $city, $area);
if (empty($userAreaData)) {
return array(
'status' => 0,
'msg' => '您的收货地址有误',
);
}
//判断出包含用户地址的模板区域信息
$areaDetails = $this->getUserRespeRegion($areaData, $userAreaData);
//组合商品和商品的配送模板信息
$goodAndTemData = $this->comGoodsAndArea($areaDetails, $goodsData);
foreach ($goodAndTemData as $item) {
if (empty($item['areaData'])) {
return array(
'status' => 0,
'msg' => '您的收货地址暂时不在购买的商品支持发货地区范围内',
);
}
}
$comGoodsAndTemData = $this->comGoodsAndTemData($goodAndTemData);//组合运费模板相同的商品
$distributionFee = $this->getDistributionFee($comGoodsAndTemData, $store_id);//获取最终配送费
if ($distributionFee == -1) {
return array(
'status' => 0,
'msg' => '商家未开启快递发货,请退出重试',
'delivery_fee' => $distributionFee,
);
} else {
return array(
'status' => 1,
'msg' => '配送费获取成功',
'delivery_fee' => $distributionFee,
);
}
}
/**
* 获取商品模板id
* @param $goodsData
* @return array
*/
private function getTempIds(&$goodsData)
{
$tempIds = array();
foreach ($goodsData as &$value) {
$tempIds[] = $value['delivery_template_id'];
if (!empty($value['weight_value'])) {
$value['num'] = round($value['num'] * $value['weight_value'], 3);
}
}
return $tempIds;
}
/**
* 返回当前用户地址所属的区域信息
* @param $areaData
* @param $userAreaData
* @return array
*/
private function getUserRespeRegion($areaData, $userAreaData)
{
$areaDetails = array();
foreach ($areaData as $item) {
if (strpos($item['area_id'], $userAreaData[2]['cityid'])) {
$areaDetails[] = $item;
continue;
} elseif (strpos($item['area_id'], $userAreaData[1]['cityid'])) {
$areaDetails[] = $item;
continue;
} elseif (strpos($item['area_id'], $userAreaData[0]['cityid'])) {
$areaDetails[] = $item;
continue;
}
}
return $areaDetails;
}
/**
* 组合商品和配送区域费用问题
* @param $areaDetails
* @param $goodsData
* @return mixed
*/
private function comGoodsAndArea($areaDetails, $goodsData)
{
foreach ($goodsData as &$goods) {
foreach ($areaDetails as $item) {
if ($goods['delivery_template_id'] == $item['template_id']) {
$goods['areaData'] = $item;
break;
}
}
}
return $goodsData;
}
/**
* 获取配送费
* @param $goodsAndTemData
* @param $store_id
* @return int
*/
private function getDistributionFee($goodsAndTemData, $store_id)
{
$storeConfigData = D('StoreConfig')->getStoreTemConfiguration($store_id);
if ($storeConfigData['delivery_template_status'] == 2) {
if ($storeConfigData['template_charging_type'] == 1) {
//累加运费
$distributionFee = $this->cumulativeFreightCalculation($goodsAndTemData);
} else {
//组合运费
$distributionFee = $this->combinedFreightCalculation($goodsAndTemData);
}
return $distributionFee;
} else {
return -1;
}
}
/**
* 累加运费计算
* @param $goodsAndTemData
* @return int
*/
private function cumulativeFreightCalculation($goodsAndTemData)
{
$count = array_count_values(array_column($goodsAndTemData, "delivery_template_id"));
$arrSize = sizeof($goodsAndTemData);
if ($count[$goodsAndTemData[0]['delivery_template_id']] == $arrSize) {//判断商品使用的模板是否相同
foreach ($goodsAndTemData as $item) {
if ($item['areaData']['type'] == 1) { //免运费
$distributionFee = 0;
break;
} elseif ($item['areaData']['type'] == 2 || $item['areaData']['type'] == 3) { //按件数 || 按重量
$totalQuantity = 0; //商品总数量totalQuantity
foreach ($goodsAndTemData as $items) {
$totalQuantity += $items['num'];
}
$firstNum = $item['areaData']['first_num']; //首重
$appendNum = $item['areaData']['append_num']; //续重
$check = ($totalQuantity > $firstNum) ? 1 : 0;
if ($check) {
$merchant = ceil(($totalQuantity - $firstNum) / $appendNum);
$distributionFee = $item['areaData']['first_fee'] + $merchant * $item['areaData']['append_fee'];
break;
} else {
$distributionFee = $item['areaData']['first_fee'];
break;
}
} elseif ($item['areaData']['type'] == 4) {//统一运费
$distributionFee = $item['areaData']['unified_fee'];
break;
}
}
} else {
$freeArr = [];//免运费数组
$numArr = [];//按件数
$weightArr = [];//按重量
$unifiedArr = [];//统一运费
$freeFee = 0;//免运费
$numFee = 0; //按件收费
$weightFee = 0; //按重收费
$maxUnifiedFee = 0; //最大统一运费
foreach ($goodsAndTemData as $goods) {
if ($goods['areaData']['type'] == 1) {
array_push($freeArr, $goods);
} elseif ($goods['areaData']['type'] == 2) {
array_push($numArr, $goods);
} elseif ($goods['areaData']['type'] == 3) {
array_push($weightArr, $goods);
} elseif ($goods['areaData']['type'] == 4) {
array_push($unifiedArr, $goods);
}
}
if (!empty($freeArr)) {
$freeFee = 0;
}
if (!empty($numArr)) {//按件数
foreach ($numArr as $num) {
$merchant = ceil(($num['num'] - $num['areaData']['first_num']) / $num['areaData']['append_num']);
$count = ($num['num'] > $num['areaData']['first_num']) ? 1 : 0;
if ($count) {
$numFee += $num['areaData']['first_fee'] + $merchant * $num['areaData']['append_fee'];
} else {
$numFee += $num['areaData']['first_fee'];
}
}
}
if (!empty($weightArr)) {//按重量
foreach ($weightArr as $weight) {
$merchant = ceil(($weight['num'] - $weight['areaData']['first_num']) / $weight['areaData']['append_num']);
$count = ($weight['num'] > $weight['areaData']['first_num']) ? 1 : 0;
if ($count) {
$weightFee += $weight['areaData']['first_fee'] + $merchant * $weight['areaData']['append_fee'];
} else {
$weightFee += $weight['areaData']['first_fee'];
}
}
}
if (!empty($unifiedArr)) {//统一运费
foreach ($unifiedArr as $unified) {
$maxUnifiedFee = ($maxUnifiedFee > $unified['areaData']['unified_fee']) ? $maxUnifiedFee : $unified['areaData']['unified_fee'];
}
}
$distributionFee = round($freeFee + $numFee + $weightFee + $maxUnifiedFee, 2);
}
return $distributionFee;
}
/**
* 组合运费计算
* @param $goodsAndTemData
* @return int
*/
private function combinedFreightCalculation($goodsAndTemData)
{
$distributionFee = 0;
if (count($goodsAndTemData) == 1) {
//商品使用相同的模板
switch ($goodsAndTemData[0]['areaData']['type']) {
case '1':
//免运费
$distributionFee = 0;
break;
case '2':
case '3':
//2按件数 3按重量
$totalQuantity = $goodsAndTemData[0]['num'];//商品总数量
$firstNum = $goodsAndTemData[0]['areaData']['first_num']; //首重
$appendNum = $goodsAndTemData[0]['areaData']['append_num']; //续重
$append_num = ceil(($totalQuantity - $firstNum) / $appendNum);
$append_num = $append_num > 0 ? $append_num : 0;
$distributionFee = round($goodsAndTemData[0]['areaData']['first_fee'] + $append_num * $goodsAndTemData[0]['areaData']['append_fee'], 2);
break;
case '4':
//统一运费
$distributionFee = $goodsAndTemData[0]['areaData']['unified_fee'];
break;
}
return $distributionFee;
} else {
//多种模板组合
$freeArr = [];//免运费数组
$numArr = [];//按件数 | 按重量
$unifiedArr = [];//统一运费
$comFee = 0; //组合运费
$maxUnifiedFee = 0; //最大统一运费
foreach ($goodsAndTemData as $goods) {
switch ($goods['areaData']['type']) {
case '1':
array_push($freeArr, $goods);
break;
case '2':
case '3':
array_push($numArr, $goods);
break;
case '4':
array_push($unifiedArr, $goods);
break;
}
}
//按件数 | 按重量
if (!empty($numArr)) {
$maxFirstFee = 0;//最大首运费
foreach ($numArr as $num) {
$maxFirstFee = ($maxFirstFee > $num['areaData']['first_fee']) ? $maxFirstFee : $num['areaData']['first_fee'];
}
//根据最大续费获取最大续费当前模板的首件|首重 以及 续件|续重
$maxIdent = 0;//最大的标识
foreach ($numArr as $nums) {
if ($maxFirstFee == $nums['areaData']['first_fee'] && $maxIdent == 0) {
if ($nums['num'] > $nums['areaData']['first_num']) {
$append_num = ceil(($nums['num'] - $nums['areaData']['first_num']) / $nums['areaData']['append_num']);
$append_num = $append_num > 0 ? $append_num : 0;
$comFee += $nums['areaData']['first_fee'] + $append_num * $nums['areaData']['append_fee'];
} else {
$comFee += $nums['areaData']['first_fee'];
}
$maxIdent = 1;
} else {
$append_num = ceil($nums['num'] / $nums['areaData']['append_num']);
$comFee += $append_num * $nums['areaData']['append_fee'];
}
}
$comFee = round($comFee, 2);
}
//统一运费
if (!empty($unifiedArr)) {
foreach ($unifiedArr as $unified) {
$maxUnifiedFee = ($maxUnifiedFee > $unified['areaData']['unified_fee']) ? $maxUnifiedFee : $unified['areaData']['unified_fee'];
}
$maxUnifiedFee = round($maxUnifiedFee, 2);
}
$distributionFee = ($comFee > $maxUnifiedFee) ? $comFee : $maxUnifiedFee;
}
return $distributionFee;
}
/**
* 把配送模板ID相同的数据融合一起
* @param $goodsAndTemData
* @return mixed
*/
private function comGoodsAndTemData($goodsAndTemData)
{
$tempData = array();
$count = count($goodsAndTemData);
for ($i = 0; $i < $count; $i++) {
if (!$goodsAndTemData[$i]['del']) {
for ($j = $i + 1; $j <= $count; $j++) {
if ($goodsAndTemData[$i]['delivery_template_id'] == $goodsAndTemData[$j]['delivery_template_id']) {
$goodsAndTemData[$i]['num'] += $goodsAndTemData[$j]['num'];
$goodsAndTemData[$j]['del'] = 1;
}
}
$tempData[] = $goodsAndTemData[$i];
}
}
return $tempData;
}
}