hyperdashi-server/DESIGN.md
2025-07-05 11:50:50 +09:00

10 KiB
Raw Permalink Blame History

HyperDashi バックエンド詳細設計書

1. システム概要

HyperDashiは、情報メディアシステム局の物品管理システム「dashi」の発展版・汎用版である。グラフデータベースと検索エンジンを使用していた従来システムから、運用の簡素化を目的としてRDBベースのシステムに移行する。

1.1 技術スタック

  • 言語: Rust
  • Webフレームワーク: Axum
  • データベース: PostgreSQL (本番環境) / SQLite (開発環境)
  • ORM: SQLx
  • ストレージ: S3互換オブジェクトストレージ (本番環境) / ローカルファイルシステム (開発環境)
  • API形式: REST API

2. データベース設計

2.1 物品情報テーブル (items)

CREATE TABLE items (
    id SERIAL PRIMARY KEY,
    name VARCHAR(255) NOT NULL,
    label_id VARCHAR(50) UNIQUE NOT NULL,
    model_number VARCHAR(255),
    remarks TEXT,
    purchase_year INTEGER,
    purchase_amount DECIMAL(12, 2),
    useful_life INTEGER,
    is_depreciable BOOLEAN DEFAULT FALSE,
    connection_names TEXT[], -- PostgreSQL配列型、SQLiteではJSON
    cable_color_pattern TEXT[], -- PostgreSQL配列型、SQLiteではJSON
    storage_locations TEXT[], -- PostgreSQL配列型、SQLiteではJSON
    is_on_loan BOOLEAN DEFAULT FALSE,
    label_type VARCHAR(20) CHECK (label_type IN ('qr', 'barcode', 'none')),
    is_disposed BOOLEAN DEFAULT FALSE,
    image_url TEXT,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

-- インデックス
CREATE INDEX idx_items_label_id ON items(label_id);
CREATE INDEX idx_items_name ON items(name);
CREATE INDEX idx_items_is_on_loan ON items(is_on_loan);
CREATE INDEX idx_items_is_disposed ON items(is_disposed);

2.2 貸出管理テーブル (loans)

CREATE TABLE loans (
    id SERIAL PRIMARY KEY,
    item_id INTEGER NOT NULL REFERENCES items(id),
    student_number VARCHAR(20) NOT NULL,
    student_name VARCHAR(100) NOT NULL,
    organization VARCHAR(255),
    loan_date TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
    return_date TIMESTAMP WITH TIME ZONE,
    remarks TEXT,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
    updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

-- インデックス
CREATE INDEX idx_loans_item_id ON loans(item_id);
CREATE INDEX idx_loans_student_number ON loans(student_number);
CREATE INDEX idx_loans_return_date ON loans(return_date);

2.3 画像管理テーブル (images) - オプション

CREATE TABLE images (
    id SERIAL PRIMARY KEY,
    file_name VARCHAR(255) NOT NULL,
    content_type VARCHAR(100) NOT NULL,
    storage_type VARCHAR(20) CHECK (storage_type IN ('s3', 'local')),
    storage_path TEXT NOT NULL,
    size_bytes BIGINT,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);

3. API設計

3.1 物品管理API

3.1.1 物品一覧取得

  • エンドポイント: GET /api/v1/items
  • クエリパラメータ:
    • page (optional): ページ番号
    • per_page (optional): 1ページあたりの件数
    • search (optional): 検索キーワード
    • is_on_loan (optional): 貸出中フィルタ
    • is_disposed (optional): 廃棄済みフィルタ
  • レスポンス:
{
  "items": [
    {
      "id": 1,
      "name": "HDMIケーブル 3m",
      "label_id": "HYP-A001",
      "model_number": "HDMI-3M-V2",
      "remarks": "端子部分に少し傷あり",
      "purchase_year": 2023,
      "purchase_amount": 1500.00,
      "useful_life": 5,
      "is_depreciable": false,
      "connection_names": ["HDMI Type-A", "HDMI Type-A"],
      "cable_color_pattern": ["赤", "青", "赤"],
      "storage_locations": ["部屋A", "ラックX", "コンテナα"],
      "is_on_loan": false,
      "label_type": "qr",
      "is_disposed": false,
      "image_url": "https://storage.example.com/images/hdmi-cable.jpg",
      "created_at": "2023-04-01T10:00:00Z",
      "updated_at": "2023-04-01T10:00:00Z"
    }
  ],
  "total": 150,
  "page": 1,
  "per_page": 20
}

3.1.2 物品詳細取得

  • エンドポイント: GET /api/v1/items/{id}
  • レスポンス: 単一の物品オブジェクト

3.1.3 物品登録

  • エンドポイント: POST /api/v1/items
  • リクエストボディ:
{
  "name": "HDMIケーブル 3m",
  "label_id": "HYP-A001",
  "model_number": "HDMI-3M-V2",
  "remarks": "端子部分に少し傷あり",
  "purchase_year": 2023,
  "purchase_amount": 1500.00,
  "useful_life": 5,
  "is_depreciable": false,
  "connection_names": ["HDMI Type-A", "HDMI Type-A"],
  "cable_color_pattern": ["赤", "青", "赤"],
  "storage_locations": ["部屋A", "ラックX", "コンテナα"],
  "label_type": "qr"
}

3.1.4 物品更新

  • エンドポイント: PUT /api/v1/items/{id}
  • リクエストボディ: 物品登録と同じ(全項目更新)

3.1.5 物品部分更新

  • エンドポイント: PATCH /api/v1/items/{id}
  • リクエストボディ: 更新したいフィールドのみ

3.1.6 物品削除

  • エンドポイント: DELETE /api/v1/items/{id}
  • 説明: 論理削除ではなく物理削除(ミス入力の修正用)

3.1.7 物品廃棄/譲渡

  • エンドポイント: POST /api/v1/items/{id}/dispose
  • 説明: is_disposedフラグを立てる

3.1.8 ラベルIDによる物品検索

  • エンドポイント: GET /api/v1/items/by-label/{label_id}
  • 説明: QRコード/バーコード読み取り時の検索用

3.2 貸出管理API

3.2.1 貸出登録

  • エンドポイント: POST /api/v1/loans
  • リクエストボディ:
{
  "item_id": 1,
  "student_number": "21001234",
  "student_name": "山田太郎",
  "organization": "第74回総合祭実行委員会",
  "remarks": "イベント用機材"
}

3.2.2 返却処理

  • エンドポイント: POST /api/v1/loans/{id}/return
  • リクエストボディ:
{
  "return_date": "2023-04-10T15:00:00Z",
  "remarks": "問題なく返却"
}

3.2.3 貸出履歴取得

  • エンドポイント: GET /api/v1/loans
  • クエリパラメータ:
    • item_id (optional): 物品ID
    • student_number (optional): 学籍番号
    • active_only (optional): 未返却のみ

3.2.4 貸出詳細取得

  • エンドポイント: GET /api/v1/loans/{id}

3.3 画像アップロードAPI

3.3.1 画像アップロード

  • エンドポイント: POST /api/v1/images/upload
  • Content-Type: multipart/form-data
  • レスポンス:
{
  "url": "https://storage.example.com/images/abc123.jpg"
}

3.4 一括操作API

3.4.1 物品一括登録

  • エンドポイント: POST /api/v1/items/bulk
  • リクエストボディ: 物品オブジェクトの配列

3.4.2 物品一括更新

  • エンドポイント: PUT /api/v1/items/bulk
  • リクエストボディ: 更新対象の物品オブジェクトの配列

4. アプリケーション構造

4.1 ディレクトリ構造

hyperdashi-server/
├── src/
│   ├── main.rs              # エントリーポイント
│   ├── config.rs            # 設定管理
│   ├── db/
│   │   ├── mod.rs          # データベース接続管理
│   │   └── migrations/     # SQLマイグレーション
│   ├── models/
│   │   ├── mod.rs
│   │   ├── item.rs         # 物品モデル
│   │   └── loan.rs         # 貸出モデル
│   ├── handlers/
│   │   ├── mod.rs
│   │   ├── items.rs        # 物品ハンドラー
│   │   ├── loans.rs        # 貸出ハンドラー
│   │   └── images.rs       # 画像ハンドラー
│   ├── services/
│   │   ├── mod.rs
│   │   ├── item_service.rs # 物品ビジネスロジック
│   │   ├── loan_service.rs # 貸出ビジネスロジック
│   │   └── storage.rs      # ストレージ抽象化
│   ├── utils/
│   │   ├── mod.rs
│   │   ├── validation.rs   # バリデーション
│   │   └── label.rs        # ラベルID生成
│   └── error.rs            # エラー型定義
├── Cargo.toml
├── .env.example
└── README.md

4.2 主要コンポーネント

4.2.1 設定管理 (config.rs)

#[derive(Debug, Deserialize)]
pub struct Config {
    pub database_url: String,
    pub server_host: String,
    pub server_port: u16,
    pub storage_type: StorageType,
    pub s3_config: Option<S3Config>,
    pub local_storage_path: Option<String>,
}

#[derive(Debug, Deserialize)]
pub enum StorageType {
    S3,
    Local,
}

4.2.2 ストレージ抽象化 (storage.rs)

#[async_trait]
pub trait Storage: Send + Sync {
    async fn upload(&self, data: Vec<u8>, filename: &str) -> Result<String>;
    async fn delete(&self, url: &str) -> Result<()>;
}

pub struct S3Storage { /* ... */ }
pub struct LocalStorage { /* ... */ }

5. セキュリティ考慮事項

5.1 認証・認可

  • 初期版では認証なし(内部システムのため)
  • 将来的にはJWT等による認証を実装予定

5.2 入力検証

  • ラベルIDの形式検証英数字、I/O除外
  • SQLインジェクション対策SQLx使用
  • ファイルアップロードのサイズ制限とMIMEタイプ検証

5.3 データ保護

  • 個人情報(学籍番号、氏名)の適切な管理
  • HTTPSによる通信の暗号化

6. パフォーマンス最適化

6.1 データベース

  • 適切なインデックスの設定
  • N+1問題の回避
  • コネクションプーリング

6.2 画像処理

  • 画像のリサイズとサムネイル生成
  • CDN利用による配信最適化将来

6.3 キャッシング

  • 頻繁にアクセスされる物品情報のキャッシング(将来)

7. 運用・保守

7.1 ロギング

  • 構造化ログの出力
  • エラートラッキング

7.2 モニタリング

  • ヘルスチェックエンドポイント
  • メトリクス収集(将来)

7.3 バックアップ

  • データベースの定期バックアップ
  • 画像データのバックアップ

8. 今後の拡張予定

  • 認証・認可機能
  • 物品の予約機能
  • 統計・レポート機能
  • モバイルアプリ対応API
  • WebSocket による リアルタイム更新