DOCUMENT 08

データベース設計書

calendar_today 作成日:2026-05-14 更新日:2026-05-24 person 作成者:清水宏美 push_pin Ver 2.0(正規化チェック済み・全テーブル追記)

1 ER図

テーブル関連図(テキストER図)
1 ─ * = 1対多(必須) /  0..1 ─ 1 = 任意1対1 /  * ─ * = 多対多(中間テーブル経由)
【1. Auth / ユーザー】
[roles] 1 ─ * [users]

【2. ペット・健康管理】
[users] 1 ─ 0..* [pets]                         (owner_user_id)
[pets]  1 ─ 0..* [health_records]
[users] 1 ─ 0..* [health_records]               (recorded_by_user_id)
[pets]  1 ─ 0..* [pet_care_records]
[users] 1 ─ 0..* [pet_care_records]             (recorded_by_user_id)
[pets]  1 ─ 0..* [symptom_checks]
[users] 1 ─ 0..* [symptom_checks]               (requested_by_user_id)

【3. プラン・課金】
[plans] 1 ─ *    [plan_features]                (PK: plan_id + feature_code)
[plans] 1 ─ 0..* [subscriptions]
[users] 1 ─ 0..* [subscriptions]
[pets]  1 ─ 0..* [subscriptions]
[subscriptions] 1 ─ 0..* [invoices]
[invoices]      1 ─ 0..* [payments]

【4. 予約・診療記録】
[users]             1 ─ 0..* [appointment_slots] (created_by_user_id)
[appointment_slots] 1 ─ 0..* [appointments]      (slot_id, NULL可)
[pets]              1 ─ 0..* [appointments]
[users]             1 ─ 0..* [appointments]       (owner_user_id)
[users]          0..1 ─ 0..* [appointments]       (staff_user_id, NULL可)
[appointments] 0..1  ─ 1    [medical_histories]   (UNIQUE FK)
[pets]              1 ─ 0..* [medical_histories]
[users]             1 ─ 0..* [medical_histories]  (handled_by_user_id)
[medical_histories] 1 ─ 0..* [medical_attachments]

【5. メッセージング・通知】
[users]          1 ─ 0..* [consult_chat_messages]
[users]          1 ─ 0..* [notifications]          (created_by_user_id)
[notifications] * ─ *    [users]
  └── 中間テーブル: [notification_recipients] (PK: notification_id + user_id)
[email_templates] 1 ─ 0..* [email_messages]
[users]           1 ─ 0..* [email_messages]        (recipient_user_id)
[pets]         0..1 ─ 0..* [email_messages]
[appointments] 0..1 ─ 0..* [email_messages]
[invoices]     0..1 ─ 0..* [email_messages]

【6. UX補助】
[pets]  1 ─ 0..* [pet_calendar_marks]
[users] 1 ─ 0..* [pet_calendar_marks]   (created_by_user_id)
[users] 1 ─ 0..* [dismissed_reminders]
[users] 1 ─ 0..* [announcements]        (created_by_user_id)
[users] 1 ─ 0..* [password_reset_tokens]
              
ビジュアルER図(ドメイン別カラーマップ)
ドメインごとに色分け。凡例: ||—o{ 1対多(必須FK)  |o—o{ 1対多(任意FK)  |o—o| 任意1対1(UNIQUE nullable FK)
🔐 Auth 🐾 Pets & Health 💳 Plans & Billing 📅 Appointments & Medical 💬 Messaging ⚙ UX Helpers
🔐 Auth / 認証(2テーブル)
%%{init:{"theme":"base","themeVariables":{"primaryColor":"#dbeafe","primaryBorderColor":"#1d4ed8","lineColor":"#1e40af","background":"#f8fbff","fontFamily":"system-ui,sans-serif","attributeBackgroundColorEven":"#eff6ff","attributeBackgroundColorOdd":"#dbeafe"}}}%%
erDiagram
    roles {
        bigint id PK "ロールID"
        varchar role_code UK "ADMIN/SUPER/USER/VET/STAFF"
        varchar role_name "ロール名"
    }
    users {
        bigint id PK "ユーザーID"
        bigint role_id FK "ロールID"
        varchar email UK "メールアドレス"
        varchar password_hash "BCryptハッシュ"
        varchar slack_user_id "Slack連携ID"
        varchar line_user_id "LINE連携ID"
        varchar status "ACTIVE/INACTIVE/SUSPENDED"
    }
    roles ||--o{ users : "role_id"
                
🐾 Pets & Health / ペット・健康管理(4テーブル)
%%{init:{"theme":"base","themeVariables":{"primaryColor":"#dcfce7","primaryBorderColor":"#16a34a","lineColor":"#15803d","background":"#f0fdf4","fontFamily":"system-ui,sans-serif","attributeBackgroundColorEven":"#f0fdf4","attributeBackgroundColorOdd":"#dcfce7"}}}%%
erDiagram
    users { bigint id PK "Auth 参照" }
    pets {
        bigint id PK "ペットID"
        bigint owner_user_id FK "飼い主ユーザー"
        varchar name "ペット名"
        varchar species "DOG/CAT 等"
        varchar sex "MALE/FEMALE"
        date birth_date "生年月日"
    }
    health_records {
        bigint id PK "健康記録ID"
        bigint pet_id FK "ペット"
        bigint recorded_by_user_id FK "記録者"
        date record_date "記録日"
        decimal weight_kg "体重(kg)"
        integer meal_score "食事 1-5"
        integer exercise_score "運動 1-5"
        integer overall_score "総合 1-5"
    }
    pet_care_records {
        bigint id PK "ケア記録ID"
        bigint pet_id FK "ペット"
        bigint recorded_by_user_id FK "記録者"
        varchar care_type "RABIES/HEARTWORM/COMBO_VACCINE..."
        date administered_on "実施日"
        date next_due_on "次回予定日"
    }
    symptom_checks {
        bigint id PK "症状チェックID"
        bigint pet_id FK "ペット"
        bigint requested_by_user_id FK "依頼者"
        varchar severity "LOW/MEDIUM/HIGH"
        varchar recommendation "OBSERVE/CONSULT/VISIT"
        text guidance "AIガイダンス"
    }
    users ||--o{ pets : "owner_user_id"
    pets ||--o{ health_records : "pet_id"
    users ||--o{ health_records : "recorded_by_user_id"
    pets ||--o{ pet_care_records : "pet_id"
    users ||--o{ pet_care_records : "recorded_by_user_id"
    pets ||--o{ symptom_checks : "pet_id"
    users ||--o{ symptom_checks : "requested_by_user_id"
                
💳 Plans & Billing / プラン・課金(5テーブル)
%%{init:{"theme":"base","themeVariables":{"primaryColor":"#fef3c7","primaryBorderColor":"#d97706","lineColor":"#b45309","background":"#fffbeb","fontFamily":"system-ui,sans-serif","attributeBackgroundColorEven":"#fffbeb","attributeBackgroundColorOdd":"#fef3c7"}}}%%
erDiagram
    users { bigint id PK "Auth 参照" }
    pets { bigint id PK "Pets 参照" }
    plans {
        bigint id PK "プランID"
        varchar name "LIGHT/STANDARD/PREMIUM"
        decimal monthly_fee "月額(円)"
        jsonb features_json "機能フラグ(表示用)"
        boolean is_active "有効フラグ"
    }
    plan_features {
        bigint plan_id FK "プランID"
        varchar feature_code "AI_SYMPTOM/SLACK_BOT/LINE_BOT/ZOOM_CONSULT"
    }
    subscriptions {
        bigint id PK "サブスクID"
        bigint user_id FK "契約ユーザー"
        bigint pet_id FK "対象ペット"
        bigint plan_id FK "プランID"
        date start_date "開始日"
        varchar status "ACTIVE/PAUSED/CANCELED"
        boolean auto_renew "自動更新"
    }
    invoices {
        bigint id PK "請求書ID"
        bigint subscription_id FK "サブスク"
        varchar invoice_number UK "請求書番号"
        decimal amount "請求金額"
        varchar payment_status "UNPAID/PARTIAL/PAID"
    }
    payments {
        bigint id PK "支払ID"
        bigint invoice_id FK "請求書"
        decimal paid_amount "支払金額"
        varchar payment_method "CARD/BANK/OTHER"
        varchar status "PENDING/SUCCEEDED/FAILED"
    }
    plans ||--o{ plan_features : "plan_id"
    plans ||--o{ subscriptions : "plan_id"
    users ||--o{ subscriptions : "user_id"
    pets ||--o{ subscriptions : "pet_id"
    subscriptions ||--o{ invoices : "subscription_id"
    invoices ||--o{ payments : "invoice_id"
                
📅 Appointments & Medical / 予約・診療記録(4テーブル)
%%{init:{"theme":"base","themeVariables":{"primaryColor":"#ede9fe","primaryBorderColor":"#7c3aed","lineColor":"#6d28d9","background":"#faf5ff","fontFamily":"system-ui,sans-serif","attributeBackgroundColorEven":"#faf5ff","attributeBackgroundColorOdd":"#ede9fe"}}}%%
erDiagram
    users { bigint id PK "Auth 参照" }
    pets { bigint id PK "Pets 参照" }
    appointment_slots {
        bigint id PK "予約枠ID"
        bigint created_by_user_id FK "作成者(ADMIN)"
        timestamp slot_datetime "枠日時"
        varchar note "備考"
    }
    appointments {
        bigint id PK "予約ID"
        bigint pet_id FK "対象ペット"
        bigint owner_user_id FK "飼い主"
        bigint staff_user_id FK "担当スタッフ(NULL可)"
        bigint slot_id FK "予約枠(NULL可)"
        varchar appointment_type "CONSULTATION/MEDICAL"
        varchar channel "ONLINE/VISIT/HOSPITAL"
        varchar status "REQUESTED/CONFIRMED/CANCELED/COMPLETED"
        varchar zoom_join_url "Zoom URL"
    }
    medical_histories {
        bigint id PK "診療記録ID"
        bigint pet_id FK "ペット"
        bigint appointment_id FK "関連予約(NULL可,UNIQUE)"
        bigint handled_by_user_id FK "対応者(VET/STAFF)"
        date performed_on "実施日"
        varchar treatment_detail "対応内容"
        varchar diagnosis "診断内容"
    }
    medical_attachments {
        bigint id PK "添付ファイルID"
        bigint medical_history_id FK "診療記録"
        varchar file_name "ファイル名"
        varchar file_mime_type "MIMEタイプ"
        bigint file_size_bytes "サイズ"
    }
    users ||--o{ appointment_slots : "created_by_user_id"
    appointment_slots |o--o{ appointments : "slot_id"
    pets ||--o{ appointments : "pet_id"
    users ||--o{ appointments : "owner_user_id"
    users |o--o{ appointments : "staff_user_id"
    appointments |o--o| medical_histories : "appointment_id(UNIQUE)"
    pets ||--o{ medical_histories : "pet_id"
    users ||--o{ medical_histories : "handled_by_user_id"
    medical_histories ||--o{ medical_attachments : "medical_history_id"
                
💬 Messaging / メッセージング・通知(5テーブル)
%%{init:{"theme":"base","themeVariables":{"primaryColor":"#ccfbf1","primaryBorderColor":"#0d9488","lineColor":"#0f766e","background":"#f0fdfa","fontFamily":"system-ui,sans-serif","attributeBackgroundColorEven":"#f0fdfa","attributeBackgroundColorOdd":"#ccfbf1"}}}%%
erDiagram
    users { bigint id PK "Auth 参照" }
    pets { bigint id PK "Pets 参照" }
    appointments { bigint id PK "Appointments 参照" }
    invoices { bigint id PK "Billing 参照" }
    consult_chat_messages {
        bigint id PK "チャットメッセージID"
        bigint user_id FK "ユーザー"
        varchar sender_type "USER/BOT"
        varchar message "メッセージ本文"
    }
    notifications {
        bigint id PK "通知ID"
        bigint created_by_user_id FK "作成者"
        varchar notification_type "REMINDER/INFO/ALERT"
        varchar title "タイトル"
        varchar delivery_status "DRAFT/SCHEDULED/SENT/FAILED"
    }
    notification_recipients {
        bigint notification_id FK "通知ID (PK)"
        bigint user_id FK "受信ユーザー (PK)"
        timestamp read_at "既読日時(NULL=未読)"
        varchar delivery_status "PENDING/SENT/FAILED"
    }
    email_templates {
        bigint id PK "テンプレートID"
        varchar template_code UK "コード"
        varchar subject_template "件名テンプレート"
    }
    email_messages {
        bigint id PK "メール送信ID"
        bigint template_id FK "テンプレート"
        bigint recipient_user_id FK "宛先ユーザー"
        bigint pet_id FK "関連ペット(NULL可)"
        bigint appointment_id FK "関連予約(NULL可)"
        bigint invoice_id FK "関連請求書(NULL可)"
        varchar status "QUEUED/SENT/FAILED"
    }
    users ||--o{ consult_chat_messages : "user_id"
    users ||--o{ notifications : "created_by_user_id"
    notifications ||--o{ notification_recipients : "notification_id"
    users ||--o{ notification_recipients : "user_id"
    email_templates ||--o{ email_messages : "template_id"
    users ||--o{ email_messages : "recipient_user_id"
    pets |o--o{ email_messages : "pet_id"
    appointments |o--o{ email_messages : "appointment_id"
    invoices |o--o{ email_messages : "invoice_id"
                
⚙ UX Helpers / UX補助(4テーブル)
%%{init:{"theme":"base","themeVariables":{"primaryColor":"#ffe4e6","primaryBorderColor":"#e11d48","lineColor":"#be123c","background":"#fff1f2","fontFamily":"system-ui,sans-serif","attributeBackgroundColorEven":"#fff1f2","attributeBackgroundColorOdd":"#ffe4e6"}}}%%
erDiagram
    users { bigint id PK "Auth 参照" }
    pets { bigint id PK "Pets 参照" }
    pet_calendar_marks {
        bigint id PK "マークID"
        bigint pet_id FK "ペット"
        bigint created_by_user_id FK "作成者"
        date mark_date "マーク日付"
        varchar mark_type "KARTE/VACCINE/HOSPITAL/TRIMMING/DOG_RUN/MEDICINE"
        varchar memo "メモ"
    }
    dismissed_reminders {
        bigint id PK "ID"
        bigint user_id FK "ユーザー"
        varchar reminder_key "リマインダーキー"
        timestamp dismissed_at "非表示設定日時"
    }
    announcements {
        bigint id PK "お知らせID"
        bigint created_by_user_id FK "作成者(ADMIN)"
        varchar title "タイトル"
        text body "本文"
        boolean is_active "表示フラグ"
    }
    password_reset_tokens {
        bigint id PK "トークンID"
        bigint user_id FK "ユーザー"
        varchar token UK "リセットトークン"
        timestamp expires_at "有効期限"
        timestamp used_at "使用日時(NULL=未使用)"
    }
    pets ||--o{ pet_calendar_marks : "pet_id"
    users ||--o{ pet_calendar_marks : "created_by_user_id"
    users ||--o{ dismissed_reminders : "user_id"
    users ||--o{ announcements : "created_by_user_id"
    users ||--o{ password_reset_tokens : "user_id"
                

2 正規化評価

正規形チェック結果
実施日: 2026-05-24 / 対象: schema.sql の全24テーブル
正規形 評価 所見
第1正規形(1NF) ✅ 合格 全テーブルで原子値を保持。plans.features_json は JSONB だが制御された非正規化(後述)。
第2正規形(2NF) ✅ 合格 複合PKを持つ中間テーブル(plan_features, notification_recipients)でも、全非キー属性がPK全体に完全関数従属。
第3正規形(3NF) ✅ 合格 推移的関数従属なし。subscriptions.user_idpet_id → pets.owner_user_id 経由で導出可能だが、クエリ性能上の意図的冗長化として許容(後述)。
ボイス・コッド正規形(BCNF) ✅ 合格 全テーブルで決定子がスーパーキーである。候補キーが複数存在するテーブルは users(id, email)のみで矛盾なし。
意図的な非正規化(設計上のトレードオフ)
スキーマ変更なし — 以下はすべて合理的かつ意図的な設計判断
箇所 種別 理由・判断
plans.features_json 表示用冗長化 マーケティング表示用に全機能フラグをJSONで保持。プログラマティックなアクセス制御は plan_features テーブルで行う(役割分担が明確)。
subscriptions.user_id 性能最適化 pet_id → pets.owner_user_id 経由で導出可能だが、ユーザーIDによる直接検索(プラン判定・サブスク一覧)の性能を優先。
health_records のスコア5列 固定属性展開 meal/exercise/sleep/mood/overall の5カテゴリは仕様固定。ピボットテーブル化するより列展開の方がクエリが単純で保守しやすい。
appointments.zoom_join_url APIキャッシュ Zoom API から動的生成も可能だが、生成済みURLをDBキャッシュすることで2回目以降のアクセスでAPI呼び出しを省略。
email_messages.body 監査用スナップショット テンプレートから再生成可能だが、実際に送信した内容の監査証跡として送信時点のレンダリング済み本文を保存。

3 テーブル定義(全24テーブル)

全テーブル一覧
見方: 左右スクロール可 / ヘッダー固定 / データ型は PostgreSQL 記法

roles

カラム名データ型NULL許可デフォルト値制約説明
idBIGINTNOIDENTITYPKロールID
role_codeVARCHAR(50)NOUNIQUEロールコード(ADMIN/SUPER/USER/VET/STAFF)
role_nameVARCHAR(100)NOロール名
created_atTIMESTAMPNOCURRENT_TIMESTAMP作成日時
updated_atTIMESTAMPNOCURRENT_TIMESTAMP更新日時

users

カラム名データ型NULL許可デフォルト値制約説明
idBIGINTNOIDENTITYPKユーザーID
role_idBIGINTNOFK → roles.idロールID
nameVARCHAR(50)NO氏名
emailVARCHAR(255)NOUNIQUEメールアドレス(ログインID)
password_hashVARCHAR(255)NOBCryptハッシュパスワード
phoneVARCHAR(20)YESNULL電話番号
slack_user_idVARCHAR(100)YESNULLSlack ユーザーID(連携用)
line_user_idVARCHAR(100)YESNULLLINE ユーザーID(連携用)
statusVARCHAR(20)NO'ACTIVE'CHECK IN (ACTIVE/INACTIVE/SUSPENDED)アカウント状態
last_login_atTIMESTAMPYESNULL最終ログイン日時
deleted_atTIMESTAMPYESNULL論理削除日時
created_atTIMESTAMPNOCURRENT_TIMESTAMP作成日時
updated_atTIMESTAMPNOCURRENT_TIMESTAMP更新日時

pets

カラム名データ型NULL許可デフォルト値制約説明
idBIGINTNOIDENTITYPKペットID
owner_user_idBIGINTNOFK → users.id飼い主ユーザーID
nameVARCHAR(40)NOペット名
speciesVARCHAR(30)NO種別(DOG/CAT 等)
breedVARCHAR(100)YESNULL品種
sexVARCHAR(10)YESNULL性別(MALE/FEMALE 等)
birth_dateDATEYESNULL生年月日
weight_baseline_kgDECIMAL(5,2)YESNULL基準体重(kg)
image_pathVARCHAR(500)YESNULLプロフィール画像ファイルパス
deceased_atTIMESTAMPYESNULL逝去日時
deleted_atTIMESTAMPYESNULL論理削除日時
created_atTIMESTAMPNOCURRENT_TIMESTAMP作成日時
updated_atTIMESTAMPNOCURRENT_TIMESTAMP更新日時

health_records

カラム名データ型NULL許可デフォルト値制約説明
idBIGINTNOIDENTITYPK記録ID
pet_idBIGINTNOFK → pets.idペットID
recorded_by_user_idBIGINTNOFK → users.id記録者ユーザーID
record_dateDATENO記録日
weight_kgDECIMAL(5,2)YESNULL体重(kg)
meal_memoVARCHAR(300)YESNULL食事メモ
exercise_minutesINTEGERYESNULL運動時間(分)
meal_scoreINTEGERYESNULLCHECK 1–5食事スコア
exercise_scoreINTEGERYESNULLCHECK 1–5運動スコア
sleep_scoreINTEGERYESNULLCHECK 1–5睡眠スコア
mood_scoreINTEGERYESNULLCHECK 1–5気分スコア
overall_scoreINTEGERYESNULLCHECK 1–5総合スコア
image_pathVARCHAR(500)YESNULL添付画像パス
noteTEXTYESNULL備考
deleted_atTIMESTAMPYESNULL論理削除日時
created_atTIMESTAMPNOCURRENT_TIMESTAMP作成日時
updated_atTIMESTAMPNOCURRENT_TIMESTAMP更新日時

pet_care_records

カラム名データ型NULL許可デフォルト値制約説明
idBIGINTNOIDENTITYPKケア記録ID
pet_idBIGINTNOFK → pets.idペットID
recorded_by_user_idBIGINTNOFK → users.id記録者ユーザーID
care_typeVARCHAR(30)NOCHECK IN (RABIES/HEARTWORM/COMBO_VACCINE/MEDICAL_VISIT/OTHER)ケア種別
administered_onDATENO実施日
next_due_onDATENO次回予定日(リマインダー基準)
memoVARCHAR(500)YESNULL備考
deleted_atTIMESTAMPYESNULL論理削除日時
created_atTIMESTAMPNOCURRENT_TIMESTAMP作成日時
updated_atTIMESTAMPNOCURRENT_TIMESTAMP更新日時

symptom_checks

カラム名データ型NULL許可デフォルト値制約説明
idBIGINTNOIDENTITYPK症状チェックID
pet_idBIGINTNOFK → pets.idペットID
requested_by_user_idBIGINTNOFK → users.id依頼者ユーザーID
symptom_typeVARCHAR(100)NO症状種別
onset_textVARCHAR(100)YESNULL発症状況テキスト
memoVARCHAR(500)YESNULL補足メモ
severityVARCHAR(10)NOCHECK IN (LOW/MEDIUM/HIGH)重症度
recommendationVARCHAR(10)NOCHECK IN (OBSERVE/CONSULT/VISIT)推奨対応
guidanceTEXTYESNULLAIガイダンス本文
ai_modelVARCHAR(100)YESNULL使用AIモデル名
created_atTIMESTAMPNOCURRENT_TIMESTAMP作成日時(更新なし)

plans

カラム名データ型NULL許可デフォルト値制約説明
idBIGINTNOIDENTITYPKプランID
nameVARCHAR(100)NOプラン名(LIGHT/STANDARD/PREMIUM)
monthly_feeDECIMAL(10,2)NO月額料金(円)
features_jsonJSONBYESNULL機能フラグ一覧(表示用・非正規化②)
is_activeBOOLEANNOTRUE有効フラグ
deleted_atTIMESTAMPYESNULL論理削除日時
created_atTIMESTAMPNOCURRENT_TIMESTAMP作成日時
updated_atTIMESTAMPNOCURRENT_TIMESTAMP更新日時

plan_features

アクセス制御用機能コードテーブル。feature_code: AI_SYMPTOM / SLACK_BOT / LINE_BOT / ZOOM_CONSULT

カラム名データ型NULL許可デフォルト値制約説明
plan_idBIGINTNOPK, FK → plans.idプランID
feature_codeVARCHAR(50)NOPK機能コード

subscriptions

ペット単位の契約。user_id は pet_id → pets.owner_user_id 経由で導出可能だが性能上の意図的冗長化(非正規化②)。

カラム名データ型NULL許可デフォルト値制約説明
idBIGINTNOIDENTITYPKサブスクリプションID
user_idBIGINTNOFK → users.id契約ユーザーID(性能最適化)
pet_idBIGINTNOFK → pets.id対象ペットID
plan_idBIGINTNOFK → plans.idプランID
start_dateDATENO契約開始日
end_dateDATEYESNULL契約終了日(NULLは無期限)
statusVARCHAR(20)NOCHECK IN (ACTIVE/PAUSED/CANCELED)契約状態
auto_renewBOOLEANNOTRUE自動更新フラグ
deleted_atTIMESTAMPYESNULL論理削除日時
created_atTIMESTAMPNOCURRENT_TIMESTAMP作成日時
updated_atTIMESTAMPNOCURRENT_TIMESTAMP更新日時

invoices

スキーマのみ実装済み(コントローラー・サービス未実装)

カラム名データ型NULL許可デフォルト値制約説明
idBIGINTNOIDENTITYPK請求書ID
subscription_idBIGINTNOFK → subscriptions.idサブスクリプションID
invoice_numberVARCHAR(50)NOUNIQUE請求書番号
invoice_dateDATENO請求日
due_dateDATENO支払期日
amountDECIMAL(10,2)NO請求金額
payment_statusVARCHAR(20)NOCHECK IN (UNPAID/PARTIAL/PAID)支払状態
issued_atTIMESTAMPYESNULL発行日時
paid_atTIMESTAMPYESNULL支払完了日時
deleted_atTIMESTAMPYESNULL論理削除日時
created_atTIMESTAMPNOCURRENT_TIMESTAMP作成日時
updated_atTIMESTAMPNOCURRENT_TIMESTAMP更新日時

payments

スキーマのみ実装済み(コントローラー・サービス未実装)

カラム名データ型NULL許可デフォルト値制約説明
idBIGINTNOIDENTITYPK支払ID
invoice_idBIGINTNOFK → invoices.id請求書ID
paid_amountDECIMAL(10,2)NO支払金額
paid_atTIMESTAMPYESNULL支払日時
payment_methodVARCHAR(20)NOCHECK IN (CARD/BANK/OTHER)支払方法
transaction_refVARCHAR(100)YESNULL決済システムトランザクション参照ID
statusVARCHAR(20)NOCHECK IN (PENDING/SUCCEEDED/FAILED)決済状態
created_atTIMESTAMPNOCURRENT_TIMESTAMP作成日時(更新なし)

appointment_slots

カラム名データ型NULL許可デフォルト値制約説明
idBIGINTNOIDENTITYPK予約枠ID
slot_datetimeTIMESTAMPNO予約枠日時
noteVARCHAR(200)YESNULL備考
created_by_user_idBIGINTNOFK → users.id作成者ユーザーID
deleted_atTIMESTAMPYESNULL論理削除日時
created_atTIMESTAMPNOCURRENT_TIMESTAMP作成日時(更新なし)

appointments

カラム名データ型NULL許可デフォルト値制約説明
idBIGINTNOIDENTITYPK予約ID
pet_idBIGINTNOFK → pets.id対象ペットID
owner_user_idBIGINTNOFK → users.id飼い主ユーザーID
staff_user_idBIGINTYESNULLFK → users.id担当スタッフID(承認後に設定)
appointment_typeVARCHAR(20)NOCHECK IN (CONSULTATION/MEDICAL)予約種別
channelVARCHAR(20)NOCHECK IN (ONLINE/VISIT/HOSPITAL)実施チャネル
scheduled_atTIMESTAMPNO予約日時
statusVARCHAR(20)NOCHECK IN (REQUESTED/CONFIRMED/CANCELED/COMPLETED)予約状態
zoom_join_urlVARCHAR(500)YESNULLZoom参加URL(非正規化④)
noteVARCHAR(500)YESNULL備考
slot_idBIGINTYESNULLFK → appointment_slots.id関連予約枠ID
deleted_atTIMESTAMPYESNULL論理削除日時
created_atTIMESTAMPNOCURRENT_TIMESTAMP作成日時
updated_atTIMESTAMPNOCURRENT_TIMESTAMP更新日時

medical_histories

カラム名データ型NULL許可デフォルト値制約説明
idBIGINTNOIDENTITYPK診療記録ID
pet_idBIGINTNOFK → pets.id対象ペットID
appointment_idBIGINTYESNULLUNIQUE, FK → appointments.id関連予約ID(1予約1記録)
handled_by_user_idBIGINTNOFK → users.id対応者(VET/STAFF)ID
performed_onDATENO実施日
treatment_detailVARCHAR(1000)NO対応内容
diagnosisVARCHAR(1000)YESNULL診断内容
prescriptionVARCHAR(1000)YESNULL処方内容
deleted_atTIMESTAMPYESNULL論理削除日時
created_atTIMESTAMPNOCURRENT_TIMESTAMP作成日時
updated_atTIMESTAMPNOCURRENT_TIMESTAMP更新日時

medical_attachments

スキーマのみ実装済み(コントローラー・サービス未実装)

カラム名データ型NULL許可デフォルト値制約説明
idBIGINTNOIDENTITYPK添付ファイルID
medical_history_idBIGINTNOFK → medical_histories.id診療記録ID
file_nameVARCHAR(255)NOファイル名
file_pathVARCHAR(500)NO保存先パス
file_mime_typeVARCHAR(100)NOMIMEタイプ
file_size_bytesBIGINTNOファイルサイズ(bytes)
descriptionVARCHAR(200)YESNULL説明
uploaded_atTIMESTAMPNOCURRENT_TIMESTAMPアップロード日時
deleted_atTIMESTAMPYESNULL論理削除日時
created_atTIMESTAMPNOCURRENT_TIMESTAMP作成日時
updated_atTIMESTAMPNOCURRENT_TIMESTAMP更新日時

consult_chat_messages

カラム名データ型NULL許可デフォルト値制約説明
idBIGINTNOIDENTITYPKメッセージID
user_idBIGINTNOFK → users.idユーザーID
sender_typeVARCHAR(10)NOCHECK IN (USER/BOT)送信者種別
messageVARCHAR(1000)NOメッセージ本文
created_atTIMESTAMPNOCURRENT_TIMESTAMP作成日時(更新なし)

notifications

カラム名データ型NULL許可デフォルト値制約説明
idBIGINTNOIDENTITYPK通知ID
notification_typeVARCHAR(20)NOCHECK IN (REMINDER/INFO/ALERT)通知種別
titleVARCHAR(100)NO通知タイトル
bodyVARCHAR(2000)NO通知本文
scheduled_atTIMESTAMPYESNULL配信予定日時
sent_atTIMESTAMPYESNULL配信完了日時
delivery_statusVARCHAR(20)NOCHECK IN (DRAFT/SCHEDULED/SENT/FAILED)配信状態
created_by_user_idBIGINTNOFK → users.id作成者ユーザーID
deleted_atTIMESTAMPYESNULL論理削除日時
created_atTIMESTAMPNOCURRENT_TIMESTAMP作成日時
updated_atTIMESTAMPNOCURRENT_TIMESTAMP更新日時

notification_recipients

notifications × users の中間テーブル(多対多)

カラム名データ型NULL許可デフォルト値制約説明
notification_idBIGINTNOPK, FK → notifications.id通知ID
user_idBIGINTNOPK, FK → users.id受信ユーザーID
read_atTIMESTAMPYESNULL既読日時
delivery_statusVARCHAR(20)NOCHECK IN (PENDING/SENT/FAILED)配信状態

email_templates

スキーマのみ実装済み(コントローラー・サービス未実装)

カラム名データ型NULL許可デフォルト値制約説明
idBIGINTNOIDENTITYPKテンプレートID
template_codeVARCHAR(100)NOUNIQUEテンプレートコード
subject_templateVARCHAR(200)NO件名テンプレート
body_templateTEXTNO本文テンプレート
is_activeBOOLEANNOTRUE有効フラグ
created_atTIMESTAMPNOCURRENT_TIMESTAMP作成日時
updated_atTIMESTAMPNOCURRENT_TIMESTAMP更新日時

email_messages

スキーマのみ実装済み。subject/body は送信時点のスナップショット(非正規化⑤)。

カラム名データ型NULL許可デフォルト値制約説明
idBIGINTNOIDENTITYPKメール送信ID
template_idBIGINTNOFK → email_templates.id使用テンプレートID
recipient_user_idBIGINTNOFK → users.id宛先ユーザーID
pet_idBIGINTYESNULLFK → pets.id関連ペットID(任意)
appointment_idBIGINTYESNULLFK → appointments.id関連予約ID(任意)
invoice_idBIGINTYESNULLFK → invoices.id関連請求書ID(任意)
subjectVARCHAR(200)NO件名(レンダリング済み)
bodyTEXTNO本文(レンダリング済み)
send_timing_atTIMESTAMPYESNULL送信予定日時
statusVARCHAR(20)NOCHECK IN (QUEUED/SENT/FAILED)送信状態
error_messageTEXTYESNULLエラー内容
sent_atTIMESTAMPYESNULL送信完了日時
created_atTIMESTAMPNOCURRENT_TIMESTAMP作成日時(更新なし)

pet_calendar_marks

カラム名データ型NULL許可デフォルト値制約説明
idBIGINTNOIDENTITYPKマークID
pet_idBIGINTNOFK → pets.idペットID
created_by_user_idBIGINTNOFK → users.id作成者ユーザーID
mark_dateDATENOマーク日付
mark_typeVARCHAR(20)NOCHECK IN (KARTE/VACCINE/HOSPITAL/TRIMMING/DOG_RUN/MEDICINE)マーク種別
memoVARCHAR(500)YESNULLメモ
deleted_atTIMESTAMPYESNULL論理削除日時
created_atTIMESTAMPNOCURRENT_TIMESTAMP作成日時
updated_atTIMESTAMPNOCURRENT_TIMESTAMP更新日時

dismissed_reminders

ユーザーが確認済みにしたスケジュールリマインダーを永続化。(user_id, reminder_key) のユニーク制約で重複防止。

カラム名データ型NULL許可デフォルト値制約説明
idBIGINTNOIDENTITYPKID
user_idBIGINTNOFK → users.idユーザーID
reminder_keyVARCHAR(200)NOリマインダーキー(例: care_1_2026-08-01)
dismissed_atTIMESTAMPNOCURRENT_TIMESTAMP非表示設定日時
UNIQUE (user_id, reminder_key)

announcements

カラム名データ型NULL許可デフォルト値制約説明
idBIGINTNOIDENTITYPKお知らせID
titleVARCHAR(200)NOタイトル
bodyTEXTNO本文
is_activeBOOLEANNOTRUE表示フラグ
created_by_user_idBIGINTNOFK → users.id作成者ユーザーID
created_atTIMESTAMPNOCURRENT_TIMESTAMP作成日時
updated_atTIMESTAMPNOCURRENT_TIMESTAMP更新日時

password_reset_tokens

カラム名データ型NULL許可デフォルト値制約説明
idBIGINTNOIDENTITYPKトークンID
user_idBIGINTNOFK → users.idユーザーID
tokenVARCHAR(100)NOUNIQUEパスワードリセットトークン
expires_atTIMESTAMPNO有効期限
used_atTIMESTAMPYESNULL使用日時(NULL=未使用)
created_atTIMESTAMPNOCURRENT_TIMESTAMP作成日時(更新なし)

4 インデックス設計

インデックス一覧
検索頻度・FK結合・一意制約・ソート用途の観点で選定
テーブル名 インデックス名 対象カラム 種類 設定理由
Auth
rolesuk_roles_role_coderole_codeUNIQUEロールコード一意制約
usersuk_users_emailemailUNIQUEログインID一意制約
usersidx_users_role_idrole_idINDEXロール別検索・FK結合
usersidx_users_status_deleted_atstatus, deleted_atINDEX有効ユーザー絞り込み
ペット・健康管理
petsidx_pets_owner_user_idowner_user_idINDEX飼い主配下のペット検索
petsidx_pets_speciesspeciesINDEX種別検索
health_recordsidx_health_records_pet_record_datepet_id, record_dateINDEXペット別時系列取得
health_recordsidx_health_records_recorded_by_user_idrecorded_by_user_idINDEX記録者検索・FK結合
pet_care_recordsidx_pet_care_records_pet_next_duepet_id, next_due_onINDEX次回予定日によるリマインダー抽出
symptom_checksidx_symptom_checks_pet_created_atpet_id, created_atINDEXペット別チェック履歴
symptom_checksidx_symptom_checks_requested_by_user_idrequested_by_user_idINDEX依頼者検索・FK結合
プラン・課金
plansidx_plans_is_activeis_activeINDEX有効プラン検索
subscriptionsidx_subscriptions_user_statususer_id, statusINDEXユーザー契約一覧・プラン判定
subscriptionsidx_subscriptions_pet_statuspet_id, statusINDEXペット契約一覧
subscriptionsidx_subscriptions_plan_idplan_idINDEXプラン別集計・FK結合
invoicesuk_invoices_invoice_numberinvoice_numberUNIQUE請求書番号一意制約
invoicesidx_invoices_subscription_idsubscription_idINDEXFK結合
invoicesidx_invoices_payment_status_due_datepayment_status, due_dateINDEX未払い・期限順管理
paymentsidx_payments_invoice_idinvoice_idINDEXFK結合
paymentsidx_payments_statusstatusINDEX決済状態別抽出
予約・診療記録
appointment_slotsidx_appointment_slots_datetimeslot_datetimeINDEX日時順検索・空き枠確認
appointmentsidx_appointments_pet_scheduled_atpet_id, scheduled_atINDEXペット別予約一覧・ソート
appointmentsidx_appointments_owner_scheduled_atowner_user_id, scheduled_atINDEX飼い主別予約検索
appointmentsidx_appointments_staff_scheduled_atstaff_user_id, scheduled_atINDEX担当者別予定検索
appointmentsidx_appointments_status_scheduled_atstatus, scheduled_atINDEX状態別の時系列検索
medical_historiesuk_medical_histories_appointment_idappointment_idUNIQUE予約と診療記録の1対1担保
medical_historiesidx_medical_histories_pet_performed_onpet_id, performed_onINDEXペット別履歴検索・日付順
medical_attachmentsidx_medical_attachments_history_idmedical_history_idINDEX履歴配下の添付取得
メッセージング・通知
consult_chat_messagesidx_consult_chat_messages_user_id_createduser_id, created_atINDEXユーザー別チャット履歴
notificationsidx_notifications_created_bycreated_by_user_idINDEX作成者別検索・FK結合
notificationsidx_notifications_status_scheduleddelivery_status, scheduled_atINDEX配信対象抽出
notification_recipientspk_notification_recipientsnotification_id, user_idPRIMARY KEY中間テーブル複合主キー
notification_recipientsidx_notification_recipients_user_statususer_id, delivery_statusINDEXユーザー受信一覧
email_templatesuk_email_templates_template_codetemplate_codeUNIQUEテンプレートコード一意制約
email_messagesidx_email_messages_recipient_createdrecipient_user_id, created_atINDEX宛先別送信履歴
email_messagesidx_email_messages_status_send_timingstatus, send_timing_atINDEX送信キュー処理
email_messagesidx_email_messages_template_idtemplate_idINDEXテンプレート別集計
UX補助
pet_calendar_marksidx_pet_calendar_marks_pet_datepet_id, mark_dateINDEXペット別カレンダー取得
dismissed_remindersuk_dismissed_reminders_user_keyuser_id, reminder_keyUNIQUEユーザー単位でのリマインダー重複防止
dismissed_remindersidx_dismissed_reminders_user_iduser_idINDEXユーザー別リマインダー一覧
password_reset_tokensuk_password_reset_tokens_tokentokenUNIQUEトークン一意制約

5 初期データ

シードデータ(data.sql)
DataInitializer (BCrypt) でユーザーを作成し、data.sql でマスタ・テストデータを投入
【roles】5件
  ADMIN(1) / SUPER(2) / USER(3) / VET(4) / STAFF(5)

【plans】3件
  LIGHT(980円) / STANDARD(1980円) / PREMIUM(2980円)

【plan_features】7件
  STANDARD: AI_SYMPTOM, SLACK_BOT, LINE_BOT
  PREMIUM:  AI_SYMPTOM, SLACK_BOT, LINE_BOT, ZOOM_CONSULT

【users】DataInitializer で自動生成(BCryptハッシュ)
  super@petlife.local (SUPER)
  admin@petlife.local (ADMIN)
  vet1@petlife.local (VET)
  staff1@petlife.local (STAFF)
  owner1@petlife.local / owner2@petlife.local / owner3@petlife.local (USER)

【pets】6件
  ポチ(DOG), タロウ(DOG) — owner1
  レオン(DOG) — owner2
  ピーコ(DOG) / カレン(DOG) / ボス(DOG) — プラン別テストアカウント用

【health_records】3件(各ペットの直近記録)

【pet_care_records】3件(ポチのワクチン・フィラリア・混合ワクチン)

【subscriptions】5件
  owner1→ポチ(STANDARD) / owner2→レオン(STANDARD)
  owner1→ピーコ(LIGHT) / owner2→カレン(STANDARD) / owner3→ボス(PREMIUM)

実行コマンド:
  psql -U postgres -d petlifeplus -f backend/src/main/resources/data.sql