From 46e7c7a77998b820e75195094e989af2ed0b4654 Mon Sep 17 00:00:00 2001 From: wlgns12370 Date: Sun, 10 Aug 2025 00:55:55 +0900 Subject: [PATCH 1/6] =?UTF-8?q?MOSU-264=20refactor:=20Dirty=20Checking?= =?UTF-8?q?=EC=9D=84=20=EC=9C=84=ED=95=9C=20Transaction=20=EB=B6=84?= =?UTF-8?q?=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../oauth/OAuthUserPersistenceProcessor.java | 51 +++++++++++++++++++ .../application/oauth/OAuthUserService.java | 43 +++------------- .../domain/user/entity/UserJpaEntity.java | 4 +- 3 files changed, 60 insertions(+), 38 deletions(-) create mode 100644 src/main/java/life/mosu/mosuserver/application/oauth/OAuthUserPersistenceProcessor.java diff --git a/src/main/java/life/mosu/mosuserver/application/oauth/OAuthUserPersistenceProcessor.java b/src/main/java/life/mosu/mosuserver/application/oauth/OAuthUserPersistenceProcessor.java new file mode 100644 index 00000000..d30a9f13 --- /dev/null +++ b/src/main/java/life/mosu/mosuserver/application/oauth/OAuthUserPersistenceProcessor.java @@ -0,0 +1,51 @@ +package life.mosu.mosuserver.application.oauth; + +import java.time.LocalDate; +import life.mosu.mosuserver.domain.profile.entity.Gender; +import life.mosu.mosuserver.domain.user.entity.AuthProvider; +import life.mosu.mosuserver.domain.user.entity.UserJpaEntity; +import life.mosu.mosuserver.domain.user.entity.UserRole; +import life.mosu.mosuserver.domain.user.repository.UserJpaRepository; +import life.mosu.mosuserver.global.processor.StepProcessor; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; + +@Component +@RequiredArgsConstructor +public class OAuthUserPersistenceProcessor implements StepProcessor { + + private final UserJpaRepository userRepository; + + @Override + @Transactional + public UserJpaEntity process(final OAuthUserInfo info) { + return userRepository.findByLoginId(info.email()) + .map(existingUser -> { + existingUser.updateOAuthUser( + info.gender(), + info.name(), + info.phoneNumber(), + info.birthDay() != null ? info.birthDay() : LocalDate.of(1900, 1, 1), + info.marketingAgreed()); + return existingUser; + }) + .orElseGet(() -> { + final UserJpaEntity newUser = UserJpaEntity.builder() + .loginId(info.email() != null ? info.email() : "NA") + .gender(info.gender() != null ? info.gender() : Gender.PENDING) + .name(info.name() != null ? info.name() : "NA") + .birth(info.birthDay() != null ? info.birthDay() + : LocalDate.EPOCH) + .phoneNumber(info.phoneNumber() != null ? info.phoneNumber() + : "010-0000-0000") + .userRole(UserRole.ROLE_PENDING) + .provider(AuthProvider.KAKAO) + .agreedToTermsOfService(true) + .agreedToPrivacyPolicy(true) + .agreedToMarketing(info.marketingAgreed()) + .build(); + return userRepository.save(newUser); + }); + } +} diff --git a/src/main/java/life/mosu/mosuserver/application/oauth/OAuthUserService.java b/src/main/java/life/mosu/mosuserver/application/oauth/OAuthUserService.java index f67b968d..50e42024 100644 --- a/src/main/java/life/mosu/mosuserver/application/oauth/OAuthUserService.java +++ b/src/main/java/life/mosu/mosuserver/application/oauth/OAuthUserService.java @@ -1,15 +1,10 @@ package life.mosu.mosuserver.application.oauth; -import java.time.LocalDate; import java.util.Collections; import java.util.List; import java.util.Map; -import life.mosu.mosuserver.domain.profile.entity.Gender; import life.mosu.mosuserver.domain.profile.repository.ProfileJpaRepository; -import life.mosu.mosuserver.domain.user.entity.AuthProvider; import life.mosu.mosuserver.domain.user.entity.UserJpaEntity; -import life.mosu.mosuserver.domain.user.entity.UserRole; -import life.mosu.mosuserver.domain.user.repository.UserJpaRepository; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.core.ParameterizedTypeReference; @@ -25,7 +20,7 @@ @RequiredArgsConstructor public class OAuthUserService extends DefaultOAuth2UserService { - private final UserJpaRepository userRepository; + private final OAuthUserPersistenceProcessor OAuthUserPersistenceProcessor; private final ProfileJpaRepository profileRepository; private final WebClient webClient; @@ -44,12 +39,15 @@ public OAuth2User loadUser(final OAuth2UserRequest userRequest) agreedToMarketing = termsList.stream() .filter(term -> term instanceof Map) .map(term -> (Map) term) - .filter(termMap -> "terms_03".equals(termMap.get("tag"))) + .filter(termMap -> + "terms_03".equals(termMap.get("tag"))) .findFirst() .map(termMap -> (Boolean) termMap.get("agreed")) .orElse(false); } + log.info("동의 여부{}", agreedToMarketing); + final String registrationId = userRequest.getClientRegistration().getRegistrationId(); final String userNameAttributeName = userRequest.getClientRegistration() .getProviderDetails() @@ -59,7 +57,7 @@ public OAuth2User loadUser(final OAuth2UserRequest userRequest) final OAuthUserInfo userInfo = OAuthUserInfo.of(OAuthProvider.from(registrationId), oAuth2UserAttributes, agreedToMarketing); - final UserJpaEntity oAuthUser = updateOrWrite(userInfo); + final UserJpaEntity oAuthUser = OAuthUserPersistenceProcessor.process(userInfo); Boolean isProfileRegistered = profileRepository.existsByUserId(oAuthUser.getId()); @@ -67,35 +65,6 @@ public OAuth2User loadUser(final OAuth2UserRequest userRequest) isProfileRegistered); } - private UserJpaEntity updateOrWrite(final OAuthUserInfo info) { - return userRepository.findByLoginId(info.email()) - .map(existingUser -> { - existingUser.updateOAuthUser( - info.gender(), - info.name(), - info.phoneNumber(), - info.birthDay() != null ? info.birthDay() : LocalDate.of(1900, 1, 1)); - return existingUser; - }) - .orElseGet(() -> { - final UserJpaEntity newUser = UserJpaEntity.builder() - .loginId(info.email() != null ? info.email() : "NA") - .gender(info.gender() != null ? info.gender() : Gender.PENDING) - .name(info.name() != null ? info.name() : "NA") - .birth(info.birthDay() != null ? info.birthDay() - : LocalDate.EPOCH) - .phoneNumber(info.phoneNumber() != null ? info.phoneNumber() - : "010-0000-0000") - .userRole(UserRole.ROLE_PENDING) - .provider(AuthProvider.KAKAO) - .agreedToTermsOfService(true) - .agreedToPrivacyPolicy(true) - .agreedToMarketing(info.marketingAgreed()) - .build(); - return userRepository.save(newUser); - }); - } - private Map getServiceTerms(String accessToken) { String url = "https://kapi.kakao.com/v2/user/service_terms"; diff --git a/src/main/java/life/mosu/mosuserver/domain/user/entity/UserJpaEntity.java b/src/main/java/life/mosu/mosuserver/domain/user/entity/UserJpaEntity.java index 280b4a13..a936bcc2 100644 --- a/src/main/java/life/mosu/mosuserver/domain/user/entity/UserJpaEntity.java +++ b/src/main/java/life/mosu/mosuserver/domain/user/entity/UserJpaEntity.java @@ -93,12 +93,14 @@ public void updateOAuthUser( Gender gender, String name, String phoneNumber, - LocalDate birth + LocalDate birth, + boolean agreedToMarketing ) { this.gender = gender; this.name = name; this.phoneNumber = phoneNumber; this.birth = birth; + this.agreedToMarketing = agreedToMarketing; } public void updateUserInfo( From 34a04b513bd49c2e4475b2b1818c66e5c1b0af6e Mon Sep 17 00:00:00 2001 From: wlgns12370 Date: Sun, 10 Aug 2025 00:56:19 +0900 Subject: [PATCH 2/6] =?UTF-8?q?MOSU-264=20test:=20=EB=A7=88=EC=BC=80?= =?UTF-8?q?=ED=8C=85=20=EB=8F=99=EC=9D=98=20=EC=97=AC=EB=B6=80=20=ED=8C=8C?= =?UTF-8?q?=EC=8B=B1=20=ED=85=8C=EC=8A=A4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../oauth/OAuthUserServiceTest.java | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 src/test/java/life/mosu/mosuserver/application/oauth/OAuthUserServiceTest.java diff --git a/src/test/java/life/mosu/mosuserver/application/oauth/OAuthUserServiceTest.java b/src/test/java/life/mosu/mosuserver/application/oauth/OAuthUserServiceTest.java new file mode 100644 index 00000000..a52a9f59 --- /dev/null +++ b/src/test/java/life/mosu/mosuserver/application/oauth/OAuthUserServiceTest.java @@ -0,0 +1,46 @@ +package life.mosu.mosuserver.application.oauth; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Nested; +import org.junit.jupiter.api.Test; + +@Nested +@DisplayName("카카오_추가기능_응답_테스트") +class OAuthUserServiceTest { + + @Test + @DisplayName("Service Terms 응답에 마케팅 동의(terms_03)가 없는 경우 false로 파싱한다") + void 마케팅_동의_여부를_파싱한다() { + Map term1 = Map.of( + "tag", "terms_02", + "required", true, + "agreed", true + ); + Map term2 = Map.of( + "tag", "terms_01", + "required", true, + "agreed", true + ); + + Map serviceTermsAttributes = new HashMap<>(); + serviceTermsAttributes.put("id", 4342056184L); + serviceTermsAttributes.put("service_terms", List.of(term1, term2)); + + boolean agreedToMarketing = false; + if (serviceTermsAttributes.get("service_terms") instanceof List termsList) { + agreedToMarketing = termsList.stream() + .filter(term -> term instanceof Map) + .map(term -> (Map) term) + .filter(termMap -> "terms_03".equals(termMap.get("tag"))) + .findFirst() + .map(termMap -> (Boolean) termMap.get("agreed")) + .orElse(false); + } + + Assertions.assertFalse(agreedToMarketing); + } +} \ No newline at end of file From 6bd062b9605363b0d37f54273b451e827a90615c Mon Sep 17 00:00:00 2001 From: wlgns12370 Date: Sun, 10 Aug 2025 00:57:05 +0900 Subject: [PATCH 3/6] =?UTF-8?q?MOSU-264=20test:=20=ED=85=8C=EC=8A=A4?= =?UTF-8?q?=ED=8A=B8=20=EC=A4=91=EB=B3=B5=20=EB=A1=9C=EC=A7=81=20=EC=82=AD?= =?UTF-8?q?=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) diff --git a/build.gradle b/build.gradle index 99ddb470..55d7bc5e 100644 --- a/build.gradle +++ b/build.gradle @@ -29,16 +29,17 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-jpa' implementation 'org.springframework.boot:spring-boot-starter-web' implementation 'org.springframework.boot:spring-boot-starter-validation' - testImplementation 'org.projectlombok:lombok' - testImplementation 'org.projectlombok:lombok' - testCompileOnly 'org.projectlombok:lombok' - testAnnotationProcessor 'org.projectlombok:lombok' developmentOnly 'org.springframework.boot:spring-boot-devtools' - compileOnly 'org.projectlombok:lombok' - annotationProcessor 'org.projectlombok:lombok' testImplementation 'org.springframework.boot:spring-boot-starter-test' testRuntimeOnly 'org.junit.platform:junit-platform-launcher' + // Lombok + compileOnly 'org.projectlombok:lombok' + annotationProcessor 'org.projectlombok:lombok' + testCompileOnly 'org.projectlombok:lombok' + testImplementation 'org.projectlombok:lombok' + testAnnotationProcessor 'org.projectlombok:lombok' + // 인증사 관련 의존성 implementation 'javax.servlet:jstl:1.2' implementation "org.apache.tomcat.embed:tomcat-embed-jasper" @@ -69,7 +70,6 @@ dependencies { testImplementation 'org.testcontainers:junit-jupiter:1.19.3' testImplementation 'org.testcontainers:mysql:1.20.0' - // security implementation 'org.springframework.boot:spring-boot-starter-security' implementation 'org.springframework.boot:spring-boot-starter-oauth2-client' @@ -103,11 +103,6 @@ dependencies { runtimeOnly 'com.h2database:h2' - testImplementation 'org.springframework.boot:spring-boot-testcontainers:3.3.5' - testImplementation 'org.testcontainers:testcontainers:1.19.3' - testImplementation 'org.testcontainers:junit-jupiter:1.19.3' - testImplementation 'org.testcoscntainers:mysql:1.20.0' - annotationProcessor "org.springframework.boot:spring-boot-configuration-processor" implementation 'org.apache.commons:commons-pool2:2.12.1' From caa07238fc231f7ccf925278168e24b19e23e4f7 Mon Sep 17 00:00:00 2001 From: wlgns12370 Date: Sun, 10 Aug 2025 01:05:59 +0900 Subject: [PATCH 4/6] =?UTF-8?q?MOSU-264=20refactor:=20null=20=EA=B2=80?= =?UTF-8?q?=EC=A6=9D=20=EB=A1=9C=EC=A7=81=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../oauth/OAuthUserPersistenceProcessor.java | 16 ++++++---------- .../application/oauth/OAuthUserService.java | 4 ++-- 2 files changed, 8 insertions(+), 12 deletions(-) diff --git a/src/main/java/life/mosu/mosuserver/application/oauth/OAuthUserPersistenceProcessor.java b/src/main/java/life/mosu/mosuserver/application/oauth/OAuthUserPersistenceProcessor.java index d30a9f13..3e823364 100644 --- a/src/main/java/life/mosu/mosuserver/application/oauth/OAuthUserPersistenceProcessor.java +++ b/src/main/java/life/mosu/mosuserver/application/oauth/OAuthUserPersistenceProcessor.java @@ -1,7 +1,5 @@ package life.mosu.mosuserver.application.oauth; -import java.time.LocalDate; -import life.mosu.mosuserver.domain.profile.entity.Gender; import life.mosu.mosuserver.domain.user.entity.AuthProvider; import life.mosu.mosuserver.domain.user.entity.UserJpaEntity; import life.mosu.mosuserver.domain.user.entity.UserRole; @@ -26,19 +24,17 @@ public UserJpaEntity process(final OAuthUserInfo info) { info.gender(), info.name(), info.phoneNumber(), - info.birthDay() != null ? info.birthDay() : LocalDate.of(1900, 1, 1), + info.birthDay(), info.marketingAgreed()); return existingUser; }) .orElseGet(() -> { final UserJpaEntity newUser = UserJpaEntity.builder() - .loginId(info.email() != null ? info.email() : "NA") - .gender(info.gender() != null ? info.gender() : Gender.PENDING) - .name(info.name() != null ? info.name() : "NA") - .birth(info.birthDay() != null ? info.birthDay() - : LocalDate.EPOCH) - .phoneNumber(info.phoneNumber() != null ? info.phoneNumber() - : "010-0000-0000") + .loginId(info.email()) + .gender(info.gender()) + .name(info.name()) + .birth(info.birthDay()) + .phoneNumber(info.phoneNumber()) .userRole(UserRole.ROLE_PENDING) .provider(AuthProvider.KAKAO) .agreedToTermsOfService(true) diff --git a/src/main/java/life/mosu/mosuserver/application/oauth/OAuthUserService.java b/src/main/java/life/mosu/mosuserver/application/oauth/OAuthUserService.java index 50e42024..3c0ddf67 100644 --- a/src/main/java/life/mosu/mosuserver/application/oauth/OAuthUserService.java +++ b/src/main/java/life/mosu/mosuserver/application/oauth/OAuthUserService.java @@ -20,7 +20,7 @@ @RequiredArgsConstructor public class OAuthUserService extends DefaultOAuth2UserService { - private final OAuthUserPersistenceProcessor OAuthUserPersistenceProcessor; + private final OAuthUserPersistenceProcessor oAuthUserPersistenceProcessor; private final ProfileJpaRepository profileRepository; private final WebClient webClient; @@ -57,7 +57,7 @@ public OAuth2User loadUser(final OAuth2UserRequest userRequest) final OAuthUserInfo userInfo = OAuthUserInfo.of(OAuthProvider.from(registrationId), oAuth2UserAttributes, agreedToMarketing); - final UserJpaEntity oAuthUser = OAuthUserPersistenceProcessor.process(userInfo); + final UserJpaEntity oAuthUser = oAuthUserPersistenceProcessor.process(userInfo); Boolean isProfileRegistered = profileRepository.existsByUserId(oAuthUser.getId()); From df0354ebc1e958abc08e11d782349544fbde45b9 Mon Sep 17 00:00:00 2001 From: wlgns12370 Date: Sun, 10 Aug 2025 01:08:58 +0900 Subject: [PATCH 5/6] =?UTF-8?q?MOSU-264=20test:=20@Nested=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mosu/mosuserver/application/oauth/OAuthUserServiceTest.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/test/java/life/mosu/mosuserver/application/oauth/OAuthUserServiceTest.java b/src/test/java/life/mosu/mosuserver/application/oauth/OAuthUserServiceTest.java index a52a9f59..e38ce290 100644 --- a/src/test/java/life/mosu/mosuserver/application/oauth/OAuthUserServiceTest.java +++ b/src/test/java/life/mosu/mosuserver/application/oauth/OAuthUserServiceTest.java @@ -5,10 +5,8 @@ import java.util.Map; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.DisplayName; -import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; -@Nested @DisplayName("카카오_추가기능_응답_테스트") class OAuthUserServiceTest { From 572ddb0ed64d1b9d34a7950aec7017e998643c79 Mon Sep 17 00:00:00 2001 From: wlgns12370 Date: Sun, 10 Aug 2025 01:18:28 +0900 Subject: [PATCH 6/6] =?UTF-8?q?MOSU-264=20feat:=20DDL=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/db/migration/V1__init.sql | 383 +++++++++++++++++++ 1 file changed, 383 insertions(+) create mode 100644 src/main/resources/db/migration/V1__init.sql 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..5b9166af --- /dev/null +++ b/src/main/resources/db/migration/V1__init.sql @@ -0,0 +1,383 @@ +CREATE TABLE application +( + application_id BIGINT AUTO_INCREMENT NOT NULL, + created_at datetime NULL, + updated_at datetime NULL, + deleted BIT(1) NULL, + user_id BIGINT NULL, + parent_phone_number VARCHAR(255) NULL, + application_status VARCHAR(255) NOT NULL, + agreed_to_notices BIT(1) NULL, + agreed_to_refund_policy BIT(1) NULL, + CONSTRAINT pk_application PRIMARY KEY (application_id) +); + +CREATE TABLE application_failure_log +( + application_failure_id BIGINT AUTO_INCREMENT NOT NULL, + created_at datetime NULL, + updated_at datetime NULL, + application_id BIGINT NOT NULL, + user_id BIGINT NOT NULL, + reason VARCHAR(255) NOT NULL, + snapshot TEXT NULL, + CONSTRAINT pk_application_failure_log PRIMARY KEY (application_failure_id) +); + +CREATE TABLE banner +( + deleted BIT(1) NOT NULL, + id BIGINT AUTO_INCREMENT NOT NULL, + file_name VARCHAR(255) NULL, + s3key VARCHAR(255) NULL, + visibility VARCHAR(255) NULL, + created_at datetime NULL, + updated_at datetime NULL, + title VARCHAR(255) NULL, + dead_line datetime NULL, + banner_link VARCHAR(255) NULL, + CONSTRAINT pk_banner PRIMARY KEY (id) +); + +CREATE TABLE blocked_ip_history_log +( + id BIGINT AUTO_INCREMENT NOT NULL, + ip VARCHAR(255) NULL, + penalty_level VARCHAR(255) NULL, + blocked_at datetime NULL, + CONSTRAINT pk_blocked_ip_history_log PRIMARY KEY (id) +); + +CREATE TABLE event +( + deleted BIT(1) NOT NULL, + event_id BIGINT AUTO_INCREMENT NOT NULL, + file_name VARCHAR(255) NULL, + s3key VARCHAR(255) NULL, + visibility VARCHAR(255) NULL, + created_at datetime NULL, + updated_at datetime NULL, + event_title VARCHAR(255) NOT NULL, + event_link VARCHAR(255) NULL, + start_date date NULL, + end_date date NULL, + CONSTRAINT pk_event PRIMARY KEY (event_id) +); + +CREATE TABLE exam +( + deleted BIT(1) NOT NULL, + id BIGINT AUTO_INCREMENT NOT NULL, + created_at datetime NULL, + updated_at datetime NULL, + school_name VARCHAR(255) NULL, + area VARCHAR(255) NULL, + capacity INT NULL, + deadline_time datetime NULL, + exam_date date NOT NULL, + lunch_name VARCHAR(255) NULL, + lunch_price INT NULL, + exam_status VARCHAR(255) NOT NULL, + zipcode VARCHAR(255) NULL, + street VARCHAR(255) NULL, + detail VARCHAR(255) NULL, + CONSTRAINT pk_exam PRIMARY KEY (id) +); + +CREATE TABLE exam_application +( + id BIGINT AUTO_INCREMENT NOT NULL, + created_at datetime NULL, + updated_at datetime NULL, + deleted BIT(1) NULL, + application_id BIGINT NULL, + user_id BIGINT NULL, + exam_id BIGINT NULL, + lunch_checked BIT(1) NULL, + exam_number VARCHAR(255) NULL, + CONSTRAINT pk_exam_application PRIMARY KEY (id) +); + +CREATE TABLE exam_subject +( + id BIGINT AUTO_INCREMENT NOT NULL, + exam_application_id BIGINT NULL, + subject VARCHAR(255) NULL, + CONSTRAINT pk_exam_subject PRIMARY KEY (id) +); + +CREATE TABLE exam_ticket_image +( + exam_ticket_image_id BIGINT AUTO_INCREMENT NOT NULL, + file_name VARCHAR(255) NULL, + s3key VARCHAR(255) NULL, + visibility VARCHAR(255) NULL, + application_id BIGINT NOT NULL, + CONSTRAINT pk_exam_ticket_image PRIMARY KEY (exam_ticket_image_id) +); + +CREATE TABLE faq +( + deleted BIT(1) NOT NULL, + faq_id BIGINT AUTO_INCREMENT NOT NULL, + created_at datetime NULL, + updated_at datetime NULL, + question VARCHAR(500) NOT NULL, + answer VARCHAR(255) NOT NULL, + author VARCHAR(255) NOT NULL, + user_id BIGINT NOT NULL, + CONSTRAINT pk_faq PRIMARY KEY (faq_id) +); + +CREATE TABLE file_move_fail_log +( + id BIGINT AUTO_INCREMENT NOT NULL, + created_at datetime NULL, + updated_at datetime NULL, + faq_id BIGINT NULL, + s3key VARCHAR(255) NULL, + destination_folder SMALLINT NULL, + CONSTRAINT pk_filemovefaillog PRIMARY KEY (id) +); + +CREATE TABLE form +( + form_id BIGINT AUTO_INCREMENT NOT NULL, + created_at datetime NULL, + updated_at datetime NULL, + exam_date date NOT NULL, + org_name VARCHAR(255) NULL, + password VARCHAR(255) NULL, + user_name VARCHAR(255) NULL, + gender VARCHAR(255) NULL, + birth date NULL, + phone_number VARCHAR(255) NULL, + subjects VARCHAR(255) NULL, + subjects2 VARCHAR(255) NULL, + lunch BIT(1) NULL, + area VARCHAR(255) NULL, + school_name VARCHAR(255) NULL, + file_name VARCHAR(255) NULL, + s3_key VARCHAR(255) NULL, + CONSTRAINT pk_form PRIMARY KEY (form_id) +); + +CREATE TABLE inquiry +( + deleted BIT(1) NOT NULL, + inquiry_id BIGINT AUTO_INCREMENT NOT NULL, + created_at datetime NULL, + updated_at datetime NULL, + title VARCHAR(300) NOT NULL, + content VARCHAR(1000) NOT NULL, + user_id BIGINT NOT NULL, + author VARCHAR(255) NULL, + status VARCHAR(255) NULL, + CONSTRAINT pk_inquiry PRIMARY KEY (inquiry_id) +); + +CREATE TABLE inquiry_answer +( + deleted BIT(1) NOT NULL, + inquiry_answer_id BIGINT AUTO_INCREMENT NOT NULL, + created_at datetime NULL, + updated_at datetime NULL, + title VARCHAR(300) NOT NULL, + content VARCHAR(1000) NOT NULL, + inquiry_id BIGINT NOT NULL, + author VARCHAR(255) NOT NULL, + user_id BIGINT NOT NULL, + CONSTRAINT pk_inquiry_answer PRIMARY KEY (inquiry_answer_id) +); + +CREATE TABLE inquiry_answer_attachment +( + inquiry_answer_attachment_id BIGINT AUTO_INCREMENT NOT NULL, + file_name VARCHAR(255) NULL, + s3key VARCHAR(255) NULL, + visibility VARCHAR(255) NULL, + inquiry_answer_id BIGINT NOT NULL, + CONSTRAINT pk_inquiry_answer_attachment PRIMARY KEY (inquiry_answer_attachment_id) +); + +CREATE TABLE inquiry_attachment +( + inquiry_attachment_id BIGINT AUTO_INCREMENT NOT NULL, + file_name VARCHAR(255) NULL, + s3key VARCHAR(255) NULL, + visibility VARCHAR(255) NULL, + inquiry_id BIGINT NOT NULL, + CONSTRAINT pk_inquiry_attachment PRIMARY KEY (inquiry_attachment_id) +); + +CREATE TABLE notice +( + deleted BIT(1) NOT NULL, + notice_id BIGINT AUTO_INCREMENT NOT NULL, + created_at datetime NULL, + updated_at datetime NULL, + title VARCHAR(255) NOT NULL, + content VARCHAR(3000) NOT NULL, + user_id BIGINT NOT NULL, + author VARCHAR(255) NOT NULL, + CONSTRAINT pk_notice PRIMARY KEY (notice_id) +); + +CREATE TABLE notice_attachment +( + notice_attachment_id BIGINT AUTO_INCREMENT NOT NULL, + file_name VARCHAR(255) NULL, + s3key VARCHAR(255) NULL, + visibility VARCHAR(255) NULL, + notice_id BIGINT NOT NULL, + CONSTRAINT pk_notice_attachment PRIMARY KEY (notice_attachment_id) +); + +CREATE TABLE notify +( + deleted BIT(1) NOT NULL, + id BIGINT AUTO_INCREMENT NOT NULL, + notify_custom_key VARCHAR(255) NOT NULL, + notify_type VARCHAR(255) NOT NULL, + notify_result_code VARCHAR(255) NOT NULL, + CONSTRAINT pk_notify PRIMARY KEY (id) +); + +CREATE TABLE payment +( + payment_id BIGINT AUTO_INCREMENT NOT NULL, + created_at datetime NULL, + updated_at datetime NULL, + deleted BIT(1) NULL, + exam_application_id BIGINT NULL, + application_id BIGINT NULL, + payment_key VARCHAR(255) NULL, + order_id VARCHAR(255) NOT NULL, + status VARCHAR(255) NOT NULL, + method VARCHAR(255) NULL, + total_amount INT NULL, + supplied_amount INT NULL, + vat_amount INT NULL, + balance_amount INT NULL, + tax_free_amount INT NULL, + CONSTRAINT pk_payment PRIMARY KEY (payment_id) +); + +CREATE TABLE payment_failure_log +( + payment_failure_id BIGINT AUTO_INCREMENT NOT NULL, + created_at datetime NULL, + updated_at datetime NULL, + payment_id BIGINT NOT NULL, + exam_application_id BIGINT NOT NULL, + application_id BIGINT NULL, + reason VARCHAR(255) NOT NULL, + snapshot TEXT NULL, + CONSTRAINT pk_payment_failure_log PRIMARY KEY (payment_failure_id) +); + +CREATE TABLE profile +( + deleted BIT(1) NOT NULL, + profile_id BIGINT AUTO_INCREMENT NOT NULL, + created_at datetime NULL, + updated_at datetime NULL, + user_id BIGINT NOT NULL, + user_name VARCHAR(255) NOT NULL, + gender VARCHAR(255) NOT NULL, + birth date NOT NULL, + phone_number VARCHAR(255) NOT NULL, + email VARCHAR(255) NULL, + education VARCHAR(255) NULL, + recommender_phone_number VARCHAR(255) NULL, + grade VARCHAR(255) NULL, + school_name VARCHAR(255) NULL, + zipcode VARCHAR(255) NULL, + street VARCHAR(255) NULL, + CONSTRAINT pk_profile PRIMARY KEY (profile_id) +); + +CREATE TABLE recommendation +( + deleted BIT(1) NOT NULL, + recommendation_id BIGINT AUTO_INCREMENT NOT NULL, + user_id BIGINT NULL, + recommeded_name VARCHAR(255) NULL, + recommeded_phone_number VARCHAR(255) NULL, + bank VARCHAR(255) NULL, + account_number VARCHAR(255) NULL, + CONSTRAINT pk_recommendation PRIMARY KEY (recommendation_id) +); + +CREATE TABLE refund +( + refund_id BIGINT AUTO_INCREMENT NOT NULL, + created_at datetime NULL, + updated_at datetime NULL, + deleted BIT(1) NULL, + transaction_key VARCHAR(255) NOT NULL, + exam_application_id BIGINT NULL, + reason VARCHAR(255) NOT NULL, + refund_status VARCHAR(255) NULL, + refunded_amount INT NULL, + refundable_amount INT NULL, + CONSTRAINT pk_refund PRIMARY KEY (refund_id) +); + +CREATE TABLE refund_failure_log +( + refund_failure_id BIGINT AUTO_INCREMENT NOT NULL, + created_at datetime NULL, + updated_at datetime NULL, + refund_id BIGINT NOT NULL, + exam_application_id BIGINT NOT NULL, + reason VARCHAR(255) NOT NULL, + snapshot TEXT NULL, + CONSTRAINT pk_refund_failure_log PRIMARY KEY (refund_failure_id) +); + +CREATE TABLE user +( + deleted BIT(1) NOT NULL, + user_id BIGINT AUTO_INCREMENT NOT NULL, + created_at datetime NULL, + updated_at datetime NULL, + login_id VARCHAR(50) NULL, + password VARCHAR(255) NULL, + gender VARCHAR(255) NULL, + name VARCHAR(255) NULL, + birth date NULL, + phone_number VARCHAR(255) NULL, + customer_key VARCHAR(255) NULL, + agreed_to_terms_of_service BIT(1) NULL, + agreed_to_privacy_policy BIT(1) NULL, + agreed_to_marketing BIT(1) NULL, + user_role VARCHAR(50) NOT NULL, + provider VARCHAR(255) NULL, + CONSTRAINT pk_user PRIMARY KEY (user_id) +); + +CREATE TABLE virtual_account_log +( + deleted BIT(1) NOT NULL, + virtual_account_log_id BIGINT AUTO_INCREMENT NOT NULL, + application_id BIGINT NULL, + order_id VARCHAR(255) NULL, + account_number VARCHAR(255) NULL, + bank_name VARCHAR(255) NULL, + customer_name VARCHAR(255) NULL, + customer_email VARCHAR(255) NULL, + deposit_status SMALLINT NULL, + CONSTRAINT pk_virtual_account_log PRIMARY KEY (virtual_account_log_id) +); + +ALTER TABLE profile + ADD CONSTRAINT uc_25d92281884ae5fdff0d3ec10 UNIQUE (user_id); + +ALTER TABLE notify + ADD CONSTRAINT uc_notify_notify_custom_key UNIQUE (notify_custom_key); + +ALTER TABLE user + ADD CONSTRAINT uc_user_login UNIQUE (login_id); + +CREATE INDEX idx_status_created_at ON payment (status, created_at); \ No newline at end of file