FIX_UTR Backend Code Changes

This commit is contained in:
sanjeev.p 2026-03-31 18:25:01 +05:30
parent 1407f7c224
commit d6452b7467
3 changed files with 237 additions and 113 deletions

View File

@ -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/list', 'InvoiceController::invoiceList');
$routes->get('invoice/details', 'InvoiceController::findInvoiceWithItems'); $routes->get('invoice/details', 'InvoiceController::findInvoiceWithItems');
$routes->post('invoice/create-or-update', 'InvoiceController::createOrUpdateInvoice'); $routes->post('invoice/create-or-update', 'InvoiceController::createOrUpdateInvoice');
$routes->post('invoice/add-payment', 'InvoiceController::addInvoicePayment'); $routes->get('invoice/utrDetails', 'InvoiceController::utrDetails');
$routes->get('invoice/add-payment-history', 'InvoiceController::addPaymentHistory'); $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->get('invoice/delete', 'InvoiceController::deleteInvoice');
$routes->post('invoice/commission-rate-list', 'InvoiceController::getCommissionRateList'); $routes->post('invoice/commission-rate-list', 'InvoiceController::getCommissionRateList');
$routes->get('invoice/getAgentUnusedCommissionList', 'InvoiceController::getAgentUnusedCommissionList'); $routes->get('invoice/getAgentUnusedCommissionList', 'InvoiceController::getAgentUnusedCommissionList');

View File

@ -8,7 +8,6 @@ use App\Models\QuotationModel;
use App\Models\InvoiceModel; use App\Models\InvoiceModel;
use App\Models\InvoiceItemModel; use App\Models\InvoiceItemModel;
use App\Models\InvoiceUtrModel; use App\Models\InvoiceUtrModel;
use App\Models\PartnerAccountHistoryModel;
use App\Models\AgentIncentiveFileModel; use App\Models\AgentIncentiveFileModel;
use CodeIgniter\Database\Exceptions\DataException; use CodeIgniter\Database\Exceptions\DataException;
use PhpOffice\PhpSpreadsheet\IOFactory; use PhpOffice\PhpSpreadsheet\IOFactory;
@ -21,7 +20,6 @@ class InvoiceController extends ResourceController
protected $InvoiceModel; protected $InvoiceModel;
protected $InvoiceItemModel; protected $InvoiceItemModel;
protected $InvoiceUtrModel; protected $InvoiceUtrModel;
protected $PartnerAccountHistoryModel;
protected $AgentIncentiveFileModel; protected $AgentIncentiveFileModel;
protected $db; protected $db;
@ -33,7 +31,6 @@ class InvoiceController extends ResourceController
$this->InvoiceModel = new InvoiceModel(); $this->InvoiceModel = new InvoiceModel();
$this->InvoiceItemModel = new InvoiceItemModel(); $this->InvoiceItemModel = new InvoiceItemModel();
$this->InvoiceUtrModel = new InvoiceUtrModel(); $this->InvoiceUtrModel = new InvoiceUtrModel();
$this->PartnerAccountHistoryModel = new PartnerAccountHistoryModel();
$this->AgentIncentiveFileModel = new AgentIncentiveFileModel(); $this->AgentIncentiveFileModel = new AgentIncentiveFileModel();
$this->db = \Config\Database::connect(); $this->db = \Config\Database::connect();
} }
@ -61,13 +58,6 @@ class InvoiceController extends ResourceController
) AS utr_numbers, ) AS utr_numbers,
partner_invoice.invoice_amount AS invoiced_amount, 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(( COALESCE((
SELECT SUM(piu.amount) SELECT SUM(piu.amount)
FROM partner_invoice_utr piu FROM partner_invoice_utr piu
@ -77,13 +67,6 @@ class InvoiceController extends ResourceController
) AS payout_amount, ) AS payout_amount,
( (
partner_invoice.invoice_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(( COALESCE((
SELECT SUM(piu.amount) SELECT SUM(piu.amount)
FROM partner_invoice_utr piu FROM partner_invoice_utr piu
@ -129,18 +112,14 @@ class InvoiceController extends ResourceController
->where('partner_invoice_items.is_active', 1) ->where('partner_invoice_items.is_active', 1)
->findAll(); ->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('invoice_id', $id)
->where('is_active', 1) ->where('is_active', 1)
->orderBy('paid_date', 'DESC') ->where('amount >', 0)
->orderBy('id', 'DESC') ->orderBy('id', 'DESC')
->findAll(); ->findAll();
$paidAmount = 0.00;
foreach ($paymentHistory as $payment) {
$paidAmount += (float) ($payment['paid_amount'] ?? 0);
}
$utrPaidAmount = (float) ( $utrPaidAmount = (float) (
$this->InvoiceUtrModel $this->InvoiceUtrModel
->selectSum('amount', 'total') ->selectSum('amount', 'total')
@ -149,7 +128,7 @@ class InvoiceController extends ResourceController
->first()['total'] ?? 0 ->first()['total'] ?? 0
); );
$totalPaidAmount = $paidAmount + $utrPaidAmount; $totalPaidAmount = $utrPaidAmount;
$invoiceAmount = (float) ($invoice['invoice_amount'] ?? 0); $invoiceAmount = (float) ($invoice['invoice_amount'] ?? 0);
$balanceAmount = max($invoiceAmount - $totalPaidAmount, 0); $balanceAmount = max($invoiceAmount - $totalPaidAmount, 0);
@ -546,7 +525,7 @@ class InvoiceController extends ResourceController
} }
} }
public function addInvoicePayment() public function updateUtrDetails()
{ {
$this->db->transBegin(); $this->db->transBegin();
@ -556,8 +535,10 @@ class InvoiceController extends ResourceController
$invoiceId = (int)($input['invoice_id'] ?? 0); $invoiceId = (int)($input['invoice_id'] ?? 0);
$paidAmount = (float)($input['paid_amount'] ?? 0); $paidAmount = (float)($input['paid_amount'] ?? 0);
$paidDateRaw = $input['paid_date'] ?? null; $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([ return $this->respond([
'status' => 'failed', 'status' => 'failed',
'code' => 400, 'code' => 400,
@ -588,14 +569,6 @@ class InvoiceController extends ResourceController
} }
$paidDate = date('Y-m-d', $paidDateTs); $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) ( $utrPaidAmount = (float) (
$this->InvoiceUtrModel $this->InvoiceUtrModel
->selectSum('amount', 'total') ->selectSum('amount', 'total')
@ -604,11 +577,96 @@ class InvoiceController extends ResourceController
->first()['total'] ?? 0 ->first()['total'] ?? 0
); );
$currentTotalPaid = $historyPaidAmount + $utrPaidAmount; $currentTotalPaid = $utrPaidAmount;
$invoiceAmount = (float) ($invoice['invoice_amount'] ?? 0); $invoiceAmount = (float) ($invoice['invoice_amount'] ?? 0);
$remainingBalance = max($invoiceAmount - $currentTotalPaid, 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([ return $this->respond([
'status' => 'failed', 'status' => 'failed',
'code' => 400, 'code' => 400,
@ -616,30 +674,24 @@ class InvoiceController extends ResourceController
], 400); ], 400);
} }
$historyData = [ $updated = $this->InvoiceUtrModel->update((int)$utrRow['id'], [
'invoice_id' => $invoiceId, 'amount' => $paidAmount,
'paid_amount' => $paidAmount, 'utr_date' => $paidDate,
'paid_date' => $paidDate, 'updated_at' => date('Y-m-d H:i:s'),
'is_active' => 1, 'updated_by' => (int)($input['updated_by'] ?? 0),
'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),
];
$historyId = $this->PartnerAccountHistoryModel->insert($historyData); if ($updated === false) {
if ($historyId === false) {
$this->db->transRollback(); $this->db->transRollback();
return $this->respond([ return $this->respond([
'status' => 'failed', 'status' => 'failed',
'code' => 500, 'code' => 500,
'message'=> 'Failed to record payment', 'message'=> 'Failed to update UTR payment',
'error' => $this->PartnerAccountHistoryModel->errors() 'error' => $this->InvoiceUtrModel->errors()
], 500); ], 500);
} }
$latestTotalPaid = $currentTotalPaid + $paidAmount; $latestTotalPaid = ($currentTotalPaid - $existingUtrAmount) + $paidAmount;
$newBalance = max($invoiceAmount - $latestTotalPaid, 0); $newBalance = max($invoiceAmount - $latestTotalPaid, 0);
$payoutStatus = $newBalance == 0.0 ? 2 : 1; $payoutStatus = $newBalance == 0.0 ? 2 : 1;
@ -660,7 +712,8 @@ class InvoiceController extends ResourceController
'status' => 'success', 'status' => 'success',
'code' => 200, 'code' => 200,
'data' => [ 'data' => [
'history_id' => $historyId, 'utr_id' => (int)$utrRow['id'],
'utr_no' => (string)$utrRow['utr_no'],
'invoice_id' => $invoiceId, 'invoice_id' => $invoiceId,
'paid_amount' => $latestTotalPaid, 'paid_amount' => $latestTotalPaid,
'balance_amount' => $newBalance 'balance_amount' => $newBalance
@ -676,7 +729,12 @@ class InvoiceController extends ResourceController
} }
} }
public function addPaymentHistory() public function addInvoicePayment()
{
return $this->updateUtrDetails();
}
public function listUtrDetails()
{ {
try { try {
$invoiceId = (int)($this->request->getGet('invoice_id') ?? 0); $invoiceId = (int)($this->request->getGet('invoice_id') ?? 0);
@ -702,42 +760,142 @@ class InvoiceController extends ResourceController
], 404); ], 404);
} }
$history = $this->db->table('partner_account_history pah') $history = $this->db->table('partner_invoice_utr piu')
->select(' ->select('
pah.id, piu.id,
pah.invoice_id, piu.invoice_id,
pi.invoice_no, pi.invoice_no,
pi.invoice_amount AS total_amount, pi.invoice_amount AS total_amount,
pah.paid_amount, piu.amount AS paid_amount,
pah.paid_date, piu.utr_no,
pah.created_at, piu.utr_date AS paid_date,
COALESCE(ps.name, "-") AS createdby_name, piu.created_at,
COALESCE(psu.name, psc.name, "-") AS createdby_name,
( (
pi.invoice_amount - COALESCE(( pi.invoice_amount - COALESCE((
SELECT SUM(pah2.paid_amount) SELECT SUM(piu2.amount)
FROM partner_account_history pah2 FROM partner_invoice_utr piu2
WHERE pah2.invoice_id = pah.invoice_id WHERE piu2.invoice_id = piu.invoice_id
AND pah2.is_active = 1 AND piu2.is_active = 1
AND pah2.id <= pah.id AND piu2.amount > 0
AND piu2.id <= piu.id
), 0) ), 0)
) AS balance_amount ) AS balance_amount
', false) ', false)
->join('partner_invoice pi', 'pi.id = pah.invoice_id', 'inner') ->join('partner_invoice pi', 'pi.id = piu.invoice_id', 'inner')
->join('partner_staff ps', 'ps.id = pah.created_by', 'left') ->join('partner_staff psc', 'psc.id = piu.created_by', 'left')
->where('pah.invoice_id', $invoiceId) ->join('partner_staff psu', 'psu.id = piu.updated_by', 'left')
->where('pah.is_active', 1) ->where('piu.invoice_id', $invoiceId)
->orderBy('pah.id', 'DESC') ->where('piu.is_active', 1)
->where('piu.amount >', 0)
->orderBy('piu.id', 'DESC')
->get() ->get()
->getResultArray(); ->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([ return $this->respond([
'status' => 'success', 'status' => 'success',
'code' => 200, 'code' => 200,
'data' => $history, 'data' => $history,
'available_utrs' => $availableUtrs,
'invoice'=> [ 'invoice'=> [
'invoice_id' => (int)$invoice['id'], 'invoice_id' => (int)$invoice['id'],
'invoice_no' => $invoice['invoice_no'], 'invoice_no' => $invoice['invoice_no'],
'total_amount' => (float)$invoice['invoice_amount'], '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); ], 200);
} catch (\Exception $e) { } catch (\Exception $e) {

View File

@ -1,39 +0,0 @@
<?php
namespace App\Models;
use CodeIgniter\Model;
class PartnerAccountHistoryModel extends Model
{
protected $table = 'partner_account_history';
protected $primaryKey = 'id';
protected $useAutoIncrement = true;
protected $returnType = 'array';
protected $useSoftDeletes = false;
protected $allowedFields = [
'invoice_id',
'paid_amount',
'paid_date',
'is_active',
'created_at',
'created_by',
'updated_at',
'updated_by',
];
protected $useTimestamps = false;
protected $createdField = 'created_at';
protected $updatedField = 'updated_at';
protected $validationRules = [
'invoice_id' => 'required|integer',
'paid_amount' => 'required|decimal',
'paid_date' => 'required|valid_date',
];
protected $validationMessages = [];
protected $skipValidation = false;
}