文件
xionggeshop/addons/shopro/library/regional_agent/Commission.php
可乐加冰 56ac5bb251 ```
refactor(shopro): 移除重复的SplitWalletSettlement引入

移除了addons/shopro/library/regional_agent/Commission.php文件中重复的
SplitWalletSettlement类引入声明,保留唯一的引入语句以避免代码冗余。
```
2026-10-02 13:51:58 +08:00

332 行
10 KiB
PHP

<?php
namespace addons\shopro\library\regional_agent;
use addons\shopro\model\Order as OrderModel;
use addons\shopro\model\User as UserModel;
use addons\shopro\model\regional_agent\Agent as AgentModel;
use addons\shopro\model\regional_agent\Level as LevelModel;
use addons\shopro\model\regional_agent\Order as RegionalOrderModel;
use addons\shopro\model\regional_agent\Reward as RewardModel;
use addons\shopro\library\split\SplitWalletSettlement;
/**
* 区域代理分佣
*/
class Commission
{
protected $_config;
public function __construct()
{
$this->_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');
}
}
}