From b444817f700a70c54217473407bc4feeacaa839c Mon Sep 17 00:00:00 2001 From: zxcv9203 <41960243+zxcv9203@users.noreply.github.com> Date: Wed, 28 Feb 2024 22:47:20 +0900 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=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=20?= =?UTF-8?q?(#54)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * :wrench: [STMT-146] DB 스키마와 데이터를 flyway를 통해 형상관리 하도록 변경 * :sparkles: [STMT-146] 분야 정보를 관리하는 도메인 정의 --- .../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 ++ src/main/resources/application-local.yml | 2 +- src/main/resources/application-prod.yml | 2 +- .../V1.1__insert_profession_data.sql | 189 ++++++++++++++++++ src/main/resources/db/migration/V1__init.sql | 53 +++++ src/test/resources/application.yml | 2 +- 20 files changed, 440 insertions(+), 20 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 create mode 100644 src/main/resources/db/migration/V1.1__insert_profession_data.sql create mode 100644 src/main/resources/db/migration/V1__init.sql 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; + +} diff --git a/src/main/resources/application-local.yml b/src/main/resources/application-local.yml index 6e3b70fd..68ac5949 100644 --- a/src/main/resources/application-local.yml +++ b/src/main/resources/application-local.yml @@ -14,7 +14,7 @@ spring: port: 6379 jpa: hibernate: - ddl-auto: update + ddl-auto: none properties: hibernate: show_sql: true diff --git a/src/main/resources/application-prod.yml b/src/main/resources/application-prod.yml index 25cf7a2b..d9b599f2 100644 --- a/src/main/resources/application-prod.yml +++ b/src/main/resources/application-prod.yml @@ -17,7 +17,7 @@ spring: port: ${REDIS_PORT} jpa: hibernate: - ddl-auto: validate + ddl-auto: none properties: hibernate: show_sql: true diff --git a/src/main/resources/db/migration/V1.1__insert_profession_data.sql b/src/main/resources/db/migration/V1.1__insert_profession_data.sql new file mode 100644 index 00000000..cb87f4f9 --- /dev/null +++ b/src/main/resources/db/migration/V1.1__insert_profession_data.sql @@ -0,0 +1,189 @@ +INSERT INTO `profession` (name, parent_id) +VALUES ('경영사무', NULL); + +INSERT INTO `profession` (name, parent_id) +VALUES ('기획전략경영', (SELECT id FROM profession WHERE name = '경영사무')), + ('경영분석·컨설턴트', (SELECT id FROM profession WHERE name = '경영사무')), + ('고객상담·인바운드', (SELECT id FROM profession WHERE name = '경영사무')), + ('감리·공무', (SELECT id FROM profession WHERE name = '경영사무')), + ('결산', (SELECT id FROM profession WHERE name = '경영사무')), + ('경리', (SELECT id FROM profession WHERE name = '경영사무')), + ('인사', (SELECT id FROM profession WHERE name = '경영사무')), + ('영업', (SELECT id FROM profession WHERE name = '경영사무')), + ('영업관리·지원·영업기획', (SELECT id FROM profession WHERE name = '경영사무')), + ('재무', (SELECT id FROM profession WHERE name = '경영사무')), + ('사무', (SELECT id FROM profession WHERE name = '경영사무')), + ('사무보조', (SELECT id FROM profession WHERE name = '경영사무')), + ('노무', (SELECT id FROM profession WHERE name = '경영사무')), + ('해외영업·무역영업', (SELECT id FROM profession WHERE name = '경영사무')), + ('헤드헌터', (SELECT id FROM profession WHERE name = '경영사무')), + ('총무', (SELECT id FROM profession WHERE name = '경영사무')), + ('IR', (SELECT id FROM profession WHERE name = '경영사무')); + +INSERT INTO profession (name, parent_id) +VALUES ('마케팅·광고·홍보', NULL); + +INSERT INTO profession (name, parent_id) +VALUES ('광고제작·카피·CF', (SELECT id FROM profession WHERE name = '마케팅·광고·홍보')), + ('리서치·통계·설문', (SELECT id FROM profession WHERE name = '마케팅·광고·홍보')), + ('마케팅', (SELECT id FROM profession WHERE name = '마케팅·광고·홍보')), + ('매장관리', (SELECT id FROM profession WHERE name = '마케팅·광고·홍보')), + ('상품기획·MD', (SELECT id FROM profession WHERE name = '마케팅·광고·홍보')); + +INSERT INTO profession (name, parent_id) +VALUES ('디자인', NULL); + +INSERT INTO profession (name, parent_id) +VALUES ('광고디자인', (SELECT id FROM profession WHERE name = '디자인')), + ('그래픽디자인', (SELECT id FROM profession WHERE name = '디자인')), + ('의류·패션·잡화디자인', (SELECT id FROM profession WHERE name = '디자인')), + ('UI/UX 디자인', (SELECT id FROM profession WHERE name = '디자인')), + ('시각디자인', (SELECT id FROM profession WHERE name = '디자인')), + ('실내디자인', (SELECT id FROM profession WHERE name = '디자인')), + ('전시·공간디자인', (SELECT id FROM profession WHERE name = '디자인')), + ('조경디자인', (SELECT id FROM profession WHERE name = '디자인')), + ('제품·산업디자인', (SELECT id FROM profession WHERE name = '디자인')), + ('캐릭터·애니매이션디자인', (SELECT id FROM profession WHERE name = '디자인')), + ('CG디자인', (SELECT id FROM profession WHERE name = '디자인')); + +INSERT INTO profession (name, parent_id) +VALUES ('무역·유통', NULL); + +INSERT INTO profession (name, parent_id) +VALUES ('배송·택배·운송', (SELECT id FROM profession WHERE name = '무역·유통')), + ('유통·물류·재고', (SELECT id FROM profession WHERE name = '무역·유통')), + ('수출입·무역 사무', (SELECT id FROM profession WHERE name = '무역·유통')); + +INSERT INTO profession (name, parent_id) +VALUES ('영업·고객상담', NULL); + +INSERT INTO profession (name, parent_id) +VALUES ('직업상담', (SELECT id FROM profession WHERE name = '영업·고객상담')), + ('보험·보상', (SELECT id FROM profession WHERE name = '영업·고객상담')), + ('아웃바운드·TM', (SELECT id FROM profession WHERE name = '영업·고객상담')), + ('부동산·중개·분양·경매', (SELECT id FROM profession WHERE name = '영업·고객상담')); + +INSERT INTO profession (name, parent_id) +VALUES ('서비스', NULL); + +INSERT INTO profession (name, parent_id) +VALUES ('가사·육아', (SELECT id FROM profession WHERE name = '서비스')), + ('요양보호', (SELECT id FROM profession WHERE name = '서비스')), + ('숙박', (SELECT id FROM profession WHERE name = '서비스')), + ('사회복지', (SELECT id FROM profession WHERE name = '서비스')), + ('설치·장비·A/S', (SELECT id FROM profession WHERE name = '서비스')); + +INSERT INTO profession (name, parent_id) +VALUES ('연구개발·설계', NULL); + +INSERT INTO profession (name, parent_id) +VALUES ('시스템설계', (SELECT id FROM profession WHERE name = '연구개발·설계')), + ('시스템분석', (SELECT id FROM profession WHERE name = '연구개발·설계')), + ('전기·소방·통신·안전', (SELECT id FROM profession WHERE name = '연구개발·설계')), + ('전기·전자·제어', (SELECT id FROM profession WHERE name = '연구개발·설계')); + +INSERT INTO profession (name, parent_id) +VALUES ('교육', NULL); + +INSERT INTO profession (name, parent_id) +VALUES ('강사', (SELECT id FROM profession WHERE name = '교육')), + ('교사', (SELECT id FROM profession WHERE name = '교육')); + +INSERT INTO profession (name, parent_id) +VALUES ('건설·건축', NULL); + +INSERT INTO profession (name, parent_id) +VALUES ('구매·자재', (SELECT id FROM profession WHERE name = '건설·건축')), + ('기계설계', (SELECT id FROM profession WHERE name = '건설·건축')), + ('인테리어', (SELECT id FROM profession WHERE name = '건설·건축')), + ('화물·중장비', (SELECT id FROM profession WHERE name = '건설·건축')), + ('토목·조경·도시·측량', (SELECT id FROM profession WHERE name = '건설·건축')), + ('시공·현장', (SELECT id FROM profession WHERE name = '건설·건축')); + +INSERT INTO profession (name, parent_id) +VALUES ('미디어·문화', NULL); + +INSERT INTO profession (name, parent_id) +VALUES ('공연·전시', (SELECT id FROM profession WHERE name = '미디어·문화')), + ('기자', (SELECT id FROM profession WHERE name = '미디어·문화')), + ('연예·엔터테인먼트', (SELECT id FROM profession WHERE name = '미디어·문화')), + ('무대·스텝', (SELECT id FROM profession WHERE name = '미디어·문화')), + ('문화콘텐츠 제작', (SELECT id FROM profession WHERE name = '미디어·문화')), + ('영상 제작', (SELECT id FROM profession WHERE name = '미디어·문화')), + ('영화·배급', (SELECT id FROM profession WHERE name = '미디어·문화')), + ('레저·스포츠', (SELECT id FROM profession WHERE name = '미디어·문화')), + ('아나운서·리포터·성우', (SELECT id FROM profession WHERE name = '미디어·문화')), + ('음악·음향', (SELECT id FROM profession WHERE name = '미디어·문화')), + ('문화콘텐츠 유통·서비스', (SELECT id FROM profession WHERE name = '미디어·문화')), + ('인쇄·출판·편집', (SELECT id FROM profession WHERE name = '미디어·문화')), + ('작가·시나리오', (SELECT id FROM profession WHERE name = '미디어·문화')), + ('전시 기획', (SELECT id FROM profession WHERE name = '미디어·문화')); + +INSERT INTO profession (name, parent_id) +VALUES ('전문·특수·연구직', NULL); + +INSERT INTO profession (name, parent_id) +VALUES ('바이오·제약·식품', (SELECT id FROM profession WHERE name = '전문·특수·연구직')), + ('바리스타', (SELECT id FROM profession WHERE name = '전문·특수·연구직')), + ('도서관 사서', (SELECT id FROM profession WHERE name = '전문·특수·연구직')), + ('법률·특허·상표', (SELECT id FROM profession WHERE name = '전문·특수·연구직')), + ('법무', (SELECT id FROM profession WHERE name = '전문·특수·연구직')), + ('법인영업', (SELECT id FROM profession WHERE name = '전문·특수·연구직')), + ('제과제빵사', (SELECT id FROM profession WHERE name = '전문·특수·연구직')), + ('영양사', (SELECT id FROM profession WHERE name = '전문·특수·연구직')), + ('요리사', (SELECT id FROM profession WHERE name = '전문·특수·연구직')), + ('애견 미용', (SELECT id FROM profession WHERE name = '전문·특수·연구직')), + ('뷰티·미용', (SELECT id FROM profession WHERE name = '전문·특수·연구직')), + ('채권·심사', (SELECT id FROM profession WHERE name = '전문·특수·연구직')), + ('외국어·번역·통역', (SELECT id FROM profession WHERE name = '전문·특수·연구직')), + ('항공', (SELECT id FROM profession WHERE name = '전문·특수·연구직')), + ('CPA', (SELECT id FROM profession WHERE name = '전문·특수·연구직')), + ('CAD', (SELECT id FROM profession WHERE name = '전문·특수·연구직')), + ('CAM', (SELECT id FROM profession WHERE name = '전문·특수·연구직')), + ('화학·에너지·환경', (SELECT id FROM profession WHERE name = '전문·특수·연구직')), + ('이벤트·웨딩·도우미', (SELECT id FROM profession WHERE name = '전문·특수·연구직')), + ('연구소·R&D', (SELECT id FROM profession WHERE name = '전문·특수·연구직')), + ('자동차·조선·기계', (SELECT id FROM profession WHERE name = '전문·특수·연구직')), + ('운전·기사', (SELECT id FROM profession WHERE name = '전문·특수·연구직')), + ('보안·경호', (SELECT id FROM profession WHERE name = '전문·특수·연구직')); + +INSERT INTO profession (name, parent_id) +VALUES ('IT', NULL); + +INSERT INTO profession (name, parent_id) +VALUES ('게임 개발', (SELECT id FROM profession WHERE name = 'IT')), + ('데이터베이스', (SELECT id FROM profession WHERE name = 'IT')), + ('빅데이터', (SELECT id FROM profession WHERE name = 'IT')), + ('네트워크·서버·보안', (SELECT id FROM profession WHERE name = 'IT')), + ('웹프로그래머', (SELECT id FROM profession WHERE name = 'IT')), + ('PM', (SELECT id FROM profession WHERE name = 'IT')), + ('QA', (SELECT id FROM profession WHERE name = 'IT')), + ('응용프로그래머', (SELECT id FROM profession WHERE name = 'IT')), + ('반도체·디스플레이', (SELECT id FROM profession WHERE name = 'IT')), + ('AI(인공지능)', (SELECT id FROM profession WHERE name = 'IT')), + ('프론트엔드', (SELECT id FROM profession WHERE name = 'IT')), + ('하드웨어 관리자', (SELECT id FROM profession WHERE name = 'IT')), + ('통신기술·네트워크구축', (SELECT id FROM profession WHERE name = 'IT')), + ('퍼블리셔', (SELECT id FROM profession WHERE name = 'IT')), + ('CS관리·강의', (SELECT id FROM profession WHERE name = 'IT')), + ('DBA', (SELECT id FROM profession WHERE name = 'IT')), + ('ERP', (SELECT id FROM profession WHERE name = 'IT')); + +INSERT INTO profession (name, parent_id) +VALUES ('의료', NULL); + +INSERT INTO profession (name, parent_id) +VALUES ('간호 조무사', (SELECT id FROM profession WHERE name = '의료')), + ('간호사', (SELECT id FROM profession WHERE name = '의료')), + ('치과 의사', (SELECT id FROM profession WHERE name = '의료')), + ('의사', (SELECT id FROM profession WHERE name = '의료')), + ('약무보조', (SELECT id FROM profession WHERE name = '의료')), + ('약사', (SELECT id FROM profession WHERE name = '의료')), + ('의료기사', (SELECT id FROM profession WHERE name = '의료')), + ('의료직기타', (SELECT id FROM profession WHERE name = '의료')), + ('병원 코디네이터', (SELECT id FROM profession WHERE name = '의료')), + ('수의간호사', (SELECT id FROM profession WHERE name = '의료')), + ('수의사', (SELECT id FROM profession WHERE name = '의료')), + ('한약사', (SELECT id FROM profession WHERE name = '의료')), + ('한의사', (SELECT id FROM profession WHERE name = '의료')), + ('원무', (SELECT id FROM profession WHERE name = '의료')); \ No newline at end of file diff --git a/src/main/resources/db/migration/V1__init.sql b/src/main/resources/db/migration/V1__init.sql new file mode 100644 index 00000000..d84e6ea4 --- /dev/null +++ b/src/main/resources/db/migration/V1__init.sql @@ -0,0 +1,53 @@ +CREATE TABLE IF NOT EXISTS `profession` +( + `id` BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT '분야 ID', + `name` VARCHAR(255) NOT NULL COMMENT '이름', + `parent_id` BIGINT NULL COMMENT '대분류 분야', + `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '생성 시간', + `updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '수정 시간', + + CONSTRAINT fk_parent FOREIGN KEY (parent_id) + REFERENCES profession (id) + ON DELETE CASCADE ON UPDATE CASCADE +) ENGINE = InnoDB + DEFAULT CHARSET = utf8mb4 + COLLATE = utf8mb4_unicode_ci; + +CREATE TABLE IF NOT EXISTS `member` +( + `id` BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT '멤버 아이디', + `profession_id` BIGINT NULL COMMENT '분야 ID', + `name` VARCHAR(255) NULL COMMENT '멤버 이름', + `image` VARCHAR(500) NULL COMMENT '멤버 이미지 URL', + `sugar_contents` DOUBLE NOT NULL DEFAULT 0 COMMENT '포도알 당도', + `region` VARCHAR(50) NULL COMMENT '지역', + `auth_type` VARCHAR(50) NOT NULL COMMENT '인증 방법(OAuth, 자체 로그인 등)', + `role` VARCHAR(20) NOT NULL COMMENT '권한(FIRST_LOGIN, MEMBER)', + `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '생성 시간', + `updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '수정 시간', + `is_deleted` tinyint(1) NOT NULL COMMENT '삭제 여부', + `deleted_at` DATETIME NULL COMMENT '삭제된 시간', + + CONSTRAINT fk_member_profession FOREIGN KEY (profession_id) + REFERENCES profession (id) + ON DELETE RESTRICT ON UPDATE CASCADE +) ENGINE = InnoDB + DEFAULT CHARSET = utf8mb4 + COLLATE = utf8mb4_unicode_ci; + + +CREATE TABLE IF NOT EXISTS `oauth_login` +( + `id` BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY COMMENT 'OAuth 로그인 정보 ID', + `member_id` BIGINT NOT NULL COMMENT '멤버 ID', + `provider_name` VARCHAR(50) NOT NULL COMMENT '제공자 이름(kakao, apple)', + `provider_id` VARCHAR(50) NOT NULL COMMENT 'OAuth 사용자 고유 아이디', + `created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '생성 시간', + `updated_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '수정 시간', + + CONSTRAINT fk_oauth_login_member FOREIGN KEY (member_id) + REFERENCES member (id) +) ENGINE = InnoDB + DEFAULT CHARSET = utf8mb4 + COLLATE = utf8mb4_unicode_ci; + diff --git a/src/test/resources/application.yml b/src/test/resources/application.yml index 14cc759b..911b1220 100644 --- a/src/test/resources/application.yml +++ b/src/test/resources/application.yml @@ -13,7 +13,7 @@ spring: port: 6379 jpa: hibernate: - ddl-auto: update + ddl-auto: none properties: hibernate: show_sql: true