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/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');

View File

@ -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) {

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;
}