# 2026-04-06 — OPD Policy Terms Plan (`policy_type_id = 72`) ## Context - Policy type: `72` - Policy terms label: `OPD Policy Terms` - Requested fields/content: - `Mode of Serviceability` - `Eligibility` - `Total Sum Insured limit - INR 15000` - `In Person Doctor Consultation` - `Prescribed Lab test (Pathology & Radiology)` - `Prescribed Pharmacy` - `Dental` - `Vision` - `Vaccination for children & adults` - Target view: `app/Views/other_policy_terms.php` ## Problem Identified - OPD fields were visible in UI but not saved to DB for `policy_type_id = 72`. - Root cause: `app/Controllers/ClientController.php` in `otherPolicyTermsFormSubmit()` uses a strict field mapping for policy `72` and did not include the newly added OPD keys. - Impact: Submitted payload contained OPD fields, but controller dropped them before `policy_terms` JSON update. ## Fix Plan 1. Update `policy_type_id = 72` save mapping - Add OPD keys to `$data` construction in `otherPolicyTermsFormSubmit()`. - Include defaults where applicable (`total_sum_insured_limit` fallback to `INR 15000`). 2. Keep existing family floater/age mapping unchanged - Preserve current business logic for `family_floater`, `family_floaters`, and `age_ratio`. - Add OPD terms in additive mode only. 3. Validate controller integrity - Run PHP syntax check for `ClientController.php`. - Confirm no changes to unrelated policy type save flow. ## New Requirement Plan - `_display` Checkbox -> `enrollment_display_key` for `other_policy_terms` ### Reference behavior (from `app/Views/policy_gmc_terms.php`) - Each term row includes a checkbox with `name` ending in `_display`. - Only checked display keys are reflected in `enrollment_display_key`. - Existing loader flow reads `enrollment_display_key` and restores checkbox states. ### Problem to solve in `other_policy_terms` - For policy type `72`, OPD fields currently do not have `*_display` checkboxes. - In controller, `otherPolicyTermsDisplayKeyConstruct()` currently builds `enrollment_display_key` only from special condition label/input pairs, not from `*_display` checkboxes. - Result: checkbox-driven display selection is not persisted/reloaded for OPD terms. ### Implementation plan 1. Add `*_display` checkboxes to OPD rows in `app/Views/other_policy_terms.php` - For each OPD field (`mode_of_serviceability`, `eligibility`, `total_sum_insured_limit`, etc.), add a checkbox input: - `name="_display"` - `id="_display"` - class `unchecked` - default checked - Keep checkbox + label + value input row layout aligned with existing non-72 dynamic term rows. 2. Update `otherPolicyTermsDisplayKeyConstruct()` in `app/Controllers/ClientController.php` - Extend logic to parse all incoming keys ending with `_display`. - For each checked display key, map base key to human-readable label and value from the corresponding base field. - Preserve current special-condition mapping behavior; merge both outputs into one `enrollment_display_key`. 3. Keep save flow backward compatible - Do not alter existing `policy_type_id == 72` family floater and age mapping. - Ensure OPD values and `enrollment_display_key` are both saved in `policy_terms`. - Keep non-72 flow unchanged. 4. Restore checkbox states on load - Reuse existing `processJsonObject`-style behavior in `other_policy_terms` (if missing, add equivalent) to set `*_display` checked state based on `enrollment_display_key`. - Verify for both newly created and previously saved records. 5. Validate end-to-end - Save with mixed checked/unchecked OPD display checkboxes. - Confirm DB JSON includes expected `enrollment_display_key` entries. - Reload and verify display checkbox states are restored. ## Implementation Plan 1. Place OPD terms section immediately after `familyFloaterDiv_others_two` - Keep `familyFloaterDiv_others_two` as the first visible block for policy `72`. - Insert OPD terms container directly below it in the DOM order (not before it). - Ensure the OPD section appears before special conditions. 2. Add OPD-specific policy terms UI block - Add dedicated OPD template/HTML for `policy_type_id = 72`. - Render OPD rows as labeled text inputs with stable keys (`mode_of_serviceability`, `eligibility`, etc.). - Keep field names in snake_case so they serialize cleanly into `policy_terms` JSON. 3. Handle fixed sum insured limit cleanly - Add a separate OPD field key like `total_sum_insured_limit`. - Set default value as `15000` (or `INR 15000` based on UI format) for new entries. - Keep numeric sanitization consistent with existing sum insured input behavior where applicable. 4. Preserve existing `policy_type_id = 72` family floater behavior - Do not remove current family floater section/logic already tied to `policy_type_id == 72`. - Ensure OPD terms are additive and do not break `family_floater`, `family_floaters`, and `age_ratio` handling. 5. Populate saved data on edit - Reuse existing JSON hydration flow (`Object.keys(jsonObject)` loop) so OPD fields auto-populate by `name`. - Confirm keys in UI match keys stored in policy terms JSON exactly. 6. Validate display behavior - Confirm form section opens for `policy_type_id > 5`. - Confirm non-72 cleanup (`if(policy_type_id != 72)`) does not remove OPD fields when policy type is 72. - Confirm OPD fields are not rendered for unrelated policy types. - Confirm visual order is `familyFloaterDiv_others_two` -> OPD terms -> special conditions. 7. QA checklist - Create a new policy terms record for `policy_type_id = 72` with all OPD values. - Reload and verify values repopulate correctly. - Verify submit and autosave payload include OPD keys in `policy_terms`. - Verify no regressions for policy types `6` and `7`. ## Suggested Field Keys - `mode_of_serviceability` - `eligibility` - `total_sum_insured_limit` - `in_person_doctor_consultation` - `prescribed_lab_test_pathology_radiology` - `prescribed_pharmacy` - `dental` - `vision` - `vaccination_for_children_and_adults` ## Tasks - [x] Place OPD section after `familyFloaterDiv_others_two` in UI order. - [x] Add `policy_type == 72` OPD HTML block in `appendPolicyTermsHTML()`. - [x] Ensure defaults are applied for total sum insured limit. - [x] Verify bind/populate works from existing JSON loader. - [x] Fix OPD term persistence in `ClientController::otherPolicyTermsFormSubmit()` for `policy_type_id = 72`. - [x] Add temporary debug logging for OPD72 save payload in controller. - [x] Add `*_display` checkboxes for OPD term rows in `other_policy_terms.php`. - [x] Extend `otherPolicyTermsDisplayKeyConstruct()` to include checked `*_display` keys. - [x] Ensure `enrollment_display_key` restores OPD checkbox states in `other_policy_terms.php`. - [ ] Verify DB `policy_terms.enrollment_display_key` for mixed checked/unchecked OPD fields. - [ ] Run manual UI verification for create/edit/submit/autosave. - [x] Confirm no regressions for other policy types (code-level condition check and syntax validation completed). - [ ] Remove temporary debug logging after verification. ## Verification Notes - PHP syntax check passed for `app/Views/other_policy_terms.php` (`php -l`). - PHP syntax check passed for `app/Controllers/ClientController.php` (`php -l`). - Verified `policy_type_id == 72` now renders OPD fields in both create and edit flows. - Verified OPD fields are now rendered in a dedicated container placed after `familyFloaterDiv_others_two`. - Verified non-`72` cleanup blocks remain scoped (`sumInsuredDiv`/family floater removals are still excluded for `72`). - Added temporary controller debug log (`OPD72 save payload`) to confirm persisted key/value mapping during manual test. - Added OPD `*_display` checkboxes and controller mapping so checked fields are now included in `enrollment_display_key`. - Added `processOtherEnrollmentDisplayKey()` in `other_policy_terms.php` to restore OPD display checkbox states from saved `enrollment_display_key`. - Manual browser verification is still required for submit + autosave end-to-end confirmation.