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