Story: Reconcile currency Qt custom features with codegen

Table of Contents

This page documents a story in Sprint 22. It captures the goal, current status, acceptance criteria, and the tasks that compose it.

Goal

Bring currency's Qt layer (ores.qt/refdata: ClientCurrencyModel, CurrencyController, CurrencyMdiWindow, CurrencyDetailDialog, CurrencyHistoryDialog + .ui files) in line with the current qt codegen profile, without silently losing any of the real functionality it has grown beyond the template. Discovered while scoping "Sync Qt codegen for currency" (task, blocked on this story): currency's Qt files are roughly 2x the size of a comparable already-synced auxiliary entity (~3600 vs ~1900 lines across the 6 hand-written source files), and the excess is real product functionality, not legacy cruft:

  • CurrencyMdiWindow: CSV export, XML import/export, and a feature-flagged "generate synthetic test data" button (gated by the system.synthetic_data_generation setting) — none of which exist in any other entity's MDI window or in the template.
  • CurrencyController: extra NATS notification wiring (onNotificationReceived), and handler names that predate the template's current naming convention (onOpenCurrencyVersion vs. the template's onOpenVersion, etc.).
  • CurrencyDetailDialog (1351 lines vs. ~300 for a synced peer): full version-navigation UI (first/prev/next/last/revert), flag image selection wired through ImageCache, its own generate-button, stale-marking — plus 3 combo-box fields (monetary_nature, market_tier, rounding_type) backed by soft-FK reference tables. The template does have a combo-field mechanism, but no entity in the codebase exercises it yet — currency would be the first, with no working example to mirror.

This story is about deciding, feature by feature, what should become a first-class qt-profile capability (version-navigation UI and CSV/XML import-export look like strong candidates to benefit other entities too) versus what stays currency-specific custom code — before attempting a full regenerate. A blind mechanical sync (the approach that worked cleanly for the C++ core sync task) is not safe here: Qt UI behavior can't be verified without running the app, and the risk of silently dropping a working feature is high.

Status

Field Value
State DONE
Parent sprint Sprint 22
Now All 3 tasks done. Regenerate plan written (per-file table + 9-step sequence); recommends splitting "Sync Qt codegen for currency" into per-step sub-tasks.
Waiting on Nothing.
Next Split "Sync Qt codegen for currency" per the plan and unblock it.
Last touched 2026-07-04

Acceptance

  • Every feature present in currency's Qt layer but absent from the qt codegen templates is triaged: either promoted to a template capability (with at least currency as a real consumer) or explicitly documented as currency-specific custom code to preserve across regeneration.
  • The combo-field template mechanism is either exercised end-to-end for currency's 3 combo fields (piloting it for the first time) or explicitly deferred with a documented reason.
  • Once triaged, "Sync Qt codegen for currency" can proceed as a mechanical regenerate + reconcile pass with a concrete, reviewed plan — not a speculative rewrite.

Tasks

Task State Start End Description
Triage currency Qt custom features against codegen templates DONE 2026-07-04 2026-07-04 For each custom feature in currency's Qt layer (CSV/XML import-export, feature-flagged synthetic data generation, full version-navigation UI, flag image handling, NATS notification wiring, handler naming drift), decide feature-by-feature whether it becomes a generalised qt-profile template capability (a variability knob other entities can opt into, e.g. import/export as a configurable capability rather than currency-specific code) or stays currency-specific custom code. As part of the triage, flag and separately note any business logic currently embedded in the Qt UI layer that belongs elsewhere (domain/service/repository) and should be relocated rather than templated in place. Produce a written decision doc covering every discovered feature.
Pilot the combo-field template mechanism for currency's 3 soft-FK fields DONE 2026-07-04 2026-07-04 Currency's monetary_nature, market_tier, and rounding_type detail-dialog fields are soft-FK combo boxes backed by reference tables, and the qt codegen profile has a combo-field mechanism that no entity currently exercises. Pilot it end-to-end for currency's 3 fields (first real consumer), or explicitly defer with a documented reason if the mechanism is not yet fit for this shape of data.
Produce concrete regenerate/reconcile plan for Sync Qt codegen for currency DONE 2026-07-04 2026-07-04 Turn the triage and combo-field piloting output into a concrete, reviewed plan for the blocked 'Sync Qt codegen for currency' task: which of the 12 output files change, which template capabilities need to land first, and which currency-specific code must be preserved across regeneration. Once this plan exists, the Qt sync task can proceed as a reviewed mechanical regenerate + reconcile pass rather than a speculative rewrite.

Decisions

  • CSV export, XML import/export, version-navigation UI, and NATS notification wiring: promote to generalised, opt-in qt-profile template capabilities.
  • Synthetic-data-generation button: promote as a conditional setting-gated action-visibility knob, generalised beyond this one button.
  • Flag image handling: not a promote/custom call — the template already has a partial generic mechanism (has_flag_icon) that currency bypasses with hand-rolled code; reconcile currency onto it.
  • 3 soft-FK combo fields (monetary_nature, market_tier, rounding_type): rather than extend the mustache templates with 5 new behaviours (fetch, guard, sort, tooltip, placeholder), wrote one hand-crafted generic helper, ores::qt::populateDynamicCombo<Entity> (ores.qt/api/include/ores.qt/DynamicComboSetup.hpp), plus 3 small LookupFetcher fetchers. Currency's 3 fields now call the helper; builds clean. Codegen's job for this pattern shrinks to emitting one fetcher function and one short call per is_dynamic_combo field. Known gap: fetch-failure signalling isn't surfaced by the helper yet (empty combo either way) — needs a decision in the regenerate plan.
  • Handler naming drift (onOpenCurrencyVersion etc.): mechanical rename on regeneration, not a design decision.
  • Business logic relocation: the random-pick selection logic in CurrencyDetailDialog::onGenerateClicked() and CurrencyMdiWindow::generateSynthetic() belongs in the generator/service layer, not the Qt UI — relocate during the eventual Qt sync.
  • Regenerate plan: "Sync Qt codegen for currency" is really 7-8 sub-tasks (relocate business logic; land CSV/XML export, setting- gated visibility, version-navigation UI, and NATS notification- wiring as template capabilities; reconcile flag image and combo fields onto existing/piloted mechanisms; decide fetch-failure signalling; only then the final mechanical regenerate+diff). Split it into per-step sub-tasks rather than attempting one task. Full per-file table and sequence in task.

Out of scope

Emacs 29.3 (Org mode 9.6.15)