Skip to content

Feature/#93 엑셀 파일로 팀 추가#104

Open
pykido wants to merge 13 commits intodevelopfrom
Feature/#93-엑셀_파일로_팀_추가

Hidden character warning

The head ref may contain hidden characters: "Feature/#93-\uc5d1\uc140_\ud30c\uc77c\ub85c_\ud300_\ucd94\uac00"
Open

Feature/#93 엑셀 파일로 팀 추가#104
pykido wants to merge 13 commits intodevelopfrom
Feature/#93-엑셀_파일로_팀_추가

Conversation

@pykido
Copy link
Copy Markdown
Contributor

@pykido pykido commented Mar 21, 2026

🔥 연관된 이슈

close: #93

📜 작업 내용

  • 관리자페이지에서, 엑셀 파일을 통한 팀 일괄 등록을 할 수 있는 API를 구현하였습니다.
  • 태영님과 함께 정리한 팀 일괄 등록에 대한 서비스 로직은 여기를 클릭하여 확인하실 수 있습니다.
  • 템플릿 파일 또한 여기를 클릭하여 확인할 수 있습니다.
  • 구현된 파일들에 대해 간단하게 설명하자면 다음과 같습니다.
    • ExcelTeamParser : 엑셀 파일(.xlsx)을 파싱하여 TeamBulkRowDto 리스트로 변환합니다. 데이터는 5행부터 읽으며, 팀원 정보는 콤마(,)로 구분합니다.
    • ExcelTeamValidator: 파일 검증(null/빈 파일/크기/형식)과 데이터 검증(필수 필드, 학번 형식, 이메일 도메인, 파일 내 중복, DB 중복)을 담당합니다.
    • ContestCommandService.bulkUploadTeams: 파싱 → 검증 → 저장 전체 흐름을 처리합니다. 모든 팀이 유효성 검사를 통과해야만 저장되며, 하나라도 실패하면 전체가 등록되지 않습니다.
    • Member.isFake: 엑셀로 등록 시 아직 실제 회원가입을 하지 않은 학생을 가짜 회원으로 생성합니다. 이후 일반/소셜 회원가입 시 실제 회원으로 전환됩니다.

💬 리뷰 요구사항

1. ExceptionAdvice에 핸들러 추가한 이유

  • 팀 일괄 등록 시 여러 행에서 동시에 에러가 발생할 수 있어서, 기존 BaseException 핸들러(단일 메시지 응답)로는 처리가 불가능합니다.
  • 따라서 TeamExceptionList<TeamBulkError> bulkErrors 필드를 추가하고, ExceptionAdvice에서 bulkErrors가 있으면 에러 목록을 담은 TeamBulkErrorResponse로, 없으면 기존 ExceptionResponse로 응답하도록 분기 처리했습니다.

2. 가짜회원 로직 간단 설명

  • 엑셀로 팀을 등록하면 아직 회원가입하지 않은 학생은 isFake=true인 가짜 회원으로 생성됩니다.
  • 일반 회원가입 시: 이메일로 가짜 회원을 조회 → 존재하면 convertFakeToGeneral()로 실제 회원으로 전환합니다.
  • 구글 소셜 로그인 시: 이메일로 가짜 회원을 조회 → 존재하면 convertFakeToSocial()로 소셜 회원으로 전환합니다. 이때 엑셀에서 등록된 학번은 유지됩니다.
  • 자세한 케이스별 정리는 위 노션 링크를 참고해주세요.

✨ 기타

  • 리팩토링을 굉장히 많이 한 거 같은데 여전히 많이 복잡해보이네요 ㅠㅠ

@pykido pykido self-assigned this Mar 21, 2026
@pykido pykido added the ⭐️ 기능 구현 새로운 기능을 구현 label Mar 21, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

관리자 페이지에서 엑셀(.xlsx) 업로드로 대회 팀을 일괄 등록할 수 있도록, 업로드 API/서비스 로직과 파싱·검증 유틸, 가짜 회원 전환 로직 및 문서/테스트를 추가한 PR입니다.

Changes:

  • 엑셀 파일 업로드 기반 팀 일괄 등록 API(POST /contests/{contestId}/teams/bulk) 및 응답 DTO 추가
  • 엑셀 파서/검증기(ExcelTeamParser, ExcelTeamValidator)와 서비스 저장 플로우 구현
  • 엑셀 등록용 가짜 회원(is_fake) 및 일반/소셜 가입 시 전환 로직 추가, 문서(RestDocs/Asciidoc)와 테스트 보강

Reviewed changes

Copilot reviewed 22 out of 23 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
src/test/java/com/opus/opus/restdocs/docs/ContestApiDocsTest.java 팀 일괄 업로드 API 성공/실패 RestDocs 스니펫 추가
src/test/java/com/opus/opus/contest/ContestExcelFixture.java 테스트용 xlsx 생성 fixture 추가(POI 사용)
src/test/java/com/opus/opus/contest/application/ContestCommandServiceTest.java bulkUploadTeams 통합 테스트 케이스 추가
src/main/resources/schema.sql member 테이블에 is_fake 추가 및 체크 제약 조건 조정
src/main/java/com/opus/opus/modules/team/exception/TeamExceptionType.java 벌크 검증/엑셀 읽기 실패 예외 타입 추가
src/main/java/com/opus/opus/modules/team/exception/TeamException.java 벌크 에러 리스트를 담는 예외 확장
src/main/java/com/opus/opus/modules/team/application/convenience/TeamMemberConvenience.java 팀 멤버 저장 convenience 메서드 추가
src/main/java/com/opus/opus/modules/team/application/convenience/TeamConvenience.java 팀 저장 convenience 메서드 추가
src/main/java/com/opus/opus/modules/member/domain/Member.java isFake 필드 및 가짜→일반/소셜 전환 메서드 추가
src/main/java/com/opus/opus/modules/member/application/MemberCommandService.java 일반 회원가입 시 가짜 회원이면 전환 처리
src/main/java/com/opus/opus/modules/member/application/convenience/MemberConvenience.java 이메일 기반 가짜 회원 생성/조회 메서드 추가
src/main/java/com/opus/opus/modules/contest/exception/ContestExceptionType.java 파일/벌크 관련 예외 타입 추가
src/main/java/com/opus/opus/modules/contest/application/dto/response/TeamBulkUploadResponse.java 벌크 업로드 성공 응답 DTO 추가
src/main/java/com/opus/opus/modules/contest/application/dto/response/TeamBulkErrorResponse.java 벌크 업로드 유효성 실패 응답 DTO 추가
src/main/java/com/opus/opus/modules/contest/application/dto/request/TeamBulkRowDto.java 엑셀 파싱 결과 row DTO 추가
src/main/java/com/opus/opus/modules/contest/application/ContestCommandService.java bulkUploadTeams 파싱→검증→저장 플로우 구현
src/main/java/com/opus/opus/modules/contest/api/ContestController.java 팀 벌크 업로드 엔드포인트 추가(관리자 전용)
src/main/java/com/opus/opus/global/util/ExcelTeamValidator.java 파일/데이터/중복(DB 포함) 검증 로직 추가
src/main/java/com/opus/opus/global/util/ExcelTeamParser.java xlsx 파싱 로직 추가(5행부터 읽기, 콤마 분리)
src/main/java/com/opus/opus/global/security/oauth2/GoogleOAuth2UserService.java 소셜 로그인 시 가짜 회원이면 소셜 회원으로 전환
src/main/java/com/opus/opus/global/error/ExceptionAdvice.java TeamException 벌크 에러 응답 분기 처리 추가
src/main/java/com/opus/opus/docs/asciidoc/contest.adoc “팀 일괄 등록(엑셀)” API 문서 섹션 추가
build.gradle Apache POI 의존성 추가

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +5 to +13
import com.opus.opus.modules.contest.application.dto.response.TeamBulkErrorResponse.TeamBulkError;
import java.util.List;
import lombok.Getter;

@Getter
public class TeamException extends BaseException {

private final TeamExceptionType exceptionType;
private final List<TeamBulkError> bulkErrors;
Copy link

Copilot AI Mar 21, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TeamException now depends on TeamBulkErrorResponse.TeamBulkError (contest module DTO). This couples the team exception layer to an API response type and makes reuse/maintenance harder (and can create module dependency issues). Consider introducing a team/global-domain error DTO (or a simple internal error value object) and map it to TeamBulkErrorResponse at the controller/advice layer instead.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

⭐️ 기능 구현 새로운 기능을 구현

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEATURE] 엑셀 파일로 팀 추가

2 participants