nhance/app/Controllers/InsuranceCommissionController.php
2025-11-14 15:30:23 +05:30

275 lines
8.8 KiB
PHP

<?php
namespace App\Controllers;
use CodeIgniter\Controller;
use CodeIgniter\API\ResponseTrait;
class InsuranceCommissionController extends AdminController
{
use ResponseTrait;
private $rules = [];
public function __construct()
{
set_session_context('Client');
$this->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 = ucfirst(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());
}
// Normalise department keys to lowercase for consistent lookups
$this->rules = [];
foreach ($parsed as $dept => $rules) {
$this->rules[strtolower($dept)] = $rules;
}
}
public function calculateCommission(array $policyData)
{
$department = $policyData['department'] ?? '';
$deptKey = strtolower($department);
if (!isset($this->rules[$deptKey])) {
throw new \Exception("No rules found for department: {$department}");
}
$matchingRules = [];
foreach ($this->rules[$deptKey] as $rule) {
if ($this->evaluateConditions($rule['conditions'] ?? [], $policyData)) {
$matchingRules[] = $rule;
}
}
if (empty($matchingRules)) {
throw new \Exception('No matching rules found for the policy data');
}
// 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
{
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;
}
}