Fix GST calculations and synchronize GRN & Purchase Invoice columns with vendor bill structure
This commit is contained in:
parent
367f63f4f3
commit
09cd46d344
|
|
@ -569,6 +569,8 @@ class MedicalProcurement extends BaseController
|
|||
$grnDate = trim((string)$this->request->getPost('grn_date') ?: date('Y-m-d'));
|
||||
$remarks = trim((string)$this->request->getPost('remarks') ?: '');
|
||||
$postToInventory = (int)($this->request->getPost('post_to_inventory') ?: 0);
|
||||
$gstType = trim((string)$this->request->getPost('gst_type') ?: 'intra_state');
|
||||
$roundOff = (float)($this->request->getPost('round_off') ?: 0.0);
|
||||
|
||||
$itemsRaw = $this->request->getPost('items');
|
||||
$items = is_array($itemsRaw) ? $itemsRaw : [];
|
||||
|
|
@ -586,9 +588,13 @@ class MedicalProcurement extends BaseController
|
|||
$grnNumber = $this->grnModel->generateGrnNumber();
|
||||
$userId = $this->getCurrentUserId();
|
||||
|
||||
$totalGross = 0.0;
|
||||
$totalDisc = 0.0;
|
||||
$totalTaxable = 0.0;
|
||||
$totalCgst = 0.0;
|
||||
$totalSgst = 0.0;
|
||||
$totalIgst = 0.0;
|
||||
$totalTax = 0.0;
|
||||
$netTotal = 0.0;
|
||||
$validItems = [];
|
||||
|
||||
foreach ($items as $row) {
|
||||
|
|
@ -615,9 +621,12 @@ class MedicalProcurement extends BaseController
|
|||
}
|
||||
|
||||
$discPercent = (float)($row['discount_percent'] ?? 0);
|
||||
$cgstPer = (float)($row['cgst_percent'] ?? 6.0);
|
||||
$sgstPer = (float)($row['sgst_percent'] ?? 6.0);
|
||||
$igstPer = (float)($row['igst_percent'] ?? 0.0);
|
||||
$schDiscPer = (float)($row['sch_disc_per'] ?? 0);
|
||||
$schDiscAmt = (float)($row['sch_disc_amt'] ?? 0);
|
||||
|
||||
// Determine GST total rate: check gst_rate, then fallback to cgst_percent * 2
|
||||
$gstRate = isset($row['gst_rate']) ? (float)$row['gst_rate'] : ((float)($row['cgst_percent'] ?? 2.5) * 2);
|
||||
|
||||
$hsnCode = trim((string)($row['hsn_code'] ?? ''));
|
||||
$rackNo = trim((string)($row['rack_no'] ?? ''));
|
||||
$shelfNo = trim((string)($row['shelf_no'] ?? ''));
|
||||
|
|
@ -631,20 +640,46 @@ class MedicalProcurement extends BaseController
|
|||
continue;
|
||||
}
|
||||
|
||||
// Calculations
|
||||
// Calculations strictly aligned with Indian Pharma Invoicing:
|
||||
$grossAmount = round($receivedPacks * $unitPurchaseRate, 2);
|
||||
$discountAmt = round($grossAmount * ($discPercent / 100), 2);
|
||||
$lineTaxable = $grossAmount - $discountAmt;
|
||||
|
||||
$cgstAmt = round($lineTaxable * ($cgstPer / 100), 2);
|
||||
$sgstAmt = round($lineTaxable * ($sgstPer / 100), 2);
|
||||
$igstAmt = round($lineTaxable * ($igstPer / 100), 2);
|
||||
$lineTax = $cgstAmt + $sgstAmt + $igstAmt;
|
||||
$lineTotal = $lineTaxable + $lineTax;
|
||||
// 1. Scheme discount (percent or amount)
|
||||
$schPerAmt = ($schDiscPer > 0) ? round($grossAmount * ($schDiscPer / 100), 2) : 0.0;
|
||||
$lineSchDisc = $schPerAmt + $schDiscAmt;
|
||||
$afterSch = max(0.0, $grossAmount - $lineSchDisc);
|
||||
|
||||
// 2. Trade discount
|
||||
$tradeDiscAmt = ($discPercent > 0) ? round($afterSch * ($discPercent / 100), 2) : 0.0;
|
||||
$lineTaxable = max(0.0, $afterSch - $tradeDiscAmt);
|
||||
|
||||
// 3. GST Calculation (Equal CGST/SGST split or 100% IGST)
|
||||
if ($gstType === 'inter_state') {
|
||||
$cgstPer = 0.0;
|
||||
$sgstPer = 0.0;
|
||||
$igstPer = $gstRate;
|
||||
$cgstAmt = 0.0;
|
||||
$sgstAmt = 0.0;
|
||||
$igstAmt = round($lineTaxable * ($igstPer / 100), 2);
|
||||
$lineTax = $igstAmt;
|
||||
} else {
|
||||
$cgstPer = round($gstRate / 2, 2);
|
||||
$sgstPer = round($gstRate / 2, 2);
|
||||
$igstPer = 0.0;
|
||||
$cgstAmt = round($lineTaxable * ($cgstPer / 100), 2);
|
||||
$sgstAmt = round($lineTaxable * ($sgstPer / 100), 2);
|
||||
$igstAmt = 0.0;
|
||||
$lineTax = $cgstAmt + $sgstAmt;
|
||||
}
|
||||
|
||||
$lineTotal = round($lineTaxable + $lineTax, 2);
|
||||
|
||||
$totalGross += $grossAmount;
|
||||
$totalDisc += ($lineSchDisc + $tradeDiscAmt);
|
||||
$totalTaxable += $lineTaxable;
|
||||
$totalCgst += $cgstAmt;
|
||||
$totalSgst += $sgstAmt;
|
||||
$totalIgst += $igstAmt;
|
||||
$totalTax += $lineTax;
|
||||
$netTotal += $lineTotal;
|
||||
|
||||
$validItems[] = [
|
||||
'po_item_id' => $poItemId > 0 ? $poItemId : null,
|
||||
|
|
@ -659,9 +694,12 @@ class MedicalProcurement extends BaseController
|
|||
'rejected_packs' => $rejectedPacks,
|
||||
'rejection_reason' => $rejectionReason ?: null,
|
||||
'unit_purchase_rate' => $unitPurchaseRate,
|
||||
'gross_amount' => $grossAmount,
|
||||
'mrp' => $mrp,
|
||||
'selling_unit_rate' => $sellingUnitRate,
|
||||
'discount_percent' => $discPercent,
|
||||
'sch_disc_per' => $schDiscPer,
|
||||
'sch_disc_amt' => $schDiscAmt,
|
||||
'taxable_amount' => $lineTaxable,
|
||||
'cgst_percent' => $cgstPer,
|
||||
'cgst_amount' => $cgstAmt,
|
||||
|
|
@ -681,6 +719,8 @@ class MedicalProcurement extends BaseController
|
|||
return $this->response->setJSON(['status' => 0, 'message' => 'No valid item rows with batch and expiry were found.']);
|
||||
}
|
||||
|
||||
$netTotal = round($totalTaxable + $totalTax + $roundOff, 2);
|
||||
|
||||
$this->db->transStart();
|
||||
|
||||
$grnHeader = [
|
||||
|
|
@ -694,6 +734,11 @@ class MedicalProcurement extends BaseController
|
|||
'grn_date' => $grnDate,
|
||||
'total_received_amount' => $totalTaxable,
|
||||
'total_tax_amount' => $totalTax,
|
||||
'cgst_amount' => $totalCgst,
|
||||
'sgst_amount' => $totalSgst,
|
||||
'igst_amount' => $totalIgst,
|
||||
'round_off' => $roundOff,
|
||||
'gst_type' => $gstType,
|
||||
'net_amount' => $netTotal,
|
||||
'status' => 'verified',
|
||||
'received_by' => $userId,
|
||||
|
|
@ -701,7 +746,6 @@ class MedicalProcurement extends BaseController
|
|||
'verified_at' => date('Y-m-d H:i:s'),
|
||||
'remarks' => $remarks,
|
||||
'created_at' => date('Y-m-d H:i:s'),
|
||||
'updated_at' => date('Y-m-d H:i:s'),
|
||||
];
|
||||
|
||||
$this->grnModel->insert($grnHeader);
|
||||
|
|
@ -812,8 +856,8 @@ class MedicalProcurement extends BaseController
|
|||
'date_of_invoice' => $grn['invoice_date'],
|
||||
'Invoice_no' => $grn['supplier_invoice_no'],
|
||||
'Taxable_Amt' => $grn['total_received_amount'],
|
||||
'CGST_Amt' => round($grn['total_tax_amount'] / 2, 2),
|
||||
'SGST_Amt' => round($grn['total_tax_amount'] / 2, 2),
|
||||
'CGST_Amt' => (float)($grn['cgst_amount'] ?? round($grn['total_tax_amount'] / 2, 2)),
|
||||
'SGST_Amt' => (float)($grn['sgst_amount'] ?? round($grn['total_tax_amount'] / 2, 2)),
|
||||
'T_Net_Amount' => $grn['net_amount'],
|
||||
'inv_status' => 1,
|
||||
'inv_status_update_by' => $userId,
|
||||
|
|
@ -851,14 +895,16 @@ class MedicalProcurement extends BaseController
|
|||
'qty' => $receivedPacks,
|
||||
'qty_free' => $freePacks,
|
||||
'tqty' => $receivedPacks + $freePacks,
|
||||
'amount' => round($receivedPacks * $purchasePricePerPack, 2),
|
||||
'discount' => $gItem['discount_percent'],
|
||||
'taxable_amount' => $gItem['taxable_amount'],
|
||||
'CGST_per' => $gItem['cgst_percent'],
|
||||
'CGST' => $gItem['cgst_amount'],
|
||||
'SGST_per' => $gItem['sgst_percent'],
|
||||
'SGST' => $gItem['sgst_amount'],
|
||||
'net_amount' => $gItem['total_amount'],
|
||||
'amount' => (float)($gItem['gross_amount'] ?: round($receivedPacks * $purchasePricePerPack, 2)),
|
||||
'discount' => (float)($gItem['discount_percent'] ?? 0),
|
||||
'sch_disc_amt' => (float)($gItem['sch_disc_amt'] ?? 0),
|
||||
'sch_disc_per' => (float)($gItem['sch_disc_per'] ?? 0),
|
||||
'taxable_amount' => (float)$gItem['taxable_amount'],
|
||||
'CGST_per' => (float)$gItem['cgst_percent'],
|
||||
'CGST' => (float)$gItem['cgst_amount'],
|
||||
'SGST_per' => (float)$gItem['sgst_percent'],
|
||||
'SGST' => (float)$gItem['sgst_amount'],
|
||||
'net_amount' => (float)$gItem['total_amount'],
|
||||
'HSNCODE' => $gItem['hsn_code'] ?: '',
|
||||
'selling_price' => $gItem['selling_unit_rate'] * $packing,
|
||||
'total_unit' => $totalUnits,
|
||||
|
|
|
|||
|
|
@ -24,9 +24,12 @@ class PharmacyGrnItemModel extends Model
|
|||
'rejected_packs',
|
||||
'rejection_reason',
|
||||
'unit_purchase_rate',
|
||||
'gross_amount',
|
||||
'mrp',
|
||||
'selling_unit_rate',
|
||||
'discount_percent',
|
||||
'sch_disc_per',
|
||||
'sch_disc_amt',
|
||||
'taxable_amount',
|
||||
'cgst_percent',
|
||||
'cgst_amount',
|
||||
|
|
|
|||
|
|
@ -21,6 +21,11 @@ class PharmacyGrnModel extends Model
|
|||
'grn_date',
|
||||
'total_received_amount',
|
||||
'total_tax_amount',
|
||||
'cgst_amount',
|
||||
'sgst_amount',
|
||||
'igst_amount',
|
||||
'round_off',
|
||||
'gst_type',
|
||||
'net_amount',
|
||||
'status',
|
||||
'purchase_id',
|
||||
|
|
|
|||
|
|
@ -62,45 +62,73 @@
|
|||
</div>
|
||||
<div class="card-body p-0">
|
||||
<div class="table-responsive">
|
||||
<table class="table table-sm table-striped align-middle mb-0">
|
||||
<table class="table table-sm table-striped align-middle mb-0" style="font-size: 13px;">
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
<th style="width: 40px;">#</th>
|
||||
<th>Product Name</th>
|
||||
<th>Batch No</th>
|
||||
<th>Expiry Date</th>
|
||||
<th class="text-center">Pack</th>
|
||||
<th class="text-center">Rec. Packs</th>
|
||||
<th class="text-center">Free</th>
|
||||
<th class="text-center">Rejected</th>
|
||||
<th class="text-end">Rate/Pack</th>
|
||||
<th class="text-end">MRP</th>
|
||||
<th class="text-center">GST %</th>
|
||||
<th class="text-end">Line Total</th>
|
||||
<th class="text-center">Live Stock ID</th>
|
||||
<th style="width: 30px;">#</th>
|
||||
<th>Medicine Name</th>
|
||||
<th style="width: 90px;">Batch No</th>
|
||||
<th style="width: 95px;">Expiry</th>
|
||||
<th class="text-center" style="width: 50px;">Pack</th>
|
||||
<th class="text-center" style="width: 65px;">Rec. Qty</th>
|
||||
<th class="text-center" style="width: 50px;">Free</th>
|
||||
<th class="text-end" style="width: 75px;">Rate/Pack</th>
|
||||
<th class="text-end" style="width: 70px;">MRP</th>
|
||||
<th class="text-end" style="width: 80px;">Gross Amt</th>
|
||||
<th class="text-center" style="width: 55px;">Disc %</th>
|
||||
<th class="text-end" style="width: 75px;">Sch Disc</th>
|
||||
<th class="text-end" style="width: 85px;">Taxable Amt</th>
|
||||
<th class="text-center" style="width: 90px;">GST</th>
|
||||
<th class="text-end" style="width: 90px;">Line Total</th>
|
||||
<th class="text-center" style="width: 85px;">Live Stock ID</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php
|
||||
$totalGross = 0.0;
|
||||
$totalDiscount = 0.0;
|
||||
?>
|
||||
<?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']));
|
||||
$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'];
|
||||
$afterSch = max(0, $gross - $schTotal);
|
||||
$tradeDiscAmt = ($tradeDisc > 0) ? ($afterSch * $tradeDisc / 100) : 0;
|
||||
$rowDisc = $schTotal + $tradeDiscAmt;
|
||||
|
||||
$totalGross += $gross;
|
||||
$totalDiscount += $rowDisc;
|
||||
|
||||
$isInter = (!empty($grn['gst_type']) && $grn['gst_type'] === 'inter_state') || ((float)$it['igst_percent'] > 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) . '%)';
|
||||
?>
|
||||
<tr>
|
||||
<td><?= $idx + 1 ?></td>
|
||||
<td><strong><?= esc($it['item_name']) ?></strong></td>
|
||||
<td>
|
||||
<strong><?= esc($it['item_name']) ?></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>
|
||||
<?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-center <?= ((float)$it['rejected_packs'] > 0) ? 'text-danger fw-bold' : 'text-muted' ?>">
|
||||
<?= (float)$it['rejected_packs'] ?>
|
||||
<?php if (!empty($it['rejection_reason'])): ?>
|
||||
<small class="d-block text-danger">(<?= esc($it['rejection_reason']) ?>)</small>
|
||||
<?php endif; ?>
|
||||
</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 class="text-center"><?= number_format((float)$it['cgst_percent'] * 2, 0) ?>%</td>
|
||||
<td class="text-end fw-semibold">₹<?= number_format((float)$it['total_amount'], 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-center small"><?= esc($gstLabel) ?></td>
|
||||
<td class="text-end font-monospace fw-semibold">₹<?= number_format((float)$it['total_amount'], 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>
|
||||
|
|
@ -114,18 +142,53 @@
|
|||
</tbody>
|
||||
<tfoot class="table-light">
|
||||
<tr>
|
||||
<th colspan="11" class="text-end">Taxable Amount:</th>
|
||||
<th class="text-end">₹<?= number_format((float)$grn['total_received_amount'], 2) ?></th>
|
||||
<th colspan="12" class="text-end text-muted">Sub Total (Gross Amount):</th>
|
||||
<th colspan="3" class="text-end font-monospace">₹<?= number_format($totalGross, 2) ?></th>
|
||||
<th></th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th colspan="11" class="text-end">Total GST:</th>
|
||||
<th class="text-end">₹<?= number_format((float)$grn['total_tax_amount'], 2) ?></th>
|
||||
<th colspan="12" class="text-end text-muted">Total Discount (Trade & Scheme):</th>
|
||||
<th colspan="3" class="text-end font-monospace text-danger">₹<?= number_format($totalDiscount, 2) ?></th>
|
||||
<th></th>
|
||||
</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></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></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></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></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></th>
|
||||
</tr>
|
||||
<?php if (isset($grn['round_off']) && (float)$grn['round_off'] != 0): ?>
|
||||
<tr>
|
||||
<th colspan="12" class="text-end text-muted">Round Off:</th>
|
||||
<th colspan="3" class="text-end font-monospace"><?= ((float)$grn['round_off'] > 0 ? '+' : '') . number_format((float)$grn['round_off'], 2) ?></th>
|
||||
<th></th>
|
||||
</tr>
|
||||
<?php endif; ?>
|
||||
<tr class="table-success">
|
||||
<th colspan="11" class="text-end fs-6">Net Inward Bill Total:</th>
|
||||
<th class="text-end fs-6 text-success fw-bold">₹<?= number_format((float)$grn['net_amount'], 2) ?></th>
|
||||
<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></th>
|
||||
</tr>
|
||||
</tfoot>
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
<i class="bi bi-box-arrow-in-down"></i> Create Goods Received Note (GRN)
|
||||
<span class="badge bg-light text-dark border ms-2 font-monospace"><?= esc($nextGrnNumber) ?></span>
|
||||
</h4>
|
||||
<small class="text-muted">Inward Stock Physical Inspection & Batch Entry</small>
|
||||
<small class="text-muted">Inward Stock Physical Inspection & Vendor Invoice Reconciliation</small>
|
||||
</div>
|
||||
<div>
|
||||
<a href="javascript:load_form_div('<?= base_url('Medical/grn_list') ?>','medical-main','GRN Register :Pharmacy');" class="btn btn-outline-secondary btn-sm">
|
||||
|
|
@ -21,14 +21,14 @@
|
|||
|
||||
<div class="card shadow-sm border-0 mb-3">
|
||||
<div class="card-header bg-light py-2">
|
||||
<strong class="text-secondary"><i class="bi bi-truck"></i> Inward Delivery Metadata</strong>
|
||||
<strong class="text-secondary"><i class="bi bi-truck"></i> Inward Delivery & Invoice Metadata</strong>
|
||||
</div>
|
||||
<div class="card-body p-3">
|
||||
<form id="grn-create-form" onsubmit="event.preventDefault(); submitGrnForm();">
|
||||
<?= csrf_field() ?>
|
||||
<div class="row g-3">
|
||||
<div class="row g-2 mb-2">
|
||||
<div class="col-md-3">
|
||||
<label class="form-label form-label-sm fw-semibold">Linked Purchase Order (PO)</label>
|
||||
<label class="form-label form-label-sm fw-semibold mb-1">Linked Purchase Order (PO)</label>
|
||||
<select name="po_id" id="grn_po_id" class="form-select form-select-sm" onchange="handlePoSelection(this.value);">
|
||||
<option value="0">-- Direct Intake (No PO) --</option>
|
||||
<?php if (!empty($approvedPos)): ?>
|
||||
|
|
@ -41,7 +41,7 @@
|
|||
</select>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<label class="form-label form-label-sm fw-semibold">Supplier / Pharmaceutical Vendor <span class="text-danger">*</span></label>
|
||||
<label class="form-label form-label-sm fw-semibold mb-1">Supplier / Pharmaceutical Vendor <span class="text-danger">*</span></label>
|
||||
<select name="supplier_id" id="grn_supplier_id" class="form-select form-select-sm" required>
|
||||
<option value="">-- Select Supplier --</option>
|
||||
<?php if (!empty($suppliers)): ?>
|
||||
|
|
@ -54,91 +54,133 @@
|
|||
</select>
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<label class="form-label form-label-sm fw-semibold">Vendor Bill / Invoice # <span class="text-danger">*</span></label>
|
||||
<input type="text" name="supplier_invoice_no" id="supplier_invoice_no" class="form-control form-control-sm" placeholder="e.g., INV-88421" required>
|
||||
<label class="form-label form-label-sm fw-semibold mb-1">Vendor Invoice / Bill # <span class="text-danger">*</span></label>
|
||||
<input type="text" name="supplier_invoice_no" id="supplier_invoice_no" class="form-control form-control-sm" placeholder="e.g. INV-88421" required>
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<label class="form-label form-label-sm fw-semibold">Bill Date</label>
|
||||
<label class="form-label form-label-sm fw-semibold mb-1">Invoice Date <span class="text-danger">*</span></label>
|
||||
<input type="date" name="invoice_date" id="invoice_date" class="form-control form-control-sm" value="<?= date('Y-m-d') ?>" required>
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<label class="form-label form-label-sm fw-semibold">GRN Received Date</label>
|
||||
<label class="form-label form-label-sm fw-semibold mb-1">GRN Received Date <span class="text-danger">*</span></label>
|
||||
<input type="date" name="grn_date" id="grn_date" class="form-control form-control-sm" value="<?= date('Y-m-d') ?>" required>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<label class="form-label form-label-sm fw-semibold">Delivery Challan / Gate Pass #</label>
|
||||
<input type="text" name="challan_no" id="challan_no" class="form-control form-control-sm" placeholder="Optional Challan No.">
|
||||
</div>
|
||||
<div class="col-md-9">
|
||||
<label class="form-label form-label-sm fw-semibold">Receiving Inspection Remarks</label>
|
||||
<input type="text" name="remarks" id="grn_remarks" class="form-control form-control-sm" placeholder="Package integrity verified, cold-chain temperature logged, etc.">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Manual Drug Search (for direct items or extra items) -->
|
||||
<div class="card border-success mt-3">
|
||||
<div class="row g-2 mb-3">
|
||||
<div class="col-md-3">
|
||||
<label class="form-label form-label-sm fw-semibold mb-1">GST Supply Type</label>
|
||||
<select name="gst_type" id="grn_gst_type" class="form-select form-select-sm" onchange="recalculateGrnTotals();">
|
||||
<option value="intra_state" selected>Intra-State (CGST + SGST)</option>
|
||||
<option value="inter_state">Inter-State (IGST)</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<label class="form-label form-label-sm fw-semibold mb-1">Delivery Challan / Gate Pass #</label>
|
||||
<input type="text" name="challan_no" id="challan_no" class="form-control form-control-sm" placeholder="Optional Challan No.">
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label form-label-sm fw-semibold mb-1">Receiving Inspection Remarks</label>
|
||||
<input type="text" name="remarks" id="grn_remarks" class="form-control form-control-sm" placeholder="Package integrity verified, cold chain maintained, etc.">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Manual Medicine Search Bar -->
|
||||
<div class="card border-success mt-2">
|
||||
<div class="card-header bg-success text-white py-2 d-flex justify-content-between align-items-center">
|
||||
<span><i class="bi bi-shield-check"></i> Physical Inspection & Batch Intake Table</span>
|
||||
<small class="text-white-50">Enter Batch, Expiry, Received Packs & Pricing</small>
|
||||
<small class="text-white-50">Match Vendor Invoice Columns (Gross, Discounts, Taxable, GST & Net Total)</small>
|
||||
</div>
|
||||
<div class="card-body p-3">
|
||||
<div class="row g-2 align-items-end mb-3">
|
||||
<div class="col-md-4">
|
||||
<label class="form-label form-label-sm mb-1 fw-semibold">Add Medicine / Drug Master</label>
|
||||
<input type="text" id="grn_drug_search" class="form-control form-control-sm" placeholder="Search medicine to add row..." autocomplete="off">
|
||||
<div class="row g-2 align-items-end mb-3 bg-light p-2 rounded border">
|
||||
<div class="col-md-3">
|
||||
<label class="form-label form-label-sm mb-1 fw-semibold">Search Medicine Master</label>
|
||||
<input type="text" id="grn_drug_search" class="form-control form-control-sm" placeholder="Search medicine to add..." autocomplete="off">
|
||||
<input type="hidden" id="grn_sel_item_code" value="">
|
||||
<input type="hidden" id="grn_sel_item_name" value="">
|
||||
<input type="hidden" id="grn_sel_packing" value="10">
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<label class="form-label form-label-sm mb-1 fw-semibold">Batch No.</label>
|
||||
<input type="text" id="grn_sel_batch" class="form-control form-control-sm" placeholder="e.g. BATCH-01">
|
||||
<input type="text" id="grn_sel_batch" class="form-control form-control-sm font-monospace" placeholder="e.g. 26DH220">
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<label class="form-label form-label-sm mb-1 fw-semibold">Expiry Date</label>
|
||||
<input type="date" id="grn_sel_expiry" class="form-control form-control-sm">
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<label class="form-label form-label-sm mb-1 fw-semibold">Received Packs</label>
|
||||
<input type="number" id="grn_sel_rec_packs" class="form-control form-control-sm" value="10" min="1">
|
||||
<div class="col-md-1">
|
||||
<label class="form-label form-label-sm mb-1 fw-semibold">Rec. Qty</label>
|
||||
<input type="number" id="grn_sel_rec_packs" class="form-control form-control-sm text-center" value="10" min="1">
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<div class="col-md-1">
|
||||
<label class="form-label form-label-sm mb-1 fw-semibold">Free</label>
|
||||
<input type="number" id="grn_sel_free_packs" class="form-control form-control-sm text-center" value="0" min="0">
|
||||
</div>
|
||||
<div class="col-md-1">
|
||||
<label class="form-label form-label-sm mb-1 fw-semibold">Rate/Pack</label>
|
||||
<input type="number" id="grn_sel_rate" class="form-control form-control-sm text-end" value="100.00" min="0" step="0.01">
|
||||
</div>
|
||||
<div class="col-md-1">
|
||||
<label class="form-label form-label-sm mb-1 fw-semibold">MRP</label>
|
||||
<input type="number" id="grn_sel_mrp" class="form-control form-control-sm text-end" value="130.00" min="0" step="0.01">
|
||||
</div>
|
||||
<div class="col-md-1">
|
||||
<button type="button" class="btn btn-success btn-sm w-100" id="btn-add-grn-row" onclick="addCustomItemToGrn();" disabled>
|
||||
<i class="bi bi-plus-lg"></i> Add Row
|
||||
<i class="bi bi-plus-lg"></i> Add
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="table-responsive">
|
||||
<table class="table table-bordered table-sm align-middle mb-0" id="grn-items-table">
|
||||
<table class="table table-bordered table-sm align-middle mb-0" id="grn-items-table" style="font-size: 13px;">
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
<th style="width: 30px;">#</th>
|
||||
<th>Medicine Name</th>
|
||||
<th style="width: 110px;">Batch No <span class="text-danger">*</span></th>
|
||||
<th style="width: 120px;">Expiry <span class="text-danger">*</span></th>
|
||||
<th class="text-center" style="width: 70px;">Pack</th>
|
||||
<th class="text-center" style="width: 80px;">Ordered</th>
|
||||
<th class="text-center" style="width: 85px;">Rec. Packs <span class="text-danger">*</span></th>
|
||||
<th class="text-center" style="width: 75px;">Free</th>
|
||||
<th class="text-center" style="width: 75px;">Damaged</th>
|
||||
<th class="text-end" style="width: 100px;">Rate/Pack</th>
|
||||
<th class="text-end" style="width: 90px;">MRP</th>
|
||||
<th class="text-center" style="width: 70px;">GST %</th>
|
||||
<th class="text-end" style="width: 110px;">Line Total</th>
|
||||
<th style="width: 40px;"></th>
|
||||
<tr class="text-center align-middle">
|
||||
<th style="width: 25px;">#</th>
|
||||
<th style="min-width: 160px;" class="text-start">Medicine Name</th>
|
||||
<th style="width: 95px;">Batch No <span class="text-danger">*</span></th>
|
||||
<th style="width: 105px;">Expiry <span class="text-danger">*</span></th>
|
||||
<th style="width: 50px;">Pack</th>
|
||||
<th style="width: 65px;">Rec. Qty <span class="text-danger">*</span></th>
|
||||
<th style="width: 50px;">Free</th>
|
||||
<th style="width: 75px;" class="text-end">Rate/Pack</th>
|
||||
<th style="width: 70px;" class="text-end">MRP</th>
|
||||
<th style="width: 80px;" class="text-end bg-light">Gross Amt</th>
|
||||
<th style="width: 60px;">Disc %</th>
|
||||
<th style="width: 60px;">Sch %</th>
|
||||
<th style="width: 65px;">Sch Amt</th>
|
||||
<th style="width: 85px;" class="text-end bg-light">Taxable Amt</th>
|
||||
<th style="width: 75px;">GST %</th>
|
||||
<th style="width: 90px;" class="text-end bg-light">Line Total</th>
|
||||
<th style="width: 35px;"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="grn-items-body">
|
||||
<?php if (!empty($poItems)): ?>
|
||||
<?php foreach ($poItems as $idx => $it): ?>
|
||||
<?php
|
||||
$defGst = (float)($it['gst_rate'] ?? 5);
|
||||
$defRate = (float)($it['estimated_ptr'] ?? 0);
|
||||
$defQty = (float)($it['remaining_packs'] ?? 0);
|
||||
$defGross = $defQty * $defRate;
|
||||
$defTaxable = $defGross;
|
||||
$defTax = $defTaxable * ($defGst / 100);
|
||||
$defLineTotal = $defTaxable + $defTax;
|
||||
?>
|
||||
<tr>
|
||||
<td class="row-num"><?= $idx + 1 ?></td>
|
||||
<td class="row-num text-center"><?= $idx + 1 ?></td>
|
||||
<td>
|
||||
<strong><?= esc($it['item_name']) ?></strong>
|
||||
<strong class="text-dark"><?= esc($it['item_name']) ?></strong>
|
||||
<input type="hidden" name="items[<?= $idx ?>][item_code]" value="<?= (int)$it['item_id'] ?>">
|
||||
<input type="hidden" name="items[<?= $idx ?>][item_name]" value="<?= esc($it['item_name']) ?>">
|
||||
<input type="hidden" name="items[<?= $idx ?>][po_item_id]" value="<?= (int)$it['po_item_id'] ?>">
|
||||
<input type="hidden" name="items[<?= $idx ?>][order_packs]" value="<?= (float)$it['remaining_packs'] ?>">
|
||||
<input type="hidden" name="items[<?= $idx ?>][rejected_packs]" value="0">
|
||||
<input type="hidden" name="items[<?= $idx ?>][hsn_code]" value="3004">
|
||||
<input type="hidden" name="items[<?= $idx ?>][cgst_percent]" class="line-cgst" value="<?= $defGst / 2 ?>">
|
||||
<input type="hidden" name="items[<?= $idx ?>][sgst_percent]" class="line-sgst" value="<?= $defGst / 2 ?>">
|
||||
<input type="hidden" name="items[<?= $idx ?>][igst_percent]" class="line-igst" value="0">
|
||||
<input type="hidden" name="items[<?= $idx ?>][gross_amount]" class="line-gross-hid" value="<?= number_format($defGross, 2, '.', '') ?>">
|
||||
<input type="hidden" name="items[<?= $idx ?>][taxable_amount]" class="line-taxable-hid" value="<?= number_format($defTaxable, 2, '.', '') ?>">
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" name="items[<?= $idx ?>][batch_no]" class="form-control form-control-sm font-monospace line-batch" placeholder="Batch #" required>
|
||||
|
|
@ -147,64 +189,100 @@
|
|||
<input type="date" name="items[<?= $idx ?>][expiry_date]" class="form-control form-control-sm line-expiry" required>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<input type="number" name="items[<?= $idx ?>][packing]" class="form-control form-control-sm text-center line-pack" value="<?= (int)$it['units_per_pack'] ?>" min="1">
|
||||
</td>
|
||||
<td class="text-center text-muted">
|
||||
<?= (float)$it['remaining_packs'] ?>
|
||||
<input type="hidden" name="items[<?= $idx ?>][order_packs]" value="<?= (float)$it['remaining_packs'] ?>">
|
||||
<input type="number" name="items[<?= $idx ?>][packing]" class="form-control form-control-sm text-center line-pack px-1" value="<?= (int)$it['units_per_pack'] ?>" min="1">
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<input type="number" name="items[<?= $idx ?>][received_packs]" class="form-control form-control-sm text-center line-rec" value="<?= (float)$it['remaining_packs'] ?>" min="0" step="1" onchange="recalculateGrnTotals();" required>
|
||||
<input type="number" name="items[<?= $idx ?>][received_packs]" class="form-control form-control-sm text-center fw-bold line-rec px-1" value="<?= $defQty ?>" min="0" step="1" oninput="recalculateGrnTotals();" required>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<input type="number" name="items[<?= $idx ?>][free_packs]" class="form-control form-control-sm text-center line-free" value="0" min="0" step="1">
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<input type="number" name="items[<?= $idx ?>][rejected_packs]" class="form-control form-control-sm text-center line-rej" value="0" min="0" step="1">
|
||||
<input type="number" name="items[<?= $idx ?>][free_packs]" class="form-control form-control-sm text-center text-success line-free px-1" value="0" min="0" step="1" oninput="recalculateGrnTotals();">
|
||||
</td>
|
||||
<td class="text-end">
|
||||
<input type="number" name="items[<?= $idx ?>][unit_purchase_rate]" class="form-control form-control-sm text-end line-rate" value="<?= number_format((float)$it['estimated_ptr'], 2, '.', '') ?>" min="0" step="0.01" onchange="recalculateGrnTotals();">
|
||||
<input type="number" name="items[<?= $idx ?>][unit_purchase_rate]" class="form-control form-control-sm text-end line-rate px-1" value="<?= number_format($defRate, 2, '.', '') ?>" min="0" step="0.01" oninput="recalculateGrnTotals();">
|
||||
</td>
|
||||
<td class="text-end">
|
||||
<input type="number" name="items[<?= $idx ?>][mrp]" class="form-control form-control-sm text-end line-mrp" value="<?= number_format((float)$it['estimated_ptr'] * 1.3, 2, '.', '') ?>" min="0" step="0.01">
|
||||
<input type="number" name="items[<?= $idx ?>][mrp]" class="form-control form-control-sm text-end line-mrp px-1" value="<?= number_format($defRate * 1.3, 2, '.', '') ?>" min="0" step="0.01">
|
||||
</td>
|
||||
<td class="text-end font-monospace line-gross-disp bg-light">₹<?= number_format($defGross, 2) ?></td>
|
||||
<td class="text-center">
|
||||
<input type="number" name="items[<?= $idx ?>][discount_percent]" class="form-control form-control-sm text-center line-disc px-1" value="0.00" min="0" max="100" step="0.01" oninput="recalculateGrnTotals();">
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<select name="items[<?= $idx ?>][cgst_percent]" class="form-select form-select-sm text-center line-gst" onchange="recalculateGrnTotals();">
|
||||
<option value="6" <?= ((float)$it['gst_rate'] == 12) ? 'selected' : '' ?>>12%</option>
|
||||
<option value="2.5" <?= ((float)$it['gst_rate'] == 5) ? 'selected' : '' ?>>5%</option>
|
||||
<option value="9" <?= ((float)$it['gst_rate'] == 18) ? 'selected' : '' ?>>18%</option>
|
||||
<option value="0" <?= ((float)$it['gst_rate'] == 0) ? 'selected' : '' ?>>0%</option>
|
||||
<input type="number" name="items[<?= $idx ?>][sch_disc_per]" class="form-control form-control-sm text-center line-sch-per px-1" value="0.00" min="0" max="100" step="0.01" oninput="recalculateGrnTotals();">
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<input type="number" name="items[<?= $idx ?>][sch_disc_amt]" class="form-control form-control-sm text-center line-sch-amt px-1" value="0.00" min="0" step="0.01" oninput="recalculateGrnTotals();">
|
||||
</td>
|
||||
<td class="text-end font-monospace line-taxable-disp bg-light">₹<?= number_format($defTaxable, 2) ?></td>
|
||||
<td class="text-center">
|
||||
<select name="items[<?= $idx ?>][gst_rate]" class="form-select form-select-sm text-center line-gst px-1" onchange="recalculateGrnTotals();">
|
||||
<option value="5" <?= ($defGst == 5) ? 'selected' : '' ?>>5%</option>
|
||||
<option value="12" <?= ($defGst == 12) ? 'selected' : '' ?>>12%</option>
|
||||
<option value="18" <?= ($defGst == 18) ? 'selected' : '' ?>>18%</option>
|
||||
<option value="28" <?= ($defGst == 28) ? 'selected' : '' ?>>28%</option>
|
||||
<option value="0" <?= ($defGst == 0) ? 'selected' : '' ?>>0%</option>
|
||||
</select>
|
||||
<input type="hidden" name="items[<?= $idx ?>][sgst_percent]" class="line-sgst" value="6">
|
||||
</td>
|
||||
<td class="text-end fw-semibold line-total-disp">₹0.00</td>
|
||||
<td class="text-end font-monospace fw-semibold line-total-disp bg-light">₹<?= number_format($defLineTotal, 2) ?></td>
|
||||
<td class="text-center">
|
||||
<button type="button" class="btn btn-outline-danger btn-sm py-0" onclick="removeGrnRow(this);">✖</button>
|
||||
<button type="button" class="btn btn-outline-danger btn-sm py-0 px-1" onclick="removeGrnRow(this);">✖</button>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
<?php else: ?>
|
||||
<tr id="grn-no-items">
|
||||
<td colspan="14" class="text-center py-4 text-muted">
|
||||
No items loaded. Select a PO above or use the Search box to add items.
|
||||
<td colspan="17" class="text-center py-4 text-muted">
|
||||
No items loaded. Select an approved PO above or use the Search box to add medicines.
|
||||
</td>
|
||||
</tr>
|
||||
<?php endif; ?>
|
||||
</tbody>
|
||||
<tfoot class="table-light">
|
||||
<tr>
|
||||
<th colspan="12" class="text-end">Taxable Amount:</th>
|
||||
<th class="text-end" id="grn-taxable-disp">₹0.00</th>
|
||||
<th colspan="13" class="text-end text-muted">Sub Total (Gross Amount):</th>
|
||||
<th colspan="3" class="text-end font-monospace" id="grn-gross-disp">₹0.00</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th colspan="12" class="text-end">GST Tax Amount:</th>
|
||||
<th class="text-end" id="grn-tax-disp">₹0.00</th>
|
||||
<th colspan="13" class="text-end text-muted">Total Discount (Trade & Scheme):</th>
|
||||
<th colspan="3" class="text-end font-monospace text-danger" id="grn-discount-disp">₹0.00</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th colspan="13" class="text-end text-dark">Taxable Amount:</th>
|
||||
<th colspan="3" class="text-end font-monospace fw-bold" id="grn-taxable-disp">₹0.00</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
<tr id="row-cgst">
|
||||
<th colspan="13" class="text-end text-muted">CGST Amount:</th>
|
||||
<th colspan="3" class="text-end font-monospace text-primary" id="grn-cgst-disp">₹0.00</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
<tr id="row-sgst">
|
||||
<th colspan="13" class="text-end text-muted">SGST Amount:</th>
|
||||
<th colspan="3" class="text-end font-monospace text-primary" id="grn-sgst-disp">₹0.00</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
<tr id="row-igst" style="display:none;">
|
||||
<th colspan="13" class="text-end text-muted">IGST Amount:</th>
|
||||
<th colspan="3" class="text-end font-monospace text-primary" id="grn-igst-disp">₹0.00</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th colspan="13" class="text-end text-dark">Total GST:</th>
|
||||
<th colspan="3" class="text-end font-monospace fw-bold" id="grn-tax-disp">₹0.00</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th colspan="13" class="text-end text-muted">Round Off (+ / -):</th>
|
||||
<th colspan="3" class="text-end">
|
||||
<input type="number" step="0.01" name="round_off" id="grn_round_off" class="form-control form-control-sm text-end font-monospace d-inline-block" style="width: 105px;" value="0.00" oninput="recalculateGrnTotals();">
|
||||
</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
<tr class="table-success">
|
||||
<th colspan="12" class="text-end fs-6">Net Inward Bill Total:</th>
|
||||
<th class="text-end fs-6 text-success fw-bold" id="grn-net-disp">₹0.00</th>
|
||||
<th colspan="13" 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" id="grn-net-disp">₹0.00</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</tfoot>
|
||||
|
|
@ -220,7 +298,7 @@
|
|||
<label class="form-check-label fw-bold text-dark" for="post_to_inventory">
|
||||
Immediately Post Verified Quantities to Live Pharmacy Store Stock & Purchase Ledgers
|
||||
</label>
|
||||
<small class="d-block text-muted">Calls stored procedure <code>p_stock_update_purchase_id</code> to make batches immediately sellable.</small>
|
||||
<small class="d-block text-muted">Creates verified purchase invoice records and updates stock ledgers.</small>
|
||||
</div>
|
||||
<div class="d-flex gap-2">
|
||||
<button type="button" class="btn btn-outline-secondary" onclick="load_form_div('<?= base_url('Medical/grn_list') ?>','medical-main');">Cancel</button>
|
||||
|
|
@ -264,6 +342,8 @@ function initGrnDrugAutocomplete() {
|
|||
document.getElementById('grn_sel_item_code').value = item.item_code || item.l_item_code || '';
|
||||
document.getElementById('grn_sel_item_name').value = item.value || '';
|
||||
document.getElementById('grn_sel_packing').value = item.l_packing || 10;
|
||||
if (item.mrp) document.getElementById('grn_sel_mrp').value = parseFloat(item.mrp).toFixed(2);
|
||||
if (item.purchase_price) document.getElementById('grn_sel_rate').value = parseFloat(item.purchase_price).toFixed(2);
|
||||
document.getElementById('btn-add-grn-row').disabled = false;
|
||||
}
|
||||
});
|
||||
|
|
@ -281,7 +361,10 @@ function addCustomItemToGrn() {
|
|||
var batch = document.getElementById('grn_sel_batch').value.trim();
|
||||
var expiry = document.getElementById('grn_sel_expiry').value;
|
||||
var packs = parseFloat(document.getElementById('grn_sel_rec_packs').value || 1);
|
||||
var freePacks = parseFloat(document.getElementById('grn_sel_free_packs').value || 0);
|
||||
var packing = parseInt(document.getElementById('grn_sel_packing').value || 10);
|
||||
var rate = parseFloat(document.getElementById('grn_sel_rate').value || 100.00);
|
||||
var mrp = parseFloat(document.getElementById('grn_sel_mrp').value || 130.00);
|
||||
|
||||
if (!code || !name) {
|
||||
alert('Please search and select a medicine.');
|
||||
|
|
@ -305,13 +388,23 @@ function addCustomItemToGrn() {
|
|||
var rowIdx = tbody.querySelectorAll('tr').length;
|
||||
var tr = document.createElement('tr');
|
||||
|
||||
var gross = packs * rate;
|
||||
|
||||
tr.innerHTML = `
|
||||
<td class="row-num">${rowIdx + 1}</td>
|
||||
<td class="row-num text-center">${rowIdx + 1}</td>
|
||||
<td>
|
||||
<strong>${escapeHtml(name)}</strong>
|
||||
<strong class="text-dark">${escapeHtml(name)}</strong>
|
||||
<input type="hidden" name="items[${rowIdx}][item_code]" value="${code}">
|
||||
<input type="hidden" name="items[${rowIdx}][item_name]" value="${escapeHtml(name)}">
|
||||
<input type="hidden" name="items[${rowIdx}][po_item_id]" value="">
|
||||
<input type="hidden" name="items[${rowIdx}][order_packs]" value="0">
|
||||
<input type="hidden" name="items[${rowIdx}][rejected_packs]" value="0">
|
||||
<input type="hidden" name="items[${rowIdx}][hsn_code]" value="3004">
|
||||
<input type="hidden" name="items[${rowIdx}][cgst_percent]" class="line-cgst" value="2.5">
|
||||
<input type="hidden" name="items[${rowIdx}][sgst_percent]" class="line-sgst" value="2.5">
|
||||
<input type="hidden" name="items[${rowIdx}][igst_percent]" class="line-igst" value="0">
|
||||
<input type="hidden" name="items[${rowIdx}][gross_amount]" class="line-gross-hid" value="${gross.toFixed(2)}">
|
||||
<input type="hidden" name="items[${rowIdx}][taxable_amount]" class="line-taxable-hid" value="${gross.toFixed(2)}">
|
||||
</td>
|
||||
<td>
|
||||
<input type="text" name="items[${rowIdx}][batch_no]" class="form-control form-control-sm font-monospace line-batch" value="${escapeHtml(batch)}" required>
|
||||
|
|
@ -320,36 +413,43 @@ function addCustomItemToGrn() {
|
|||
<input type="date" name="items[${rowIdx}][expiry_date]" class="form-control form-control-sm line-expiry" value="${expiry}" required>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<input type="number" name="items[${rowIdx}][packing]" class="form-control form-control-sm text-center line-pack" value="${packing}" min="1">
|
||||
</td>
|
||||
<td class="text-center text-muted">0</td>
|
||||
<td class="text-center">
|
||||
<input type="number" name="items[${rowIdx}][received_packs]" class="form-control form-control-sm text-center line-rec" value="${packs}" min="1" onchange="recalculateGrnTotals();" required>
|
||||
<input type="number" name="items[${rowIdx}][packing]" class="form-control form-control-sm text-center line-pack px-1" value="${packing}" min="1">
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<input type="number" name="items[${rowIdx}][free_packs]" class="form-control form-control-sm text-center line-free" value="0" min="0">
|
||||
<input type="number" name="items[${rowIdx}][received_packs]" class="form-control form-control-sm text-center fw-bold line-rec px-1" value="${packs}" min="1" oninput="recalculateGrnTotals();" required>
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<input type="number" name="items[${rowIdx}][rejected_packs]" class="form-control form-control-sm text-center line-rej" value="0" min="0">
|
||||
<input type="number" name="items[${rowIdx}][free_packs]" class="form-control form-control-sm text-center text-success line-free px-1" value="${freePacks}" min="0" oninput="recalculateGrnTotals();">
|
||||
</td>
|
||||
<td class="text-end">
|
||||
<input type="number" name="items[${rowIdx}][unit_purchase_rate]" class="form-control form-control-sm text-end line-rate" value="100.00" min="0" step="0.01" onchange="recalculateGrnTotals();">
|
||||
<input type="number" name="items[${rowIdx}][unit_purchase_rate]" class="form-control form-control-sm text-end line-rate px-1" value="${rate.toFixed(2)}" min="0" step="0.01" oninput="recalculateGrnTotals();">
|
||||
</td>
|
||||
<td class="text-end">
|
||||
<input type="number" name="items[${rowIdx}][mrp]" class="form-control form-control-sm text-end line-mrp" value="130.00" min="0" step="0.01">
|
||||
<input type="number" name="items[${rowIdx}][mrp]" class="form-control form-control-sm text-end line-mrp px-1" value="${mrp.toFixed(2)}" min="0" step="0.01">
|
||||
</td>
|
||||
<td class="text-end font-monospace line-gross-disp bg-light">₹${gross.toFixed(2)}</td>
|
||||
<td class="text-center">
|
||||
<input type="number" name="items[${rowIdx}][discount_percent]" class="form-control form-control-sm text-center line-disc px-1" value="0.00" min="0" max="100" step="0.01" oninput="recalculateGrnTotals();">
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<select name="items[${rowIdx}][cgst_percent]" class="form-select form-select-sm text-center line-gst" onchange="recalculateGrnTotals();">
|
||||
<option value="6" selected>12%</option>
|
||||
<option value="2.5">5%</option>
|
||||
<option value="9">18%</option>
|
||||
<input type="number" name="items[${rowIdx}][sch_disc_per]" class="form-control form-control-sm text-center line-sch-per px-1" value="0.00" min="0" max="100" step="0.01" oninput="recalculateGrnTotals();">
|
||||
</td>
|
||||
<td class="text-center">
|
||||
<input type="number" name="items[${rowIdx}][sch_disc_amt]" class="form-control form-control-sm text-center line-sch-amt px-1" value="0.00" min="0" step="0.01" oninput="recalculateGrnTotals();">
|
||||
</td>
|
||||
<td class="text-end font-monospace line-taxable-disp bg-light">₹${gross.toFixed(2)}</td>
|
||||
<td class="text-center">
|
||||
<select name="items[${rowIdx}][gst_rate]" class="form-select form-select-sm text-center line-gst px-1" onchange="recalculateGrnTotals();">
|
||||
<option value="5" selected>5%</option>
|
||||
<option value="12">12%</option>
|
||||
<option value="18">18%</option>
|
||||
<option value="28">28%</option>
|
||||
<option value="0">0%</option>
|
||||
</select>
|
||||
<input type="hidden" name="items[${rowIdx}][sgst_percent]" class="line-sgst" value="6">
|
||||
</td>
|
||||
<td class="text-end fw-semibold line-total-disp">₹0.00</td>
|
||||
<td class="text-end font-monospace fw-semibold line-total-disp bg-light">₹0.00</td>
|
||||
<td class="text-center">
|
||||
<button type="button" class="btn btn-outline-danger btn-sm py-0" onclick="removeGrnRow(this);">✖</button>
|
||||
<button type="button" class="btn btn-outline-danger btn-sm py-0 px-1" onclick="removeGrnRow(this);">✖</button>
|
||||
</td>
|
||||
`;
|
||||
|
||||
|
|
@ -368,7 +468,7 @@ function removeGrnRow(btn) {
|
|||
var tbody = document.getElementById('grn-items-body');
|
||||
var rows = tbody.querySelectorAll('tr');
|
||||
if (rows.length === 0) {
|
||||
tbody.innerHTML = '<tr id="grn-no-items"><td colspan="14" class="text-center py-4 text-muted">No items loaded.</td></tr>';
|
||||
tbody.innerHTML = '<tr id="grn-no-items"><td colspan="17" class="text-center py-4 text-muted">No items loaded.</td></tr>';
|
||||
} else {
|
||||
rows.forEach(function(r, idx) {
|
||||
var numTd = r.querySelector('.row-num');
|
||||
|
|
@ -380,28 +480,114 @@ function removeGrnRow(btn) {
|
|||
|
||||
function recalculateGrnTotals() {
|
||||
var rows = document.querySelectorAll('#grn-items-body tr:not(#grn-no-items)');
|
||||
var taxable = 0.0;
|
||||
var isInterState = (document.getElementById('grn_gst_type')?.value === 'inter_state');
|
||||
|
||||
var totalGross = 0.0;
|
||||
var totalDisc = 0.0;
|
||||
var totalTaxable = 0.0;
|
||||
var totalCgst = 0.0;
|
||||
var totalSgst = 0.0;
|
||||
var totalIgst = 0.0;
|
||||
var totalTax = 0.0;
|
||||
|
||||
rows.forEach(function(r) {
|
||||
var recPacks = parseFloat(r.querySelector('.line-rec')?.value || 0);
|
||||
var rate = parseFloat(r.querySelector('.line-rate')?.value || 0);
|
||||
var gstVal = parseFloat(r.querySelector('.line-gst')?.value || 0) * 2; // CGST + SGST
|
||||
var gross = recPacks * rate;
|
||||
|
||||
var lineSub = recPacks * rate;
|
||||
var lineTax = lineSub * (gstVal / 100);
|
||||
var lineTotal = lineSub + lineTax;
|
||||
var discPer = parseFloat(r.querySelector('.line-disc')?.value || 0);
|
||||
var schPer = parseFloat(r.querySelector('.line-sch-per')?.value || 0);
|
||||
var schAmt = parseFloat(r.querySelector('.line-sch-amt')?.value || 0);
|
||||
|
||||
taxable += lineSub;
|
||||
totalTax += lineTax;
|
||||
// Scheme discount calculation
|
||||
var schPerAmt = (schPer > 0) ? (gross * (schPer / 100)) : 0.0;
|
||||
var lineSch = schPerAmt + schAmt;
|
||||
var afterSch = Math.max(0.0, gross - lineSch);
|
||||
|
||||
// Trade discount calculation
|
||||
var tradeDiscAmt = (discPer > 0) ? (afterSch * (discPer / 100)) : 0.0;
|
||||
var taxable = Math.max(0.0, afterSch - tradeDiscAmt);
|
||||
|
||||
// GST calculation
|
||||
var gstRate = parseFloat(r.querySelector('.line-gst')?.value || 0);
|
||||
var cgstPer = 0.0;
|
||||
var sgstPer = 0.0;
|
||||
var igstPer = 0.0;
|
||||
var cgstAmt = 0.0;
|
||||
var sgstAmt = 0.0;
|
||||
var igstAmt = 0.0;
|
||||
|
||||
if (isInterState) {
|
||||
igstPer = gstRate;
|
||||
igstAmt = taxable * (igstPer / 100);
|
||||
} else {
|
||||
cgstPer = gstRate / 2;
|
||||
sgstPer = gstRate / 2;
|
||||
cgstAmt = taxable * (cgstPer / 100);
|
||||
sgstAmt = taxable * (sgstPer / 100);
|
||||
}
|
||||
|
||||
var lineTax = cgstAmt + sgstAmt + igstAmt;
|
||||
var lineTotal = taxable + lineTax;
|
||||
|
||||
// Update displays
|
||||
var grossDisp = r.querySelector('.line-gross-disp');
|
||||
if (grossDisp) grossDisp.innerText = '₹' + gross.toFixed(2);
|
||||
|
||||
var taxableDisp = r.querySelector('.line-taxable-disp');
|
||||
if (taxableDisp) taxableDisp.innerText = '₹' + taxable.toFixed(2);
|
||||
|
||||
var totalDisp = r.querySelector('.line-total-disp');
|
||||
if (totalDisp) totalDisp.innerText = '₹' + lineTotal.toFixed(2);
|
||||
|
||||
// Update hidden inputs
|
||||
var cgstInp = r.querySelector('.line-cgst');
|
||||
if (cgstInp) cgstInp.value = cgstPer;
|
||||
|
||||
var sgstInp = r.querySelector('.line-sgst');
|
||||
if (sgstInp) sgstInp.value = sgstPer;
|
||||
|
||||
var igstInp = r.querySelector('.line-igst');
|
||||
if (igstInp) igstInp.value = igstPer;
|
||||
|
||||
var grossInp = r.querySelector('.line-gross-hid');
|
||||
if (grossInp) grossInp.value = gross.toFixed(2);
|
||||
|
||||
var taxableInp = r.querySelector('.line-taxable-hid');
|
||||
if (taxableInp) taxableInp.value = taxable.toFixed(2);
|
||||
|
||||
// Accumulate
|
||||
totalGross += gross;
|
||||
totalDisc += (lineSch + tradeDiscAmt);
|
||||
totalTaxable += taxable;
|
||||
totalCgst += cgstAmt;
|
||||
totalSgst += sgstAmt;
|
||||
totalIgst += igstAmt;
|
||||
totalTax += lineTax;
|
||||
});
|
||||
|
||||
document.getElementById('grn-taxable-disp').innerText = '₹' + taxable.toFixed(2);
|
||||
document.getElementById('grn-gross-disp').innerText = '₹' + totalGross.toFixed(2);
|
||||
document.getElementById('grn-discount-disp').innerText = '₹' + totalDisc.toFixed(2);
|
||||
document.getElementById('grn-taxable-disp').innerText = '₹' + totalTaxable.toFixed(2);
|
||||
|
||||
if (isInterState) {
|
||||
document.getElementById('row-cgst').style.display = 'none';
|
||||
document.getElementById('row-sgst').style.display = 'none';
|
||||
document.getElementById('row-igst').style.display = '';
|
||||
document.getElementById('grn-igst-disp').innerText = '₹' + totalIgst.toFixed(2);
|
||||
} else {
|
||||
document.getElementById('row-cgst').style.display = '';
|
||||
document.getElementById('row-sgst').style.display = '';
|
||||
document.getElementById('row-igst').style.display = 'none';
|
||||
document.getElementById('grn-cgst-disp').innerText = '₹' + totalCgst.toFixed(2);
|
||||
document.getElementById('grn-sgst-disp').innerText = '₹' + totalSgst.toFixed(2);
|
||||
}
|
||||
|
||||
document.getElementById('grn-tax-disp').innerText = '₹' + totalTax.toFixed(2);
|
||||
document.getElementById('grn-net-disp').innerText = '₹' + (taxable + totalTax).toFixed(2);
|
||||
|
||||
var roundOff = parseFloat(document.getElementById('grn_round_off')?.value || 0);
|
||||
var netPayable = totalTaxable + totalTax + roundOff;
|
||||
document.getElementById('grn-net-disp').innerText = '₹' + netPayable.toFixed(2);
|
||||
}
|
||||
|
||||
function submitGrnForm() {
|
||||
|
|
|
|||
|
|
@ -62,37 +62,61 @@
|
|||
<table class="items-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 25px;">#</th>
|
||||
<th style="width: 20px;">#</th>
|
||||
<th>Item Name</th>
|
||||
<th style="width: 75px;">Batch No</th>
|
||||
<th style="width: 65px;">Expiry</th>
|
||||
<th class="text-center" style="width: 45px;">Pack</th>
|
||||
<th class="text-center" style="width: 50px;">Ordered</th>
|
||||
<th class="text-center" style="width: 50px;">Received</th>
|
||||
<th class="text-center" style="width: 40px;">Free</th>
|
||||
<th class="text-center" style="width: 45px;">Damaged</th>
|
||||
<th class="text-end" style="width: 65px;">Rate/Pack</th>
|
||||
<th class="text-end" style="width: 60px;">MRP</th>
|
||||
<th class="text-end" style="width: 75px;">Line Total</th>
|
||||
<th style="width: 65px;">Batch No</th>
|
||||
<th style="width: 55px;">Expiry</th>
|
||||
<th class="text-center" style="width: 35px;">Pack</th>
|
||||
<th class="text-center" style="width: 45px;">Rec. Qty</th>
|
||||
<th class="text-center" style="width: 35px;">Free</th>
|
||||
<th class="text-end" style="width: 55px;">Rate</th>
|
||||
<th class="text-end" style="width: 50px;">MRP</th>
|
||||
<th class="text-end" style="width: 55px;">Gross</th>
|
||||
<th class="text-center" style="width: 40px;">Disc%</th>
|
||||
<th class="text-end" style="width: 55px;">Taxable</th>
|
||||
<th class="text-center" style="width: 50px;">GST</th>
|
||||
<th class="text-end" style="width: 65px;">Line Total</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php
|
||||
$pdfGross = 0.0;
|
||||
$pdfDisc = 0.0;
|
||||
?>
|
||||
<?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']));
|
||||
$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'];
|
||||
$afterSch = max(0, $gross - $schTotal);
|
||||
$tradeDiscAmt = ($tradeDisc > 0) ? ($afterSch * $tradeDisc / 100) : 0;
|
||||
$rowDisc = $schTotal + $tradeDiscAmt;
|
||||
|
||||
$pdfGross += $gross;
|
||||
$pdfDisc += $rowDisc;
|
||||
|
||||
$isInter = (!empty($grn['gst_type']) && $grn['gst_type'] === 'inter_state') || ((float)($it['igst_percent'] ?? 0) > 0);
|
||||
$gstStr = $isInter
|
||||
? number_format((float)($it['igst_percent'] ?? 0), 0) . '% IGST'
|
||||
: number_format((float)$it['cgst_percent'] + (float)$it['sgst_percent'], 0) . '%';
|
||||
?>
|
||||
<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"><?= (float)$it['order_packs'] ?></td>
|
||||
<td class="text-center"><strong><?= (float)$it['received_packs'] ?></strong></td>
|
||||
<td class="text-center"><?= (float)$it['free_packs'] ?></td>
|
||||
<td class="text-center <?= ((float)$it['rejected_packs'] > 0) ? 'style=\"color:red;\"' : '' ?>">
|
||||
<?= (float)$it['rejected_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 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-center"><?= esc($gstStr) ?></td>
|
||||
<td class="text-end">₹<?= number_format((float)$it['total_amount'], 2) ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
|
|
@ -101,16 +125,45 @@
|
|||
</table>
|
||||
|
||||
<table class="totals-table">
|
||||
<tr>
|
||||
<td>Subtotal (Gross Amount):</td>
|
||||
<td class="text-end">₹<?= number_format($pdfGross, 2) ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Total Discount:</td>
|
||||
<td class="text-end">₹<?= number_format($pdfDisc, 2) ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Taxable Amount:</td>
|
||||
<td class="text-end">₹<?= number_format((float)$grn['total_received_amount'], 2) ?></td>
|
||||
</tr>
|
||||
<?php if (!empty($grn['gst_type']) && $grn['gst_type'] === 'inter_state'): ?>
|
||||
<tr>
|
||||
<td>IGST Amount:</td>
|
||||
<td class="text-end">₹<?= number_format((float)($grn['igst_amount'] ?? $grn['total_tax_amount']), 2) ?></td>
|
||||
</tr>
|
||||
<?php else: ?>
|
||||
<tr>
|
||||
<td>CGST Amount:</td>
|
||||
<td class="text-end">₹<?= number_format((float)($grn['cgst_amount'] ?? ((float)$grn['total_tax_amount'] / 2)), 2) ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>SGST Amount:</td>
|
||||
<td class="text-end">₹<?= number_format((float)($grn['sgst_amount'] ?? ((float)$grn['total_tax_amount'] / 2)), 2) ?></td>
|
||||
</tr>
|
||||
<?php endif; ?>
|
||||
<tr>
|
||||
<td>GST Tax:</td>
|
||||
<td>Total GST:</td>
|
||||
<td class="text-end">₹<?= number_format((float)$grn['total_tax_amount'], 2) ?></td>
|
||||
</tr>
|
||||
<?php if (isset($grn['round_off']) && (float)$grn['round_off'] != 0): ?>
|
||||
<tr>
|
||||
<td>Round Off:</td>
|
||||
<td class="text-end"><?= ((float)$grn['round_off'] > 0 ? '+' : '') . number_format((float)$grn['round_off'], 2) ?></td>
|
||||
</tr>
|
||||
<?php endif; ?>
|
||||
<tr class="grand-total">
|
||||
<td>Net Payable Total:</td>
|
||||
<td>Net Inward Bill Total:</td>
|
||||
<td class="text-end">₹<?= number_format((float)$grn['net_amount'], 2) ?></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
|
|
|||
|
|
@ -102,25 +102,20 @@
|
|||
</div>
|
||||
<div class="col-md-2">
|
||||
<label class="form-label">CGST</label>
|
||||
<select class="form-select form-select-sm" name="input_CGST" id="input_CGST" onchange="calculate()">
|
||||
<select class="form-select form-select-sm" name="input_CGST" id="input_CGST" onchange="onCgstChange()">
|
||||
<?php
|
||||
$formatGstLabel = static function($val) {
|
||||
$f = (float)$val;
|
||||
if ($f == 0.0) return '0% (Exempt)';
|
||||
if ($f == 2.5) return '2.5% (5% GST)';
|
||||
if ($f == 6.0) return '6.0% (12% GST)';
|
||||
if ($f == 9.0) return '9.0% (18% GST)';
|
||||
if ($f == 20.0) return '20% (40% GST)';
|
||||
if ($f == 6.0) return '6.0% (12% Legacy)';
|
||||
if ($f == 14.0) return '14% (28% Legacy)';
|
||||
if ($f == 14.0) return '14.0% (28% GST)';
|
||||
return $val . '%';
|
||||
};
|
||||
$stdRates = ['0', '2.5', '9', '20', '6', '14'];
|
||||
$pRates = !empty($gstRates) ? array_map(static fn($r) => trim((string)($r->gst_per ?? '0')), $gstRates) : $stdRates;
|
||||
foreach ($stdRates as $sr) {
|
||||
if (!in_array($sr, $pRates, true)) $pRates[] = $sr;
|
||||
}
|
||||
$stdRates = ['0', '2.5', '6', '9', '14'];
|
||||
?>
|
||||
<?php foreach ($pRates as $gstValue): ?>
|
||||
<?php foreach ($stdRates as $gstValue): ?>
|
||||
<option value="<?= esc($gstValue) ?>" <?= ((float) $gstValue === 2.5) ? 'selected' : '' ?>><?= esc($formatGstLabel($gstValue)) ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
|
|
@ -128,7 +123,7 @@
|
|||
<div class="col-md-2">
|
||||
<label class="form-label">SGST / IGST</label>
|
||||
<select class="form-select form-select-sm" name="input_SGST" id="input_SGST" onchange="calculate()">
|
||||
<?php foreach ($pRates as $gstValue): ?>
|
||||
<?php foreach ($stdRates as $gstValue): ?>
|
||||
<option value="<?= esc($gstValue) ?>" <?= ((float) $gstValue === 2.5) ? 'selected' : '' ?>><?= esc($formatGstLabel($gstValue)) ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
|
|
@ -179,6 +174,12 @@
|
|||
</div>
|
||||
|
||||
<script>
|
||||
function onCgstChange() {
|
||||
var cgst = $('#input_CGST').val();
|
||||
$('#input_SGST').val(cgst);
|
||||
calculate();
|
||||
}
|
||||
|
||||
function calculate() {
|
||||
var pp = parseFloat($('#input_purchase_price').val() || 0);
|
||||
var qty = parseFloat($('#input_Qty').val() || 0);
|
||||
|
|
@ -186,23 +187,26 @@ function calculate() {
|
|||
var schamt = parseFloat($('#input_sch_amount').val() || 0);
|
||||
var schdisc = parseFloat($('#input_sch_disc').val() || 0);
|
||||
|
||||
var gross = pp * qty;
|
||||
var sch_per_amt = 0;
|
||||
if (schdisc > 0) {
|
||||
pp = pp - (pp * schdisc / 100);
|
||||
sch_per_amt = gross * (schdisc / 100);
|
||||
}
|
||||
var after_sch = Math.max(0, gross - sch_per_amt - schamt);
|
||||
|
||||
var amount = pp * qty;
|
||||
if (schamt > 0) {
|
||||
amount = amount - schamt;
|
||||
var trade_disc_amt = 0;
|
||||
if (disc > 0) {
|
||||
trade_disc_amt = after_sch * (disc / 100);
|
||||
}
|
||||
var taxamount = Math.max(0, after_sch - trade_disc_amt);
|
||||
|
||||
var taxamount = (amount - (amount * disc / 100));
|
||||
var cgst = parseFloat($('#input_CGST').val() || 0);
|
||||
var sgst = parseFloat($('#input_SGST').val() || 0);
|
||||
var cgst_amt = taxamount * cgst / 100;
|
||||
var sgst_amt = taxamount * sgst / 100;
|
||||
var net_amount = taxamount + cgst_amt + sgst_amt;
|
||||
|
||||
$('#amount_price').val(amount.toFixed(2));
|
||||
$('#amount_price').val(gross.toFixed(2));
|
||||
$('#Tamount_price').val(taxamount.toFixed(2));
|
||||
$('#Net_amount').val(net_amount.toFixed(2));
|
||||
|
||||
|
|
@ -332,9 +336,8 @@ function edit_item_invoice(inv_item_id) {
|
|||
$('#input_storage').val(data.cold_storage || '');
|
||||
$('#input_shelf_no').val(data.shelf_no || '');
|
||||
$('#input_rack_no').val(data.rack_no || '');
|
||||
$('#input_HSNCODE').val(data.HSNCODE || '');
|
||||
$('#input_CGST').val(data.CGST_per || '0');
|
||||
$('#input_SGST').val(data.SGST_per || '0');
|
||||
setSelectByNumericValue('input_CGST', data.CGST_per || '0');
|
||||
setSelectByNumericValue('input_SGST', data.SGST_per || '0');
|
||||
$('#invoice_item_id').val(data.item_id || 0);
|
||||
|
||||
calculate();
|
||||
|
|
@ -342,6 +345,21 @@ function edit_item_invoice(inv_item_id) {
|
|||
}, 'json');
|
||||
}
|
||||
|
||||
function setSelectByNumericValue(selectId, val) {
|
||||
var fVal = parseFloat(val || 0);
|
||||
var matched = false;
|
||||
$('#' + selectId + ' option').each(function() {
|
||||
if (Math.abs(parseFloat($(this).val()) - fVal) < 0.01) {
|
||||
$('#' + selectId).val($(this).val());
|
||||
matched = true;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
if (!matched) {
|
||||
$('#' + selectId).val(val);
|
||||
}
|
||||
}
|
||||
|
||||
$(document).ready(function () {
|
||||
toggle_update_purchase_items(false);
|
||||
load_form_div('<?= base_url('Medical/purchase_invoice_item_list/' . (int) ($invoice->id ?? 0)) ?>', 'invoice_item_list');
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user