0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Python × Dify × RAGで学ぶ業務システム開発入門【第3回 ER図・画面設計編】

0
Last updated at Posted at 2026-06-17

はじめに

前回は、業務の現状分析から要求定義・要件定義までを行いました。

前回の記事:Python × Dify × RAGで学ぶ業務システム開発入門【第2回 要求定義・要件定義編】

第3回では、定義した機能要件をテーブル構造(ER図)と画面設計に落とし込みます。

コードを書き始める前にこの設計を固めることには、明確な理由があります。

ER図を先に設計する理由
  → テーブル構造が決まれば、どんなSQLを書けばよいかが見える
  → 後からカラムを追加すると、既存コードへの影響が大きい

画面設計を先に行う理由
  → 画面が決まれば、必要なURLとデータの流れが見える
  → 実装途中で「この画面、どこに置く?」という混乱を防げる

本連載は「作って終わり」ではなく、なぜそう設計するのかを重視しています。
設計の意図を理解することで、他のシステムにも応用できる力が身につきます。

本記事で学ぶこと

項目 内容
ER図 テーブル設計・カラム定義・リレーション
画面一覧 必要な画面とURLの整理
画面遷移図 画面間の移動ルールの整理
ワイヤーフレーム 主要画面のレイアウト設計

ER図とは何か

ER図(Entity-Relationship Diagram)とは、データベースのテーブル構造と関係性を図で表したものです。

Entity(エンティティ)  ── テーブルに対応する
Relationship(リレーション) ── テーブル間の関係(1対多・多対多)
Attribute(属性)       ── テーブルのカラム

ER図を読み書きできるようになると、

  • 「このデータはどのテーブルに入れるべきか」
  • 「JOINはどのテーブルとどのテーブルで行うか」
  • 「外部キーはどこに置くか」

といった判断が素早くできるようになります。

テーブル設計

第2回で定義した機能要件(F-01〜F-53)をもとに、必要なテーブルを設計します。

テーブル一覧

テーブル名 概要 対応機能
user ログインユーザー・権限管理 F-01〜F-03
department 部署マスタ F-15
employee 社員マスタ F-10〜F-16
training 研修マスタ F-20〜F-21
training_enrollment 研修受講登録(誰がどの研修を受講するか) F-22
training_history 研修受講履歴(出席率・理解度・課題スコア) F-23〜F-25
evaluation 評価(スコア・AIコメント) F-30〜F-33
daily_report 日報・週報 F-40〜F-42

各テーブルの詳細設計

user(ログインユーザー)

カラム名 制約 説明
id INTEGER PK / AUTO 主キー
username TEXT NOT NULL / UNIQUE ログインID
password TEXT NOT NULL ハッシュ化済みパスワード
role TEXT NOT NULL 権限(admin / staff / user)
created_at DATETIME DEFAULT NOW 作成日時

password カラムには平文のパスワードを絶対に保存しないでください。
第4回で werkzeug.security.generate_password_hash を使ったハッシュ化を実装します。

department(部署マスタ)

カラム名 制約 説明
id INTEGER PK / AUTO 主キー
dept_name TEXT NOT NULL / UNIQUE 部署名
created_at DATETIME DEFAULT NOW 作成日時

employee(社員マスタ)

カラム名 制約 説明
id INTEGER PK / AUTO 主キー
employee_no TEXT NOT NULL / UNIQUE 社員番号
name TEXT NOT NULL 氏名
department TEXT 部署名
position TEXT 役職
hire_date DATE 入社日
is_active INTEGER DEFAULT 1 有効フラグ(0=退職)
created_at DATETIME DEFAULT NOW 作成日時
updated_at DATETIME DEFAULT NOW 更新日時

is_active = 0 にすることで論理削除を実現します。
物理削除(レコードを消す)と異なり、退職者のデータを研修履歴・評価に残せます。

training(研修マスタ)

カラム名 制約 説明
id INTEGER PK / AUTO 主キー
training_name TEXT NOT NULL 研修名
start_date DATE 開始日
end_date DATE 終了日
description TEXT 研修概要
created_at DATETIME DEFAULT NOW 作成日時

training_history(研修受講履歴)

カラム名 制約 説明
id INTEGER PK / AUTO 主キー
employee_id INTEGER FK → employee.id 受講者
training_id INTEGER FK → training.id 研修
attendance_rate REAL DEFAULT 0.0 出席率(0.0〜100.0)
understanding_level INTEGER DEFAULT 0 理解度スコア(0〜100)
report_score INTEGER DEFAULT 0 課題・レポートスコア
created_at DATETIME DEFAULT NOW 作成日時

employee_idtraining_id の組み合わせで、誰がどの研修を受講したかを表します。
この2つの外部キーの組み合わせに UNIQUE 制約を設けることで、同じ組み合わせの重複登録を防ぎます。

evaluation(評価)

カラム名 制約 説明
id INTEGER PK / AUTO 主キー
employee_id INTEGER FK → employee.id 評価対象社員
score REAL 総合評価スコア
ai_comment TEXT AI生成コメント
created_at DATETIME DEFAULT NOW 評価日時

daily_report(日報)

カラム名 制約 説明
id INTEGER PK / AUTO 主キー
employee_id INTEGER FK → employee.id 日報作成者
report_date DATE NOT NULL 日報の日付
content TEXT 学習内容・作業内容
memo TEXT 所感・気づき
created_at DATETIME DEFAULT NOW 作成日時

ER図(全体)

テーブル間のリレーションを整理します。

┌──────────┐         ┌─────────────────────┐         ┌──────────┐
│ employee │ 1     * │  training_history   │ *     1 │ training │
│──────────│─────────│─────────────────────│─────────│──────────│
│ id    PK │         │ id              PK  │         │ id    PK │
│ emp_no   │         │ employee_id  FK(*)  │         │ name     │
│ name     │         │ training_id  FK(*)  │         │ start_dt │
│ dept     │         │ attendance_rate     │         │ end_dt   │
│ position │         │ understanding_level │         └──────────┘
│ hire_date│         │ report_score        │
│ is_active│         └─────────────────────┘
└────┬─────┘
     │ 1
     │                ┌────────────┐
     │ *              │ evaluation │
     └────────────────│────────────│
     │                │ id      PK │
     │                │ employee_id│
     │                │ score      │
     │                │ ai_comment │
     │                └────────────┘
     │ 1
     │                ┌──────────────┐
     │ *              │ daily_report │
     └────────────────│──────────────│
                      │ id        PK │
                      │ employee_id  │
                      │ report_date  │
                      │ content      │
                      └──────────────┘

┌──────┐         ┌──────┐
│ user │         │ dept │
│──────│         │──────│
│ id   │         │ id   │
│ name │         │ name │
│ role │         └──────┘
└──────┘

リレーションの読み方

関係 説明
employee 1 → * training_history 1人の社員が複数の研修を受講できる
training 1 → * training_history 1つの研修に複数の社員が参加できる
employee 1 → * evaluation 1人の社員が複数回評価される(年度ごとなど)
employee 1 → * daily_report 1人の社員が複数の日報を持つ

画面設計

テーブル設計が終わったら、次は画面設計です。
「どんな画面が必要か」「画面間をどう移動するか」を先に決めます。

画面一覧

画面名 URL HTTPメソッド 対応機能 権限
ログイン /login GET / POST F-01 全員
ダッシュボード / GET - 全員
社員一覧 /employees GET F-10 / F-11 staff / admin
社員登録 /employees/new GET / POST F-12 staff / admin
社員編集 /employees/<id>/edit GET / POST F-13 staff / admin
社員削除 /employees/<id>/delete POST F-14 admin
研修一覧 /trainings GET F-20 staff / admin
研修登録 /trainings/new GET / POST F-21 staff / admin
研修履歴 /trainings/<id>/history GET / POST F-22〜F-25 staff / admin
評価一覧 /evaluations GET F-30 staff / admin
評価コメント生成 /evaluations/<id>/generate POST F-31 staff / admin
Excel取込 /import GET / POST F-16 / F-26 staff / admin
Excel出力 /export GET F-32 staff / admin
日報一覧 /reports GET F-41 全員
日報登録 /reports/new GET / POST F-40 user以上
社内文書検索 /search GET / POST F-50 / F-51 全員
FAQチャット /chat GET F-52 / F-53 全員

画面遷移図

画面間の移動ルールを整理します。

[ログイン画面]
     │ ログイン成功
     ▼
[ダッシュボード] ─────────────────────────────────────┐
     │                                              │
     ├──▶ [社員一覧]                                │
     │         ├──▶ [社員登録] ──▶ 登録完了 ──▶ [社員一覧]
     │         └──▶ [社員編集] ──▶ 更新完了 ──▶ [社員一覧]
     │
     ├──▶ [研修一覧]
     │         └──▶ [研修履歴(出席・理解度入力)]
     │                    └──▶ 保存完了 ──▶ [研修履歴]
     │
     ├──▶ [評価一覧]
     │         └──▶ [AIコメント生成] ──▶ 生成完了 ──▶ [評価一覧]
     │
     ├──▶ [Excel取込] ──▶ 取込完了 ──▶ [社員一覧 or 研修履歴]
     ├──▶ [Excel出力] ──▶ ファイルダウンロード
     │
     ├──▶ [日報一覧]
     │         └──▶ [日報登録] ──▶ 登録完了 ──▶ [日報一覧]
     │
     ├──▶ [社内文書検索] ──▶ 検索結果表示(同一画面)
     └──▶ [FAQチャット]  ──▶ チャット応答(同一画面)
                                                    │
                      ログアウト ◀──────────────────┘
                          │
                     [ログイン画面]

ワイヤーフレーム(主要画面)

実際の開発では Figma などのツールを使います。

ダッシュボード

image.png

社員一覧

image.png

社員登録・編集フォーム

image.png

評価一覧・AIコメント生成

image.png

社内文書検索(RAG)

image.png

設計をコードに反映する

ER図と画面設計が決まれば、実装の見通しが立ちます。
設計と実装の対応関係を整理しておきます。

テーブル設計 → database.py

# database.py(抜粋)
def init_db():
    conn = get_db()
    cur = conn.cursor()
    cur.executescript("""
        CREATE TABLE IF NOT EXISTS employee (
            id           INTEGER PRIMARY KEY AUTOINCREMENT,
            employee_no  TEXT    NOT NULL UNIQUE,
            name         TEXT    NOT NULL,
            department   TEXT,
            position     TEXT,
            hire_date    DATE,
            is_active    INTEGER NOT NULL DEFAULT 1,  -- 論理削除フラグ
            created_at   DATETIME DEFAULT CURRENT_TIMESTAMP,
            updated_at   DATETIME DEFAULT CURRENT_TIMESTAMP
        );

        CREATE TABLE IF NOT EXISTS training_history (
            id                  INTEGER PRIMARY KEY AUTOINCREMENT,
            employee_id         INTEGER NOT NULL REFERENCES employee(id),
            training_id         INTEGER NOT NULL REFERENCES training(id),
            attendance_rate     REAL    DEFAULT 0.0,
            understanding_level INTEGER DEFAULT 0,
            report_score        INTEGER DEFAULT 0,
            -- 同一社員が同一研修に重複登録されるのを防ぐ
            UNIQUE (employee_id, training_id)
        );
    """)
    conn.commit()

画面設計 → app.py のルーティング

# app.py(抜粋)
# 画面一覧の URL がそのままルーティングに対応する

@app.route("/employees")               # 社員一覧
@app.route("/employees/new")           # 社員登録
@app.route("/employees/<id>/edit")     # 社員編集
@app.route("/employees/<id>/delete")   # 社員削除(POST)

@app.route("/trainings")               # 研修一覧
@app.route("/trainings/<id>/history")  # 研修履歴

@app.route("/evaluations")             # 評価一覧
@app.route("/evaluations/<id>/generate") # AIコメント生成(POST)

@app.route("/search")                  # 社内文書検索
@app.route("/chat")                    # FAQチャット

画面設計 → templates/ のHTMLファイル

templates/
  ├── base.html             ← 共通ナビゲーション(全画面で継承)
  ├── login.html            ← ログイン画面
  ├── index.html            ← ダッシュボード
  ├── employee_list.html    ← 社員一覧ワイヤーフレームに対応
  ├── employee_form.html    ← 社員登録・編集フォームに対応
  ├── training_list.html    ← 研修一覧
  ├── training_history.html ← 研修履歴(出席・理解度入力)
  ├── evaluation.html       ← 評価一覧・AIコメント生成に対応
  ├── import.html           ← Excel取込
  ├── report.html           ← 日報一覧
  ├── search.html           ← 社内文書検索ワイヤーフレームに対応
  └── chat.html             ← FAQチャット

今後の連載予定

タイトル 主な内容
第1回 業務システム全体設計編 システム概要・技術選定・アーキテクチャ
第2回 要求定義・要件定義編 業務分析・機能要件・非機能要件
第3回 ER図・画面設計編(本記事) テーブル設計・画面遷移図・ワイヤーフレーム
第4回 Flaskログイン機能編 セッション・パスワードハッシュ・認証ミドルウェア
第5回 社員管理CRUD編 一覧・登録・更新・削除・バリデーション
第6回 研修管理編 リレーション・集計・出席率自動計算
第7回 Excel業務自動化編 pandas取込・openpyxl出力・テンプレート活用
第8回 Dify API連携編 プロンプト設計・API呼び出し・エラーハンドリング
第9回 RAG構築編 Knowledgeへの登録・Embedding・検索精度改善
第10回 FAQチャットボット編 チャットUI・会話履歴・ストリーミングレスポンス
第11回 GitHubチーム開発編 ブランチ戦略・Pull Request・コードレビュー
第12回 テスト編 pytest・テスト設計・デモ・振り返り

おわりに

第3回では、ER図と画面設計を通じて「実装の地図」を作成しました。

ポイントを振り返ります。

  • ER図:8つのテーブルとリレーションを設計。外部キー・論理削除・UNIQUE制約の考え方を整理した
  • 画面一覧:17画面のURL・HTTPメソッド・権限を整理し、app.py のルーティングと対応させた
  • 画面遷移図:画面間の移動ルールを可視化し、実装時の迷いをなくした
  • ワイヤーフレーム:主要5画面のレイアウトを設計し、テンプレートHTML作成の土台を作った

次回は**「Flaskログイン機能編」**として、ログイン・ログアウト・セッション管理・パスワードハッシュ化を実装します。
設計した user テーブルと login 画面のワイヤーフレームを使って、いよいよコードを書き始めます。

次回 : Python × Dify × RAGで学ぶ業務システム開発入門【第4回 Flaskログイン機能編】

参考リンク

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?