Commit af50af65 authored by 刘小敏's avatar 刘小敏

feat(commission): 新增分销商申请与佣金结算功能

parent fb5e2c61
......@@ -77,7 +77,7 @@ class Agent extends Commission
$this->success("", $config);
}
// 申请分销商/完善资料
// 申请分销商
public function apply()
{
if (!$this->request->isPost()) {
......@@ -86,6 +86,79 @@ class Agent extends Commission
if (!$this->service->config->isAgentApplyForm()) {
$this->error('未开启分销商申请');
}
// 校验消费累计条件
/** @var array $becomeAgentEvent */
$becomeAgentEvent = $this->service->config->getBecomeAgentEvent();
if ($becomeAgentEvent['type'] === 'consume') {
$requiredConsume = $becomeAgentEvent['value'] ?? 0;
$userConsume = floatval($this->service->user->total_consume ?? 0);
if ($userConsume < $requiredConsume) {
$this->error('累计消费未达到申请要求,当前累计消费 ¥' . $userConsume . ',需达到 ¥' . $requiredConsume);
}
}
$status = $this->service->getAgentStatus(true);
// 不同状态返回不同提示文案
switch ($status) {
case AgentModel::AGENT_STATUS_NEEDINFO:
case AgentModel::AGENT_STATUS_REJECT:
// 允许申请,继续执行
break;
case AgentModel::AGENT_STATUS_NORMAL:
$this->error('您已是分销商');
break;
case AgentModel::AGENT_STATUS_PENDING:
$this->error('您的申请正在审核中,请耐心等待');
break;
case AgentModel::AGENT_STATUS_FREEZE:
$this->error('您的账户已被冻结,如有疑问请联系客服');
break;
case AgentModel::AGENT_STATUS_FORBIDDEN:
$this->error('您的分销商账户已被禁用');
break;
case AgentModel::AGENT_STATUS_NULL:
default:
$this->error('您暂未满足成为分销商的条件');
break;
}
Db::transaction(function () use ($status) {
// 简化申请:无需表单资料,直接创建分销商
$isCheck = $this->service->config->isAgentCheck();
$finalStatus = $isCheck ? AgentModel::AGENT_STATUS_PENDING : AgentModel::AGENT_STATUS_NORMAL;
AgentModel::create([
'user_id' => $this->service->user->id,
'level' => 1,
'status' => $finalStatus,
'apply_info' => [],
'apply_num' => 1,
'become_time' => time()
]);
// 绑定推荐人
if ($this->service->user->parent_user_id === NULL) {
$this->service->bindUserRelation('agent');
if ($this->service->user->parent_user_id === NULL) {
$this->service->user->parent_user_id = 0;
$this->service->user->save();
}
}
// 添加分销商状态日志
\app\admin\model\shopro\commission\Log::add($this->service->user->id, 'agent', ['type' => 'status', 'value' => $finalStatus]);
});
$this->success('提交成功');
}
// 申请分销商-原来的申请分销商接口 2026.07.04
public function apply_old()
{
if (!$this->request->isPost()) {
$this->error('');
}
if (!$this->service->config->isAgentApplyForm()) {
$this->error('未开启分销商申请');
}
$status = $this->service->getAgentStatus(true);
if (!in_array($status, [AgentModel::AGENT_STATUS_NEEDINFO, AgentModel::AGENT_STATUS_REJECT, AgentModel::AGENT_STATUS_NORMAL])) {
......@@ -93,6 +166,9 @@ class Agent extends Commission
}
Db::transaction(function () use ($status) {
$data = $this->request->param('data/a');
if (empty($data) || !is_array($data)) {
$this->error('请填写申请资料');
}
// 过滤无效表单字段数据
$config = $this->service->config->getAgentForm();
$form = (array)$config['content'];
......@@ -122,6 +198,14 @@ class Agent extends Commission
$this->success('提交成功');
}
// 判断用户是否已是分销商(含冻结、禁用、正常、审核中状态)
public function isAgent()
{
$status = $this->service->getAgentStatus(false);
$isAgent = in_array($status, [AgentModel::AGENT_STATUS_NORMAL, AgentModel::AGENT_STATUS_FREEZE, AgentModel::AGENT_STATUS_FORBIDDEN, AgentModel::AGENT_STATUS_PENDING]) ? 1 : 0;
$this->success('', $isAgent);
}
// 我的团队
public function team()
{
......
......@@ -3,6 +3,7 @@
namespace addons\shopro\controller\user;
use addons\shopro\controller\Common;
use app\admin\model\shopro\commission\Agent as AgentModel;
class Agent extends Common
{
......@@ -24,10 +25,16 @@ class Agent extends Common
$userId = $user->id ?? 0;
custom_log('[agent.apply] 收到代理申请请求, user_id=' . $userId, $userId, 'share');
// 校验是否为分销商
$isDistributor = \app\admin\model\shopro\commission\Agent::where('user_id', $userId)->find();
if (!$isDistributor) {
$this->error('请先申请成为分销商');
// 校验消费累计条件
$commissionConfig = new \addons\shopro\service\commission\Config();
$becomeAgentEvent = $commissionConfig->getBecomeAgentEvent();
if ($becomeAgentEvent['type'] === 'consume') {
$requiredConsume = $becomeAgentEvent['value'] ?? 0;
$userConsume = floatval($user->total_consume ?? 0);
if ($userConsume < $requiredConsume) {
custom_log('[agent.apply] 消费金额不足, user_id=' . $userId . ', 累计消费=' . $userConsume . ', 要求=' . $requiredConsume, $userId, 'share', 'warning');
$this->error('累计消费未达到申请要求,当前累计消费 ¥' . $userConsume . ',需达到 ¥' . $requiredConsume);
}
}
$params = $this->request->only(['real_name', 'id_card', 'id_card_images']);
......
......@@ -31,6 +31,12 @@ class AgentOrderCommission extends Command
protected $output = null;
/**
* 本轮处理中受影响的代理商 ID 集合,用于结束时更新累计佣金
* @var array [agent_id => true]
*/
protected $affectedAgentIds = [];
/**
* 查询时间范围(小时)
*/
const LOOKBACK_HOURS = 36;
......@@ -176,6 +182,10 @@ class AgentOrderCommission extends Command
}
$this->customLog('info', "共处理 {$totalProcessed} 笔订单 - 成功: {$successCount}, 跳过: {$skipCount}, 异常: {$errorCount}");
// 2. 所有订单佣金统计完毕后,更新代理商累计佣金总额
$this->updateAgentsTotalCommission();
$this->customLog('info', '========== 分销订单佣金结算任务执行完成 ==========');
} catch (\Exception $e) {
......@@ -367,6 +377,7 @@ class AgentOrderCommission extends Command
if ($inserted) {
$this->customLog('info', "订单[{$orderSn}]第{$agentLevel}级代理商[{$recordAgentId}]佣金: ¥{$commissionAmount} (订单金额: ¥{$payFee})");
$this->affectedAgentIds[$recordAgentId] = true;
$processedCount++;
}
}
......@@ -465,4 +476,49 @@ class AgentOrderCommission extends Command
return null;
}
/**
* 更新本轮受影响代理商的累计佣金总额
*
* 从 fa_shopro_agent_order_commission 表汇总每个代理商的 commission_amount,
* 回写到 fa_shopro_agent.total_commission 字段。
*/
protected function updateAgentsTotalCommission()
{
if (empty($this->affectedAgentIds)) {
$this->customLog('info', '本轮无新增佣金记录,跳过更新代理商累计佣金');
return;
}
$agentIds = array_keys($this->affectedAgentIds);
$agentCount = count($agentIds);
$this->customLog('info', "开始更新 {$agentCount} 个代理商的累计佣金总额...");
$updatedCount = 0;
foreach ($agentIds as $agentId) {
try {
// 汇总该代理商所有佣金记录
$total = Db::name('shopro_agent_order_commission')
->where('agent_id', $agentId)
->sum('commission_amount');
$total = round(floatval($total), 2);
// 更新 fa_shopro_agent 累计佣金
Db::name('shopro_agent')
->where('id', $agentId)
->update([
'total_commission' => $total,
'updatetime' => time(),
]);
$updatedCount++;
$this->customLog('info', "代理商[{$agentId}]累计佣金更新为: ¥{$total}");
} catch (\Exception $e) {
$this->customLog('error', "代理商[{$agentId}]累计佣金更新失败: " . $e->getMessage());
}
}
$this->customLog('info', "累计佣金更新完成: {$updatedCount}/{$agentCount}");
}
}
......@@ -328,7 +328,7 @@ return [
'ai_mix' => Env::get('app.ai_mix', ''),
'ai_hook' => Env::get('app.ai_hook', ''),
// 每天3D试戴次数上限
// 每天3D试戴次数上限3次
'ai_tryon_count' => Env::get('app.ai_tryon_count', 2),
// obs 配置
......
......@@ -34,7 +34,7 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
{field: 'id_card', title: __('Id_card'), operate: 'LIKE'},
{field: 'commission_rate', title: __('Commission_rate'), operate:'BETWEEN'},
{field: 'total_commission', title: __('Total_commission'), operate:'BETWEEN'},
{field: 'status', title: __('Status'), searchList: {"normal":__('Status normal'),"frozen":__('Status frozen')}, formatter: Table.api.formatter.status},
// {field: 'status', title: __('Status'), searchList: {"normal":__('Status normal'),"frozen":__('Status frozen')}, formatter: Table.api.formatter.status},
{field: 'apply_id', title: __('Apply_id')},
{field: 'createtime', title: __('Createtime'), operate:'RANGE', addclass:'datetimerange', autocomplete:false, formatter: Table.api.formatter.datetime},
{field: 'updatetime', title: __('Updatetime'), operate:'RANGE', addclass:'datetimerange', autocomplete:false, formatter: Table.api.formatter.datetime},
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment