diff --git a/app/Config/Routes.php b/app/Config/Routes.php
index eab9f909..6a7ac292 100644
--- a/app/Config/Routes.php
+++ b/app/Config/Routes.php
@@ -317,6 +317,13 @@ $routes->group("policy_tranction", ["filter" => "authMVC"], function ($routes) {
$routes->get("list", "PolicyTransactionController::reportBDS");
});
+ $routes->group("statement", ["filter" => "authMVC"], function ($routes) {
+ $routes->get("list", "PolicyTransactionController::statementList");
+ $routes->post("upload", "PolicyTransactionController::uploadInsurerStatement");
+ $routes->get("getPaymentDetails/(:any)", "PolicyTransactionController::getInvoicePaymentDetails/$1");
+ $routes->post("saveInvoicePaymentDetails", "PolicyTransactionController::saveInvoicePaymentDetails");
+ });
+
});
$routes->cli('cli/processjob', 'JobWorker::processJob');
diff --git a/app/Controllers/PolicyTransactionController.php b/app/Controllers/PolicyTransactionController.php
index 7c9c46e7..60daeb55 100644
--- a/app/Controllers/PolicyTransactionController.php
+++ b/app/Controllers/PolicyTransactionController.php
@@ -25,7 +25,9 @@ use App\Models\EmployeeModel;
use App\Models\UserTeamsModel;
use App\Models\UserModel;
use App\Models\EmployeePolicyModel;
-
+use App\Models\InsurerStatements;
+use App\Models\InvPaymentDetailsModel;
+use Kint;
class PolicyTransactionController extends BaseController
{
@@ -51,6 +53,9 @@ class PolicyTransactionController extends BaseController
protected $userTeamsModel;
protected $userModel;
protected $employeePolicyModel;
+ protected $insurerStatements;
+ protected $invoiceStatus;
+ protected $invPaymentDetailsModel;
public function __construct()
{
@@ -76,6 +81,15 @@ class PolicyTransactionController extends BaseController
$this->userTeamsModel = new UserTeamsModel();
$this->userModel = new UserModel();
$this->employeePolicyModel = new EmployeePolicyModel();
+ $this->insurerStatements = new InsurerStatements();
+ $this->invPaymentDetailsModel = new InvPaymentDetailsModel();
+ $this->invoiceStatus = [
+ 'pending' => 'Pending',
+ 'generated' => 'Generated',
+ 'sent' => 'Sent',
+ 'payment_received' => 'Payment Received',
+
+ ];
}
// Policy Transaction Inception
@@ -965,6 +979,438 @@ class PolicyTransactionController extends BaseController
$this->loadLayout('report_bds_filter', $data);
}
+
+ //insurer statement list page
+ public function statementList()
+ {
+ // dd($this->updateInsurerStatement(['file_id' => 13]));
+ // $data['insurers'] = $this->insurerModel->where('is_active',1)->findAll();
+ $data['invoice_status_array'] = $this->invoiceStatus;
+ $data['insurers'] = $this->insurerBranchModel ->getInsurerBranchesWithInsurerNames();
+
+ // dd( $data['insurers']);
+ $data['insurer_statement_list'] = $this->insurerStatements
+ ->select('insurer_statements.*,
+ insurers.name AS insurer_name,insurers.short_name,user_profiles.first_name,insurer_branch.branch_code
+ ')
+ ->join('insurers', 'insurer_statements.insurer_id = insurers.id')
+ ->join('insurer_branch', 'insurer_statements.branch_id = insurer_branch.id')
+ ->join('user_profiles', 'insurer_statements.created_by = user_profiles.id')
+ ->orderBy('insurer_statements.id', 'desc')
+ ->findAll();
+ // dd( $data['insurer_statement_list']);
+ $this->loadLayout('insurer_statement_list', $data);
+ }
+
+ public function uploadInsurerStatement()
+ {
+
+ //validate uploaded file
+ $filename = '';
+ $validated = $this->validate([
+ 'statement' => [
+ 'uploaded[statement]',
+ 'mime_in[statement,application/vnd.ms-excel,application/vnd,application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,application/vnd.oasis.opendocument.spreadsheet]',
+ 'max_size[statement,16384]',
+ ],
+ ]);
+ $this->createStatementFolder();
+ if ($validated)
+ {
+ $avatar = $this->request->getFile('statement');
+ if (!$avatar) {
+ $this->myLogger->logme("error", 'Statement File not found');
+ return $this->respond(['dataStatus' => false, 'code' => 400, 'message' => 'File not found'], 400);
+ }
+
+ $is_moved = $avatar->move(WRITEPATH . 'uploads/statements/');
+ if ($is_moved) {
+ $filename = $avatar->getName();
+ // Handle successful upload, e.g., log success or further processing
+ $this->myLogger->logme("error", 'Statement File moved successful');
+
+ } else {
+ $this->myLogger->logme("error", 'Statement File move failed');
+ return $this->respond(['dataStatus' => false, 'code' => 500, 'message' => 'File move failed'], 500);
+ }
+ } else {
+ $this->myLogger->logme("error", 'Statement Upload failed Invalid file');
+ return $this->respond(['dataStatus' => false, 'code' => 404, 'message' => 'Invalid file'], 404);
+ }
+
+ //process post variable entry in file table
+ $loggedInUserID = get_session_userid();
+ // dd($loggedInUserID);
+ // $loggedInUserID = 8;
+
+ $insurer = $this->request->getPost('insurer');
+
+ $insurer_id = explode('-', $insurer)[0];
+ $branch_id = explode('-', $insurer)[1];
+ // print_r($insurer_id);
+ // print_r($branch_id);
+ // die();
+ $month = $this->request->getPost('statement_month');
+ $month = change_date_format($month,'Y-M-d','Y-m-d');
+ // print_r($month);die;
+
+ $file_id = $this->insurerStatements->insert(['insurer_id' => $insurer_id, 'branch_id' => $branch_id, 'file_name' => $filename,'month' => $month, 'created_by' => $loggedInUserID]); //here field policy_id have client_policy_id and not policy id from policy master
+ $this->myLogger->logme("error", '{file_id} statement uploaded success', ['file_id' => $file_id]);
+
+ //validate file
+ $validation_result = $this->validateInsurerStatement(['file_id' => $file_id]);
+ //update file content to DB
+ if($validation_result['status'] )
+ {
+ $this->updateInsurerStatement(['file_id' => $file_id]);
+ }
+
+ if (!isset($file_id) || !$validation_result['status']) {
+ return $this->respond(['dataStatus' => false, 'code' => 404, 'message' => 'file not uploaded', 'error_data' => $validation_result['error_data'],'error_code' => $validation_result['error_code']], 200);
+ }
+
+ return $this->respond(['dataStatus' => true, 'code' => 200, 'data' => 'file upload success'], 200);
+ }
+
+ public function createStatementFolder()
+ {
+ $folderPath = WRITEPATH . 'uploads/statements/';
+
+ // Check if the folder doesn't exist
+ if (!file_exists($folderPath))
+ {
+ // Create the folder
+ if (mkdir($folderPath, 0777, true)) {
+ $this->myLogger->logme('error','statement upload folder created successfully');
+
+ // Set permissions to a+rwx (read, write, execute for all)
+ chmod($folderPath, 0777);
+ $this->myLogger->logme('error','Permissions set to a+rwx.');
+ } else {
+ // echo "Failed to create folder.";
+ $this->myLogger->logme('error','Failed to create statement upload folder.');
+ }
+ }
+ else
+ {
+ $this->myLogger->logme('error','upload folder exists.');
+ }
+ }
+
+ public function validateInsurerStatement($params)
+ {
+ //get file info
+ $file_id = $params['file_id'];
+ $file = $this->insurerStatements->find($file_id);
+ // dd($file);
+ $date = new \DateTime($file['month']);
+
+ $month = $date->format('m');
+ $year = $date->format('Y');
+
+ $error_data = ['error_code' => '','error_data' => []];
+ $status = 'success';
+ $ret_status = true;
+ // dd($month.'-'.$year);
+ $return = [];
+ if(!isset($file))
+ {
+ //file not found in DB
+ return array('status' => false, 'msg' => 'statement file not found in DB');
+ }
+ $file_name_with_path = WRITEPATH."/uploads/statements/".$file['file_name'];
+
+ //check physical file
+ if(!file_exists($file_name_with_path))
+ {
+ //file not found update status and reason
+ $message = "Physcial file not found";
+ // echo $message;
+ $this->myLogger->logme('error',($message . ' for statement file id ' . $file_id));
+ $this->insurerStatements->where('id', $file_id)->set(['file_status' => 'failed','reason' => json_encode(['error_code' => 0,'error_data' => $message])])->update();
+ return array('status' => false, 'error_code' => 0); //0 - Physcial file not found
+ }
+
+ //get excel data to php array
+ $spreadsheet = \PhpOffice\PhpSpreadsheet\IOFactory::load($file_name_with_path);
+ $sheet = $spreadsheet->getActiveSheet();
+
+ $highestRowAndColumn = $sheet->getHighestRowAndColumn();
+ // dd($highestRowAndColumn);
+ $excel_data = $sheet->rangeToArray('A1:' . $highestRowAndColumn['column'] . $highestRowAndColumn['row']);
+ unset($excel_data[0]);
+ // dd($excel_data);
+ //get no of line items and update in DB
+ $line_items = count($excel_data);
+ // get uploaded month transactions data
+ $source_data = $this->PTCOShareDetailsModel->getNonReconcileredPolicyTransactions(month:$month,year:$year,insurer_id:$file['insurer_id'],insurer_branch_id:$file['branch_id']);
+ // Kint::dump($source_data);
+ // Kint::dump($excel_data);
+
+ // check policy no,insurer and etc in DB for this month
+ // if all good return true, otherwise return false with messssage
+ foreach ($excel_data as $excel_key => $excel_row)
+ {
+ $is_source_found = 0;
+ $excel_row[4] = trim($excel_row[4]);
+ $excel_row[5] = trim($excel_row[5]);
+ // Kint::dump(change_date_format($excel_row[4],'d-m-Y','Y-m-d'));
+ // echo $excel_row[1].'#'.$excel_row[2] .'#'.$excel_row[3].'#'.change_date_format($excel_row[4],'d-m-Y','Y-m-d').'#'.change_date_format($excel_row[5],'d-m-Y','Y-m-d').'
';
+ foreach ($source_data as $source_key => $source_row)
+ {
+ // Kint::dump(change_date_format($excel_row[3],'d-m-Y','Y-m-d'));
+ if( (trim($excel_row[1]) == $source_row['policy_no']) && trim($excel_row[2]) == $source_row['endorsement_no'] && trim($excel_row[3]) == $source_row['client_name'] && change_date_format($excel_row[4],'d-m-Y','Y-m-d') == $source_row['policy_start_date'] && change_date_format($excel_row[5],'d-m-Y','Y-m-d') == $source_row['policy_end_date'])
+ {
+ $is_source_found = 1;
+ unset($source_data[$source_key]);
+ continue 2;
+ }
+ }
+
+ if($is_source_found == 0)
+ {
+ // echo $excel_key.'-'.$excel_row[1] . '- not found
';
+ $error_data['error_code'] = 1;//match not found
+ // $error_data['error_data'] = ($error_data['error_data'] ?? []);
+ $error_data['error_data'] = array_merge($error_data['error_data'],[$excel_row[0]]);//match not found
+ }
+ }
+
+ if($error_data['error_code'])
+ {
+ $status = 'failed';
+ $ret_status = false;
+ }
+ //update in DB
+ $this->insurerStatements->where('id', $file_id)->set(['line_items' => $line_items,'file_status' => $status,'reason' => json_encode($error_data)])->update();
+ return array('status' => $ret_status, 'error_code' => $error_data['error_code'],'error_data' => $error_data['error_data']);
+ }
+
+
+ public function updateInsurerStatement($params)
+ {
+ //get file info
+ $file_id = $params['file_id'];
+ $file = $this->insurerStatements->find($file_id);
+ // dd($file);
+ $date = new \DateTime($file['month']);
+
+ $month = $date->format('m');
+ $year = $date->format('Y');
+
+ $error_data = ['error_code' => '','error_data' => []];
+ $status = 'success';
+ $ret_status = true;
+ // dd($month.'-'.$year);
+ $return = [];
+ if(!isset($file))
+ {
+ //file not found in DB
+ return array('status' => false, 'msg' => 'statement file not found in DB');
+ }
+ $file_name_with_path = WRITEPATH."/uploads/statements/".$file['file_name'];
+
+ //check physical file
+ if(!file_exists($file_name_with_path))
+ {
+ //file not found update status and reason
+ $message = "Physcial file not found";
+ // echo $message;
+ $this->myLogger->logme('error',($message . ' for statement file id ' . $file_id));
+ $this->insurerStatements->where('id', $file_id)->set(['file_status' => 'failed','reason' => json_encode(['error_code' => 0,'error_data' => $message])])->update();
+ return array('status' => false, 'error_code' => 0); //0 - Physcial file not found
+ }
+
+ //get excel data to php array
+ $spreadsheet = \PhpOffice\PhpSpreadsheet\IOFactory::load($file_name_with_path);
+ $sheet = $spreadsheet->getActiveSheet();
+
+ $highestRowAndColumn = $sheet->getHighestRowAndColumn();
+ // dd($highestRowAndColumn);
+ $excel_data = $sheet->rangeToArray('A1:' . $highestRowAndColumn['column'] . $highestRowAndColumn['row']);
+ unset($excel_data[0]);
+ // dd($excel_data);
+ //get no of line items and update in DB
+ $line_items = count($excel_data);
+ // get uploaded month transactions data
+ $source_data = $this->PTCOShareDetailsModel->getNonReconcileredPolicyTransactions(month:$month,year:$year,insurer_id:$file['insurer_id'],insurer_branch_id:$file['branch_id']);
+ // Kint::dump($source_data);die;
+ // Kint::dump($excel_data);
+
+ // check policy no,insurer and etc in DB for this month
+ // if all good return true, otherwise return false with messssage
+ $data_to_update = [];
+ foreach ($excel_data as $excel_key => $excel_row)
+ {
+ $is_source_found = 0;
+ $excel_row[4] = trim($excel_row[4]);
+ $excel_row[5] = trim($excel_row[5]);
+
+ foreach ($source_data as $source_key => $source_row)
+ {
+ // Kint::dump(change_date_format($excel_row[3],'d-m-Y','Y-m-d'));
+ if( (trim($excel_row[1]) == $source_row['policy_no']) && trim($excel_row[2]) == $source_row['endorsement_no'] && trim($excel_row[3]) == $source_row['client_name'] && change_date_format($excel_row[4],'d-m-Y','Y-m-d') == $source_row['policy_start_date'] && change_date_format($excel_row[5],'d-m-Y','Y-m-d') == $source_row['policy_end_date'])
+ {
+ $is_source_found = 1;
+
+ //calculate percentage first
+ $total_amt = 0;
+
+ $actual_bp_per = trim($excel_row[9]);
+ $actual_bp_brokerage = trim($excel_row[12]);
+ $actual_bp_amt = trim($excel_row[6]);
+
+ if(($actual_bp_brokerage && $actual_bp_brokerage != 0 && $actual_bp_brokerage != ""))
+ {
+ $total_amt += $actual_bp_brokerage;
+ //percentage reverse calculation
+ if($actual_bp_per == 0 || $actual_bp_per == "")
+ {
+ $actual_bp_per = round(($actual_bp_brokerage / $actual_bp_amt) * 100,2);
+ }
+
+ }
+ else
+ {
+ $actual_bp_brokerage = $actual_bp_amt * ($actual_bp_per / 100);
+ $total_amt += $actual_bp_brokerage;
+ }
+
+ $actual_tp_per = trim($excel_row[10]);
+ $actual_tp_brokerage = trim($excel_row[13]);
+ $actual_tp_amt = trim($excel_row[7]);
+
+ if($actual_tp_brokerage && $actual_tp_brokerage != 0 && $actual_tp_brokerage != "")
+ {
+ $total_amt += $actual_tp_brokerage;
+ //percentage reverse calculation
+ if($actual_tp_per == 0 || $actual_tp_per == "")
+ {
+ $actual_tp_per = ($actual_tp_brokerage / $actual_tp_amt) * 100;
+ }
+ }
+ else
+ {
+ $actual_tp_brokerage = $actual_tp_amt * ($actual_tp_per / 100);
+ $total_amt += $actual_tp_brokerage;
+ }
+
+ $actual_tep_per = trim($excel_row[11]);
+ $actual_tep_brokerage = trim($excel_row[14]);
+ $actual_tep_amt = trim($excel_row[8]);
+
+ if($actual_tep_brokerage && $actual_tep_brokerage != 0 && $actual_tep_brokerage != "")
+ {
+ $total_amt += $actual_tep_brokerage;
+ //percentage reverse calculation
+ if($actual_tep_per == 0 || $actual_tep_per == "")
+ {
+ $actual_tep_per = ($actual_tep_brokerage / $actual_tep_amt) * 100;
+ }
+ }
+ else
+ {
+ $actual_tep_brokerage = $actual_tep_amt * ($actual_tep_per / 100);
+ $total_amt += $actual_tep_brokerage;
+ }
+
+ //find variance
+ $variance_amt = $source_row['exp_amt'] - $total_amt;
+
+ $data_to_update[] = ['id' => $source_row['id'],'actual_bp_amt' => $actual_bp_amt,'actual_tp_amt' => $actual_tp_amt,'actual_tep_amt' => $actual_tep_amt,'actual_bp_per' => $actual_bp_per,'actual_tp_per' => $actual_tp_per,'actual_tep_per' => $actual_tep_per,'variance' => $variance_amt,'actual_tep_brokerage_amt' => $actual_tep_brokerage,'actual_tp_brokerage_amt' => $actual_tp_brokerage,'actual_bp_brokerage_amt' => $actual_bp_brokerage,'reward' => trim($excel_row[15]),'statement_id' => $file_id];
+
+ unset($source_data[$source_key]);
+ continue 2;
+ }
+ }
+ }
+ $this->PTCOShareDetailsModel->updateBatch($data_to_update, 'id');
+ // dd($data_to_update);
+ // if($error_data['error_code'])
+ // {
+ // $status = 'failed';
+ // $ret_status = false;
+ // }
+ //update in DB
+ //$this->insurerStatements->where('id', $file_id)->set(['file_status' => $status,'reason' => json_encode($error_data)])->update();
+ return array('status' => $ret_status, 'error_code' => $error_data['error_code'],'error_data' => $error_data['error_data']);
+ }
+
+ public function getInvoicePaymentDetails()
+ {
+ $statement_id = $this->request->getUri()->getSegment(4);
+
+ $inv_details = $this->insurerStatements->find($statement_id);
+ $inv_payment_details = $this->invPaymentDetailsModel
+ ->where('statement_id',$statement_id)
+ ->where('is_active',1)
+ ->get()
+ ->getResultArray();
+ // print_r($inv_details);
+ $data = [ 'invoice_status' => $inv_details['invoice_status'],
+ 'invoice_no' => $inv_details['invoice_no'],
+ 'invoice_date' => $inv_details['invoice_date'] ];
+ $data['payments'] = $inv_payment_details;
+ return $this->respond(['dataStatus' => true, 'code' => 200, 'data' => $data], 200);
+
+
+ }
+
+ public function saveInvoicePaymentDetails()
+ {
+ $jsonData = $this->request->getJSON();
+ $jsonData = (array)$jsonData;
+ // echo 'Hi';
+ // print_r($jsonData);die();
+
+ $invoiceStatus = $jsonData['invoice_status'];
+ $hiddenStatementId = $jsonData['hidden_statement_id'];
+ $invoiceNo = $jsonData['invoice_no'];
+ $invoiceDate = $jsonData['invoice_date'];
+
+ //Update statement table
+ $parentData = [
+ 'invoice_status' => $invoiceStatus,
+ 'invoice_no' => $invoiceNo,
+ 'invoice_date' => $invoiceDate,
+ 'updated_by' => get_session_userid()
+ ];
+
+
+
+ // $this->insurerStatements->update($hiddenStatementId, $parentData);
+
+ // Process child data
+ $invoiceAmounts = $jsonData['invoice_amount'];
+ $utrNos = $jsonData['utr_no'];
+ $paymentDates = $jsonData['payment_date'];
+ $pks = $jsonData['pk'];
+
+ foreach ($invoiceAmounts as $index => $invoiceAmount) {
+ $pk = $pks[$index]; // Get the pk for the current record
+ $utrNo = $utrNos[$index];
+ $paymentDate = $paymentDates[$index];
+
+ // Prepare data for insert/update
+ $childData = [
+ 'inv_amt' => $invoiceAmount,
+ 'utr_no' => $utrNo,
+ 'received_date' => $paymentDate,
+ 'statement_id' => $hiddenStatementId,
+ 'id' => is_numeric($pk) ? (int)$pk : '',
+ ];
+ if($pk){ $childData['updated_by'] = get_session_userid(); }
+ else { $childData['created_by'] = get_session_userid(); }
+ // print_r($childData);
+ // Insert or update
+ $this->invPaymentDetailsModel->save($childData);
+ print_r($this->invPaymentDetailsModel->errors());
+
+ }
+
+ return $this->respond(['dataStatus' => true, 'code' => 200], 200);
+ //return $this->response->setJSON(['dataStatus' => 'true']);
+ }
}
\ No newline at end of file
diff --git a/app/Helpers/utility_helper.php b/app/Helpers/utility_helper.php
index 6c7c6c1a..a764697b 100644
--- a/app/Helpers/utility_helper.php
+++ b/app/Helpers/utility_helper.php
@@ -24,6 +24,7 @@ if (!function_exists('change_date_format')) {
function change_date_format($data, $source_format, $output_format)
{
+ $data = trim($data);
// echo $data, $source_format, $output_format;return true;
try {
// Create DateTime object with the source format
@@ -31,7 +32,8 @@ if (!function_exists('change_date_format')) {
// Check if the DateTime object is created successfully
if ($dateTime === false) {
- throw new Exception('Invalid date or format');
+ $errors = DateTime::getLastErrors();
+ throw new Exception('Invalid date or format' . implode(', ', $errors['errors']));
}
// Format the DateTime object with the output format
$formattedDate = $dateTime->format($output_format);
diff --git a/app/Models/InsurerStatements.php b/app/Models/InsurerStatements.php
new file mode 100644
index 00000000..6b85ed0f
--- /dev/null
+++ b/app/Models/InsurerStatements.php
@@ -0,0 +1,30 @@
+db->table('pt_co_share_details pt_co')
+ ->select('
+ pt_co.id,
+ pt_co.pt_id,
+ pt_co.exp_amt,
+ pt.id AS policy_transaction_id,
+ pt.endorsement_no,
+ c.client_name,
+ pt.created_at,
+ pt_co.insurer_id,
+ pt_co.insurer_branch_id,
+ pt.policy_no,
+ pt.policy_issue_date,
+ pt.policy_start_date,
+ pt.policy_end_date,
+ pt.status,
+ pt_co.bp_amt,
+ pt_co.tp_amt,
+ pt_co.tep_amt,
+ pt_co.exp_amt
+ ')
+ ->join('policy_transaction pt', 'pt_co.pt_id = pt.id')
+ ->join('clients c', 'pt.client_id = c.id')
+ ->where('pt_co.is_active', 1)
+ ->where('MONTH(pt.created_at)', $month)
+ ->where('YEAR(pt.created_at)', $year)
+ ->where('pt_co.insurer_id', $insurer_id)
+ ->where('pt_co.insurer_branch_id', $insurer_branch_id)
+ // ->where('pt_co.exp_amt', 0.00)
+ // ->orWhere('pt_co.exp_amt is null')
+ ->get()
+ ->getResultArray();
+ }
}
diff --git a/app/Views/insurer_statement_list.php b/app/Views/insurer_statement_list.php
new file mode 100644
index 00000000..29d14a7b
--- /dev/null
+++ b/app/Views/insurer_statement_list.php
@@ -0,0 +1,708 @@
+
+
+
+
+