import { Controller, Get, Param, Logger, Inject } from '@nestjs/common'; import { ApiTags, ApiOperation, ApiParam, ApiResponse } from '@nestjs/swagger'; import { TEAM_STATISTICS_REPOSITORY, ITeamStatisticsRepository, } from '../../domain'; /** * 内部团队统计API - 供其他微服务调用 * 无需JWT认证(服务间内部通信) */ @ApiTags('Internal Team Statistics API') @Controller('internal/team-statistics') export class InternalTeamStatisticsController { private readonly logger = new Logger(InternalTeamStatisticsController.name); constructor( @Inject(TEAM_STATISTICS_REPOSITORY) private readonly teamStatsRepo: ITeamStatisticsRepository, ) {} @Get('user/:userId') @ApiOperation({ summary: '根据 userId 获取团队统计(内部API)' }) @ApiParam({ name: 'userId', description: '用户ID (bigint)' }) @ApiResponse({ status: 200, description: '团队统计数据', schema: { type: 'object', properties: { userId: { type: 'string' }, accountSequence: { type: 'string' }, totalTeamPlantingCount: { type: 'number' }, selfPlantingCount: { type: 'number' }, provinceCityDistribution: { type: 'object' }, }, }, }) async getStatsByUserId(@Param('userId') userId: string) { this.logger.debug(`[INTERNAL] getStatsByUserId: ${userId}`); try { const stats = await this.teamStatsRepo.findByUserId(BigInt(userId)); if (!stats) { this.logger.debug(`[INTERNAL] No stats found for userId: ${userId}`); return null; } const distribution = stats.provinceCityDistribution; return { userId: stats.userId.toString(), accountSequence: '0', // userId 查询时无法获取 accountSequence totalTeamPlantingCount: stats.teamPlantingCount, // 团队总认种(不含自己,只有下级) selfPlantingCount: stats.personalPlantingCount, // 自己的认种数 provinceCityDistribution: distribution.toJson(), }; } catch (error) { this.logger.error(`[INTERNAL] Error getting stats for userId ${userId}:`, error); throw error; } } @Get('account/:accountSequence') @ApiOperation({ summary: '根据 accountSequence 获取团队统计(内部API)' }) @ApiParam({ name: 'accountSequence', description: '账户序列号' }) @ApiResponse({ status: 200, description: '团队统计数据', schema: { type: 'object', properties: { userId: { type: 'string' }, accountSequence: { type: 'string' }, totalTeamPlantingCount: { type: 'number' }, selfPlantingCount: { type: 'number' }, provinceCityDistribution: { type: 'object' }, }, }, }) async getStatsByAccountSequence(@Param('accountSequence') accountSequence: string) { this.logger.debug(`[INTERNAL] getStatsByAccountSequence: ${accountSequence}`); try { // 需要先通过 accountSequence 查找 userId // 这里需要扩展 repository 方法 const stats = await this.findByAccountSequence(accountSequence); if (!stats) { this.logger.debug(`[INTERNAL] No stats found for accountSequence: ${accountSequence}`); return null; } const distribution = stats.provinceCityDistribution; return { userId: stats.userId.toString(), accountSequence: accountSequence, totalTeamPlantingCount: stats.teamPlantingCount, // 团队总认种(不含自己,只有下级) selfPlantingCount: stats.personalPlantingCount, // 自己的认种数 provinceCityDistribution: distribution.toJson(), }; } catch (error) { this.logger.error(`[INTERNAL] Error getting stats for accountSequence ${accountSequence}:`, error); throw error; } } /** * 通过 accountSequence 查找团队统计 * 需要先查询 referral_relationships 获取 userId,再查询 team_statistics */ private async findByAccountSequence(accountSequence: string) { // 使用 repository 的 findByUserId,但这里需要 accountSequence 到 userId 的映射 // 由于当前架构 accountSequence 和 userId 不一定相等,需要通过 referral_relationships 表查询 // 暂时尝试将 accountSequence 字符串转换为 BigInt 作为 userId 查询 // 注意:这里的实现取决于业务逻辑,可能需要通过 referral_relationships 表查询 try { // 尝试从 accountSequence 中提取数字部分或直接使用 // 这是临时方案,实际应该通过 referral_relationships 查询 return this.teamStatsRepo.findByUserId(BigInt(accountSequence.replace(/\D/g, ''))); } catch { return null; } } }