ペット管理仕様 (FR-003)
| 項目 | 内容 |
|---|---|
| 対象FR | FR-003(ペット登録) |
| 優先度 | 高 |
| ステータス | 詳細化済み |
概要
認証済みユーザーは1匹以上の猫をペットとして登録できる。登録されたペットは体重・食事・通院などの健康記録の親エンティティとなる。ペットプロフィールには名前・品種・生年月日・性別・避妊/去勢状態・写真を含む。初期フェーズでは猫のみを対象とする。
入力フィールド
| フィールド | 型 | 必須 | バリデーション |
|---|---|---|---|
| name | varchar | ○ | 1〜50文字、前後の空白はトリム |
| breedId | integer | - | 存在する cat_breeds.id であること |
| breedOther | varchar | - | breedId 未指定時のみ有効、1〜50文字 |
| dateOfBirth | date | - | ISO 8601 日付形式(YYYY-MM-DD)、未来日不可 |
| isBirthdayEstimated | boolean | - | dateOfBirth 指定時のみ有効、default false |
| sex | varchar | ○ | male / female / unknown |
| isNeutered | boolean | ○ | - |
| coatColor | varchar | - | 1〜50文字 |
| memo | text | - | 最大500文字 |
- 品種は
cat_breedsマスタテーブルから選択するか、「その他」としてbreedOtherに自由入力する breedIdとbreedOtherの両方が指定された場合はbreedIdを優先し、breedOtherは無視する- 生年月日が不明な場合(保護猫など)は推定日付を入力し、
isBirthdayEstimatedをtrueにする - 写真(
photoUrl)はスキーマに定義するが、アップロード機能は後続フェーズで実装する
制約
| 項目 | 値 |
|---|---|
| 1ユーザーあたりの登録上限 | 50匹 |
| 対象ペット種別 | 猫のみ(初期フェーズ) |
APIエンドポイント
全エンドポイントで認証必須(__Host-session Cookie)。
| メソッド | パス | 概要 |
|---|---|---|
| POST | /api/pets | ペット登録 |
| GET | /api/pets | 自分のペット一覧 |
| GET | /api/pets/:petId | ペット詳細 |
| PATCH | /api/pets/:petId | ペット更新 |
| DELETE | /api/pets/:petId | ペット削除(論理削除) |
POST /api/pets — ペット登録
リクエストボディに入力フィールドを指定してペットを登録する。
- 成功時:
201 Created、作成されたペット情報を返す breedIdが存在しない場合:422 Unprocessable Entity- 登録上限超過:
409 Conflict
リクエスト:
{ "name": "そうにゃ", "breedId": 3, "dateOfBirth": "2024-05-01", "isBirthdayEstimated": false, "sex": "female", "isNeutered": true, "coatColor": "キジトラ"}成功レスポンス:
{ "data": { "id": 1, "name": "そうにゃ", "breedId": 3, "breedOther": null, "dateOfBirth": "2024-05-01", "isBirthdayEstimated": false, "sex": "female", "isNeutered": true, "coatColor": "キジトラ", "photoUrl": null, "memo": null, "createdAt": "2026-02-18T10:00:00Z", "updatedAt": "2026-02-18T10:00:00Z" }}GET /api/pets — ペット一覧
ログインユーザーが登録したペットの一覧を返す。論理削除済みペットは含まない。
- 成功時:
200 OK - ペット未登録時: 空配列を返す(エラーではない)
{ "data": [ { "id": 1, "name": "そうにゃ", "..." : "..." }, { "id": 2, "name": "みけ", "..." : "..." } ]}GET /api/pets/:petId — ペット詳細
指定IDのペット情報を返す。
- 成功時:
200 OK(レスポンス形式はPOSTと同一) - 存在しない / 他ユーザーのペット / 論理削除済み:
404 Not Found
PATCH /api/pets/:petId — ペット更新
指定したフィールドのみ部分更新する。リクエストボディに含まれないフィールドは変更しない。
リクエスト(例: 名前と避妊状態を更新):
{ "name": "そうにゃん", "isNeutered": true}- 成功時:
200 OK、更新後のペット情報を返す - 存在しない / 他ユーザーのペット / 論理削除済み:
404 Not Found breedIdが存在しない場合:422 Unprocessable Entity
DELETE /api/pets/:petId — ペット削除
論理削除(deleted_at に現在日時を設定)する。関連する健康記録は保持される。
- 成功時:
204 No Content - 存在しない / 他ユーザーのペット / 既に削除済み:
404 Not Found
認可ルール
- 全エンドポイントで認証必須(未認証は
401 Unauthorized) - 自分が登録したペットのみ操作可能(他ユーザーのペットIDを指定した場合は
404を返し、存在の有無を漏らさない) - 論理削除済みペットへのアクセスは
404を返す - 家族メンバーによる共有アクセスは FR-011 で定義
エッジケース
breedIdとbreedOtherの両方が指定された場合 →breedIdを優先し、breedOtherはnullとして保存するdateOfBirthなしでisBirthdayEstimated: trueが送信された場合 →isBirthdayEstimatedはfalseとして保存する- 登録上限(50匹)超過 →
409 Conflict(エラー詳細に上限超過を明示) - 同名のペット登録 → 許可する(別個体として扱う)
- 生年月日が未来日 →
422 Unprocessable Entity - 削除済みペットのIDへのアクセス →
404 Not Found - 削除済みペットへの更新・再削除リクエスト →
404 Not Found - ペット削除時に関連する健康記録が存在 → 健康記録は保持される(論理削除のため)
拡張予定(現時点ではスコープ外)
- 猫以外のペット種別への対応(犬、小動物等)
- プロフィール写真のアップロードAPI
- ペットの並び順カスタマイズ
- ペットのアーカイブ機能(削除ではなく非表示化)
- 家族共有時の共有ペットへのアクセス(FR-011で対応)
検証方法
- ペットを登録し、一覧・詳細で取得できること
- 必須フィールド(name, sex, isNeutered)が欠けた場合にバリデーションエラーになること
- 存在しない
breedId指定時に422が返ること - 未来日の生年月日が拒否されること
- 登録上限(50匹)を超えた場合にエラーになること
- 他ユーザーのペットにアクセスした場合に
404が返ること - ペット情報の部分更新が正しく反映されること
- ペット削除後に関連する健康記録データがDBに保持されていること
- 未認証状態で全エンドポイントが
401を返すこと