在庫管理 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:
321
改善案/在庫管理機能実装案.md
321
改善案/在庫管理機能実装案.md
@@ -1578,6 +1578,321 @@ alias 例:
|
||||
|
||||
### 22.3 実装フェーズの整理
|
||||
|
||||
- セクション1〜16: Phase 1(初期実装)
|
||||
- セクション17〜21: Phase 2(公式データ同期、alias辞書、LLM調査支援)
|
||||
- CODEX への初回作業指示は Phase 1 のみを対象とする
|
||||
- セクション1〜16: Phase 1(初期実装)→ 実装済み
|
||||
- セクション17〜21: Phase 3(公式データ同期、alias辞書、LLM調査支援)
|
||||
- セクション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 この設計のメリット
|
||||
|
||||
- 計画作成時に利用可能在庫を見ながら計画を立てられる
|
||||
- 普段は一括確定するだけなので操作は軽い
|
||||
- アクシデント時は個別に実績数量を修正できる
|
||||
- 計画の削除・変更で引当が自動解除されるため、在庫が宙に浮かない
|
||||
- 在庫一覧で「引当中」が見えるため、在庫状況が透明
|
||||
|
||||
Reference in New Issue
Block a user