feat: paperwork flows — compose base-intake and per-service forms at booking (OTR-2309 pt 2/2)#8131
Open
dmabram wants to merge 1 commit into
Open
feat: paperwork flows — compose base-intake and per-service forms at booking (OTR-2309 pt 2/2)#8131dmabram wants to merge 1 commit into
dmabram wants to merge 1 commit into
Conversation
…booking
Practices design their own paperwork flows: which forms every booking on a base
intake includes, plus per-service form bundles, composed at booking time.
Data model (FHIR List, tagged practice-paperwork-flow):
- Service flow: { slug, name, base: standard | consent-only, ordered formIds },
referenced by ServiceCategory config (paperworkFlowId); assigning a service to
a flow is reconciled across categories (single-valued field).
- Base flow: 3 fixed Lists, one per base intake canonical (in-person / virtual /
consent-only), marked by a paperwork-flow-canonical extension; auto-created
idempotently (ensureBaseFlows); identity is fixed, only their form list edits.
Booking time (create-appointment):
- The slot's service category resolves its paperworkFlowId; a consent-only flow
base maps to the consent-form-only subtype (lite intake canonical); the flow id
is stamped on the Encounter and Appointment. Flow-lookup failures fall back to
the mode default and are logged, never silently.
Form resolution (get-practice-managed-questionnaires):
- A booking's forms = base-intake forms (the base flow bound to the resolved
canonical) + service-flow forms, base-first, de-duped keep-first
(composeFormIds). Same-base isolation falls out: a consent-only booking never
inherits standard-intake forms. Flow searches are paginated. The standalone
send-form path is unchanged.
Admin (Paperwork Flows tab):
- Base intake cards (In-person / Virtual / Consent-only) with auto-saving
add/remove/reorder of attached forms — debounced reorder, sequenced saves with
a stable unmount flush, and failed saves surfacing an error and reconciling to
refetched server state.
- Service flows table + dialog (name, auto-slug via shared slugify, base, forms,
applies-to-services) with "New flow" scoped to that section.
- admin-{list,create,update,delete}-paperwork-flow zambdas with base-flow guard
rails (not creatable/deletable; only formIds editable; delete refuses to
proceed when the guard fetch fails).
Unit tests: flow List round-trip, base-flow catalog, composeFormIds
ordering/dedup, canonical mapping for the consent-only base.
Co-Authored-By: Claude Opus 4.8 <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.
Part 2 of 2 for OTR-2309, stacked on #8130 (
otr-2309-forms) — re-target torelease/1.36after part 1 merges. Practices design their own paperwork flows: forms every booking on a base intake includes, plus per-service form bundles, composed at booking time.Model
What this adds
Data model — flows persist as FHIR
Lists (taggedpractice-paperwork-flow). Three fixed base flows, one per base canonical (marked by apaperwork-flow-canonicalextension), auto-created idempotently; identity fixed, only their form lists edit. Service flows reference services via the ServiceCategory config blob (paperworkFlowId).Booking time (create-appointment) — the slot's service category resolves its flow; consent-only base maps to the lite intake canonical (explicit staff paperwork-subtype still wins); flow id stamped on Encounter + Appointment. Channel-agnostic: patient booking and EHR
/visits/addbehave identically. Flow-lookup failures fall back to the mode default and are logged, never blocking the booking.Form resolution (get-practice-managed-questionnaires) — composes base + service forms with same-base isolation (a consent-only booking never inherits standard-intake forms; a Virtual-only form never appears in-person). Insertion point inside the intake is server-determined (client substring heuristic removed; boundary cached per appointment, statuses fetched fresh at the boundary). The standalone send-form path is untouched. Flow searches paginate.
Admin (Paperwork Flows tab) — Base intake cards (In-person / Virtual / Consent-only) with auto-saving add/remove/reorder (debounced reorder, sequenced saves, stable unmount flush; failed saves surface an error and reconcile to server state). Service flows table + dialog (name, auto-slug via shared
slugify, base, forms, applies-to-services); "New flow" scoped to service flows. CRUD zambdas carry base-flow guard rails (not creatable/deletable; delete refuses when the guard fetch fails).Patient experience — composed forms render as pages inside the intake before finalization; completing them marks responses complete and the intake skips completed forms (re-editing returns one to in-progress until finished again). All part-1 guarantees (resume, required validation, error surfacing, no visible scores, answer fidelity) apply to in-intake forms.
Verification
[ACE (base), SWYC (service flow)]; ACE saved asvalueCodingcodes1,0,1,0…= displaysYes,No,…matching the exact clicks; SWYC 4 pages with [10,12,6,2] answers — each page only its own, zero duplication, zero raw-code strings; both QRs completed, no re-entry loop (completed forms skipped; re-edited form correctly revisited); resume pre-seeded all saved answers; EHR visit page shows display text (": Somewhat", not ": 2"); base-card auto-save persisted via the UI.Functional requirements:
practice-forms-functional-requirements.mdPart 2 (local docs).🤖 Generated with Claude Code