diff --git a/app/Config/Routes.php b/app/Config/Routes.php index e69e7d7..59f115f 100755 --- a/app/Config/Routes.php +++ b/app/Config/Routes.php @@ -205,8 +205,13 @@ $routes->group('api', ['filter' => ["jwtAuth:1,2,3,4,agent","appSignature"] ], f $routes->get('invoice/list', 'InvoiceController::invoiceList'); $routes->get('invoice/details', 'InvoiceController::findInvoiceWithItems'); $routes->post('invoice/create-or-update', 'InvoiceController::createOrUpdateInvoice'); - $routes->post('invoice/add-payment', 'InvoiceController::addInvoicePayment'); - $routes->get('invoice/add-payment-history', 'InvoiceController::addPaymentHistory'); + $routes->get('invoice/utrDetails', 'InvoiceController::utrDetails'); + $routes->post('invoice/add-payment', 'InvoiceController::addInvoicePayment'); // tempo + $routes->post('invoice/updateUtrDetails', 'InvoiceController::updateUtrDetails'); + $routes->get('invoice/add-payment-history', 'InvoiceController::addPaymentHistory'); // tempo + $routes->post('invoice/add-payment-history', 'InvoiceController::addPaymentHistory'); // tempo + $routes->get('invoice/listUtrDetails', 'InvoiceController::listUtrDetails'); + $routes->post('invoice/listUtrDetails', 'InvoiceController::listUtrDetails'); $routes->get('invoice/delete', 'InvoiceController::deleteInvoice'); $routes->post('invoice/commission-rate-list', 'InvoiceController::getCommissionRateList'); $routes->get('invoice/getAgentUnusedCommissionList', 'InvoiceController::getAgentUnusedCommissionList'); diff --git a/app/Controllers/InvoiceController.php b/app/Controllers/InvoiceController.php index 9ead9c0..3325e7d 100644 --- a/app/Controllers/InvoiceController.php +++ b/app/Controllers/InvoiceController.php @@ -8,7 +8,6 @@ use App\Models\QuotationModel; use App\Models\InvoiceModel; use App\Models\InvoiceItemModel; use App\Models\InvoiceUtrModel; -use App\Models\PartnerAccountHistoryModel; use App\Models\AgentIncentiveFileModel; use CodeIgniter\Database\Exceptions\DataException; use PhpOffice\PhpSpreadsheet\IOFactory; @@ -21,7 +20,6 @@ class InvoiceController extends ResourceController protected $InvoiceModel; protected $InvoiceItemModel; protected $InvoiceUtrModel; - protected $PartnerAccountHistoryModel; protected $AgentIncentiveFileModel; protected $db; @@ -33,7 +31,6 @@ class InvoiceController extends ResourceController $this->InvoiceModel = new InvoiceModel(); $this->InvoiceItemModel = new InvoiceItemModel(); $this->InvoiceUtrModel = new InvoiceUtrModel(); - $this->PartnerAccountHistoryModel = new PartnerAccountHistoryModel(); $this->AgentIncentiveFileModel = new AgentIncentiveFileModel(); $this->db = \Config\Database::connect(); } @@ -61,13 +58,6 @@ class InvoiceController extends ResourceController ) AS utr_numbers, partner_invoice.invoice_amount AS invoiced_amount, ( - COALESCE(( - SELECT SUM(pah.paid_amount) - FROM partner_account_history pah - WHERE pah.invoice_id = partner_invoice.id - AND pah.is_active = 1 - ), 0.00) - + COALESCE(( SELECT SUM(piu.amount) FROM partner_invoice_utr piu @@ -77,13 +67,6 @@ class InvoiceController extends ResourceController ) AS payout_amount, ( partner_invoice.invoice_amount - ( - COALESCE(( - SELECT SUM(pah.paid_amount) - FROM partner_account_history pah - WHERE pah.invoice_id = partner_invoice.id - AND pah.is_active = 1 - ), 0.00) - + COALESCE(( SELECT SUM(piu.amount) FROM partner_invoice_utr piu @@ -129,18 +112,14 @@ class InvoiceController extends ResourceController ->where('partner_invoice_items.is_active', 1) ->findAll(); - $paymentHistory = $this->PartnerAccountHistoryModel + $paymentHistory = $this->InvoiceUtrModel + ->select('id, invoice_id, amount as paid_amount, utr_no, utr_date as paid_date, created_at, created_by') ->where('invoice_id', $id) ->where('is_active', 1) - ->orderBy('paid_date', 'DESC') + ->where('amount >', 0) ->orderBy('id', 'DESC') ->findAll(); - $paidAmount = 0.00; - foreach ($paymentHistory as $payment) { - $paidAmount += (float) ($payment['paid_amount'] ?? 0); - } - $utrPaidAmount = (float) ( $this->InvoiceUtrModel ->selectSum('amount', 'total') @@ -149,7 +128,7 @@ class InvoiceController extends ResourceController ->first()['total'] ?? 0 ); - $totalPaidAmount = $paidAmount + $utrPaidAmount; + $totalPaidAmount = $utrPaidAmount; $invoiceAmount = (float) ($invoice['invoice_amount'] ?? 0); $balanceAmount = max($invoiceAmount - $totalPaidAmount, 0); @@ -546,7 +525,7 @@ class InvoiceController extends ResourceController } } - public function addInvoicePayment() + public function updateUtrDetails() { $this->db->transBegin(); @@ -556,8 +535,10 @@ class InvoiceController extends ResourceController $invoiceId = (int)($input['invoice_id'] ?? 0); $paidAmount = (float)($input['paid_amount'] ?? 0); $paidDateRaw = $input['paid_date'] ?? null; + $utrId = (int)($input['utr_id'] ?? 0); + $utrNoInput = trim((string)($input['utr_no'] ?? '')); - if ($invoiceId <= 0 || $paidAmount <= 0 || empty($paidDateRaw)) { + if ($invoiceId <= 0 || $paidAmount < 0 || empty($paidDateRaw)) { return $this->respond([ 'status' => 'failed', 'code' => 400, @@ -588,14 +569,6 @@ class InvoiceController extends ResourceController } $paidDate = date('Y-m-d', $paidDateTs); - $historyPaidAmount = (float) ( - $this->PartnerAccountHistoryModel - ->selectSum('paid_amount', 'total') - ->where('invoice_id', $invoiceId) - ->where('is_active', 1) - ->first()['total'] ?? 0 - ); - $utrPaidAmount = (float) ( $this->InvoiceUtrModel ->selectSum('amount', 'total') @@ -604,11 +577,96 @@ class InvoiceController extends ResourceController ->first()['total'] ?? 0 ); - $currentTotalPaid = $historyPaidAmount + $utrPaidAmount; + $currentTotalPaid = $utrPaidAmount; $invoiceAmount = (float) ($invoice['invoice_amount'] ?? 0); $remainingBalance = max($invoiceAmount - $currentTotalPaid, 0); - if ($paidAmount > $remainingBalance) { + /* + * If utr_id is empty/0 from request: + * 1) create a fresh UTR row with given utr_no (or generated fallback), + * 2) keep amount = 0 first, + * 3) then continue existing update flow using the new utr_id. + */ + if ($utrId <= 0) { + $utrNo = $utrNoInput !== '' ? $utrNoInput : ('UTR' . date('YmdHis')); + while ( + !empty( + $this->InvoiceUtrModel + ->where('invoice_id', $invoiceId) + ->where('utr_no', $utrNo) + ->where('is_active', 1) + ->first() + ) + ) { + usleep(200000); + $utrNo = 'UTR' . date('YmdHis'); + } + + $insertedUtrId = $this->InvoiceUtrModel->insert([ + 'invoice_id' => $invoiceId, + 'utr_no' => $utrNo, + 'utr_date' => null, + 'amount' => 0, + 'is_active' => 1, + 'created_at' => date('Y-m-d H:i:s'), + 'created_by' => (int)($input['created_by'] ?? 0), + 'updated_at' => date('Y-m-d H:i:s'), + 'updated_by' => (int)($input['updated_by'] ?? 0), + ]); + + if ($insertedUtrId === false) { + $this->db->transRollback(); + return $this->respond([ + 'status' => 'failed', + 'code' => 500, + 'message'=> 'Failed to create UTR', + 'error' => $this->InvoiceUtrModel->errors() + ], 500); + } + + $utrId = (int)$insertedUtrId; + } + + $utrQuery = $this->InvoiceUtrModel + ->where('invoice_id', $invoiceId) + ->where('is_active', 1) + ->where('id', $utrId); + $utrRow = $utrQuery->first(); + + if (empty($utrRow)) { + return $this->respond([ + 'status' => 'failed', + 'code' => 404, + 'message'=> 'Selected UTR not found for this invoice' + ], 404); + } + + $existingUtrAmount = (float)($utrRow['amount'] ?? 0); + if ($paidAmount > ($remainingBalance + $existingUtrAmount)) { + return $this->respond([ + 'status' => 'failed', + 'code' => 400, + 'message'=> 'Paid amount exceeds invoice balance' + ], 400); + } + if ($paidAmount < $existingUtrAmount) { + return $this->respond([ + 'status' => 'failed', + 'code' => 400, + 'message'=> 'Paid amount cannot be less than existing paid amount' + ], 400); + } + + $otherUtrPaidAmount = (float) ( + $this->InvoiceUtrModel + ->selectSum('amount', 'total') + ->where('invoice_id', $invoiceId) + ->where('is_active', 1) + ->where('id !=', (int)$utrRow['id']) + ->first()['total'] ?? 0 + ); + $maxAllowedForSelectedUtr = max($invoiceAmount - $otherUtrPaidAmount, 0); + if ($paidAmount > $maxAllowedForSelectedUtr) { return $this->respond([ 'status' => 'failed', 'code' => 400, @@ -616,30 +674,24 @@ class InvoiceController extends ResourceController ], 400); } - $historyData = [ - 'invoice_id' => $invoiceId, - 'paid_amount' => $paidAmount, - 'paid_date' => $paidDate, - 'is_active' => 1, - 'created_at' => date('Y-m-d H:i:s'), - 'created_by' => (int)($input['created_by'] ?? 0), - 'updated_at' => date('Y-m-d H:i:s'), - 'updated_by' => (int)($input['updated_by'] ?? 0), - ]; + $updated = $this->InvoiceUtrModel->update((int)$utrRow['id'], [ + 'amount' => $paidAmount, + 'utr_date' => $paidDate, + 'updated_at' => date('Y-m-d H:i:s'), + 'updated_by' => (int)($input['updated_by'] ?? 0), + ]); - $historyId = $this->PartnerAccountHistoryModel->insert($historyData); - - if ($historyId === false) { + if ($updated === false) { $this->db->transRollback(); return $this->respond([ 'status' => 'failed', 'code' => 500, - 'message'=> 'Failed to record payment', - 'error' => $this->PartnerAccountHistoryModel->errors() + 'message'=> 'Failed to update UTR payment', + 'error' => $this->InvoiceUtrModel->errors() ], 500); } - $latestTotalPaid = $currentTotalPaid + $paidAmount; + $latestTotalPaid = ($currentTotalPaid - $existingUtrAmount) + $paidAmount; $newBalance = max($invoiceAmount - $latestTotalPaid, 0); $payoutStatus = $newBalance == 0.0 ? 2 : 1; @@ -660,7 +712,8 @@ class InvoiceController extends ResourceController 'status' => 'success', 'code' => 200, 'data' => [ - 'history_id' => $historyId, + 'utr_id' => (int)$utrRow['id'], + 'utr_no' => (string)$utrRow['utr_no'], 'invoice_id' => $invoiceId, 'paid_amount' => $latestTotalPaid, 'balance_amount' => $newBalance @@ -676,7 +729,12 @@ class InvoiceController extends ResourceController } } - public function addPaymentHistory() + public function addInvoicePayment() + { + return $this->updateUtrDetails(); + } + + public function listUtrDetails() { try { $invoiceId = (int)($this->request->getGet('invoice_id') ?? 0); @@ -702,42 +760,142 @@ class InvoiceController extends ResourceController ], 404); } - $history = $this->db->table('partner_account_history pah') + $history = $this->db->table('partner_invoice_utr piu') ->select(' - pah.id, - pah.invoice_id, + piu.id, + piu.invoice_id, pi.invoice_no, pi.invoice_amount AS total_amount, - pah.paid_amount, - pah.paid_date, - pah.created_at, - COALESCE(ps.name, "-") AS createdby_name, + piu.amount AS paid_amount, + piu.utr_no, + piu.utr_date AS paid_date, + piu.created_at, + COALESCE(psu.name, psc.name, "-") AS createdby_name, ( pi.invoice_amount - COALESCE(( - SELECT SUM(pah2.paid_amount) - FROM partner_account_history pah2 - WHERE pah2.invoice_id = pah.invoice_id - AND pah2.is_active = 1 - AND pah2.id <= pah.id + SELECT SUM(piu2.amount) + FROM partner_invoice_utr piu2 + WHERE piu2.invoice_id = piu.invoice_id + AND piu2.is_active = 1 + AND piu2.amount > 0 + AND piu2.id <= piu.id ), 0) ) AS balance_amount ', false) - ->join('partner_invoice pi', 'pi.id = pah.invoice_id', 'inner') - ->join('partner_staff ps', 'ps.id = pah.created_by', 'left') - ->where('pah.invoice_id', $invoiceId) - ->where('pah.is_active', 1) - ->orderBy('pah.id', 'DESC') + ->join('partner_invoice pi', 'pi.id = piu.invoice_id', 'inner') + ->join('partner_staff psc', 'psc.id = piu.created_by', 'left') + ->join('partner_staff psu', 'psu.id = piu.updated_by', 'left') + ->where('piu.invoice_id', $invoiceId) + ->where('piu.is_active', 1) + ->where('piu.amount >', 0) + ->orderBy('piu.id', 'DESC') ->get() ->getResultArray(); + // Return unique UTR list for this invoice (remove duplicates by utr_no). + // Keep only unpaid UTR rows (amount 0 or null). + $availableUtrs = $this->db->table('partner_invoice_utr') + ->select('MIN(id) as id, utr_no') + ->where('invoice_id', $invoiceId) + ->where('is_active', 1) + ->where('(amount IS NULL OR amount <= 0)', null, false) + ->where('TRIM(COALESCE(utr_no, "")) !=', '') + ->groupBy('utr_no') + ->orderBy('MIN(id)', 'ASC', false) + ->get() + ->getResultArray(); + + $paidToDate = (float) ( + $this->InvoiceUtrModel + ->selectSum('amount', 'total') + ->where('invoice_id', $invoiceId) + ->where('is_active', 1) + ->first()['total'] ?? 0 + ); + $balanceAmount = max(((float)$invoice['invoice_amount']) - $paidToDate, 0); + return $this->respond([ 'status' => 'success', 'code' => 200, 'data' => $history, + 'available_utrs' => $availableUtrs, 'invoice'=> [ 'invoice_id' => (int)$invoice['id'], 'invoice_no' => $invoice['invoice_no'], 'total_amount' => (float)$invoice['invoice_amount'], + 'paid_to_date' => $paidToDate, + 'balance_amount' => $balanceAmount, + ], + ], 200); + } catch (\Exception $e) { + return $this->respond([ + 'status' => 'failed', + 'code' => 500, + 'message'=> $e->getMessage() + ], 500); + } + } + + public function addPaymentHistory() + { + return $this->listUtrDetails(); + } + + public function utrDetails() + { + try { + $invoiceId = (int)($this->request->getGet('invoice_id') ?? 0); + if ($invoiceId <= 0) { + return $this->respond([ + 'status' => 'failed', + 'code' => 400, + 'message'=> 'invoice_id is required' + ], 400); + } + + $invoice = $this->InvoiceModel + ->select('id, invoice_no, invoice_amount') + ->where('id', $invoiceId) + ->where('is_active', 1) + ->first(); + + if (empty($invoice)) { + return $this->respond([ + 'status' => 'failed', + 'code' => 404, + 'message'=> 'Invoice not found' + ], 404); + } + + $utrDetails = $this->InvoiceUtrModel + ->select('id, invoice_id, amount as paid_amount, utr_no, utr_date') + ->where('invoice_id', $invoiceId) + ->where('is_active', 1) + ->orderBy('id', 'ASC') + ->findAll(); + + $paidToDate = (float) ( + $this->InvoiceUtrModel + ->selectSum('amount', 'total') + ->where('invoice_id', $invoiceId) + ->where('is_active', 1) + ->first()['total'] ?? 0 + ); + + $balanceAmount = max(((float)$invoice['invoice_amount']) - $paidToDate, 0); + + return $this->respond([ + 'status' => 'success', + 'code' => 200, + 'data' => [ + 'utrs_details' => $utrDetails, + 'invoice' => [ + 'invoice_id' => (int)$invoice['id'], + 'invoice_no' => $invoice['invoice_no'], + 'total_amount' => (float)$invoice['invoice_amount'], + 'paid_to_date' => $paidToDate, + 'balance_amount' => $balanceAmount, + ], ], ], 200); } catch (\Exception $e) { diff --git a/app/Models/PartnerAccountHistoryModel.php b/app/Models/PartnerAccountHistoryModel.php deleted file mode 100644 index 4d55bf4..0000000 --- a/app/Models/PartnerAccountHistoryModel.php +++ /dev/null @@ -1,39 +0,0 @@ - 'required|integer', - 'paid_amount' => 'required|decimal', - 'paid_date' => 'required|valid_date', - ]; - - protected $validationMessages = []; - protected $skipValidation = false; -}