import { Controller, Get, Param, Logger, Inject, NotFoundException } from '@nestjs/common'; import { ApiTags, ApiOperation, ApiParam, ApiResponse } from '@nestjs/swagger'; import { REFERRAL_RELATIONSHIP_REPOSITORY, IReferralRelationshipRepository, TEAM_STATISTICS_REPOSITORY, ITeamStatisticsRepository, } from '../../domain'; /** * 内部推荐链API - 供其他微服务调用 * 无需JWT认证(服务间内部通信) */ @ApiTags('Internal Referral Chain API') @Controller('internal/referral-chain') export class InternalReferralChainController { private readonly logger = new Logger(InternalReferralChainController.name); constructor( @Inject(REFERRAL_RELATIONSHIP_REPOSITORY) private readonly referralRepo: IReferralRelationshipRepository, @Inject(TEAM_STATISTICS_REPOSITORY) private readonly teamStatsRepo: ITeamStatisticsRepository, ) {} /** * 获取用户的祖先链(从直接推荐人到根节点) */ @Get(':accountSequence') @ApiOperation({ summary: '获取用户推荐链(内部API)' }) @ApiParam({ name: 'accountSequence', description: '账户序列号' }) @ApiResponse({ status: 200, description: '推荐链数据', schema: { type: 'object', properties: { accountSequence: { type: 'string', description: '格式: D + YYMMDD + 5位序号' }, userId: { type: 'string' }, ancestorPath: { type: 'array', items: { type: 'string' }, description: '祖先链(从直接推荐人到根节点的accountSequence列表)', }, referrerId: { type: 'string', nullable: true }, }, }, }) async getReferralChain(@Param('accountSequence') accountSequence: string) { this.logger.debug(`[INTERNAL] getReferralChain: accountSequence=${accountSequence}`); const relationship = await this.referralRepo.findByAccountSequence(accountSequence); if (!relationship) { this.logger.debug(`[INTERNAL] No referral found for accountSequence: ${accountSequence}`); // 返回空的祖先链而不是抛出错误 return { accountSequence: accountSequence, userId: null, ancestorPath: [], referrerId: null, }; } // referralChain 存储的是 userId (bigint),需要转换为 accountSequence // 因为 authorization-service 使用 accountSequence 来查询授权记录 const ancestorUserIds = relationship.referralChain; const ancestorPath: string[] = []; for (const ancestorUserId of ancestorUserIds) { const ancestorRelationship = await this.referralRepo.findByUserId(ancestorUserId); if (ancestorRelationship) { ancestorPath.push(ancestorRelationship.accountSequence); } else { this.logger.warn(`[INTERNAL] Ancestor userId ${ancestorUserId} not found`); } } this.logger.debug(`[INTERNAL] getReferralChain result: ${ancestorPath.length} ancestors`); return { accountSequence: relationship.accountSequence, userId: relationship.userId.toString(), ancestorPath, referrerId: relationship.referrerId?.toString() ?? null, }; } /** * 批量获取用户的祖先链 */ @Get('batch/:accountSequences') @ApiOperation({ summary: '批量获取用户推荐链(内部API)' }) @ApiParam({ name: 'accountSequences', description: '账户序列号列表,逗号分隔' }) @ApiResponse({ status: 200, description: '批量推荐链数据', }) async getBatchReferralChains(@Param('accountSequences') accountSequences: string) { const sequences = accountSequences.split(',').map((s) => s.trim()); this.logger.debug(`[INTERNAL] getBatchReferralChains: ${sequences.length} accounts`); const results: Record = {}; for (const seq of sequences) { const relationship = await this.referralRepo.findByAccountSequence(seq); if (relationship) { // 转换 userId 为 accountSequence const ancestorPath: string[] = []; for (const ancestorUserId of relationship.referralChain) { const ancestorRelationship = await this.referralRepo.findByUserId(ancestorUserId); if (ancestorRelationship) { ancestorPath.push(ancestorRelationship.accountSequence); } } results[seq] = { userId: relationship.userId.toString(), ancestorPath, referrerId: relationship.referrerId?.toString() ?? null, }; } else { results[seq] = { userId: null, ancestorPath: [], referrerId: null, }; } } return results; } /** * 获取用户的团队成员(下级用户)的accountSequence列表 * 用于查找下级社区 */ @Get(':accountSequence/team-members') @ApiOperation({ summary: '获取团队成员accountSequence列表(内部API)' }) @ApiParam({ name: 'accountSequence', description: '账户序列号' }) @ApiResponse({ status: 200, description: '团队成员列表', schema: { type: 'object', properties: { accountSequence: { type: 'string', description: '格式: D + YYMMDD + 5位序号' }, teamMembers: { type: 'array', items: { type: 'string' }, description: '团队成员accountSequence列表(直接和间接下级)', }, }, }, }) async getTeamMembers(@Param('accountSequence') accountSequence: string) { this.logger.debug(`[INTERNAL] getTeamMembers: accountSequence=${accountSequence}`); const relationship = await this.referralRepo.findByAccountSequence(accountSequence); if (!relationship) { return { accountSequence: accountSequence, teamMembers: [], }; } // 获取所有直推用户 const directReferrals = await this.referralRepo.findDirectReferrals(relationship.userId); // 递归获取所有下级成员的accountSequence const teamMembers: string[] = []; const queue = [...directReferrals]; while (queue.length > 0) { const current = queue.shift()!; teamMembers.push(current.accountSequence); // 获取当前用户的直推 const subReferrals = await this.referralRepo.findDirectReferrals(current.userId); queue.push(...subReferrals); } return { accountSequence: accountSequence, teamMembers, }; } /** * 获取用户的完整团队统计(内部API) * 用于用户详情页展示 */ @Get(':accountSequence/profile-stats') @ApiOperation({ summary: '获取用户团队统计(内部API)' }) @ApiParam({ name: 'accountSequence', description: '账户序列号' }) @ApiResponse({ status: 200, description: '用户团队统计', schema: { type: 'object', properties: { accountSequence: { type: 'string' }, directReferralCount: { type: 'number', description: '直推人数' }, umbrellaUserCount: { type: 'number', description: '伞下用户数(团队总人数)' }, personalPlantingCount: { type: 'number', description: '个人认种数量' }, teamPlantingCount: { type: 'number', description: '团队认种数量' }, }, }, }) async getProfileStats(@Param('accountSequence') accountSequence: string) { this.logger.debug(`[INTERNAL] getProfileStats: accountSequence=${accountSequence}`); const relationship = await this.referralRepo.findByAccountSequence(accountSequence); if (!relationship) { return { accountSequence: accountSequence, directReferralCount: 0, umbrellaUserCount: 0, personalPlantingCount: 0, teamPlantingCount: 0, }; } // 获取直推人数 const directReferrals = await this.referralRepo.findDirectReferrals(relationship.userId); const directReferralCount = directReferrals.length; // 获取伞下用户数(递归获取所有下级) let umbrellaUserCount = 0; const queue = [...directReferrals]; while (queue.length > 0) { umbrellaUserCount++; const current = queue.shift()!; const subReferrals = await this.referralRepo.findDirectReferrals(current.userId); queue.push(...subReferrals); } // 获取团队统计 const teamStats = await this.teamStatsRepo.findByUserId(relationship.userId); const personalPlantingCount = teamStats?.personalPlantingCount ?? 0; const teamPlantingCount = teamStats?.teamPlantingCount ?? 0; return { accountSequence: accountSequence, directReferralCount, umbrellaUserCount, personalPlantingCount, teamPlantingCount, }; } }