Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions fishing/apps/api/src/tournaments/day-code.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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' });
Expand Down
11 changes: 10 additions & 1 deletion fishing/apps/api/src/tournaments/tournaments.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down Expand Up @@ -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 };
Expand Down
10 changes: 10 additions & 0 deletions fishing/apps/api/src/tournaments/tournaments.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Loading