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() { $raw_json = $this->request->getJSON(true); // 1. Check if the JSON was actually valid/parsed before sanitizing if (is_null($raw_json)) { return $this->response->setJSON(['error' => 'Invalid JSON','message' => 'Invalid JSON received.'])->setStatusCode(400); } // 2. Sanitize the data $json = sanitizeInputArrayAdvanced($raw_json); // 3. Now you can safely use $json (even if it is an empty array) $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; } }