Task: Codegen: generate calendar_date service/protocol/nats-handler layers using extra_list_requests
Table of Contents
This page documents a task in the Calendar entity follow-ups: date picker, list-pagination fix, QuantLib materialization story. It captures the goal, current status, acceptance, and any notes or results.
Goal
calendar_date currently has only domain/SQL/repository layers
generated. This task applies the list_by knob added in
Codegen: extend junction repository/service templates with paginated list_by filter
(repository + service, regenerated for real this time, not just
dry-run diffed) and generates a protocol/nats-handler layer via the
extra_list_requests knob – the first real consumer of that
mechanism – so a paginated, filtered-by-calendar_code NATS request
exists for the Qt Browse Holidays view to call in the follow-on task.
Status
| Field | Value |
|---|---|
| State | DONE |
| Parent story | Calendar entity follow-ups: date picker, list-pagination fix, QuantLib materialization |
| Now | Nothing. |
| Waiting on | Nothing. |
| Next | Nothing. |
| Last touched | 2026-07-27 |
Acceptance
[X]calendar_date's repository/service files regenerate for real (not dry-run) with the paginated list_by-by-calendar_code method.[X]calendar_date gets a protocol layer with a paginated, calendar_code-filtered get_calendar_dates_…/request/response pair via extra_list_requests.[X]calendar_date gets a nats-handler layer wiring that request to the service's paginated list method, registered on a NATS subject.[X]Build is clean and calendar_date's new messaging code compiles and links.
Plan
(Implementation strategy. Written when work starts; key decisions
are distilled into the parent story's * Decisions at close, but the
plan itself stays — it is the historical record of what we did.)
Correction to the Goal's premise: extra_list_requests turned out
to be a domain_entity-only mechanism – protocol_header.org,
nats_handler_header.org, and nats_registrar_{header,implementation}.org
are each wrapped entirely in \{\{#domain_entity\}\}...\{\{/domain_entity\}\},
with no junction path at all. Deeper still: all four facets
(ores.cpp.service, ores.cpp.protocol, ores.cpp.nats-handler,
ores.cpp.nats-sub-registrar) declare
#+model_types: domain_entity schema – junction models are excluded
at the facet-applicability level, so even the \{\{#junction\}\}
section already added to service_header/impl.org in the prior task
was unreachable dead code until this task added junction to that
list.
Rather than reusing extra_list_requests verbatim, added a parallel,
deliberately minimal \{\{#junction\}\} section to each of the four
templates, covering only what a read-only paginated browse view
needs (no save/delete/history/CRUD – junctions don't have a uniform
CRUD shape the way domain entities do):
protocol_header.org:get_<name>_by_<column>_request/responsegated byleft.list_by=/=right.list_by, same shape as the domain_entityextra_list_requestsblock.nats_handler_header.org: a handler class with onelist_by_<column>method per flagged side, calling the service's paginatedlist_<name_short>_by_<column>+ count methods.nats_registrar_{header,implementation}.org: constructor + one subject subscription per flagged side.service.org: addedjunctionto#+model_types:so the service-layerlist_bysection from the prior task actually fires.
Verified via --diff against currency_calendar (no list_by set)
that all four facets now generate a minimal-but-valid skeleton (empty
handler/registrar, base service methods) with zero regression risk to
existing entities – these files aren't checked in for any junction
except calendar_date, so nothing else's build is affected.
Wired calendar_date_registrar into
ores.refdata.core/src/messaging/registrar.cpp (hand-maintained
composition point, not itself generated) alongside the other
alphabetically-ordered register_*_handlers calls.
Notes
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 |
|---|---|---|
PRs
| PR | Title |
|---|---|
| #1714 | [refdata,codegen] Generate calendar_date messaging layer, fix date-column validation in service templates |
Review
| Comment summary | File | Decision | Notes |
|---|---|---|---|
Result
Shipped calendar_date's full messaging layer (service, protocol,
nats-handler, nats-registrar) via a new \{\{#junction\}\} path added
to all four generating templates, and wired
calendar_date_registrar into the hand-maintained
ores.refdata.core/src/messaging/registrar.cpp.
Build broke on first attempt: the generated
save_calendar_date validation called .empty() on
calendar_date.date (a std::chrono::year_month_day, which has no
.empty()) – a latent bug in cpp_service.cpp.mustache /
ores.cpp.service.service_impl.org, which only distinguished
is_uuid vs. a string-only .empty() fallback for primary-key/
junction-key validation, with no branch for the is_date flag that
already existed in the codegen data model (used elsewhere, e.g. SQL
templates). Fixed both templates to check is_date first
(!x.ok()) before falling back to .empty(), then regenerated
calendar_date_service.\{hpp,cpp\} for real from the corrected
template rather than hand-patching the generated output. Full build
is green.