在庫管理 Phase 1.5(引当・散布確定)の設計を追記し、CODEX指示書を更新

- 在庫管理機能実装案.md: セクション23(引当・散布確定ワークフロー)を追加
- CODEX.md: Phase 1完了を受け、Phase 1.5実装指示に全面書き換え

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Akira
2026-03-14 17:29:05 +09:00
parent 497bc87c24
commit 42b11a5df8
2 changed files with 949 additions and 760 deletions

1388
CODEX.md

File diff suppressed because it is too large Load Diff

View File

@@ -1578,6 +1578,321 @@ alias 例:
### 22.3 実装フェーズの整理 ### 22.3 実装フェーズの整理
- セクション1〜16: Phase 1初期実装 - セクション1〜16: Phase 1初期実装→ 実装済み
- セクション17〜21: Phase 2公式データ同期、alias辞書、LLM調査支援 - セクション17〜21: Phase 3公式データ同期、alias辞書、LLM調査支援
- CODEX への初回作業指示は Phase 1 のみを対象とする - セクション23: Phase 1.5(施肥計画連携・引当機能)→ 次の実装対象
---
## 23. 施肥計画連携: 引当(reserve)・散布確定フロー
### 23.1 背景と要件
施肥計画を立てるとき、現在の利用可能在庫を見ながら計画を立てたい。
しかし「計画確定 = 即在庫消費」にすると、実際の散布量が計画と異なった場合に
差異調整が毎回必要になる。
そこで「引当 → 散布確定」の2段階方式を採用する。
要件:
- 施肥計画確定時に、計画数量を「引当」として在庫から仮押さえする
- 実際に散布した後、実績数量で「使用確定」に変換する
- 差分は自動で在庫に戻す
- 計画削除・変更時は引当を自動解除する
- 施肥計画画面で「利用可能在庫」を表示し、計画策定の判断材料にする
### 23.2 在庫の3つの状態
```
総在庫 = 入庫 + 調整増 - 使用確定 - 調整減 - 廃棄 - 引当中
利用可能在庫 = 総在庫のうち引当を除いた分
= 入庫 + 調整増 - 使用確定 - 調整減 - 廃棄
引当中 = reserve トランザクションの合計(未確定の施肥計画分)
```
施肥計画画面では「利用可能在庫」を表示する。
在庫一覧画面では「総在庫(引当中 X を含む)」のように表示する。
### 23.3 StockTransaction への変更
#### transaction_type に `reserve` を追加
```python
class TransactionType(models.TextChoices):
PURCHASE = 'purchase', '入庫'
USE = 'use', '使用' # 散布確定済み
RESERVE = 'reserve', '引当' # ← 新規追加
ADJUSTMENT_PLUS = 'adjustment_plus', '棚卸増'
ADJUSTMENT_MINUS = 'adjustment_minus', '棚卸減'
DISCARD = 'discard', '廃棄'
```
`reserve``use` と同じく在庫を減少させる方向で集計する。
#### fertilization_plan FK を追加
```python
fertilization_plan = models.ForeignKey(
'fertilizer.FertilizationPlan',
on_delete=models.SET_NULL,
null=True,
blank=True,
related_name='stock_reservations',
verbose_name='施肥計画',
)
```
当初除外した `reference_type` / `reference_id`Generic FKではなく、
施肥計画への明示的な FK を採用する。理由:
- 現時点で在庫連携が必要なのは施肥計画のみ
- Generic FK は Django の管理上も ORM 上も扱いにくい
- 将来、農薬散布計画が加わった場合は `pesticide_plan` FK を追加すればよい
#### INCREASE_TYPES / DECREASE_TYPES の更新
```python
INCREASE_TYPES = {
TransactionType.PURCHASE,
TransactionType.ADJUSTMENT_PLUS,
}
DECREASE_TYPES = {
TransactionType.USE,
TransactionType.RESERVE, # ← 追加
TransactionType.ADJUSTMENT_MINUS,
TransactionType.DISCARD,
}
```
### 23.4 操作フロー
#### フロー1: 施肥計画の確定(引当作成)
```
ユーザー: 施肥計画を保存
システム: 計画内の各 FertilizationEntry について
→ 対応する Fertilizer.material を特定
→ StockTransaction(type='reserve', material=...,
quantity=bags, fertilization_plan=plan) を作成
→ 利用可能在庫が減少
```
注意: `Fertilizer.material` が null の場合(未連携の古いデータ)は引当を作成しない。
#### フロー2: 散布確定(引当 → 使用変換)
```
ユーザー: 施肥計画画面で「散布確定」ボタンを押す
システム: 確定前の調整画面を表示
┌─────────────┬──────┬──────┬────────┐
│ 圃場 │ 計画 │ 実績 │ 状態 │
├─────────────┼──────┼──────┼────────┤
│ 上の田 │ 3袋 │ 3 │ ✓ │
│ 下の田 │ 4袋 │ 3.5 │ 修正 │
│ 山の畑 │ 2袋 │ 0 │ 未散布 │
└─────────────┴──────┴──────┴────────┘
ユーザー: 各行の実績を確認・修正し、「一括確定」を押す
システム:
- 実績 > 0 の行: reserve を削除 → use(quantity=実績) を作成
- 実績 = 0 の行: reserve を削除(引当解除、在庫に戻る)
- 差分は自動計算(ユーザーの追加操作不要)
```
普段は計画値がそのまま実績にプリセットされるので、何も修正せず「一括確定」するだけ。
アクシデントがあった圃場だけ数量を修正する。
#### フロー3: 計画の削除
```
ユーザー: 施肥計画を削除
システム: その計画に紐づく全 reserve トランザクションを削除
→ 引当が解除され、在庫に戻る
```
#### フロー4: 計画の変更(エントリ追加・削除・数量変更)
```
ユーザー: 施肥計画を編集・保存
システム: その計画に紐づく既存 reserve を全削除
→ 新しいエントリに基づいて reserve を再作成
```
注意: reserve の差分更新は複雑になるため、「全削除 → 再作成」方式を推奨する。
### 23.5 施肥計画画面の在庫表示
施肥計画の編集画面(マトリクス表)で、肥料ごとの在庫情報を表示する。
表示位置: 肥料列ヘッダーの下、または肥料名の横
表示例:
```
仁井田米有機
在庫 18袋 / 計画計 24袋 / 不足 6袋
```
API:
- 既存の `GET /api/materials/stock-summary/` を流用
- または施肥計画用の専用エンドポイントで肥料在庫のみ返す
### 23.6 在庫一覧画面の表示変更
在庫一覧(`/materials`)では、引当中の数量も表示する。
表示例:
```
仁井田米有機: 在庫 18袋うち引当 12袋/ 利用可能 6袋
```
StockSummary API のレスポンスに以下を追加:
```json
{
"material_id": 3,
"name": "仁井田米有機",
"current_stock": "18.000",
"reserved_stock": "12.000",
"available_stock": "6.000",
"last_transaction_date": "2026-03-14"
}
```
### 23.7 施肥計画の状態管理
施肥計画に散布確定状態を持たせる。
FertilizationPlan に以下のフィールドを追加:
```python
is_confirmed = models.BooleanField(default=False, verbose_name='散布確定済み')
confirmed_at = models.DateTimeField(null=True, blank=True, verbose_name='散布確定日時')
```
状態遷移:
- `is_confirmed=False`: 計画中(編集可能、引当あり)
- `is_confirmed=True`: 散布確定済み(引当 → 使用に変換済み)
確定済みの計画は:
- 編集不可(またはバナーで注意喚起して編集許可)
- 再確定はしない
- 削除は可能use トランザクションはそのまま残す)
### 23.8 API 変更・追加
#### 既存 API への影響
| API | 変更内容 |
|-----|----------|
| `POST/PUT /api/fertilizer/plans/` | 保存時に reserve 自動作成(全削除→再作成) |
| `DELETE /api/fertilizer/plans/{id}/` | 削除時に reserve 自動削除 |
#### 新規 API
| メソッド | パス | 説明 |
|----------|------|------|
| `POST` | `/api/fertilizer/plans/{id}/confirm_spreading/` | 散布確定reserve→use変換 |
| `GET` | `/api/materials/fertilizer-stock/` | 肥料在庫一覧(施肥計画画面用、利用可能在庫含む) |
散布確定 API のリクエスト例:
```json
{
"entries": [
{"field_id": 1, "fertilizer_id": 3, "actual_bags": 3.0},
{"field_id": 2, "fertilizer_id": 3, "actual_bags": 3.5},
{"field_id": 3, "fertilizer_id": 3, "actual_bags": 0}
]
}
```
`actual_bags=0` の行は引当解除として処理する。
### 23.9 マイグレーション計画
#### materials 0002: reserve タイプ追加 + fertilization_plan FK
```python
# StockTransaction に以下を追加:
# - transaction_type の choices に 'reserve' を追加choices 変更はマイグレーション不要)
# - fertilization_plan FK を追加
migrations.AddField(
model_name='stocktransaction',
name='fertilization_plan',
field=models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name='stock_reservations',
to='fertilizer.fertilizationplan',
verbose_name='施肥計画',
),
)
```
#### fertilizer 0006: is_confirmed, confirmed_at 追加
```python
migrations.AddField(
model_name='fertilizationplan',
name='is_confirmed',
field=models.BooleanField(default=False, verbose_name='散布確定済み'),
),
migrations.AddField(
model_name='fertilizationplan',
name='confirmed_at',
field=models.DateTimeField(blank=True, null=True, verbose_name='散布確定日時'),
),
```
### 23.10 フロントエンド変更
#### 施肥計画一覧 (`/fertilizer`)
- 各計画に確定状態アイコンを追加(未確定 / 確定済み)
- 確定済みの計画は背景色で視覚的に区別
#### 施肥計画編集 (`/fertilizer/[id]/edit`)
- 肥料列ヘッダーに在庫情報を表示
- 確定済みの場合は編集不可バナーを表示
#### 散布確定画面(新規)
- 施肥計画一覧から「散布確定」ボタンで遷移 or モーダル
- 圃場×肥料のマトリクスに「計画」と「実績」列を並べて表示
- 計画値がプリセットされ、修正が必要な行だけ編集する
- 「一括確定」ボタンで POST
#### 在庫一覧 (`/materials`)
- `reserved_stock``available_stock` を表示に追加
### 23.11 実装順序
1. StockTransaction に `reserve` タイプ追加 + `fertilization_plan` FKマイグレーション
2. FertilizationPlan に `is_confirmed` / `confirmed_at` 追加(マイグレーション)
3. StockSummary API に `reserved_stock` / `available_stock` 追加
4. 施肥計画の保存処理に reserve 自動作成ロジック追加
5. 施肥計画の削除処理に reserve 自動削除ロジック追加
6. 散布確定 API`confirm_spreading`)実装
7. 肥料在庫 API`fertilizer-stock`)実装
8. フロントエンド: 在庫一覧に引当表示追加
9. フロントエンド: 施肥計画編集に在庫参照追加
10. フロントエンド: 散布確定画面実装
11. フロントエンド: 施肥計画一覧に確定状態表示追加
### 23.12 この設計のメリット
- 計画作成時に利用可能在庫を見ながら計画を立てられる
- 普段は一括確定するだけなので操作は軽い
- アクシデント時は個別に実績数量を修正できる
- 計画の削除・変更で引当が自動解除されるため、在庫が宙に浮かない
- 在庫一覧で「引当中」が見えるため、在庫状況が透明