{"v":[{"id":1345,"html_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/156#issuecomment-1345","pull_request_url":"","issue_url":"https:\/\/www-s01.apinet.com\/codeforge\/apiintl\/hhmanager\/issues\/156","user":{"id":1,"login":"charles","login_name":"","source_id":0,"full_name":"Charles Willgren","email":"charles@noreply.www-s01.apinet.com","avatar_url":"https:\/\/www-s01.apinet.com\/codeforge\/avatars\/d3c894f7297c5a18eb3f6ac837c335b11a00aa9cc0961323771632b1e2d61bb2","html_url":"https:\/\/www-s01.apinet.com\/codeforge\/charles","language":"","is_admin":false,"last_login":"0001-01-01T00:00:00Z","created":"2025-12-08T10:03:41-06:00","restricted":false,"active":false,"prohibit_login":false,"location":"","pronouns":"","website":"","description":"","visibility":"public","followers_count":0,"following_count":0,"starred_repos_count":0,"username":"charles"},"original_author":"","original_author_id":0,"body":"## Where the code stands today\n\nPer visit type, part of this is already handled and part is not.\n\n| Varies by visit type | Today |\n|---|---|\n| **Which forms** | \u2705 The packet (`docs\/form-packets\/*.json`) decides, including `when` choices (PAS\/PHC vs PCS consent on the program). |\n| **Which questions, order, wording, conditions** | \u2705 The structure allows it: there is one interview file per packet (`docs\/form-v2-interviews\/{PACKET}.json`). But **only `SOC_AO.json` exists**. The other 14 packets have no interview yet. |\n| **Answer choices** | \u26a0\ufe0f Only partly. Choices come from the form definition, which is global. An interview can relabel a choice and add `option_info`, but it can't offer a **subset** of the choices. |\n| **Fixed answers (never asked)** | \u274c Not per visit type. A `derived` + `fixed` element in `code\/form_v2_shared.inc.php` is **install-wide**. Examples are supervision level = Non-RN and frequency = Q12\/PRN. Nothing lets a fixed value depend on the visit type. |\n| **Fixed answers that are *shown*** | \u274c A `fixed` element is never shown. A step's `shows` can only list values pinned from the record (`auth.*` etc.), not derived ones. |\n\n### Concrete cases already in the files\n\n- **Client Information Sheet `visit_type`** (Start of Care \/ Annual Reassessment) is currently *asked* in SOC_AO, with help text \"almost always Start of Care\". It should be fixed by the visit type: SOC_AO \u2192 `soc`, AR \u2192 `ar`.\n- **3040 `attendant_{a,b,c}_visit_type`** (AO \/ SV \/ SA) is asked once per attendant. It is probably fixed by the visit type (SOC_AO \u2192 AO, SV \u2192 SV\u2026). There may be an exception when one attendant is new and another is being supervised.\n- **3040 `visit_setting`** has help text \"Tick it at a first visit\", so it is also visit-type dependent.\n\n## Ideas\n\n1. **Make the visit type a fact.** Add a pinned `visit.packet_code` (or `visit.type`) to `form_packet_facts()` \/ the visit's pins. Then every existing mechanism can key off it:\n   - conditions: `{\"==\": [{\"field\": \"visit.type\"}, \"AR\"]}`\n   - `shows` can show it (\"This is an Annual Reassessment\")\n   - a derive can map it, e.g. `derive: {op: \"map\", from: \"visit.type\", values: {SOC_AO: \"soc\", AR: \"ar\"}}`\n\n   This reuses the existing `map` op (#105) instead of inventing a new concept.\n2. **Fixed answers per visit type: choose the file that declares them.**\n   - **(a)** Use a `map`-from-visit-type derive in `form_v2_shared.inc.php` (the idea above). Everything stays in one place, but that file starts knowing about packets.\n   - **(b)** Add a `fixed` block to each interview file (`\"fixed\": {\"form.client-information-sheet.visit_type\": \"soc\"}`), with an optional `\"show\": true` per entry for answers the supervisor should see. This keeps \"what this visit type does\" in one file per visit type, as interviews are now.\n\n   I lean towards **(b)** for anything that varies per visit type. I'd keep `form_v2_shared` `fixed` for things that never vary at this customer. The publish check should refuse a key that is both fixed in the interview and asked in it.\n3. **Shown vs hidden fixed answers:** extend `shows` to accept a fixed\/derived element (read-only, in words, as pinned values are shown now). Anything not listed there stays silent and only prints.\n4. **Choice subsets:** allow an interview question to carry `\"only\": [\"ao\", \"sv\"]`. The rule would be that it may narrow a form's choices but never add one, the same principle as \"`required` can only be made stricter\". If only one choice is left, it becomes a fixed answer.\n5. **Write the next interview to test the design.** AR is the obvious one, since it shares most forms with SOC_AO. Writing `AR.json` will show exactly which SOC_AO questions turn into fixed or shown answers, and which choices narrow.\n\n## Questions\n\n1. **Combined visits.** V2 runs **one packet per visit** today, even though `form_packet_merge()` can union several. Will staff ever do two visit types at once (e.g. AR + SV, or SOC + a transfer)? If so, two visit types may fix the same box differently (CIS `visit_type` = soc vs ar). We'd need a precedence rule, or the publish check refuses the combination. Interviews would also need merging, which nothing does yet.\n2. **Which fixed answers should the supervisor see?** Is the rule \"show anything the client is told or signs\" and hide administrative boxes? Or does the customer want to list them one by one?\n3. **3040 attendant visit type:** is it always the same for every attendant on a visit, or can one attendant be AO while another is SV on the same visit?\n4. **Is there a list from the customer** of per-visit-type differences, or do we derive it from the packets and the paper? The `Compliance RVSD. 5.13.2025` checklist names the forms but not the answers.\n5. Should a supervisor ever be able to **override** a fixed answer (e.g. a visit started as the wrong type)? Or is the answer always \"start the right visit type\"? I'd suggest the latter, so the paper can't disagree with the visit record.","assets":[],"created_at":"2026-10-07T13:54:38-05:00","updated_at":"2026-10-07T13:54:38-05:00"}]}