# Case Review Workflow for Disbursement Query --- ## Ticket Implementation — 2026-05-26 ### Overview Implemented a complete "Request Case Review" and "Reply for Case Review" workflow for consumer applications currently in the "Disbursement Query" status. The goal is to allow admin users to raise specific queries regarding an application's disbursement and mandate that these queries are either approved or rejected by an authorized user before the application can proceed to the "Query Resolved" status. --- ### Business Rules - **State Gating (Visibility)**: The "Disbursement Query Case Review" (Submit Request) and "Reply for Case Review" options should only be visible in the application list dropdown when the application is actively in the `Disbursement Query` state. - **Request Submission**: Users can submit one or more "reasons" for the review in a single modal. - **Reply/Resolution**: Users with appropriate permissions can view the history of requests and must respond to any `PENDING` requests with a mandatory response message, selecting either "Approve" or "Reject". - **Status Locking**: On the application edit page, if there are any `PENDING` case review requests, the "Query Resolved" status option is completely locked/disabled. Only once all pending requests are handled (Approved/Rejected) does the option unlock. --- ### Logic Added #### Frontend (Blade & JavaScript) `resources/views/admin/consumer-application/index.blade.php` - Added the dropdown options under strict state-gates (`strtolower($consumer_application->state) == 'disbursement query'`). - Integrated two new Bootstrap modals: `#case_review_request_modal` (with dynamic multi-input rows) and `#reply_case_review_modal`. - Added jQuery AJAX handlers to send request payloads securely via POST and dynamically re-render the list of queries upon approval/rejection. `resources/views/admin/consumer-application/edit_v1.blade.php` - Added logic to evaluate `$caseReviewPendingCount`. If greater than zero, the "Query Resolved" status is visually disabled with a descriptive tooltip indicating the number of pending replies. #### Backend Controllers & Models `CaseReviewRequest.php` (Model) - Added two static helper methods: `getAppIdsWithRequests($appIds)` and `getPendingCountsForApps($appIds)` to encapsulate the raw DB aggregation queries. `ConsumerApplicationController.php` (Controller) - **`submitCaseReviewRequest`**: Validates the payload and application state, then batch inserts multiple review reasons into the `CaseReviewRequest` database table with the `PENDING` status. - **`getCaseReviewRequests`**: Fetches and formats the list of case review requests for a specific application to be rendered in the Reply modal. - **`respondCaseReviewRequest`**: Handles the approval/rejection action for a specific request ID, logging the response message, response time, and the responding user's ID. - **`index` / `edit` modifications**: Adjusted data fetching to calculate the pending case review counts efficiently to pass down to the Blade templates for state gating. Relies cleanly on the newly created `CaseReviewRequest` model static methods for `index()`. Included try/catch defensive programming around fragile `AvanseServices` calls in `edit()` to prevent 500 errors. #### Helpers `CustomHelpers.php` - Updated `wall_decrypt` to safely handle non-encrypted plaintext strings without throwing `openssl_decrypt` and `hash_equals` warnings by checking the payload length against the cipher IV length. --- ### Impact — Files Changed / Added | File | Type | Change | |------|------|--------| | `resources/views/admin/consumer-application/index.blade.php` | Modified | Added modals, AJAX JS, and dropdown buttons for the Case Review workflow. | | `resources/views/admin/consumer-application/edit_v1.blade.php` | Modified | Added `$caseReviewPendingCount` checks to disable the "Query Resolved" status option. | | `app/Http/Controllers/Admin/ConsumerApplicationController.php` | Modified | Added API endpoints (`submitCaseReviewRequest`, `getCaseReviewRequests`, `respondCaseReviewRequest`) and updated `edit`/`index` methods with necessary context data and try-catch blocks. | | `app/Helpers/CustomHelpers.php` | Modified | Patched `wall_decrypt` to silently fail on plaintext strings to resolve PHP warnings. | | `playwright-cf/test-case-review.js` & `test-case-review-negative.js` | Added (Local) | Implemented full E2E positive and negative testing suites for the workflow to ensure data validation, UI alerts, and API state-gates. | ---