FEAT_COMMISSION_FILE_UPLOAD

This commit is contained in:
VENKATESHWARAN 2025-11-17 18:13:26 +05:30
parent 9d113bbea3
commit e7a3e9593d
11 changed files with 833 additions and 136 deletions

View File

@ -776,3 +776,12 @@ $routes->group('payout', function($routes) {
$routes->post('removeUtrDetails',"PayoutController::removeUtrDetails");
});
//PARTNER COMMISSION
$routes->group('commission', function($routes) {
$routes->match (['get','post'],'list',"RuleImportController::commissionFileUploadList");
$routes->post('upload',"RuleImportController::upload");
$routes->get('sample_file',"RuleImportController::downloadSampleCommissionFileUploadExcel");
$routes->get('downloadErrorFile',"RuleImportController::downloadErrorFile");
$routes->get("deleteCommissionData/(:any)", "RuleImportController::deleteCommissionData/$1");
});

View File

@ -81,6 +81,7 @@ class PayoutController extends BaseController
// for list
$data['payout_status'] = $this->payout_status;
$data['agent_list'] = $this->invoiceModel->agentList();
$data['page_name'] = "Payout";
$payout_data['payout_list_data'] = $this->invoiceModel->invoiceList();
$data['payout_list'] = view('payout_list', $payout_data);

View File

@ -1,13 +1,48 @@
<?php
namespace App\Controllers;
use CodeIgniter\API\ResponseTrait;
use App\Models\CommissionFilesModel;
use App\Models\InsurerModel;
class RuleImportController extends AdminController
{
{
use ResponseTrait;
protected $myLogger;
protected $ruleImportService;
protected $commissionFilesModel;
protected $departments;
protected $insurerModel;
public function __construct()
{
{
set_session_context('RuleImportController');
$this->myLogger = \Config\Services::mylogger();
$this->ruleImportService = \Config\Services::ruleImportService();
$this->commissionFilesModel = new CommissionFilesModel();
$this->insurerModel = new InsurerModel();
$this->departments = [
'motor' => 'Motor',
'health' => 'Health',
];
}
public function commissionFileUploadList()
{
$data['page_name'] = "Commision File Upload";
$data['departments'] = $this->departments;
$data['insurers'] = $this->insurerModel->where('is_active', 1)->findAll();
$data['commission_file_list'] = $this->commissionFilesModel
->select('commission_files.*, insurers.name as insurer_name, user_profiles.first_name as created_user_name')
->join('insurers', 'commission_files.insurer_id = insurers.id')
->join('user_profiles', 'commission_files.created_by = user_profiles.id')
->where('commission_files.is_active', 1)
->orderBy('commission_files.id', 'desc')
->findAll();
// dd( $data);
return $this->loadLayout('commission_file_upload', $data);
}
/**
@ -21,7 +56,7 @@ class RuleImportController extends AdminController
try {
$file = $this->request->getFile('rules_file');
if (!$file || !$file->isValid()) {
return $this->response->setJSON(['status'=>'error','message'=>'No file uploaded or upload error']);
return $this->response->setJSON(['status'=>false,'message'=>'No file uploaded or upload error']);
}
// Move uploaded file to writable temp location
@ -42,30 +77,22 @@ class RuleImportController extends AdminController
return $this->response->setJSON($result);
} catch (\Throwable $e) {
log_message('critical', 'RuleImportController::upload ' . $e->getMessage());
return $this->response->setJSON(['status'=>'exception','message'=>$e->getMessage()]);
$this->myLogger->logme('critical', 'RuleImportController::upload ' . $e->getMessage());
return $this->response->setJSON(['status'=>false,'message'=>$e->getMessage()]);
}
}
public function upload()
{
// Make sure filesystem helpers available if you need them
helper(['filesystem']);
// CommissionFilesModel adjust namespace if different
$commissionFilesModel = new \App\Models\CommissionFilesModel();
try {
// ---------------------------------------------------------
// 1. Get uploaded file
// ---------------------------------------------------------
$file = $this->request->getFile('rules_file');
if (!$file || !$file->isValid()) {
log_message('warning', 'RuleImportController::upload - No file or invalid upload.');
return $this->respond([
'status' => 'error',
'message' => 'No file uploaded or upload error.'
], 400);
$this->myLogger->logme('error', 'RuleImportController::upload - No file or invalid upload.');
return $this->respond(['status' => false, 'code' => 404, 'message' => 'No file uploaded or upload error.'], 200);
}
// ---------------------------------------------------------
@ -74,19 +101,11 @@ class RuleImportController extends AdminController
$insurerId = $this->request->getPost('insurer_id');
$department = $this->request->getPost('department');
$commissionMonth = $this->request->getPost('commission_month');
$createdBy = $this->request->getPost('created_by');
$createdBy = get_session_userid();
if (empty($insurerId) || empty($department) || empty($commissionMonth) || empty($createdBy)) {
log_message('warning', 'RuleImportController::upload - Missing required POST data.', [
'insurer_id' => $insurerId,
'department' => $department,
'commission_month' => $commissionMonth,
'created_by' => $createdBy,
]);
return $this->respond([
'status' => 'error',
'message' => 'Missing required fields: insurer_id, department, commission_month, created_by.'
], 400);
if (empty($insurerId) || empty($department) || empty($commissionMonth)) {
$this->myLogger->logme('error', 'RuleImportController::upload - Missing required POST data.' . json_encode($this->request->getPost() ?? []));
return $this->respond(['status' => false, 'code' => 404, 'message' => 'Missing required fields: insurer_id, department, commission_month'], 200);
}
// Optional / default fields
@ -116,14 +135,11 @@ class RuleImportController extends AdminController
$file->move($uploadDir, $targetFileName);
if (!file_exists($movedFullPath)) {
log_message('error', "RuleImportController::upload - Failed to move uploaded file to {$movedFullPath}");
return $this->respond([
'status' => 'error',
'message' => 'Failed to store uploaded file.'
], 500);
$this->myLogger->logme('error', "RuleImportController::upload - Failed to move uploaded file to {$movedFullPath}");
return $this->respond(['status' => false, 'code' => 404, 'message' => 'Failed to store uploaded file.'], 500);
}
log_message('info', "RuleImportController::upload - File moved to {$movedFullPath}");
$this->myLogger->logme('info', "RuleImportController::upload - File moved to {$movedFullPath}");
// ---------------------------------------------------------
// 4. Insert commission_files row with status pending
@ -132,7 +148,7 @@ class RuleImportController extends AdminController
'file_name' => $targetFileName,
'insurer_id' => (int)$insurerId,
'department' => $department,
'commission_month'=> $commissionMonth,
'commission_month' => $commissionMonth,
'rules_count' => 0, // will update on success
'file_status' => $fileStatus, // 'pending' by default
'is_active' => $isActive,
@ -140,18 +156,19 @@ class RuleImportController extends AdminController
'created_at' => date('Y-m-d H:i:s'),
];
$commissionFilesModel->insert($insertData);
$insertId = $commissionFilesModel->getInsertID();
$this->commissionFilesModel->insert($insertData);
$insertId = $this->commissionFilesModel->getInsertID();
if (empty($insertId)) {
log_message('error', 'RuleImportController::upload - Failed to insert commission_files record', ['data' => $insertData]);
$this->myLogger->logme('error', 'RuleImportController::upload - Failed to insert commission_files record', ['data' => $insertData]);
return $this->respond([
'status' => 'error',
'status' => false,
'code' => 404,
'message' => 'Failed to record upload in database.'
], 500);
], 200);
}
log_message('info', "RuleImportController::upload - commission_files inserted id={$insertId}", $insertData);
$this->myLogger->logme('info', "RuleImportController::upload - commission_files inserted id={$insertId}", $insertData);
// ---------------------------------------------------------
// 5. Call ruleImportService->processUpload with inserted file info
@ -172,22 +189,23 @@ class RuleImportController extends AdminController
'commission_month' => $commissionMonth,
];
log_message('info', 'RuleImportController::upload - Calling ruleImportService->processUpload', ['payload' => $payload]);
$this->myLogger->logme('info', 'RuleImportController::upload - Calling ruleImportService->processUpload', ['payload' => $payload]);
$result = $this->ruleImportService->processUpload($payload);
if (!is_array($result) || !isset($result['status'])) {
log_message('error', 'RuleImportController::upload - Invalid service response', ['response' => $result]);
$this->myLogger->logme('error', 'RuleImportController::upload - Invalid service response', ['response' => $result]);
// update file status as failed
$commissionFilesModel->update($insertId, [
$this->commissionFilesModel->update($insertId, [
'file_status' => 'failed',
'updated_by' => (int)$createdBy,
'updated_at' => date('Y-m-d H:i:s'),
]);
return $this->respond([
'status' => 'error',
'status' => false,
'code' => 404,
'message' => 'Invalid response from import service.'
], 500);
], 200);
}
// ---------------------------------------------------------
@ -215,43 +233,45 @@ class RuleImportController extends AdminController
$jsonData = json_encode($rulesArray, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
if ($jsonData === false) {
log_message('error', 'RuleImportController::upload - json_encode failed for rules', [
$this->myLogger->logme('error', 'RuleImportController::upload - json_encode failed for rules', [
'last_error' => json_last_error_msg()
]);
// mark as failed since we cannot save rules
$commissionFilesModel->update($insertId, [
$this->commissionFilesModel->update($insertId, [
'file_status' => 'failed',
'updated_by' => (int)$createdBy,
'updated_at' => date('Y-m-d H:i:s'),
]);
return $this->respond([
'status' => 'error',
'status' => false,
'code' => 404,
'message' => 'Failed to encode rules as JSON.'
], 500);
], 200);
}
if (file_put_contents($jsonPath, $jsonData) === false) {
log_message('error', 'RuleImportController::upload - Failed to write rules JSON file', ['json_path' => $jsonPath]);
$commissionFilesModel->update($insertId, [
$this->myLogger->logme('error', 'RuleImportController::upload - Failed to write rules JSON file', ['json_path' => $jsonPath]);
$this->commissionFilesModel->update($insertId, [
'file_status' => 'failed',
'updated_by' => (int)$createdBy,
'updated_at' => date('Y-m-d H:i:s'),
]);
return $this->respond([
'status' => 'error',
'status' => false,
'code' => 404,
'message' => 'Failed to store rules JSON file.'
], 500);
}
log_message('info', 'RuleImportController::upload - Rules JSON written', [
$this->myLogger->logme('info', 'RuleImportController::upload - Rules JSON written', [
'file_id' => $insertId,
'json_path' => $jsonPath,
'rules_cnt' => $rulesCount,
]);
// Update DB: status, rules_count, updated_by
$commissionFilesModel->update($insertId, [
'file_status' => 'processed',
$this->commissionFilesModel->update($insertId, [
'file_status' => 'pending',
'rules_count' => $rulesCount,
'updated_by' => (int)$createdBy,
'updated_at' => date('Y-m-d H:i:s'),
@ -260,7 +280,8 @@ class RuleImportController extends AdminController
]);
return $this->respond([
'status' => 'success',
'status' => true,
'code' => 200,
'message' => 'File processed successfully.',
'file_id' => $insertId,
'rules_count' => $rulesCount,
@ -291,15 +312,16 @@ class RuleImportController extends AdminController
$updateData['annotated_file_path'] = $annotatedPath;
}
$commissionFilesModel->update($insertId, $updateData);
$this->commissionFilesModel->update($insertId, $updateData);
log_message('warning', "RuleImportController::upload - Validation failed for file_id={$insertId}", [
$this->myLogger->logme('error', "RuleImportController::upload - Validation failed for file_id={$insertId}", [
'errors' => $errors,
'annotated_file' => $annotatedPath
]);
return $this->respond([
'status' => 'error',
'status' => false,
'code' => 404,
'message' => 'Validation failed. No rules saved.',
'file_id' => $insertId,
'errors' => $errors,
@ -310,41 +332,93 @@ class RuleImportController extends AdminController
// ---------------------------------------------------------
// 8. Unexpected status
// ---------------------------------------------------------
log_message('error', 'RuleImportController::upload - Unexpected result status from service', ['result' => $result]);
$commissionFilesModel->update($insertId, [
$this->myLogger->logme('error', 'RuleImportController::upload - Unexpected result status from service', ['result' => $result]);
$this->commissionFilesModel->update($insertId, [
'file_status' => 'failed',
'updated_by' => (int)$createdBy,
'updated_at' => date('Y-m-d H:i:s'),
]);
return $this->respond([
'status' => 'error',
'status' => false,
'code' => 404,
'message' => 'Unexpected import service result.'
], 500);
} catch (\Throwable $ex) {
log_message('critical', 'RuleImportController::upload exception: ' . $ex->getMessage(), [
$this->myLogger->logme('critical', 'RuleImportController::upload exception: ' . $ex->getMessage(), [
'trace' => $ex->getTraceAsString()
]);
// Try to update the commission_files record if insertId exists
if (isset($insertId) && !empty($insertId)) {
try {
$commissionFilesModel->update($insertId, [
$this->commissionFilesModel->update($insertId, [
'file_status' => 'failed',
'updated_by' => isset($createdBy) ? (int)$createdBy : null,
'updated_at' => date('Y-m-d H:i:s'),
'notes' => 'Upload exception: ' . $ex->getMessage(),
]);
} catch (\Throwable $e2) {
log_message('error', 'RuleImportController::upload - failed to update commission_files after exception: ' . $e2->getMessage());
$this->myLogger->logme('error', 'RuleImportController::upload - failed to update commission_files after exception: ' . $e2->getMessage());
}
}
return $this->respond([
'status' => 'exception',
'status' => false,
'code' => 500,
'message' => $ex->getMessage(),
], 500);
}
}
public function downloadSampleCommissionFileUploadExcel()
{
$filePath = ROOTPATH . 'public/sample_excel/sample_commission.csv';
// Check if the file exists
if (file_exists($filePath)) {
// Set the appropriate MIME type
$mimeType = mime_content_type($filePath);
// Send the file to the client for download
return $this->response->download($filePath, null, $mimeType);
} else {
// File not found, show an error message or redirect
echo view('errors/html/production');
}
}
public function downloadErrorFile()
{
$file_id = $this->request->getGet('file_id');
$file_data = $this->commissionFilesModel->where('id', $file_id)->where('is_active', 1)->first();
$filePath = WRITEPATH . 'uploads/commission/files/annotated_' . $file_data['file_name'];
// Check if the file exists
if (file_exists($filePath)) {
// Set the appropriate MIME type
$mimeType = mime_content_type($filePath);
// Send the file to the client for download
return $this->response->download($filePath, null, $mimeType);
} else {
// File not found, show an error message or redirect
$data['message'] = 'The Physical File Not Found';
echo view('errors/404', $data);
}
}
public function deleteCommissionData($id)
{
$this->commissionFilesModel->where('id', $id)
->set(['is_active' => 0])
->update();
return $this->respond(['status' => true, 'code' => 200, 'message' => "File removed successfully"], 200);
}
}

View File

@ -21,6 +21,7 @@ class CommissionFilesModel extends Model
'is_active',
'created_by',
'updated_by',
'rules_count',
];
// Auto timestamps by CI4

View File

@ -0,0 +1,584 @@
<style>
.table th,
.table td {
padding: 8px;
}
table.dataTable tbody td {
padding: 4px 4px !important;
}
.highlight {
border: 2px solid red;
background-color: #ffe6e6;
}
.column-header {
margin-right: 10px;
/* Adjust this value as needed */
}
.form-section {
border: 1px solid #ccc;
padding: 15px;
margin-bottom: 20px;
}
.row-box {
border: 1px solid #ccc;
padding: 10px;
margin-bottom: 10px;
}
table[data-custom-table-css="table"] tbody tr td {
padding: 1px 10px !important;
line-height: 12px;
min-height: 40px;
vertical-align: middle;
}
</style>
<style>
.switch {
position: relative;
display: inline-block;
width: 54px;
height: 34px;
}
.switch input {
opacity: 0;
width: 0;
height: 0;
}
.slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #ccc;
-webkit-transition: .4s;
transition: .4s;
}
.slider:before {
position: absolute;
content: "";
height: 19px;
width: 19px;
left: 4px;
bottom: 4px;
background-color: white;
-webkit-transition: .4s;
transition: .4s;
}
input:checked+.slider {
background-color: #2196F3;
}
input:focus+.slider {
box-shadow: 0 0 1px #2196F3;
}
input:checked+.slider:before {
-webkit-transform: translateX(26px);
-ms-transform: translateX(26px);
transform: translateX(26px);
}
/* Rounded sliders */
.slider.round {
border-radius: 34px;
}
.slider.round:before {
border-radius: 50%;
}
.disabled-option {
color: gray;
}
.custom-dropdown-menu {
display: none;
position: absolute;
background-color: #ffffff !important;
border: 1px solid rgba(0, 0, 0, 0.15);
border-radius: 0.25rem;
padding: 0.5rem 0;
min-width: 10rem;
z-index: 9999;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
}
.custom-dropdown-menu .dropdown-item {
display: block !important;
width: 100% !important;
padding: 0.5rem 1rem !important;
color: #212529 !important;
text-decoration: none !important;
background-color: transparent !important;
}
.custom-dropdown-menu .dropdown-item:hover {
background-color: #f8f9fa !important;
color: #16181b !important;
cursor: pointer !important;
}
</style>
<div class="row" id="inception_list">
<div class="col-12">
<div class="card">
<div class="card-body">
<div>
<div class="table-responsive">
<table data-custom-table-css="table" class="table table-striped mb-0 nowrap" cellspacing="0" id="tickets-table">
<thead class="bg-light">
<tr>
<th><div class="column-header">S.No.</div></th>
<th><div class="column-header">File Name</div></th>
<th><div class="column-header">Insurer</div></th>
<th><div class="column-header">Commission Month</div></th>
<th><div class="column-header">Department</div></th>
<th><div class="column-header">Rules Count</div></th>
<th><div class="column-header">File<br>status</div></th>
<th><div class="column-header">User/Time</div></th>
<th><div class="column-header">Action</div></th>
</tr>
</thead>
<tbody>
<?php if (isset($commission_file_list)) : ?>
<?php foreach ($commission_file_list as $index => $row) { ?>
<tr>
<td class="text-center"><?= $index+1 ?></td>
<td><?php echo $row['file_name'] ?> </td>
<td><?php echo $row['insurer_name'] ?> </td>
<td><?php echo change_date_format($row['commission_month'], 'Y-m-d', 'M-Y'); ?></td>
<td><?php echo ucfirst($row['department']) ?> </td>
<td><?php echo $row['rules_count'] ?></td>
<td><?php echo ucfirst($row['file_status']) ?> </td>
<td><?php echo change_date_format($row['created_at'],'Y-m-d H:i:s', 'd M Y h:i a') . ' by <strong>' . $row['created_user_name'] . '</strong>' ?>
<td>
<div class="btn-group dropdown">
<a href="javascript: void(0);" class="dropdown-toggle arrow-none btn btn-light btn-sm" data-toggle="dropdown" aria-expanded="false"><i class="mdi mdi-dots-horizontal"></i></a>
<div class="dropdown-menu dropdown-menu-right">
<?php if($row['file_status'] == "failed") : ?>
<a href="<?= base_url('commission/downloadErrorFile?file_id=') . $row['id'] ?>" class="dropdown-item" target="_blank"><i class="mdi mdi-delete mr-2 text-muted font-18 vertical-middle"></i>Download Error File</a>
<?php endif; ?>
<a class="dropdown-item btnEdit" data-id="<?= $row['id']; ?>" onclick="deleteCommissionData(<?= $row['id']; ?>)">
<i class="mdi mdi-delete mr-2 text-muted font-18 vertical-middle"></i>Delete
</a>
</div>
</div>
</td>
</tr>
<?php } ?>
<?php endif; ?>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="modal fade" id="file_upload" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title" id="title">Commission File Upload</h4>
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
</div>
<div class="modal-body p-4">
<div class="">
<form role="form" class="parsley-examples" method="post" id="commission_upload_form" enctype="multipart/form-data" action="upload">
<div class="form-group">
<div class="row">
<div class="form-group float-right-end offset-8 col-4">
<span><a href="sample_file" id="download_sample_file" style="font-size: small; color:red !important;">Download sample file</a></span>
</div>
</div>
<div class="row">
<div class="form-group col-md-6">
<label for="insurer"> Insurer <spanclass="text-danger">*</spanclass=></label>
<select class="form-control" id="insurer_id" name="insurer_id" required>
<option value="" selected>Select Insurer</option>
<?php
if (isset($insurers) && count($insurers)) {
foreach ($insurers as $key => $value) {
echo "<option value=" . $value['id'] . ">" . $value['short_name'] . "</option>";
}
}
?>
</select>
</div>
<div class="form-group col-md-6">
<label for="statement_month">Commission Month</label>
<input type="text" class="form-control" id="commission_month" name="commission_month" placeholder="" required readonly>
</div>
</div>
<div class="row">
<div class="form-group col-md-6">
<label for="statement_no">Department</label>
<select class="form-control" id="department" name="department" required>
<option value="" selected>Select Department</option>
<?php
if (isset($departments) && count($departments)) {
foreach ($departments as $key => $value) {
echo "<option value=" . $key . ">" . $value . "</option>";
}
}
?>
</select>
</div>
<div class="form-group col-md-6">
<label for="statment">File</label>
<div class="input-icon">
<input type="file" class="form-control" name="rules_file" required accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,
application/vnd.ms-excel,
application/vnd.oasis.opendocument.spreadsheet,
text/csv"
>
<i class="mdi mdi-upload additional-icon"></i>
</div>
</div>
</div>
</div>
<div class="form-group text-right m-b-0">
<button type="button" class="btn app-btn-outline-secondary mr-2" data-dismiss="modal" aria-hidden="true">Cancel</button>
<button type="submit" class="btn btn-primary waves-effect waves-light mr-1" id="btnSubmit">Submit</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
<script>
document.addEventListener("DOMContentLoaded", function() {
const table = document.getElementById("tickets-table");
// Create custom dropdown
function createCustomDropdown(row) {
const originalDropdown = row.querySelector('.dropdown-menu');
if (!originalDropdown) return null;
const customDropdown = document.createElement('div');
customDropdown.className = 'custom-dropdown-menu';
customDropdown.innerHTML = originalDropdown.innerHTML;
// Remove inline onclick handlers and store them in data attributes
const originalItems = originalDropdown.querySelectorAll('.dropdown-item');
customDropdown.querySelectorAll('.dropdown-item').forEach((item, index) => {
const originalOnclick = originalItems[index].getAttribute('onclick');
item.removeAttribute('onclick'); // Remove the inline handler
item.setAttribute('data-onclick', originalOnclick); // Store in data attribute
});
return customDropdown;
}
let activeDropdown = null;
// Add click event listener to rows
table.querySelectorAll("tbody tr").forEach(row => {
const customDropdown = createCustomDropdown(row);
if (!customDropdown) return;
document.body.appendChild(customDropdown);
row.addEventListener("click", function(event) {
// Ignore clicks on the first column
if (event.target.closest('td:first-child')) return;
if (activeDropdown) activeDropdown.style.display = 'none';
const rect = event.target.getBoundingClientRect();
customDropdown.style.display = 'block';
customDropdown.style.position = 'fixed';
customDropdown.style.left = `${rect.left}px`;
customDropdown.style.top = `${rect.bottom + 5}px`;
activeDropdown = customDropdown;
event.stopPropagation();
});
// Handle custom dropdown clicks
customDropdown.querySelectorAll('.dropdown-item').forEach(item => {
item.addEventListener('click', function(e) {
e.preventDefault();
// Execute the original onclick from data attribute
const onclickAttr = this.getAttribute('data-onclick');
if (onclickAttr) eval(onclickAttr);
// Handle href navigation
const href = this.getAttribute('href');
if (href && href !== '#') window.location.href = href;
if (activeDropdown) {
activeDropdown.style.display = 'none';
activeDropdown = null;
}
e.stopPropagation();
});
});
});
// Close dropdown on outside click
document.addEventListener("click", function() {
if (activeDropdown) {
activeDropdown.style.display = 'none';
activeDropdown = null;
}
});
});
$(document).ready(function() {
table = $('#tickets-table').DataTable({
scrollX: true,
dom: "<'row'<'col-12 d-flex justify-content-between align-items-center'<'datatable-search dataTables_filter'f><'datatable-buttons dt-buttons'B>>>" +
"<'row'<'col-sm-12'tr>>" +
"<'row'<'col-sm-5'i><'col-sm-7'p>>",
buttons: [{
text: 'Upload <i class="mdi mdi-upload"></i>',
className: 'btn app-btn-primary mr-2', // custom class
action: function(e, dt, node, config) {
showFileUploadModal();
}
},
{
extend: 'collection',
text: '<span class=" btn-custom"> Export </span><i class="mdi mdi-menu-down"></i>',
className: 'btn app-btn-secondary ',
buttons: [{
extend: 'csv',
text: '<i class="mdi mdi-file-delimited " ></i><span class=" btn-custom"> CSV </span>',
title: 'Client-List',
// title: function() {
// return $('#toggleButtons').is(':checked')
// ? 'GC-Client-List'
// : 'RC-Client-List';
// },
className: 'app-btn-primary ',
exportOptions: {
columns: ':not(:last-child)'
},
}]
}
],
language: {
search: `
<div class="datatable-search-wrapper" style="position:relative; display:inline-block;">
_INPUT_
<i class="mdi mdi-magnify datatable-search-icon"
style="position:absolute; right:10px; top:50%; transform:translateY(-50%); color:#666;"></i>
<i class="mdi mdi-close-circle datatable-clear-icon"
style="position:absolute; right:10px; top:50%; transform:translateY(-50%); color:#666; display:none;"></i>
</div>`,
searchPlaceholder: "Search",
emptyTable: '<div class="text-center text-muted">No Data found</div>'
},
paging: true,
// pagingType: 'full_numbers'
});
$(".datatable-buttons").prepend(`
<span id="statusSwitchWrapper" class="dt-switch-wrapper" style="margin-right: 20px !important;">
<span class="custom-switch" style="text-align: left;">
<input type="checkbox" class="custom-control-input" id="statusSwitch">
<label class="custom-control-label" for="statusSwitch" style="vertical-align: middle !important;">Failed Status</label>
</span>
</span>
`);
})
$(document).ready(function() {
$('#insurer_id').select2();
$('#commission_month').datepicker({
format: 'yyyy-M',
viewMode: 'months',
minViewMode: 'months',
autoclose: true
});
});
$(document).ready(function() {
$('#file_upload').on('hidden.bs.modal', function () {
console.log("Modal closed");
});
});
$(document).ready(function() {
// Add custom filter function to DataTables
$.fn.dataTable.ext.search.push(function(settings, data, dataIndex) {
const showFailedStatus = $('#statusSwitch').is(':checked');
const status = data[6].toLowerCase().trim(); // Index 6 is the file_status column
if (showFailedStatus) {
return status.includes('failed');
} else{
return !status.includes('failed');
}
});
// Add event listener for switch changes
$('#statusSwitch').on('change', function() {
table.draw(); // Redraw the table to apply the filter
});
// Trigger initial filter to show only success status
table.draw();
});
</script>
<script>
function showFileUploadModal(input) {
var myModal = new bootstrap.Modal(document.getElementById('file_upload'));
myModal.show();
// $(input).val('');
}
$('#commission_upload_form').submit(function(event) {
event.preventDefault();
var isValid = $('#commission_upload_form').parsley().validate();
if (!isValid) {
console.log('Form is Empty', 'Warning');
return;
}
$('#btnSubmit').prop('disabled', true).text('Submitting...');
// Create FormData object
var formData = new FormData($(this)[0]);
$('.loader').fadeIn();
$('.loader-mask').fadeIn();
$.ajax({
url: $(this).attr("action"),
type: "POST",
data: formData,
processData: false, // Prevent jQuery from automatically processing the data
contentType: false, // Let jQuery handle the content type
headers: {
// "Content-Type":"multipart/form-data",
"X-Requested-With": "XMLHttpRequest"
},
success: function(response) {
console.log(response);
$('#commission_upload_form')[0].reset();
if (response.code === 200 && response.status === true) {
toastr.success('File upload successs','SUCCESS');
$('.close').click();
window.location.reload(true);
} else if (response.code === 404 && response.status === false) {
console.error('no data found', response);
toastr.error(response.message, 'FAILED');
window.location.reload(true);
} else {
console.error('Something went wrong!');
toastr.error('Something went wrong! Try later', 'ERROR');
window.location.reload(true);
}
$('.close').click()
$('.loader').fadeOut();
$('.loader-mask').delay(10).fadeOut('slow');
$('#btnSubmit').prop('disabled', false).text('Submit');
},
error: function(xhr, status, error) {
// Request failed, handle error
console.error("Request failed:", status, error);
toastr.error('Something went wrong! Try later', 'Error');
$('.close').click()
$('.loader').fadeOut();
$('.loader-mask').delay(10).fadeOut('slow');
// window.location.reload(true);
}
});
});
function deleteCommissionData(id) {
Swal.fire({
title: "Do you want to delete commission & it's data if any?",
showCancelButton: true,
confirmButtonText: "Delete",
confirmButtonColor: "#ff3333",
}).then((result) => {
console.log(result);
if (result.isConfirmed) {
$('.loader').fadeIn();
$('.loader-mask').fadeIn();
var apiURL = 'deleteCommissionData/' + id;
$.ajax({
url: apiURL,
method: 'GET',
headers: {
"X-Requested-With": "XMLHttpRequest"
},
success: function(response) {
$('.loader').fadeOut();
$('.loader-mask').delay(10).fadeOut('slow');
if (response.code === 200 && response.status === true) {
Swal.fire({
title: "Deleted!",
icon: "success"
});
window.location.reload(true);
} else {
Swal.fire({
title: "Failed!",
text: 'Something went wrong! Try later',
icon: "error"
});
window.location.reload(true);
}
},
error: function(xhr, status, error) {
console.error(xhr.responseText);
console.error(status, error);
$('.loader').fadeOut();
$('.loader-mask').delay(10).fadeOut('slow');
console.error('Error fetching data from API:', error);
toastr.error('Something went wrong! Try later', 'Error');
window.location.reload(true);
}
});
}
});
}
</script>

View File

@ -1256,14 +1256,14 @@
/* Cancel Bootstrap's .form-control for file inputs */
/* input[type="file"].form-control { */
/* height: auto !important;*/
/* remove forced height */
/* padding: initial !important;*/
/* reset padding */
/* font-size: inherit !important;*/
/* reset font size */
/* line-height: normal !important;*/
/* reset line height */
/* height: auto !important;*/
/* remove forced height */
/* padding: initial !important;*/
/* reset padding */
/* font-size: inherit !important;*/
/* reset font size */
/* line-height: normal !important;*/
/* reset line height */
/* } */
@ -1327,7 +1327,7 @@
<!-- accordian -->
<style>
.card #collapseOne .card-body,
#collapseOne .card-body,
#collapseOne .card-body,
.card #collapseTwo .card-body,
.card #collapseThree .card-body,
.card #collapseFour .card-body {
@ -1758,62 +1758,62 @@
</li>
<?php } ?>
<!-- Masters -->
<?php if (get_role_id() == 1 || get_role_id() == 5 || ( get_role_id() == 4 && (in_array(BUSINESS_SUPPORT_TEAM_ID, user_team()) || in_array(SALES_TEAM_ID, user_team())))) { ?>
<!-- Masters -->
<?php if (get_role_id() == 1 || get_role_id() == 5 || (get_role_id() == 4 && (in_array(BUSINESS_SUPPORT_TEAM_ID, user_team()) || in_array(SALES_TEAM_ID, user_team())))) { ?>
<li class="li-seperate" id="masters-li">
<a href="#sidebarPolicies" data-toggle="collapse" class=" img-inactive">
<img
src="<?= base_url() . "public"; ?>/assets/images/masters_sb.png" alt="Logo" height="20">
<span> Masters </span>
</a>
<div class="collapse" id="sidebarDashboards">
<ul class="nav-second-level">
<span> Masters </span>
</a>
<div class="collapse" id="sidebarDashboards">
<ul class="nav-second-level">
<?php if (get_role_id() == 1 || get_role_id() == 5 || ( get_role_id() == 4 && (in_array(BUSINESS_SUPPORT_TEAM_ID, user_team()) || in_array(SALES_TEAM_ID, user_team())))) { ?>
<?php if (get_role_id() == 1 || get_role_id() == 5 || (get_role_id() == 4 && (in_array(BUSINESS_SUPPORT_TEAM_ID, user_team()) || in_array(SALES_TEAM_ID, user_team())))) { ?>
<li>
<a href="<?= base_url('/master/insurer/list') ?>">Insurer</a>
</li>
<li>
<a href="<?= base_url('/master/insurer/list') ?>">Insurer</a>
</li>
<?php } ?>
<?php } ?>
<?php if (get_role_id() == 1 || get_role_id() == 5) { ?>
<?php if (get_role_id() == 1 || get_role_id() == 5) { ?>
<li>
<a href="<?= base_url('/master/tpa/list') ?>">TPA</a>
</li>
<li>
<a href="<?= base_url('/master/kyc/list') ?>">KYC</a>
</li>
<li>
<a href="<?= base_url('/master/policy/list') ?>">Policy</a>
</li>
<li>
<a href="<?= base_url('/master/cash_deposite/list') ?>">CD Master</a>
</li>
<li>
<a href="<?= base_url('/master/vehicle/list') ?>">Vehicle Master</a>
</li>
<li>
<a href="<?= base_url('/user/list') ?>"> Users </a>
</li>
<li>
<a href="<?= base_url('/util/nhanceBranchMaster') ?>"> Nhance Branch </a>
</li>
<li>
<a href="<?= base_url('/util/vehicleTypeMaster') ?>"> Vehicle Type </a>
</li>
<li>
<a href="<?= base_url('/util/rtoMaster') ?>"> RTO </a>
</li>
<li>
<a href="<?= base_url('/master/tpa/list') ?>">TPA</a>
</li>
<li>
<a href="<?= base_url('/master/kyc/list') ?>">KYC</a>
</li>
<li>
<a href="<?= base_url('/master/policy/list') ?>">Policy</a>
</li>
<li>
<a href="<?= base_url('/master/cash_deposite/list') ?>">CD Master</a>
</li>
<li>
<a href="<?= base_url('/master/vehicle/list') ?>">Vehicle Master</a>
</li>
<li>
<a href="<?= base_url('/user/list') ?>"> Users </a>
</li>
<li>
<a href="<?= base_url('/util/nhanceBranchMaster') ?>"> Nhance Branch </a>
</li>
<li>
<a href="<?= base_url('/util/vehicleTypeMaster') ?>"> Vehicle Type </a>
</li>
<li>
<a href="<?= base_url('/util/rtoMaster') ?>"> RTO </a>
</li>
<?php } ?>
<?php } ?>
</ul>
</div>
</li>
</ul>
</div>
</li>
<?php } ?>
@ -1904,9 +1904,9 @@
</div>
</li>
<?php if ((get_role_id() == 1 || get_role_id() == 5) ||(get_role_id() == 4 && in_array(FINANCE_TEAM_ID, user_team())) || (in_array(MANAGEMENT_TEAM_ID, user_team()) || in_array(FINANCE_TEAM_ID, user_team()) || in_array(BUSINESS_TEAM_ID, user_team()) || in_array(POS_TEAM_ID, user_team()))) { ?>
<?php if ((get_role_id() == 1 || get_role_id() == 5) || (get_role_id() == 4 && in_array(FINANCE_TEAM_ID, user_team())) || (in_array(MANAGEMENT_TEAM_ID, user_team()) || in_array(FINANCE_TEAM_ID, user_team()) || in_array(BUSINESS_TEAM_ID, user_team()) || in_array(POS_TEAM_ID, user_team()))) { ?>
<?php if (in_array(get_role_id(), [1, 5]) ||(get_role_id() == 4 && in_array(FINANCE_TEAM_ID, user_team())) || in_array(MANAGEMENT_TEAM_ID, user_team()) || in_array(POS_TEAM_ID, user_team())) { ?>
<?php if (in_array(get_role_id(), [1, 5]) || (get_role_id() == 4 && in_array(FINANCE_TEAM_ID, user_team())) || in_array(MANAGEMENT_TEAM_ID, user_team()) || in_array(POS_TEAM_ID, user_team())) { ?>
<li>
<a href="#policyReports" data-toggle="collapse" class="waves-effect">
<i class="ri-file-chart-fill"></i>
@ -2018,11 +2018,17 @@
</li>
<?php } ?>
<li>
<a href="<?= base_url('/payouts') ?>">
<i class="ri-book-open-line"></i>
<span> Payouts</span>
</a>
</li>
<a href="<?= base_url('/payout/list') ?>">
<i class="ri-book-open-line"></i>
<span> Payouts</span>
</a>
</li>
<li>
<a href="<?= base_url('/commission/list') ?>">
<i class="ri-book-open-line"></i>
<span> commission</span>
</a>
</li>
<?php } ?>
</ul>

View File

@ -182,11 +182,11 @@
<div class="col-12">
<div class="card">
<div class="card-body">
<div class="row" style="padding-bottom: 10px;">
<!-- <div class="row" style="padding-bottom: 10px;">
<div class="col-6" style="align-self: center;">
<h4 style="position: relative;">Payout List <span id="payout_title"></span></h4>
</div>
</div>
</div> -->
<div class="table-responsive">
<table data-custom-table-css="table" id="scroll-horizontal-datatable" class="table w-100 nowrap">
<thead class="bg-light">

View File

@ -48,7 +48,7 @@
<input type="hidden" id="endDate">
</div>
<div class="form-group col-md-12 text-right m-b-0" style="margin-top: 29px;">
<div class="form-group col-md-3 text-right" style="margin-top: 29px;">
<a class="btn btn-secondary" id="clear-filters">Clear</a>
<a class="btn btn-primary" id="get-emp-list" onclick="fetchPayoutList(this);">Submit</a>
</div>
@ -69,6 +69,7 @@
</div>
<script>
let utrHasBeenChanged = false;
$(document).ready(function(){
$('#agent_id').select2();
@ -131,16 +132,19 @@
});
function fetchPayoutList()
function fetchPayoutList(internalCall = false)
{
let agent_id = $('#agent_id').val();
let status_id = $('#status_id').val();
let start_date = $('#startDate').val();
let end_date = $('#endDate').val();
console.log({agent_id, status_id, start_date, end_date, internalCall, utrHasBeenChanged});
if (!agent_id && !status_id && !start_date && !end_date) {
toastr.warning("Please select any one filter!", "WARNING");
return false;
if(!internalCall){
if (!agent_id && !status_id && !start_date && !end_date) {
toastr.warning("Please select any one filter!", "WARNING");
return false;
}
}
let url = '<?= base_url('payout/list') ?>';
@ -180,5 +184,15 @@
toastr.error('An error occurred while fetching the data.', 'ERROR');
});
}
$(document).ready(function(){
$('#payout_modal').on('hidden.bs.modal', function () {
console.log("Payout Modal closed");
console.log('utrHasBeenChanged', utrHasBeenChanged);
if(utrHasBeenChanged == true){
fetchPayoutList(true);
}
});
});
</script>

View File

@ -107,7 +107,7 @@
</div>
<script>
<script>
var dob = flatpickr("#utrDate", {
dateFormat: "d/m/Y",
@ -176,6 +176,7 @@
$('#utr_submit_btn').prop('disabled', false).text('Add UTR');
$('.loader').fadeOut();
$('.loader-mask').delay(350).fadeOut('slow');
utrHasBeenChanged = true;
resetvalues();
}
});
@ -253,6 +254,8 @@
console.error(xhr.responseText);
toastr.error('An error occurred while fetching the data.', 'ERROR');
});
utrHasBeenChanged = true;
}
function checkSum(input) {

View File

@ -654,7 +654,7 @@
<div class="form-group col-md-3">
<label for="addon_policy">Policy Issue Month<span id="base_danger" class="text-danger">*</span></label>
<input type="text" class="form-control" id="month" name="month" placeholder="MM/YYYY" >
<input type="text" class="form-control readonly-select" id="month" name="month" placeholder="MM/YYYY" >
</div>
<div class="form-group col-md-3">

View File

@ -0,0 +1,5 @@
Rule Name,Policy Business Type,Policy Name,Premium Type,Vehicle Type,Vehicle Sub Type,Make,Model,CC Min,CC Max,Fuel Type,Vehicle Age Min,Vehicle Age Max,Vehicle Weight Min,Vehicle Weight Max,RTO State,RTO City,Renewal Type,Renewal Sub Type,Commission Type,Commission Value,Commission Params(TP:OD:PA),Notes
Motor sample 1,Retail,,,Two Wheeler,,,,100,100,,,,,,,,,,composite,,10:25:0,"id: rule_68bc096e6d7df; conditions: vehicle_type == Two Wheeler; cubic_capcity == 100; calculation: composite 10% on tp_premium, 25% on od_premium"
Motor sample 2,Retail,,,Four Wheeler,,,,1000,1000,,5,5,,,,,,,percentage,10,,id: rule_68fb5ad42f3c4; conditions: vehicle_type == Four Wheeler; cubic_capcity >= 1000; vehicle_age <= 5; calculation: 10% on premium
Sample 2,Retail,,TP,Four Wheeler,,,,1000,1000,,,,,,,,,,composite,,10:0:0,id: rule_691438a7cb08b; conditions: vehicle_type == Four Wheeler; policy_type == TP; is_new_vehicle == true; cubic_capcity > 1000; calculation: composite 10% on tp_premium
Sample 2 test,Retail,,,"Two Wheeler,Four Wheeler",,,,2500,2500,,,,,,,,,,flat,500,,"id: rule_6916ad2837807; conditions: vehicle_type in [Two Wheeler, Four Wheeler]; cubic_capcity == 2500; calculation: fixed 500 on premium"
1 Rule Name Policy Business Type Policy Name Premium Type Vehicle Type Vehicle Sub Type Make Model CC Min CC Max Fuel Type Vehicle Age Min Vehicle Age Max Vehicle Weight Min Vehicle Weight Max RTO State RTO City Renewal Type Renewal Sub Type Commission Type Commission Value Commission Params(TP:OD:PA) Notes
2 Motor sample 1 Retail Two Wheeler 100 100 composite 10:25:0 id: rule_68bc096e6d7df; conditions: vehicle_type == Two Wheeler; cubic_capcity == 100; calculation: composite 10% on tp_premium, 25% on od_premium
3 Motor sample 2 Retail Four Wheeler 1000 1000 5 5 percentage 10 id: rule_68fb5ad42f3c4; conditions: vehicle_type == Four Wheeler; cubic_capcity >= 1000; vehicle_age <= 5; calculation: 10% on premium
4 Sample 2 Retail TP Four Wheeler 1000 1000 composite 10:0:0 id: rule_691438a7cb08b; conditions: vehicle_type == Four Wheeler; policy_type == TP; is_new_vehicle == true; cubic_capcity > 1000; calculation: composite 10% on tp_premium
5 Sample 2 test Retail Two Wheeler,Four Wheeler 2500 2500 flat 500 id: rule_6916ad2837807; conditions: vehicle_type in [Two Wheeler, Four Wheeler]; cubic_capcity == 2500; calculation: fixed 500 on premium