Fix HTTP 500 on GRN view/edit: add self-healing schema migration and null-safe view rendering

This commit is contained in:
DevSoftTech Server 2026-10-22 10:44:27 +05:30
parent 09cd46d344
commit deea6529f7
4 changed files with 242 additions and 56 deletions

View File

@ -25,6 +25,46 @@ class MedicalProcurement extends BaseController
$this->poItemModel = new PharmacyPurchaseOrderItemModel();
$this->grnModel = new PharmacyGrnModel();
$this->grnItemModel = new PharmacyGrnItemModel();
$this->ensureGrnSchema();
}
private function ensureGrnSchema(): void
{
try {
if (!$this->db->tableExists('mst_grns')) {
return;
}
if (!$this->db->fieldExists('cgst_amount', 'mst_grns')) {
$this->db->query("ALTER TABLE `mst_grns` ADD COLUMN `cgst_amount` DECIMAL(10,2) DEFAULT 0.00 AFTER `total_tax_amount`");
}
if (!$this->db->fieldExists('sgst_amount', 'mst_grns')) {
$this->db->query("ALTER TABLE `mst_grns` ADD COLUMN `sgst_amount` DECIMAL(10,2) DEFAULT 0.00 AFTER `cgst_amount`");
}
if (!$this->db->fieldExists('igst_amount', 'mst_grns')) {
$this->db->query("ALTER TABLE `mst_grns` ADD COLUMN `igst_amount` DECIMAL(10,2) DEFAULT 0.00 AFTER `sgst_amount`");
}
if (!$this->db->fieldExists('round_off', 'mst_grns')) {
$this->db->query("ALTER TABLE `mst_grns` ADD COLUMN `round_off` DECIMAL(6,2) DEFAULT 0.00 AFTER `igst_amount`");
}
if (!$this->db->fieldExists('gst_type', 'mst_grns')) {
$this->db->query("ALTER TABLE `mst_grns` ADD COLUMN `gst_type` VARCHAR(20) DEFAULT 'intra_state' AFTER `round_off`");
}
if ($this->db->tableExists('mst_grn_items')) {
if (!$this->db->fieldExists('gross_amount', 'mst_grn_items')) {
$this->db->query("ALTER TABLE `mst_grn_items` ADD COLUMN `gross_amount` DECIMAL(12,2) DEFAULT 0.00 AFTER `unit_purchase_rate`");
}
if (!$this->db->fieldExists('sch_disc_per', 'mst_grn_items')) {
$this->db->query("ALTER TABLE `mst_grn_items` ADD COLUMN `sch_disc_per` DECIMAL(5,2) DEFAULT 0.00 AFTER `discount_percent`");
}
if (!$this->db->fieldExists('sch_disc_amt', 'mst_grn_items')) {
$this->db->query("ALTER TABLE `mst_grn_items` ADD COLUMN `sch_disc_amt` DECIMAL(10,2) DEFAULT 0.00 AFTER `sch_disc_per`");
}
}
} catch (\Throwable $e) {
log_message('error', 'ensureGrnSchema: ' . $e->getMessage());
}
}
private function ensurePharmacyAccess()

View File

@ -0,0 +1,120 @@
<?php
namespace App\Database\Migrations;
use CodeIgniter\Database\Migration;
class AddGrnEnhancementsColumns extends Migration
{
public function up(): void
{
// 1. Enhancements to mst_grns
if ($this->tableExists('mst_grns')) {
$colsToAdd = [];
if (!$this->fieldExists('mst_grns', 'cgst_amount')) {
$colsToAdd['cgst_amount'] = [
'type' => 'DECIMAL',
'constraint' => '10,2',
'default' => 0.00,
'after' => 'total_tax_amount',
];
}
if (!$this->fieldExists('mst_grns', 'sgst_amount')) {
$colsToAdd['sgst_amount'] = [
'type' => 'DECIMAL',
'constraint' => '10,2',
'default' => 0.00,
'after' => 'cgst_amount',
];
}
if (!$this->fieldExists('mst_grns', 'igst_amount')) {
$colsToAdd['igst_amount'] = [
'type' => 'DECIMAL',
'constraint' => '10,2',
'default' => 0.00,
'after' => 'sgst_amount',
];
}
if (!$this->fieldExists('mst_grns', 'round_off')) {
$colsToAdd['round_off'] = [
'type' => 'DECIMAL',
'constraint' => '6,2',
'default' => 0.00,
'after' => 'igst_amount',
];
}
if (!$this->fieldExists('mst_grns', 'gst_type')) {
$colsToAdd['gst_type'] = [
'type' => 'VARCHAR',
'constraint' => 20,
'default' => 'intra_state',
'after' => 'round_off',
];
}
if (!empty($colsToAdd)) {
$this->forge->addColumn('mst_grns', $colsToAdd);
}
}
// 2. Enhancements to mst_grn_items
if ($this->tableExists('mst_grn_items')) {
$itemColsToAdd = [];
if (!$this->fieldExists('mst_grn_items', 'gross_amount')) {
$itemColsToAdd['gross_amount'] = [
'type' => 'DECIMAL',
'constraint' => '12,2',
'default' => 0.00,
'after' => 'unit_purchase_rate',
];
}
if (!$this->fieldExists('mst_grn_items', 'sch_disc_per')) {
$itemColsToAdd['sch_disc_per'] = [
'type' => 'DECIMAL',
'constraint' => '5,2',
'default' => 0.00,
'after' => 'discount_percent',
];
}
if (!$this->fieldExists('mst_grn_items', 'sch_disc_amt')) {
$itemColsToAdd['sch_disc_amt'] = [
'type' => 'DECIMAL',
'constraint' => '10,2',
'default' => 0.00,
'after' => 'sch_disc_per',
];
}
if (!empty($itemColsToAdd)) {
$this->forge->addColumn('mst_grn_items', $itemColsToAdd);
}
}
}
public function down(): void
{
if ($this->tableExists('mst_grn_items')) {
foreach (['sch_disc_amt', 'sch_disc_per', 'gross_amount'] as $col) {
if ($this->fieldExists('mst_grn_items', $col)) {
$this->forge->dropColumn('mst_grn_items', $col);
}
}
}
if ($this->tableExists('mst_grns')) {
foreach (['gst_type', 'round_off', 'igst_amount', 'sgst_amount', 'cgst_amount'] as $col) {
if ($this->fieldExists('mst_grns', $col)) {
$this->forge->dropColumn('mst_grns', $col);
}
}
}
}
private function tableExists(string $table): bool
{
return $this->db->tableExists($table);
}
private function fieldExists(string $table, string $field): bool
{
return $this->db->fieldExists($field, $table);
}
}

View File

@ -2,7 +2,7 @@
<div>
<h4 class="mb-0 text-success">
<i class="bi bi-card-checklist"></i> GRN Inspection Details
<span class="badge bg-light text-dark border ms-2 font-monospace"><?= esc($grn['grn_number']) ?></span>
<span class="badge bg-light text-dark border ms-2 font-monospace"><?= esc($grn['grn_number'] ?? 'GRN') ?></span>
</h4>
<small class="text-muted">Inward Goods Inspection &amp; Live Stock Posting</small>
</div>
@ -10,9 +10,11 @@
<a href="javascript:load_form_div('<?= base_url('Medical/grn_list') ?>','medical-main','GRN Register :Pharmacy');" class="btn btn-outline-secondary btn-sm">
<i class="bi bi-arrow-left"></i> Back to GRN List
</a>
<a href="<?= base_url('Medical/grn_print/' . $grn['grn_id']) ?>" target="_blank" class="btn btn-outline-secondary btn-sm">
<i class="bi bi-printer"></i> Print Slip
</a>
<?php if (!empty($grn['grn_id'])): ?>
<a href="<?= base_url('Medical/grn_print/' . (int)$grn['grn_id']) ?>" target="_blank" class="btn btn-outline-secondary btn-sm">
<i class="bi bi-printer"></i> Print Slip
</a>
<?php endif; ?>
</div>
</div>
@ -21,19 +23,19 @@
<div class="row g-3">
<div class="col-md-3">
<small class="text-muted d-block">Supplier / Vendor</small>
<strong><?= esc($grn['name_supplier']) ?></strong>
<strong><?= esc($grn['name_supplier'] ?? 'Supplier') ?></strong>
</div>
<div class="col-md-2">
<small class="text-muted d-block">Vendor Invoice #</small>
<strong><?= esc($grn['supplier_invoice_no']) ?></strong>
<strong><?= esc($grn['supplier_invoice_no'] ?? '-') ?></strong>
</div>
<div class="col-md-2">
<small class="text-muted d-block">Invoice Date</small>
<span><?= date('d-M-Y', strtotime($grn['invoice_date'])) ?></span>
<span><?= !empty($grn['invoice_date']) ? date('d-M-Y', strtotime($grn['invoice_date'])) : '-' ?></span>
</div>
<div class="col-md-2">
<small class="text-muted d-block">GRN Date</small>
<span><?= date('d-M-Y', strtotime($grn['grn_date'])) ?></span>
<span><?= !empty($grn['grn_date']) ? date('d-M-Y', strtotime($grn['grn_date'])) : '-' ?></span>
</div>
<div class="col-md-3">
<small class="text-muted d-block">Linked PO</small>
@ -56,8 +58,8 @@
<div class="card shadow-sm border-0 mb-3">
<div class="card-header bg-light py-2 d-flex justify-content-between align-items-center">
<strong class="text-secondary"><i class="bi bi-capsule"></i> Verified Medicine Items</strong>
<span class="badge bg-<?= ($grn['status'] === 'posted_to_inventory') ? 'success' : 'info text-dark' ?> text-uppercase">
<?= str_replace('_', ' ', esc($grn['status'])) ?>
<span class="badge bg-<?= (($grn['status'] ?? '') === 'posted_to_inventory') ? 'success' : 'info text-dark' ?> text-uppercase">
<?= str_replace('_', ' ', esc($grn['status'] ?? 'draft')) ?>
</span>
</div>
<div class="card-body p-0">
@ -91,44 +93,56 @@
<?php if (!empty($grnItems)): ?>
<?php foreach ($grnItems as $idx => $it): ?>
<?php
$gross = (float)($it['gross_amount'] ?: ((float)$it['received_packs'] * (float)$it['unit_purchase_rate']));
$recPacks = (float)($it['received_packs'] ?? 0);
$rate = (float)($it['unit_purchase_rate'] ?? 0);
$gross = isset($it['gross_amount']) && (float)$it['gross_amount'] > 0
? (float)$it['gross_amount']
: round($recPacks * $rate, 2);
$schPer = (float)($it['sch_disc_per'] ?? 0);
$schAmt = (float)($it['sch_disc_amt'] ?? 0);
$schTotal = ($schPer > 0 ? ($gross * $schPer / 100) : 0) + $schAmt;
$tradeDisc = (float)$it['discount_percent'];
$schTotal = ($schPer > 0 ? round($gross * $schPer / 100, 2) : 0) + $schAmt;
$tradeDisc = (float)($it['discount_percent'] ?? 0);
$afterSch = max(0, $gross - $schTotal);
$tradeDiscAmt = ($tradeDisc > 0) ? ($afterSch * $tradeDisc / 100) : 0;
$tradeDiscAmt = ($tradeDisc > 0) ? round($afterSch * $tradeDisc / 100, 2) : 0;
$rowDisc = $schTotal + $tradeDiscAmt;
$totalGross += $gross;
$totalDiscount += $rowDisc;
$isInter = (!empty($grn['gst_type']) && $grn['gst_type'] === 'inter_state') || ((float)$it['igst_percent'] > 0);
$cgstPer = (float)($it['cgst_percent'] ?? 0);
$sgstPer = (float)($it['sgst_percent'] ?? 0);
$igstPer = (float)($it['igst_percent'] ?? 0);
$isInter = (!empty($grn['gst_type']) && $grn['gst_type'] === 'inter_state') || ($igstPer > 0);
$gstLabel = $isInter
? number_format((float)$it['igst_percent'], 1) . '% IGST'
: number_format((float)$it['cgst_percent'] + (float)$it['sgst_percent'], 0) . '% (' . number_format((float)$it['cgst_percent'], 1) . '+' . number_format((float)$it['sgst_percent'], 1) . '%)';
? number_format($igstPer, 1) . '% IGST'
: number_format($cgstPer + $sgstPer, 0) . '% (' . number_format($cgstPer, 1) . '+' . number_format($sgstPer, 1) . '%)';
$taxableAmt = isset($it['taxable_amount']) ? (float)$it['taxable_amount'] : ($gross - $rowDisc);
$totalAmt = isset($it['total_amount']) ? (float)$it['total_amount'] : ($taxableAmt + ($taxableAmt * ($cgstPer + $sgstPer + $igstPer) / 100));
?>
<tr>
<td><?= $idx + 1 ?></td>
<td>
<strong><?= esc($it['item_name']) ?></strong>
<strong><?= esc($it['item_name'] ?? 'Item') ?></strong>
<?php if (!empty($it['rejected_packs']) && (float)$it['rejected_packs'] > 0): ?>
<small class="d-block text-danger">Damaged: <?= (float)$it['rejected_packs'] ?> (<?= esc($it['rejection_reason'] ?: 'Damaged') ?>)</small>
<small class="d-block text-danger">Damaged: <?= (float)$it['rejected_packs'] ?> (<?= esc($it['rejection_reason'] ?? 'Damaged') ?>)</small>
<?php endif; ?>
</td>
<td><span class="badge bg-light text-dark font-monospace border"><?= esc($it['batch_no']) ?></span></td>
<td><?= date('d-M-Y', strtotime($it['expiry_date'])) ?></td>
<td class="text-center"><?= (int)$it['packing'] ?>s</td>
<td class="text-center fw-bold"><?= (float)$it['received_packs'] ?></td>
<td class="text-center text-success"><?= (float)$it['free_packs'] ?></td>
<td class="text-end">₹<?= number_format((float)$it['unit_purchase_rate'], 2) ?></td>
<td class="text-end">₹<?= number_format((float)$it['mrp'], 2) ?></td>
<td><span class="badge bg-light text-dark font-monospace border"><?= esc($it['batch_no'] ?? '-') ?></span></td>
<td><?= !empty($it['expiry_date']) ? date('d-M-Y', strtotime($it['expiry_date'])) : '-' ?></td>
<td class="text-center"><?= (int)($it['packing'] ?? 1) ?>s</td>
<td class="text-center fw-bold"><?= $recPacks ?></td>
<td class="text-center text-success"><?= (float)($it['free_packs'] ?? 0) ?></td>
<td class="text-end">₹<?= number_format($rate, 2) ?></td>
<td class="text-end">₹<?= number_format((float)($it['mrp'] ?? 0), 2) ?></td>
<td class="text-end font-monospace">₹<?= number_format($gross, 2) ?></td>
<td class="text-center"><?= number_format($tradeDisc, 1) ?>%</td>
<td class="text-end text-muted font-monospace">₹<?= number_format($schTotal, 2) ?></td>
<td class="text-end font-monospace fw-semibold">₹<?= number_format((float)$it['taxable_amount'], 2) ?></td>
<td class="text-end font-monospace fw-semibold">₹<?= number_format($taxableAmt, 2) ?></td>
<td class="text-center small"><?= esc($gstLabel) ?></td>
<td class="text-end font-monospace fw-semibold">₹<?= number_format((float)$it['total_amount'], 2) ?></td>
<td class="text-end font-monospace fw-semibold">₹<?= number_format($totalAmt, 2) ?></td>
<td class="text-center">
<?php if (!empty($it['purchase_item_id'])): ?>
<span class="badge bg-success font-monospace">Item #<?= (int)$it['purchase_item_id'] ?></span>
@ -153,30 +167,30 @@
</tr>
<tr>
<th colspan="12" class="text-end text-dark">Taxable Amount:</th>
<th colspan="3" class="text-end font-monospace fw-bold">₹<?= number_format((float)$grn['total_received_amount'], 2) ?></th>
<th colspan="3" class="text-end font-monospace fw-bold">₹<?= number_format((float)($grn['total_received_amount'] ?? $totalGross), 2) ?></th>
<th></th>
</tr>
<?php if (!empty($grn['gst_type']) && $grn['gst_type'] === 'inter_state'): ?>
<tr>
<th colspan="12" class="text-end text-muted">IGST Amount:</th>
<th colspan="3" class="text-end font-monospace text-primary">₹<?= number_format((float)($grn['igst_amount'] ?? $grn['total_tax_amount']), 2) ?></th>
<th colspan="3" class="text-end font-monospace text-primary">₹<?= number_format((float)($grn['igst_amount'] ?? ($grn['total_tax_amount'] ?? 0)), 2) ?></th>
<th></th>
</tr>
<?php else: ?>
<tr>
<th colspan="12" class="text-end text-muted">CGST Amount:</th>
<th colspan="3" class="text-end font-monospace text-primary">₹<?= number_format((float)($grn['cgst_amount'] ?? ((float)$grn['total_tax_amount'] / 2)), 2) ?></th>
<th colspan="3" class="text-end font-monospace text-primary">₹<?= number_format((float)($grn['cgst_amount'] ?? (((float)($grn['total_tax_amount'] ?? 0)) / 2)), 2) ?></th>
<th></th>
</tr>
<tr>
<th colspan="12" class="text-end text-muted">SGST Amount:</th>
<th colspan="3" class="text-end font-monospace text-primary">₹<?= number_format((float)($grn['sgst_amount'] ?? ((float)$grn['total_tax_amount'] / 2)), 2) ?></th>
<th colspan="3" class="text-end font-monospace text-primary">₹<?= number_format((float)($grn['sgst_amount'] ?? (((float)($grn['total_tax_amount'] ?? 0)) / 2)), 2) ?></th>
<th></th>
</tr>
<?php endif; ?>
<tr>
<th colspan="12" class="text-end text-dark">Total GST:</th>
<th colspan="3" class="text-end font-monospace fw-bold">₹<?= number_format((float)$grn['total_tax_amount'], 2) ?></th>
<th colspan="3" class="text-end font-monospace fw-bold">₹<?= number_format((float)($grn['total_tax_amount'] ?? 0), 2) ?></th>
<th></th>
</tr>
<?php if (isset($grn['round_off']) && (float)$grn['round_off'] != 0): ?>
@ -188,7 +202,7 @@
<?php endif; ?>
<tr class="table-success">
<th colspan="12" class="text-end fs-6">Net Inward Bill Total (Grand Total):</th>
<th colspan="3" class="text-end fs-6 font-monospace text-success fw-bold">₹<?= number_format((float)$grn['net_amount'], 2) ?></th>
<th colspan="3" class="text-end fs-6 font-monospace text-success fw-bold">₹<?= number_format((float)($grn['net_amount'] ?? 0), 2) ?></th>
<th></th>
</tr>
</tfoot>
@ -200,9 +214,9 @@
<div class="card p-3 border-0 bg-light">
<div class="d-flex justify-content-between align-items-center flex-wrap gap-2">
<div>
<?php if ($grn['status'] === 'posted_to_inventory'): ?>
<?php if (($grn['status'] ?? '') === 'posted_to_inventory'): ?>
<span class="text-success fw-bold">
<i class="bi bi-check-circle-fill"></i> Posted to Live Store Inventory (Purchase Bill Ref #<?= (int)$grn['purchase_id'] ?>)
<i class="bi bi-check-circle-fill"></i> Posted to Live Store Inventory (Purchase Bill Ref #<?= (int)($grn['purchase_id'] ?? 0) ?>)
</span>
<?php else: ?>
<span class="text-warning fw-bold">
@ -211,11 +225,11 @@
<?php endif; ?>
</div>
<div class="d-flex gap-2">
<?php if ($grn['status'] !== 'posted_to_inventory'): ?>
<?php if (($grn['status'] ?? '') !== 'posted_to_inventory' && !empty($grn['grn_id'])): ?>
<button type="button" class="btn btn-success px-4" onclick="postGrnToLiveInventory(<?= (int)$grn['grn_id'] ?>)">
<i class="bi bi-box-arrow-in-down"></i> Post to Live Inventory
</button>
<?php else: ?>
<?php elseif (!empty($grn['purchase_id'])): ?>
<a href="javascript:load_form_div('<?= base_url('Medical/PurchaseInvoiceEdit/' . (int)$grn['purchase_id']) ?>','medical-main');" class="btn btn-outline-primary btn-sm">
<i class="bi bi-receipt"></i> View Purchase Invoice
</a>

View File

@ -86,38 +86,50 @@
<?php if (!empty($items)): ?>
<?php foreach ($items as $idx => $it): ?>
<?php
$gross = (float)($it['gross_amount'] ?: ((float)$it['received_packs'] * (float)$it['unit_purchase_rate']));
$recPacks = (float)($it['received_packs'] ?? 0);
$rate = (float)($it['unit_purchase_rate'] ?? 0);
$gross = isset($it['gross_amount']) && (float)$it['gross_amount'] > 0
? (float)$it['gross_amount']
: round($recPacks * $rate, 2);
$schPer = (float)($it['sch_disc_per'] ?? 0);
$schAmt = (float)($it['sch_disc_amt'] ?? 0);
$schTotal = ($schPer > 0 ? ($gross * $schPer / 100) : 0) + $schAmt;
$tradeDisc = (float)$it['discount_percent'];
$schTotal = ($schPer > 0 ? round($gross * $schPer / 100, 2) : 0) + $schAmt;
$tradeDisc = (float)($it['discount_percent'] ?? 0);
$afterSch = max(0, $gross - $schTotal);
$tradeDiscAmt = ($tradeDisc > 0) ? ($afterSch * $tradeDisc / 100) : 0;
$tradeDiscAmt = ($tradeDisc > 0) ? round($afterSch * $tradeDisc / 100, 2) : 0;
$rowDisc = $schTotal + $tradeDiscAmt;
$pdfGross += $gross;
$pdfDisc += $rowDisc;
$isInter = (!empty($grn['gst_type']) && $grn['gst_type'] === 'inter_state') || ((float)($it['igst_percent'] ?? 0) > 0);
$cgstPer = (float)($it['cgst_percent'] ?? 0);
$sgstPer = (float)($it['sgst_percent'] ?? 0);
$igstPer = (float)($it['igst_percent'] ?? 0);
$isInter = (!empty($grn['gst_type']) && $grn['gst_type'] === 'inter_state') || ($igstPer > 0);
$gstStr = $isInter
? number_format((float)($it['igst_percent'] ?? 0), 0) . '% IGST'
: number_format((float)$it['cgst_percent'] + (float)$it['sgst_percent'], 0) . '%';
? number_format($igstPer, 0) . '% IGST'
: number_format($cgstPer + $sgstPer, 0) . '%';
$taxableAmt = isset($it['taxable_amount']) ? (float)$it['taxable_amount'] : ($gross - $rowDisc);
$totalAmt = isset($it['total_amount']) ? (float)$it['total_amount'] : ($taxableAmt + ($taxableAmt * ($cgstPer + $sgstPer + $igstPer) / 100));
?>
<tr>
<td class="text-center"><?= $idx + 1 ?></td>
<td><strong><?= esc($it['item_name']) ?></strong></td>
<td><?= esc($it['batch_no']) ?></td>
<td><?= date('d-M-Y', strtotime($it['expiry_date'])) ?></td>
<td class="text-center"><?= (int)$it['packing'] ?>s</td>
<td class="text-center"><strong><?= (float)$it['received_packs'] ?></strong></td>
<td class="text-center"><?= (float)$it['free_packs'] ?></td>
<td class="text-end">₹<?= number_format((float)$it['unit_purchase_rate'], 2) ?></td>
<td class="text-end">₹<?= number_format((float)$it['mrp'], 2) ?></td>
<td><strong><?= esc($it['item_name'] ?? 'Item') ?></strong></td>
<td><?= esc($it['batch_no'] ?? '-') ?></td>
<td><?= !empty($it['expiry_date']) ? date('d-M-Y', strtotime($it['expiry_date'])) : '-' ?></td>
<td class="text-center"><?= (int)($it['packing'] ?? 1) ?>s</td>
<td class="text-center"><strong><?= $recPacks ?></strong></td>
<td class="text-center"><?= (float)($it['free_packs'] ?? 0) ?></td>
<td class="text-end">₹<?= number_format($rate, 2) ?></td>
<td class="text-end">₹<?= number_format((float)($it['mrp'] ?? 0), 2) ?></td>
<td class="text-end">₹<?= number_format($gross, 2) ?></td>
<td class="text-center"><?= number_format($tradeDisc, 0) ?>%</td>
<td class="text-end">₹<?= number_format((float)$it['taxable_amount'], 2) ?></td>
<td class="text-end">₹<?= number_format($taxableAmt, 2) ?></td>
<td class="text-center"><?= esc($gstStr) ?></td>
<td class="text-end">₹<?= number_format((float)$it['total_amount'], 2) ?></td>
<td class="text-end">₹<?= number_format($totalAmt, 2) ?></td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
@ -135,7 +147,7 @@
</tr>
<tr>
<td>Taxable Amount:</td>
<td class="text-end">₹<?= number_format((float)$grn['total_received_amount'], 2) ?></td>
<td class="text-end">₹<?= number_format((float)($grn['total_received_amount'] ?? $pdfGross), 2) ?></td>
</tr>
<?php if (!empty($grn['gst_type']) && $grn['gst_type'] === 'inter_state'): ?>
<tr>