nhance/app/Controllers/PayoutController.php

662 lines
26 KiB
PHP

<?php
namespace App\Controllers;
use App\Controllers\BaseController;
use CodeIgniter\HTTP\ResponseInterface;
use CodeIgniter\API\ResponseTrait;
use App\Models\InvoiceItemModel;
use App\Models\InvoiceModel;
use App\Models\InvoiceUtrModel;
use App\Models\PolicyTransactionModel;
use App\Models\AuditHistoryModel;
use Dompdf\Dompdf;
use Dompdf\Options;
class PayoutController extends BaseController
{
use ResponseTrait;
protected $myLogger;
protected $invoiceItemModel;
protected $invoiceModel;
protected $invoiceUtrModel;
protected $policyTransactionModel;
protected $payout_status;
protected $auditHistory;
public function __construct()
{
set_session_context('PayoutController');
$this->myLogger = \Config\Services::mylogger();
$this->payout_status = [
1 => "Pending",
2 => "Completed",
];
$this->invoiceItemModel = new InvoiceItemModel();
$this->invoiceModel = new InvoiceModel();
$this->invoiceUtrModel = new InvoiceUtrModel();
$this->policyTransactionModel = new PolicyTransactionModel();
$this->auditHistory = new AuditHistoryModel();
}
public function payoutList()
{
// for filtering list
if($this->request->is('post')){
try{
$data = $this->request->getPost();
// print_r($data); die;
// $agent_id = $data['agent_id'] ?? null; because dropdown hided
$pos_id = $data['pos_id'] ?? null;
$status_id = $data['status_id'] ?? null;
$start_date = $data['start_date'] ?? null;
$end_date = $data['end_date'] ?? null;
// $payout_data = $this->invoiceModel->invoiceList($agent_id, $status_id, $start_date, $end_date); // because dropdown hided
$payout_data = $this->invoiceModel->invoiceList($pos_id, $status_id, $start_date, $end_date);
$payout_data['payout_list_data'] = $payout_data;
$payout_data = view('payout_list', $payout_data);
if(!empty($payout_data)){
return $this->respond(['status' => true, 'code' => 200, 'data' => $payout_data], 200);
}else{
return $this->respond(['status' => false, 'code' => 400, 'data' => $payout_data, "message" => "No data found"], 200);
}
}catch (\Throwable $th) {
$this->myLogger->logme("error", "PayoutController - payoutList: Exception: " . $th->getMessage() . " --- Line: " . $th->getLine() . " --- Trace: " . $th->getTraceAsString());
$errorData = [
'message' => $th->getMessage(),
'file' => $th->getFile(),
'line' => $th->getLine(),
'code' => $th->getCode(),
'trace' => $th->getTraceAsString(),
'trace_array' => $th->getTrace(), // full array version (optional)
'function' => $th->getTrace()[0]['function'] ?? null,
'class' => $th->getTrace()[0]['class'] ?? null,
];
$payout_data = view('payout_list');
return $this->respond(['status' => false, 'code' => 500, 'data' => $payout_data, "message" => "No data found", 'error_data' => $errorData], 500);
}
}
// for list
$data['payout_status'] = $this->payout_status;
// $data['agent_list'] = $this->invoiceModel->agentList(); // because dropdown hided
$data['pos_list'] = $this->invoiceModel->posList();
$data['page_name'] = "Invoices";
$payout_data['payout_list_data'] = $this->invoiceModel->invoiceList();
$data['payout_list'] = view('payout_list', $payout_data);
// dd($data);
return $this->loadLayout('payout_list_handler', $data);
}
public function fetchUtrDetails()
{
$invoice_id = $this->request->getPost('invoice_id') ?? null;
$payout_data = $this->constructUtrDetails($invoice_id);
if(!empty($payout_data)){
return $this->respond(['status' => true, 'code' => 200, 'data' => $payout_data], 200);
}else{
return $this->respond(['status' => false, 'code' => 400, 'data' => $payout_data, "message" => "No data found"], 200);
}
}
public function constructUtrDetails($invoice_id)
{
$utr_data = $this->invoiceUtrModel->where('is_active', 1)->where('invoice_id', $invoice_id)->findAll();
$summary_data = $this->invoiceModel->utrSummary($invoice_id);
if($summary_data['invoice_amount'] == $summary_data['total_utr_amount']) {
$data['invoice_completed'] = true;
}
$data['utr_list_data'] = $utr_data;
$data['summary'] = $summary_data;
$data = view('payout_utr_details', $data);
return $data;
}
public function saveUtrDetails()
{
$data = $this->request->getPost();
$invoice_id = $this->request->getPost('invoice_id') ?? null;
$utr_id = $this->request->getPost('utr_pk') ?? null;
if(isset($data['utr_date'])){
$data['utr_date'] = change_date_format($data['utr_date']);
}
if(!empty($utr_id)){
$update = $this->invoiceUtrModel->where('id', $utr_id)->set($data)->update();
$payout_edit_data = $this->constructUtrDetails($invoice_id);
if($update){
$summary_data = $this->invoiceModel->utrSummary($invoice_id);
if($summary_data['invoice_amount'] == $summary_data['total_utr_amount']){
$sql = "UPDATE partner_invoice SET payout_status = 2 WHERE id = ?";
db_connect()->query($sql, [(int)$invoice_id]);
}
return $this->respond(['status' => true, 'code' => 200, 'data' => $payout_edit_data, "message" => "UTR successfully updated"], 200);
}else{
return $this->respond(['status' => false, 'code' => 400, 'data' => $payout_edit_data, "message" => "Failed to update UTR"], 200);
}
}else{
unset($data['utr_pk']);
$insert_id = $this->invoiceUtrModel->insert($data);
$payout_data = $this->constructUtrDetails($invoice_id);
if($insert_id){
$summary_data = $this->invoiceModel->utrSummary($invoice_id);
if($summary_data['invoice_amount'] == $summary_data['total_utr_amount']){
$sql = "UPDATE partner_invoice SET payout_status = 2 WHERE id = ?";
db_connect()->query($sql, [(int)$invoice_id]);
}
return $this->respond(['status' => true, 'code' => 200, 'data' => $payout_data, "message" => "UTR added successfully"], 200);
}else{
return $this->respond(['status' => false, 'code' => 400, 'data' => $payout_data, "message" => "Failed to add UTR"], 200);
}
}
}
public function removeUtrDetails()
{
$data = $this->request->getPost();
if(isset($data['utr_id'])){
$sql = "UPDATE partner_invoice_utr SET is_active = 0 WHERE id = ?";
$update = db_connect()->query($sql, [$data['utr_id']]);
$payout_data = $this->constructUtrDetails($data['invoice_id'] ?? "");
if($update){
return $this->respond(['status' => true, 'code' => 200, 'data' => $payout_data, "message" => "UTR removed successfully"], 200);
}else{
return $this->respond(['status' => false, 'code' => 400, 'data' => $payout_data, "message" => "Failed to remove UTR"], 200);
}
}else {
return $this->respond(['status' => false, 'code' => 500, 'data' => "", "message" => "Failed to remove UTR"], 200);
}
}
/*************************************************************************************************************/
//... Payout-invoice Mapping Commission's amount and Adjustment's Amount - Data Display
public function invoices()
{
$type = $this->request->getGet('type');
$title = $type === 'add' ? 'Add Payouts'
: ($type === 'edit' ? 'Edit Payouts'
: ($type === 'view' ? 'View Payouts'
: ($type === 'adjustment' ? 'Payouts Adjustment'
: 'Payouts')));
$data['tab_name'] = $title;
$data['page_name'] = $title;
$id = $this->request->getGet('id');
if($type == 'add')
{
$data['agents'] = $this->invoiceModel->agentList(['is_active' => 1]); // common both add and edit
$data['pos_list'] = $this->invoiceModel->posList(['is_active' => 1]); // common both add and edit
}
else
{
$data['agents'] = $this->invoiceModel->agentList(); // common both add and edit
$data['pos_list'] = $this->invoiceModel->posList(); // common both add and edit
}
// $data['checked_policy_numbers'] = [];
// $data['invoice'] = [];
// $data['extra_payouts'] = [];
//... Now Seperated add => 'policy_transaction_payouts1'
//... Now Seperated edit and adjustment => 'policy_transaction_payouts' old file
//... Reason : Due Datatable issues Export button Searching like that so seperated
if ($type === 'add') {
// $invoiceNo = $this->generateInvoiceNumber();
$data['payouts'] = $this->invoiceModel->payoutList(1);
// print_rr($data['payouts']);die();
// print_rr($this->invoiceModel->getLastQuery());die();
// $data['invoice_number'] = $invoiceNo;
return $this->loadLayout('invoice_policy_mapping_add', $data);
}
if (($type === 'edit' || $type === 'view' || $type === 'adjustment') && !empty($id)) {
$invoice = $this->invoiceModel->where('id', $id)->first();
// print_r($invoice);die;
$data['freeze_edit'] = $this->auditHistory->where('table_name', 'partner_invoice')->where('pk', $id)->countAllResults();
if($type === 'view'){ $data['freeze_edit'] = 1; }
// $agentId = $invoice['agent_id'] ?? null;
$posId = $invoice['pos_id'] ?? null;
// $data['payouts'] = $this->invoiceModel->payoutList(2 ,$agentId,$id);
// $data['extra_payouts'] = $agentId ? $this->invoiceModel->payoutList(3, $agentId) : [];
$data['payouts'] = $this->invoiceModel->payoutList(2 ,$posId,$id);
// print_r($data['payouts']);die;
$data['extra_payouts'] = $posId ? $this->invoiceModel->payoutList(3, $posId) : [];
$invoice_items = $this->invoiceItemModel->where('invoice_id', $id)->findAll();
if (!$invoice) { return redirect()->to('payout/invoices')->with('error', 'Invoice not found'); }
$data['invoice'] = $invoice;
$data['invoice_items'] = $invoice_items;
// Initialize array for policy numbers
$data['checked_policy_numbers'] = array_column(array_filter($invoice_items, fn($ii) => isset($ii['is_active']) && $ii['is_active'] == 1),'policy_no');
$data['invoice_number']= $invoice['invoice_no'];
$data['type'] = $type;
$data['payout_status'] = $invoice['payout_status'] ;
// dd($data);
return $this->loadLayout('invoice_policy_mapping', $data);
}
}
//... Payout-invoice Mapping - Save/update/soft Delete/Hard Delete Data
public function saveInvoice()
{
$json = $this->request->getJSON(true);
// print_rr($json);die();
if (!$json) {
return $this->response->setJSON(['error' => 'Invalid JSON','message' => 'Invalid JSON received.'])->setStatusCode(400);
}
$id = $json['invoice_id'] ?? null;
try {
//... ADD Part
if (empty($id)) {
$exists = $this->invoiceModel
->where('invoice_no', $json['invoice_no'])
->first();
if ($exists) {
$InvNum = $this->generateInvoiceNumber($json['agent_id']);
} else {
$InvNum = $json['invoice_no'];
}
$invoiceData = [
'invoice_no' => $InvNum,
'agent_id' => $json['agent_id'],
'invoice_date' => $json['invoice_date'],
'invoice_amount' => $json['invoice_amount'],
'payout_status' => 1,
'broker_id' => 1
];
$invoiceId = $this->invoiceModel->insert($invoiceData);
foreach ($json['policies'] as $p) {
$this->invoiceItemModel->insert([
'invoice_id' => $invoiceId,
'policy_id' => $p['partner_policy_id'],
'policy_no' => $p['policy_no'],
'commission_amount' => $p['commission_amount'],
'is_active' => 1
]);
}
$message = "Invoice created successfully.\nInvoice No: " . $json['invoice_no'];
}
// ... EDIT part
if (!empty($id)) {
$invoiceId = $id;
$invoiceData = [
'invoice_no' => $json['invoice_no'],
// 'agent_id' => $json['agent_id'] ?? null,
'invoice_date' => $json['invoice_date'],
'invoice_amount' => $json['invoice_amount'],
];
$this->invoiceModel->update($invoiceId, $invoiceData);
//... Fetch existing invoice item rows
$existingItems = $this->invoiceItemModel
->where('invoice_id', $invoiceId)
->findAll();
//... Create map by policy_no
$existingMap = [];
foreach ($existingItems as $item) {
$existingMap[$item['policy_no']] = $item;
}
$newPolicyNos = [];
//... Loop new JSON policies
foreach ($json['policies'] as $p) {
$newPolicyNos[] = $p['policy_no'];
if (isset($existingMap[$p['policy_no']])) {
//... Update existing item
$this->invoiceItemModel
->where('id', $existingMap[$p['policy_no']]['id'])
->set([
'commission_amount' => $p['commission_amount'],
'is_active' => 1
])
->update();
} else {
//... Insert new item
$this->invoiceItemModel->insert([
'invoice_id' => $invoiceId,
'policy_id' => $p['policy_id'],
'policy_no' => $p['policy_no'],
'commission_amount' => $p['commission_amount'],
'is_active' => 1,
]);
}
}
//... Delete items removed in JSON (hard delete)
foreach ($existingItems as $old) {
if (!in_array($old['policy_no'], $newPolicyNos)) {
$this->invoiceItemModel
->where('id', $old['id'])
->delete();
}
}
//... Delete items removed in JSON (soft delete REF : SVM )
// foreach ($existingItems as $old) {
// if (!in_array($old['policy_no'], $newPolicyNos)) {
// $this->invoiceItemModel
// ->where('id', $old['id'])
// ->set(['is_active' => 0])
// ->update();
// }
// }
$message = "Invoice updated successfully.";
}
return $this->response->setJSON([
'status' => 'success',
'message' => $message,
'invoice_id' => $invoiceId
]);
} catch (\Exception $e) {
return $this->response->setJSON([
'status' => 'error',
'message' => 'Unexpected error occurred: ' . $e->getMessage()
]);
}
}
//... Payout-invoice Mapping - Invoice number is auto-generated only for the Add mode.
// Note New Pattern : INV/AG001/20251101/xx (REF:SVM)
public function generateInvoiceNumberAjax($agentId)
{
if (!$agentId) {
return $this->response->setJSON([
'status' => 'error',
'message' => 'Agent ID missing'
]);
}
$invoiceNo = $this->generateInvoiceNumber($agentId);
return $this->response->setJSON([
'status' => 'success',
'invoice_no' => $invoiceNo
]);
}
//... Payout-invoice Mapping - Invoice number is auto-generated only for the Add mode.
// Note New Pattern : INV/AG001/20251101/xx (REF:SVM)
private function generateInvoiceNumber($agentId)
{
$agent = $this->invoiceModel->agentListById($agentId);
$agentCode = $agent["agent_code"];
$today = date("Ymd");
$likePattern = "NIIB/$agentCode/$today/%";
$count = $this->invoiceModel
->like("invoice_no", $likePattern)
->countAllResults();
$nextNumber = $count + 1;
return "NIIB/$agentCode/$today/$nextNumber";
}
// private function generateInvoiceNumber()
// {
// $year = date('Y');
// $month = date('m');
// do {
// // random 3-digit number
// $random = str_pad(rand(1, 999), 3, '0', STR_PAD_LEFT);
// $invoiceNo = "INV{$year}{$month}{$random}";
// // check main invoice table
// $existsMain = $this->invoiceModel
// ->where('invoice_no', $invoiceNo)
// ->first();
// // check partner invoice table
// $existsPartner = $this->invoiceModel
// ->where('invoice_no', $invoiceNo)
// ->first();
// } while ($existsMain || $existsPartner); // regenerate if duplicate found
// return $invoiceNo;
// }
//... Payout-invoice Mapping Audit History Based on "Adjustment" value (REF: KV,SVM)
public function auditHistory()
{
$iid = $this->request->getGet('id');
$details['invoice'] = $this->auditHistory
->select('auditing_history.*,partner_invoice.invoice_no, user_profiles.first_name as created_name')
->join('user_profiles', 'user_profiles.id = auditing_history.created_by', 'left')
->join('partner_invoice', 'partner_invoice.id = auditing_history.pk', 'left')
->where('auditing_history.table_name', 'partner_invoice') // ok
->where('auditing_history.pk', $iid)
->orderBy('auditing_history.created_at', 'desc')
->get()
->getResultArray();
$details['invoice_child'] = $this->auditHistory
->select('auditing_history.*,partner_invoice.invoice_no, user_profiles.first_name as created_name,partner_invoice_items.policy_no')
->join('user_profiles', 'user_profiles.id = auditing_history.created_by', 'left')
->join('partner_invoice_items', 'partner_invoice_items.id = auditing_history.pk', 'left')
->join('partner_invoice', 'partner_invoice.id = partner_invoice_items.invoice_id', 'left')
->where('auditing_history.table_name', 'partner_invoice_items') // FIXED
->where('partner_invoice.id', $iid)
->orderBy('auditing_history.created_at', 'desc')
->get()
->getResultArray();
return $this->response->setJSON([
'status' => 'success',
'data' => $details
]);
}
// ****************************************************************************************************************************************************************
public function preview($invoiceId = null)
{
$invoiceId = $this->request->getGet('invoice_id');
// Get invoice data from database
$invoiceData = $this->getInvoiceData($invoiceId);
// print_r($invoiceData);die;
if (empty($invoiceData)) {
return $this->respond([
'status' => false,
'code' => 404,
'data' => '',
'message' => 'Invoice not found'
], 200);
}
// Load view with data
$html = view('invoice_template_2', $invoiceData);
// echo $html; die;
return $this->respond([
'status' => true,
'code' => 200,
'data' => $html
], 200);
}
public function downloadPdf($invoiceId = null, $type = 0)
{
// Get invoice data from database
$invoiceData = $this->getInvoiceData($invoiceId);
if (empty($invoiceData)) {
return redirect()->back()->with('error', 'Invoice not found');
}
// Generate HTML
$html = view('invoice_template_2', $invoiceData);
// Configure Dompdf
$options = new Options();
$options->set('isHtml5ParserEnabled', true);
$options->set('isPhpEnabled', true);
$options->set('isRemoteEnabled', true);
$options->set('defaultFont', 'Arial');
$options->set('chroot', FCPATH);
// Initialize Dompdf
$dompdf = new Dompdf($options);
// Load HTML
$dompdf->loadHtml($html);
// Set paper size and orientation
$dompdf->setPaper('A4', 'portrait');
// Render PDF
$dompdf->render();
// Generate filename
$filename = 'Invoice_' . $invoiceData['invoice_no'] . '_' . date('Ymd') . '.pdf';
if($type == 0){
// Download PDF
return $this->response
->setHeader('Content-Type', 'application/pdf')
->setHeader('Content-Disposition', 'attachment; filename="' . $filename . '"')
->setBody($dompdf->output());
}else{
// View PDF
return $this->response
->setHeader('Content-Type', 'application/pdf')
->setHeader('Content-Disposition', 'inline; filename="' . $filename . '"')
->setBody($dompdf->output());
}
}
// private function getInvoiceData($invoiceId)
// {
// $invoice_data = $this->invoiceModel
// ->select('
// partner_invoice.*,
// pa.name as agent_name,
// pa.email as agent_email,
// pa.mobile as agent_mobile,
// pa.address as agent_address,
// pa.agent_code,
// pa.certificate_file_name,
// pa.commission_retain
// ')
// ->join('partner_agent pa', 'partner_invoice.agent_id = pa.id')
// ->where('partner_invoice.is_active', 1)
// ->where('partner_invoice.id', $invoiceId)
// ->first();
// return $invoice_data;
// }
private function getInvoiceData($invoiceId)
{
$invoice_data = $this->invoiceModel
->select('
partner_invoice.*,
pa.name as agent_name,
pa.email as agent_email,
pa.mobile as agent_mobile,
pa.address as agent_address,
pa.agent_code,
pa.certificate_file_name,
pa.commission_retain,
pos.name as pos_name,
pos.email as pos_email,
pos.mobile as pos_mobile,
pos.address as pos_address,
pos.city as pos_city,
pos.pincode as pos_pincode,
pos.state as pos_state,
pos.pos_code,
pos.certificate_file_name as pos_certificate_file_name,
pos.bank_name,pos.account_holder_name,pos.account_number,pos.ifsc_code,
')
->join('partner_agent pa', 'partner_invoice.agent_id = pa.id','left')
->join('partner_pos pos', 'partner_invoice.pos_id = pos.id')
->where('partner_invoice.is_active', 1)
->where('partner_invoice.id', $invoiceId)
->first();
return $invoice_data;
}
}