diff --git a/src/main/java/org/ject/support/admin/member/controller/AdminMemberMakersApiSpec.java b/src/main/java/org/ject/support/admin/member/controller/AdminMemberMakersApiSpec.java new file mode 100644 index 00000000..87d2e9ae --- /dev/null +++ b/src/main/java/org/ject/support/admin/member/controller/AdminMemberMakersApiSpec.java @@ -0,0 +1,17 @@ +package org.ject.support.admin.member.controller; + +import org.ject.support.admin.member.dto.request.CreateMemberMakersRequest; +import org.springframework.web.bind.annotation.RequestBody; + +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.validation.Valid; + +@Tag(name = "AdminMemberMakers", description = "메이커스팀 구성원 API") +public interface AdminMemberMakersApiSpec { + @Operation( + summary = "메이커스팀 구성원 추가", + description = "메이커스팀 구성원을 추가합니다." + ) + void createAdminMemberMakers(@RequestBody @Valid CreateMemberMakersRequest request); +} diff --git a/src/main/java/org/ject/support/admin/member/controller/AdminMemberMakersController.java b/src/main/java/org/ject/support/admin/member/controller/AdminMemberMakersController.java new file mode 100644 index 00000000..b37e50d2 --- /dev/null +++ b/src/main/java/org/ject/support/admin/member/controller/AdminMemberMakersController.java @@ -0,0 +1,27 @@ +package org.ject.support.admin.member.controller; + +import org.ject.support.admin.member.dto.request.CreateMemberMakersRequest; +import org.ject.support.admin.member.service.AdminMemberMakersUseCase; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; + +@RestController +@RequestMapping("/admin/members/makers") +@RequiredArgsConstructor +public class AdminMemberMakersController implements AdminMemberMakersApiSpec{ + + private final AdminMemberMakersUseCase adminMemberMakersUseCase; + + // 메이커스팀 구성원 추가 + @Override + @PostMapping + public void createAdminMemberMakers( + @RequestBody @Valid CreateMemberMakersRequest request) { + adminMemberMakersUseCase.createMemberMakers(request); + } +} diff --git a/src/main/java/org/ject/support/admin/member/controller/AdminMemberSemesterController.java b/src/main/java/org/ject/support/admin/member/controller/AdminMemberSemesterController.java index 120d101f..676f530d 100644 --- a/src/main/java/org/ject/support/admin/member/controller/AdminMemberSemesterController.java +++ b/src/main/java/org/ject/support/admin/member/controller/AdminMemberSemesterController.java @@ -3,7 +3,7 @@ import org.ject.support.admin.member.dto.request.CreateMemberSemesterRequest; import org.ject.support.admin.member.dto.request.MemberSemesterSearchCondition; import org.ject.support.admin.member.dto.response.SearchMemberSemesterResponse; -import org.ject.support.admin.member.service.AdminMemberUseCase; +import org.ject.support.admin.member.service.AdminMemberSemesterUseCase; import org.ject.support.common.response.CursorPageResponse; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.ModelAttribute; @@ -20,7 +20,7 @@ @RequiredArgsConstructor public class AdminMemberSemesterController implements AdminMemberSemesterApiSpec { - private final AdminMemberUseCase adminMemberUsecase; + private final AdminMemberSemesterUseCase adminMemberUsecase; // 일반 구성원 추가 @Override diff --git a/src/main/java/org/ject/support/admin/member/dto/request/CreateMemberMakersRequest.java b/src/main/java/org/ject/support/admin/member/dto/request/CreateMemberMakersRequest.java new file mode 100644 index 00000000..5d839b01 --- /dev/null +++ b/src/main/java/org/ject/support/admin/member/dto/request/CreateMemberMakersRequest.java @@ -0,0 +1,82 @@ +package org.ject.support.admin.member.dto.request; + +import java.util.List; + +import org.ject.support.domain.member.Availability; +import org.ject.support.domain.member.CareerDetails; +import org.ject.support.domain.member.CareerLevel; +import org.ject.support.domain.member.ExperiencePeriod; +import org.ject.support.domain.member.JobFamily; +import org.ject.support.domain.member.MakersTeam; +import org.ject.support.domain.member.Region; +import org.ject.support.domain.recruit.domain.RecruitTypeDetail; + +import jakarta.validation.constraints.Email; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Pattern; +import jakarta.validation.constraints.Size; + +public record CreateMemberMakersRequest( + + // 필수 항목: 이름, 전화번호, 이메일, 직군(포자션), 지원자 신분, 소속, 모집단위 + + @NotBlank(message = "이름을 입력해주세요") + @Size(max = 20, message = "이름은 20자 이하로 입력해주세요.") + @Pattern(regexp = "^[^\\s]+$", message = "이름은 공백없이 입력해주세요") + String name, + + @NotBlank(message = "이메일을 입력해주세요.") + @Email(message = "올바른 이메일 형식이 아닙니다.") + @Size(max = 30, message = "이메일은 30자 이하로 입력해주세요.") + String email, + + @NotBlank(message = "전화번호를 입력해주세요") + @Pattern(regexp = "^010\\d{8}$", message = "010으로 시작하는 11자리 숫자를 입력해주세요.") + String phoneNumber, + + @NotNull(message = "포지션을 선택해주세요") + JobFamily jobFamily, + + @NotNull(message = "지원자 신분을 선택해주세요") + CareerDetails careerDetails, + + @NotNull(message = "소속을 선택해주세요") + MakersTeam makersTeam, + + @NotNull(message = "모집 단위를 선택해주세요") + RecruitTypeDetail recruitTypeDetail, + + // 선택 항목: 거주지역, 관심도메인, 직무관련경험, 멘토링 가능 여부, 프로젝트 충원 가능 여부, 연사 가능 여부, 경력, 기술, 회사, 공유 가능한 전문 주제, 활동 증명서 번호, 비고 + + Region region, + + @Size(min = 1, max = 3, message = "관심 도메인은 최소 1개부터 최대 3개까지 선택 가능합니다.") + List interestedDomains, + + ExperiencePeriod experiencePeriod, + + Availability mentoringAvailability, + + Availability projectSupplementAvailability, + + Availability speakerAvailability, + + CareerLevel careerLevel, + + @Size(max = 255, message = "기술은 255자 이하로 입력해주세요.") + String skills, + + @Size(max = 30, message = "회사는 30자 이하로 입력해주세요.") + String company, + + @Size(max = 30, message = "공유 가능한 전문 주제는 30자 이하로 입력해주세요.") + String expertTopics, + + @Size(max = 20, message = "활동 증명서 번호는 20자 이하로 입력해주세요.") + String activityCertNumber, + + @Size(max = 100, message = "비고는 100자 이하로 입력해주세요.") + String memo +) implements CreateMemberRequest { +} diff --git a/src/main/java/org/ject/support/admin/member/dto/request/CreateMemberRequest.java b/src/main/java/org/ject/support/admin/member/dto/request/CreateMemberRequest.java new file mode 100644 index 00000000..17853d1f --- /dev/null +++ b/src/main/java/org/ject/support/admin/member/dto/request/CreateMemberRequest.java @@ -0,0 +1,18 @@ +package org.ject.support.admin.member.dto.request; + +import java.util.List; + +import org.ject.support.domain.member.Region; + +public interface CreateMemberRequest { + + String name(); + + String email(); + + String phoneNumber(); + + List interestedDomains(); + + Region region(); +} diff --git a/src/main/java/org/ject/support/admin/member/dto/request/CreateMemberSemesterRequest.java b/src/main/java/org/ject/support/admin/member/dto/request/CreateMemberSemesterRequest.java index f50ce805..97fa6c7c 100644 --- a/src/main/java/org/ject/support/admin/member/dto/request/CreateMemberSemesterRequest.java +++ b/src/main/java/org/ject/support/admin/member/dto/request/CreateMemberSemesterRequest.java @@ -58,5 +58,5 @@ public record CreateMemberSemesterRequest( Region region -) { +) implements CreateMemberRequest { } diff --git a/src/main/java/org/ject/support/admin/member/service/AdminMemberActivityService.java b/src/main/java/org/ject/support/admin/member/service/AdminMemberActivityService.java index 623b693c..a21394ff 100644 --- a/src/main/java/org/ject/support/admin/member/service/AdminMemberActivityService.java +++ b/src/main/java/org/ject/support/admin/member/service/AdminMemberActivityService.java @@ -1,6 +1,7 @@ package org.ject.support.admin.member.service; import org.ject.support.admin.member.dto.projection.SearchMemberSemesterProjection; +import org.ject.support.admin.member.dto.request.CreateMemberMakersRequest; import org.ject.support.admin.member.dto.request.CreateMemberSemesterRequest; import org.ject.support.admin.member.dto.request.MemberSemesterSearchCondition; import org.ject.support.admin.member.dto.result.SearchMemberSemesterPageResult; @@ -13,6 +14,7 @@ import lombok.RequiredArgsConstructor; +import static org.ject.support.domain.member.exception.MemberErrorCode.ALREADY_EXIST_ACTIVE_MEMBER_MAKERS_ACTIVITY; import static org.ject.support.domain.member.exception.MemberErrorCode.ALREADY_EXIST_MEMBER_SEMESTER_ACTIVITY; import java.util.List; @@ -43,6 +45,32 @@ public void createMemberSemesterActivity(CreateMemberSemesterRequest request, Lo memberActivityRepository.save(memberActivity); } + public void createMemberMakersActivity(CreateMemberMakersRequest request, Long memberId) { + // 추가하려는 대상이 이미 활동 중인 상태인지 검증 + validateDuplicateActiveMakersActivity(memberId); + + // MemberActivity생성, 내부에서 MemberMakers 생성 + MemberActivity memberActivity = MemberActivity.createMakersActivity( + memberId, + request.jobFamily(), + request.recruitTypeDetail(), + request.careerDetails(), + request.experiencePeriod(), + request.memo(), + request.makersTeam(), + request.mentoringAvailability(), + request.projectSupplementAvailability(), + request.speakerAvailability(), + request.careerLevel(), + request.skills(), + request.company(), + request.expertTopics(), + request.activityCertNumber() + ); + + memberActivityRepository.save(memberActivity); + } + // 동적 필터로 일반 구성원 목록 조회 public SearchMemberSemesterPageResult searchMemberSemesterList(MemberSemesterSearchCondition condition) { // size+1로 조회 (다음 페이지 유무 확인) @@ -63,4 +91,11 @@ private void validateDuplicateSemesterActivity(Long memberId, Long semesterId) { throw new MemberException(ALREADY_EXIST_MEMBER_SEMESTER_ACTIVITY); } } + + // ACTIVE 상태인 메이커스팀 활동 존재 여부 검증(메이커스팀 활동은 반드시 1개만 활성 상태여야 함) + private void validateDuplicateActiveMakersActivity(Long memberId) { + if (memberActivityRepository.existsActiveMakersActivityByMemberId(memberId)) { + throw new MemberException(ALREADY_EXIST_ACTIVE_MEMBER_MAKERS_ACTIVITY); + } + } } diff --git a/src/main/java/org/ject/support/admin/member/service/AdminMemberMakersUseCase.java b/src/main/java/org/ject/support/admin/member/service/AdminMemberMakersUseCase.java new file mode 100644 index 00000000..1d5f6f14 --- /dev/null +++ b/src/main/java/org/ject/support/admin/member/service/AdminMemberMakersUseCase.java @@ -0,0 +1,26 @@ +package org.ject.support.admin.member.service; + +import org.ject.support.admin.member.dto.request.CreateMemberMakersRequest; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +import jakarta.validation.Valid; +import lombok.RequiredArgsConstructor; + +@Service +@RequiredArgsConstructor +public class AdminMemberMakersUseCase { + + private final AdminMemberService adminMemberService; + private final AdminMemberActivityService adminMemberActivityService; + + // 메이커스팀 구성원 추가 + @Transactional + public void createMemberMakers(CreateMemberMakersRequest request) { + // email 기준 기존 Member 조회 또는 신규 생성 + Long memberId = adminMemberService.findOrCreateMember(request); + + // memberId 기준 MemberActivity와 MemberMakers 생성 및 저장 + adminMemberActivityService.createMemberMakersActivity(request, memberId); + } +} diff --git a/src/main/java/org/ject/support/admin/member/service/AdminMemberUseCase.java b/src/main/java/org/ject/support/admin/member/service/AdminMemberSemesterUseCase.java similarity index 99% rename from src/main/java/org/ject/support/admin/member/service/AdminMemberUseCase.java rename to src/main/java/org/ject/support/admin/member/service/AdminMemberSemesterUseCase.java index 55bad1df..d1a3ae8e 100644 --- a/src/main/java/org/ject/support/admin/member/service/AdminMemberUseCase.java +++ b/src/main/java/org/ject/support/admin/member/service/AdminMemberSemesterUseCase.java @@ -21,7 +21,7 @@ @Service @RequiredArgsConstructor -public class AdminMemberUseCase { +public class AdminMemberSemesterUseCase { private final AdminMemberService adminMemberService; private final AdminMemberActivityService adminMemberActivityService; diff --git a/src/main/java/org/ject/support/admin/member/service/AdminMemberService.java b/src/main/java/org/ject/support/admin/member/service/AdminMemberService.java index 2a140691..1e267c95 100644 --- a/src/main/java/org/ject/support/admin/member/service/AdminMemberService.java +++ b/src/main/java/org/ject/support/admin/member/service/AdminMemberService.java @@ -1,6 +1,6 @@ package org.ject.support.admin.member.service; -import org.ject.support.admin.member.dto.request.CreateMemberSemesterRequest; +import org.ject.support.admin.member.dto.request.CreateMemberRequest; import org.ject.support.domain.member.entity.Member; import org.ject.support.domain.member.repository.MemberRepository; import org.springframework.stereotype.Service; @@ -19,17 +19,17 @@ public class AdminMemberService { 2. 삭제된 구성원 존재시: isDeleted 복구 3. 활성 구성원 존재시: 새로 입력받은 값으로 덮어쓰기 4. 미 존재시: 새로 생성 - */ + */ // email 기준 구성원 조회 또는 신상정보 생성 - public Long findOrCreateMember(CreateMemberSemesterRequest request) { + public Long findOrCreateMember(CreateMemberRequest request) { return memberRepository.findByEmailIncludingDeleted(request.email()) .map(member -> useExistingMember(member, request)) .orElseGet(() -> createMember(request)); } // 기존 구성원 복구 후 신상정보 갱신 - private Long useExistingMember(Member member, CreateMemberSemesterRequest request) { + private Long useExistingMember(Member member, CreateMemberRequest request) { if (member.getIsDeleted()) { member.restore(); } @@ -44,7 +44,7 @@ private Long useExistingMember(Member member, CreateMemberSemesterRequest reques } // 구성원 신상정보 생성 - private Long createMember(CreateMemberSemesterRequest request) { + private Long createMember(CreateMemberRequest request) { Member member = Member.create( request.name(), request.email(), diff --git a/src/main/java/org/ject/support/domain/member/Availability.java b/src/main/java/org/ject/support/domain/member/Availability.java new file mode 100644 index 00000000..b72082a9 --- /dev/null +++ b/src/main/java/org/ject/support/domain/member/Availability.java @@ -0,0 +1,15 @@ +package org.ject.support.domain.member; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public enum Availability { + UNAVAILABLE("불가능"), + CONSIDER_LATER("추후 고려"), + AVAILABLE_BY_TOPIC("주제에 따라 가능"), + HIGHLY_AVAILABLE("적극 가능"); + + private final String description; +} diff --git a/src/main/java/org/ject/support/domain/member/CareerLevel.java b/src/main/java/org/ject/support/domain/member/CareerLevel.java new file mode 100644 index 00000000..ad61b8cb --- /dev/null +++ b/src/main/java/org/ject/support/domain/member/CareerLevel.java @@ -0,0 +1,15 @@ +package org.ject.support.domain.member; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public enum CareerLevel { + UNDER_1_YEAR("1년 미만"), + JUNIOR("주니어(1-3년차)"), + MIDDLE("미들(4-7년차)"), + SENIOR("시니어(8년차~)"); + + private final String description; +} diff --git a/src/main/java/org/ject/support/domain/member/MakersTeam.java b/src/main/java/org/ject/support/domain/member/MakersTeam.java new file mode 100644 index 00000000..181fff94 --- /dev/null +++ b/src/main/java/org/ject/support/domain/member/MakersTeam.java @@ -0,0 +1,14 @@ +package org.ject.support.domain.member; + +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +@Getter +@RequiredArgsConstructor +public enum MakersTeam { + TEAM_1("메이커스 1팀"), + TEAM_2("메이커스 2팀"); + + private final String description; + +} diff --git a/src/main/java/org/ject/support/domain/member/entity/MemberActivity.java b/src/main/java/org/ject/support/domain/member/entity/MemberActivity.java index 14231e65..83e54b28 100644 --- a/src/main/java/org/ject/support/domain/member/entity/MemberActivity.java +++ b/src/main/java/org/ject/support/domain/member/entity/MemberActivity.java @@ -18,9 +18,12 @@ import org.hibernate.annotations.SQLRestriction; import org.ject.support.domain.base.BaseTimeEntity; import org.ject.support.domain.member.ActivityStatus; +import org.ject.support.domain.member.Availability; import org.ject.support.domain.member.CareerDetails; +import org.ject.support.domain.member.CareerLevel; import org.ject.support.domain.member.ExperiencePeriod; import org.ject.support.domain.member.JobFamily; +import org.ject.support.domain.member.MakersTeam; import org.ject.support.domain.member.MemberType; import org.ject.support.domain.member.exception.MemberErrorCode; import org.ject.support.domain.member.exception.MemberException; @@ -82,6 +85,9 @@ public class MemberActivity extends BaseTimeEntity { @OneToOne(mappedBy = "memberActivity", fetch = FetchType.LAZY, orphanRemoval = true, cascade = CascadeType.ALL) private MemberSemester memberSemester; + @OneToOne(mappedBy = "memberActivity", fetch = FetchType.LAZY, orphanRemoval = true, cascade = CascadeType.ALL) + private MemberMakers memberMakers; + // 일반 구성원 활동과 관리 항목 생성 public static MemberActivity createSemesterActivity( Long memberId, @@ -108,7 +114,48 @@ public static MemberActivity createSemesterActivity( return memberActivity; } - //Todo: 메이커스 구성원 활동과 관리 항목 생성 + // 메이커스팀 구성원 활동과 관리 항목 생성 + public static MemberActivity createMakersActivity( + Long memberId, + JobFamily jobFamily, + RecruitTypeDetail recruitTypeDetail, + CareerDetails careerDetails, + ExperiencePeriod experiencePeriod, + String memo, + MakersTeam makersTeam, + Availability mentoringAvailability, + Availability projectSupplementAvailability, + Availability speakerAvailability, + CareerLevel careerLevel, + String skills, + String company, + String expertTopics, + String activityCertNumber + ){ + MemberActivity memberActivity = MemberActivity.builder() + .memberId(memberId) + .memberType(MemberType.MAKERS) + .jobFamily(jobFamily) + .recruitTypeDetail(recruitTypeDetail) + .careerDetails(careerDetails) + .experiencePeriod(experiencePeriod) + .memo(memo) + .build(); + // 애그리거트 루트인 MemberActivity쪽에서 식별 관계인 엔티티 생성 책임 + memberActivity.memberMakers = MemberMakers.create( + memberActivity, + makersTeam, + mentoringAvailability, + projectSupplementAvailability, + speakerAvailability, + careerLevel, + skills, + company, + expertTopics, + activityCertNumber + ); + return memberActivity; + } //Todo: 운영 서포터즈 구성원 활동과 관리 항목 생성 diff --git a/src/main/java/org/ject/support/domain/member/entity/MemberMakers.java b/src/main/java/org/ject/support/domain/member/entity/MemberMakers.java index a2445602..24a0ba4a 100644 --- a/src/main/java/org/ject/support/domain/member/entity/MemberMakers.java +++ b/src/main/java/org/ject/support/domain/member/entity/MemberMakers.java @@ -2,6 +2,8 @@ import jakarta.persistence.Column; import jakarta.persistence.Entity; +import jakarta.persistence.EnumType; +import jakarta.persistence.Enumerated; import jakarta.persistence.FetchType; import jakarta.persistence.Id; import jakarta.persistence.JoinColumn; @@ -10,6 +12,9 @@ import jakarta.persistence.Table; import lombok.*; import org.ject.support.domain.base.BaseTimeEntity; +import org.ject.support.domain.member.Availability; +import org.ject.support.domain.member.MakersTeam; +import org.ject.support.domain.member.CareerLevel; @Entity @Getter @@ -27,20 +32,25 @@ public class MemberMakers extends BaseTimeEntity { @JoinColumn(name = "id", nullable = false) private MemberActivity memberActivity; + @Enumerated(EnumType.STRING) @Column(length = 20) - private String teamName; + private MakersTeam makersTeam; + @Enumerated(EnumType.STRING) @Column(length = 30) - private String mentoringAvailability; + private Availability mentoringAvailability; + @Enumerated(EnumType.STRING) @Column(length = 30) - private String projectSupplementAvailability; + private Availability projectSupplementAvailability; + @Enumerated(EnumType.STRING) @Column(length = 30) - private String speakerAvailability; + private Availability speakerAvailability; + @Enumerated(EnumType.STRING) @Column(length = 30) - private String careerLevel; + private CareerLevel careerLevel; @Column(length = 255) private String skills; @@ -53,4 +63,30 @@ public class MemberMakers extends BaseTimeEntity { @Column(length = 20) private String activityCertNumber; + + public static MemberMakers create( + MemberActivity memberActivity, + MakersTeam makersTeam, + Availability mentoringAvailability, + Availability projectSupplementAvailability, + Availability speakerAvailability, + CareerLevel careerLevel, + String skills, + String company, + String expertTopics, + String activityCertNumber + ){ + return MemberMakers.builder() + .memberActivity(memberActivity) + .makersTeam(makersTeam) + .mentoringAvailability(mentoringAvailability) + .projectSupplementAvailability(projectSupplementAvailability) + .speakerAvailability(speakerAvailability) + .careerLevel(careerLevel) + .skills(skills) + .company(company) + .expertTopics(expertTopics) + .activityCertNumber(activityCertNumber) + .build(); + } } diff --git a/src/main/java/org/ject/support/domain/member/exception/MemberErrorCode.java b/src/main/java/org/ject/support/domain/member/exception/MemberErrorCode.java index e78cde93..11a64bd2 100644 --- a/src/main/java/org/ject/support/domain/member/exception/MemberErrorCode.java +++ b/src/main/java/org/ject/support/domain/member/exception/MemberErrorCode.java @@ -19,6 +19,7 @@ public enum MemberErrorCode implements ErrorCode { NOT_FOUND_TEAM_OF_SEMESTER(NOT_FOUND, "MEMBER-7", "해당 기수의 팀을 찾을 수 없습니다."), REQUIRED_SEMESTER_FOR_TEAM_FILTER(BAD_REQUEST, "MEMBER-8", "팀 필터를 사용할 때는 기수를 함께 선택해야 합니다."), INVALID_ACTIVITY_STATUS(BAD_REQUEST, "MEMBER-9", "구성원 유형에 맞지 않는 활동 상태입니다."), + ALREADY_EXIST_ACTIVE_MEMBER_MAKERS_ACTIVITY(CONFLICT, "MEMBER-10", "이미 활동 중인 메이커스팀 구성원입니다."), ; private final HttpStatus httpStatus; diff --git a/src/main/java/org/ject/support/domain/member/repository/MemberActivityRepository.java b/src/main/java/org/ject/support/domain/member/repository/MemberActivityRepository.java index 868b320f..c39cfae9 100644 --- a/src/main/java/org/ject/support/domain/member/repository/MemberActivityRepository.java +++ b/src/main/java/org/ject/support/domain/member/repository/MemberActivityRepository.java @@ -23,4 +23,13 @@ boolean existsSemesterActivity( @Param("memberType") MemberType memberType, @Param("semesterId") Long semesterId ); + + @Query(""" + select count(ma) > 0 + from MemberActivity ma + where ma.memberId = :memberId + and ma.memberType = org.ject.support.domain.member.MemberType.MAKERS + and ma.activityStatus = org.ject.support.domain.member.ActivityStatus.ACTIVE + """) + boolean existsActiveMakersActivityByMemberId(@Param("memberId") Long memberId); } diff --git a/src/main/resources/db/migration/V35__rename_member_makers_team_name_to_makers_team.sql b/src/main/resources/db/migration/V35__rename_member_makers_team_name_to_makers_team.sql new file mode 100644 index 00000000..5d75c3fc --- /dev/null +++ b/src/main/resources/db/migration/V35__rename_member_makers_team_name_to_makers_team.sql @@ -0,0 +1,2 @@ +ALTER TABLE member_makers + CHANGE COLUMN team_name makers_team VARCHAR(20) NULL; diff --git a/src/test/java/org/ject/support/admin/member/controller/AdminMemberMakersControllerTest.java b/src/test/java/org/ject/support/admin/member/controller/AdminMemberMakersControllerTest.java new file mode 100644 index 00000000..8bbf5ffc --- /dev/null +++ b/src/test/java/org/ject/support/admin/member/controller/AdminMemberMakersControllerTest.java @@ -0,0 +1,189 @@ +package org.ject.support.admin.member.controller; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.ject.support.domain.member.fixture.MemberFixture.member; +import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.List; +import org.ject.support.admin.member.dto.request.CreateMemberMakersRequest; +import org.ject.support.domain.member.ActivityStatus; +import org.ject.support.domain.member.Availability; +import org.ject.support.domain.member.CareerDetails; +import org.ject.support.domain.member.CareerLevel; +import org.ject.support.domain.member.ExperiencePeriod; +import org.ject.support.domain.member.JobFamily; +import org.ject.support.domain.member.MakersTeam; +import org.ject.support.domain.member.MemberType; +import org.ject.support.domain.member.Region; +import org.ject.support.domain.member.entity.Member; +import org.ject.support.domain.member.entity.MemberActivity; +import org.ject.support.domain.member.entity.MemberMakers; +import org.ject.support.domain.member.exception.MemberErrorCode; +import org.ject.support.domain.member.repository.MemberActivityRepository; +import org.ject.support.domain.member.repository.MemberRepository; +import org.ject.support.domain.recruit.domain.RecruitTypeDetail; +import org.ject.support.testconfig.AuthenticatedUser; +import org.ject.support.testconfig.IntegrationTest; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc; +import org.springframework.http.MediaType; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.transaction.annotation.Transactional; + +@IntegrationTest +@AutoConfigureMockMvc +@Transactional +@AuthenticatedUser(isAdmin = true) +@TestPropertySource(properties = {"spring.data.redis.repositories.enabled=false"}) +class AdminMemberMakersControllerTest { + + @Autowired + private MockMvc mockMvc; + + @Autowired + private ObjectMapper objectMapper; + + @Autowired + private MemberRepository memberRepository; + + @Autowired + private MemberActivityRepository memberActivityRepository; + + @Test + @DisplayName("메이커스팀 구성원을 추가한다") + void 메이커스팀_구성원을_추가한다() throws Exception { + // given + String email = uniqueEmail("makers"); + CreateMemberMakersRequest request = createMemberMakersRequest(email); + + // when + mockMvc.perform(post("/admin/members/makers") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(request))) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.status").value("SUCCESS")); + + // then + Member member = memberRepository.findByEmail(email).orElseThrow(); + MemberActivity memberActivity = findOnlyActivity(member.getId()); + MemberMakers memberMakers = memberActivity.getMemberMakers(); + + assertThat(member.getName()).isEqualTo(request.name()); + assertThat(member.getPhoneNumber()).isEqualTo(request.phoneNumber()); + assertThat(member.getInterestedDomains()).containsExactlyElementsOf(request.interestedDomains()); + assertThat(member.getRegion()).isEqualTo(request.region()); + assertThat(memberActivity.getMemberType()).isEqualTo(MemberType.MAKERS); + assertThat(memberActivity.getActivityStatus()).isEqualTo(ActivityStatus.ACTIVE); + assertThat(memberActivity.getJobFamily()).isEqualTo(request.jobFamily()); + assertThat(memberActivity.getRecruitTypeDetail()).isEqualTo(request.recruitTypeDetail()); + assertThat(memberActivity.getCareerDetails()).isEqualTo(request.careerDetails()); + assertThat(memberActivity.getExperiencePeriod()).isEqualTo(request.experiencePeriod()); + assertThat(memberActivity.getMemo()).isEqualTo(request.memo()); + assertThat(memberMakers.getMakersTeam()).isEqualTo(request.makersTeam()); + assertThat(memberMakers.getMentoringAvailability()).isEqualTo(request.mentoringAvailability()); + assertThat(memberMakers.getProjectSupplementAvailability()).isEqualTo(request.projectSupplementAvailability()); + assertThat(memberMakers.getSpeakerAvailability()).isEqualTo(request.speakerAvailability()); + assertThat(memberMakers.getCareerLevel()).isEqualTo(request.careerLevel()); + assertThat(memberMakers.getSkills()).isEqualTo(request.skills()); + assertThat(memberMakers.getCompany()).isEqualTo(request.company()); + assertThat(memberMakers.getExpertTopics()).isEqualTo(request.expertTopics()); + assertThat(memberMakers.getActivityCertNumber()).isEqualTo(request.activityCertNumber()); + } + + @Test + @DisplayName("활동 중인 메이커스팀 구성원이 있으면 추가하지 않는다") + void 활동_중인_메이커스팀_구성원이_있으면_추가하지_않는다() throws Exception { + // given + String email = uniqueEmail("duplicate"); + CreateMemberMakersRequest request = createMemberMakersRequest(email); + mockMvc.perform(post("/admin/members/makers") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(request))) + .andExpect(status().isOk()); + + // when & then + mockMvc.perform(post("/admin/members/makers") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(request))) + .andExpect(status().isConflict()) + .andExpect(jsonPath("$.status").value(MemberErrorCode.ALREADY_EXIST_ACTIVE_MEMBER_MAKERS_ACTIVITY.getCode())); + } + + @Test + @DisplayName("삭제된 기존 구성원도 메이커스팀 구성원으로 복구해 추가한다") + void 삭제된_기존_구성원도_메이커스팀_구성원으로_복구해_추가한다() throws Exception { + // given + String email = uniqueEmail("restore"); + Member deletedMember = memberRepository.save(member() + .email(email) + .build()); + memberRepository.delete(deletedMember); + memberRepository.flush(); + CreateMemberMakersRequest request = createMemberMakersRequest(email); + + // when + mockMvc.perform(post("/admin/members/makers") + .contentType(MediaType.APPLICATION_JSON) + .content(objectMapper.writeValueAsString(request))) + .andExpect(status().isOk()) + .andExpect(jsonPath("$.status").value("SUCCESS")); + + // then + Member restoredMember = memberRepository.findByEmail(email).orElseThrow(); + MemberActivity memberActivity = findOnlyActivity(restoredMember.getId()); + + assertThat(restoredMember.getIsDeleted()).isFalse(); + assertThat(restoredMember.getName()).isEqualTo(request.name()); + assertThat(restoredMember.getPhoneNumber()).isEqualTo(request.phoneNumber()); + assertThat(memberActivity.getMemberType()).isEqualTo(MemberType.MAKERS); + assertThat(memberActivity.getMemberMakers().getMakersTeam()).isEqualTo(request.makersTeam()); + } + + private CreateMemberMakersRequest createMemberMakersRequest(String email) { + return new CreateMemberMakersRequest( + "김메이커", + email, + "01087654321", + JobFamily.FE, + CareerDetails.EMPLOYEE, + MakersTeam.TEAM_1, + RecruitTypeDetail.REGULAR, + Region.SEOUL, + List.of("HEALTHCARE", "FINTECH", "AI"), + ExperiencePeriod.ONE_TO_TWO, + Availability.HIGHLY_AVAILABLE, + Availability.AVAILABLE_BY_TOPIC, + Availability.CONSIDER_LATER, + CareerLevel.JUNIOR, + "Spring", + "JECT", + "백오피스", + "MK-001", + "memo" + ); + } + + private MemberActivity findOnlyActivity(Long memberId) { + List activities = memberActivityRepository.findAll().stream() + .filter(activity -> activity.getMemberId().equals(memberId)) + .toList(); + + assertThat(activities).hasSize(1); + return activities.get(0); + } + + private String uniqueEmail(String prefix) { + return prefix + uniqueSuffix() + "@t.kr"; + } + + private String uniqueSuffix() { + String suffix = String.valueOf(System.nanoTime()); + return suffix.substring(suffix.length() - 6); + } +} diff --git a/src/test/java/org/ject/support/admin/member/service/AdminMemberActivityServiceTest.java b/src/test/java/org/ject/support/admin/member/service/AdminMemberActivityServiceTest.java index 7922822a..cd5bc859 100644 --- a/src/test/java/org/ject/support/admin/member/service/AdminMemberActivityServiceTest.java +++ b/src/test/java/org/ject/support/admin/member/service/AdminMemberActivityServiceTest.java @@ -10,14 +10,18 @@ import java.util.List; import org.ject.support.admin.member.dto.projection.SearchMemberSemesterProjection; +import org.ject.support.admin.member.dto.request.CreateMemberMakersRequest; import org.ject.support.admin.member.dto.request.CreateMemberSemesterRequest; import org.ject.support.admin.member.dto.request.MemberSemesterSearchCondition; import org.ject.support.admin.member.dto.result.SearchMemberSemesterPageResult; import org.ject.support.common.response.CursorPageResponse; import org.ject.support.domain.member.ActivityStatus; +import org.ject.support.domain.member.Availability; import org.ject.support.domain.member.CareerDetails; +import org.ject.support.domain.member.CareerLevel; import org.ject.support.domain.member.ExperiencePeriod; import org.ject.support.domain.member.JobFamily; +import org.ject.support.domain.member.MakersTeam; import org.ject.support.domain.member.MemberType; import org.ject.support.domain.member.Region; import org.ject.support.domain.member.entity.MemberActivity; @@ -100,6 +104,61 @@ class AdminMemberActivityServiceTest { verify(memberActivityRepository, never()).save(any(MemberActivity.class)); } + @Test + @DisplayName("메이커스팀으로 활동 중인 이력이 없으면 신규 메이커스팀 활동 이력을 생성한다") + void 메이커스팀으로_활동_중인_이력이_없으면_신규_메이커스팀_활동_이력을_생성한다() { + // given + CreateMemberMakersRequest request = createMemberMakersRequest(); + Long memberId = 1L; + given(memberActivityRepository.existsActiveMakersActivityByMemberId(memberId)).willReturn(false); + + // when + adminMemberActivityService.createMemberMakersActivity(request, memberId); + + // then + ArgumentCaptor captor = ArgumentCaptor.forClass(MemberActivity.class); + verify(memberActivityRepository).save(captor.capture()); + + MemberActivity memberActivity = captor.getValue(); + assertThat(memberActivity.getMemberId()).isEqualTo(memberId); + assertThat(memberActivity.getMemberType()).isEqualTo(MemberType.MAKERS); + assertThat(memberActivity.getJobFamily()).isEqualTo(request.jobFamily()); + assertThat(memberActivity.getRecruitTypeDetail()).isEqualTo(request.recruitTypeDetail()); + assertThat(memberActivity.getCareerDetails()).isEqualTo(request.careerDetails()); + assertThat(memberActivity.getExperiencePeriod()).isEqualTo(request.experiencePeriod()); + assertThat(memberActivity.getMemo()).isEqualTo(request.memo()); + assertThat(memberActivity.getMemberMakers().getMakersTeam()).isEqualTo(request.makersTeam()); + assertThat(memberActivity.getMemberMakers().getMentoringAvailability()).isEqualTo(request.mentoringAvailability()); + assertThat(memberActivity.getMemberMakers().getProjectSupplementAvailability()).isEqualTo(request.projectSupplementAvailability()); + assertThat(memberActivity.getMemberMakers().getSpeakerAvailability()).isEqualTo(request.speakerAvailability()); + assertThat(memberActivity.getMemberMakers().getCareerLevel()).isEqualTo(request.careerLevel()); + assertThat(memberActivity.getMemberMakers().getSkills()).isEqualTo(request.skills()); + assertThat(memberActivity.getMemberMakers().getCompany()).isEqualTo(request.company()); + assertThat(memberActivity.getMemberMakers().getExpertTopics()).isEqualTo(request.expertTopics()); + assertThat(memberActivity.getMemberMakers().getActivityCertNumber()).isEqualTo(request.activityCertNumber()); + } + + @Test + @DisplayName("메이커스팀으로 활동 중인 이력이 있으면 예외가 발생한다") + void 메이커스팀으로_활동_중인_이력이_있으면_예외가_발생한다() { + // given + CreateMemberMakersRequest request = createMemberMakersRequest(); + Long memberId = 1L; + given(memberActivityRepository.existsActiveMakersActivityByMemberId(memberId)).willReturn(true); + + // when + Throwable throwable = catchThrowable(() -> + adminMemberActivityService.createMemberMakersActivity(request, memberId) + ); + + // then + assertThat(throwable) + .isInstanceOf(MemberException.class) + .extracting("errorCode") + .isEqualTo(MemberErrorCode.ALREADY_EXIST_ACTIVE_MEMBER_MAKERS_ACTIVITY); + verify(memberActivityRepository, never()).save(any(MemberActivity.class)); + } + /** * 일반 구성원 목록 조회 테스트 */ @@ -159,5 +218,29 @@ private CreateMemberSemesterRequest createMemberSemesterRequest() { ); } + private CreateMemberMakersRequest createMemberMakersRequest() { + return new CreateMemberMakersRequest( + "김메이커", + "maker@ject.kr", + "01087654321", + JobFamily.FE, + CareerDetails.EMPLOYEE, + MakersTeam.TEAM_1, + RecruitTypeDetail.REGULAR, + Region.SEOUL, + List.of("HEALTHCARE", "FINTECH", "AI"), + ExperiencePeriod.ONE_TO_TWO, + Availability.HIGHLY_AVAILABLE, + Availability.AVAILABLE_BY_TOPIC, + Availability.CONSIDER_LATER, + CareerLevel.JUNIOR, + "Spring", + "JECT", + "백오피스", + "MK-001", + "memo" + ); + } + } diff --git a/src/test/java/org/ject/support/admin/member/service/AdminMemberUseCaseTest.java b/src/test/java/org/ject/support/admin/member/service/AdminMemberSemesterUseCaseTest.java similarity index 91% rename from src/test/java/org/ject/support/admin/member/service/AdminMemberUseCaseTest.java rename to src/test/java/org/ject/support/admin/member/service/AdminMemberSemesterUseCaseTest.java index 9b50327a..70147334 100644 --- a/src/test/java/org/ject/support/admin/member/service/AdminMemberUseCaseTest.java +++ b/src/test/java/org/ject/support/admin/member/service/AdminMemberSemesterUseCaseTest.java @@ -30,7 +30,7 @@ import org.mockito.junit.jupiter.MockitoExtension; @ExtendWith(MockitoExtension.class) -class AdminMemberUseCaseTest { +class AdminMemberSemesterUseCaseTest { @Mock private AdminMemberService adminMemberService; @@ -45,7 +45,7 @@ class AdminMemberUseCaseTest { private SemesterInquiryUsecase semesterInquiryUsecase; @InjectMocks - private AdminMemberUseCase adminMemberUseCase; + private AdminMemberSemesterUseCase adminMemberSemesterUseCase; private CreateMemberSemesterRequest createMemberSemesterRequest() { return createMemberSemesterRequest(null); @@ -115,7 +115,7 @@ private SearchMemberSemesterProjection searchProjection(Long memberActivityId) { given(adminMemberService.findOrCreateMember(request)).willReturn(memberId); // when - adminMemberUseCase.createMemberSemester(request); + adminMemberSemesterUseCase.createMemberSemester(request); // then verify(semesterInquiryUsecase).getSemester(request.semesterId()); @@ -135,7 +135,7 @@ private SearchMemberSemesterProjection searchProjection(Long memberActivityId) { given(adminMemberService.findOrCreateMember(request)).willReturn(memberId); // when - adminMemberUseCase.createMemberSemester(request); + adminMemberSemesterUseCase.createMemberSemester(request); // then verify(semesterInquiryUsecase).getSemester(request.semesterId()); @@ -153,7 +153,7 @@ private SearchMemberSemesterProjection searchProjection(Long memberActivityId) { .willReturn(List.of(1L, 2L, 3L)); // when - Throwable throwable = catchThrowable(() -> adminMemberUseCase.createMemberSemester(request)); + Throwable throwable = catchThrowable(() -> adminMemberSemesterUseCase.createMemberSemester(request)); // then assertThat(throwable) @@ -173,7 +173,7 @@ private SearchMemberSemesterProjection searchProjection(Long memberActivityId) { given(semesterInquiryUsecase.getSemester(request.semesterId())).willThrow(exception); // when - Throwable throwable = catchThrowable(() -> adminMemberUseCase.createMemberSemester(request)); + Throwable throwable = catchThrowable(() -> adminMemberSemesterUseCase.createMemberSemester(request)); // then assertThat(throwable).isSameAs(exception); @@ -199,7 +199,7 @@ private SearchMemberSemesterProjection searchProjection(Long memberActivityId) { // when CursorPageResponse response = - adminMemberUseCase.searchMemberSemester(condition); + adminMemberSemesterUseCase.searchMemberSemester(condition); // then assertThat(response.content()).hasSize(2); @@ -223,7 +223,7 @@ private SearchMemberSemesterProjection searchProjection(Long memberActivityId) { // when CursorPageResponse response = - adminMemberUseCase.searchMemberSemester(condition); + adminMemberSemesterUseCase.searchMemberSemester(condition); // then assertThat(response.content()).hasSize(2); @@ -242,7 +242,7 @@ private SearchMemberSemesterProjection searchProjection(Long memberActivityId) { // when CursorPageResponse response = - adminMemberUseCase.searchMemberSemester(condition); + adminMemberSemesterUseCase.searchMemberSemester(condition); // then assertThat(response.content()).isEmpty(); @@ -258,7 +258,7 @@ private SearchMemberSemesterProjection searchProjection(Long memberActivityId) { MemberSemesterSearchCondition condition = searchCondition(3, null, 1L); // when - Throwable throwable = catchThrowable(() -> adminMemberUseCase.searchMemberSemester(condition)); + Throwable throwable = catchThrowable(() -> adminMemberSemesterUseCase.searchMemberSemester(condition)); // then assertThat(throwable) @@ -277,7 +277,7 @@ private SearchMemberSemesterProjection searchProjection(Long memberActivityId) { .willReturn(List.of(1L, 2L, 3L)); // when - Throwable throwable = catchThrowable(() -> adminMemberUseCase.searchMemberSemester(condition)); + Throwable throwable = catchThrowable(() -> adminMemberSemesterUseCase.searchMemberSemester(condition)); // then assertThat(throwable) @@ -295,7 +295,7 @@ private SearchMemberSemesterProjection searchProjection(Long memberActivityId) { MemberSemesterSearchCondition condition = searchCondition(3, null, null, ActivityStatus.DROPOUT); // when - Throwable throwable = catchThrowable(() -> adminMemberUseCase.searchMemberSemester(condition)); + Throwable throwable = catchThrowable(() -> adminMemberSemesterUseCase.searchMemberSemester(condition)); // then assertThat(throwable) @@ -315,7 +315,7 @@ private SearchMemberSemesterProjection searchProjection(Long memberActivityId) { // when CursorPageResponse response = - adminMemberUseCase.searchMemberSemester(condition); + adminMemberSemesterUseCase.searchMemberSemester(condition); // then assertThat(response.content()).isEmpty(); diff --git a/src/test/java/org/ject/support/domain/member/entity/MemberActivityTest.java b/src/test/java/org/ject/support/domain/member/entity/MemberActivityTest.java index ccde5b96..c259ae26 100644 --- a/src/test/java/org/ject/support/domain/member/entity/MemberActivityTest.java +++ b/src/test/java/org/ject/support/domain/member/entity/MemberActivityTest.java @@ -5,9 +5,12 @@ import static org.ject.support.domain.member.fixture.SemesterActivityFixture.semesterActivity; import org.ject.support.domain.member.ActivityStatus; +import org.ject.support.domain.member.Availability; import org.ject.support.domain.member.CareerDetails; +import org.ject.support.domain.member.CareerLevel; import org.ject.support.domain.member.ExperiencePeriod; import org.ject.support.domain.member.JobFamily; +import org.ject.support.domain.member.MakersTeam; import org.ject.support.domain.member.MemberType; import org.ject.support.domain.member.exception.MemberErrorCode; import org.ject.support.domain.member.exception.MemberException; @@ -65,6 +68,50 @@ class MemberActivityTest { assertThat(memberSemester.getMemberActivity()).isSameAs(memberActivity); } + @Test + @DisplayName("메이커스 구성원 활동을 생성하면 관리 항목이 함께 생성된다") + void 메이커스_구성원_활동을_생성하면_관리_항목이_함께_생성된다() { + // when + MemberActivity memberActivity = MemberActivity.createMakersActivity( + 1L, + JobFamily.FE, + RecruitTypeDetail.REGULAR, + CareerDetails.EMPLOYEE, + ExperiencePeriod.ONE_TO_TWO, + "테스트 메모", + MakersTeam.TEAM_1, + Availability.HIGHLY_AVAILABLE, + Availability.AVAILABLE_BY_TOPIC, + Availability.CONSIDER_LATER, + CareerLevel.JUNIOR, + "Spring", + "JECT", + "백오피스", + "MK-001" + ); + MemberMakers memberMakers = memberActivity.getMemberMakers(); + + // then + assertThat(memberActivity.getMemberId()).isEqualTo(1L); + assertThat(memberActivity.getMemberType()).isEqualTo(MemberType.MAKERS); + assertThat(memberActivity.getJobFamily()).isEqualTo(JobFamily.FE); + assertThat(memberActivity.getRecruitTypeDetail()).isEqualTo(RecruitTypeDetail.REGULAR); + assertThat(memberActivity.getCareerDetails()).isEqualTo(CareerDetails.EMPLOYEE); + assertThat(memberActivity.getExperiencePeriod()).isEqualTo(ExperiencePeriod.ONE_TO_TWO); + assertThat(memberActivity.getMemo()).isEqualTo("테스트 메모"); + assertThat(memberMakers).isNotNull(); + assertThat(memberMakers.getMemberActivity()).isSameAs(memberActivity); + assertThat(memberMakers.getMakersTeam()).isEqualTo(MakersTeam.TEAM_1); + assertThat(memberMakers.getMentoringAvailability()).isEqualTo(Availability.HIGHLY_AVAILABLE); + assertThat(memberMakers.getProjectSupplementAvailability()).isEqualTo(Availability.AVAILABLE_BY_TOPIC); + assertThat(memberMakers.getSpeakerAvailability()).isEqualTo(Availability.CONSIDER_LATER); + assertThat(memberMakers.getCareerLevel()).isEqualTo(CareerLevel.JUNIOR); + assertThat(memberMakers.getSkills()).isEqualTo("Spring"); + assertThat(memberMakers.getCompany()).isEqualTo("JECT"); + assertThat(memberMakers.getExpertTopics()).isEqualTo("백오피스"); + assertThat(memberMakers.getActivityCertNumber()).isEqualTo("MK-001"); + } + @Test @DisplayName("팀을 선택하지 않으면 팀 정보 없이 일반 구성원 활동을 생성한다") void 팀을_선택하지_않으면_팀_정보_없이_일반_구성원_활동을_생성한다() { diff --git a/src/test/java/org/ject/support/domain/member/repository/MemberActivityRepositoryTest.java b/src/test/java/org/ject/support/domain/member/repository/MemberActivityRepositoryTest.java index 2bf4a156..25282a16 100644 --- a/src/test/java/org/ject/support/domain/member/repository/MemberActivityRepositoryTest.java +++ b/src/test/java/org/ject/support/domain/member/repository/MemberActivityRepositoryTest.java @@ -9,9 +9,12 @@ import org.ject.support.admin.member.dto.projection.SearchMemberSemesterProjection; import org.ject.support.admin.member.dto.request.MemberSemesterSearchCondition; import org.ject.support.domain.member.ActivityStatus; +import org.ject.support.domain.member.Availability; import org.ject.support.domain.member.CareerDetails; +import org.ject.support.domain.member.CareerLevel; import org.ject.support.domain.member.ExperiencePeriod; import org.ject.support.domain.member.JobFamily; +import org.ject.support.domain.member.MakersTeam; import org.ject.support.domain.member.MemberType; import org.ject.support.domain.member.dto.TeamMemberNames; import org.ject.support.domain.member.entity.Member; @@ -121,6 +124,29 @@ private MemberActivity saveSemesterActivity( ActivityStatus.ACTIVE ); } + + private MemberActivity createMakersActivity(Long memberId, ActivityStatus activityStatus) { + MemberActivity memberActivity = MemberActivity.createMakersActivity( + memberId, + JobFamily.FE, + RecruitTypeDetail.REGULAR, + CareerDetails.EMPLOYEE, + ExperiencePeriod.ONE_TO_TWO, + "테스트 메모", + MakersTeam.TEAM_1, + Availability.HIGHLY_AVAILABLE, + Availability.AVAILABLE_BY_TOPIC, + Availability.CONSIDER_LATER, + CareerLevel.JUNIOR, + "Spring", + "JECT", + "백오피스", + "MK-001" + ); + memberActivity.updateActivityStatus(activityStatus); + return memberActivity; + } + /** * 일반 구성원 추가 테스트 */ @@ -235,6 +261,34 @@ private MemberActivity saveSemesterActivity( assertThat(result).isFalse(); } + @Test + @DisplayName("메이커스팀으로 활동 중인 이력이 존재하면 true를 반환한다") + void 메이커스팀으로_활동_중인_이력이_존재하면_true를_반환한다() { + // given + Member member = memberRepository.save(member().email("makers@test.com").build()); + memberActivityRepository.saveAndFlush(createMakersActivity(member.getId(), ActivityStatus.ACTIVE)); + + // when + boolean result = memberActivityRepository.existsActiveMakersActivityByMemberId(member.getId()); + + // then + assertThat(result).isTrue(); + } + + @Test + @DisplayName("메이커스팀으로 활동 중인 이력이 없으면 false를 반환한다") + void 메이커스팀으로_활동_중인_이력이_없으면_false를_반환한다() { + // given + Member member = memberRepository.save(member().email("completed-makers@test.com").build()); + memberActivityRepository.saveAndFlush(createMakersActivity(member.getId(), ActivityStatus.ENDED)); + + // when + boolean result = memberActivityRepository.existsActiveMakersActivityByMemberId(member.getId()); + + // then + assertThat(result).isFalse(); + } + /** * 일반 구성원 목록 조회 테스트 */