# 依頼文

## 1. 目的
harukaze に新しいサブコマンド order-suggest を足し、`python -m harukaze order-suggest --date 2026-10-26` と打つと、指定日の時点で有効在庫が発注点を下回っている商品と、その発注数が CSV の一覧で出るようにします。一覧は仕入先ごとにまとまり、既存の発注書 CSV（po-export）と同じ列に「保留」列を1つ足した形で、そのまま発注書づくりに使えるようにします。

## 2. 背景
購買担当（総務・購買）は毎週月曜に、在庫が発注点を切っている商品を目で探して発注書を作っています。時間がかかるうえに見落としがあるため、ツールで候補を出したいという依頼です。コマンドの形は情シスと相談済みで、上の打ち方で決まっています。

## 3. 触ってよい範囲
- 新しいファイル: `harukaze/` 直下に .py を1つ（例: `harukaze/order_suggest.py`）、`tests/` 直下に `test_*.py` を1つ（例: `tests/test_order_suggest.py`）。
- 既存ファイルで変えてよいもの: `harukaze/cli.py`（サブコマンドの登録とそのハンドラ）と `README.md`（「コマンド一覧」の表に1行足すだけ）。
- これは README.md の「開発の決まり」節に書かれている決まりです。

## 4. やらないこと
- 上の範囲外のファイル（`harukaze/orders.py`、`harukaze/stock.py`、`harukaze/store.py`、`harukaze/csvout.py`、`data/` の CSV、既存のテスト、`tests/helpers.py`、`.gitignore`）は変えない・消さない。新しいフォルダは作らない。
- 出力ファイルや一時ファイルを作業フォルダに残さない（テストで要るデータは一時フォルダに作る。既存の `tests/helpers.py` の `make_data_dir` を使える）。
- コミットしない。
- 既存コマンドの動きや出力を変えない。
- 依頼にない機能（発注書ファイルの保存、発注済みデータへの書き込み、商品・仕入先での絞り込みオプション）は足さない。
- Python 標準ライブラリ以外を使わない。

## 5. 決まり（要件）
1. サブコマンド名は `order-suggest`。`--date YYYY-MM-DD` は必須で、省くとエラー終了（終了コードが0でない）。既存の `_date_arg` を使う。共通の `--data-dir` も既存の仕組みどおり使える。
2. 対象は商品マスタで状態が「販売中」の商品だけ。「終売予定」など「販売中」以外の商品は、在庫がいくら少なくても出さない。
3. 有効在庫 ＝ 基準日時点の現在庫 ＋ 発注済み未入荷の数 − 引当済みの数。現在庫は既存の `stock_as_of`（基準日当日の記録を含む）、発注済み未入荷は既存の `open_orders` が返す行のうちその商品の数量の合計（日付で絞らない）、引当済みは既存の `allocated_qty`、足し引きは既存の `available_stock` を使う。自前で数え直さない。
4. 有効在庫が発注点より小さい（厳密に下回る）商品だけが候補。等しいときは候補にしない。発注点が0の商品でも、有効在庫がマイナスなら候補になる。
5. 発注数 ＝ （発注点 × 2 − 有効在庫）を、既存の `round_up_to_case` で入数の倍数に切り上げた数。
6. 金額 ＝ 発注数 × 仕入単価（税抜）。
7. 出力の列は、既存の `PO_COLUMNS` の並び（仕入先コード, 仕入先名, 商品コード, 商品名, 入数, 発注数, 仕入単価（税抜）, 金額）の後ろに「保留」を1列足したもの。`PO_COLUMNS` そのものは書き換えず、新しいファイル側で列の並びを定義する。
8. 仕入先ごとに、その仕入先の候補行の金額を合計する。合計が仕入先マスタの最低発注金額に満たない場合も候補行はすべて出し、その仕入先の全行の「保留」列に「最低金額未満」と書く。合計が最低発注金額以上なら「保留」列は空にする。
9. 行の並びは、仕入先コードの昇順、同じ仕入先の中では商品コードの昇順（`build_po_rows` と同じ並べ方）。
10. 出力は既存の `write_csv` で標準出力に書く（UTF-8、改行 LF、見出し行あり）。候補が0件なら見出し行だけを出し、終了コードは0。
11. 計算の部分（一覧の行を作る関数）は CLI から切り離して新しいファイルに置き、DataStore と基準日を受け取って行のリストを返す形にする。cli.py のハンドラはそれを呼んで書き出すだけにする。
12. README.md の「コマンド一覧」の表に `order-suggest --date YYYY-MM-DD` の行を1行足す。
13. 新しいテストファイルに、少なくとも次を確かめるテストを書く: 厳密に下回るときだけ候補になる（等しいときは出ない）、発注済み未入荷と引当が有効在庫に効く、基準日より後の入出庫は数えない、終売予定は出ない、ケース切り上げ、最低発注金額未満の仕入先の全行に「最低金額未満」が入り満たす仕入先は空、並び順、0件で見出し行だけ、CLI から `--date` なしでエラー終了。

## 6. 注意点
- 有効在庫の基準日の扱い: `stock_as_of` は基準日当日の入出庫を含む。open_orders と allocations には日付で絞る処理をしない（既存関数が返すものをそのまま使う）。
- `stock_as_of` は入出庫の記録にあるが商品マスタにない商品コードも返すことがある。候補は商品マスタの「販売中」の商品から作る。
- 「保留」は仕入先単位の判定であり、行単位ではない。合計に使うのは切り上げ後の発注数で出した金額。
- 状態は文字列「販売中」と完全一致で判定する。
- cli.py の既存の `command` デコレータで登録すれば `--data-dir` は自動で付く。エラーは既存の `main` の扱い（エラー: … を標準エラーに出して終了コード1）に任せる。
- 既存テストの `tests/test_cli.py` は作業フォルダ直下をカレントにしてサブプロセスで CLI を動かしている。CLI のテストはこれに合わせる。テストは `tests/` を起点に `helpers` を import する形（既存テストと同じ）。
- 環境は Windows。標準出力の改行は LF のまま（`write_csv` が面倒を見るので、自前で print しない）。

## 7. 完了の条件と確かめ方
- `python -m unittest discover -s tests` を作業フォルダ直下で実行し、既存のテストと新しいテストがすべて通ること。
- `python -m harukaze order-suggest --date 2026-10-26` を実行し、同梱データで次の結果になること（仕入先コード, 商品コード, 発注数, 金額, 保留 の順で書きます）:
  - 201, 1001, 50, 19000, 空
  - 201, 1022, 50, 13000, 空
  - 201, 1023, 20, 10800, 空
  - 202, 1007, 40, 18000, 空
  - 202, 1009, 18, 17640, 空
  - 202, 1014, 10, 2400, 空
  - 203, 1004, 80, 7600, 最低金額未満
  - 203, 1012, 60, 7200, 最低金額未満
  - 204, 1015, 20, 17800, 最低金額未満
  - 204, 1018, 15, 19500, 最低金額未満
  - 見出しのほかはこの10行だけで、1011・1020（終売予定）、1019・1024（有効在庫が発注点と等しい）は出ないこと。
  - この結果は、新しいテストのうち1つで CLI の出力として確かめておくこと。
- `python -m harukaze order-suggest` （--date なし）が0以外の終了コードで終わること。
- 作業後、変更・追加されたファイルが「3. 触ってよい範囲」のものだけであること（`__pycache__` を除く）。
- 終わったら、変えたファイルの一覧と、テストの実行結果（通った件数）を報告してください。分からない点があれば、推測で進めずに質問として返してください。

分からない点があれば、変更せずに質問を列挙して終えてよい。
