_config = new Config(); } /** * 订单支付后处理区域代理分佣 */ public function handleOrderPayed($order) { if (!$this->_config->isEnable()) { return false; } if ($order['type'] === 'score' || empty($order['province_id'])) { return false; } $order = OrderModel::with('item')->where('id', $order['id'])->find(); if (!$order || !$order['item']) { return false; } $agents = $this->matchRegionalAgents($order); if (empty($agents)) { return false; } foreach ($order['item'] as $item) { if (!$this->isGoodsRegionalEnabled($item['goods_id'])) { continue; } $this->createRegionalCommissionsForItem($order, $item, $agents); } return true; } /** * 按收货地址匹配省/市/区县代理 */ public function matchRegionalAgents($order) { $matched = []; $areaFields = [ 1 => 'province_id', 2 => 'city_id', 3 => 'area_id', ]; $levels = LevelModel::order('area_level asc')->select(); if (!$levels || count($levels) === 0) { $levels = [ ['area_level' => 1], ['area_level' => 2], ['area_level' => 3], ]; } foreach ($levels as $levelRow) { $areaLevel = intval($levelRow['area_level']); $field = $areaFields[$areaLevel] ?? null; if (!$field) { continue; } $areaId = $order[$field] ?? null; if (empty($areaId)) { continue; } $agent = AgentModel::findByArea($areaId, $areaLevel); if ($agent) { // 校验代理绑定的用户是否存在,防止脏数据导致分佣结算崩溃 $agentUser = UserModel::get($agent['user_id']); if (!$agentUser) { \think\Log::error("[regional_agent] agent id={$agent['id']} user_id={$agent['user_id']} not found in fa_user, skipped"); continue; } $matched[] = [ 'agent' => $agent, 'area_id' => $areaId, 'area_level' => $areaLevel, ]; } } return $matched; } protected function isGoodsRegionalEnabled($goodsId) { $row = \think\Db::name('shopro_commission_goods')->where('goods_id', $goodsId)->find(); if (!$row) { return true; } return boolval($row['regional_enable'] ?? 1); } protected function createRegionalCommissionsForItem($order, $item, $agents) { $amount = floatval($item['pay_price']); if ($amount <= 0) { return false; } $mode = $this->_config->getCommissionMode(); if ($mode === 'exclusive') { $agents = $this->filterExclusiveAgents($agents); } if (empty($agents)) { return false; } $commissionMap = $this->calculateCommissionMap($agents, $amount, $mode); foreach ($agents as $agentData) { $agent = $agentData['agent']; $commission = $commissionMap[$agent['id']] ?? 0; if ($commission <= 0) { continue; } $this->persistRegionalCommission($order, $item, $agentData, $amount, $commission); } return true; } protected function filterExclusiveAgents($agents) { if (empty($agents)) { return []; } usort($agents, function ($a, $b) { return $b['area_level'] - $a['area_level']; }); return [$agents[0]]; } protected function calculateCommissionMap($agents, $amount, $mode) { $map = []; $levelRows = []; foreach ($agents as $agentData) { $level = LevelModel::get($agentData['agent']['level']); if (!$level) { continue; } $effective = $this->resolveEffectiveCommission($agentData['agent'], $level); $levelRows[] = [ 'agent_id' => $agentData['agent']['id'], 'area_level' => $agentData['area_level'], 'commission' => $effective, ]; } if (empty($levelRows)) { return $map; } if ($mode === 'differential') { return $this->calculateDifferentialMap($levelRows, $amount); } foreach ($levelRows as $row) { $map[$row['agent_id']] = $this->calculateFullCommission($row['commission'], $amount); } return $map; } protected function calculateDifferentialMap($levelRows, $amount) { $types = []; foreach ($levelRows as $row) { $types[$row['commission']['commission_type']] = true; } if (count($types) !== 1) { $map = []; foreach ($levelRows as $row) { $map[$row['agent_id']] = $this->calculateFullCommission($row['commission'], $amount); } return $map; } usort($levelRows, function ($a, $b) { return $a['area_level'] - $b['area_level']; }); $map = []; $prevValue = 0; $type = key($types); foreach ($levelRows as $row) { $commission = $row['commission']; if ($type === 'rate') { $current = floatval($commission['commission_rate']); $effective = max(0, $current - $prevValue); $map[$row['agent_id']] = round($amount * $effective * 0.01, 2); $prevValue = $current; } else { $current = floatval($commission['commission_money']); $effective = max(0, $current - $prevValue); $map[$row['agent_id']] = round($effective, 2); $prevValue = $current; } } return $map; } /** * 单个代理有自定义佣金时优先,否则跟随等级通用配置 */ protected function resolveEffectiveCommission($agent, $level) { $type = $agent['commission_type'] ?? null; if (!empty($type)) { return [ 'commission_type' => $type, 'commission_rate' => floatval($agent['commission_rate'] ?? 0), 'commission_money' => floatval($agent['commission_money'] ?? 0), ]; } return [ 'commission_type' => $level['commission_type'], 'commission_rate' => floatval($level['commission_rate']), 'commission_money' => floatval($level['commission_money']), ]; } protected function calculateFullCommission($commission, $amount) { if ($commission['commission_type'] === 'rate') { return round($amount * floatval($commission['commission_rate']) * 0.01, 2); } return round(floatval($commission['commission_money']), 2); } protected function persistRegionalCommission($order, $item, $agentData, $amount, $commission) { $agent = $agentData['agent']; $exists = RegionalOrderModel::where('order_item_id', $item['id']) ->where('agent_id', $agent['id']) ->find(); if ($exists) { return $exists; } $regionalOrder = RegionalOrderModel::create([ 'order_id' => $order['id'], 'order_item_id' => $item['id'], 'buyer_id' => $order['user_id'], 'agent_id' => $agent['id'], 'agent_user_id' => $agent['user_id'], 'area_id' => $agentData['area_id'], 'area_level' => $agentData['area_level'], 'amount' => $amount, 'commission_event' => $this->_config->getCommissionEvent(), 'commission_reward_status' => 0, ]); RewardModel::create([ 'order_id' => $order['id'], 'order_item_id' => $item['id'], 'buyer_id' => $order['user_id'], 'regional_order_id' => $regionalOrder->id, 'agent_id' => $agent['id'], 'agent_user_id' => $agent['user_id'], 'type' => 'money', 'commission' => $commission, 'original_commission' => $commission, 'status' => 0, ]); $agent->setInc('order_money', $amount); $agent->setInc('order_count', 1); if ($this->_config->getCommissionEvent() === 'payed') { if (!SplitWalletSettlement::shouldDeferRegionalWallet($order, 'payed')) { (new Reward())->settleByRegionalOrder($regionalOrder->id, 'payed'); } } return $regionalOrder; } /** * 订单确认收货/完成时结算 */ public function settleByEvent($event, $orderItemId) { $regionalOrders = RegionalOrderModel::where('order_item_id', $orderItemId) ->where('commission_reward_status', 0) ->select(); $rewardLib = new Reward(); foreach ($regionalOrders as $regionalOrder) { if ($regionalOrder['commission_event'] === $event) { $rewardLib->settleByRegionalOrder($regionalOrder->id, $event); } } } /** * 退款退回区域代理佣金 */ public function refundByOrderItem($orderItemId) { $regionalOrders = RegionalOrderModel::where('order_item_id', $orderItemId)->select(); $rewardLib = new Reward(); foreach ($regionalOrders as $regionalOrder) { $rewardLib->backByRegionalOrder($regionalOrder->id, 'refund'); } } }