From 1a8417d0bd7a47ac5feb538efb2d42f3cb178ed8 Mon Sep 17 00:00:00 2001 From: si-zero Date: Sun, 30 Aug 2026 23:25:38 +0900 Subject: [PATCH 1/2] =?UTF-8?q?docs:=20=EB=88=84=EB=9D=BD=EB=90=9C=20?= =?UTF-8?q?=EB=A7=88=EC=9D=B4=EA=B7=B8=EB=A0=88=EC=9D=B4=EC=85=98=20SQL=20?= =?UTF-8?q?=ED=8C=8C=EC=9D=BC=20=EB=B3=B4=EC=99=84=20(deleted=5Fat=20?= =?UTF-8?q?=EC=BB=AC=EB=9F=BC,=20notification=5Fdelivery=5Fresults=20?= =?UTF-8?q?=ED=85=8C=EC=9D=B4=EB=B8=94)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../V20260826_01__add_deleted_at_to_notifications.sql | 3 +++ ...60826_02__create_notification_delivery_results.sql | 11 +++++++++++ 2 files changed, 14 insertions(+) create mode 100644 src/main/resources/db/migration/V20260826_01__add_deleted_at_to_notifications.sql create mode 100644 src/main/resources/db/migration/V20260826_02__create_notification_delivery_results.sql diff --git a/src/main/resources/db/migration/V20260826_01__add_deleted_at_to_notifications.sql b/src/main/resources/db/migration/V20260826_01__add_deleted_at_to_notifications.sql new file mode 100644 index 0000000..717c911 --- /dev/null +++ b/src/main/resources/db/migration/V20260826_01__add_deleted_at_to_notifications.sql @@ -0,0 +1,3 @@ +-- 관리자 공지사항 soft delete를 위한 deleted_at 컬럼 추가 +ALTER TABLE notifications + ADD COLUMN IF NOT EXISTS deleted_at TIMESTAMP; diff --git a/src/main/resources/db/migration/V20260826_02__create_notification_delivery_results.sql b/src/main/resources/db/migration/V20260826_02__create_notification_delivery_results.sql new file mode 100644 index 0000000..6d754e6 --- /dev/null +++ b/src/main/resources/db/migration/V20260826_02__create_notification_delivery_results.sql @@ -0,0 +1,11 @@ +-- 관리자 공지/예약 알림 발송 결과(대상/성공/실패 건수) 집계 테이블 +CREATE TABLE IF NOT EXISTS notification_delivery_results ( + id BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, + notification_id BIGINT NOT NULL, + target_count INT NOT NULL, + success_count INT NOT NULL DEFAULT 0, + failure_count INT NOT NULL DEFAULT 0, + created_at TIMESTAMP, + updated_at TIMESTAMP, + CONSTRAINT uk_notification_delivery_results_notification_id UNIQUE (notification_id) +); From 29530a4edf63f4f78fef93f217f7fbaf7b38b333 Mon Sep 17 00:00:00 2001 From: si-zero Date: Sun, 30 Aug 2026 23:29:00 +0900 Subject: [PATCH 2/2] =?UTF-8?q?docs:=20=EC=95=8C=EB=A6=BC=20=EB=8F=84?= =?UTF-8?q?=EB=A9=94=EC=9D=B8=20ERD=EB=A5=BC=20=EC=8B=A4=EC=A0=9C=20?= =?UTF-8?q?=EC=8A=A4=ED=82=A4=EB=A7=88=EC=97=90=20=EB=A7=9E=EA=B2=8C=20?= =?UTF-8?q?=EA=B0=B1=EC=8B=A0=20(NotificationSchedule/DeliveryResult=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 --- docs/erd/notice-notification.puml | 73 +++++++++++++++++++++++-------- 1 file changed, 54 insertions(+), 19 deletions(-) diff --git a/docs/erd/notice-notification.puml b/docs/erd/notice-notification.puml index 5402b62..be440e8 100644 --- a/docs/erd/notice-notification.puml +++ b/docs/erd/notice-notification.puml @@ -7,35 +7,70 @@ entity "USERS\n사용자" as users { * id : Long <> } -entity "NOTICES\n전체 공지" as notices { +entity "NOTIFICATIONS\n인앱 알림 / 공지 (user_id NULL이면 전체 broadcast)" as notifications { * id : Long <> -- - title : string - body : text - notice_type : string - is_pinned : boolean - starts_at : datetime - ends_at : datetime + user_id : Long <> + category : ENUM('CONTENT', 'NOTICE', 'EVENT') + detail_code : ENUM('NEW_BATTLE', 'COMMENT_LIKE', 'NEW_COMMENT', 'CREDIT_EARNED', 'POLICY_CHANGE', 'PROMOTION', 'VOTE_RESULT', 'DAILY_MESSAGE') + title : VARCHAR(150) + body : TEXT + reference_id : Long (nullable) + perspective_id : Long (nullable) + is_read : boolean + read_at : datetime (nullable) + deleted_at : datetime (nullable) created_at : datetime + updated_at : datetime } -entity "NOTIFICATIONS\n알림 발송 이력" as notifications { +entity "NOTIFICATION_READS\nbroadcast 알림 유저별 읽음 처리" as notification_reads { * id : Long <> -- - user_id : Long <> - notification_type : string - title : string - body : text - payload_json : text - status : string - scheduled_at : datetime - sent_at : datetime - failed_at : datetime - provider_message_id : string - failure_reason : string + notification_id : Long <> + user_id : Long created_at : datetime + updated_at : datetime + UNIQUE(notification_id, user_id) +} + +entity "NOTIFICATION_SCHEDULES\n관리자 예약 발송(매일 정해진 시각)" as notification_schedules { + * id : Long <> + -- + title : VARCHAR(150) + subtitle : VARCHAR(150) + send_time : TIME + enabled : boolean + last_sent_date : DATE (nullable) + created_at : datetime + updated_at : datetime +} + +entity "NOTIFICATION_DELIVERY_RESULTS\n공지/예약 발송 결과(대상/성공/실패 건수)" as notification_delivery_results { + * id : Long <> + -- + notification_id : Long <> + target_count : int + success_count : int + failure_count : int + created_at : datetime + updated_at : datetime } users ||--o{ notifications +notifications ||--o{ notification_reads +notifications ||--o| notification_delivery_results + +note right of notifications + user_id가 NULL이면 전체 broadcast 알림(공지/이벤트/예약메시지). + broadcast 알림의 유저별 읽음 상태는 notification_reads에 별도 기록하고, + 개인 알림(user_id 존재)의 읽음 상태는 is_read/read_at을 직접 사용한다. + deleted_at은 관리자 공지 soft delete용. +end note + +note right of notification_delivery_results + notifyAdminNotice()로 발송되는 공지(NOTICE/EVENT)와 예약 알림만 생성된다. + CONTENT 카테고리 공지는 이 발송 트리거를 타지 않아 결과가 없다. +end note @enduml