コンテンツにスキップ

体重記録仕様 (FR-004)

項目内容
対象FRFR-004(体重記録)
優先度
ステータス詳細化済み

概要

ユーザーはペットの体重を日時とともに記録できる。1日に複数回の記録が可能で、記録にはメモを添えられる。記録された体重は一覧APIで日付範囲を指定して取得でき、クライアント側で時系列グラフを描画する。

入力フィールド

フィールド必須バリデーション
weightGinteger1〜30000(単位: g)
recordedAttimestamptz未来日時不可
memotext-最大200文字
  • 体重はグラム単位の整数で保存・入出力する(浮動小数点の精度問題を回避)
  • recordedAt はクライアントが計測日時を指定する(サーバー側の createdAt とは独立)
  • 同一ペット・同一日時でも複数レコードの登録を許可する

APIエンドポイント

全エンドポイントで認証必須(__Host-session Cookie)。

メソッドパス概要
POST/api/pets/:petId/weights体重記録
GET/api/pets/:petId/weights体重記録一覧(日付範囲フィルタ・ページネーション対応)
GET/api/pets/:petId/weights/:weightId体重記録詳細
PATCH/api/pets/:petId/weights/:weightId体重記録更新
DELETE/api/pets/:petId/weights/:weightId体重記録削除

POST /api/pets/:petId/weights — 体重記録

リクエストボディに体重情報を指定して記録する。

リクエスト:

{
"weightG": 4500,
"recordedAt": "2026-02-18T09:00:00+09:00",
"memo": "朝食前"
}
  • 成功時: 201 Created、作成されたレコードを返す
  • ペットが存在しない / 他ユーザーのペット / 論理削除済み: 404 Not Found

成功レスポンス:

{
"data": {
"id": 1,
"petId": 1,
"weightG": 4500,
"recordedAt": "2026-02-18T00:00:00.000Z",
"memo": "朝食前",
"createdAt": "2026-02-18T10:00:00.000Z",
"updatedAt": "2026-02-18T10:00:00.000Z"
}
}

GET /api/pets/:petId/weights — 体重記録一覧

指定ペットの体重記録を一覧取得する。日付範囲フィルタとページネーションに対応する。

クエリパラメータ:

パラメータ必須デフォルト説明
fromISO 8601日時--取得開始日時(recordedAt >= from
toISO 8601日時--取得終了日時(recordedAt <= to
limitinteger-50取得件数上限(1〜100)
offsetinteger-0オフセット(0以上)
orderstring-descソート順(asc / descrecordedAt 基準)
  • 成功時: 200 OK
  • 記録なし: 空配列を返す(エラーではない)

成功レスポンス:

{
"data": [
{
"id": 2,
"petId": 1,
"weightG": 4520,
"recordedAt": "2026-02-18T21:00:00.000Z",
"memo": null,
"createdAt": "2026-02-18T22:00:00.000Z",
"updatedAt": "2026-02-18T22:00:00.000Z"
},
{
"id": 1,
"petId": 1,
"weightG": 4500,
"recordedAt": "2026-02-18T00:00:00.000Z",
"memo": "朝食前",
"createdAt": "2026-02-18T10:00:00.000Z",
"updatedAt": "2026-02-18T10:00:00.000Z"
}
],
"pagination": {
"total": 30,
"limit": 50,
"offset": 0
}
}

GET /api/pets/:petId/weights/:weightId — 体重記録詳細

指定IDの体重記録を返す。

  • 成功時: 200 OK
  • 存在しない / 他ユーザーのペットの記録: 404 Not Found

PATCH /api/pets/:petId/weights/:weightId — 体重記録更新

指定したフィールドのみ部分更新する。リクエストボディに含まれないフィールドは変更しない。

リクエスト(例: 体重とメモを修正):

{
"weightG": 4480,
"memo": "計り直し"
}
  • 成功時: 200 OK、更新後のレコードを返す
  • 存在しない / 他ユーザーのペットの記録: 404 Not Found

DELETE /api/pets/:petId/weights/:weightId — 体重記録削除

体重記録を物理削除する。

  • 成功時: 204 No Content
  • 存在しない / 他ユーザーのペットの記録: 404 Not Found

認可ルール

  • 全エンドポイントで認証必須
  • :petId で指定したペットが自分の所有であること(他ユーザーのペットIDの場合は 404 を返し、存在の有無を漏らさない)
  • :weightId のレコードが :petId に属すること(不一致は 404
  • 論理削除済みペットへの操作は 404 を返す

エッジケース

  • recordedAt が未来日時 → 422 Unprocessable Entity
  • weightG が範囲外(0以下 / 30001以上) → 422 Unprocessable Entity
  • 論理削除済みペットへの体重記録作成 → 404 Not Found
  • 同一ペット・同一 recordedAt で複数登録 → 許可する(制約なし)
  • ペット論理削除時 → 体重記録は保持される(論理削除のためカスケード削除は発動しない)
  • ペット物理削除時 → 関連する体重記録もカスケード削除される(DB制約)

拡張予定(現時点ではスコープ外)

  • 体重の統計・集計API(期間別の平均・最大・最小など)
  • BCS(Body Condition Score)の記録
  • 体重の目標値設定・アラート機能
  • 体重変動が大きい場合の自動通知(FR-010と連携)

検証方法

  • 体重記録 → 一覧取得 → 詳細取得の一連フローが完了すること
  • 必須フィールド(weightG, recordedAt)未指定時にバリデーションエラーが返ること
  • weightG が範囲外(0以下、30001以上)の場合に 422 が返ること
  • recordedAt が未来日時の場合に 422 が返ること
  • 他ユーザーのペットに対する操作で 404 が返ること
  • PATCH で指定したフィールドのみが更新され、他フィールドが変更されないこと
  • DELETE 後に一覧・詳細から表示されなくなること
  • 日付範囲フィルタ(from / to)で正しく絞り込まれること
  • ページネーション(limit / offset)が正しく動作すること
  • ソート順(asc / desc)が正しく適用されること
  • 同一日時に複数レコードを登録できること
  • 論理削除済みペットへの操作が 404 を返すこと