Category Rendering
Category Rendering And Visibility
Purpose
This document maps the current category rendering path used by the coding,
reviewing, data-manager (vadata) and area/viewer (vaarea) renderings:
- which route serves each category
- which partial renders it
- which mapping source is used
- which fields matter for category presence
- which conditions must be met for the category to appear in the left nav
This is a current-state description of the running code, not a target-state design.
SmartVA Analysis displays its original cause and ICD-10 code for each available primary, secondary, and tertiary result. The adjacent ICD-11 mapping is read from WHO's local 10-to-11 crosswalk and may show alternatives or postcoordination. An unmapped ICD-10 code displays "unavailable". This display does not change saved SmartVA or assessment values.
Shared Render Pipeline
All category panels are served by app/routes/va_api.py
through:
/<va_action>/<va_actiontype>/<va_sid>/<va_partial>
Current route behavior:
- the render path now resolves form type from
va_submissions.va_form_id -> va_forms.form_type_id -> mas_form_types.form_type_code - category eligibility and previous/next traversal now come from
CategoryRenderingService, which reads ordered role visibility frommas_category_display_config - if
form_type_idis not populated, the runtime falls back to the legacyva_forms.form_typevalue when it matches a registered active form type - if neither link is available, the runtime falls back to the default form type
WHO_2022_VA - coder and reviewer views still start from the static coder mapping in
app/utils/va_mapping/va_mapping_02_fieldcoder.pybut now bridge in DB-backed categories that are visible in category config and missing from the static dict - the data-manager and area/viewer renderings use the DB-backed mappings from
app/services/field_mapping_service.pyviaget_fieldsitepi() - category partial selection now branches by
mas_category_display_config.render_modefor categories visible to the current role:table_sections-> generic renderer incategory_table_sections.htmlhealth_history_summary-> generic renderer incategory_health_history_summary.htmlattachments-> hybrid renderer incategory_attachments.htmlusing generic submission-data sections plus explicit workflow/result panelsworkflow_panel-> explicit workflow renderer incategory_va_cod_assessment.html
Common filtering happens in
app/utils/va_render/va_render_06_processcategorydata.py.
A mapped field contributes to rendered category content only if:
- the field exists in
va_submission.va_data - the value is not
None - the value is not string
dk - the value is not string
ref - if the field is one of
isNeonatal,isChild,isAdult, the value is not0 - if the field is an attachment, the referenced file exists on disk
Additional render-time transforms:
- some fields are date-normalized
- some fields are datetime-normalized
- choice-coded fields are label-mapped
- some multi-select fields are expanded to mapped choice labels
- attachment fields are converted to media URLs
table_sectionscategories now render subcategory sections generically from ordered DB config and reuse the same flip/info badge rules as the legacy static partialshealth_history_summarynow renders positive diagnoses, absent diagnoses, and non-binary leftovers generically from category data instead of using a category- specific templateattachmentsnow renders narration/audio/images and document galleries generically from category data, while still appending explicit QA and legacy workflow UI- the coder-only
workflow_panelCOD step now assembles a condensed evidence block before the COD form, including:- live DB-driven summary badges from
summary_include/summary_label - narration and document sections
vahealthhistorydetails / medical_historygrouped with the same positive / absent / detail logic used in the health history renderer- the current coder note for the submission
- live DB-driven summary badges from
- in
attachments, file type detection is automatic by file extension - image carousel behavior is now controlled by subcategory-level
MasSubcategoryOrder.render_mode, currently seeded asmedia_galleryformedical_documentsanddeath_documents - attachment images now open in an in-page lightbox with close, zoom, and pan support
- document gallery images in
vanarrationanddocumentsnow expose per-image rotate-left and rotate-right controls that apply 90-degree steps and persist client-side inlocalStorage, keyed by submission SID plus attachment identity, with a 5-minute expiry - the attachments lightbox now supports fullscreen gallery navigation and keyboard
shortcuts:
- left/right arrows move between images in the current gallery
;/'rotate the current image</>zoom out / zoom in
social_autopsyintable_sectionsmode appends an app-owned Social Autopsy analysis form for coder coding flows when the submission's project hassocial_autopsy_enabled = true, and for reviewer flows when the project hasreviewer_social_autopsy_enabled = true- coder views now also append a synthetic final nav item
vacodassessment, which renders the dedicated COD workflow panel outsidevanarrationanddocuments - the
vacodassessmentworkflow panel also reuses the shared attachments lightbox for COD evidence images and galleries - coder/reviewer rendering uses a bridge path so DB-only categories such as
social_autopsydo not render empty while the field-level coder config remains partially static
Important nuance for social_autopsy:
- mapped
social_autopsysubmission fields still render based on form/category mappings and submission data - the app-owned Social Autopsy analysis form is controlled separately at the
project level by
va_project_master.social_autopsy_enabledfor coders andva_project_master.reviewer_social_autopsy_enabledfor reviewers - when the relevant project flag is
false, the category can still appear in the left nav if mapped fields are present, but the app-owned analysis form is not shown and its completion is not enforced
Left Nav Visibility
The left nav is rendered by
app/templates/va_frontpages/va_coding.html.
Current visibility rules:
- the coding-page left nav is now rendered from
CategoryRenderingService - a category must be role-visible in
mas_category_display_config - a category must either:
- be present in the live visible category set derived from current submission data, or
- have
always_include = trueinmas_category_display_config
- this means
vainterviewdetailsis now site-PI-only because the category config marks it hidden for coder and reviewer vanarrationanddocumentsis always shown because its category config setsalways_include = true- coder flows also show a final workflow nav item
vacodassessment, which is not derived from mapped submission fields
The live visible category set is computed by
get_visible_category_codes()
from current submission data, form type, and mapped category content. Stored
va_category_list remains in the database for legacy compatibility, but it is no
longer the runtime source of truth for the nav.
Current UI behavior:
- the initial HTMX-loaded category now comes from the visible nav order:
- preferred
is_default_start = truecategory if visible - otherwise the first visible category by
display_order
- preferred
Category Inventory
For each category below, "important fields" means the mapped field groups that currently determine whether the category can produce any content. In practice, a category appears when at least one of its mapped fields survives the shared filtering rules above.
vainterviewdetails
- Nav label:
Interview Details - Route:
/<va_action>/<va_actiontype>/<va_sid>/vainterviewdetails - Partial:
app/templates/va_formcategory_partials/vainterviewdetails.html - Mapping source:
- data manager and area/viewer (
vadata,vaarea): DB-backedget_fieldsitepi() - coder/reviewer: the static coder mapping has no
vainterviewdetailsentry; the DB mapping is bridged in only when the category is visible to that role
- data manager and area/viewer (
- Partial sections:
interviewva_interviewerva_respondent
- Important mapped fields:
va_interviewer:Id10010,Id10010a,Id10010b,Id10010cinterview:language,Id10012,Id10013,Id10011,Id10481va_respondent:Id10007,Id10007a,Id10007b,Id10008,Id10009
- Conditions to appear in left nav:
vainterviewdetailsmust be present inva_category_list- the category must be visible to the rendering's role
(
show_to_site_pi_datamanagerforvadataandvaarea;show_to_coder/show_to_reviewerotherwise). Thevasitepirendering was removed on 2026-10-03 (digitva-a00o)
- Effective trigger rule:
- any surviving field in
va_interviewer,interview, orva_respondent
- any surviving field in
vademographicdetails
- Nav label:
Demographic / Risk Factors - Route:
/<va_action>/<va_actiontype>/<va_sid>/vademographicdetails - Partial:
app/templates/va_formcategory_partials/vademographicdetails.html - Partial sections:
generalrisk_factors
- Important mapped fields:
general:Site,unique_id,site_individual_id,Id10017,Id10018,Id10021,Id10023,isNeonatal,isChild,isAdult,Id10019,Id10058risk_factors:Id10411,Id10413,Id10413_d,Id10413_a,Id10413_b,Id10414,Id10414_d,Id10414_a,Id10414_b,Id10487
- Conditions to appear in left nav:
vademographicdetailsmust be present inva_category_list
- Effective trigger rule:
- any surviving field in
generalorrisk_factors
- any surviving field in
- Important nuance:
isNeonatal,isChild, andisAdultonly count when their stored value is truthy (1,1.0)
vaneonatalperioddetails
- Nav label:
Neonatal Period - Route:
/<va_action>/<va_actiontype>/<va_sid>/vaneonatalperioddetails - Partial:
app/templates/va_formcategory_partials/vaneonatalperioddetails.html - Partial sections:
generaldeliverystillbirthbirth_weightsymptomsphysical_abnormalitiesbaby_mother
- Important mapped fields:
general:Id10354,Id10367delivery:Id10387,Id10388,Id10389,Id10369stillbirth:Id10104,Id10105,Id10110,Id10114birth_weight:Id10366_check,Id10366,Id10363,Id10365symptoms:Id10406,Id10284,Id10286,Id10287physical_abnormalities:Id10370,Id10371,Id10372,Id10373baby_mother:Id10391,Id10393,Id10395,Id10396
- Conditions to appear in left nav:
vaneonatalperioddetailsmust be present inva_category_list
- Effective trigger rule:
- any surviving field in any neonatal-period subcategory
vainjuriesdetails
- Nav label:
Injuries - Route:
/<va_action>/<va_actiontype>/<va_sid>/vainjuriesdetails - Partial:
app/templates/va_formcategory_partials/vainjuriesdetails.html - Partial sections:
default
- Important mapped fields:
Id10077,Id10077_a,Id10079,Id10082,Id10083,Id10084,Id10085,Id10089,Id10098,Id10099,Id10100
- Conditions to appear in left nav:
vainjuriesdetailsmust be present inva_category_list
- Effective trigger rule:
- any surviving field in the
defaultinjury field group
- any surviving field in the
vahealthhistorydetails
- Nav label:
Disease/Co-morbidity - Route:
/<va_action>/<va_actiontype>/<va_sid>/vahealthhistorydetails - Partial:
app/templates/va_formcategory_partials/vahealthhistorydetails.html - Partial sections:
medical_historyneonate
- Important mapped fields:
neonate:Id10351,Id10408medical_history:Id10125,Id10126,Id10127,Id10128,Id10482,Id10132,Id10133,Id10134,Id10135,Id10137
- Conditions to appear in left nav:
vahealthhistorydetailsmust be present inva_category_list
- Effective trigger rule:
- any surviving field in
medical_historyorneonate
- any surviving field in
- Important partial behavior:
- the partial groups many
medical_historyyes/no values into positive vs negative diagnosis summaries before rendering the detailed tables - in the admin Categories browser,
vahealthhistorydetails / medical_historyshould be treated as a special subcategory because assigning a field there opts it into this summary behavior, not a plain query/response section
- the partial groups many
social_autopsy
- Nav label:
Social Autopsy - Route:
/<va_action>/<va_actiontype>/<va_sid>/social_autopsy - Partial:
app/templates/va_formcategory_partials/category_table_sections.htmlwithapp/templates/va_formcategory_partials/_social_autopsy_analysis_form.html - Partial sections:
- DB-configured Social Autopsy subcategories and fields
- app-owned
Social Autopsy Analysisform appended after the mapped sections
- Important mapped fields:
- all fields assigned to category
social_autopsyfor the active form type
- all fields assigned to category
- Conditions to appear in left nav:
social_autopsymust be visible for the current role and have surviving mapped field data
- Important partial behavior:
- the mapped Social Autopsy submission fields render through the generic
table_sectionspipeline - in coder coding flows, the category then appends the app-owned Social Autopsy analysis form
- in the admin Categories browser,
social_autopsyshould be treated as a special category because it mixes dynamic submission rendering with an explicit workflow form
- the mapped Social Autopsy submission fields render through the generic
vageneralsymptoms
- Nav label:
General Symptoms - Route:
/<va_action>/<va_actiontype>/<va_sid>/vageneralsymptoms - Partial:
app/templates/va_formcategory_partials/vageneralsymptoms.html - Partial sections:
duration_of_illnessfeverskin_rashyellow_discolorationnutritionpuffinessswelling
- Important mapped fields:
duration_of_illness:Id10123,Id10121,Id10122,Id10120fever:Id10147,Id10148,Id10149,Id10150skin_rash:Id10233,Id10234,Id10235,Id10236yellow_discoloration:Id10265,Id10266,Id10267nutrition:Id10268,Id10269,Id10252,Id10485puffiness:Id10247,Id10248swelling:Id10249,Id10250,Id10251
- Conditions to appear in left nav:
vageneralsymptomsmust be present inva_category_list
- Effective trigger rule:
- any surviving field in any general-symptom subcategory
varespiratorycardiacsymptoms
- Nav label:
Respiratory / Cardiac - Route:
/<va_action>/<va_actiontype>/<va_sid>/varespiratorycardiacsymptoms - Partial:
app/templates/va_formcategory_partials/varespiratorycardiacsymptoms.html - Partial sections:
coughbreathlessnessfast_breathingbreathing_patternchest_pain
- Important mapped fields:
cough:Id10153,Id10154,Id10155,Id10157breathlessness:Id10159,Id10161,Id10162,Id10171fast_breathing:Id10166,Id10167breathing_pattern:Id10172,Id10173_nc,Id10173_achest_pain:Id10174,Id10175,Id10176,Id10179
- Conditions to appear in left nav:
varespiratorycardiacsymptomsmust be present inva_category_list
- Effective trigger rule:
- any surviving field in any respiratory/cardiac subcategory
vaabdominalsymptoms
- Nav label:
Abdominal - Route:
/<va_action>/<va_actiontype>/<va_sid>/vaabdominalsymptoms - Partial:
app/templates/va_formcategory_partials/vaabdominalsymptoms.html - Partial sections:
diarrhoeavomitabdominal_painprotuding_abdomenmass_abdomenurine_issues
- Important mapped fields:
diarrhoea:Id10181,Id10182,Id10183,Id10185bleeding:Id10186vomit:Id10188,Id10190_a,Id10189,Id10191abdominal_pain:Id10194,Id10195,Id10196,Id10199protuding_abdomen:Id10200,Id10201,Id10202,Id10203mass_abdomen:Id10204,Id10205,Id10206urine_issues:Id10223,Id10226,Id10224
- Conditions to appear in left nav:
vaabdominalsymptomsmust be present inva_category_list
- Effective trigger rule:
- any surviving field in any abdominal subcategory
- Important partial nuance:
- the mapping includes
bleeding, but the current partial has no dedicatedbleedingsection, so that field group can influence category presence without being visibly rendered as its own table
- the mapping includes
vaneurologicalsymptoms
- Nav label:
Neurological - Route:
/<va_action>/<va_actiontype>/<va_sid>/vaneurologicalsymptoms - Partial:
app/templates/va_formcategory_partials/vaneurologicalsymptoms.html - Partial sections:
headachesmell_tastemental_confusionunconciousparalysesstiff_painful_neckconvulsionsswallowing
- Important mapped fields:
headache:Id10207smell_taste:Id10486mental_confusion:Id10212,Id10213_a,Id10213unconcious:Id10214,Id10216_b,Id10216,Id10217paralyses:Id10258,Id10259,Id10260stiff_painful_neck:Id10208,Id10209_b,Id10209convulsions:Id10220,Id10222,Id10275,Id10276swallowing:Id10261,Id10262_b,Id10262,Id10262_c
- Conditions to appear in left nav:
vaneurologicalsymptomsmust be present inva_category_list
- Effective trigger rule:
- any surviving field in any neurological subcategory
vaskinmucosalsymptoms
- Nav label:
Skin / Mucosal / Others - Route:
/<va_action>/<va_actiontype>/<va_sid>/vaskinmucosalsymptoms - Partial:
app/templates/va_formcategory_partials/vaskinmucosalsymptoms.html - Partial sections:
ulcersskin_rashlumpsothers
- Important mapped fields:
ulcers:Id10230,Id10231,Id10232_b,Id10232skin_rash:Id10233,Id10234,Id10235,Id10236lumps:Id10254,Id10255,Id10256,Id10257others:Id10237,Id10238,Id10239,Id10240
- Conditions to appear in left nav:
vaskinmucosalsymptomsmust be present inva_category_list
- Effective trigger rule:
- any surviving field in any skin/mucosal subcategory
vaneonatalfeedingsymptoms
- Nav label:
Neonatal Specific - Route:
/<va_action>/<va_actiontype>/<va_sid>/vaneonatalfeedingsymptoms - Partial:
app/templates/va_formcategory_partials/vaneonatalfeedingsymptoms.html - Partial sections:
feedingphysical_abnormalalityunresponsive
- Important mapped fields:
feeding:Id10271,Id10272,Id10273,Id10274_cphysical_abnormalality:Id10277,Id10278,Id10279unresponsive:Id10281,Id10282,Id10283
- Conditions to appear in left nav:
vaneonatalfeedingsymptomsmust be present inva_category_list
- Effective trigger rule:
- any surviving field in any neonatal-specific subcategory
vamaternalsymptoms
- Nav label:
Maternal - Route:
/<va_action>/<va_actiontype>/<va_sid>/vamaternalsymptoms - Partial:
app/templates/va_formcategory_partials/vamaternalsymptoms.html - Partial sections:
generalpld_trantenataldelivery
- Important mapped fields:
general:Id10296,Id10299,Id10300,Id10301pld_tr:Id10302,Id10303,Id10305,Id10312antenatal:Id10319,Id10317,Id10309,Id10320delivery:Id10337,Id10332,Id10342,Id10343
- Conditions to appear in left nav:
vamaternalsymptomsmust be present inva_category_list
- Effective trigger rule:
- any surviving field in any maternal subcategory
vahealthserviceutilisation
- Nav label:
Health Service Utilization - Route:
/<va_action>/<va_actiontype>/<va_sid>/vahealthserviceutilisation - Partial:
app/templates/va_formcategory_partials/vahealthserviceutilisation.html - Partial sections:
treatmenthcw_codmother_related
- Important mapped fields:
treatment:Id10418,Id10419,Id10420,Id10421hcw_cod:Id10435,Id10436mother_related:Id10446
- Conditions to appear in left nav:
vahealthserviceutilisationmust be present inva_category_list
- Effective trigger rule:
- any surviving field in
treatment,hcw_cod, ormother_related
- any surviving field in
vanarrationanddocuments
- Nav label:
Narration / Documents / COD - Route:
/<va_action>/<va_actiontype>/<va_sid>/vanarrationanddocuments - Partial:
app/templates/va_formcategory_partials/vanarrationanddocuments.html - Partial sections:
narrationdeath_registerationmedical_certsmedical_documentsdeath_documentsiv_final
- Important mapped fields:
narration:narr_language,Id10476_audio,imagenarr,Id10476death_registeration:Id10070,Id10071,Id10072medical_certs:Id10462,Id10463,Id10464,Id10465medical_documents:md_im1tomd_im30death_documents:ds_im1tods_im5iv_final:comment
- Conditions to appear in left nav:
- none beyond being on the coding page; this category is always shown
- Effective trigger rule for actual content:
- any surviving field in the narration/documents mapping will render content
- attachment-backed sections only render if the referenced file exists on disk
- Important mapping nuance:
- site PI mapping includes
death_registeration - coder static mapping omits
death_registeration
- site PI mapping includes
- Important partial behavior:
- the active runtime path now uses
category_attachments.html, not the legacy category-specific partial above - audio fields render as players
- narration image opens in the shared attachments lightbox
medical_documentsanddeath_documentsare seeded with subcategoryrender_mode = media_gallery, which drives their carousel rendering- in coding mode with NQA enabled,
Narrative Quality Assessmentappears immediately beforeSymptoms on VA Interview
- the active runtime path now uses
Current Gaps And Mismatches
vaabdominalsymptomsmapping containsbleeding, but the partial does not render a dedicatedbleedingsectionvanarrationanddocumentshas a subcategory mismatch between site-PI and coder mappings:death_registerationexists only in the site-PI mapping- coder/reviewer category rendering still depends on the static
va_mapping_02_fieldcoder.pydict even though site-PI and preprocess category mapping are now form-type aware - left-nav visibility is derived from stored preprocess output, while panel content is recalculated at request time
Section data cache
The data of a category (summary items, rendered fields, the COD panel evidence)
is built by app/services/case_content_service.py (get_section_data) for
both the web partials and /api/v1/va/<sid>/categories/<code>, and cached in
Redis for 30 minutes under
form_data2:<sid>:<payload_version_id>:<role>:<category> (plus :nopii for a
viewer without PII). The role bucket matters because coder and reviewer views
use the legacy coder field mapping and every other role the DB mapping; the
payload version means a revised interview is never served its old answers.
invalidate_section_data_cache(sid) drops every role and PII variant of the
current version but has no production caller: the payload version in the key is
what stops stale answers after a revision, while mapping or PII-set edits still
wait out the 30-minute TTL.