fix(fsgx): 直推积分奖励改为标准逐级级差

按 direct_reward_points 沿推荐链逐级扣减:买家自身等级作初始下限,
各祖先仅得 max(0, 自身直推积分 - 链中已取最高直推积分) * 数量。
伞下积分逻辑暂缓,统一记 reward_direct。

Made-with: Cursor
This commit is contained in:
panchengyong
2026-03-30 13:13:59 +08:00
parent 2acc3acfb0
commit cfe023aa2a

View File

@@ -62,28 +62,40 @@ class PointsRewardServices extends BaseServices
if (!$buyer || !$buyer['spread_uid']) { if (!$buyer || !$buyer['spread_uid']) {
return; return;
} }
$this->propagateReward($buyer['spread_uid'], $orderUid, $orderId, 0, 0, $orderDbId, $preUpgradeLevels, $qty);
// 取买家自身的直推奖励积分作为级差下限,确保第一级父节点只拿差额
$buyerLevelId = array_key_exists($orderUid, $preUpgradeLevels)
? $preUpgradeLevels[$orderUid]
: (int)($buyer['agent_level'] ?? 0);
$buyerDirectReward = $this->agentLevelServices->getDirectRewardPoints($buyerLevelId);
$this->propagateReward((int)$buyer['spread_uid'], $orderUid, $orderId, $buyerDirectReward, 0, $orderDbId, $preUpgradeLevels, $qty);
} catch (\Throwable $e) { } catch (\Throwable $e) {
Log::error("[PointsReward] 积分奖励失败 orderUid={$orderUid} orderId={$orderId}: " . $e->getMessage()); Log::error("[PointsReward] 积分奖励失败 orderUid={$orderUid} orderId={$orderId}: " . $e->getMessage());
} }
} }
/** /**
* 向上递归发放级差积分 * 向上递归发放直推积分奖励(标准逐级级差)
* *
* @param int $uid 当前被奖励用户 * 算法沿推荐链向上遍历每个分销等级大于0的祖先获得
* @param int $fromUid 触发方(下级)用户 ID * max(0, 自身 direct_reward_points - 链中已见最高 direct_reward_points) * qty
* @param string $orderId 来源订单号 * 非分销员grade=0跳过但继续向上传递$lowerDirectReward 不变。
* @param int $lowerReward 下级已获得的伞下奖励积分(用于级差扣减) *
* @param int $depth 递归深度 * @param int $uid 当前被奖励用户
* @param array $preUpgradeLevels 升级前各用户的 agent_level 快照 [uid => level_id] * @param int $fromUid 触发方(下级)用户 ID
* @param int $qty 报单商品数量积分按数量倍乘B3 * @param string $orderId 来源订单号
* @param int $lowerDirectReward 链中已被下级拿走的最高 direct_reward_points级差下限
* @param int $depth 递归深度(防止无限递归)
* @param int $orderDbId 订单表主键 id
* @param array $preUpgradeLevels 升级前各用户的 agent_level 快照 [uid => level_id]B2
* @param int $qty 报单商品数量积分按数量倍乘B3
*/ */
private function propagateReward( private function propagateReward(
int $uid, int $uid,
int $fromUid, int $fromUid,
string $orderId, string $orderId,
int $lowerReward, int $lowerDirectReward,
int $depth = 0, int $depth = 0,
int $orderDbId = 0, int $orderDbId = 0,
array $preUpgradeLevels = [], array $preUpgradeLevels = [],
@@ -105,44 +117,37 @@ class PointsRewardServices extends BaseServices
$grade = $this->agentLevelServices->getGradeByLevelId($agentLevelId); $grade = $this->agentLevelServices->getGradeByLevelId($agentLevelId);
if ($grade === 0) { if ($grade === 0) {
// 非分销员:跳过奖励,但继续向上传递,$lowerDirectReward 保持不变
if ($user['spread_uid']) { if ($user['spread_uid']) {
$this->propagateReward((int)$user['spread_uid'], $uid, $orderId, 0, $depth + 1, $orderDbId, $preUpgradeLevels, $qty); $this->propagateReward((int)$user['spread_uid'], $uid, $orderId, $lowerDirectReward, $depth + 1, $orderDbId, $preUpgradeLevels, $qty);
} }
return; return;
} }
$isDirect = ($depth === 0); $directReward = $this->agentLevelServices->getDirectRewardPoints($agentLevelId);
// fsgx B4直推奖励和伞下奖励分别读取级差计算只用伞下奖励做扣减
// 这样当中间层如创客umbrella=0上报时上级云店umbrella=300
// 计算 max(0, 300-0)=300而不会被直推奖励 500 错误抵消
$directReward = $this->agentLevelServices->getDirectRewardPoints($agentLevelId);
$umbrellaReward = $this->agentLevelServices->getUmbrellaRewardPoints($agentLevelId);
if ($isDirect) { // 级差:本节点只拿超出下级已取走部分的差额,再乘以数量
// fsgx B3直推奖励按报单商品数量倍乘 $actual = max(0, $directReward - $lowerDirectReward) * $qty;
$actual = $directReward * $qty;
} else {
// 级差:基于单件奖励做差值,再乘以数量
$actual = max(0, $umbrellaReward - $lowerReward) * $qty;
}
if ($actual > 0) { if ($actual > 0) {
$this->grantFrozenPoints( $this->grantFrozenPoints(
$uid, $uid,
$actual, $actual,
$orderId, $orderId,
$isDirect ? 'reward_direct' : 'reward_umbrella', 'reward_direct',
($isDirect ? '直推奖励' : '伞下奖励(级差)') . " x{$qty} - 来源订单 {$orderId}", '直推奖励(级差)' . " x{$qty} - 来源订单 {$orderId}",
$orderDbId $orderDbId
); );
} }
// 向上传递时,下限取当前节点与已有下限中的较大值,确保上级只拿增量
$nextLower = max($directReward, $lowerDirectReward);
if ($user['spread_uid']) { if ($user['spread_uid']) {
$this->propagateReward( $this->propagateReward(
(int)$user['spread_uid'], (int)$user['spread_uid'],
$uid, $uid,
$orderId, $orderId,
$umbrellaReward, // 向上传单件伞下奖励(级差基数),让上级自行乘以 $qty $nextLower,
$depth + 1, $depth + 1,
$orderDbId, $orderDbId,
$preUpgradeLevels, $preUpgradeLevels,