FIX_Changes and Additional Requirements ( Report BUGS )

This commit is contained in:
sanjeev.p 2026-03-27 18:33:45 +05:30
parent a5a9004a5d
commit 08e296e3fd
6 changed files with 395 additions and 10 deletions

View File

@ -126,6 +126,7 @@ $routes->group('api', ['filter' => ["jwtAuth:1,2,3,4,agent","appSignature"] ], f
$routes->get('policy/findPolicy', 'PolicyController::findPolicy');
$routes->post('policy/createPolicy', 'PolicyController::createPolicy');
$routes->post('policy/updatePolicy', 'PolicyController::updatePolicy');
$routes->post('policy/updatePolicyCommission', 'PolicyController::updatePolicyCommission');
$routes->get('policy/downloadPolicyFile', 'PolicyController::downloadPolicyFile');
$routes->post('policy/uploadPolicyFile', 'PolicyController::uploadPolicyFile');
$routes->get("policy/searchThePolicies", "PolicyController::searchThePolicies");
@ -196,8 +197,8 @@ $routes->group('api', ['filter' => ["jwtAuth:1,2,3,4,agent","appSignature"] ], f
// GET /partner/{id}/earnings
$routes->get('partner/(:num)/earnings', 'DashboardController::partnerEarnings/$1');
// DASHBOARD Season 7 — Partner Portal
$routes->get('grid/download', 'ExcelExportController::downloadExcelGrid');
//invoice
@ -210,8 +211,6 @@ $routes->group('api', ['filter' => ["jwtAuth:1,2,3,4,agent","appSignature"] ], f
$routes->get('invoice/getAgentUnusedCommissionList', 'InvoiceController::getAgentUnusedCommissionList');
$routes->post('invoice/bulk-upload-commission', 'InvoiceController::bulkUploadCommission');
$routes->post('invoice/bulk-upload-commission/proceed', 'InvoiceController::bulkUploadCommissionProceed');
$routes->post('invoice/bulk-upload-commission', 'InvoiceController::bulkUploadCommission');
$routes->post('invoice/bulk-upload-commission/proceed', 'InvoiceController::bulkUploadCommissionProceed');
// SALES EXECUTIVE

View File

@ -316,11 +316,30 @@ class EndorsementController extends ResourceController
$uploadRevisedFile->move($uploadRevisedPath, $uploadedRevisedCompletionFile);
}
//COMMON UPDATE FIELDS
/*
* COMMON UPDATE FIELDS
* Keep update mapping explicit so fields sent by frontend are not silently ignored.
*/
$updateData = [];
// Update only if provided (avoid null overwrite)
if (isset($reqData['policy_from'])) {
$updateData['policy_from'] = $reqData['policy_from'];
}
if (isset($reqData['policy_number'])) {
$updateData['policy_number'] = $reqData['policy_number'];
}
if (isset($reqData['manager_id'])) {
$updateData['manager_id'] = $reqData['manager_id'];
}
if (isset($reqData['agent_id'])) {
$updateData['agent_id'] = $reqData['agent_id'];
}
if (isset($reqData['endorsement_type'])) {
$updateData['endorsement_type'] = $reqData['endorsement_type'];
}
@ -349,6 +368,10 @@ class EndorsementController extends ResourceController
$updateData['endorsement_premium'] = $reqData['endorsement_premium'];
}
if (isset($reqData['commission_amount'])) {
$updateData['commission_amount'] = $reqData['commission_amount'];
}
if (isset($reqData['pending_days'])) {
$updateData['pending_days'] = $reqData['pending_days'];
}
@ -358,8 +381,13 @@ class EndorsementController extends ResourceController
$updateData['endorsement_file_name'] = $uploadedOriginalCompletionFile;
$updateData['endorsement_completion_file'] = $uploadedRevisedCompletionFile; // ✅ fixed variable
// External Policy Editable Fields
if ($endorsement['policy_from'] === 'External') {
/*
* External Policy Editable Fields
* Use incoming policy_from first (if provided), fallback to stored value.
* This prevents missing updates when stored value casing differs (external/External).
*/
$effectivePolicyFrom = $reqData['policy_from'] ?? $endorsement['policy_from'] ?? '';
if (strcasecmp(trim((string)$effectivePolicyFrom), 'External') === 0) {
if (isset($reqData['insurer_id'])) {
$updateData['insurer_id'] = $reqData['insurer_id'] ?? null;

View File

@ -2550,4 +2550,179 @@ class ExcelExportController extends ResourceController
}
}
// grid/download?role=Manager means all list
// grid/download?role=Manager&insurer=HDFC&vehicle_type=TWO%20WHEELER&plan_type=comp
// grid/download?role=Manager&insurer=HDFC&rto=TN&segment=BIKE&plan_type=comp
// grid/download?role=Manager&insurer=HDFC&segment=BIKE&vehicle_type=TWO%20WHEELER&plan_type=comp
public function downloadExcelGrid()
{
try {
$request = $this->request;
// ✅ Inputs
$role = trim((string) ($request->getGet('role') ?? ''));
$fileId = trim((string) ($request->getGet('file_id') ?? ''));
$insurer = trim((string) ($request->getGet('insurer') ?? ''));
$rto = trim((string) ($request->getGet('rto') ?? ''));
$segment = trim((string) ($request->getGet('segment') ?? ''));
$vehicleType = trim((string) ($request->getGet('vehicle_type') ?? ''));
$planType = strtolower(trim((string) ($request->getGet('plan_type') ?? '')));
$search = trim((string) ($request->getGet('search') ?? ''));
$loggedId = trim((string) ($request->getGet('logged_id') ?? ''));
if ($role === '') {
return $this->response->setJSON([
'status' => 'failed',
'code' => 400,
'data' => 'Role is required to export payout grid.',
]);
}
$isAgent = strtolower($role) === 'agent';
// ✅ Get retention rate (only for Agent)
$retentionRate = 0;
if ($isAgent && $loggedId !== '') {
$agent = $this->db->table('partner_agent')
->select('retention_rate')
->where('id', $loggedId)
->get()
->getRowArray();
$retentionRate = isset($agent['retention_rate']) ? (float)$agent['retention_rate'] : 0;
}
// ✅ Main query
$builder = $this->db->table('partner_insurance_payout_grid');
if ($fileId !== '') {
$builder->where('partner_agent_incentive_file_id', $fileId);
} else {
$maxFileId = $this->db->table('partner_insurance_payout_grid')
->selectMax('partner_agent_incentive_file_id')
->get()
->getRow()
->partner_agent_incentive_file_id ?? null;
if (!empty($maxFileId)) {
$builder->where('partner_agent_incentive_file_id', $maxFileId);
}
}
// ✅ Filters
if ($insurer !== '') $builder->where('insurer', $insurer);
if ($rto !== '') $builder->where('rto', $rto);
if ($segment !== '') $builder->where('segment', $segment);
if ($vehicleType !== '') $builder->where('vehicle_type', $vehicleType);
if (in_array($planType, ['comp', 'tp', 'od'])) {
$builder->where("$planType IS NOT NULL", null, false)
->where("$planType !=", '')
->where("$planType !=", '0');
}
// ✅ Search
if ($search !== '') {
$builder->groupStart()
->like('insurer', $search)
->orLike('vehicle_type', $search)
->orLike('segment', $search)
->orLike('rto', $search)
->orLike('remarks', $search)
->groupEnd();
}
// ✅ Fetch rows
$rows = $builder
->select('id, insurer, vehicle_type, segment, rto, comp, tp, od, remarks')
->orderBy('id', 'DESC')
->get()
->getResultArray();
// =========================
// ✅ HEADERS
// =========================
$headers = ['S.No', 'Insurer', 'Vehicle Type', 'Segment', 'RTO'];
if ($isAgent) {
if ($planType === 'comp') {
$headers[] = 'Comp';
} elseif ($planType === 'tp') {
$headers[] = 'TP';
} elseif ($planType === 'od') {
$headers[] = 'OD';
}
} else {
// ✅ Manager / Accounts
$headers[] = 'Comp';
$headers[] = 'TP';
$headers[] = 'OD';
}
$headers[] = 'Remarks';
// =========================
// ✅ DATA
// =========================
$data = [];
$sNo = 1;
foreach ($rows as $row) {
$comp = isset($row['comp']) ? (float)$row['comp'] : 0;
$tp = isset($row['tp']) ? (float)$row['tp'] : 0;
$od = isset($row['od']) ? (float)$row['od'] : 0;
// ✅ Apply retention only for Agent
if ($isAgent) {
$comp -= $retentionRate;
$tp -= $retentionRate;
$od -= $retentionRate;
}
$line = [
$sNo++,
$row['insurer'] ?? '-',
$row['vehicle_type'] ?? '-',
$row['segment'] ?? '-',
$row['rto'] ?? '-',
];
// ✅ Dynamic columns (Agent only)
if ($isAgent) {
if ($planType === 'comp') {
$line[] = $comp;
} elseif ($planType === 'tp') {
$line[] = $tp;
} elseif ($planType === 'od') {
$line[] = $od;
}
} else {
// ✅ Manager / Accounts → always all
$line[] = $comp;
$line[] = $tp;
$line[] = $od;
}
$line[] = $row['remarks'] ?? '-';
$data[] = $line;
}
// ✅ Export
$fileName = "grid_" . date('Ymd_His') . ".xlsx";
return $this->streamExcelFile($headers, $data, 'Payout Grid', $fileName, false);
} catch (\Throwable $e) {
return $this->response->setJSON([
'status' => 'failed',
'code' => 500,
'data' => $e->getMessage(),
]);
}
}
}

View File

@ -9,7 +9,9 @@ use App\Models\InvoiceModel;
use App\Models\InvoiceItemModel;
use App\Models\InvoiceUtrModel;
use App\Models\PartnerAccountHistoryModel;
// use App\Models\AgentIncentiveFileModel;
use CodeIgniter\Database\Exceptions\DataException;
// use PhpOffice\PhpSpreadsheet\IOFactory;
class InvoiceController extends ResourceController
{
@ -20,6 +22,7 @@ class InvoiceController extends ResourceController
protected $InvoiceItemModel;
protected $InvoiceUtrModel;
protected $PartnerAccountHistoryModel;
// protected $AgentIncentiveFileModel;
protected $db;
public function __construct()
@ -31,6 +34,7 @@ class InvoiceController extends ResourceController
$this->InvoiceItemModel = new InvoiceItemModel();
$this->InvoiceUtrModel = new InvoiceUtrModel();
$this->PartnerAccountHistoryModel = new PartnerAccountHistoryModel();
// $this->AgentIncentiveFileModel = new AgentIncentiveFileModel();
$this->db = \Config\Database::connect();
}
@ -193,7 +197,7 @@ class InvoiceController extends ResourceController
if (!$invoiceId) {
// Generate invoice number only for CREATE
$invoiceData['invoice_no'] = $this->generateInvoiceNo($input['pos_id']);
$invoiceData['invoice_no'] = $this->generateInvoiceNo($input['pos_id'] ?? 0);
$invoiceData['created_at'] = date('Y-m-d H:i:s');
$invoiceData['created_by'] = $input['created_by'] ?? 0;
@ -266,9 +270,8 @@ class InvoiceController extends ResourceController
private function generateInvoiceNo($pos_id)
{
$pos_id = !empty($pos_id) ? $pos_id : 0;
$year = date('Y');
$prefix = "NIIB/$pos_id/$year/";
$prefix = !empty($pos_id) & $pos_id != 0 ? "NIIB/$pos_id/$year/" : "MIG/$year/";
// Get last invoice of current year
$lastInvoice = $this->InvoiceModel
@ -592,6 +595,109 @@ class InvoiceController extends ResourceController
}
}
// public function bulkUploadCommission()
// {
// $this->db->transBegin();
// try {
// $input = $this->request->getJSON(true);
// if (!is_array($input)) {
// $input = [];
// }
// $post = $this->request->getPost();
// if (!is_array($post)) {
// $post = [];
// }
// $rows = $input['rows'] ?? [];
// $updatedBy = (int)($input['updated_by'] ?? ($post['created_by'] ?? 0));
// // Multipart flow: read excel on backend and store upload metadata.
// $file = $this->request->getFile('file_name');
// if ($file && $file->isValid()) {
// $month = date('Y-m-d');
// $uploadPath = WRITEPATH . 'uploads/agent/incentive_file/';
// if (!is_dir($uploadPath)) {
// mkdir($uploadPath, 0777, true);
// }
// $storedFileName = time() . '_' . $file->getRandomName();
// $file->move($uploadPath, $storedFileName);
// $this->AgentIncentiveFileModel->insert([
// 'incentive_month' => $month,
// 'incentive_file_name' => $storedFileName,
// 'file_type' => 'invoice',
// 'is_active' => 1,
// 'created_by' => $updatedBy > 0 ? $updatedBy : null,
// ], true);
// $spreadsheet = IOFactory::load($uploadPath . $storedFileName);
// $excelRows = $spreadsheet->getActiveSheet()->toArray(null, true, true, false);
// if (empty($excelRows)) {
// return $this->respond([
// 'status' => 'failed',
// 'code' => 400,
// 'message' => 'Uploaded file is empty',
// ], 400);
// }
// $headerRow = $excelRows[0] ?? [];
// $headerIndex = [];
// foreach ($headerRow as $idx => $headerValue) {
// $normalized = preg_replace('/[^a-z0-9]/', '', strtolower(trim((string)$headerValue)));
// if (!empty($normalized)) {
// $headerIndex[$normalized] = (int)$idx;
// }
// }
// $policyIdx = $headerIndex['policynumber'] ?? null;
// $invoiceIdx = $headerIndex['invoicenumber'] ?? null;
// $commissionIdx = $headerIndex['commission'] ?? ($headerIndex['commissionamount'] ?? null);
// if ($policyIdx === null || $commissionIdx === null) {
// return $this->respond([
// 'status' => 'failed',
// 'code' => 400,
// 'message' => 'Expected columns: Policy Number, Invoice Number, Commission or Commission Amount',
// ], 400);
// }
// $fallbackInvoiceNo = trim((string)($post['invoice_number'] ?? ''));
// $rows = [];
// foreach ($excelRows as $index => $row) {
// if ($index === 0) {
// continue;
// }
// $policyNo = trim((string)($row[$policyIdx] ?? ''));
// $invoiceNoFromFile = $invoiceIdx !== null ? trim((string)($row[$invoiceIdx] ?? '')) : '';
// $invoiceNo = $invoiceNoFromFile !== '' ? $invoiceNoFromFile : $fallbackInvoiceNo;
// $commissionRaw = trim((string)($row[$commissionIdx] ?? ''));
// if ($policyNo === '' && $invoiceNo === '' && $commissionRaw === '') {
// continue;
// }
// $commission = (float)str_replace(',', '', $commissionRaw);
// if ($policyNo === '' || $invoiceNo === '' || !is_numeric(str_replace(',', '', $commissionRaw))) {
// return $this->respond([
// 'status' => 'failed',
// 'code' => 400,
// 'message' => 'Invalid data at line ' . ($index + 1),
// ], 400);
// }
// $rows[] = [
// 'line_no' => $index + 1,
// 'policy_number' => $policyNo,
// 'invoice_no' => $invoiceNo,
// 'commission_amount' => $commission,
// ];
// }
// }
public function bulkUploadCommission()
{
$this->db->transBegin();

View File

@ -411,6 +411,82 @@ class PolicyController extends ResourceController
}
}
public function updatePolicyCommission()
{
try {
$data = $this->request->getJSON(true);
if (empty($data['id'])) {
return $this->respond([
'status' => 'failed',
'code' => 422,
'data' => 'Policy id is required',
], 422);
}
if (!isset($data['commission_amount']) || $data['commission_amount'] === '') {
return $this->respond([
'status' => 'failed',
'code' => 422,
'data' => 'commission_amount is required',
], 422);
}
$policyId = (int) $data['id'];
$policy = $this->PolicyModel->find($policyId);
if (!$policy) {
return $this->respond([
'status' => 'failed',
'code' => 404,
'data' => 'Policy not found',
], 404);
}
$commission = (float) $data['commission_amount'];
if ($commission < 0) {
return $this->respond([
'status' => 'failed',
'code' => 422,
'data' => 'commission_amount must be positive',
], 422);
}
/*
* Commission-only update endpoint.
* Keeps the existing policy workflow unchanged and updates only required fields.
*/
$updateData = [
'commission_amount' => number_format($commission, 2, '.', ''),
'updated_by' => $data['updated_by'] ?? null,
'updated_on' => date('Y-m-d H:i:s'),
];
if (!$this->PolicyModel->update($policyId, $updateData)) {
return $this->respond([
'status' => 'failed',
'code' => 422,
'data' => $this->PolicyModel->errors(),
], 422);
}
return $this->respond([
'status' => 'success',
'code' => 200,
'data' => [
'policy_id' => (string) $policyId,
'commission_amount' => $updateData['commission_amount'],
'message' => 'Commission updated successfully',
],
], 200);
} catch (\Exception $e) {
return $this->respond([
'status' => 'failed',
'code' => 500,
'data' => $e->getMessage(),
], 500);
}
}
public function uploadPolicyFile()
{
try {

View File

@ -30,6 +30,7 @@ class PolicyModel extends Model
'pt_oc_share_details_id',
'created_by',
'updated_by',
'updated_on',
// newly added
'tp',