nhance/public/dev_logs/2026-04-01.md
2026-04-08 12:58:17 +05:30

186 lines
9.9 KiB
Markdown

# Dev Log — 2026-04-01
## NonEbClaimApiController — Bug Fix, Enhancements & API Docs
---
### 1. Fix: JSON Parse 500 Error on `createClaim`
- **Problem:** `getJSON(true)` throws a `500 HTTPException` (Syntax error) when the request body is multipart/form-data (file upload), not JSON.
- **Fix:** Replaced `getJSON(true)` with `json_decode(getBody()) ?? getPost()` so multipart POST data is read correctly without throwing.
### 2. Fix: JSON Parse 500 Error on `listClaims` and `listPolicies`
- **Problem:** Same `getJSON(true)` issue — any malformed or missing JSON body causes a 500 instead of a graceful 400.
- **Fix:** Wrapped `getJSON(true)` calls in `try/catch (\Throwable)` returning a proper `400 Invalid JSON body` response.
### 3. Add: Logging to all API endpoints
Added `myLogger->logme('error', ...)` calls to all 6 endpoints under `employeeRest/api/v1/non-eb-claim` that previously had no log coverage:
| Endpoint | Log event |
|---|---|
| `createClaim` | No ACM found, claim created with ID + user |
| `listClaims` | User + page + total count |
| `claimHistory` | Claim ID + history steps + user |
| `listClaimStatuses` | User + status count |
| `listPolicies` | User + client_md5 + branch + count |
| `uploadRequiredDoc` | Transaction failure + successful upload with doc/file/user |
All log tags follow the pattern `[NON_EB_API][methodName]` for easy log filtering.
### 4. Enhance: `claimHistory` endpoint — full claim detail response
Previously returned only status history array. Now returns 4 keys:
| Key | Source | Description |
|---|---|---|
| `claims_data` | `non_eb_ticket_master` + joins | Major display fields (name, policy, status, surveyor, etc.) |
| `required_docs` | `non_eb_ticket_master.required_docs` (decoded) | IR documents checklist |
| `claims_files` | `claim_files` table | Uploaded documents for this claim |
| `ticket_data` | `ticket_history` table | Claim status change history (renamed from `history`) |
Also removed early-return on empty history so all 4 keys are always present in the response.
---
### Files Changed
- `app/Controllers/Api/NonEbClaimApiController.php`
### API Docs
- `dev_logs/non_eb_claim_api.md`
---
### 5. Change: `uploadRequiredDoc` — rewritten to mirror `uploadIRDocs`
**Old URL:** `POST /api/v1/non-eb-claim/{claim_id}/upload-required-doc`
**New URL:** `POST /api/v1/non-eb-claim/upload-required-doc`
Old function copied as `uploadRequiredDoc_v1` (preserved for reference).
**What changed:**
- Removed `claim_id` from URL; `ticket_id` now comes from POST body
- Switched from single-file (`file` field) to multi-file (`claim_docs[]` field) using `multi_file_Upload`
- Added `claim_doc_names[]` — index-matched names for uploaded files
- `required_docs` JSON string now sent by client and stored directly to `non_eb_ticket_master.required_docs` (no server-side checklist merging)
- Each inserted `claim_files` row now has `docs_for_ir = 1`
- Removed TPA push (`pushClaimFiles` not called)
- Success response simplified to `{status, code, message}`
### Files Changed
- `app/Controllers/Api/NonEbClaimApiController.php`
- `app/Config/Routes.php`
### API Docs
- `nonebapidocs.md`
- `dev_logs/non_eb_claim_api.md`
---
## LeadsController — Bug Fix: `createClientWithLeadData` for Non-EB Leads
### 6. Fix: `prepareClientPolicyData` crashes on Non-EB leads
**Problem:** `proposel_data` is always `null` for Non-EB leads. The function unconditionally did:
```php
$proposel_data = json_decode($data['proposel_data'], true);
list($insurer_branch_id, $insurer_id) = explode('-', $proposel_data['insurer'], 2);
```
This throws a PHP 8 TypeError (cannot access key on null) for any Non-EB lead, making `createClientWithLeadData` silently fail.
**Fix:** Split insurer resolution by `lead_form_type`:
- **EB (`lead_form_type == 1`):** parse insurer from `proposel_data['insurer']` as `"{insurer_branch_id}-{insurer_id}"` — unchanged
- **Non-EB:** read `insurer_id` and `insurer_branch_id` directly from lead row columns
### 7. Fix: `getPlacementJson` null-safety for Non-EB leads
**Problem:** Same null `proposel_data` issue — `json_decode($data['proposel_data'], true)` returned null, and downstream `$proposel_data['proposel_name']` access would crash if a Non-EB lead had QCR data.
**Fix:** `json_decode($data['proposel_data'] ?? '', true) ?? []``proposel_data` is now always an array, so all `??` key accesses are safe.
### Smoke Test Results
| Path | Step | Result |
|---|---|---|
| EB | `proposel_data` decode | ✅ decodes normally |
| EB | `explode('-', proposel_data['insurer'])` | ✅ `insurer_branch_id` + `insurer_id` parsed correctly |
| EB | `preparePolicyTermsFromRFQ` | ✅ unaffected |
| Non-EB | `proposel_data` null → `[]` | ✅ safe |
| Non-EB | insurer from lead row columns | ✅ `insurer_id` + `insurer_branch_id` read directly |
| Non-EB | `getPlacementJson` — no QCR data | ✅ returns null safely, policy terms skipped |
| Non-EB | `getPlacementJson` — QCR data exists | ⚠️ line 4356: `$proposel_data['proposel_name']` missing `??` — pending clarification on whether Non-EB leads can have QCR data |
### Files Changed
- `app/Controllers/LeadsController.php`
## Task Plan — Policy Transaction Inception Form JS Validation
### Goal
Implement client-side form validation for `app/Views/policy_transaction_inception_form.php` by following the existing validation approach used in `app/Views/ticket_form_gmc.php` (centralized submit + reusable validator), but moving inception validation into a dedicated external JavaScript file.
### Current-State Notes
- `policy_transaction_inception_form.php` currently contains inline submit and validation logic on `#inception_form_id` (Parsley validation + custom checks + toastr + AJAX submit flow).
- `ticket_form_gmc.php` follows a cleaner pattern where submit handler delegates validation and shows first invalid field feedback.
- No dedicated inception validation `.js` file currently exists.
### Proposed File Changes
1. **Create** `public/assets/js/policy_transaction_inception_validation.js`
- Add a single public validation entry function (example: `window.validateInceptionFormInputs(form)`).
- Keep all custom rules here (beyond HTML `required` and Parsley):
- `follow_insurer_id[]` must be selected for all rows.
- `pt_form_sumbit_handler` must be `1`.
- CD account selection rule for client/policy status condition.
- Any date/business-rule checks currently done during submit.
- Return a boolean result and handle user-facing messages consistently via toastr.
2. **Refactor** `app/Views/policy_transaction_inception_form.php`
- Keep submit flow in one handler, but delegate custom validations to the new JS file.
- Minimize inline validation logic in view.
- Ensure first invalid field is focused/scrolled for better UX.
- Include the new script after shared dependencies (jQuery/Parsley/toastr), before submit logic usage.
3. **(Optional Cleanup)** Move remaining inline helper validation code to dedicated JS if it is inception-form-specific and not used elsewhere.
### Implementation Steps (Execution Order)
- [x] Step 1: Create new file `public/assets/js/pages/policy_transaction_inception_validation.js`.
- [x] Step 2: Extract custom validation blocks from `#inception_form_id` submit handler into reusable functions.
- [x] Step 3: Expose one callable function for submit handler (`validateInceptionFormInputs`).
- [x] Step 4: Update `policy_transaction_inception_form.php` to include new JS file.
- [x] Step 5: Replace inline custom checks with function call and keep existing AJAX submit behavior unchanged.
- [x] Step 6: Ensure invalid-field focus and warning message are preserved.
- [ ] Step 7: Verify create/edit journeys and conditional sections (renewal, co-insurer, CD account, policy status).
### Validation Rules Checklist (to implement in JS)
- [ ] Parsley base validation must pass.
- [ ] Every `follow_insurer_id[]` select must have value.
- [ ] `pt_form_sumbit_handler != 0`.
- [ ] If `client_type == 1` and `policy_status == completed` and `policy_type_id > 7`, at least one `cd_ac_no_for_child[]` must be selected.
- [ ] Keep existing toastr wording (or align to one consistent warning style).
### Testing Checklist
- [ ] Submit with empty required fields -> blocked with field-level indication.
- [ ] Submit with any empty co-insurer selector -> blocked with warning.
- [ ] Submit with base premium/CD mismatch (`pt_form_sumbit_handler = 0`) -> blocked.
- [ ] Submit valid data -> AJAX create request fires successfully.
- [ ] Edit existing inception record -> validation still works and submit succeeds.
- [ ] No regression in date conversion before submit (`policy_issue_date`, `policy_start_date`, `policy_end_date`, `renewal_date`, `rollover_date`, `month`).
### Risks / Attention Points
- Large inline script currently mixes validation and business logic; refactor should avoid changing API payload or field names.
- Multiple dynamic rows (`follow_insurer_id[]`, `cd_ac_no_for_child[]`) need delegated-safe selectors.
- Script include order is critical (new validation JS must load before submit handler executes).
### Completion Update (Implemented)
- Added `public/assets/js/pages/policy_transaction_inception_validation.js` with:
- `window.validateInceptionFormInputs(form)` as centralized entrypoint
- Parsley validation gate
- Co-insurer (`follow_insurer_id[]`) mandatory selection check
- `pt_form_sumbit_handler` (CD amount) guard check
- Child CD account selection rule for applicable completed flow
- First invalid field focus/scroll helper
- Updated `app/Views/policy_transaction_inception_form.php`:
- Included external script: `assets/js/pages/policy_transaction_inception_validation.js`
- Refactored `#inception_form_id` submit handler to delegate custom validation to new file
- Preserved existing AJAX submit and payload/date conversion behavior
- Technical validation done:
- JS syntax check passed (`node --check public/assets/js/pages/policy_transaction_inception_validation.js`)