```
feat(commission): 完善分销订单支付时数据同步机制 - 新增 syncExistingCommissionOrderOnPay 方法处理已存在分销单的支付同步场景 - 添加 encodeCommissionRulesSnapshot 和 commissionRulesSnapshotEquals 辅助方法 - 优化佣金规则快照存储方式,统一JSON编码格式 - 增加已入账奖励数量检查,防止对已结算订单进行错误同步 fix(wallet-settlement): 调整分账和佣金结算的余额处理逻辑 - 新增 shouldSettleCommissionViaWalletHook 和 shouldSettleRegionalViaWalletHook 方法控制分账成功后的钱包入账行为 - 修改 shouldDeferRegionalWallet 调用为 shouldSettleRegionalViaWalletHook - 修复分账成功时仍可能重复入钱包的问题 - 统一佣金和区域代理的钩子结算判断逻辑 refactor(hook): 优化佣金钩子触发条件和订单查询逻辑 - 在 CommissionHook 中使用新的钱包结算判断方法 - 修正 orderFinish 事件中的订单项遍历逻辑 - 增加订单有效性检查,避免空值异常 - 统一各事件中的结算条件判断 test(sql): 更新分账佣金验证SQL脚本 - 修正注释说明,明确分账成功不入余额的控制逻辑 - 补充区域代理佣金缺失汇付接收方的查询 - 重构单笔订单深度核验脚本,提供更详细的订单分析信息 - 增加分账成功与钱包流水的对比检查逻辑 ```
这个提交包含在:
@@ -14,6 +14,8 @@ use addons\shopro\model\commission\Order as OrderModel;
|
||||
|
||||
use addons\shopro\model\commission\Reward as RewardModel;
|
||||
|
||||
use addons\shopro\library\commission\Reward as RewardLibrary;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
@@ -193,7 +195,7 @@ class Commission
|
||||
|
||||
if ($commissionOrder) {
|
||||
|
||||
return $commissionOrder;
|
||||
return $this->syncExistingCommissionOrderOnPay($commissionOrder);
|
||||
|
||||
}
|
||||
|
||||
@@ -225,17 +227,7 @@ class Commission
|
||||
|
||||
'commission_price_type' => $this->_config->getCommissionPriceType(),
|
||||
|
||||
'commission_rules' => json_encode([
|
||||
|
||||
'rules' => $this->goods->getCommissionRules(),
|
||||
|
||||
'differential_enable' => $this->goods->isDifferentialEnable() ? 1 : 0,
|
||||
|
||||
'management_enable' => $this->goods->isManagementEnable() ? 1 : 0,
|
||||
|
||||
'repurchase_enable' => $this->goods->isRepurchaseEnable() ? 1 : 0,
|
||||
|
||||
]),
|
||||
'commission_rules' => $this->encodeCommissionRulesSnapshot(),
|
||||
|
||||
'commission_event' => $this->_config->getCommissionEvent(),
|
||||
|
||||
@@ -279,6 +271,128 @@ class Commission
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 支付时若已存在分销单(测试/脏数据/提前写入),与当前订单项不一致则同步并重算待发佣金
|
||||
*/
|
||||
protected function syncExistingCommissionOrderOnPay($commissionOrder)
|
||||
{
|
||||
$agentId = $this->selfBuy
|
||||
? $this->buyer->user->id
|
||||
: ($this->buyer->getParentAgentId() ?: $this->buyer->user->id);
|
||||
|
||||
$newAmount = round(floatval($this->amount), 2);
|
||||
$oldAmount = round(floatval($commissionOrder->amount), 2);
|
||||
$newPriceType = $this->_config->getCommissionPriceType();
|
||||
$newRulesJson = $this->encodeCommissionRulesSnapshot();
|
||||
|
||||
$needsSync = (
|
||||
abs($newAmount - $oldAmount) >= 0.01
|
||||
|| intval($commissionOrder->order_id) !== intval($this->item['order_id'])
|
||||
|| intval($commissionOrder->agent_id) !== intval($agentId)
|
||||
|| (string) $commissionOrder->commission_price_type !== (string) $newPriceType
|
||||
|| !$this->commissionRulesSnapshotEquals($commissionOrder->commission_rules, $newRulesJson)
|
||||
);
|
||||
|
||||
if (!$needsSync) {
|
||||
return $commissionOrder;
|
||||
}
|
||||
|
||||
$accountedCount = RewardModel::where('commission_order_id', $commissionOrder->id)
|
||||
->where('status', RewardLibrary::COMMISSION_REWARD_STATUS_ACCOUNTED)
|
||||
->count();
|
||||
if ($accountedCount > 0) {
|
||||
\think\Log::warning(sprintf(
|
||||
'[commission] skip sync commission_order id=%d order_item_id=%d: %d accounted reward(s), old_amount=%s new_amount=%s',
|
||||
$commissionOrder->id,
|
||||
$this->item['id'],
|
||||
$accountedCount,
|
||||
$oldAmount,
|
||||
$newAmount
|
||||
));
|
||||
return $commissionOrder;
|
||||
}
|
||||
|
||||
RewardModel::where('commission_order_id', $commissionOrder->id)
|
||||
->where('status', RewardLibrary::COMMISSION_REWARD_STATUS_WAITING)
|
||||
->delete();
|
||||
|
||||
if (
|
||||
intval($commissionOrder->commission_order_status) === OrderModel::COMMISSION_ORDER_STATUS_YES
|
||||
&& abs($newAmount - $oldAmount) >= 0.01
|
||||
) {
|
||||
$orderAgent = new Agent($commissionOrder->agent_id);
|
||||
if ($orderAgent->isAgentAvaliable()) {
|
||||
$delta = bcsub((string) $newAmount, (string) $oldAmount, 2);
|
||||
if (bccomp($delta, '0', 2) > 0) {
|
||||
$orderAgent->agent->setInc('order_money', $delta);
|
||||
} elseif (bccomp($delta, '0', 2) < 0) {
|
||||
$dec = ltrim($delta, '-');
|
||||
if (bccomp((string) $orderAgent->agent->order_money, $dec, 2) < 0) {
|
||||
$orderAgent->agent->order_money = 0;
|
||||
} else {
|
||||
$orderAgent->agent->setDec('order_money', $dec);
|
||||
}
|
||||
}
|
||||
$orderAgent->agent->save();
|
||||
}
|
||||
}
|
||||
|
||||
$commissionOrder->self_buy = intval($this->selfBuy);
|
||||
$commissionOrder->order_id = intval($this->item['order_id']);
|
||||
$commissionOrder->buyer_id = $this->buyer->user->id;
|
||||
$commissionOrder->goods_id = $this->item['goods_id'];
|
||||
$commissionOrder->agent_id = intval($agentId);
|
||||
$commissionOrder->amount = $newAmount;
|
||||
$commissionOrder->commission_price_type = $newPriceType;
|
||||
$commissionOrder->commission_rules = $newRulesJson;
|
||||
$commissionOrder->commission_event = $this->_config->getCommissionEvent();
|
||||
if (intval($commissionOrder->commission_reward_status) !== RewardLibrary::COMMISSION_REWARD_STATUS_WAITING) {
|
||||
$commissionOrder->commission_reward_status = RewardLibrary::COMMISSION_REWARD_STATUS_WAITING;
|
||||
$commissionOrder->commission_time = null;
|
||||
}
|
||||
$commissionOrder->save();
|
||||
|
||||
\think\Log::info(sprintf(
|
||||
'[commission] synced commission_order id=%d order_item_id=%d amount %s -> %s',
|
||||
$commissionOrder->id,
|
||||
$this->item['id'],
|
||||
$oldAmount,
|
||||
$newAmount
|
||||
));
|
||||
|
||||
return $commissionOrder;
|
||||
}
|
||||
|
||||
|
||||
|
||||
protected function encodeCommissionRulesSnapshot()
|
||||
{
|
||||
return json_encode([
|
||||
'rules' => $this->goods->getCommissionRules(),
|
||||
'differential_enable' => $this->goods->isDifferentialEnable() ? 1 : 0,
|
||||
'management_enable' => $this->goods->isManagementEnable() ? 1 : 0,
|
||||
'repurchase_enable' => $this->goods->isRepurchaseEnable() ? 1 : 0,
|
||||
], JSON_UNESCAPED_UNICODE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
protected function commissionRulesSnapshotEquals($stored, $newJson)
|
||||
{
|
||||
$left = json_decode($stored ?: '{}', true);
|
||||
$right = json_decode($newJson ?: '{}', true);
|
||||
if (!is_array($left)) {
|
||||
$left = [];
|
||||
}
|
||||
if (!is_array($right)) {
|
||||
$right = [];
|
||||
}
|
||||
|
||||
return json_encode($left, JSON_UNESCAPED_UNICODE) === json_encode($right, JSON_UNESCAPED_UNICODE);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
||||
* 执行分销计划:关系链、级差、管理奖可同时发放
|
||||
|
||||
@@ -292,7 +292,7 @@ class Commission
|
||||
$agent->setInc('order_count', 1);
|
||||
|
||||
if ($this->_config->getCommissionEvent() === 'payed') {
|
||||
if (!SplitWalletSettlement::shouldDeferRegionalWallet($order, 'payed')) {
|
||||
if (SplitWalletSettlement::shouldSettleRegionalViaWalletHook($order, 'payed')) {
|
||||
(new Reward())->settleByRegionalOrder($regionalOrder->id, 'payed');
|
||||
}
|
||||
}
|
||||
@@ -311,7 +311,11 @@ class Commission
|
||||
|
||||
$rewardLib = new Reward();
|
||||
foreach ($regionalOrders as $regionalOrder) {
|
||||
if ($regionalOrder['commission_event'] === $event) {
|
||||
if ($regionalOrder['commission_event'] !== $event) {
|
||||
continue;
|
||||
}
|
||||
$order = \addons\shopro\model\Order::get($regionalOrder->order_id);
|
||||
if ($order && SplitWalletSettlement::shouldSettleRegionalViaWalletHook($order, $event)) {
|
||||
$rewardLib->settleByRegionalOrder($regionalOrder->id, $event);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,6 +38,38 @@ class SplitWalletSettlement
|
||||
return self::shouldDeferWalletUntilGatewaySplitResolves($order);
|
||||
}
|
||||
|
||||
/**
|
||||
* 分销钩子是否应把待发佣金写入余额(false = 等分账 finalize 或已走通道,避免与汇付/微信分账重复)
|
||||
*/
|
||||
public static function shouldSettleCommissionViaWalletHook($order, $event)
|
||||
{
|
||||
$commissionEvent = (new CommissionConfig())->getCommissionEvent();
|
||||
if ($commissionEvent !== $event && $event !== 'admin') {
|
||||
return false;
|
||||
}
|
||||
if (self::shouldDeferWalletUntilGatewaySplitResolves($order)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 区域代理钩子是否应把待发佣金写入余额
|
||||
*/
|
||||
public static function shouldSettleRegionalViaWalletHook($order, $event)
|
||||
{
|
||||
$regionalEvent = (new RegionalConfig())->getCommissionEvent();
|
||||
if ($regionalEvent !== $event && $event !== 'admin') {
|
||||
return false;
|
||||
}
|
||||
if (self::shouldDeferWalletUntilGatewaySplitResolves($order)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 分销/区域结算事件(如 payed)早于 split_timing(如 confirm)时,仍应等分账结束再入钱包
|
||||
*/
|
||||
@@ -54,8 +86,9 @@ class SplitWalletSettlement
|
||||
if (!$config->isEnable() || !$config->shouldSkipWallet()) {
|
||||
return false;
|
||||
}
|
||||
// 分账已成功:佣金应由 finalizeAfterSplitAttempt 处理(或已标记通道到账),钩子不得再入余额
|
||||
if (self::isSplitSuccessful($order['id'])) {
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (class_exists('\\addons\\shopro_huifu\\library\\Bridge')
|
||||
|
||||
@@ -50,7 +50,7 @@ class CommissionHook
|
||||
// 执行奖金计划
|
||||
$commission->runCommissionPlan($commissionOrder);
|
||||
// 支付后拨款(汇付分账同事件时延至分账结果后再结算)
|
||||
if (!SplitWalletSettlement::shouldDeferCommissionWallet($order, 'payed')) {
|
||||
if (SplitWalletSettlement::shouldSettleCommissionViaWalletHook($order, 'payed')) {
|
||||
(new RewardLibrary())->runCommissionRewardByOrder('payed', $commissionOrder->id);
|
||||
}
|
||||
}
|
||||
@@ -102,7 +102,10 @@ class CommissionHook
|
||||
|
||||
$commissionOrder = \addons\shopro\model\commission\Order::get(['order_item_id' => $item['id']]);
|
||||
if ($commissionOrder) {
|
||||
(new RewardLibrary())->runCommissionRewardByOrder('confirm', $commissionOrder);
|
||||
$order = Order::get($commissionOrder->order_id);
|
||||
if ($order && SplitWalletSettlement::shouldSettleCommissionViaWalletHook($order, 'confirm')) {
|
||||
(new RewardLibrary())->runCommissionRewardByOrder('confirm', $commissionOrder);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -110,9 +113,13 @@ class CommissionHook
|
||||
public function orderFinish(&$params)
|
||||
{
|
||||
$order = $params['order'];
|
||||
foreach ($order['item'] as $item) {
|
||||
$orderRow = Order::with('item')->where('id', $order['id'])->find();
|
||||
if (!$orderRow) {
|
||||
return;
|
||||
}
|
||||
foreach ($orderRow['item'] as $item) {
|
||||
$commissionOrder = \addons\shopro\model\commission\Order::get(['order_item_id' => $item['id']]);
|
||||
if ($commissionOrder) {
|
||||
if ($commissionOrder && SplitWalletSettlement::shouldSettleCommissionViaWalletHook($orderRow, 'finish')) {
|
||||
(new RewardLibrary())->runCommissionRewardByOrder('finish', $commissionOrder);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,7 +127,7 @@ GROUP BY pay_type;
|
||||
-- 网关分账:fa_shopro_split_order_receiver + receiver 表(汇付 huifu_id / 微信 openid)
|
||||
-- 业务佣金:fa_shopro_commission_reward / fa_shopro_regional_agent_reward
|
||||
-- 钱包入账:fa_shopro_user_wallet_log type=commission_income / regional_agent_income
|
||||
-- 代码说明:shouldSkipWallet() 尚未接入 Reward,分账开启时仍可能同时入账钱包(需重点核对)
|
||||
-- 代码说明:SplitWalletSettlement + shouldSettle*ViaWalletHook 控制分账成功不入余额;§9 仍用于核对历史数据
|
||||
|
||||
SELECT '=== 7. 分账成功订单明细(最近 30 笔)===' AS section;
|
||||
|
||||
@@ -298,11 +298,12 @@ LIMIT 20;
|
||||
|
||||
SELECT '=== 12. 有推广/区域佣金但缺少汇付接收方(导致无法分账)===' AS section;
|
||||
|
||||
-- 推广:r.agent_id 即分销商 user_id(非 commission_agent 表主键)
|
||||
SELECT DISTINCT
|
||||
r.order_id,
|
||||
o.order_sn,
|
||||
'commission' AS reward_source,
|
||||
a.user_id AS beneficiary_user_id,
|
||||
r.agent_id AS beneficiary_user_id,
|
||||
u.mobile,
|
||||
ho.huifu_id AS onboard_huifu_id,
|
||||
sr.id AS split_receiver_id
|
||||
@@ -318,6 +319,26 @@ WHERE r.status >= 0
|
||||
AND sr.id IS NULL
|
||||
LIMIT 30;
|
||||
|
||||
SELECT DISTINCT
|
||||
rr.order_id,
|
||||
o.order_sn,
|
||||
'regional_agent' AS reward_source,
|
||||
rr.agent_user_id AS beneficiary_user_id,
|
||||
u.mobile,
|
||||
ho.huifu_id AS onboard_huifu_id,
|
||||
sr.id AS split_receiver_id
|
||||
FROM fa_shopro_regional_agent_reward rr
|
||||
INNER JOIN fa_shopro_order o ON o.id = rr.order_id
|
||||
INNER JOIN fa_user u ON u.id = rr.agent_user_id
|
||||
LEFT JOIN fa_shopro_huifu_onboard ho ON ho.user_id = rr.agent_user_id AND ho.onboard_status = 'approved'
|
||||
LEFT JOIN fa_shopro_split_receiver sr ON sr.role_type = 'regional_agent'
|
||||
AND sr.role_id = rr.agent_user_id AND sr.channel = 'huifu' AND sr.status = 'normal'
|
||||
WHERE rr.status >= 0
|
||||
AND o.pay_type = 'huifu_wechat'
|
||||
AND o.paytime >= UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 90 DAY))
|
||||
AND sr.id IS NULL
|
||||
LIMIT 30;
|
||||
|
||||
SELECT '=== 13. 延时分账标记:支付扩展 delay_acct(近90天汇付单抽样)===' AS section;
|
||||
|
||||
SELECT
|
||||
@@ -343,37 +364,160 @@ FROM fa_shopro_split_receiver
|
||||
GROUP BY channel, role_type;
|
||||
|
||||
-- =============================================================================
|
||||
-- 五、单笔订单深度核验(把 @order_sn 改成实际订单号后执行)
|
||||
-- 五、单笔订单深度核验
|
||||
-- 用法:只改下面一行 @order_id 或 @order_sn,然后整段执行
|
||||
-- 预设:77 = 598单 202605495163454091004900;74 = 分账成功样例 202609215157744091003800
|
||||
-- =============================================================================
|
||||
/*
|
||||
SET @order_sn = '2025010100000001';
|
||||
|
||||
SELECT o.* FROM fa_shopro_order o WHERE o.order_sn = @order_sn;
|
||||
SET @order_id = 77;
|
||||
-- SET @order_sn = '202605495163454091004900';
|
||||
-- SET @order_id = (SELECT id FROM fa_shopro_order WHERE order_sn = @order_sn LIMIT 1);
|
||||
|
||||
SELECT * FROM fa_shopro_split_order WHERE order_sn = @order_sn;
|
||||
SELECT sor.*, sr.receiver_account, sr.channel
|
||||
FROM fa_shopro_split_order_receiver sor
|
||||
SELECT '=== 5.1 订单主表 ===' AS section;
|
||||
-- 确认/完成时间在 ext JSON(confirm_time / finish_time),非独立字段
|
||||
SELECT id, order_sn, status, pay_type, pay_fee, total_fee,
|
||||
FROM_UNIXTIME(paytime) AS pay_time,
|
||||
FROM_UNIXTIME(
|
||||
NULLIF(CAST(JSON_UNQUOTE(JSON_EXTRACT(ext, '$.confirm_time')) AS UNSIGNED), 0)
|
||||
) AS confirm_time,
|
||||
FROM_UNIXTIME(
|
||||
NULLIF(CAST(JSON_UNQUOTE(JSON_EXTRACT(ext, '$.finish_time')) AS UNSIGNED), 0)
|
||||
) AS finish_time,
|
||||
FROM_UNIXTIME(updatetime) AS order_updated,
|
||||
ext
|
||||
FROM fa_shopro_order WHERE id = @order_id;
|
||||
|
||||
SELECT '=== 5.2 订单商品行 ===' AS section;
|
||||
SELECT id AS order_item_id, goods_id, goods_title, goods_price, goods_num,
|
||||
pay_price, discount_fee, ext
|
||||
FROM fa_shopro_order_item WHERE order_id = @order_id;
|
||||
|
||||
SELECT '=== 5.3 汇付支付扩展 delay_acct ===' AS section;
|
||||
SELECT order_id, delay_acct_flag, confirm_status, confirm_hf_seq_id, hf_seq_id, trans_stat,
|
||||
LEFT(extra, 200) AS extra_preview
|
||||
FROM fa_shopro_huifu_pay_ext WHERE order_id = @order_id;
|
||||
|
||||
SELECT '=== 5.4 分账单(全部状态)===' AS section;
|
||||
SELECT id, channel, status,
|
||||
CASE status WHEN 0 THEN '待分账' WHEN 1 THEN '分账中' WHEN 2 THEN '成功'
|
||||
WHEN 3 THEN '部分成功' WHEN 4 THEN '失败' ELSE status END AS status_label,
|
||||
total_amount, split_amount, confirm_hf_seq_id,
|
||||
FROM_UNIXTIME(createtime) AS created_at,
|
||||
LEFT(wx_result, 180) AS result_msg
|
||||
FROM fa_shopro_split_order WHERE order_id = @order_id
|
||||
ORDER BY id DESC;
|
||||
|
||||
SELECT '=== 5.5 分账接收方明细 ===' AS section;
|
||||
SELECT so.order_sn, sor.role_type, sor.amount, sor.description, sor.status AS line_status,
|
||||
sr.receiver_account, sr.receiver_type, sr.channel, sr.receiver_name, sr.role_id AS user_id
|
||||
FROM fa_shopro_split_order so
|
||||
INNER JOIN fa_shopro_split_order_receiver sor ON sor.split_order_id = so.id
|
||||
LEFT JOIN fa_shopro_split_receiver sr ON sr.id = sor.receiver_id
|
||||
WHERE sor.split_order_id IN (SELECT id FROM fa_shopro_split_order WHERE order_sn = @order_sn);
|
||||
WHERE so.order_id = @order_id
|
||||
ORDER BY so.id DESC, sor.id;
|
||||
|
||||
SELECT * FROM fa_shopro_commission_reward WHERE order_id = (SELECT id FROM fa_shopro_order WHERE order_sn = @order_sn LIMIT 1);
|
||||
SELECT rr.*
|
||||
SELECT '=== 5.6 分销单 + 推广佣金 ===' AS section;
|
||||
SELECT co.id AS commission_order_id, co.order_item_id, co.amount AS dist_base,
|
||||
co.commission_price_type, co.commission_event,
|
||||
co.commission_reward_status, FROM_UNIXTIME(co.createtime) AS co_created,
|
||||
FROM_UNIXTIME(co.commission_time) AS co_settled,
|
||||
LEFT(co.commission_rules, 120) AS rules_preview
|
||||
FROM fa_shopro_commission_order co
|
||||
WHERE co.order_id = @order_id;
|
||||
|
||||
SELECT r.id AS reward_id, r.agent_id AS user_id, u.nickname, u.mobile,
|
||||
r.commission_level, r.commission, r.status,
|
||||
CASE r.status WHEN 0 THEN '待入账' WHEN 1 THEN '已入账' WHEN -1 THEN '已退回' ELSE r.status END AS status_label,
|
||||
r.commission_rules, FROM_UNIXTIME(r.createtime) AS reward_created
|
||||
FROM fa_shopro_commission_reward r
|
||||
LEFT JOIN fa_user u ON u.id = r.agent_id
|
||||
WHERE r.order_id = @order_id
|
||||
ORDER BY r.id;
|
||||
|
||||
SELECT '=== 5.7 区域代理单 + 区域佣金 ===' AS section;
|
||||
SELECT ro.id AS regional_order_id, ro.amount AS regional_base, ro.commission_event,
|
||||
ro.commission_reward_status, FROM_UNIXTIME(ro.createtime) AS ro_created
|
||||
FROM fa_shopro_regional_agent_order ro
|
||||
WHERE ro.order_id = @order_id;
|
||||
|
||||
SELECT rr.id AS reward_id, rr.agent_user_id AS user_id, u.nickname, u.mobile,
|
||||
rr.commission, rr.status,
|
||||
CASE rr.status WHEN 0 THEN '待入账' WHEN 1 THEN '已入账' WHEN -1 THEN '已退回' ELSE rr.status END AS status_label,
|
||||
FROM_UNIXTIME(rr.createtime) AS reward_created
|
||||
FROM fa_shopro_regional_agent_reward rr
|
||||
INNER JOIN fa_shopro_regional_agent_order ro ON ro.id = rr.regional_order_id
|
||||
WHERE ro.order_id = (SELECT id FROM fa_shopro_order WHERE order_sn = @order_sn LIMIT 1);
|
||||
LEFT JOIN fa_user u ON u.id = rr.agent_user_id
|
||||
WHERE rr.order_id = @order_id
|
||||
ORDER BY rr.id;
|
||||
|
||||
SELECT wl.*
|
||||
SELECT '=== 5.8 钱包流水(佣金/区域)===' AS section;
|
||||
SELECT wl.id, wl.user_id, wl.type, wl.wallet, wl.item_id,
|
||||
FROM_UNIXTIME(wl.createtime) AS log_time, LEFT(wl.memo, 80) AS memo
|
||||
FROM fa_shopro_user_wallet_log wl
|
||||
WHERE wl.wallet_type = 'money'
|
||||
AND wl.type IN ('commission_income', 'regional_agent_income', 'commission_back', 'regional_agent_back')
|
||||
AND (
|
||||
wl.item_id IN (SELECT id FROM fa_shopro_commission_reward WHERE order_id = (SELECT id FROM fa_shopro_order WHERE order_sn = @order_sn LIMIT 1))
|
||||
OR wl.item_id IN (
|
||||
SELECT rr.id FROM fa_shopro_regional_agent_reward rr
|
||||
INNER JOIN fa_shopro_regional_agent_order ro ON ro.id = rr.regional_order_id
|
||||
WHERE ro.order_id = (SELECT id FROM fa_shopro_order WHERE order_sn = @order_sn LIMIT 1)
|
||||
)
|
||||
);
|
||||
wl.item_id IN (SELECT id FROM fa_shopro_commission_reward WHERE order_id = @order_id)
|
||||
OR wl.item_id IN (SELECT id FROM fa_shopro_regional_agent_reward WHERE order_id = @order_id)
|
||||
)
|
||||
ORDER BY wl.id;
|
||||
|
||||
SELECT * FROM fa_shopro_huifu_pay_ext WHERE order_id = (SELECT id FROM fa_shopro_order WHERE order_sn = @order_sn LIMIT 1);
|
||||
*/
|
||||
SELECT '=== 5.9 已入账佣金但无钱包流水(应为通道分账/仅记 total_income)===' AS section;
|
||||
SELECT 'commission' AS src, r.id AS reward_id, r.agent_id AS user_id, r.commission,
|
||||
IF(wl.id IS NULL, '无 wallet_log(符合 gateway)', '有 wallet_log(可能双发)') AS wallet_check
|
||||
FROM fa_shopro_commission_reward r
|
||||
LEFT JOIN fa_shopro_user_wallet_log wl ON wl.wallet_type = 'money'
|
||||
AND wl.type = 'commission_income' AND wl.item_id = r.id
|
||||
WHERE r.order_id = @order_id AND r.status = 1
|
||||
UNION ALL
|
||||
SELECT 'regional', rr.id, rr.agent_user_id, rr.commission,
|
||||
IF(wl.id IS NULL, '无 wallet_log(符合 gateway)', '有 wallet_log(可能双发)')
|
||||
FROM fa_shopro_regional_agent_reward rr
|
||||
LEFT JOIN fa_shopro_user_wallet_log wl ON wl.wallet_type = 'money'
|
||||
AND wl.type = 'regional_agent_income' AND wl.item_id = rr.id
|
||||
WHERE rr.order_id = @order_id AND rr.status = 1;
|
||||
|
||||
SELECT '=== 5.10 本单结论(与 §9 同逻辑)===' AS section;
|
||||
SELECT
|
||||
o.order_sn,
|
||||
o.pay_fee,
|
||||
IFNULL(so.split_amount, 0) AS gateway_split_sum,
|
||||
IFNULL(cr.dist_sum, 0) AS dist_reward_sum,
|
||||
IFNULL(rr.reg_sum, 0) AS regional_reward_sum,
|
||||
IFNULL(wl.w_comm, 0) AS wallet_commission,
|
||||
IFNULL(wl.w_reg, 0) AS wallet_regional,
|
||||
CASE
|
||||
WHEN IFNULL(wl.w_comm, 0) + IFNULL(wl.w_reg, 0) > 0 AND IFNULL(so.split_amount, 0) > 0
|
||||
THEN '⚠ 网关已分账且钱包也有流水'
|
||||
WHEN IFNULL(so.split_amount, 0) > 0
|
||||
AND IFNULL(wl.w_comm, 0) + IFNULL(wl.w_reg, 0) = 0
|
||||
THEN '✓ 分账成功且未进钱包(或仅记收益)'
|
||||
WHEN IFNULL(so.id, 0) = 0 OR so.status NOT IN (2, 3)
|
||||
THEN '未分账成功:佣金可能在钱包或仍待结算'
|
||||
ELSE '请人工核对'
|
||||
END AS check_hint
|
||||
FROM fa_shopro_order o
|
||||
LEFT JOIN (
|
||||
SELECT order_id, MAX(id) AS id, MAX(split_amount) AS split_amount, MAX(status) AS status
|
||||
FROM fa_shopro_split_order WHERE channel = 'huifu' GROUP BY order_id
|
||||
) so ON so.order_id = o.id
|
||||
LEFT JOIN (
|
||||
SELECT order_id, SUM(commission) AS dist_sum FROM fa_shopro_commission_reward WHERE status >= 0 GROUP BY order_id
|
||||
) cr ON cr.order_id = o.id
|
||||
LEFT JOIN (
|
||||
SELECT order_id, SUM(commission) AS reg_sum FROM fa_shopro_regional_agent_reward WHERE status >= 0 GROUP BY order_id
|
||||
) rr ON rr.order_id = o.id
|
||||
LEFT JOIN (
|
||||
SELECT order_id,
|
||||
SUM(CASE WHEN wl.type = 'commission_income' THEN wl.wallet ELSE 0 END) AS w_comm,
|
||||
SUM(CASE WHEN wl.type = 'regional_agent_income' THEN wl.wallet ELSE 0 END) AS w_reg
|
||||
FROM (
|
||||
SELECT cr.order_id, wl.type, wl.wallet
|
||||
FROM fa_shopro_commission_reward cr
|
||||
INNER JOIN fa_shopro_user_wallet_log wl ON wl.item_id = cr.id AND wl.type = 'commission_income' AND wl.wallet_type = 'money'
|
||||
UNION ALL
|
||||
SELECT rr.order_id, wl.type, wl.wallet
|
||||
FROM fa_shopro_regional_agent_reward rr
|
||||
INNER JOIN fa_shopro_user_wallet_log wl ON wl.item_id = rr.id AND wl.type = 'regional_agent_income' AND wl.wallet_type = 'money'
|
||||
) wl GROUP BY order_id
|
||||
) wl ON wl.order_id = o.id
|
||||
WHERE o.id = @order_id;
|
||||
|
||||
在新工单中引用
屏蔽一个用户