From c5c1822813e917d3552ebf924ab4a97da715039e Mon Sep 17 00:00:00 2001 From: "sanjeev.p" Date: Thu, 9 Apr 2026 09:19:16 +0530 Subject: [PATCH] FIX_GRID --- app/Controllers/AgentIncentiveController.php | 45 ++--- app/Libraries/PartnerPayoutGridRetention.php | 171 ++++++++++--------- 2 files changed, 111 insertions(+), 105 deletions(-) diff --git a/app/Controllers/AgentIncentiveController.php b/app/Controllers/AgentIncentiveController.php index 03a0bf6..f14737d 100644 --- a/app/Controllers/AgentIncentiveController.php +++ b/app/Controllers/AgentIncentiveController.php @@ -539,6 +539,7 @@ class AgentIncentiveController extends ResourceController // List all grid records (optional utility endpoint) // ------------------------------------------------------------------------- // GET /grid?role=Manager means all list (optional insurer, rto, segment, vehicle_type) + // GET /grid?role=Manager means all list (optional insurer, rto, segment, vehicle_type) public function getGridData() { try { @@ -555,32 +556,33 @@ class AgentIncentiveController extends ResourceController ], 400); } - // 2. Extract Filters + // 2. Agent requires logged_id + if (strtolower(trim((string) $role)) === 'agent') { + $agentId = (int) trim((string) ($request->getGet('logged_id') ?? $request->getGet('agent_id') ?? 0)); + if ($agentId <= 0) { + return $this->respond([ + 'status' => 'failed', + 'code' => 400, + 'data' => 'logged_id is required for Agent role.' + ], 400); + } + } + + // 3. Extract Filters $insurer = trim((string) ($request->getGet('insurer') ?? '')); $rto = trim((string) ($request->getGet('rto') ?? '')); $segment = trim((string) ($request->getGet('segment') ?? '')); $vehicle_type = trim((string) ($request->getGet('vehicle_type') ?? '')); $search = trim((string) ($request->getGet('search') ?? '')); - // ── 3. Resolve file_id based on role ───────────────────────────────── + // ── 4. Resolve file_id ──────────────────────────────────────────────── $db = \Config\Database::connect(); - if (in_array($role, ['Manager', 'Accounts'], true)) { - - // Manager / Accounts: file_id must be supplied in query param - if (empty($file_id)) { - return $this->respond([ - 'status' => 'failed', - 'code' => 400, - 'data' => 'file_id is required for Manager / Accounts role.' - ], 400); - } - + if (!empty($file_id)) { + // If file_id is explicitly passed (any role), use it directly $resolvedFileId = (int) $file_id; - } else { - - // Agent: find the latest id from partner_agent_incentive_file (no agent filter needed) + // No file_id supplied — resolve latest from table (all roles) $fileRow = $db->table('partner_agent_incentive_file') ->select('id') ->orderBy('id', 'DESC') @@ -599,12 +601,12 @@ class AgentIncentiveController extends ResourceController $resolvedFileId = (int) $fileRow['id']; } - // ── 4. Build Grid Query ─────────────────────────────────────────────── + // ── 5. Build Grid Query ─────────────────────────────────────────────── $builder = $this->PayoutGridModel->builder(); $builder->where('partner_agent_incentive_file_id', $resolvedFileId); $builder->orderBy('vehicle_type', 'ASC')->orderBy('insurer', 'ASC'); - // Apply filters for every role on the same resolved file. + // Apply filters if ($insurer !== '') { $builder->where('insurer', $insurer); } @@ -631,7 +633,6 @@ class AgentIncentiveController extends ResourceController $builder->select('id, insurer, vehicle_type, segment, rto, comp, tp, od, fuel, broker_name, remarks, broker_comp, broker_tp, broker_od, created_by, created_at, updated_by, updated_at'); - } else { // Agent $builder->select('id, insurer, vehicle_type, segment, rto, comp, tp, od, fuel, @@ -639,7 +640,7 @@ class AgentIncentiveController extends ResourceController partner_agent_incentive_file_id, created_at, updated_at', false); } - // ── 5. Execute (once) ───────────────────────────────────────────────── + // ── 6. Execute ──────────────────────────────────────────────────────── $gridResults = $builder->get()->getResultArray(); if (empty($gridResults)) { @@ -650,7 +651,7 @@ class AgentIncentiveController extends ResourceController ], 404); } - // ── 6. Role-based post-processing ───────────────────────────────────── + // ── 7. Role-based post-processing ───────────────────────────────────── if (in_array($role, ['Manager', 'Accounts'], true)) { $gridResults = PartnerPayoutGridRetention::applyManagerAccountsDisplayToRows($gridResults); } @@ -675,7 +676,7 @@ class AgentIncentiveController extends ResourceController } } - // ── 7. Respond ──────────────────────────────────────────────────────── + // ── 8. Respond ──────────────────────────────────────────────────────── return $this->respond([ 'status' => 'success', 'code' => 200, diff --git a/app/Libraries/PartnerPayoutGridRetention.php b/app/Libraries/PartnerPayoutGridRetention.php index 8e129cb..2d492a0 100644 --- a/app/Libraries/PartnerPayoutGridRetention.php +++ b/app/Libraries/PartnerPayoutGridRetention.php @@ -8,7 +8,6 @@ class PartnerPayoutGridRetention { /** * Fetch PRR rows with vehicle_type AND segment joined. - * Now includes segment_id for per-segment RR matching. */ private static function fetchPrrPvtRows(BaseConnection $db, int $agentId): array { @@ -20,7 +19,7 @@ class PartnerPayoutGridRetention ->select('prr.vehicle_type_id, prr.segment_id, prr.retention_rate, vt.vehicle_type, seg.segment') ->join('vehicle_type vt', 'vt.id = prr.vehicle_type_id', 'left') - ->join('partner_segment seg', 'seg.id = prr.segment_id', 'left') // join segment table + ->join('partner_segment seg', 'seg.id = prr.segment_id', 'left') ->where('prr.agent_id', $agentId) ->where('prr.is_active', 1) ->get() @@ -44,18 +43,14 @@ class PartnerPayoutGridRetention } /** - * Build meta map keyed by: - * 1. "vt::{normalizedVehicleType}::seg::{normalizedSegment}" ← most specific - * 2. "vt::{normalizedVehicleType}" ← fallback (no segment) - * 3. "id::{vehicle_type_id}::seg::{segment_id}" ← by IDs - * 4. "id::{vehicle_type_id}" ← by VT id only + * Build meta map keyed by vt+segment combinations for resolution. */ private static function partnerMetaMapFromPrrRows(array $prrRows): array { $meta = []; foreach ($prrRows as $r) { - if (!array_key_exists('retention_rate', $r) - || $r['retention_rate'] === null + if (!array_key_exists('retention_rate', $r) + || $r['retention_rate'] === null || $r['retention_rate'] === '') { continue; } @@ -82,7 +77,6 @@ class PartnerPayoutGridRetention // Key 2: vt only (text fallback) if ($normVt !== '') { - // Only set if not already set (more specific wins) $meta["vt::{$normVt}"] = $meta["vt::{$normVt}"] ?? $entry; } @@ -123,12 +117,8 @@ class PartnerPayoutGridRetention return $out; } - /** - * Build segment label → id map for resolving grid segment text to segment_id. - */ public static function buildMasterNormSegmentToIdMap(BaseConnection $db): array { - // Adjust table/column name to match your actual segment table $rows = $db->table('partner_segment') ->select('id, segment') ->where('is_active', 1) @@ -172,7 +162,6 @@ class PartnerPayoutGridRetention $vid = isset($row['vehicle_type_id']) ? (int) $row['vehicle_type_id'] : 0; $sid = isset($row['segment_id']) ? (int) $row['segment_id'] : 0; - // Try to resolve IDs from master maps if not on the row if ($vid <= 0 && $masterNormLabelToVtId !== null && $normVt !== '') { $vid = $masterNormLabelToVtId[$normVt] ?? 0; } @@ -209,31 +198,31 @@ class PartnerPayoutGridRetention } /** - * Agent payout: partner_RR − base value. - * e.g. RR=1.0, comp=7.2 → 1.0 - 7.2 = -5.8 ... wait. - * - * Based on your example: 1.0 - 6.8 displayed. - * So formula is: base - RR (comp minus retention). + * Agent payout column: partner_RR − original base value. + * oa = original comp, ob = original tp, oc = original od + * comp = partner_RR - oa + * tp = partner_RR - ob + * od = partner_RR - oc */ -public static function agentPayoutColumnFromPartnerRr($raw, float $partnerRr): string -{ - if ($raw === null || $raw === '' || $raw === '-') return '-'; - $base = self::toFloat($raw); - if ($base === null || $base <= 0) return '-'; + public static function agentPayoutColumnFromPartnerRr($raw, float $partnerRr): string + { + if ($raw === null || $raw === '' || $raw === '-') return '-'; + $base = self::toFloat($raw); + if ($base === null) return '-'; - // Formula: RR − base (e.g. RR=1.0, comp=7.2 → 1.0 - 7.2 = -6.2) - $result = $partnerRr - $base; + // Formula: partner_RR − base + $result = $partnerRr - $base; - return self::formatGridNumericDisplay($result); -} - -private static function formatGridNumericDisplay(float $v): string -{ - if (abs($v - round($v)) < 0.00001) { - return (string) (int) round($v); + return self::formatGridNumericDisplay($result); + } + + private static function formatGridNumericDisplay(float $v): string + { + if (abs($v - round($v)) < 0.00001) { + return (string) (int) round($v); + } + return rtrim(rtrim(number_format($v, 2, '.', ''), '0'), '.'); } - return rtrim(rtrim(number_format($v, 2, '.', ''), '0'), '.'); -} public static function applyManagerAccountsDisplayToRows(array $rows): array { @@ -246,13 +235,12 @@ private static function formatGridNumericDisplay(float $v): string return $rows; } - private static function retentionMapFromPrrRows(array $prrRows): array { $map = []; foreach ($prrRows as $r) { - if (!array_key_exists('retention_rate', $r) - || $r['retention_rate'] === null + if (!array_key_exists('retention_rate', $r) + || $r['retention_rate'] === null || $r['retention_rate'] === '') continue; $rate = (float) $r['retention_rate']; @@ -286,59 +274,76 @@ private static function formatGridNumericDisplay(float $v): string } /** - * Main apply — now passes segment master map for full resolution. + * Main apply for Agent role: + * + * oa = original comp (raw DB value) + * ob = original tp (raw DB value) + * oc = original od (raw DB value) + * + * comp = partner_RR - oa + * tp = partner_RR - ob + * od = partner_RR - oc + * + * Also sets: partner_VT, partner_RR, partner_segment, + * partner_comp, partner_tp, partner_od */ public static function applyToRows(array $rows, int $agentId, BaseConnection $db): array -{ - if ($agentId <= 0 || $rows === []) return $rows; + { + if ($agentId <= 0 || $rows === []) return $rows; - $prrRows = self::fetchPrrPvtRows($db, $agentId); - $metaMap = self::partnerMetaMapFromPrrRows($prrRows); - $masterVt = self::buildMasterNormLabelToVehicleTypeIdMap($db); - $masterSeg = self::buildMasterNormSegmentToIdMap($db); + $prrRows = self::fetchPrrPvtRows($db, $agentId); + $metaMap = self::partnerMetaMapFromPrrRows($prrRows); + $masterVt = self::buildMasterNormLabelToVehicleTypeIdMap($db); + $masterSeg = self::buildMasterNormSegmentToIdMap($db); - foreach ($rows as &$row) { - // Keep originals as-is (no oa/ob/oc/raw_* aliases) - $origComp = $row['comp'] ?? null; - $origTp = $row['tp'] ?? null; - $origOd = $row['od'] ?? null; + foreach ($rows as &$row) { - $pm = self::resolvePartnerMetaForGridRow($row, $metaMap, $masterVt, $masterSeg); + // ── Store originals as oa / ob / oc ────────────────────────────────── + $row['oa'] = $row['comp'] ?? null; // original comp + $row['ob'] = $row['tp'] ?? null; // original tp + $row['oc'] = $row['od'] ?? null; // original od - if ($pm === null) { - $row['partner_VT'] = '-'; - $row['partner_RR'] = '-'; - $row['partner_comp'] = '-'; - $row['partner_tp'] = '-'; - $row['partner_od'] = '-'; - // comp/tp/od stay as original values - continue; + $pm = self::resolvePartnerMetaForGridRow($row, $metaMap, $masterVt, $masterSeg); + + if ($pm === null) { + // No retention rate found for this row + $row['partner_VT'] = '-'; + $row['partner_RR'] = '-'; + $row['partner_segment'] = '-'; + $row['partner_comp'] = '-'; + $row['partner_tp'] = '-'; + $row['partner_od'] = '-'; + $row['comp'] = '-'; + $row['tp'] = '-'; + $row['od'] = '-'; + continue; + } + + $rr = (float) $pm['partner_RR']; + + // ── Partner meta columns ────────────────────────────────────────────── + $row['partner_VT'] = $pm['partner_VT']; + $row['partner_RR'] = $pm['partner_RR']; + $row['partner_segment'] = $row['segment'] ?? '-'; + + // partner_* = original − RR (display only, same as before) + $row['partner_comp'] = self::agentPayoutColumnFromPartnerRr($row['oa'], $rr); + $row['partner_tp'] = self::agentPayoutColumnFromPartnerRr($row['ob'], $rr); + $row['partner_od'] = self::agentPayoutColumnFromPartnerRr($row['oc'], $rr); + + // ── Overwrite comp / tp / od = partner_RR − original ───────────────── + // $row['comp'] = self::agentPayoutColumnFromPartnerRr($row['oa'], $rr); + // $row['tp'] = self::agentPayoutColumnFromPartnerRr($row['ob'], $rr); + // $row['od'] = self::agentPayoutColumnFromPartnerRr($row['oc'], $rr); + + $row['comp'] = (($x = self::agentPayoutColumnFromPartnerRr($row['oa'], $rr)) > 0) ? $x : '-'; + $row['tp'] = (($y = self::agentPayoutColumnFromPartnerRr($row['ob'], $rr)) > 0) ? $y : '-'; + $row['od'] = (($z = self::agentPayoutColumnFromPartnerRr($row['oc'], $rr)) > 0) ? $z : '-'; } + unset($row); - $rr = (float) $pm['partner_RR']; - - $row['partner_VT'] = $pm['partner_VT']; - $row['partner_RR'] = $pm['partner_RR']; - - // partner_* = original − RR (e.g. 7.2 − 1.0 = 6.2) - $row['partner_comp'] = array_key_exists('comp', $row) - ? self::agentPayoutColumnFromPartnerRr($origComp, $rr) - : '-'; - $row['partner_tp'] = array_key_exists('tp', $row) - ? self::agentPayoutColumnFromPartnerRr($origTp, $rr) - : '-'; - $row['partner_od'] = array_key_exists('od', $row) - ? self::agentPayoutColumnFromPartnerRr($origOd, $rr) - : '-'; - - // comp/tp/od remain as original values — DO NOT overwrite + return $rows; } - unset($row); - - return $rows; -} - - public static function retentionForRow(array $row, array $map): ?float {