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
Original file line number Diff line number Diff line change
@@ -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);
}
Original file line number Diff line number Diff line change
@@ -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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -20,7 +20,7 @@
@RequiredArgsConstructor
public class AdminMemberSemesterController implements AdminMemberSemesterApiSpec {

private final AdminMemberUseCase adminMemberUsecase;
private final AdminMemberSemesterUseCase adminMemberUsecase;

// 일반 구성원 추가
@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -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<String> 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 {
}
Original file line number Diff line number Diff line change
@@ -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<String> interestedDomains();

Region region();
}
Original file line number Diff line number Diff line change
Expand Up @@ -58,5 +58,5 @@ public record CreateMemberSemesterRequest(

Region region

) {
) implements CreateMemberRequest {
}
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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로 조회 (다음 페이지 유무 확인)
Expand All @@ -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);
}
}
}
Original file line number Diff line number Diff line change
@@ -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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@

@Service
@RequiredArgsConstructor
public class AdminMemberUseCase {
public class AdminMemberSemesterUseCase {

private final AdminMemberService adminMemberService;
private final AdminMemberActivityService adminMemberActivityService;
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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();
}
Expand All @@ -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(),
Expand Down
15 changes: 15 additions & 0 deletions src/main/java/org/ject/support/domain/member/Availability.java
Original file line number Diff line number Diff line change
@@ -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;
}
15 changes: 15 additions & 0 deletions src/main/java/org/ject/support/domain/member/CareerLevel.java
Original file line number Diff line number Diff line change
@@ -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;
}
14 changes: 14 additions & 0 deletions src/main/java/org/ject/support/domain/member/MakersTeam.java
Original file line number Diff line number Diff line change
@@ -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;

}
Loading
Loading