From aa400a8f5eb5ad1883237f9464a9c8633f45d15d Mon Sep 17 00:00:00 2001 From: fervovita Date: Sun, 12 Jul 2026 02:02:56 +0900 Subject: [PATCH 1/5] =?UTF-8?q?Refactor:=20=EC=A0=9C=EC=95=BD=20=EB=84=A4?= =?UTF-8?q?=EC=9D=B4=EB=B0=8D=20=EA=B7=9C=EC=B9=99=EC=97=90=20=EB=A7=9E?= =?UTF-8?q?=EA=B2=8C=20=EC=9C=A0=EB=8B=88=ED=81=AC=20=EC=A0=9C=EC=95=BD=20?= =?UTF-8?q?=EC=9D=B4=EB=A6=84=20=ED=86=B5=EC=9D=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../commission/category/textbook/entity/TextbookPage.java | 2 +- .../backend/domain/commission/core/entity/CommissionColor.java | 2 +- .../domain/commission/core/entity/CommissionConcept.java | 2 +- .../backend/domain/commission/draft/entity/CommissionDraft.java | 2 +- .../domain/commission/draft/entity/CommissionDraftFile.java | 2 +- .../domain/commission/revision/entity/RevisionRequest.java | 2 +- .../domain/commission/revision/entity/RevisionResponse.java | 2 +- .../java/ditda/backend/domain/settlement/entity/Settlement.java | 2 +- src/main/java/ditda/backend/domain/user/entity/User.java | 2 +- 9 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/main/java/ditda/backend/domain/commission/category/textbook/entity/TextbookPage.java b/src/main/java/ditda/backend/domain/commission/category/textbook/entity/TextbookPage.java index fd396110..f4d65ba5 100644 --- a/src/main/java/ditda/backend/domain/commission/category/textbook/entity/TextbookPage.java +++ b/src/main/java/ditda/backend/domain/commission/category/textbook/entity/TextbookPage.java @@ -26,7 +26,7 @@ name = "textbook_pages", uniqueConstraints = { @UniqueConstraint( - name = "uk_commission_required_page_type", + name = "uk_textbook_pages_commission_id_page_type", columnNames = {"commission_id", "page_type"} ) } diff --git a/src/main/java/ditda/backend/domain/commission/core/entity/CommissionColor.java b/src/main/java/ditda/backend/domain/commission/core/entity/CommissionColor.java index 7623c298..b1c1ab9f 100644 --- a/src/main/java/ditda/backend/domain/commission/core/entity/CommissionColor.java +++ b/src/main/java/ditda/backend/domain/commission/core/entity/CommissionColor.java @@ -25,7 +25,7 @@ name = "commission_colors", uniqueConstraints = { @UniqueConstraint( - name = "uk_commission_color_role", + name = "uk_commission_colors_commission_id_role", columnNames = {"commission_id", "role"} ) } diff --git a/src/main/java/ditda/backend/domain/commission/core/entity/CommissionConcept.java b/src/main/java/ditda/backend/domain/commission/core/entity/CommissionConcept.java index ac7663c4..41df5965 100644 --- a/src/main/java/ditda/backend/domain/commission/core/entity/CommissionConcept.java +++ b/src/main/java/ditda/backend/domain/commission/core/entity/CommissionConcept.java @@ -25,7 +25,7 @@ name = "commission_concepts", uniqueConstraints = { @UniqueConstraint( - name = "uk_commission_concept", + name = "uk_commission_concepts_commission_id_concept", columnNames = {"commission_id", "concept"} ) } diff --git a/src/main/java/ditda/backend/domain/commission/draft/entity/CommissionDraft.java b/src/main/java/ditda/backend/domain/commission/draft/entity/CommissionDraft.java index 33bc7710..90a2594d 100644 --- a/src/main/java/ditda/backend/domain/commission/draft/entity/CommissionDraft.java +++ b/src/main/java/ditda/backend/domain/commission/draft/entity/CommissionDraft.java @@ -24,7 +24,7 @@ name = "commission_drafts", uniqueConstraints = { @UniqueConstraint( - name = "uk_commission_draft_round", + name = "uk_commission_drafts_commission_application_id_round", columnNames = {"commission_application_id", "round"} ) } diff --git a/src/main/java/ditda/backend/domain/commission/draft/entity/CommissionDraftFile.java b/src/main/java/ditda/backend/domain/commission/draft/entity/CommissionDraftFile.java index 6bc4c6f9..e1e5fb85 100644 --- a/src/main/java/ditda/backend/domain/commission/draft/entity/CommissionDraftFile.java +++ b/src/main/java/ditda/backend/domain/commission/draft/entity/CommissionDraftFile.java @@ -26,7 +26,7 @@ name = "commission_draft_files", uniqueConstraints = { @UniqueConstraint( - name = "uk_commission_draft_file_order", + name = "uk_commission_draft_files_commission_draft_id_file_order", columnNames = {"commission_draft_id", "file_order"} ) } diff --git a/src/main/java/ditda/backend/domain/commission/revision/entity/RevisionRequest.java b/src/main/java/ditda/backend/domain/commission/revision/entity/RevisionRequest.java index ba928d98..238bc1c2 100644 --- a/src/main/java/ditda/backend/domain/commission/revision/entity/RevisionRequest.java +++ b/src/main/java/ditda/backend/domain/commission/revision/entity/RevisionRequest.java @@ -25,7 +25,7 @@ name = "revision_requests", uniqueConstraints = { @UniqueConstraint( - name = "uk_revision_request_target_draft", + name = "uk_revision_requests_target_draft_id", columnNames = {"target_draft_id"} ) } diff --git a/src/main/java/ditda/backend/domain/commission/revision/entity/RevisionResponse.java b/src/main/java/ditda/backend/domain/commission/revision/entity/RevisionResponse.java index 7c3678e9..95ce0a35 100644 --- a/src/main/java/ditda/backend/domain/commission/revision/entity/RevisionResponse.java +++ b/src/main/java/ditda/backend/domain/commission/revision/entity/RevisionResponse.java @@ -22,7 +22,7 @@ name = "revision_responses", uniqueConstraints = { @UniqueConstraint( - name = "uk_revision_response_produced_draft", + name = "uk_revision_responses_produced_draft_id", columnNames = {"produced_draft_id"} ) } diff --git a/src/main/java/ditda/backend/domain/settlement/entity/Settlement.java b/src/main/java/ditda/backend/domain/settlement/entity/Settlement.java index 6c57a8d1..feb261a3 100644 --- a/src/main/java/ditda/backend/domain/settlement/entity/Settlement.java +++ b/src/main/java/ditda/backend/domain/settlement/entity/Settlement.java @@ -28,7 +28,7 @@ @Entity @Table(name = "settlements", uniqueConstraints = @UniqueConstraint( - name = "uk_settlements_designer_commission_type", + name = "uk_settlements_designer_id_commission_id_settlement_type", columnNames = {"designer_id", "commission_id", "settlement_type"} )) @Getter diff --git a/src/main/java/ditda/backend/domain/user/entity/User.java b/src/main/java/ditda/backend/domain/user/entity/User.java index b9303660..087c728d 100644 --- a/src/main/java/ditda/backend/domain/user/entity/User.java +++ b/src/main/java/ditda/backend/domain/user/entity/User.java @@ -50,7 +50,7 @@ public class User extends BaseEntity { private String phone; @Enumerated(EnumType.STRING) - @Column(name = "role", nullable = false) + @Column(name = "role", nullable = false, length = 20) private UserRole role; @Column(name = "email_verified_at") From 4b7e6141c6f06f406f6d85c0374b0bb218241a4c Mon Sep 17 00:00:00 2001 From: fervovita Date: Sun, 12 Jul 2026 02:03:32 +0900 Subject: [PATCH 2/5] =?UTF-8?q?Feat:=20Flyway=20=EB=8F=84=EC=9E=85=20?= =?UTF-8?q?=EB=B0=8F=20=EC=B4=88=EA=B8=B0=20=EC=8A=A4=ED=82=A4=EB=A7=88=20?= =?UTF-8?q?=EB=A7=88=EC=9D=B4=EA=B7=B8=EB=A0=88=EC=9D=B4=EC=85=98=20?= =?UTF-8?q?=EC=84=A4=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 4 + src/main/resources/application-local.yaml | 2 +- src/main/resources/application-prod.yaml | 2 +- src/main/resources/application.yaml | 7 + src/main/resources/db/migration/V1__init.sql | 390 +++++++++++++++++++ 5 files changed, 403 insertions(+), 2 deletions(-) create mode 100644 src/main/resources/db/migration/V1__init.sql diff --git a/build.gradle b/build.gradle index 864f84b5..e32b9be1 100644 --- a/build.gradle +++ b/build.gradle @@ -30,6 +30,10 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-data-jpa' runtimeOnly 'com.mysql:mysql-connector-j' + // flyway + implementation 'org.springframework.boot:spring-boot-starter-flyway' + implementation 'org.flywaydb:flyway-mysql' + // S3 implementation platform('io.awspring.cloud:spring-cloud-aws-dependencies:4.0.2') implementation 'io.awspring.cloud:spring-cloud-aws-starter-s3' diff --git a/src/main/resources/application-local.yaml b/src/main/resources/application-local.yaml index 63b2736a..56e27ec4 100644 --- a/src/main/resources/application-local.yaml +++ b/src/main/resources/application-local.yaml @@ -1,7 +1,7 @@ spring: jpa: hibernate: - ddl-auto: update + ddl-auto: validate properties: hibernate: format_sql: true diff --git a/src/main/resources/application-prod.yaml b/src/main/resources/application-prod.yaml index 49ed592f..3707eb3d 100644 --- a/src/main/resources/application-prod.yaml +++ b/src/main/resources/application-prod.yaml @@ -1,7 +1,7 @@ spring: jpa: hibernate: - ddl-auto: update # TODO: validate로 변경 + ddl-auto: validate properties: hibernate: format_sql: false diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index 1e32ee5a..cae3fb2b 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -13,6 +13,13 @@ spring: password: ${DB_PASSWORD} driver-class-name: com.mysql.cj.jdbc.Driver + flyway: + enabled: true + locations: classpath:db/migration + baseline-on-migrate: true + baseline-version: 1 + out-of-order: true + data: redis: host: ${REDIS_HOST} 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..a4b32fe9 --- /dev/null +++ b/src/main/resources/db/migration/V1__init.sql @@ -0,0 +1,390 @@ +-- ========================================================= +-- V1__init.sql +-- Ditda 초기 schema +-- +-- 정책: +-- - Enum: VARCHAR + @Enumerated(EnumType.STRING) 매핑 +-- - Timestamp: DATETIME(6) 사용 +-- - BaseEntity(@MappedSuperclass): 각 테이블에 인라인으로 전개 +-- - 제약 네이밍 : Hibernate 자동 생성 난수 이름 대신 명시적 이름 사용 +-- (PK 컬럼 기본, uk__ / idx_
_ / fk_
_) +-- ========================================================= + + +-- ========================================================= +-- ADMIN +-- ========================================================= + +CREATE TABLE admins +( + admin_id BIGINT NOT NULL AUTO_INCREMENT, + username VARCHAR(20) NOT NULL, + password VARCHAR(255) NOT NULL, + name VARCHAR(50) NOT NULL, + created_at DATETIME(6) NOT NULL, + updated_at DATETIME(6) NOT NULL, + PRIMARY KEY (admin_id), + UNIQUE KEY uk_admins_username (username) +); + +-- ========================================================= +-- USER +-- ========================================================= + +CREATE TABLE users +( + user_id BIGINT NOT NULL AUTO_INCREMENT, + username VARCHAR(20) NOT NULL, + password VARCHAR(255) NOT NULL, + name VARCHAR(50) NOT NULL, + email VARCHAR(100) NOT NULL, + profile_image_url VARCHAR(255) NOT NULL, + phone VARCHAR(20) NOT NULL, + role VARCHAR(20) NOT NULL, + email_verified_at DATETIME(6) DEFAULT NULL, + created_at DATETIME(6) NOT NULL, + updated_at DATETIME(6) NOT NULL, + PRIMARY KEY (user_id), + UNIQUE KEY uk_users_email (email), + UNIQUE KEY uk_users_username (username) +); + +CREATE TABLE designers +( + designer_id BIGINT NOT NULL, + level VARCHAR(20) NOT NULL, + exp INT NOT NULL, + bank_name VARCHAR(50) NOT NULL, + account_number VARCHAR(255) NOT NULL, + account_holder VARCHAR(50) NOT NULL, + created_at DATETIME(6) NOT NULL, + updated_at DATETIME(6) NOT NULL, + PRIMARY KEY (designer_id), + CONSTRAINT fk_designers_user_id FOREIGN KEY (designer_id) REFERENCES users (user_id) +); + +CREATE TABLE instructors +( + instructor_id BIGINT NOT NULL, + created_at DATETIME(6) NOT NULL, + updated_at DATETIME(6) NOT NULL, + PRIMARY KEY (instructor_id), + CONSTRAINT fk_instructors_user_id FOREIGN KEY (instructor_id) REFERENCES users (user_id) +); + +CREATE TABLE portfolios +( + portfolio_id BIGINT NOT NULL AUTO_INCREMENT, + designer_id BIGINT NOT NULL, + portfolio_url VARCHAR(255) NOT NULL, + created_at DATETIME(6) NOT NULL, + updated_at DATETIME(6) NOT NULL, + PRIMARY KEY (portfolio_id), + KEY idx_portfolios_designer_id (designer_id), + CONSTRAINT fk_portfolios_designer_id FOREIGN KEY (designer_id) REFERENCES designers (designer_id) +); + +-- ========================================================= +-- AUTH +-- ========================================================= + +CREATE TABLE refresh_tokens +( + session_id VARCHAR(36) NOT NULL, + user_id BIGINT NOT NULL, + refresh_token_hash VARCHAR(128) NOT NULL, + expires_at DATETIME(6) NOT NULL, + PRIMARY KEY (session_id), + KEY idx_refresh_tokens_user_id (user_id), + CONSTRAINT fk_refresh_tokens_user_id FOREIGN KEY (user_id) REFERENCES users (user_id) +); + +-- ========================================================= +-- COMMISSION +-- ========================================================= + +CREATE TABLE commissions +( + commission_id BIGINT NOT NULL AUTO_INCREMENT, + instructor_id BIGINT NOT NULL, + assigned_designer_id BIGINT DEFAULT NULL, + plan_code VARCHAR(10) NOT NULL, + title VARCHAR(50) NOT NULL, + category_type VARCHAR(50) NOT NULL, + size VARCHAR(10) NOT NULL, + additional_concept VARCHAR(300) DEFAULT NULL, + color_selection_mode VARCHAR(30) NOT NULL, + first_draft_deadline DATE NOT NULL, + application_deadline DATE NOT NULL, + final_deadline DATE NOT NULL, + status VARCHAR(30) NOT NULL, + max_revision INT NOT NULL, + selected_at DATETIME(6) DEFAULT NULL, + created_at DATETIME(6) NOT NULL, + updated_at DATETIME(6) NOT NULL, + PRIMARY KEY (commission_id), + KEY idx_commissions_assigned_designer_id (assigned_designer_id), + KEY idx_commissions_instructor_id (instructor_id), + CONSTRAINT fk_commissions_assigned_designer_id FOREIGN KEY (assigned_designer_id) REFERENCES designers (designer_id), + CONSTRAINT fk_commissions_instructor_id FOREIGN KEY (instructor_id) REFERENCES instructors (instructor_id) +); + + +CREATE TABLE commission_colors +( + commission_color_id BIGINT NOT NULL AUTO_INCREMENT, + commission_id BIGINT NOT NULL, + color_code VARCHAR(7) NOT NULL, + role VARCHAR(10) NOT NULL, + PRIMARY KEY (commission_color_id), + UNIQUE KEY uk_commission_colors_commission_id_role (commission_id, role), + CONSTRAINT fk_commission_colors_commission_id FOREIGN KEY (commission_id) REFERENCES commissions (commission_id) +); + +CREATE TABLE commission_concepts +( + commission_concept_id BIGINT NOT NULL AUTO_INCREMENT, + commission_id BIGINT NOT NULL, + concept VARCHAR(30) NOT NULL, + PRIMARY KEY (commission_concept_id), + UNIQUE KEY uk_commission_concepts_commission_id_concept (commission_id, concept), + CONSTRAINT fk_commission_concepts_commission_id FOREIGN KEY (commission_id) REFERENCES commissions (commission_id) +); + +CREATE TABLE commission_files +( + commission_file_id BIGINT NOT NULL AUTO_INCREMENT, + commission_id BIGINT NOT NULL, + file_kind VARCHAR(20) NOT NULL, + file_url VARCHAR(255) NOT NULL, + description VARCHAR(300) DEFAULT NULL, + created_at DATETIME(6) NOT NULL, + updated_at DATETIME(6) NOT NULL, + PRIMARY KEY (commission_file_id), + KEY idx_commission_files_commission_id (commission_id), + CONSTRAINT fk_commission_files_commission_id FOREIGN KEY (commission_id) REFERENCES commissions (commission_id) +); + + +-- ========================================================= +-- APPLICATION +-- ========================================================= + +CREATE TABLE commission_applications +( + commission_application_id BIGINT NOT NULL AUTO_INCREMENT, + commission_id BIGINT NOT NULL, + designer_id BIGINT NOT NULL, + status VARCHAR(20) NOT NULL, + active_key VARCHAR(64) GENERATED ALWAYS AS ( + CASE + WHEN status <> 'CANCELLED' + THEN CONCAT(commission_id, '-', designer_id) END + ) VIRTUAL, + created_at DATETIME(6) NOT NULL, + updated_at DATETIME(6) NOT NULL, + PRIMARY KEY (commission_application_id), + UNIQUE KEY uk_commission_applications_active_key (active_key), + KEY idx_commission_applications_commission_id (commission_id), + KEY idx_commission_applications_designer_id (designer_id), + CONSTRAINT fk_commission_applications_commission_id FOREIGN KEY (commission_id) REFERENCES commissions (commission_id), + CONSTRAINT fk_commission_applications_designer_id FOREIGN KEY (designer_id) REFERENCES designers (designer_id) +); + +-- ========================================================= +-- DRAFT +-- ========================================================= + +CREATE TABLE commission_drafts +( + commission_draft_id BIGINT NOT NULL AUTO_INCREMENT, + commission_application_id BIGINT NOT NULL, + round INT NOT NULL, + created_at DATETIME(6) NOT NULL, + updated_at DATETIME(6) NOT NULL, + PRIMARY KEY (commission_draft_id), + UNIQUE KEY uk_commission_drafts_commission_application_id_round (commission_application_id, round), + CONSTRAINT fk_commission_drafts_commission_application_id FOREIGN KEY (commission_application_id) REFERENCES commission_applications (commission_application_id) +); + + +CREATE TABLE commission_draft_files +( + commission_draft_file_id BIGINT NOT NULL AUTO_INCREMENT, + commission_draft_id BIGINT NOT NULL, + file_order INT NOT NULL, + file_url VARCHAR(255) NOT NULL, + watermarked_file_url VARCHAR(255) DEFAULT NULL, + watermark_status VARCHAR(20) NOT NULL, + created_at DATETIME(6) NOT NULL, + updated_at DATETIME(6) NOT NULL, + PRIMARY KEY (commission_draft_file_id), + UNIQUE KEY uk_commission_draft_files_commission_draft_id_file_order (commission_draft_id, file_order), + CONSTRAINT fk_commission_draft_files_commission_draft_id FOREIGN KEY (commission_draft_id) REFERENCES commission_drafts (commission_draft_id) +); + +-- ========================================================= +-- REVISION +-- ========================================================= + +CREATE TABLE revision_requests +( + revision_request_id BIGINT NOT NULL AUTO_INCREMENT, + commission_id BIGINT NOT NULL, + target_draft_id BIGINT NOT NULL, + checked BIT(1) NOT NULL, + created_at DATETIME(6) NOT NULL, + updated_at DATETIME(6) NOT NULL, + PRIMARY KEY (revision_request_id), + UNIQUE KEY uk_revision_requests_target_draft_id (target_draft_id), + KEY idx_revision_requests_commission_id (commission_id), + CONSTRAINT fk_revision_requests_commission_id FOREIGN KEY (commission_id) REFERENCES commissions (commission_id), + CONSTRAINT fk_revision_requests_target_draft_id FOREIGN KEY (target_draft_id) REFERENCES commission_drafts (commission_draft_id) +); + +CREATE TABLE revision_responses +( + revision_request_id BIGINT NOT NULL, + produced_draft_id BIGINT NOT NULL, + designer_comment VARCHAR(300) DEFAULT NULL, + checked BIT(1) NOT NULL, + created_at DATETIME(6) NOT NULL, + updated_at DATETIME(6) NOT NULL, + PRIMARY KEY (revision_request_id), + UNIQUE KEY uk_revision_responses_produced_draft_id (produced_draft_id), + CONSTRAINT fk_revision_responses_produced_draft_id FOREIGN KEY (produced_draft_id) REFERENCES commission_drafts (commission_draft_id), + CONSTRAINT fk_revision_responses_revision_request_id FOREIGN KEY (revision_request_id) REFERENCES revision_requests (revision_request_id) +); + +CREATE TABLE revision_details +( + revision_detail_id BIGINT NOT NULL AUTO_INCREMENT, + revision_request_id BIGINT NOT NULL, + category VARCHAR(20) NOT NULL, + comment VARCHAR(300) NOT NULL, + created_at DATETIME(6) NOT NULL, + updated_at DATETIME(6) NOT NULL, + PRIMARY KEY (revision_detail_id), + KEY idx_revision_details_revision_request_id (revision_request_id), + CONSTRAINT fk_revision_details_revision_request_id FOREIGN KEY (revision_request_id) REFERENCES revision_requests (revision_request_id) +); + +-- ========================================================= +-- TEXTBOOK +-- ========================================================= + +CREATE TABLE textbooks +( + commission_id BIGINT NOT NULL, + title VARCHAR(50) NOT NULL, + instructor_name VARCHAR(50) NOT NULL, + subject VARCHAR(50) NOT NULL, + PRIMARY KEY (commission_id), + CONSTRAINT fk_textbooks_commission_id FOREIGN KEY (commission_id) REFERENCES commissions (commission_id) +); + +CREATE TABLE textbook_pages +( + textbook_page_id BIGINT NOT NULL AUTO_INCREMENT, + commission_id BIGINT NOT NULL, + page_type VARCHAR(30) NOT NULL, + page_description VARCHAR(150) DEFAULT NULL, + PRIMARY KEY (textbook_page_id), + UNIQUE KEY uk_textbook_pages_commission_id_page_type (commission_id, page_type), + CONSTRAINT fk_textbook_pages_commission_id FOREIGN KEY (commission_id) REFERENCES commissions (commission_id) +); + +-- ========================================================= +-- PAYMENT +-- ========================================================= + +CREATE TABLE payments +( + payment_id BIGINT NOT NULL AUTO_INCREMENT, + commission_id BIGINT NOT NULL, + amount INT NOT NULL, + depositor_name VARCHAR(50) DEFAULT NULL, + status VARCHAR(30) NOT NULL, + paid_at DATETIME(6) DEFAULT NULL, + deposit_notified_at DATETIME(6) DEFAULT NULL, + created_at DATETIME(6) NOT NULL, + updated_at DATETIME(6) NOT NULL, + PRIMARY KEY (payment_id), + KEY idx_payments_commission_id (commission_id), + CONSTRAINT fk_payments_commission_id FOREIGN KEY (commission_id) REFERENCES commissions (commission_id) +); + +-- ========================================================= +-- SETTLEMENT +-- ========================================================= + +CREATE TABLE settlements +( + settlement_id BIGINT NOT NULL AUTO_INCREMENT, + designer_id BIGINT NOT NULL, + commission_id BIGINT NOT NULL, + settlement_type VARCHAR(20) NOT NULL, + amount INT NOT NULL, + status VARCHAR(20) NOT NULL, + settled_at DATETIME(6) DEFAULT NULL, + created_at DATETIME(6) NOT NULL, + updated_at DATETIME(6) NOT NULL, + PRIMARY KEY (settlement_id), + UNIQUE KEY uk_settlements_designer_id_commission_id_settlement_type (designer_id, commission_id, settlement_type), + KEY idx_settlements_commission_id (commission_id), + CONSTRAINT fk_settlements_commission_id FOREIGN KEY (commission_id) REFERENCES commissions (commission_id), + CONSTRAINT fk_settlements_designer_id FOREIGN KEY (designer_id) REFERENCES designers (designer_id) +); + +-- ========================================================= +-- OUTBOX +-- ========================================================= + +CREATE TABLE notification_outboxes +( + notification_outbox_id BIGINT NOT NULL AUTO_INCREMENT, + recipient_email VARCHAR(100) NOT NULL, + subject VARCHAR(150) NOT NULL, + template_name VARCHAR(100) NOT NULL, + template_variables TEXT NOT NULL, + status VARCHAR(20) NOT NULL, + scheduled_at DATETIME(6) NOT NULL, + retry_count INT NOT NULL, + error_message TEXT, + sent_at DATETIME(6) DEFAULT NULL, + created_at DATETIME(6) NOT NULL, + updated_at DATETIME(6) NOT NULL, + PRIMARY KEY (notification_outbox_id) +); + +-- ========================================================= +-- TERM +-- ========================================================= + +CREATE TABLE user_terms +( + user_term_id BIGINT NOT NULL AUTO_INCREMENT, + user_id BIGINT NOT NULL, + term_type VARCHAR(50) NOT NULL, + version VARCHAR(20) NOT NULL, + is_agreed BIT(1) NOT NULL, + created_at DATETIME(6) NOT NULL, + updated_at DATETIME(6) NOT NULL, + PRIMARY KEY (user_term_id), + KEY idx_user_terms_user_id (user_id), + CONSTRAINT fk_user_terms_user_id FOREIGN KEY (user_id) REFERENCES users (user_id) +); + +CREATE TABLE payment_terms +( + payment_term_id BIGINT NOT NULL AUTO_INCREMENT, + payment_id BIGINT NOT NULL, + term_type VARCHAR(50) NOT NULL, + version VARCHAR(20) NOT NULL, + is_agreed BIT(1) NOT NULL, + created_at DATETIME(6) NOT NULL, + updated_at DATETIME(6) NOT NULL, + PRIMARY KEY (payment_term_id), + KEY idx_payment_terms_payment_id (payment_id), + CONSTRAINT fk_payment_terms_payment_id FOREIGN KEY (payment_id) REFERENCES payments (payment_id) +); From 2c801d1f91aebe7a018d91f5dd0831d35a886b04 Mon Sep 17 00:00:00 2001 From: fervovita Date: Sun, 12 Jul 2026 02:04:29 +0900 Subject: [PATCH 3/5] =?UTF-8?q?Test:=20Testcontainers=20=EA=B8=B0=EB=B0=98?= =?UTF-8?q?=20=ED=86=B5=ED=95=A9=20=ED=85=8C=EC=8A=A4=ED=8A=B8=20=ED=99=98?= =?UTF-8?q?=EA=B2=BD=EC=9C=BC=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 5 ++-- .../backend/BackendApplicationTests.java | 11 ++------- .../support/IntegrationTestSupport.java | 16 +++++++++++++ .../support/TestcontainersConfiguration.java | 23 +++++++++++++++++++ src/test/resources/application-test.yaml | 11 ++++----- 5 files changed, 48 insertions(+), 18 deletions(-) create mode 100644 src/test/java/ditda/backend/support/IntegrationTestSupport.java create mode 100644 src/test/java/ditda/backend/support/TestcontainersConfiguration.java diff --git a/build.gradle b/build.gradle index e32b9be1..836600a8 100644 --- a/build.gradle +++ b/build.gradle @@ -69,10 +69,11 @@ dependencies { implementation 'org.springframework.boot:spring-boot-starter-actuator' // test - testImplementation 'org.springframework.boot:spring-boot-starter-test' + testImplementation 'org.springframework.boot:spring-boot-starter-webmvc-test' testImplementation 'org.springframework.security:spring-security-test' testRuntimeOnly 'org.junit.platform:junit-platform-launcher' - testImplementation 'com.h2database:h2' + testImplementation 'org.springframework.boot:spring-boot-testcontainers' + testImplementation 'org.testcontainers:testcontainers-mysql' } // CheckStyle diff --git a/src/test/java/ditda/backend/BackendApplicationTests.java b/src/test/java/ditda/backend/BackendApplicationTests.java index 0e14068a..acfab744 100644 --- a/src/test/java/ditda/backend/BackendApplicationTests.java +++ b/src/test/java/ditda/backend/BackendApplicationTests.java @@ -1,17 +1,10 @@ package ditda.backend; import org.junit.jupiter.api.Test; -import org.redisson.api.RedissonClient; -import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.test.context.ActiveProfiles; -import org.springframework.test.context.bean.override.mockito.MockitoBean; -@SpringBootTest -@ActiveProfiles("test") -class BackendApplicationTests { +import ditda.backend.support.IntegrationTestSupport; - @MockitoBean - private RedissonClient redissonClient; +class BackendApplicationTests extends IntegrationTestSupport { @Test void contextLoads() { diff --git a/src/test/java/ditda/backend/support/IntegrationTestSupport.java b/src/test/java/ditda/backend/support/IntegrationTestSupport.java new file mode 100644 index 00000000..7e78caa0 --- /dev/null +++ b/src/test/java/ditda/backend/support/IntegrationTestSupport.java @@ -0,0 +1,16 @@ +package ditda.backend.support; + +import org.redisson.api.RedissonClient; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.context.annotation.Import; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.bean.override.mockito.MockitoBean; + +@SpringBootTest +@ActiveProfiles("test") +@Import(TestcontainersConfiguration.class) +public abstract class IntegrationTestSupport { + + @MockitoBean + protected RedissonClient redissonClient; +} diff --git a/src/test/java/ditda/backend/support/TestcontainersConfiguration.java b/src/test/java/ditda/backend/support/TestcontainersConfiguration.java new file mode 100644 index 00000000..e31cbcc4 --- /dev/null +++ b/src/test/java/ditda/backend/support/TestcontainersConfiguration.java @@ -0,0 +1,23 @@ +package ditda.backend.support; + +import org.springframework.boot.test.context.TestConfiguration; +import org.springframework.boot.testcontainers.service.connection.ServiceConnection; +import org.springframework.context.annotation.Bean; +import org.testcontainers.mysql.MySQLContainer; + +@TestConfiguration(proxyBeanMethods = false) +public class TestcontainersConfiguration { + + @Bean + @ServiceConnection + MySQLContainer mysqlContainer() { + MySQLContainer container = new MySQLContainer("mysql:8.4") + .withDatabaseName("ditda"); + + container.setCommand( + "--character-set-server=utf8mb4", + "--collation-server=utf8mb4_unicode_ci" + ); + return container; + } +} diff --git a/src/test/resources/application-test.yaml b/src/test/resources/application-test.yaml index a1a37820..2b9cd51d 100644 --- a/src/test/resources/application-test.yaml +++ b/src/test/resources/application-test.yaml @@ -1,13 +1,10 @@ spring: - datasource: - url: jdbc:h2:mem:testdb;MODE=MYSQL;DB_CLOSE_DELAY=-1 - username: sa - password: - driver-class-name: org.h2.Driver - jpa: hibernate: - ddl-auto: create-drop + ddl-auto: validate + properties: + hibernate: + default_batch_fetch_size: 100 data: redis: From 6cfd097c00f6754e2756cfeecceca77bd71b2765 Mon Sep 17 00:00:00 2001 From: fervovita Date: Sun, 12 Jul 2026 02:52:16 +0900 Subject: [PATCH 4/5] =?UTF-8?q?Fix(db):=20notification=5Foutboxes=EC=97=90?= =?UTF-8?q?=20=EC=95=84=EC=9B=83=EB=B0=95=EC=8A=A4=20=ED=8F=B4=EB=A7=81?= =?UTF-8?q?=EC=9A=A9=20=EB=B3=B5=ED=95=A9=20=EC=9D=B8=EB=8D=B1=EC=8A=A4=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/db/migration/V1__init.sql | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/resources/db/migration/V1__init.sql b/src/main/resources/db/migration/V1__init.sql index a4b32fe9..387f152b 100644 --- a/src/main/resources/db/migration/V1__init.sql +++ b/src/main/resources/db/migration/V1__init.sql @@ -355,6 +355,7 @@ CREATE TABLE notification_outboxes created_at DATETIME(6) NOT NULL, updated_at DATETIME(6) NOT NULL, PRIMARY KEY (notification_outbox_id) + KEY idx_notification_outboxes_status_scheduled_at (status, scheduled_at) ); -- ========================================================= From f96fb08c70da54533ce8eb99b0e047d58b32901b Mon Sep 17 00:00:00 2001 From: fervovita Date: Mon, 13 Jul 2026 17:46:47 +0900 Subject: [PATCH 5/5] =?UTF-8?q?Fix(db):=20notification=5Foutboxes=20CREATE?= =?UTF-8?q?=20TABLE=20=EB=AC=B8=EB=B2=95=20=EC=98=A4=EB=A5=98=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/main/resources/db/migration/V1__init.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/db/migration/V1__init.sql b/src/main/resources/db/migration/V1__init.sql index 387f152b..46c88059 100644 --- a/src/main/resources/db/migration/V1__init.sql +++ b/src/main/resources/db/migration/V1__init.sql @@ -354,7 +354,7 @@ CREATE TABLE notification_outboxes sent_at DATETIME(6) DEFAULT NULL, created_at DATETIME(6) NOT NULL, updated_at DATETIME(6) NOT NULL, - PRIMARY KEY (notification_outbox_id) + PRIMARY KEY (notification_outbox_id), KEY idx_notification_outboxes_status_scheduled_at (status, scheduled_at) );