Task: Currency add dialog: Save button stays disabled
Table of Contents
This page documents a task in the Sprint 24 quick bug fixes: currency CRUD, party re-provisioning story. It captures the goal, current status, acceptance, and any notes or results.
Goal
In the Qt client, Reference Data > Currencies > Add opens
CurrencyDetailDialog in create mode. Filling in all fields (ISO
code, name, numeric code, symbol, fractions per unit, change reason,
commentary) does not enable the Save button — it stays disabled and
the currency cannot be created. Found while manually testing the
generic HistoryDialog widget; unrelated to that change. Repro
against main to confirm scope and find the root cause in
CurrencyDetailDialog's create-mode dirty/validation tracking.
Status
| Field | Value |
|---|---|
| State | DONE |
| Parent story | Sprint 24 quick bug fixes: currency CRUD, party re-provisioning |
| Now | Nothing. |
| Waiting on | Nothing. |
| Next | Nothing. |
| Last touched | 2026-07-21 |
Acceptance
- Root cause identified in CurrencyDetailDialog's create-mode dirty/validation tracking.
- Filling in all required fields enables Save; a new currency can be created from the Qt client.
Plan
Root cause: CurrencyDetailDialog::setupConnections() wired every
editable widget to the dirty-flag handler (onFieldChanged=/
=onCodeChanged) except the two QSpinBox fields —
fractionsPerUnitSpinBox and roundingPrecisionSpinBox — which had
no valueChanged connection at all, so editing only those never set
hasChanges_ and Save stayed disabled. Traced to a template gap:
cpp_qt_detail_dialog.cpp.mustache's connection loop had branches
for every other field kind (is_line_edit, is_static_combo,
is_dynamic_combo, is_flagged_combo, is_check_box, is_text_edit)
but none for is_spin_box — so every generated detail dialog with a
spin-box field has the same gap, not just currency.
Fixed the template and regenerated the 23 refdata entities with a
spin-box field (out of ~57 total across the app; refdata is the only
commissioned component today, so scope stopped there). Regenerating
also surfaced a second, unrelated template bug in
cpp_qt_client_model.cpp.mustache: its is_int column-rendering
case did an unchecked static_cast<qlonglong>, with no
is_optional_int branch mirroring the existing is_optional_string
one — silently dropping the null case for std::optional<int>
columns (surfaced via payment_frequency's period_multiplier).
Fixed by adding the missing classification in core.py and the
corresponding template branch.
Notes
Manual QA testing of this task's scenario also surfaced a second, genuinely unrelated bug — the currencies list pagination counter/data desync — tracked and fixed separately as Currencies list window paging does not seem to work.
Test Scenarios
Manual QA scenarios (scaffolded via compass add test_scenario, run
through the QA Validation Runner panel) that verify this task. Link
new ones here as they're created; the scenario doc itself links back
via its "Verifies task" field.
| Scenario | State | Notes |
|---|---|---|
| Verify Currency Save button enables from spin-box fields | PASSED |
PRs
| PR | Title |
|---|---|
| #1670 | [qt/codegen] Fix currency Save-button and pagination state machines |
Review
| Comment summary | File | Decision | Notes |
|---|---|---|---|
Result
Fixed at the codegen level rather than hand-patched: added an
is_spin_box branch to cpp_qt_detail_dialog.cpp.mustache's
setupConnections() loop, wiring QSpinBox::valueChanged to
onFieldChanged, and regenerated all 23 refdata entities with a
spin-box detail field. Also fixed the is_optional_int gap in
cpp_qt_client_model.cpp.mustache=/=core.py uncovered along the way.
Full test suite green (382 assertions, 119 cases), SQL schemas
validated, and
Verify Currency Save button enables from spin-box fields PASSED
manually — filling in only the fractions-per-unit or
rounding-precision spin box now enables Save, and the create/read/
update/delete/history/eventing round-trip all check out.