diff --git a/fishing/apps/api/src/tournaments/day-code.service.spec.ts b/fishing/apps/api/src/tournaments/day-code.service.spec.ts index 1429328..10ccaf0 100644 --- a/fishing/apps/api/src/tournaments/day-code.service.spec.ts +++ b/fishing/apps/api/src/tournaments/day-code.service.spec.ts @@ -59,6 +59,45 @@ describe('TournamentsService 일일 코드', () => { expect(prisma.tournamentEntry.findUnique).not.toHaveBeenCalled(); }); + it('공개 조회는 코드가 있는지만 알려 준다', async () => { + prisma.tournamentDayCode.findUnique.mockResolvedValue({ code: 'LAKE1' }); + + const result = await service.getTodayDayCode('tour-1', now); + + expect(result).toEqual({ codeDate: '2026-10-20', hasCode: true }); + expect(JSON.stringify(result)).not.toContain('LAKE1'); + }); + + it('코드가 없으면 공개 조회도 값 없이 없다고 한다', async () => { + prisma.tournamentDayCode.findUnique.mockResolvedValue(null); + + await expect(service.getTodayDayCode('tour-1', now)).resolves.toEqual({ + codeDate: '2026-10-20', + hasCode: false, + }); + }); + + it('대회 운영자는 오늘 코드를 확인한다', async () => { + prisma.user.findUnique.mockResolvedValue({ id: 'org-1', role: 'organizer' }); + prisma.tournament.findUnique.mockResolvedValue({ id: 'tour-1', organizerId: 'org-1' }); + prisma.tournamentDayCode.findUnique.mockResolvedValue({ code: 'LAKE1' }); + + await expect(service.getManagedDayCode('org-1', 'tour-1', now)).resolves.toEqual({ + codeDate: '2026-10-20', + code: 'LAKE1', + }); + }); + + it('참가자는 오늘 코드를 조회하지 못한다', async () => { + prisma.user.findUnique.mockResolvedValue({ id: 'user-1', role: 'user' }); + prisma.tournament.findUnique.mockResolvedValue({ id: 'tour-1', organizerId: 'org-1' }); + + await expect(service.getManagedDayCode('user-1', 'tour-1', now)).rejects.toBeInstanceOf( + ForbiddenException, + ); + expect(prisma.tournamentDayCode.findUnique).not.toHaveBeenCalled(); + }); + it('다른 코드는 거절한다', async () => { prisma.tournamentEntry.findUnique.mockResolvedValue({ paymentStatus: 'paid' }); prisma.tournamentDayCode.findUnique.mockResolvedValue({ code: 'LAKE1' }); diff --git a/fishing/apps/api/src/tournaments/tournaments.controller.ts b/fishing/apps/api/src/tournaments/tournaments.controller.ts index dae86ca..491e3e3 100644 --- a/fishing/apps/api/src/tournaments/tournaments.controller.ts +++ b/fishing/apps/api/src/tournaments/tournaments.controller.ts @@ -125,6 +125,15 @@ export class TournamentsController { return { success: true, data: result }; } + @Get('organized/:id/day-code') + @UseGuards(JwtAuthGuard) + @ApiBearerAuth() + @ApiOperation({ summary: '운영 중인 대회의 오늘 코드 확인' }) + async getManagedDayCode(@Param('id') id: string, @CurrentUser() user: any) { + const result = await this.tournamentsService.getManagedDayCode(user.id, id); + return { success: true, data: result }; + } + @Get('organized/:id/export') @UseGuards(JwtAuthGuard) @ApiBearerAuth() @@ -291,7 +300,7 @@ export class TournamentsController { } @Get(':id/day-code') - @ApiOperation({ summary: '오늘(서울) 대회 코드 조회' }) + @ApiOperation({ summary: '오늘(서울) 대회 코드 등록 여부. 코드 값은 반환하지 않음' }) async getDayCode(@Param('id') id: string) { const result = await this.tournamentsService.getTodayDayCode(id); return { success: true, data: result }; diff --git a/fishing/apps/api/src/tournaments/tournaments.service.ts b/fishing/apps/api/src/tournaments/tournaments.service.ts index e483c39..14373c6 100644 --- a/fishing/apps/api/src/tournaments/tournaments.service.ts +++ b/fishing/apps/api/src/tournaments/tournaments.service.ts @@ -159,6 +159,16 @@ export class TournamentsService { } async getTodayDayCode(tournamentId: string, now = new Date()) { + const row = await this.findTodayDayCode(tournamentId, now); + return { codeDate: row.codeDate, hasCode: row.code !== null }; + } + + async getManagedDayCode(actorId: string, tournamentId: string, now = new Date()) { + await this.assertManagesTournament(actorId, tournamentId); + return this.findTodayDayCode(tournamentId, now); + } + + private async findTodayDayCode(tournamentId: string, now: Date) { const tournament = await this.prisma.tournament.findUnique({ where: { id: tournamentId } }); if (!tournament) throw new NotFoundException('대회를 찾을 수 없습니다.'); const codeDate = seoulDateKey(now);