Files
huangjingfen/pro_v3.5.1/app/services/hjf/PointsRewardServices.php
apple 76ccb24679 feat(fsgx): HJF queue merge, brokerage timing, cycle commission, points release
- Add HJF jobs, services, DAOs, models, admin/API controllers, release command
- Respect brokerage_timing (on_pay vs confirm); dispatch HjfOrderPayJob for queue goods
- Queue-only cycle commission and position index fix in StoreOrderCreateServices
- UserBill income types: frozen_points_brokerage, frozen_points_release
- Timer: fsgx_release_frozen_points -> PointsReleaseServices
- Agent tasks: no_assess filtering for direct/umbrella counts
- Migrations: queue_pool, points_release_log, fsgx_v1 checklist updates
- Admin/uniapp: crontab preset, membership level, user list, finance routes, docs

Made-with: Cursor
2026-03-24 11:59:09 +08:00

136 lines
4.1 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<?php
declare(strict_types=1);
namespace app\services\hjf;
use app\dao\hjf\PointsReleaseLogDao;
use app\dao\user\UserDao;
use app\services\agent\AgentLevelServices;
use app\services\BaseServices;
use think\annotation\Inject;
use think\facade\Db;
use think\facade\Log;
/**
* 积分奖励服务(级差计算)—— 改造复用版
*
* 改造要点PRD 3.2.2
* - 使用 eb_user.agent_level (FK → eb_agent_level.id) 获取会员等级
* - 从 eb_agent_level 表的 direct_reward_points / umbrella_reward_points 字段读取奖励积分
* - 不再使用独立的 member_level 字段和系统配置表中的 hjf_reward_* 键
*
* Class PointsRewardServices
* @package app\services\hjf
*/
class PointsRewardServices extends BaseServices
{
#[Inject]
protected PointsReleaseLogDao $logDao;
#[Inject]
protected UserDao $userDao;
#[Inject]
protected AgentLevelServices $agentLevelServices;
/**
* 对一笔报单订单发放积分奖励
*/
public function reward(int $orderUid, string $orderId): void
{
try {
$buyer = $this->userDao->get($orderUid);
if (!$buyer || !$buyer['spread_uid']) {
return;
}
$this->propagateReward($buyer['spread_uid'], $orderUid, $orderId, 0);
} 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 递归深度
*/
private function propagateReward(
int $uid,
int $fromUid,
string $orderId,
int $lowerReward,
int $depth = 0
): void {
if ($depth >= 10 || $uid <= 0) {
return;
}
$user = $this->userDao->get($uid);
if (!$user) {
return;
}
$agentLevelId = (int)($user['agent_level'] ?? 0);
$grade = $this->agentLevelServices->getGradeByLevelId($agentLevelId);
if ($grade === 0) {
if ($user['spread_uid']) {
$this->propagateReward((int)$user['spread_uid'], $uid, $orderId, 0, $depth + 1);
}
return;
}
$isDirect = ($depth === 0);
$reward = $isDirect
? $this->agentLevelServices->getDirectRewardPoints($agentLevelId)
: $this->agentLevelServices->getUmbrellaRewardPoints($agentLevelId);
$actual = max(0, $reward - $lowerReward);
if ($actual > 0) {
$this->grantFrozenPoints(
$uid,
$actual,
$orderId,
$isDirect ? 'reward_direct' : 'reward_umbrella',
($isDirect ? '直推奖励' : '伞下奖励(级差)') . " - 来源订单 {$orderId}"
);
}
if ($user['spread_uid']) {
$this->propagateReward(
(int)$user['spread_uid'],
$uid,
$orderId,
$reward,
$depth + 1
);
}
}
/**
* 写入待释放积分frozen_points并记录明细
*/
private function grantFrozenPoints(int $uid, int $points, string $orderId, string $type, string $mark): void
{
Db::transaction(function () use ($uid, $points, $orderId, $type, $mark) {
$this->userDao->bcInc($uid, 'frozen_points', $points, 'uid');
$this->logDao->save([
'uid' => $uid,
'points' => $points,
'pm' => 1,
'type' => $type,
'title' => ($type === 'reward_direct') ? '直推奖励' : '伞下奖励',
'mark' => $mark,
'status' => 'frozen',
'order_id' => $orderId,
]);
});
}
}