"1.00", // 一星合伙人 1 => "10.00", // 二星合伙人 2 => "8.00", // 三星合伙人 3 => "5.00", // 钻石合伙人 4 => "3.00", // 总裁合伙人 5 => "2.00", // 联席主席团 6 => "1.00" ]; /** * @param $data * @return array 分配明细数据 * @throws \Exception * @author 史晨 * @date 2026/2/10 10:10 * 合伙人分红(加权分配) */ public function partner($data) { // 获取时间范围内订单 $start = $data['startTime']; $end = $data['endTime']; $isTest = $data['isTest'] ?? false; // 是否测试模式(不实际发放) // 获取pv /** @var SharedProsperityRewardRecordRepository $rewardRecordRepository */ $rewardRecordRepository = app()->make(SharedProsperityRewardRecordRepository::class); $orderList = $rewardRecordRepository->getListByTime($start, $end, self::REWARD_TYPE_PV); if (empty($orderList)) { throw new \Exception('没有订单'); } // 计算可分配利润 $totalConPri = array_sum(array_column($orderList, 'number')); $conPri = floor($totalConPri * self::PARTNER_RADIO * 100) / 100; // 获取合伙人分配规则 $config = self::CONFIG; if (empty($config)) { /** @var SharedProsperityRecommendConfigDao $configDao */ $configDao = app()->make(SharedProsperityRecommendConfigDao::class); $config = $configDao->getConfigList(false); $config = array_column($config, 'profit_ratio', 'level'); } if (empty($config)) { throw new \Exception('没有合伙人分配规则'); } // 获取合伙人 /** @var SharedProsperityUserDao $userDao */ $userDao = app()->make(SharedProsperityUserDao::class); $users = $userDao->getUserGroupByPartnerLevel(); /** @var SharedProsperityBalanceLogDao $balanceDao */ $balanceDao = app()->make(SharedProsperityBalanceLogDao::class); // 分配明细数据收集 $distributionDetails = []; // 如果是测试模式,不开启事务,只计算不实际发放 if (!$isTest) { Db::startTrans(); } try { foreach ($users as $key => $userIds) { if ($key == 0) { continue; } $radio = $config[$key]; // 该等级总分红 $levelTotal = bcmul($conPri, bcdiv($radio, 100, 2), 2); // 获取该等级所有用户的基本信息 $userInfos = $userDao->getSharedProsperityUserEntityListByUserIdList($userIds); if (empty($userInfos)) { continue; } // 计算每个用户的团队业绩(实时统计) $teamPvMap = []; $totalTeamPv = 0; foreach ($userInfos as $userInfo) { $teamPv = $userDao->getTeamPvSum($userInfo->getUserId()); $teamPvMap[$userInfo->getUserId()] = $teamPv; $totalTeamPv += $teamPv; } // 如果总团队业绩为0,则平均分配 if ($totalTeamPv == 0) { $userNum = count($userInfos); $eachReward = floor(($levelTotal / $userNum) * 100) / 100; foreach ($userInfos as $userInfo) { $userReward = $eachReward; $weight = 1 / $userNum; // 平均分配的权重 // 收集分配明细 $distributionDetails[] = [ 'user_id' => $userInfo->getUserId(), //用户ID 'level' => $key, //合伙人等级 'total_allocation' => $levelTotal, //该等级总分配金额 'team_pv' => $teamPvMap[$userInfo->getUserId()] ?? 0, //个人团队PV 'current_level_team_pv' => $totalTeamPv, //当前等级所有用户的团队PV总和 'ratio' => $weight, //占比(个人团队PV/当前等级团队PV) 'actual_amount' => $userReward,//实际发放金额 ]; $this->distributeReward($userInfo, $userReward, $radio, $levelTotal, $balanceDao, $userDao, $isTest); } } else { // 加权分配 foreach ($userInfos as $userInfo) { $weight = $teamPvMap[$userInfo->getUserId()] / $totalTeamPv; $userReward = floor($levelTotal * $weight * 100) / 100; // 收集分配明细 $distributionDetails[] = [ 'user_id' => $userInfo->getUserId(),//用户ID 'level' => $key,//合伙人等级 'total_allocation' => $levelTotal,//该等级总分配金额 'team_pv' => $teamPvMap[$userInfo->getUserId()] ?? 0,//个人团队PV 'current_level_team_pv' => $totalTeamPv,//当前等级所有用户的团队PV总和 'ratio' => $weight,//占比(个人团队PV/当前等级团队PV) 'actual_amount' => $userReward,//实际发放金额 ]; $this->distributeReward($userInfo, $userReward, $radio, $levelTotal, $balanceDao, $userDao, $isTest); } } } if (!$isTest) { // 记录分红日志 // $this->dividendLog($start, $end, $conPri, $conPri, $config, $isTest, '共富体系合伙人分红'); Db::commit(); } // 返回分配明细数据 return [ 'success' => true, 'is_test' => $isTest, 'total_pv' => $totalConPri, 'allocatable_profit' => $conPri, 'distribution_details' => $distributionDetails, 'config' => $config, ]; } catch (\Exception $e) { if (!$isTest) { Db::rollback(); } throw new \Exception($e->getMessage()); } } /** * 分发奖励(记录日志和更新余额) * @param $userInfo * @param $userReward * @param $radio * @param $levelTotal * @param $balanceDao * @param $userDao * @param bool $isTest 是否测试模式(不实际发放) * @return void */ private function distributeReward($userInfo, $userReward, $radio, $levelTotal, $balanceDao, $userDao, $isTest = false) { $userId = $userInfo->getUserId(); // 如果是测试模式,只记录日志不实际执行数据库操作 if ($isTest) { Log::info("测试模式:用户 {$userId} 应发放奖励 {$userReward},等级 {$userInfo->getPartnerLevel()},比例 {$radio},等级总分红 {$levelTotal}"); return; } $balanceDao->create([ 'user_id' => $userId, 'level' => $userInfo->getPartnerLevel(), 'radio' => $radio, 'total_profit' => $levelTotal, 'old' => $userInfo->getBalance(), 'number' => $userReward, 'after' => $userInfo->getBalance() + $userReward ]); $bill = [ 'uid' => $userId, 'link_id' => 0, 'pm' => 1, 'title' => '共富体系合伙人分佣(加权)', 'category' => 'now_money', 'type' => 'commission', 'number' => $userReward, 'balance' => 0, 'mark' => '共富体系合伙人分佣明细入账(加权)', 'create_time' => date('Y-m-d H:i:s'), 'status' => 1, 'commission_type' => CommonEnum::COMMISSION_TYPE['SHARED_PROSPERITY_PARTNER_COMMISSION']['code'], 'order_sn' => 0, 'tripartite' => 0, 'type_shop' => 0, 'mer_id' => 0, 'source' => 0, 'order_type' => 1, 'is_red_brokerage' => 0, 'gzc' => 3, 'take_time' => time(), 'district_id' => '', 'street_id' => '', 'month' => '', ]; Db::name('user_bill')->insert($bill); $userDao->updateByUserId($userId, ['balance' => ['inc', $userReward]]); } // private function dividendLog($startTime, $endTime, $performance, $allocated, $starList, $isTest, $remark) // { // // 组装日志信息 // /** @var DividendLogEntity $dividendLogEntity */ // $dividendLogEntity = DividendLogEntity::newInstance(); // $dividendLogEntity->setType(DividendLogEnum::TYPE['SharedProsperityPartnerProfit']['code']) // ->setStartTime($startTime) // ->setEndTime($endTime) // ->setPerformance($performance) // ->setAbatement(json_encode([])) // ->setAllocated($allocated) // ->setRule(json_encode($starList)) // ->setIsTest($isTest) // ->setRemark($remark) // ->setExpected(); // } /** * @param $data * @return true * @throws \think\db\exception\DataNotFoundException * @throws \think\db\exception\DbException * @throws \think\db\exception\ModelNotFoundException * @author 史晨 * @date 2026/2/10 15:22 * 感恩奖 */ public function thank($data) { // 获取时间范围内订单 $start = $data['startTime']; $end = $data['endTime']; // 获取收入 /** @var UserBillRepository $userBillRepository */ $userBillRepository = app()->make(UserBillRepository::class); $billList = $userBillRepository->getListForSharedProsperityThank($start, $end); if (empty($billList)) { throw new \Exception('没有佣金记录,无需处理'); } // /** @var SharedProsperityRewardRecordRepository $rewardRecordRepository */ // $rewardRecordRepository = app()->make(SharedProsperityRewardRecordRepository::class); // $rewardList = $rewardRecordRepository->getListByTime($start, $end, self::REWARD_TYPE_PV); // if (empty($rewardList)) { // throw new \Exception('没有订单'); // } // user_id分区求和 [id]=>[number] $groupedResult = array_reduce($billList, function ($carry, $item) { $userId = $item['uid']; $number = floatval($item['number']); if (!isset($carry[$userId])) { $carry[$userId] = 0; } $carry[$userId] += $number; return $carry; }, []); if (empty($groupedResult)) { throw new \Exception('分组求和错误'); } /** @var SharedProsperityUserRepository $userRepository */ $userRepository = app()->make(SharedProsperityUserRepository::class); /** @var SharedProsperityPointLogDao $balanceDao */ $logDao = app()->make(SharedProsperityPointLogDao::class); DB::startTrans(); try { foreach ($groupedResult as $key => $value) { // 获取感恩奖比例 $radio = CommonEnum::ORDER_EARNING_ALLOCATION['SharedProsperity']['Thank']['code']; // 计算积分 $points = floor($value * $radio * 100) / 100; // 获取上级 $userData = $userRepository->getSharedProsperityUserEntityByUserId($key); if (empty($userData->getUserId())) { Log::info('共富感恩奖发放:' . $key . '不是共富会员,不发放感恩奖'); continue; } $parentId = $userData->getParentId(); if ($parentId == 0) { Log::info('共富感恩奖发放:' . $key . '的上级是0,不发放感恩奖'); continue; } // 给上级发积分,记录日志 if ($parentId > 0) { if ($points <= 0) { Log::info('共富感恩奖发放:' . $key . '的收入是' . $value . ',奖励占比是' . $radio . ',积分是' . $value * $radio . '所以' . $parentId . '发放感恩奖'); continue; } $parentData = $userRepository->getSharedProsperityUserEntityByUserId($parentId); // 记录日志 $logDao->create([ 'user_id' => $parentId, 'total' => $value, 'radio' => $radio, 'old' => $parentData->getPoints(), 'number' => $points, 'after' => $parentData->getPoints() + $points ]); // 发放积分 $userRepository->updateByUserId($parentId, ['points' => ['inc', $points]]); } } Db::commit(); return true; } catch (\Exception $e) { DB::rollback(); throw new \Exception($e->getMessage()); } } /** * @param $data * @return array 分配明细数据 * @throws \Exception * @author 史晨 * @date 2026/2/14 10:54 * 共富奖(团队平均分配) */ public function group($data) { // 获取时间范围内订单 $start = $data['startTime']; $end = $data['endTime']; $isTest = $data['isTest'] ?? false; // 是否测试模式(不实际发放) // 获取pv /** @var SharedProsperityRewardRecordRepository $rewardRecordRepository */ $rewardRecordRepository = app()->make(SharedProsperityRewardRecordRepository::class); $orderList = $rewardRecordRepository->getListByTime($start, $end, self::REWARD_TYPE_PV); if (empty($orderList)) { throw new \Exception('没有订单'); } // 计算总PV $totalPv = array_sum(array_column($orderList, 'number')); $totalPv = 100; // 可分配总额 = 总PV * 15% $totalAllocatable = floor($totalPv * 0.15 * 100) / 100; // 获取团队配置 /** @var SharedProsperityGroupDao $groupDao */ $groupDao = app()->make(SharedProsperityGroupDao::class); $groups = $groupDao->getAllGroups(); // 获取所有团队等级 if (empty($groups)) { throw new \Exception('没有团队配置'); } // 按 group_id 映射比例 $groupRatios = []; foreach ($groups as $group) { $groupRatios[$group['id']] = [ 'name' => $group['name'], 'radio' => $group['radio'], // 百分比,例如 8.00 'max' => $group['max'] ]; } // 获取团队成员 /** @var SharedProsperityGroupUserDao $groupUserDao */ $groupUserDao = app()->make(SharedProsperityGroupUserDao::class); $groupUsers = $groupUserDao->getValidUsersGroupByGroup(); // 获取有效用户按团队分组 if (empty($groupUsers)) { throw new \Exception('没有团队成员'); } /** @var SharedProsperityBalanceLogDao $balanceDao */ $balanceDao = app()->make(SharedProsperityBalanceLogDao::class); /** @var SharedProsperityUserDao $userDao */ $userDao = app()->make(SharedProsperityUserDao::class); // 分配明细数据收集 $distributionDetails = []; // 如果是测试模式,不开启事务,只计算不实际发放 if ($isTest === 'false') { Db::startTrans(); } try { foreach ($groupRatios as $groupId => $groupInfo) { $ratio = $groupInfo['radio']; // 百分比 // 该团队等级总分配金额 = 总PV * ratio / 100 $groupTotal = floor($totalPv * $ratio / 100 * 100) / 100; // 获取该团队等级下的有效用户 $userIds = $groupUsers[$groupId] ?? []; if (empty($userIds)) { // 没有成员,跳过分配 continue; } $userCount = count($userIds); // 平均分配 $eachReward = floor(($groupTotal / $userCount) * 100) / 100; // 获取用户信息 $userInfos = $userDao->getSharedProsperityUserEntityListByUserIdList($userIds); if (empty($userInfos)) { continue; } foreach ($userInfos as $userInfo) { $userReward = $eachReward; // 收集分配明细 $distributionDetails[] = [ 'user_id' => $userInfo->getUserId(), 'group_id' => $groupId, 'group_name' => $groupInfo['name'], 'total_allocation' => $groupTotal, 'user_count' => $userCount, 'ratio' => $ratio, 'actual_amount' => $userReward, ]; $this->distributeGroupReward($userInfo, $userReward, $ratio, $groupTotal, $balanceDao, $userDao, $groupId, $isTest); } } if ($isTest === 'false') { // 记录分红日志 // $this->dividendLog($start, $end, $totalPv, $totalAllocatable, $groupRatios, $isTest, '共富体系团队奖'); Db::commit(); } // 返回分配明细数据 return [ 'success' => true, 'is_test' => $isTest, 'total_pv' => $totalPv, 'allocatable_profit' => $totalAllocatable, 'distribution_details' => $distributionDetails, 'group_ratios' => $groupRatios, ]; } catch (\Exception $e) { if ($isTest === 'false') { Db::rollback(); } throw new \Exception($e->getMessage()); } } /** * 分发团队奖励(记录日志和更新余额) * @param $userInfo * @param $userReward * @param $radio * @param $groupTotal * @param $balanceDao * @param $userDao * @param $isTest * @return void */ private function distributeGroupReward($userInfo, $userReward, $radio, $groupTotal, $balanceDao, $userDao, $groupId, $isTest) { $userId = $userInfo->getUserId(); // 如果是测试模式,只记录日志不实际执行数据库操作 if ($isTest === 'true') { Log::info("测试模式:用户 {$userId} 应发放团队奖励 {$userReward},比例 {$radio},团队总分红 {$groupTotal}"); return; } $balanceDao->create([ 'user_id' => $userId, 'level' => $groupId, // 共富团队等级 'radio' => $radio, 'total_profit' => $groupTotal, 'old' => $userInfo->getBalance(), 'number' => $userReward, 'after' => $userInfo->getBalance() + $userReward, 'type' => SharedProsperityBalanceLogEnum::TYPE['GROUP']['code'] ]); $bill = [ 'uid' => $userId, 'link_id' => 0, 'pm' => 1, 'title' => '共富体系团队奖', 'category' => 'now_money', 'type' => 'commission', 'number' => $userReward, 'balance' => 0, 'mark' => '共富体系团队奖明细入账', 'create_time' => date('Y-m-d H:i:s'), 'status' => 1, 'commission_type' => CommonEnum::COMMISSION_TYPE['SHARED_PROSPERITY_GROUP_COMMISSION']['code'], 'order_sn' => 0, 'tripartite' => 0, 'type_shop' => 0, 'mer_id' => 0, 'source' => 0, 'order_type' => 1, 'is_red_brokerage' => 0, 'gzc' => 3, 'take_time' => time(), 'district_id' => '', 'street_id' => '', 'month' => '', ]; Db::name('user_bill')->insert($bill); $userDao->updateByUserId($userId, ['balance' => ['inc', $userReward]]); } }