myLogger = \Config\Services::mylogger(); // Load rules file if present in writable config path // $rulesPath = WRITEPATH . 'config/insurance_rules.json'; // if (file_exists($rulesPath)) { // $this->loadRulesFromFile($rulesPath); // } } /** * POST /insurance/calculate * Accepts JSON body with policy data and returns commission calculation */ public function initiateCommissionCalc() { // Accept POST params (JSON, form-data, x-www-form-urlencoded) $input = $this->request->getPost(); if (empty($input)) { $json = $this->request->getJSON(true); if ($json) { $input = $json; } } if (empty($input)) { return $this->failValidationError('No input data received'); } // -------- Required Params Check -------- if (empty($input['policy_issue_date'])) { return $this->failValidationError('policy_issue_date is required'); } if (empty($input['department'])) { return $this->failValidationError('department is required'); } if (empty($input['insurer_id'])) { return $this->failValidationError('insurer_id is required'); } // -------- Build Dynamic Rules Path -------- $policyDate = strtotime($input['policy_issue_date']); if (!$policyDate) { return $this->failValidationError('Invalid policy_issue_date'); } $month = strtoupper(date('M', $policyDate)); // SEP $year = date('Y', $policyDate); // 2025 $folderName = $month . $year; // SEP2025 $insurerId = $input['insurer_id']; // 5 $department = (strtolower($input['department'])); // Motor, Health, Fire // Final Path: WRITEPATH/rules/SEP2025/5_Motor.json $rulesPath = WRITEPATH . "uploads/commission/rules/{$folderName}/{$insurerId}_{$department}.json"; // echo $rulesPath;die(); if (!file_exists($rulesPath)) { return $this->fail("Rules file not found at: {$rulesPath}"); } // Load the dynamic rule set $this->loadRulesFromFile($rulesPath); // -------- Execute Rule Matching & Commission Calculation -------- try { $result = $this->calculateCommission($input); $comment = isset($result['rule']['name']) ? "Matched rule: " . $result['rule']['name'] : "Matched rule: (unnamed rule)"; return $this->respond([ 'success' => true, 'data' => [ 'payout' => $result['payout'], 'rule' => $result['rule'], 'comment' => $comment, // 'rules_path_used' => $rulesPath ] ]); } catch (\Exception $e) { return $this->fail($e->getMessage()); } } /** * Load rules JSON and normalise department keys to lowercase for lookups */ private function loadRulesFromFile(string $filePath) { if (!file_exists($filePath)) { throw new \Exception("Rules file not found: {$filePath}"); } $json = file_get_contents($filePath); $parsed = json_decode($json, true); if (json_last_error() !== JSON_ERROR_NONE) { throw new \Exception('Invalid JSON in rules file: ' . json_last_error_msg()); } // print_r($parsed);die(); // Normalise department keys to lowercase for consistent lookups $this->rules = []; foreach ($parsed as $dept => $rules) { if($rules['is_deleted'] === false) { $this->rules[strtolower($dept)] = $rules; } } // print_r($this->rules);die(); } public function calculateCommission(array $policyData) { $department = $policyData['department'] ?? ''; $deptKey = strtolower($department); // print_r($this->rules);die(); // if (!isset($this->rules[$deptKey])) { // throw new \Exception("No rules found for department: {$department}"); // } $matchingRules = []; foreach ($this->rules as $rule) { if ($this->evaluateConditions($rule['conditions'] ?? [], $policyData)) { $matchingRules[] = $rule; } } if (empty($matchingRules)) { throw new \Exception('No matching rules found for the policy data'); } // print_r($matchingRules);die; // Use the first matching rule. In future you can implement priority/weighting $applicableRule = $matchingRules[0]; $payout = $this->applyCalculation($applicableRule['calculation'], $policyData); return ['rule' => $applicableRule, 'payout' => $payout]; } private function evaluateConditions(array $conditions, array $data): bool { foreach ($conditions as $condition) { $field = $condition['field']; $operator = $condition['operator']; $expectedValue = $condition['value']; if (!array_key_exists($field, $data)) { return false; } $actualValue = $data[$field]; if (!$this->compareValues($actualValue, $operator, $expectedValue)) { return false; } } return true; } private function compareValues($actual, string $operator, $expected): bool { $actual = strtolower($actual); $expected = strtolower($expected); switch ($operator) { case '==': return $actual == $expected; case '!=': return $actual != $expected; case '>': return $actual > $expected; case '>=': return $actual >= $expected; case '<': return $actual < $expected; case '<=': return $actual <= $expected; case 'between': return is_array($expected) && $actual >= $expected[0] && $actual <= $expected[1]; case 'in': return is_array($expected) && in_array($actual, $expected); default: throw new \Exception("Unsupported operator: {$operator}"); } } private function applyCalculation(array $calculation, array $policyData) { $type = $calculation['type'] ?? null; switch ($type) { case 'percentage': $percentage = $calculation['value'] ?? 0; $base = $calculation['on'] ?? null; if ($base === null || !isset($policyData[$base])) { throw new \Exception("Base value for calculation not found: {$base}"); } return ($percentage / 100) * $policyData[$base]; case 'composite': $total = 0; foreach ($calculation['components'] as $component) { $percentage = $component['percentage'] ?? 0; $base = $component['on'] ?? null; if ($base === null || !isset($policyData[$base])) { throw new \Exception("Base value for calculation not found: {$base}"); } if (!empty($component['only_first_year'])) { if (!empty($policyData['is_renewal'])) { continue; // Skip this component for renewals } } $total += ($percentage / 100) * $policyData[$base]; } return $total; case 'fixed': $fixedAmount = $calculation['value'] ?? 0; // If 'on' specified but not needed, return fixed amount as-is return $fixedAmount; default: throw new \Exception('Unsupported calculation type: ' . $type); } } public function getVolumeReward(array $premiumData) { $annualPremium = $premiumData['annual_premium'] ?? 0; $department = $premiumData['department'] ?? ''; if ($department === 'Fire' || $department === 'Marine' || $department === 'Engineering') { if ($annualPremium > 20000000) { return 0.01 * $annualPremium; } elseif ($annualPremium > 10000000) { return 0.005 * $annualPremium; } elseif ($annualPremium > 5000000) { return 0.0025 * $annualPremium; } } elseif ($department === 'Motor') { if ($annualPremium > 15000000) { return 0.02 * $annualPremium; } elseif ($annualPremium > 7500000) { return 0.01 * $annualPremium; } } return 0; } }