Skip to content

Commit bde266a

Browse files
newt239claude
andauthored
fix: APIからparentNameフィールドを削除 (#255) (#256)
緊急連絡先氏名フィールド(parentName)がバリデーションエラーを引き起こす問題を修正。 フロントエンドがparentLastName/parentFirstNameに移行済みのため、 旧parentNameフィールドをAPI定義・SQL・ビジネスロジックから完全に削除した。 DBカラム(parent_name)はDEFAULT ''で残存し、既存データを保持する。 Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent a0d397c commit bde266a

13 files changed

+156
-218
lines changed

docs/emergency_contact_name_spec.md

Lines changed: 36 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -2,31 +2,27 @@
22

33
## 概要
44

5-
緊急連絡先の氏名を「氏名」「名字」「名前」の3フィールドで扱い、データベースでは既存の氏名カラムに加えて名字・名前用のカラムを追加します。既存の `parent_name`(氏名)カラムは残し、`parent_last_name`(名字)および `parent_first_name`(名前)を新規追加することで、既存クライアントの動作を維持しつつ、名字・名前を個別に扱えるようにします
5+
緊急連絡先の氏名を「名字」「名前」の2フィールドで扱う。データベースでは `parent_last_name`(名字)および `parent_first_name`(名前)カラムを使用する
66

7-
- **氏名**: 既存の `parent_name` カラム。フルネームとしての表示・更新に利用する。
8-
- **名字**: 新規 `parent_last_name` カラム。姓のみを格納する。
9-
- **名前**: 新規 `parent_first_name` カラム。名のみを格納する。
7+
旧フィールド `parent_name`(氏名フルネーム)は DB カラムとしては残存するが(`DEFAULT ''`)、API・SQL からは参照・更新しない。
108

11-
本人の氏名と同様、緊急連絡先も **parentLastName = 名字(姓)、parentFirstName = 名前(名)** の命名とします。
9+
- **名字**: `parent_last_name` カラム。姓のみを格納する。
10+
- **名前**: `parent_first_name` カラム。名のみを格納する。
11+
12+
本人の氏名と同様、緊急連絡先も **parentLastName = 名字(姓)、parentFirstName = 名前(名)** の命名とする。
1213

1314
## データベース
1415

1516
### 対象テーブル: `user_private_profiles`
1617

17-
#### 既存カラム(変更なし)
18-
19-
- `parent_name VARCHAR(255) NOT NULL` … 緊急連絡先氏名(フルネーム)
20-
21-
#### 追加カラム
18+
#### 使用カラム
2219

2320
- `parent_last_name VARCHAR(255) NOT NULL DEFAULT ''` … 緊急連絡先の名字
2421
- `parent_first_name VARCHAR(255) NOT NULL DEFAULT ''` … 緊急連絡先の名前
2522

26-
#### マイグレーション
23+
#### 廃止済みカラム(残存)
2724

28-
- 上記2カラムを `ALTER TABLE` で追加するのみとする。
29-
- 既存行へのデータ投入は行わない。既存レコードは `parent_last_name` および `parent_first_name` がデフォルトの空文字のままとなる。
25+
- `parent_name VARCHAR(255) NOT NULL DEFAULT ''` … 旧・緊急連絡先氏名。API からは参照・更新しない。既存データの保持のみ。
3026

3127
## API レスポンス(取得)
3228

@@ -36,11 +32,8 @@
3632

3733
| フィールド | 説明 | 対応DBカラム |
3834
|-----------|------|--------------|
39-
| `parentName` | 緊急連絡先氏名(既存) | `parent_name` |
40-
| `parentLastName` | 緊急連絡先の名字(新規) | `parent_last_name` |
41-
| `parentFirstName` | 緊急連絡先の名前(新規) | `parent_first_name` |
42-
43-
既存クライアントは `parentName` のみを参照しても従来どおり動作する。新規クライアントは `parentLastName` / `parentFirstName` も利用可能。
35+
| `parentLastName` | 緊急連絡先の名字 | `parent_last_name` |
36+
| `parentFirstName` | 緊急連絡先の名前 | `parent_first_name` |
4437

4538
## API リクエスト(作成・更新)
4639

@@ -50,35 +43,35 @@
5043

5144
| フィールド | 説明 | 更新先DBカラム |
5245
|-----------|------|----------------|
53-
| `parentName` | 緊急連絡先氏名 | `parent_name` |
5446
| `parentLastName` | 緊急連絡先の名字 | `parent_last_name` |
5547
| `parentFirstName` | 緊急連絡先の名前 | `parent_first_name` |
5648

57-
- OpenAPI 上では `parentName` / `parentLastName` / `parentFirstName`**required にしない**。既存クライアントが `parentName` のみを送る利用形態を許容する
49+
- OpenAPI 上では `parentLastName` / `parentFirstName`**required にしない**
5850
- 未送信のフィールドは更新しない(既存値維持)。部分更新として扱う。
51+
- `parentLastName``parentFirstName` は必ずセットで送信する必要がある。片方のみの送信は 400 Bad Request を返す。
5952

6053
## バリデーション
6154

62-
- **送信したフィールドに空文字を許容しない**: リクエストに含まれた `parentName` / `parentLastName` / `parentFirstName` のいずれかが空文字の場合は、400 Bad Request を返す。
63-
- 未送信のフィールドは「空文字」としては扱わず、更新対象から外す(既存値維持)。このため、従来どおり `parentName` のみを送るクライアントはそのまま動作する。
55+
- **送信したフィールドに空文字を許容しない**: リクエストに含まれた `parentLastName` / `parentFirstName` のいずれかが空文字の場合は、400 Bad Request を返す。
56+
- 未送信のフィールドは「空文字」としては扱わず、更新対象から外す(既存値維持)。
6457

6558
## 後方互換性
6659

67-
- **既存クライアント**: `parentName` のみの送受信で従来どおり利用可能。レスポンスに `parentLastName` / `parentFirstName` が追加されても、無視すればよい
68-
- **新規クライアント**: `parentLastName` / `parentFirstName` を送受信することで、名字・名前を個別に扱える
60+
- `parentName` フィールドは API から完全に削除済み。リクエストに含まれていても Go の JSON デコーダにより無視される
61+
- DB の `parent_name` カラムは `DEFAULT ''` で残存し、既存データは保持される
6962

7063
## 実装時の変更ファイル一覧(参考)
7164

7265
| 種別 | ファイル |
7366
|------|----------|
74-
| スキーマ | 新規マイグレーション(`parent_last_name`, `parent_first_name` の追加) |
75-
| OpenAPI | `document/schemas/req_put_user_me_private.yml`プロパティ `parentLastName`, `parentFirstName` を追加(required には含めない) |
76-
| OpenAPI | `document/schemas/res_get_user_me_private.yml`プロパティ `parentLastName`, `parentFirstName` を追加 |
77-
| SQL | `pkg/db/sql/user/select_user_private_from_user_id.sql`新カラムを SELECT に含める |
78-
| SQL | `pkg/db/sql/user/update_user_private.sql`新カラムを UPDATE に含める |
79-
| SQL | `pkg/db/sql/user/insert_user_private.sql`新カラムを INSERT に含める |
80-
| Go | `pkg/user/get_user_me_private.go` … private 構造体およびレスポンスマッピングに新フィールドを追加 |
81-
| Go | `pkg/user/put_user_me_private.go`パラメータ構造体に新フィールドを追加し、空文字チェックのバリデーションを実装 |
67+
| OpenAPI | `document/schemas/req_put_user_me_private.yml``parentLastName`, `parentFirstName` のみ |
68+
| OpenAPI | `document/schemas/res_get_user_me_private.yml``parentLastName`, `parentFirstName` のみ |
69+
| SQL | `pkg/db/sql/user/select_user_private_from_user_id.sql``parent_last_name`, `parent_first_name` を SELECT |
70+
| SQL | `pkg/db/sql/user/update_user_private.sql``parent_last_name`, `parent_first_name` を UPDATE |
71+
| SQL | `pkg/db/sql/user/insert_user_private.sql``parent_last_name`, `parent_first_name` を INSERT |
72+
| SQL | `pkg/db/sql/user/insert_user_private_default.sql`デフォルト INSERT`parent_name` は含めない) |
73+
| Go | `pkg/user/get_user_me_private.go` … private 構造体に `ParentLastName`, `ParentFirstName` のみ |
74+
| Go | `pkg/user/put_user_me_private.go``parentLastName` / `parentFirstName` のペアバリデーションと更新処理 |
8275
| 生成 | `make generate_api` 実行により `pkg/api/models.gen.go` 等の生成コードを更新 |
8376

8477
`*.gen.go` および `*.gen.yml` は直接編集せず、OpenAPI 修正後に `make generate_api` で更新する。
@@ -89,28 +82,24 @@
8982

9083
以下は `GET /user/me/private` および `PUT /user/me/private` の動作確認用テスト項目である。認証は Bearer トークン(JWT の `sub` にユーザーID)が必要。開発環境では `.env``AUTH=disable` にし、署名検証なしでトークンを扱える。
9184

92-
**JWT(テスト用トークン)**: プロジェクトルートで `make jwt` を実行すると有効なテスト用 JWT が出力される(`scripts/gen_jwt.sh`)。第1引数で user_id を指定可能。形式の詳細は [グループ管理機能 仕様書](docs/group_management_spec.md) の「認証ヘッダー設定」を参照。
93-
9485
### 前提
9586

9687
- ベースURL: `http://localhost:8000``BACKEND_PORT` に合わせる)
97-
- 認証: `Authorization: Bearer <JWT>``sub` に対象ユーザーの UUID)。形式は上記グループ管理仕様書に同じ。
88+
- 認証: `Authorization: Bearer <JWT>``sub` に対象ユーザーの UUID)
9889
- 対象ユーザーに `user_private_profiles` が存在すること(存在しない場合は PUT で新規作成される)
9990
- **テスト実行前**: (1) `make migrate` を実行し、`user_private_profiles``parent_last_name` / `parent_first_name` が存在することを確認する。(2) 実装反映後はバックエンドを再ビルド・再起動(例: `make build && make up`)してから叩くこと。
10091

10192
### テスト一覧
10293

10394
| No. | エンドポイント | 内容 | 期待結果 |
10495
|-----|----------------|------|----------|
105-
| 1 | GET /user/me/private | 個人情報取得 | 200。レスポンスに `parentName`, `parentLastName`, `parentFirstName` が含まれる。既存データのみの場合は `parentLastName` / `parentFirstName` は空文字の可能性あり。 |
106-
| 2 | PUT /user/me/private | 3フィールドすべて指定して更新 | 200。`parentName`, `parentLastName`, `parentFirstName` をすべて送信。レスポンスで同じ値が返る。 |
107-
| 3 | GET /user/me/private | 更新後の取得 | 200。No.2 で送った `parentName`, `parentLastName`, `parentFirstName` がそのまま返る。 |
108-
| 4 | PUT /user/me/private | 既存クライアント様式(parentName のみ送信) | 200。`parentName` のみ含め、`parentLastName` / `parentFirstName` は送らない。既存の名字・名前は維持され、氏名のみ更新される。 |
109-
| 5 | GET /user/me/private | 部分更新後の取得 | 200。No.4 で更新した `parentName` が反映され、`parentLastName` / `parentFirstName` は前回(No.2)の値のまま。 |
110-
| 6 | PUT /user/me/private | parentLastName / parentFirstName のみ送信 | 200。名字・名前のみ送信し、`parentName` は送らない。氏名は既存値維持、名字・名前のみ更新。 |
111-
| 7 | PUT /user/me/private | parentName に空文字を送信 | 400 Bad Request。メッセージに「緊急連絡先氏名に空文字は指定できません」等の旨が含まれる。 |
112-
| 8 | PUT /user/me/private | parentLastName に空文字を送信 | 400 Bad Request。メッセージに「緊急連絡先の名字に空文字は指定できません」等の旨が含まれる。 |
113-
| 9 | PUT /user/me/private | parentFirstName に空文字を送信 | 400 Bad Request。メッセージに「緊急連絡先の名前に空文字は指定できません」等の旨が含まれる。 |
96+
| 1 | GET /user/me/private | 個人情報取得 | 200。レスポンスに `parentLastName`, `parentFirstName` が含まれる。 |
97+
| 2 | PUT /user/me/private | parentLastName / parentFirstName を指定して更新 | 200。レスポンスで同じ値が返る。 |
98+
| 3 | GET /user/me/private | 更新後の取得 | 200。No.2 で送った `parentLastName`, `parentFirstName` がそのまま返る。 |
99+
| 4 | PUT /user/me/private | parentLastName / parentFirstName を送らずに更新 | 200。名字・名前は既存値が維持される。 |
100+
| 5 | PUT /user/me/private | parentLastName のみ送信(parentFirstName なし) | 400 Bad Request。名字と名前は両方指定が必要。 |
101+
| 6 | PUT /user/me/private | parentLastName に空文字を送信 | 400 Bad Request。「緊急連絡先の名字に空文字は指定できません」の旨。 |
102+
| 7 | PUT /user/me/private | parentFirstName に空文字を送信 | 400 Bad Request。「緊急連絡先の名前に空文字は指定できません」の旨。 |
114103

115104
### curl 例(テスト用)
116105

@@ -121,27 +110,10 @@ TOKEN="$(make jwt | head -1)"
121110
# No.1 GET 取得
122111
curl -s -w "\n%{http_code}" -H "Authorization: Bearer $TOKEN" http://localhost:8000/user/me/private
123112

124-
# No.2 PUT 3フィールド指定(parentHomephoneNumber は省略可。送る場合は電話番号形式)
113+
# No.2 PUT 名字・名前指定
125114
curl -s -w "\n%{http_code}" -X PUT -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
126-
-d '{"lastName":"山田","lastNameKana":"ヤマダ","firstName":"太郎","firstNameKana":"タロウ","isMale":true,"phoneNumber":"09012345678","address":"東京都","parentName":"山田花子","parentLastName":"山田","parentFirstName":"花子","parentCellphoneNumber":"09098765432","parentHomephoneNumber":"0312345678","parentAddress":"東京都"}' \
115+
-d '{"lastName":"山田","lastNameKana":"ヤマダ","firstName":"太郎","firstNameKana":"タロウ","isMale":true,"phoneNumber":"09012345678","address":"東京都","parentLastName":"山田","parentFirstName":"花子","parentCellphoneNumber":"09098765432","parentHomephoneNumber":"0312345678","parentAddress":"東京都"}' \
127116
http://localhost:8000/user/me/private
128117
```
129118

130-
(PUT のボディは必須項目をすべて含む。緊急連絡先氏名まわりは `parentName` / `parentLastName` / `parentFirstName` を必要に応じて省略可能。`parentHomephoneNumber` を送る場合は電話番号形式であること。)
131-
132-
### 実施結果の記録(任意)
133-
134-
| No. | 期待HTTP | 実際のHTTP | 備考 |
135-
|-----|----------|------------|------|
136-
| 1 | 200 | 200 または 404 | 404 は個人情報未登録時。PUT で作成後に 200 |
137-
| 2 | 200 | **200** | parentName/parentLastName/parentFirstName 反映 |
138-
| 3 | 200 | **200** | No.2 の値が返る |
139-
| 4 | 200 | **200** | parentName のみ更新、名字・名前は維持 |
140-
| 5 | 200 | **200** | 部分更新の確認 |
141-
| 6 | 200 | **200** | parentLastName/parentFirstName のみ更新 |
142-
| 7 | 400 | **400** | 緊急連絡先氏名の長さは少なくとも1文字は… |
143-
| 8 | 400 | **400** | 緊急連絡先の名字の長さは少なくとも1文字は… |
144-
| 9 | 400 | **400** | 緊急連絡先の名前の長さは少なくとも1文字は… |
145-
146-
- **JWT**: テスト用トークンの形式は [group_management_spec.md](docs/group_management_spec.md) の「認証ヘッダー設定」に従うこと(jwt.io で `sub` にユーザー UUID、必要なら `exp` を含めたダミートークンを生成する)。
147-
- **「不明なエラーが発生しました」の原因**: このメッセージは `get_user_me_private.go` では `dbClient.Select()``err != nil` のとき、`put_user_me_private.go` では `dbClient.DuplicateUpdate()``err != nil` のときに返る。**実際の原因はクライアントには返さず、サーバー側のログ(`logrus.Error(err.Log)`)にのみ出力される**。500 が出たらバックエンドのコンテナログ(`make logs``docker compose logs backend`)で `err.Log` の内容を確認すること。想定される原因例: (1) テスト用 JWT が不正で `user_id` が期待どおりでない、(2) `make migrate` 前で DB に `parent_last_name` / `parent_first_name` が無い、(3) SQL や struct の不整合。
119+
(PUT のボディは必須項目をすべて含む。`parentLastName` / `parentFirstName` は省略可能だが、送る場合は両方セットで。`parentHomephoneNumber` を送る場合は電話番号形式であること。)

document/bundle.gen.yml

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2043,7 +2043,6 @@ components:
20432043
- isMale
20442044
- phoneNumber
20452045
- address
2046-
- parentName
20472046
- parentLastName
20482047
- parentFirstName
20492048
- parentCellphoneNumber
@@ -2064,8 +2063,6 @@ components:
20642063
type: string
20652064
address:
20662065
type: string
2067-
parentName:
2068-
type: string
20692066
parentLastName:
20702067
type: string
20712068
parentFirstName:
@@ -2123,11 +2120,6 @@ components:
21232120
x-oapi-codegen-extra-tags:
21242121
validate: 'required,min=1,max=255'
21252122
ja: 住所
2126-
parentName:
2127-
type: string
2128-
x-oapi-codegen-extra-tags:
2129-
validate: 'omitempty,min=1,max=255'
2130-
ja: 緊急連絡先氏名
21312123
parentLastName:
21322124
type: string
21332125
x-oapi-codegen-extra-tags:

document/schemas/req_put_user_me_private.yml

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,6 @@ properties:
4444
x-oapi-codegen-extra-tags:
4545
validate: required,min=1,max=255
4646
ja: 住所
47-
parentName:
48-
type: string
49-
x-oapi-codegen-extra-tags:
50-
validate: omitempty,min=1,max=255
51-
ja: 緊急連絡先氏名
5247
parentLastName:
5348
type: string
5449
x-oapi-codegen-extra-tags:

document/schemas/res_get_user_me_private.yml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ required:
66
- isMale
77
- phoneNumber
88
- address
9-
- parentName
109
- parentLastName
1110
- parentFirstName
1211
- parentCellphoneNumber
@@ -27,8 +26,6 @@ properties:
2726
type: string
2827
address:
2928
type: string
30-
parentName:
31-
type: string
3229
parentLastName:
3330
type: string
3431
parentFirstName:

pkg/api/models.gen.go

Lines changed: 0 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)