Repository navigation
feat: Web UI で前処理フック・入力の読み込み・結果 Excel・入力項目を差し替えられるようにする - #26
Merged
Merged
Conversation
環境変数 CHILMAI_WEB_CUSTOMIZATION に module:ClassName 形式で WebCustomization のサブクラスを指定すると、apps/ を改変せずに 次の 4 か所を差し替えられる。 - 前処理フック: create_preprocessor() で BasePreprocessor を返す - 入力ファイルの読み込み: create_parser() で InputParser のサブクラスを返す - 結果 Excel: build_result_workbook() / result_filename() - 画面の入力項目: fields に ParamField を定義し、値を params で受け取る コア側は MatchingService に parser 引数を追加し、InputParser に SHEET_NAME・HEADER_ROW と read_table() フックを設けた。 サーバ API の /validate・/match は params(JSON 文字列)を受け付ける。 Closes #24 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- 空欄で送られた入力値を既定値で上書きしない(任意の select で「—」を選べるように) - 数値の判定を半角の整数・小数に限定する(nan・inf・全角数字を弾く) - type・checkbox の default・number の default の誤りを起動時に検出する - カスタマイズのメソッドの想定外の例外を E109 として返し、500 エラーにしない - 結果 Excel の数式の扱いについて、docstring・ドキュメントを実際の処理に合わせる - transform_output の時点で結果列が末尾に ID・名の順で並ぶことを明記する Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
CHILMAI_WEB_CUSTOMIZATION を設定して apps/packager.py でビルドすると、 指定したモジュールを hidden import として exe に組み込み、指定を apps/api/bundled_customization.txt として同梱する。起動時に環境変数が ない場合はこのファイルを読むため、自治体は exe を起動するだけで使える。 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
build_customization_pyi_args() が呼ばれるたびに sys.path を書き換えて いたため、テストで ROOT を差し替えると一時ディレクトリが残っていた。 python apps/packager.py で実行したときだけ必要なので __main__ に移す。 あわせて、カスタマイズ用のライブラリを uv add で依存に加えれば ライセンスの一覧と検査の対象になることをドキュメントに追記する。 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Contributor
Coverage reportClick to see where and how coverage changed
This report was generated by python-coverage-comment-action |
||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment.
🟡 Changes recommended
Stale in-flight responses can re-enable matching and expose results for outdated parameters, while unguarded customization calls bypass the intended E109 error handling.
3 open issues
What changed in this PR
Adds extension points to the reference Web UI and server API so municipalities can customize input handling, preprocessing, result workbooks, and form fields without modifying apps/, addressing #24.
Changes:
- Introduces
WebCustomization, parameter validation, configurable parsers, and customization error handling. - Connects custom fields and Excel output to the UI and bundles selected customizations into packaged executables.
- Adds a sample customization, documentation, and API, packaging, and browser tests.
| File | Description |
|---|---|
test/chilmai/browser/test_customization_ui.py |
Tests custom fields, validation reset, and download filenames. |
test/apps/test_packager.py |
Tests customization bundling and invalid specifications. |
test/apps/test_customization.py |
Covers loading, parameters, parsers, output, and errors. |
test/apps/test_api_contract.py |
Updates mocks for request-scoped services. |
examples/sample_web_customization.py |
Demonstrates all four customization points. |
docs/reference/web-ui/troubleshooting.md |
Documents E108 and E109 troubleshooting. |
docs/development/customization.md |
Explains extension points and packaging. |
docs/api/reference-app.md |
Documents API parameters and customization. |
chilmai/generic/service.py |
Accepts injected parsers and passes file kind. |
chilmai/generic/preprocessor.py |
Clarifies output-column order in the docstring. |
chilmai/generic/parser.py |
Adds configurable sheets, headers, and read hooks. |
chilmai/generic/error_codes.py |
Adds parameter and customization error codes. |
apps/packager.py |
Bundles customization modules and specifications. |
apps/api/templates/match_result.html |
Uses customized download filenames. |
apps/api/templates/index.html |
Renders custom fields and resets workflow state. |
apps/api/static/style.css |
Styles custom checkbox fields. |
apps/api/static/htmx-lite.js |
Disables matching after parameter changes. |
apps/api/main.py |
Integrates custom services, parameters, and workbooks. |
apps/api/customization.py |
Defines extension contracts, loading, and validation. |
Review effort: Balanced
Comment on lines
+236
to
+239
| form.querySelectorAll('[name^="param__"]').forEach(function (input) { | ||
| input.addEventListener('change', function () { | ||
| setMatchEnabled(form, false); | ||
| }); |
Comment on lines
+98
to
+99
| preprocessor=_call_customization(customization.create_preprocessor, params), | ||
| parser=_call_customization(customization.create_parser), |
| try: | ||
| columns = InputParser.read_columns( | ||
| upload.file, _infer_file_format_from_filename(upload.filename) | ||
| columns = customization.create_parser().read_columns( |
- データ確認の送信時の入力の世代を記録し、応答待ちの間にファイルや追加の入力項目が 変わっていれば、応答が届いてもマッチングボタンを有効にしない - カスタマイズが返した前処理フック・パーサーの公開メソッドの呼び出しにも例外の変換を 適用し、transform_children() や read_table() の実行中の例外を 500 ではなく E109 として返す (ChilmError はそのまま返す。標準の InputParser・BasePreprocessor は対象外) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- データ確認・マッチングの応答待ちの間に入力が変わったら、変更前の入力の結果を表示せず、 完了イベントの発火やボタンの再有効化もしない(入力変更による画面のリセットを戻さない) - 項目名の設定画面の列名の自動検出でも、create_parser() とパーサーのメソッドの例外を E109 として表示する Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
表示先ごとに最新のリクエスト ID を記録し、最新のリクエストだけが応答の表示と 後処理(入力変更の案内・ボタンの有効化・通信エラーの表示)を行うようにする。 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- パーサー・前処理フックのメソッドを書き換える _guard_customized をやめ、 エンドポイント側でカスタマイズ使用時だけ ValueError 以外の例外を E109 にする。 同じインスタンスを使い回してもラッパーが重ならず、標準の処理や利用者のファイルに 起因するエラーを E109 として表示しない - 結果 Excel の戻り値を検証し、数式の無害化と保存の失敗も E109 にする - Web UI で E108・E109 を「設定の問題」ではなく専用のセクションに表示する - 既定値のない必須の select に「選択してください」を表示する - checkbox に真偽値でない値が指定された場合は E108 にする - 入力の変更で破棄したマッチングの応答で、ステップの「処理中」を戻す - サンプルのパーサーで SHEET_NAME と標準の read_table を使う Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.


関連 Issue
Closes #24
変更概要
事業者が自治体向けにカスタマイズするときに、
apps/を改変(フォーク)せずに済むよう、リファレンスアプリ(Web UI・サーバ API)に差し替え口を設けました。WebCustomizationを継承したクラスをapps/の外に実装し、環境変数CHILMAI_WEB_CUSTOMIZATION=module:ClassNameで指定すると、次の 4 か所を差し替えられます。create_preprocessor(params)でBasePreprocessorを返すcreate_parser()でInputParserのサブクラスを返す(SHEET_NAME・HEADER_ROWの上書き、またはread_table()のオーバーライド)build_result_workbook()・result_filename()fieldsにParamFieldを定義し、値をparamsで受け取る主な変更点:
chilmai/)InputParserにSHEET_NAME・HEADER_ROWとread_table()フックを追加しました。kind引数で、申込者・保育所・組み合わせのファイルごとに読み方を変えられます。MatchingServiceにparser引数を追加しました。CUSTOMIZATION_FAILED)を追加しました。apps/)apps/api/customization.pyに、差し替え口・入力値の検証・標準の結果 Excel をまとめました。/validate・/matchでparams(JSON 文字列)を受け付けるようにしました。apps/packager.py)CHILMAI_WEB_CUSTOMIZATIONを設定してビルドすると、次のように動きます。apps/api/bundled_customization.txtとして同梱します。ChilmAI.exeを起動するだけで使えます。examples/sample_web_customization.pyを追加しました。年度・入所月の入力、備考列の追加、帳票タイトル行の読み飛ばし、施設別シートを実装しています。docs/development/customization.mdなどを更新しました。できなくなること:
できていないこと:
THIRD-PARTY-NOTICES.txtとライセンスの検査の対象は、ChilmAI の依存ライブラリだけです。カスタマイズ用のライブラリはuv addで依存に加えれば対象になり、環境に入れただけのライブラリについては、事業者がライセンス表示を用意します(ドキュメントに記載)。テスト結果
macOS で確認しました。
uv run python -m pytest test/ -m 'not (browser or binary)' -n auto:576 passed, 4 skippeduv run python -m pytest test/chilmai/browser -m browser -n0:19 passed-n0)で実行しています。今回の変更とは関係ありません。ruff check・ruff format --check・mkdocs build --strict:エラーなし選考結果_2027年度5月.xlsxになることresult・施設別・metaになることチェックリスト
uv run python -m pytest test/ -m 'not (browser or binary)' -n autoがパスするuv run python -m pytest test/chilmai/browser -m browser -n 1がパスする(-n0で実行。上記参照)その他
verify_runtime_dlls_are_accounted_forでビルドが止まらないかを確認したいです。🤖 Generated with Claude Code