Feat(global temp): include in-office procedures in global templates#7980
Open
alexwillingham wants to merge 6 commits into
Open
Feat(global temp): include in-office procedures in global templates#7980alexwillingham wants to merge 6 commits into
alexwillingham wants to merge 6 commits into
Conversation
Mirrors the in-house labs template pattern for the in-office Procedures
feature, with the linked-structure cross-refs adapted to procedures'
shape: a procedure ServiceRequest carries reasonReference into encounter
diagnosis Conditions and supportingInfo into CPT-code Procedures.
admin-create-template captures chart procedures (filtered to includable
statuses so entered-in-error/revoked ones don't leak in) and materializes
each as a plan ServiceRequest in List.contained. The plan preserves the
procedure form's full payload - category (procedureType), performerType,
bodySite, and the dozen extensions for technique/medication/etc - and
remaps reasonReference/supportingInfo through oldIdToNewIdMap so they
point at the template's contained Conditions and CPT Procedures.
admin-get-template-detail parses procedure plans into TemplateProcedurePlan
with inline {code, display} (plus modifiers, matching the in-house labs
TemplateCptCodeInfo shape) for the linked diagnoses and CPT codes, so the
UI never has to walk the FHIR graph.
apply-template materializes procedure plans via a small builder
(apply-procedures.ts) which rewrites cross-refs through a contained-id ->
urn:uuid fullUrl map built during makeCreateRequests. CPT-Procedure creates
moved into the mini-transaction so the procedure plan's supportingInfo
fullUrls resolve atomically in the same FHIR transaction. References whose
target section is set to 'skip' get dropped on the rewritten request.
Section actions: 'procedures' added to TemplateSectionKey,
TEMPLATE_SECTIONS_IN_ORDER, and TEMPLATE_SECTION_DEFAULT_ACTIONS (append),
with the section constrained to skip/append (no overwrite) so applying a
template never silently wipes a provider's existing procedure
documentation.
UI: TemplatePreviewDialog and GlobalTemplateDetailPage each render a
Procedures section. The preview lays out the procedure type as a subtitle
subheading with the details left-indented underneath - uppercase-caption
"CPT codes" and "Diagnoses" labels above the shared CodeList rendering,
followed by a compact label/value list of the procedure-form fields the
template actually carried (Yes/No for booleans, free-text blocks inline
with their label, multi-line content via whiteSpace: pre-wrap).
Tests: 9 unit tests pin the procedure-plan builder (apply-procedures.ts)
- reference rewrite, drop semantics when a target section is skipped,
status/intent/tag transitions, sparse plan handling. 2 validation tests
cover the skip/append-only constraint. 2 EHR component tests cover the
section card (codes/fields visible, Overwrite hidden) and the empty
template case.
The in-house labs work landed isValidInHouseLabServiceRequest tests in admin-create-template.test.ts and a makeCreateRequests block in apply-template.test.ts that exercised every action-combination overlap between the labs section and CPT Codes. The procedure-plan code added in this branch had unit tests for its builder (apply-procedures.test.ts) but no equivalent coverage for the capture filter or for the makeCreateRequests integration. Filled the gap: admin-create-template.test.ts gains 7 isValidProcedureServiceRequest tests pinning the includable-status set, exclusion of deleted procedures (entered-in-error / revoked), the procedure meta-tag requirement, and the non-ServiceRequest fallthrough. apply-template.test.ts gains 6 makeCreateRequests procedure-plan tests: - procedures='skip' emits no SR - procedures='append' emits one chart-data-shaped SR per plan with the procedure meta tag (not the plan tag) and a urn:uuid fullUrl - reasonReference / supportingInfo are rewritten to the fullUrls of the new live Condition / CPT Procedure in the same transaction - diagnoses='skip' drops reasonReference rather than leaking the template-stub id - cptCodes='skip' drops supportingInfo for the same reason - a sparse plan (no cross-refs) produces a clean SR without empty arrays
A reuse / simplification pass surfaced several places the diff had re-implemented existing helpers or duplicated structure inside itself. Folded those in so the procedures code reads like the rest of the templates surface area: - apply-procedures.ts uses resourceHasTagSystem from utils instead of an inline meta?.tag?.some() probe. - buildLiveProcedureRequest returns BatchInputPostRequest<ServiceRequest> directly. The droppedReasonReferences / droppedSupportingInfo counters were only consulted in tests, never operationally - removed. - admin-create-template lifts TEMPLATE_INCLUDABLE_SR_STATUSES to a module-level constant; isValidInHouseLabServiceRequest and isValidProcedureServiceRequest share the same allow-list instead of redefining it inline. - admin-get-template-detail imports CPT_CODE_SYSTEM from utils instead of hard-coding 'http://www.ama-assn.org/go/cpt', and walks the template's contained array once to build conditionById and cptProcedureById together instead of two sequential passes. - TemplatePreviewDialog's ProcedurePlanFields collapses the parallel rows[] / blocks[] arrays into one list with a multiline flag, removing the duplicate filter+render logic for free-text vs single-line fields. - A new getProcedureDisplayFields(plan) helper in src/helpers/templates.ts carries the 12-field display list; the apply-template preview and the admin detail page both consume it instead of inlining the same 12 rows twice.
8 tasks
pare down giant comment Signed-off-by: alexwillingham <awillingham@masslight.com>
alexwillingham
commented
Jun 7, 2026
…lder Per PR review: apply-template's buildLiveProcedureRequest was duplicating the procedure ServiceRequest construction logic, so any future change to the procedure feature (new extension, different status default, refined codings) would have needed two edits to land in both the chart-data save path and the template apply path. Refactored so the apply-template path now flows through the same createProcedureServiceRequest builder save-chart-data uses: - Pulled the procedure-form field reader (extension/coding extraction) out of makeProceduresDTOFromFhirResources into a named export, readProcedureFormFieldsFromServiceRequest. Both the chart-data reader and apply-template now call it; the read shape stays in one place too. - Taught createProcedureServiceRequest to pass `urn:uuid:`-prefixed resourceIds through verbatim on reasonReference / supportingInfo. Plain ids still get the FHIR resource-type prefix, so save-chart-data keeps emitting `Condition/<id>` while apply-template can emit `urn:uuid:<...>` and have the FHIR transaction resolve the link to the Conditions and CPT Procedures it's creating alongside. - buildLiveProcedureRequest now reads the plan's form payload via the shared reader, encodes the remapped fullUrls into the DiagnosisDTO / CPTCodeDTO resourceId slots, delegates the ServiceRequest construction to the shared builder, and just adds the urn:uuid fullUrl so other resources in the transaction can reference the new procedure. The plan→DTO conversion drops uncanonical codings (no system, or unknown system) and rebuilds the extension list in canonical order — both are desirable, since the template should never persist non-canonical data through the apply path. Updated the unit test fixtures to use canonical systems and adjusted assertions accordingly.
alexwillingham
commented
Jun 8, 2026
…pply Per PR review: silently falling back to undefined when the ISO timestamp generation fails hides the bug. now() can only return an invalid DateTime under truly broken conditions, but if it ever does we'd rather fail loudly than ship a procedure with no documentedDateTime.
Contributor
There was a problem hiding this comment.
Copilot reviewed 14 out of 14 changed files in this pull request and generated no comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
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.
OTR-2087: Global templates -- Add Procedures
🤖 Claude generated this code, but I reviewed it carefully and edited it.
The description below is from Claude also.
Summary
Mirrors the in-house labs template pattern for the in-office Procedures feature, with the linked-structure cross-refs adapted to procedures' shape: a procedure ServiceRequest carries
reasonReferenceinto encounter diagnosis Conditions andsupportingInfointo CPT-code Procedures, so the template snapshot has to preserve those links to round-trip.Test coverage added
Mirroring the in-house labs work:
apply-procedures.test.ts— 9 unit tests on the procedure-plan builder: reference rewrite, drop semantics when the target section is skipped, intent/status/tag transitions, sparse plan handling.admin-create-template.test.ts— 7 tests onisValidProcedureServiceRequest: includable-status set, exclusion of deleted procedures (entered-in-error/revoked), the procedure meta-tag requirement, the non-ServiceRequest fallthrough.apply-template.test.ts— 6makeCreateRequestsprocedure-plan tests: action propagation, end-to-end cross-ref rewrite into fullUrls in the same transaction, drop semantics when diagnoses/CPT sections are skipped, sparse-plan handling.apply-template.test.ts— 2 validation tests pin the skip/append-only constraint.ApplyTemplate.test.tsx— 2 component tests cover the procedure section card (CPT/diagnosis text + form fields visible, Overwrite hidden) and the empty-procedures case where the section is suppressed.Generated by Claude Code