From 44b6a7ebb4fa8c3db692af15f8d76a867a54cec3 Mon Sep 17 00:00:00 2001 From: yongckim Date: Wed, 28 Feb 2024 22:29:06 +0900 Subject: [PATCH] =?UTF-8?q?:sparkles:=20[STMT-146]=20=EB=B6=84=EC=95=BC=20?= =?UTF-8?q?=EC=A0=95=EB=B3=B4=EB=A5=BC=20=EA=B4=80=EB=A6=AC=ED=95=98?= =?UTF-8?q?=EB=8A=94=20=EB=8F=84=EB=A9=94=EC=9D=B8=20=EC=A0=95=EC=9D=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../server/common/response/ErrorCode.java | 1 + .../out/persistence/MemberJpaEntity.java | 12 +++-- .../persistence/MemberPersistenceMapper.java | 9 +++- .../out/persistence/OAuthLoginJpaEntity.java | 2 +- .../port/in/MemberSignupCommand.java | 4 +- .../service/MemberAuthService.java | 8 ++- .../stumeet/server/member/domain/Member.java | 14 ++++-- .../persistence/JpaProfessionRepository.java | 6 +++ .../out/persistence/ProfessionJpaEntity.java | 29 +++++++++++ .../ProfessionPersistenceAdapter.java | 23 +++++++++ .../ProfessionPersistenceMapper.java | 50 +++++++++++++++++++ .../port/in/ProfessionQueryUseCase.java | 7 +++ .../port/out/ProfessionQueryPort.java | 7 +++ .../service/ProfessionQueryService.java | 21 ++++++++ .../server/profession/domain/Profession.java | 19 +++++++ 15 files changed, 195 insertions(+), 17 deletions(-) create mode 100644 src/main/java/com/stumeet/server/profession/adapter/out/persistence/JpaProfessionRepository.java create mode 100644 src/main/java/com/stumeet/server/profession/adapter/out/persistence/ProfessionJpaEntity.java create mode 100644 src/main/java/com/stumeet/server/profession/adapter/out/persistence/ProfessionPersistenceAdapter.java create mode 100644 src/main/java/com/stumeet/server/profession/adapter/out/persistence/ProfessionPersistenceMapper.java create mode 100644 src/main/java/com/stumeet/server/profession/application/port/in/ProfessionQueryUseCase.java create mode 100644 src/main/java/com/stumeet/server/profession/application/port/out/ProfessionQueryPort.java create mode 100644 src/main/java/com/stumeet/server/profession/application/service/ProfessionQueryService.java create mode 100644 src/main/java/com/stumeet/server/profession/domain/Profession.java diff --git a/src/main/java/com/stumeet/server/common/response/ErrorCode.java b/src/main/java/com/stumeet/server/common/response/ErrorCode.java index aad39650..cf7ad4af 100644 --- a/src/main/java/com/stumeet/server/common/response/ErrorCode.java +++ b/src/main/java/com/stumeet/server/common/response/ErrorCode.java @@ -20,6 +20,7 @@ public enum ErrorCode { INVALID_IMAGE_EXCEPTION(HttpStatus.BAD_REQUEST, "잘못된 이미지 파일입니다."), INVALID_FILE_EXTENSION_EXCEPTION(HttpStatus.BAD_REQUEST, "잘못된 파일 확장자입니다."), DUPLICATE_NICKNAME_EXCEPTION(HttpStatus.BAD_REQUEST, "닉네임이 중복되었습니다."), + NOT_EXIST_EXCEPTION(HttpStatus.BAD_REQUEST, "요청으로 전달한 값이 존재하지 않습니다."), /* diff --git a/src/main/java/com/stumeet/server/member/adapter/out/persistence/MemberJpaEntity.java b/src/main/java/com/stumeet/server/member/adapter/out/persistence/MemberJpaEntity.java index 921299de..2fa9754f 100644 --- a/src/main/java/com/stumeet/server/member/adapter/out/persistence/MemberJpaEntity.java +++ b/src/main/java/com/stumeet/server/member/adapter/out/persistence/MemberJpaEntity.java @@ -3,6 +3,7 @@ import com.stumeet.server.common.model.BaseTimeEntity; import com.stumeet.server.member.domain.AuthType; import com.stumeet.server.member.domain.UserRole; +import com.stumeet.server.profession.adapter.out.persistence.ProfessionJpaEntity; import jakarta.persistence.*; import lombok.*; import org.hibernate.annotations.Comment; @@ -22,6 +23,11 @@ public class MemberJpaEntity extends BaseTimeEntity { @Comment("멤버 아이디") private Long id; + @ManyToOne + @JoinColumn(name = "profession_id") + @Comment("분야") + private ProfessionJpaEntity profession; + @Column(name = "name") @Comment("멤버 이름") private String name; @@ -38,10 +44,6 @@ public class MemberJpaEntity extends BaseTimeEntity { @Comment("지역") private String region; - @Column(name = "profession", length = 50) - @Comment("분야") - private String profession; - @Column(name = "auth_type", length = 50, nullable = false) @Enumerated(EnumType.STRING) @Comment("인증 방법(OAuth, 자체 로그인 등)") @@ -49,7 +51,7 @@ public class MemberJpaEntity extends BaseTimeEntity { @Column(name = "role", length = 20, nullable = false) @Enumerated(EnumType.STRING) - @Comment("권한") + @Comment("권한(FIRST_LOGIN, MEMBER)") private UserRole role; @Column(name = "is_deleted", nullable = false) diff --git a/src/main/java/com/stumeet/server/member/adapter/out/persistence/MemberPersistenceMapper.java b/src/main/java/com/stumeet/server/member/adapter/out/persistence/MemberPersistenceMapper.java index 20064ef2..3e6daf95 100644 --- a/src/main/java/com/stumeet/server/member/adapter/out/persistence/MemberPersistenceMapper.java +++ b/src/main/java/com/stumeet/server/member/adapter/out/persistence/MemberPersistenceMapper.java @@ -1,11 +1,16 @@ package com.stumeet.server.member.adapter.out.persistence; import com.stumeet.server.member.domain.Member; +import com.stumeet.server.profession.adapter.out.persistence.ProfessionPersistenceMapper; +import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; @Component +@RequiredArgsConstructor public class MemberPersistenceMapper { + private final ProfessionPersistenceMapper professionPersistenceMapper; + public MemberJpaEntity toEntity(Member domain) { return MemberJpaEntity.builder() .id(domain.getId()) @@ -13,7 +18,7 @@ public MemberJpaEntity toEntity(Member domain) { .image(domain.getImage()) .sugarContents(domain.getSugarContents()) .region(domain.getRegion()) - .profession(domain.getProfession()) + .profession(professionPersistenceMapper.toEntity(domain.getProfession())) .authType(domain.getAuthType()) .role(domain.getRole()) .build(); @@ -26,7 +31,7 @@ public Member toDomain(MemberJpaEntity entity) { .image(entity.getImage()) .sugarContents(entity.getSugarContents()) .region(entity.getRegion()) - .profession(entity.getProfession()) + .profession(professionPersistenceMapper.toDomain(entity.getProfession())) .authType(entity.getAuthType()) .role(entity.getRole()) .build(); diff --git a/src/main/java/com/stumeet/server/member/adapter/out/persistence/OAuthLoginJpaEntity.java b/src/main/java/com/stumeet/server/member/adapter/out/persistence/OAuthLoginJpaEntity.java index 015ce4ca..120d98c1 100644 --- a/src/main/java/com/stumeet/server/member/adapter/out/persistence/OAuthLoginJpaEntity.java +++ b/src/main/java/com/stumeet/server/member/adapter/out/persistence/OAuthLoginJpaEntity.java @@ -26,7 +26,7 @@ public class OAuthLoginJpaEntity extends BaseTimeEntity { @Column(name = "provider_name", length = 50, nullable = false) @Enumerated(EnumType.STRING) - @Comment("제공자 이름") + @Comment("제공자 이름(kakao, apple)") private OAuthProvider providerName; @Column(name = "provider_id", length = 50, nullable = false) diff --git a/src/main/java/com/stumeet/server/member/application/port/in/MemberSignupCommand.java b/src/main/java/com/stumeet/server/member/application/port/in/MemberSignupCommand.java index 01cede70..8ac487ed 100644 --- a/src/main/java/com/stumeet/server/member/application/port/in/MemberSignupCommand.java +++ b/src/main/java/com/stumeet/server/member/application/port/in/MemberSignupCommand.java @@ -16,7 +16,7 @@ public record MemberSignupCommand( @NotBlank(message = "지역을 입력해주세요") String region, - @NotBlank(message = "분야를 선택해주세요") - String profession + @NotNull(message = "분야를 선택해주세요") + Long profession ) { } diff --git a/src/main/java/com/stumeet/server/member/application/service/MemberAuthService.java b/src/main/java/com/stumeet/server/member/application/service/MemberAuthService.java index ec8410d5..885c8412 100644 --- a/src/main/java/com/stumeet/server/member/application/service/MemberAuthService.java +++ b/src/main/java/com/stumeet/server/member/application/service/MemberAuthService.java @@ -7,12 +7,14 @@ import com.stumeet.server.file.application.port.in.FileUploadUseCase; import com.stumeet.server.file.application.port.out.FileUrl; import com.stumeet.server.member.adapter.in.web.response.TokenResponse; -import com.stumeet.server.member.application.port.in.MemberSignupCommand; import com.stumeet.server.member.application.port.in.MemberAuthUseCase; +import com.stumeet.server.member.application.port.in.MemberSignupCommand; import com.stumeet.server.member.application.port.in.TokenRenewCommand; import com.stumeet.server.member.application.port.out.MemberCommandPort; import com.stumeet.server.member.application.port.out.MemberQueryPort; import com.stumeet.server.member.domain.Member; +import com.stumeet.server.profession.application.port.in.ProfessionQueryUseCase; +import com.stumeet.server.profession.domain.Profession; import lombok.RequiredArgsConstructor; import org.springframework.transaction.annotation.Transactional; @@ -26,12 +28,14 @@ public class MemberAuthService implements MemberAuthUseCase { private final FileUploadUseCase fileUploadUseCase; private final RefreshTokenService refreshTokenService; private final JwtTokenProvider jwtTokenProvider; + private final ProfessionQueryUseCase professionQueryUseCase; @Override public void signup(Member member, MemberSignupCommand request) { + Profession profession = professionQueryUseCase.getById(request.profession()); FileUrl url = fileUploadUseCase.uploadUserProfileImage(member.getId(), request.image()); - member.registerWithAdditionalDetails(request, url); + member.registerWithAdditionalDetails(request, url, profession); memberCommandPort.save(member); } diff --git a/src/main/java/com/stumeet/server/member/domain/Member.java b/src/main/java/com/stumeet/server/member/domain/Member.java index bdbe51b9..0d48dd11 100644 --- a/src/main/java/com/stumeet/server/member/domain/Member.java +++ b/src/main/java/com/stumeet/server/member/domain/Member.java @@ -2,7 +2,11 @@ import com.stumeet.server.file.application.port.out.FileUrl; import com.stumeet.server.member.application.port.in.MemberSignupCommand; -import lombok.*; +import com.stumeet.server.profession.domain.Profession; +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; @AllArgsConstructor(access = AccessLevel.PRIVATE) @Builder @@ -10,6 +14,8 @@ public class Member { private Long id; + private Profession profession; + private String name; private String image; @@ -18,17 +24,15 @@ public class Member { private String region; - private String profession; - private AuthType authType; private UserRole role; - public void registerWithAdditionalDetails(MemberSignupCommand request, FileUrl profileImage) { + public void registerWithAdditionalDetails(MemberSignupCommand request, FileUrl profileImage, Profession profession) { this.image = profileImage.url(); this.name = request.nickname(); this.region = request.region(); - this.profession = request.profession(); + this.profession = profession; this.role = UserRole.MEMBER; } } diff --git a/src/main/java/com/stumeet/server/profession/adapter/out/persistence/JpaProfessionRepository.java b/src/main/java/com/stumeet/server/profession/adapter/out/persistence/JpaProfessionRepository.java new file mode 100644 index 00000000..b92919c3 --- /dev/null +++ b/src/main/java/com/stumeet/server/profession/adapter/out/persistence/JpaProfessionRepository.java @@ -0,0 +1,6 @@ +package com.stumeet.server.profession.adapter.out.persistence; + +import org.springframework.data.jpa.repository.JpaRepository; + +public interface JpaProfessionRepository extends JpaRepository { +} diff --git a/src/main/java/com/stumeet/server/profession/adapter/out/persistence/ProfessionJpaEntity.java b/src/main/java/com/stumeet/server/profession/adapter/out/persistence/ProfessionJpaEntity.java new file mode 100644 index 00000000..f98416bb --- /dev/null +++ b/src/main/java/com/stumeet/server/profession/adapter/out/persistence/ProfessionJpaEntity.java @@ -0,0 +1,29 @@ +package com.stumeet.server.profession.adapter.out.persistence; + +import com.stumeet.server.common.model.BaseTimeEntity; +import jakarta.persistence.*; +import lombok.*; +import org.hibernate.annotations.Comment; + +@Entity +@Table(name = "profession") +@NoArgsConstructor(access = AccessLevel.PROTECTED) +@AllArgsConstructor(access = AccessLevel.PRIVATE) +@Builder +@Getter +public class ProfessionJpaEntity extends BaseTimeEntity { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + @Comment("분야 ID") + private Long id; + + @Column(name = "name", nullable = false) + @Comment("이름") + private String name; + + @ManyToOne + @JoinColumn(name = "parent_id") + @Comment("대분류 분야") + private ProfessionJpaEntity parent; +} diff --git a/src/main/java/com/stumeet/server/profession/adapter/out/persistence/ProfessionPersistenceAdapter.java b/src/main/java/com/stumeet/server/profession/adapter/out/persistence/ProfessionPersistenceAdapter.java new file mode 100644 index 00000000..bf6f9c5c --- /dev/null +++ b/src/main/java/com/stumeet/server/profession/adapter/out/persistence/ProfessionPersistenceAdapter.java @@ -0,0 +1,23 @@ +package com.stumeet.server.profession.adapter.out.persistence; + +import com.stumeet.server.common.annotation.PersistenceAdapter; +import com.stumeet.server.common.exception.model.BusinessException; +import com.stumeet.server.common.response.ErrorCode; +import com.stumeet.server.profession.application.port.out.ProfessionQueryPort; +import com.stumeet.server.profession.domain.Profession; +import lombok.RequiredArgsConstructor; + +@PersistenceAdapter +@RequiredArgsConstructor +public class ProfessionPersistenceAdapter implements ProfessionQueryPort { + private final ProfessionPersistenceMapper professionPersistenceMapper; + private final JpaProfessionRepository jpaProfessionRepository; + + @Override + public Profession getById(Long id) { + ProfessionJpaEntity entity = jpaProfessionRepository.findById(id) + .orElseThrow(() -> new BusinessException(ErrorCode.NOT_EXIST_EXCEPTION)); + + return professionPersistenceMapper.toDomain(entity); + } +} diff --git a/src/main/java/com/stumeet/server/profession/adapter/out/persistence/ProfessionPersistenceMapper.java b/src/main/java/com/stumeet/server/profession/adapter/out/persistence/ProfessionPersistenceMapper.java new file mode 100644 index 00000000..402dc3ec --- /dev/null +++ b/src/main/java/com/stumeet/server/profession/adapter/out/persistence/ProfessionPersistenceMapper.java @@ -0,0 +1,50 @@ +package com.stumeet.server.profession.adapter.out.persistence; + +import com.stumeet.server.profession.domain.Profession; +import org.springframework.stereotype.Component; + +@Component +public class ProfessionPersistenceMapper { + + public ProfessionJpaEntity toEntity(Profession domain) { + if (domain == null) { + return null; + } + ProfessionJpaEntity parent = null; + + if (domain.getParent() != null) { + parent = ProfessionJpaEntity.builder() + .id(domain.getId()) + .name(domain.getName()) + .parent(null) + .build(); + } + + return ProfessionJpaEntity.builder() + .id(domain.getId()) + .name(domain.getName()) + .parent(parent) + .build(); + } + + public Profession toDomain(ProfessionJpaEntity entity) { + if (entity == null) { + return null; + } + Profession parent = null; + + if (entity.getParent() != null) { + parent = Profession.builder() + .id(entity.getId()) + .name(entity.getName()) + .parent(null) + .build(); + } + + return Profession.builder() + .id(entity.getId()) + .name(entity.getName()) + .parent(parent) + .build(); + } +} diff --git a/src/main/java/com/stumeet/server/profession/application/port/in/ProfessionQueryUseCase.java b/src/main/java/com/stumeet/server/profession/application/port/in/ProfessionQueryUseCase.java new file mode 100644 index 00000000..297b19ac --- /dev/null +++ b/src/main/java/com/stumeet/server/profession/application/port/in/ProfessionQueryUseCase.java @@ -0,0 +1,7 @@ +package com.stumeet.server.profession.application.port.in; + +import com.stumeet.server.profession.domain.Profession; + +public interface ProfessionQueryUseCase { + Profession getById(Long id); +} diff --git a/src/main/java/com/stumeet/server/profession/application/port/out/ProfessionQueryPort.java b/src/main/java/com/stumeet/server/profession/application/port/out/ProfessionQueryPort.java new file mode 100644 index 00000000..e64cd7b2 --- /dev/null +++ b/src/main/java/com/stumeet/server/profession/application/port/out/ProfessionQueryPort.java @@ -0,0 +1,7 @@ +package com.stumeet.server.profession.application.port.out; + +import com.stumeet.server.profession.domain.Profession; + +public interface ProfessionQueryPort { + Profession getById(Long id); +} diff --git a/src/main/java/com/stumeet/server/profession/application/service/ProfessionQueryService.java b/src/main/java/com/stumeet/server/profession/application/service/ProfessionQueryService.java new file mode 100644 index 00000000..ea8b6c29 --- /dev/null +++ b/src/main/java/com/stumeet/server/profession/application/service/ProfessionQueryService.java @@ -0,0 +1,21 @@ +package com.stumeet.server.profession.application.service; + +import com.stumeet.server.common.annotation.UseCase; +import com.stumeet.server.profession.application.port.in.ProfessionQueryUseCase; +import com.stumeet.server.profession.application.port.out.ProfessionQueryPort; +import com.stumeet.server.profession.domain.Profession; +import lombok.RequiredArgsConstructor; +import org.springframework.transaction.annotation.Transactional; + +@UseCase +@Transactional(readOnly = true) +@RequiredArgsConstructor +public class ProfessionQueryService implements ProfessionQueryUseCase { + + private final ProfessionQueryPort professionQueryPort; + + @Override + public Profession getById(Long id) { + return professionQueryPort.getById(id); + } +} diff --git a/src/main/java/com/stumeet/server/profession/domain/Profession.java b/src/main/java/com/stumeet/server/profession/domain/Profession.java new file mode 100644 index 00000000..90521320 --- /dev/null +++ b/src/main/java/com/stumeet/server/profession/domain/Profession.java @@ -0,0 +1,19 @@ +package com.stumeet.server.profession.domain; + +import lombok.AccessLevel; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Getter; + +@AllArgsConstructor(access = AccessLevel.PRIVATE) +@Builder +@Getter +public class Profession { + + private Long id; + + private String name; + + private Profession parent; + +}