diff --git a/src/repositories/folder.repository.js b/src/repositories/folder.repository.js index 1d973e6..79a1a34 100644 --- a/src/repositories/folder.repository.js +++ b/src/repositories/folder.repository.js @@ -8,7 +8,7 @@ class FolderRepository { }); } - // 유저의 폴더 개수 조회 (기본 폴더 포함됨) + // 유저의 폴더 개수 조회 (기본 폴더 포함) async countByUserId(userId) { return await prisma.folder.count({ where: { userId: userId }, @@ -25,6 +25,16 @@ class FolderRepository { }); } + // 유저가 특정 이름의 폴더를 이미 가지고 있는지 조회 + async findByUserAndTitle(userId, folderTitle) { + return await prisma.folder.findFirst({ + where: { + userId: userId, + folderTitle: folderTitle, + }, + }); + } + // 1. 폴더 생성 async addFolder(userId, data) { const newFolder = await prisma.folder.create({ diff --git a/src/services/folder.service.js b/src/services/folder.service.js index cf8b041..21da10c 100644 --- a/src/services/folder.service.js +++ b/src/services/folder.service.js @@ -13,6 +13,11 @@ class FolderService { const folderData = FolderDto.bodyToFolderDto(body); + const duplicateNameFolder = await folderRepository.findByUserAndTitle(userId, folderData.folderTitle); + if (duplicateNameFolder) { + throw new BadRequestError("DUPLICATE_NAME", "이미 존재하는 폴더 이름입니다."); + } + const duplicateColorFolder = await folderRepository.findByUserAndColor(userId, folderData.color); if (duplicateColorFolder) { throw new BadRequestError("DUPLICATE_COLOR", "이미 사용 중인 색상입니다. 다른 색상을 선택해주세요."); @@ -39,6 +44,14 @@ class FolderService { return FolderDto.responseFromFolder(folder); } + // 이름이 변경되는 경우, 중복 이름 확인 + if (updateData.folderTitle && updateData.folderTitle !== folder.folderTitle) { + const duplicateNameFolder = await folderRepository.findByUserAndTitle(userId, updateData.folderTitle); + if (duplicateNameFolder) { + throw new BadRequestError("DUPLICATE_NAME", "이미 존재하는 폴더 이름입니다."); + } + } + // (4) 색상이 변경되는 경우에만 중복 체크 if (updateData.color && updateData.color !== folder.color) { const duplicateColorFolder = await folderRepository.findByUserAndColor(userId, updateData.color); diff --git a/src/swagger/swagger.yml b/src/swagger/swagger.yml index 6b58efe..a6148a2 100644 --- a/src/swagger/swagger.yml +++ b/src/swagger/swagger.yml @@ -2609,7 +2609,7 @@ paths: resultType: "FAIL" code: 400 errorCode: "INVALID_NICKNAME" - reason: "닉네임은 최대 10자까지만 가능합니다." + reason: "닉네임은 최대 100자까지만 가능합니다." data: null '401': description: | @@ -2713,6 +2713,7 @@ paths: - INVALID_COLOR: 색상 형식이 올바르지 않음 (#123456 형식 아님). - MAX_FOLDER_LIMIT: 폴더 개수 5개 초과. - DUPLICATE_COLOR: 이미 사용 중인 색상. + - DUPLICATE_NAME: 이미 사용 중인 폴더 이름. content: application/json: schema: @@ -2720,8 +2721,8 @@ paths: example: resultType: "FAIL" code: 400 - errorCode: "BAD_REQUEST | INVALID_INPUT_VALUE | INVALID_FOLDER_TITLE | COLOR_REQUIRED | INVALID_COLOR | MAX_FOLDER_LIMIT | DUPLICATE_COLOR" - reason: "인증 토큰이 형식에 맞지 않습니다. | 폴더 이름은 필수입니다. | 폴더 이름은 최대 11자까지만 가능합니다. | 색상은 필수 입력 사항입니다. | 색상은 #을 포함한 7자리 Hex 코드여야 합니다. | 폴더는 최대 5개까지만 생성할 수 있습니다. | 이미 사용 중인 색상입니다." + errorCode: "BAD_REQUEST | INVALID_INPUT_VALUE | INVALID_FOLDER_TITLE | COLOR_REQUIRED | INVALID_COLOR | MAX_FOLDER_LIMIT | DUPLICATE_COLOR | DUPLICATE_NAME" + reason: "인증 토큰이 형식에 맞지 않습니다. | 폴더 이름은 필수입니다. | 폴더 이름은 최대 11자까지만 가능합니다. | 색상은 필수 입력 사항입니다. | 색상은 #을 포함한 7자리 Hex 코드여야 합니다. | 폴더는 최대 5개까지만 생성할 수 있습니다. | 이미 사용 중인 색상입니다. | 이미 존재하는 폴더 이름입니다." data: null '401': description: | @@ -2815,6 +2816,7 @@ paths: - INVALID_COLOR: 색상 형식이 올바르지 않음. - DUPLICATE_COLOR: 이미 사용 중인 색상으로 변경 시도. - PROTECTED_FOLDER: '팀' 폴더를 수정하려고 시도함. + - DUPLICATE_NAME: 이미 사용 중인 폴더 이름으로 변경 시도. content: application/json: schema: @@ -2822,8 +2824,8 @@ paths: example: resultType: "FAIL" code: 400 - errorCode: "BAD_REQUEST | INVALID_FOLDER_TITLE | INVALID_COLOR | DUPLICATE_COLOR | PROTECTED_FOLDER" - reason: "인증 토큰이 형식에 맞지 않습니다. | 폴더 이름은 최대 11자까지만 가능합니다. | 색상 형식이 올바르지 않습니다. | 이미 사용 중인 색상입니다. | '팀' 폴더는 수정할 수 없습니다." + errorCode: "BAD_REQUEST | INVALID_FOLDER_TITLE | INVALID_COLOR | DUPLICATE_COLOR | PROTECTED_FOLDER | DUPLICATE_NAME" + reason: "인증 토큰이 형식에 맞지 않습니다. | 폴더 이름은 최대 11자까지만 가능합니다. | 색상 형식이 올바르지 않습니다. | 이미 사용 중인 색상입니다. | '팀' 폴더는 수정할 수 없습니다. | 이미 존재하는 폴더 이름입니다." data: null '401': description: |