|
@@ -0,0 +1,205 @@
|
|
|
+<?php
|
|
|
+
|
|
|
+namespace app\common\Service\commission;
|
|
|
+
|
|
|
+use app\common\model\commission\Agent as AgentModel;
|
|
|
+use app\common\model\commission\Reward as RewardModel;
|
|
|
+use app\common\model\commission\Log as LogModel;
|
|
|
+use app\common\model\User as UserModel;
|
|
|
+use think\Db;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 区域代理商分佣服务
|
|
|
+ */
|
|
|
+class RegionalCommission
|
|
|
+{
|
|
|
+ protected $commissionOrder;
|
|
|
+ protected $orderUser;
|
|
|
+ protected $goods;
|
|
|
+ protected $config;
|
|
|
+
|
|
|
+ public function __construct($commissionOrder, $goods, $config)
|
|
|
+ {
|
|
|
+ $this->commissionOrder = $commissionOrder;
|
|
|
+ $this->goods = $goods;
|
|
|
+ $this->config = $config;
|
|
|
+
|
|
|
+ // 获取下单用户信息
|
|
|
+ $this->orderUser = UserModel::where('id', $commissionOrder->buyer_id)->find();
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 执行区域代理商分佣
|
|
|
+ */
|
|
|
+ public function executeRegionalCommission()
|
|
|
+ {
|
|
|
+ if (!$this->orderUser) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取下单用户的地区信息
|
|
|
+ $userArea = $this->getUserArea();
|
|
|
+ if (!$userArea) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 查找管辖该区域的区域代理商
|
|
|
+ $regionalAgents = $this->getRegionalAgents($userArea);
|
|
|
+
|
|
|
+ foreach ($regionalAgents as $agent) {
|
|
|
+ $this->processRegionalAgent($agent, $userArea);
|
|
|
+ }
|
|
|
+
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取用户地区信息
|
|
|
+ */
|
|
|
+ protected function getUserArea()
|
|
|
+ {
|
|
|
+ // 假设用户表有地区字段,或者从用户地址中获取
|
|
|
+ // 这里需要根据实际业务逻辑调整
|
|
|
+ return [
|
|
|
+ 'province_id' => $this->orderUser->province_id ?? 0,
|
|
|
+ 'city_id' => $this->orderUser->city_id ?? 0,
|
|
|
+ 'district_id' => $this->orderUser->district_id ?? 0
|
|
|
+ ];
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取管辖该区域的区域代理商
|
|
|
+ */
|
|
|
+ protected function getRegionalAgents($userArea)
|
|
|
+ {
|
|
|
+ $agents = [];
|
|
|
+
|
|
|
+ // 查找区域代理商:按管辖范围从小到大查找(区 -> 市 -> 省)
|
|
|
+
|
|
|
+ // 1. 查找管辖该区的代理商
|
|
|
+ if ($userArea['district_id'] > 0) {
|
|
|
+ $districtAgents = AgentModel::where('agent_type', 'regional')
|
|
|
+ ->where('manage_district_id', $userArea['district_id'])
|
|
|
+ ->where('status', AgentModel::AGENT_STATUS_NORMAL)
|
|
|
+ ->with(['identity'])
|
|
|
+ ->select();
|
|
|
+ $agents = array_merge($agents, $districtAgents->toArray());
|
|
|
+ }
|
|
|
+
|
|
|
+ // 2. 查找管辖该市的代理商(如果还没有区级代理商)
|
|
|
+ if ($userArea['city_id'] > 0) {
|
|
|
+ $cityAgents = AgentModel::where('agent_type', 'regional')
|
|
|
+ ->where('manage_city_id', $userArea['city_id'])
|
|
|
+ ->where('manage_district_id', 0) // 市级代理商不管具体区
|
|
|
+ ->where('status', AgentModel::AGENT_STATUS_NORMAL)
|
|
|
+ ->with(['identity'])
|
|
|
+ ->select();
|
|
|
+ $agents = array_merge($agents, $cityAgents->toArray());
|
|
|
+ }
|
|
|
+
|
|
|
+ // 3. 查找管辖该省的代理商(如果还没有市级代理商)
|
|
|
+ if ($userArea['province_id'] > 0) {
|
|
|
+ $provinceAgents = AgentModel::where('agent_type', 'regional')
|
|
|
+ ->where('manage_province_id', $userArea['province_id'])
|
|
|
+ ->where('manage_city_id', 0)
|
|
|
+ ->where('manage_district_id', 0)
|
|
|
+ ->where('status', AgentModel::AGENT_STATUS_NORMAL)
|
|
|
+ ->with(['identity'])
|
|
|
+ ->select();
|
|
|
+ $agents = array_merge($agents, $provinceAgents->toArray());
|
|
|
+ }
|
|
|
+
|
|
|
+ return $agents;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 处理单个区域代理商分佣
|
|
|
+ */
|
|
|
+ protected function processRegionalAgent($agent, $userArea)
|
|
|
+ {
|
|
|
+ // 防止重复分佣
|
|
|
+ $existingReward = RewardModel::where([
|
|
|
+ 'commission_order_id' => $this->commissionOrder->id,
|
|
|
+ 'agent_id' => $agent['user_id'],
|
|
|
+ 'reward_type' => 'regional'
|
|
|
+ ])->find();
|
|
|
+
|
|
|
+ if ($existingReward) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取区域分佣比例
|
|
|
+ $commissionRate = $agent['identity']['regional_commission_rate'] ?? 0;
|
|
|
+ if ($commissionRate <= 0) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 计算佣金
|
|
|
+ $commission = round($this->commissionOrder->amount * $commissionRate / 100, 2);
|
|
|
+ if ($commission <= 0) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 创建区域分佣记录
|
|
|
+ $rewardData = [
|
|
|
+ 'order_id' => $this->commissionOrder->order_id,
|
|
|
+ 'order_item_id' => $this->commissionOrder->order_item_id,
|
|
|
+ 'buyer_id' => $this->commissionOrder->buyer_id,
|
|
|
+ 'commission_order_id' => $this->commissionOrder->id,
|
|
|
+ 'agent_id' => $agent['user_id'],
|
|
|
+ 'type' => 'commission',
|
|
|
+ 'reward_type' => 'regional', // 区域分佣标识
|
|
|
+ 'commission' => $commission,
|
|
|
+ 'original_commission' => $commission,
|
|
|
+ 'commission_level' => 0, // 区域分佣不按层级
|
|
|
+ 'agent_level' => $agent['level'],
|
|
|
+ 'commission_rules' => json_encode([
|
|
|
+ 'type' => 'regional',
|
|
|
+ 'rate' => $commissionRate,
|
|
|
+ 'area' => $userArea,
|
|
|
+ 'agent_area' => [
|
|
|
+ 'province' => $agent['manage_province_id'],
|
|
|
+ 'city' => $agent['manage_city_id'],
|
|
|
+ 'district' => $agent['manage_district_id']
|
|
|
+ ]
|
|
|
+ ]),
|
|
|
+ 'status' => 0 // 待入账
|
|
|
+ ];
|
|
|
+
|
|
|
+ $reward = RewardModel::create($rewardData);
|
|
|
+
|
|
|
+ // 记录日志
|
|
|
+ LogModel::add($agent['user_id'], 'reward', [
|
|
|
+ 'type' => 'regional_commission',
|
|
|
+ 'reward' => $reward,
|
|
|
+ 'area' => $userArea
|
|
|
+ ], $this->orderUser);
|
|
|
+
|
|
|
+ return $reward;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 检查区域冲突 - 确保同一区域只有一个代理商获得分佣
|
|
|
+ */
|
|
|
+ protected function checkAreaConflict($agents, $userArea)
|
|
|
+ {
|
|
|
+ // 按管辖范围精确度排序:区 > 市 > 省
|
|
|
+ usort($agents, function($a, $b) {
|
|
|
+ $aScore = 0;
|
|
|
+ $bScore = 0;
|
|
|
+
|
|
|
+ if ($a['manage_district_id'] > 0) $aScore = 3;
|
|
|
+ elseif ($a['manage_city_id'] > 0) $aScore = 2;
|
|
|
+ elseif ($a['manage_province_id'] > 0) $aScore = 1;
|
|
|
+
|
|
|
+ if ($b['manage_district_id'] > 0) $bScore = 3;
|
|
|
+ elseif ($b['manage_city_id'] > 0) $bScore = 2;
|
|
|
+ elseif ($b['manage_province_id'] > 0) $bScore = 1;
|
|
|
+
|
|
|
+ return $bScore - $aScore; // 降序,精确度高的优先
|
|
|
+ });
|
|
|
+
|
|
|
+ // 只返回最精确的代理商
|
|
|
+ return array_slice($agents, 0, 1);
|
|
|
+ }
|
|
|
+}
|