延長保育料金・請求転送仕様
- 文書バージョン: 1.0(実装反映)
- 現況再確認: 2026-08-11
- ステータス: 実装済み
ExtendedCareBillingSetting、ExtendedCareBillingTransferLog、転送元紐付け列、extended_care_billing_transfer_service.py、/extended-care-fees/billing-transferを実装済みである。転送・再転送・解除、手入力競合、全銀作成後のロック、監査を自動テストで確認している。
1. 目的
確定した延長保育料金を、同じ対象月の請求明細へ安全に転送できるようにする。
既存の延長保育料金機能は、降園打刻からの日別料金計算、職員による確認・調整、月次集計、CSV出力までを扱っている。既存の請求機能は、園児別明細、家族単位の請求合計、口座振替用の全銀データ作成を扱っている。本仕様では両者を接続し、延長保育料金を二重入力せず請求へ反映する。
2. 背景
現在は、延長保育料金画面で確定額を確認した後、請求入力画面の「延長保育料」へ職員が手入力する必要がある。
この運用には次の問題がある。
- 転記漏れが発生する。
- 園児や金額を取り違える可能性がある。
- 同じ料金を複数回転記する可能性がある。
- 延長料金を修正したとき、請求側との不一致を発見しにくい。
- どの延長料金を誰が請求へ反映したか追跡できない。
仕様作成前はBillingChargeSourceType.extension_autoだけが定義され、転送処理、転送設定、転送元との紐付けは未実装だった。現在は上記のとおり実装済みである。
3. 既存仕様との関係
本仕様は次の既存仕様を拡張する。
docs/extended-care-fee-spec.mddocs/facility-settings-spec.mddocs/staff-permissions-and-billing-accounts-spec.md
延長料金の計算は既存の ExtendedCareFeeRule と ExtendedCareCharge を正とする。
models.py に存在する未使用の ExtensionFeeRule は本機能では使用しない。料金計算モデルの統合または削除は別タスクとする。
4. 基本方針
- 初期実装では月単位の手動一括転送とする。
- 自動転送やスケジュール実行は行わない。
- 転送前に対象件数、金額、未確認件数、競合をプレビューする。
confirmedとmanual_adjustedの延長料金だけを転送する。- 正の金額を持つ
draftが残っている場合、月全体の転送を禁止する。 excludedと0円の料金は転送しない。- 利用月と同じ
BillingCycle.year_monthへ転送する。 - 転送先の請求月は自動作成しない。
- 園児ごとに月額を集計し、請求明細を1行作成する。
- 転送済み明細は請求画面から直接編集できないようにする。
- 同じ園児・同じ請求月の再転送で二重明細を作らない。
- 全銀データ作成後の請求月は転送、再転送、転送解除を禁止する。
- 転送と監査ログは同一トランザクションで保存する。
- 本転送で扱う月額は日別確定額の月次集計額であり、月極固定料金の契約・自動算定は扱わない。
5. 用語
| 用語 | 意味 |
|---|---|
| 対象月 | 延長保育を利用した月。YYYY-MM |
| 転送先請求月 | BillingCycle.year_month が対象月と一致する請求月 |
| 転送対象 | 請求へ反映できる日別延長料金 |
| 転送明細 | BillingChargeSourceType.extension_auto の請求明細 |
| 手入力競合 | 同じ園児、請求月、費目に手入力明細が存在する状態 |
| 再転送 | 転送後の金額を再集計し、既存の転送明細を更新する操作 |
| 転送解除 | 転送明細を削除し、日別延長料金との紐付けを解除する操作 |
| 月次集計額 | 対象月の日別延長料金を園児ごとに合計した転送額。月極固定料金とは異なる |
6. 対象範囲
6.1 初期実装に含めるもの
- 請求連携設定
- 月次転送プレビュー
- 月次一括転送
- 差分がある場合の再転送
- 全銀データ作成前の転送解除
- 転送元と請求明細の紐付け
- 重複防止
- 手入力明細との競合検出
- 転送履歴
- 権限チェック
- 自動テスト
6.2 初期実装に含めないもの
- 日別明細を1日1行で請求へ転送する方式
- 自動・定時転送
- 請求月の自動作成
- 前月利用分を翌月請求へ送る等の月ずらし設定
- クラス、年齢、認定区分別の転送先変更
- 補食費、夕食費、給食費の同時転送
- 兄弟割引、月額上限の新規実装
- 月極固定料金の契約管理、自動算定、日割り、スポット料金との相殺
- 全銀データ作成後の請求月を直接修正する機能
- 会計ソフトへの外部連携
ExtensionFeeRuleの整理
7. 処理フロー
flowchart LR
A["降園打刻"] --> B["日別延長料金を自動計算"]
B --> C["職員が確認・調整"]
C --> D["月次転送プレビュー"]
D --> E["請求明細へ一括転送"]
E --> F["請求内容を確認"]
F --> G["全銀データを作成"]
7.1 通常フロー
- 降園打刻から日別延長料金を計算する。
- 職員が発生額を確認し、必要に応じて調整または対象外にする。
- 対象月の延長保育料金画面で「請求転送を確認」を押す。
- システムは転送先請求月と転送可否を確認する。
- 園児別の転送額、未確認件数、競合を表示する。
- 職員が「請求へ転送」を押す。
- システムは転送条件を再検証する。
- 園児ごとの転送明細を作成または更新する。
- 家族単位の請求合計を再計算する。
- 転送履歴を記録してコミットする。
8. 請求連携設定
8.1 設定項目
延長保育料金ルール設定画面 /extended-care-fees/settings に「請求連携」セクションを追加する。
| 項目 | 型 | 初期値 | 内容 |
|---|---|---|---|
| 請求連携を利用する | boolean | false |
無効の場合は転送操作を表示しない |
| 請求費目 | string | monthly_childcare |
転送明細で使用する FeeItem.code |
| 明細名テンプレート | string | 延長保育料({year}年{month}月分) |
請求明細の説明 |
| 転送方式 | enum | manual_monthly |
初期実装では変更不可 |
| 対象月ルール | enum | same_month |
初期実装では変更不可 |
請求連携設定は施設全体に適用する。日付ごとの料金計算ルールである ExtendedCareFeeRule には追加しない。
8.2 設定権限
請求連携設定を表示・変更できるのは管理者だけとする。
設定変更だけでは、過去の延長料金、転送済み明細、確定済み請求を変更しない。
8.3 設定モデル
新規シングルトンテーブルを追加する。
extended_care_billing_settings
| カラム | 型 | 内容 |
|---|---|---|
id |
integer | 主キー。初期実装では1行 |
is_enabled |
boolean | 請求連携の有効状態 |
fee_item_code |
string | 転送先費目コード |
description_template |
string | 明細名テンプレート |
transfer_mode |
string | manual_monthly |
target_month_rule |
string | same_month |
updated_at |
datetime | 更新日時 |
updated_by_user_id |
UUID, nullable | 更新者 |
updated_by_name |
string, nullable | 更新者名スナップショット |
設定行が存在しない場合は、請求連携無効として扱う。
9. 転送対象の判定
9.1 対象となる日別料金
次をすべて満たす ExtendedCareCharge を対象とする。
target_dateが対象月の初日以上、末日以下statusがconfirmedまたはmanual_adjustedfinal_amount > 0- 園児が存在する
- 園児に
family_idが設定されている
9.2 対象外
draftexcludedfinal_amount == 0- 園児または家族情報が解決できない料金
- 別の請求月へ転送済みの料金
正の金額を持つ draft が1件でもある場合は、対象月全体の転送を禁止する。0円の draft は警告に表示するが転送を妨げない。
9.3 月次集計
対象料金を園児IDごとに集計する。
園児別転送額 = 対象となる日別料金の final_amount 合計
家族単位ではなく園児単位で明細を作る。兄弟が同じ家族に所属する場合、同じ BillingClaim に複数の園児別明細を作成する。
10. 転送先請求月
転送先は次を満たす BillingCycle とする。
year_monthが対象月と一致するperiod_startとperiod_endが対象月を含む- 状態が
draft、generated、confirmedのいずれか
転送先請求月が存在しない場合は転送しない。「先に対象月の請求月を作成してください」と表示し、請求入力へのリンクを表示する。
exported、result_imported、closed の請求月には転送できない。
11. 請求明細の作成
11.1 費目
既定では FeeItem.code = monthly_childcare を使用する。
費目が存在しない場合、次の内容で作成する。
| 項目 | 値 |
|---|---|
code |
monthly_childcare |
name |
延長保育料 |
category |
monthly |
charge_unit |
child |
taxable_type |
non_taxable |
11.2 転送明細
園児ごとに次の BillingChargeLine を作成または更新する。
| 項目 | 値 |
|---|---|
billing_claim_id |
対象家族の請求ID |
fee_item_id |
請求連携設定の費目ID |
child_id |
対象園児ID |
source_type |
extension_auto |
source_date |
対象月初日 |
source_reference |
extended-care:{billing_cycle_id}:{child_id} |
description |
明細名テンプレートを展開した文字列 |
quantity |
1 |
unit_label |
月 |
unit_price |
園児別転送額 |
amount |
園児別転送額 |
is_locked |
true |
source_reference は一意とする。同じ請求月・園児の転送を再実行しても、同じ明細を更新し、新規明細を追加しない。
11.3 請求の作成と再計算
対象家族に BillingClaim がない場合は、既存の請求作成処理を使用して作成する。
転送後は対象となった全 BillingClaim.total_amount を再計算する。請求月が confirmed の場合、請求明細の追加後も請求状態を confirmed とする。
12. 転送元との紐付け
12.1 BillingChargeLineの追加項目
BillingChargeLine に次を追加する。
| カラム | 型 | 内容 |
|---|---|---|
source_reference |
string, nullable, unique | 転送元を一意に識別するキー |
SQLiteではNULLを複数保持できるため、既存の手入力明細には影響しない。
12.2 ExtendedCareChargeの追加項目
ExtendedCareCharge に次を追加する。
| カラム | 型 | 内容 |
|---|---|---|
billing_charge_line_id |
integer, nullable | 転送先請求明細ID |
transferred_amount |
integer, nullable | 転送時点の金額スナップショット |
transferred_at |
datetime, nullable | 最終転送日時 |
transferred_by_user_id |
UUID, nullable | 転送実行者 |
transferred_by_name |
string, nullable | 実行者名スナップショット |
同じ園児の同じ月の日別料金は、同じ billing_charge_line_id を参照する。
13. プレビュー
転送前に次を表示する。
- 対象月
- 転送先請求月と状態
- 対象園児数
- 対象日別料金数
- 転送合計額
- 未確認件数
- 対象外件数
- 0円件数
- 転送済み件数
- 再転送で金額が変わる園児
- 手入力競合
- 家族未設定等のエラー
園児別に次を表示する。
| 項目 | 内容 |
|---|---|
| 園児 | 氏名、クラス |
| 延長回数 | 正の転送対象料金の日数 |
| 延長分数 | 対象料金の延長分数合計 |
| 転送予定額 | final_amount 合計 |
| 現在の請求額 | 既存転送明細の金額 |
| 差額 | 転送予定額-現在の請求額 |
| 状態 | 新規、変更なし、更新、競合、転送不可 |
転送不可理由が1件でもある場合、月全体の転送ボタンを無効にする。初期実装では部分転送を行わない。
14. 手入力明細との競合
同じ請求月、園児、費目に source_type != extension_auto の明細が存在する場合、手入力競合とする。
競合時は次の動作とする。
- 手入力明細を自動削除・上書きしない。
- 転送処理全体を中止する。
- 対象園児と既存金額を表示する。
- 職員に、手入力額を0円にして削除するか、請求連携を使用しないか選択してもらう。
転送明細が存在する場合、請求一覧の延長保育料セルは読み取り専用で表示し、「延長保育料金から転送済み」と表示する。
15. 再転送
請求月が編集可能で、既存の転送明細がある場合は再転送できる。
再転送は、初回転送後に遅れて登録・確認された日別料金を追加反映するために使用する。
再転送では次を行う。
- 現在の転送対象料金と、既に紐付いている料金を再集計する。
source_referenceで既存転送明細を取得する。- 新たに確認された未転送料金を既存明細へ加算し、スナップショットを保存する。
- 新たに対象となった園児の明細を作成する。
- 請求合計を再計算する。
- 再転送履歴を記録する。
転送済み料金の final_amount や状態が転送時のスナップショットから変化している場合は、再転送で自動補正しない。転送を解除してから料金を修正し、改めて転送するよう案内する。
差分がない場合はDBを変更せず、「転送内容に変更はありません」と表示する。
16. 転送後の料金修正
転送済みの日別料金を直接調整、対象外、再計算しようとした場合は、次のルールを適用する。
16.1 全銀データ作成前
- 対象月の転送を解除してから修正する。
- 転送中の料金変更操作は拒否し、「先に請求転送を解除してください」と表示する。
- 修正後、再度プレビューして転送する。
16.2 全銀データ作成後
- 元の請求月の転送解除と再転送を禁止する。
- 日別延長料金の金額は履歴保全のため変更しない。
- 修正が必要な場合は、翌月以降の請求へ手動調整明細を作成する。
全銀データ作成後の自動差額繰越は初期実装の対象外とする。
17. 転送解除
転送解除は対象月単位で行う。園児単位の部分解除は初期実装では行わない。
解除条件:
- 請求月が
draft、generated、confirmedのいずれか - 対象請求が
exportedまたはpaidではない - 対象の転送明細が存在する
解除処理:
source_type = extension_autoかつ対象月の転送明細だけを削除する。- 対象
ExtendedCareChargeの転送紐付けを解除する。 - 家族請求合計を再計算する。
- 転送解除履歴を記録する。
- 同一トランザクションでコミットする。
手入力明細や他の自動明細は削除しない。
18. 監査ログ
新規テーブル extended_care_billing_transfer_logs を追加する。
| カラム | 型 | 内容 |
|---|---|---|
id |
integer | 主キー |
action |
string | transfer、retransfer、revert |
target_month |
string | 対象月 |
billing_cycle_id |
integer | 対象請求月 |
affected_child_count |
integer | 対象園児数 |
affected_charge_count |
integer | 対象日別料金数 |
total_amount |
integer | 操作後または解除対象の合計額 |
changed_child_ids |
JSON | 金額が変わった園児ID一覧 |
executed_by_user_id |
UUID, nullable | 実行者 |
executed_by_name |
string | 実行者名スナップショット |
executed_at |
datetime | 実行日時。UTC保存 |
監査ログには保護者名、口座番号等の機微情報を保存しない。ログは画面から編集・削除できない。
19. 権限
| 操作 | 閲覧のみ | 編集可 | 管理者 |
|---|---|---|---|
| 月次転送状況の閲覧 | 可 | 可 | 可 |
| 転送プレビュー | 不可 | 可 | 可 |
| 転送・再転送 | 不可 | 可 | 可 |
| 転送解除 | 不可 | 可 | 可 |
| 請求連携設定の変更 | 不可 | 不可 | 可 |
| 転送履歴の閲覧 | 不可 | 可 | 可 |
初期実装では既存の請求金額編集権限に合わせて can_edit を使用する。将来、請求確定・全銀出力等を業務別権限へ分離する場合は、転送権限も同じ権限体系へ移行する。
口座情報管理権限 can_manage_billing_accounts は、口座詳細の閲覧・編集権限であり、本転送操作の必要条件にはしない。
20. 画面仕様
20.1 延長保育料金一覧
対象: /extended-care-fees/
請求連携が有効な場合、月次集計の上部に「請求連携」カードを表示する。
表示内容:
- 対象請求月
- 転送状態: 未転送、転送済み、差分あり、転送不可
- 転送対象額
- 現在の請求転送額
- 未確認件数
- 「請求転送を確認」ボタン
- 転送済みの場合は「転送解除」ボタン
20.2 転送確認画面
対象: /extended-care-fees/billing-transfer?month=YYYY-MM
プレビュー内容とエラーを表示する。転送可能な場合のみ「請求へ転送」を表示する。
転送操作の直前に「対象月、園児数、合計額」を確認できるようにする。
20.3 請求入力画面
転送された延長保育料は次のように表示する。
- 金額欄は読み取り専用
- 「延長保育料金から転送済み」バッジ
- 対象月
- 最終転送日時
- 延長保育料金画面へのリンク
21. API・ルーティング
| メソッド | パス | 用途 | 必要権限 |
|---|---|---|---|
| GET | /extended-care-fees/billing-transfer?month=YYYY-MM |
転送プレビュー | 編集可以上 |
| POST | /extended-care-fees/billing-transfer |
転送・再転送 | 編集可以上 |
| POST | /extended-care-fees/billing-transfer/revert |
転送解除 | 編集可以上 |
| POST | /extended-care-fees/settings/billing |
請求連携設定保存 | 管理者 |
POSTではCSRF対策を適用する。
22. トランザクションと排他
- プレビューはDBを変更しない。
- POST時にプレビューと同じ条件を再検証する。
- 転送明細、転送元紐付け、請求合計、監査ログを同一トランザクションで保存する。
- 1園児でも失敗した場合は月全体をロールバックする。
source_referenceの一意制約で同時実行時の二重明細を防ぐ。- 一意制約違反時はロールバックし、「他の職員が先に転送しました。画面を更新してください」と表示する。
23. エラー表示
| 状況 | 表示・応答 |
|---|---|
| 請求連携が無効 | 「請求連携が無効です」 |
| 転送先請求月がない | 「先に対象月の請求月を作成してください」 |
| 未確認料金がある | 件数と対象園児を表示し転送不可 |
| 家族未設定 | 対象園児を表示し転送不可 |
| 手入力競合 | 対象園児と既存金額を表示し転送不可 |
| 全銀データ作成済み | 「全銀データ作成後の請求月は変更できません」 |
| 権限なし | 403 Forbidden |
| 同時実行競合 | ロールバックして再読込を案内 |
| DB保存失敗 | 全件ロールバックし一般化したエラーを表示 |
24. 移行方針
- 請求連携設定は無効で追加する。
- 既存の延長料金を自動転送しない。
- 既存の手入力延長保育料を自動変換しない。
- 管理者が設定を有効化した後の手動操作から転送を開始する。
- 初回転送時、対象月の手入力競合を必ずプレビューする。
BillingChargeLine.source_referenceは既存行ではNULLとする。ExtendedCareChargeの転送関連項目は既存行ではNULLとする。
25. 自動テスト
25.1 対象判定
confirmedとmanual_adjustedの正の料金だけが対象になる。excluded、0円は対象外になる。- 正の
draftがあると月全体が転送不可になる。 - 家族未設定の園児がいると転送不可になる。
25.2 転送
- 園児ごとに1行の転送明細が作成される。
- 兄弟の明細が同じ家族請求へ合算される。
source_typeがextension_autoになる。source_referenceが一意になる。- 転送明細がロックされる。
- 請求合計が再計算される。
- 転送元料金に明細IDと金額スナップショットが保存される。
25.3 重複・再転送
- 同じ月を2回転送しても明細数が増えない。
- 差分がない再転送ではDBを変更しない。
- 新たな確認済み料金が追加された後の再転送で既存明細が更新される。
- 転送済み料金の金額や状態がスナップショットと異なる場合は再転送が拒否される。
- 手入力競合がある場合は全件ロールバックされる。
- 同時実行で二重明細が作られない。
25.4 転送解除・ロック
- 全銀データ作成前は月全体を解除できる。
- 解除しても手入力明細は削除されない。
- 転送済み料金の調整は解除前に拒否される。
- 全銀データ作成後は解除、再転送、料金変更が拒否される。
25.5 権限と監査
- 閲覧のみ職員は転送、解除、設定変更ができない。
- 編集可職員は転送と解除ができるが設定変更はできない。
- 管理者は設定変更できる。
- 転送、再転送、解除で監査ログが残る。
- 保存失敗時は請求明細と監査ログの両方がロールバックされる。
26. 受け入れ条件
- 管理者が請求連携を有効化できる。
- 確認済み・調整済みの延長料金だけが転送される。
- 未確認料金が残る月は転送できない。
- 転送先請求月がない場合に安全に案内される。
- 園児ごとの日別延長料金の月次集計額が請求明細へ反映される。
- 兄弟分が家族請求へ正しく合算される。
- 同じ月を複数回操作しても二重請求にならない。
- 転送明細を請求画面から直接変更できない。
- 全銀データ作成前は転送解除して修正できる。
- 全銀データ作成後は元請求を変更できない。
- 手入力明細を勝手に削除・上書きしない。
- 転送、再転送、解除の履歴が残る。
- 権限のない職員からの操作を拒否する。
- 一部失敗時に部分転送が残らない。
- 既存の延長料金計算、請求入力、全銀データ作成テストが成功する。
27. 実装順序
- 請求連携設定モデルと設定UIを追加する。
BillingChargeLine.source_referenceと転送監査ログを追加する。ExtendedCareChargeに転送紐付け項目を追加する。- 転送対象集計・競合検出サービスを実装する。
- 転送プレビュー画面を追加する。
- 転送・再転送処理を実装する。
- 請求画面で転送明細をロック表示する。
- 転送解除処理を実装する。
- 転送済み料金の変更制御を追加する。
- 権限・監査・同時実行テストを追加する。
- 既存の延長料金・請求・全銀テストを再実行する。