# AutoDecision Flow Documentation This document outlines the entire architectural flow and execution trace of the **AutoDecision (AutoBRE)** feature, starting from the application trigger points to the evaluation executed by the JSON BRE engine. ## 1. Trigger Point: Consent & Data Submission The auto-decision flow begins its lifecycle typically at the points of consent submission or complete application saving. - **Trigger Files**: `app/Http/Controllers/ConsentController.php`, `app/Http/Controllers/Admin/ConsumerApplicationController.php`, `app/Http/Controllers/ApiController.php`. - **Pre-Conditions for Trigger**: Before dispatching the event, several conditions are rigorously evaluated: - **Required Data Check**: Validates that minimum required parameters (e.g., `employee_status`, `monthly_income`, `power_savings`) are present. - **Data Point Evaluation**: Calls `$autoBRE->checkDataPoints($id, $request)` to ensure the integrity and completeness of the submitted form details. - **Merchant Eligibility**: Queries the `merchant` table to ensure the merchant has a defined `grade_id` and has enabled at least one of: `is_auto_approve`, `is_auto_doc`, or `pre_approval`. - **State-Specific Document Constraints**: If the application is in the `waiting for documents` state, it checks the `mandatory_document_list` inside `ConsumerApplicationElement`. If the pending documents contain items *other* than `consent_logs` or `co_app_consent_logs` (e.g., operational docs like electricity bills or bank statements), it specifically bypasses the AutoDecision queue (`$triggerAutoDecision = false`) and directly routes to a pure Rejection BRE evaluation (`autoReject()`). - **Duplicate Prevention**: Queries `QueueLog` to verify a job with `command:AutoDecision` for the specific `applicant_type` doesn't already exist. - **Action**: If all constraints pass, the system queues the event. ```php event(new EventAutoDecision(['id' => $application->id, 'applicant_type' => $applicant_type])); ``` ## 2. Event Listener & Queue Logging (`ListenerAutoDecision`) Instead of running heavy operations synchronously and blocking the user request, the application relies on an asynchronous event-driven architecture powered by RabbitMQ. - **Listener File**: `app/Listeners/V1/ListenerAutoDecision.php` - **Action**: The `handle(EventAutoDecision $event)` method intercepts the event and persists it into the `QueueLog` database table. - **Detailed Execution**: - It constructs a `$request_data` payload array containing: `'cmd' => 'command:AutoDecision'`, `'con' => 'jobs'`, and the `param` array containing the `id` and `applicant_type`. - It extracts predefined RabbitMQ configurations (e.g., `job_handler`, `job_exch`, `exch_rout_key_job`) from config `constants.rabbitmq`. - Executes `QueueLog::create([...])` binding the JSON payload to the queue. This effectively acts as the producer, letting a background worker consume and execute it. ## 3. Asynchronous Job Execution (`AutoDecision` Command) A backend worker polls the RabbitMQ channels / database queue and launches the Artisan command corresponding to the logged job. - **Command File**: `app/Console/Commands/AutoDecision.php` - **Detailed `handle()` Execution**: 1. **Initialization & Logging**: Fetches `$id` and `$applicant_type` from the passed parameters and starts a CloudWatch log entry (`AutoDecisionQueueLog`). 2. **MERCHANT API Pre-computation (LTV Bootstrapping)**: If the application was sourced via the `MERCHANT API` (where offer mappings are strict), it immediately instantiates `GradeController::calculateLTV()`. It computes detailed LTV metrics (e.g., `ltv_gross_project_amount`, `ltv_net_loan_amount`, `loan_amount`), saves these against `ConsumerApplicationAdditional`, pushes a historical record to `ContentLogger`, and adds an internal comment detailing the LTV breakdown before handing off to the BRE. 3. **Co-applicant Route (`applicant_type == 2`)**: - Immediately calls `generateSoftBureauReport($id, 'autoBRE', 2, false)` explicitly for the co-applicant. - If the report fails (due to missing consent or bureau errors), it halts further execution. Co-applicants are processed strictly to ensure their data exists before the main applicant is evaluated. 4. **Applicant Route (`applicant_type == 1`)**: - Calls `generateSoftBureauReport($id, 'autoBRE', 1, $runBRE)`. - Upon a successful bureau pull, provided the application isn't strictly flagged as `rejected` or `pre_approved`, it pushes through to post-evaluation hooks. - **Proforma Update**: Calls `$consumerApplicationController->updateProforma($id)`. - **Rule Validation Check**: Calls `$this->getApprovedRules($id)` which queries `jsonbre_approval_status_log` to verify if the latest executed rule batch returned a successful approval (`status = 1`). - **State Overrides & Resolution**: - *SSE Merchant Special Flow*: If the merchant belongs to a designated SSE group, it routes to `sseSetStatus()`. This complex sub-routine evaluates fuzzy-matching scores between the E-bill names and the applicant/co-applicant names. Depending on the matching percentage thresholds, it can push the application to `waiting for documents` (and append `electricity_bill` or `bank_statement` to the mandatory checklist), `waiting for decision`, or fully `approved`. - *Standard Flow*: Applications that pass all rules are cleanly moved to `approved` (or `cf approved` for multi-lender routing). - Persists the final state utilizing `$consumerApplicationController->updateStatus($id, true)`. ## 4. Soft Bureau Report Generation & Hand-off The actual fetching of Experian/Crif credit data happens within a controller helper that acts as a hard gatekeeper for compliance. - **File**: `app/Http/Controllers/Admin/ConsumerApplicationController.php` (Method: `generateSoftBureauReport`) - **Detailed Execution**: - **Consent Validation**: Determines the specific variables (`consent_logs` vs `co_app_consent_logs`) depending on `$applicantType`. It checks if a physical log file exists in `ConsumerApplicationFiles` or if the equivalent boolean flag (`is_consent` or `is_co_app_consent`) was activated in `ConsumerApplicationElement` (often set by MConnect webhooks). - **Short-circuiting**: If consent is entirely missing, it completely aborts the pull, returning a direct `FAIL` response: `"Please get applicant/Co-Applicant consent."` - **Data Formatting**: Checks if a valid `credit_report` already exists. If not, constructs the `$bureauData` array. This includes splitting the full name into `first_name` and `last_name`, fetching the specific `pan_card`, injecting the `mobile_number`, setting the vendor, and handling the `skip_pan_validation` flags. - **API Execution**: Once the payload is ready, the system fires off the API call to the respective bureau partner. - Assuming the report generates correctly (or already existed), the logic falls back up. For main applicants with `$runBre` set to `true`, the process cascades into the `runAutoDecisionAlgorithm`. ## 5. Auto-Decision Algorithm Orchestration With validated consent, calculated metrics, and pulled bureau reports, the algorithmic mapping commences. - **File**: `app/Http/Controllers/Admin/ConsumerApplicationController.php` (Method: `runAutoDecisionAlgorithm`) - **Detailed Execution**: - **State Gatekeeping**: Immediately skips evaluating any application already carrying an `aborted` or `rejected` state. - **Controller Mapping**: Instantiates `GradeController($request)` which acts as the algorithmic bridge. - **Approved Initializations**: If the application's underlying status map points to `approved`, it directly calls `$gradeController->autoApproveInit($id, $isLog)`. This acts as the entry point into the comprehensive evaluation logic bridging to JSON BRE. - **Pre-Approval Handling**: If identified as `pre approved`, it leverages `pre_approvalCheck()`, initiates auto-documentation rules (`initAutoDocumentation`), forcefully overrides the application state to `pre approved`, logs to `StatusLogs`, and triggers communication APIs (SMS/Email) to inform the user of their pre-approval status. - **Fallback Document Routing**: If standard rules do not pass a definitive state but aren't rejected either, it calls `$gradeController->initAutoDocumentation()` and cleanly returns `false` which generally moves the application into a `waiting for decision` bucket for manual underwriter review. ## 6. Execution within the JSON BRE Engine `GradeController` bridges the application logic with the core JSON BRE Engine which computes the actual decisions. - **Trigger Files**: `app/Http/Controllers/Grade/GradeController.php` - **Engine File**: `app/Http/Controllers/JsonBREController.php` - **Action**: - **Approval Flow**: `GradeController::MultiApprovalCheckJSONBRE()` gathers all application variables, merges additional properties (like `account_aggregator_id`, LTV), and feeds them to `JsonBREController::runJsonBreApproval()`. - **Rejection Flow**: If bypassing standard approval (e.g., due to specific missing documents), Rejection BRE is triggered via `AutoRejection::autoReject()` leading to `JsonBREController::runRejection()`. - **JSON BRE Execution**: Inside `JsonBREController`, the generic `runAutoDecisionBRE($payload)` constructs the final JSON payload and executes the rule policies based on the specific merchant/application grade. - **Response Storage**: The response (decisions, passes, fails) is logged immutably into the `jsonbre_approval_status_log` table via `store_jsonbre_response()`. - **Conclusion**: `GradeController` evaluates the logged responses, constructs the `loan_decision_table` (via `saveDecisionInTable()`), and hands the decision back to the `AutoDecision` command to finalize the application state update.