Add pharmacy invoice permissions and discount print fixes
This commit is contained in:
parent
7422f9c170
commit
252f911fad
|
|
@ -53,6 +53,10 @@ class AuthGroups extends ShieldAuthGroups
|
||||||
'title' => 'Developer',
|
'title' => 'Developer',
|
||||||
'description' => 'Site programmers.',
|
'description' => 'Site programmers.',
|
||||||
],
|
],
|
||||||
|
'pharmacy_admin' => [
|
||||||
|
'title' => 'Pharmacy Admin',
|
||||||
|
'description' => 'Full pharmacy controls including old bill edits and discount overrides.',
|
||||||
|
],
|
||||||
'stock_manager' => [
|
'stock_manager' => [
|
||||||
'title' => 'Stock Manager',
|
'title' => 'Stock Manager',
|
||||||
'description' => 'Manages stock masters, approvals, and procurement.',
|
'description' => 'Manages stock masters, approvals, and procurement.',
|
||||||
|
|
@ -148,6 +152,11 @@ class AuthGroups extends ShieldAuthGroups
|
||||||
'doctor_work.advice.manage' => 'Can manage OPD advice master',
|
'doctor_work.advice.manage' => 'Can manage OPD advice master',
|
||||||
'doctor_work.template_workspace.access' => 'Can access clinical templates workspace',
|
'doctor_work.template_workspace.access' => 'Can access clinical templates workspace',
|
||||||
'pharmacy.access' => 'Can access pharmacy module',
|
'pharmacy.access' => 'Can access pharmacy module',
|
||||||
|
'pharmacy.invoice.admin' => 'Can fully manage pharmacy invoice controls (old bills and discount overrides)',
|
||||||
|
'pharmacy.invoice.discount.10' => 'Can apply pharmacy invoice discount up to 10%',
|
||||||
|
'pharmacy.invoice.discount.20' => 'Can apply pharmacy invoice discount up to 20%',
|
||||||
|
'pharmacy.invoice.discount.30' => 'Can apply pharmacy invoice discount up to 30%',
|
||||||
|
'pharmacy.invoice.edit-old' => 'Can edit past Walk-in/Registered pharmacy invoices',
|
||||||
'pharmacy.purchase.status-update' => 'Can update pharmacy purchase invoice status',
|
'pharmacy.purchase.status-update' => 'Can update pharmacy purchase invoice status',
|
||||||
'template.pathology' => 'Can access pathology templates',
|
'template.pathology' => 'Can access pathology templates',
|
||||||
'template.ultrasound' => 'Can access ultrasound templates',
|
'template.ultrasound' => 'Can access ultrasound templates',
|
||||||
|
|
@ -247,6 +256,9 @@ class AuthGroups extends ShieldAuthGroups
|
||||||
'hospital_stock.*',
|
'hospital_stock.*',
|
||||||
'abdm.*',
|
'abdm.*',
|
||||||
],
|
],
|
||||||
|
'pharmacy_admin' => [
|
||||||
|
'pharmacy.*',
|
||||||
|
],
|
||||||
'stock_manager' => [
|
'stock_manager' => [
|
||||||
'hospital_stock.access',
|
'hospital_stock.access',
|
||||||
'hospital_stock.master.manage',
|
'hospital_stock.master.manage',
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,15 @@ class Medical extends BaseController
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
$permission !== 'pharmacy.invoice.admin'
|
||||||
|
&& $user
|
||||||
|
&& method_exists($user, 'can')
|
||||||
|
&& $user->can('pharmacy.invoice.admin')
|
||||||
|
) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if ($user && method_exists($user, 'inGroup') && $user->inGroup('superadmin', 'admin', 'developer')) {
|
if ($user && method_exists($user, 'inGroup') && $user->inGroup('superadmin', 'admin', 'developer')) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
@ -53,6 +62,89 @@ class Medical extends BaseController
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function getHospitalSettingValue(string $name, string $default = ''): string
|
||||||
|
{
|
||||||
|
$name = trim($name);
|
||||||
|
if ($name === '' || ! $this->db->tableExists('hospital_setting')) {
|
||||||
|
return $default;
|
||||||
|
}
|
||||||
|
|
||||||
|
$row = $this->db->table('hospital_setting')
|
||||||
|
->select('s_value')
|
||||||
|
->where('s_name', $name)
|
||||||
|
->get()
|
||||||
|
->getRowArray();
|
||||||
|
|
||||||
|
if (! is_array($row) || ! array_key_exists('s_value', $row)) {
|
||||||
|
return $default;
|
||||||
|
}
|
||||||
|
|
||||||
|
$value = trim((string) ($row['s_value'] ?? ''));
|
||||||
|
return $value !== '' ? $value : $default;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getPharmacyBaseDiscountPercent(): float
|
||||||
|
{
|
||||||
|
$raw = $this->getHospitalSettingValue('PHARMACY_NORMAL_MAX_DISCOUNT_PERCENT', '10');
|
||||||
|
$percent = is_numeric($raw) ? (float) $raw : 10.0;
|
||||||
|
if ($percent < 0) {
|
||||||
|
$percent = 0.0;
|
||||||
|
}
|
||||||
|
if ($percent > 100) {
|
||||||
|
$percent = 100.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return round($percent, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getPharmacyMaxDiscountPercent(): float
|
||||||
|
{
|
||||||
|
if ($this->canPharmacyPermission('pharmacy.invoice.admin')) {
|
||||||
|
return 100.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
$percent = $this->getPharmacyBaseDiscountPercent();
|
||||||
|
|
||||||
|
if ($this->canPharmacyPermission('pharmacy.invoice.discount.10')) {
|
||||||
|
$percent = max($percent, 10.0);
|
||||||
|
}
|
||||||
|
if ($this->canPharmacyPermission('pharmacy.invoice.discount.20')) {
|
||||||
|
$percent = max($percent, 20.0);
|
||||||
|
}
|
||||||
|
if ($this->canPharmacyPermission('pharmacy.invoice.discount.30')) {
|
||||||
|
$percent = max($percent, 30.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($percent < 0) {
|
||||||
|
$percent = 0.0;
|
||||||
|
}
|
||||||
|
if ($percent > 100) {
|
||||||
|
$percent = 100.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return round($percent, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function validatePharmacyDiscountAmount(float $grossAmount, float $discountAmount, ?string &$errorText = null): bool
|
||||||
|
{
|
||||||
|
$errorText = null;
|
||||||
|
|
||||||
|
if ($discountAmount < 0) {
|
||||||
|
$errorText = 'Discount amount cannot be negative.';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$maxPercent = $this->getPharmacyMaxDiscountPercent();
|
||||||
|
$maxAmount = round(max(0.0, $grossAmount) * $maxPercent / 100, 2);
|
||||||
|
|
||||||
|
if ($discountAmount > $maxAmount + 0.00001) {
|
||||||
|
$errorText = 'Discount Amount is greater than allowed limit. Max : ' . number_format($maxAmount, 2, '.', '') . ' (' . rtrim(rtrim(number_format($maxPercent, 2, '.', ''), '0'), '.') . '%)';
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
private function ensureMedicalAdminActionLogTable(): void
|
private function ensureMedicalAdminActionLogTable(): void
|
||||||
{
|
{
|
||||||
if ($this->db->tableExists('medical_admin_action_log')) {
|
if ($this->db->tableExists('medical_admin_action_log')) {
|
||||||
|
|
@ -2064,6 +2156,8 @@ class Medical extends BaseController
|
||||||
$message = trim((string) $this->request->getGet('msg'));
|
$message = trim((string) $this->request->getGet('msg'));
|
||||||
$editBlockReason = null;
|
$editBlockReason = null;
|
||||||
$canEditInvoice = $this->canEditInvoiceRecord((array) $invoice, $editBlockReason);
|
$canEditInvoice = $this->canEditInvoiceRecord((array) $invoice, $editBlockReason);
|
||||||
|
$discountPercentLimit = $this->getPharmacyMaxDiscountPercent();
|
||||||
|
$discountAmountLimit = round((float) ($invoice->gross_amount ?? 0) * $discountPercentLimit / 100, 2);
|
||||||
|
|
||||||
return view('medical/medical_final_invoice', [
|
return view('medical/medical_final_invoice', [
|
||||||
'invoice' => $invoice,
|
'invoice' => $invoice,
|
||||||
|
|
@ -2077,6 +2171,8 @@ class Medical extends BaseController
|
||||||
'message' => $message,
|
'message' => $message,
|
||||||
'canEditInvoice' => $canEditInvoice,
|
'canEditInvoice' => $canEditInvoice,
|
||||||
'editBlockReason' => (string) ($editBlockReason ?? ''),
|
'editBlockReason' => (string) ($editBlockReason ?? ''),
|
||||||
|
'discountPercentLimit' => $discountPercentLimit,
|
||||||
|
'discountAmountLimit' => $discountAmountLimit,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2669,6 +2765,12 @@ class Medical extends BaseController
|
||||||
return service('response')->setJSON(['update' => 0, 'msg_text' => 'No invoice found']);
|
return service('response')->setJSON(['update' => 0, 'msg_text' => 'No invoice found']);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$grossAmount = (float) ($invoice->gross_amount ?? 0);
|
||||||
|
$discountError = null;
|
||||||
|
if (! $this->validatePharmacyDiscountAmount($grossAmount, $discount, $discountError)) {
|
||||||
|
return service('response')->setJSON(['update' => 0, 'msg_text' => (string) $discountError]);
|
||||||
|
}
|
||||||
|
|
||||||
$invoiceId = (int) ($invoice->id ?? 0);
|
$invoiceId = (int) ($invoice->id ?? 0);
|
||||||
$update = [];
|
$update = [];
|
||||||
if (in_array('discount_amount', $fields, true)) {
|
if (in_array('discount_amount', $fields, true)) {
|
||||||
|
|
@ -3110,6 +3212,15 @@ class Medical extends BaseController
|
||||||
$discountAmount = (float) $this->request->getPost('input_dis_amt');
|
$discountAmount = (float) $this->request->getPost('input_dis_amt');
|
||||||
$discountRemark = trim((string) $this->request->getPost('input_dis_desc'));
|
$discountRemark = trim((string) $this->request->getPost('input_dis_desc'));
|
||||||
|
|
||||||
|
$grossAmount = (float) ($invoice->gross_amount ?? 0);
|
||||||
|
$discountError = null;
|
||||||
|
if (! $this->validatePharmacyDiscountAmount($grossAmount, $discountAmount, $discountError)) {
|
||||||
|
return service('response')->setJSON([
|
||||||
|
'update' => 0,
|
||||||
|
'error_text' => (string) $discountError,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
$user = service('auth')->user();
|
$user = service('auth')->user();
|
||||||
$userId = (int) ($user->id ?? 0);
|
$userId = (int) ($user->id ?? 0);
|
||||||
$userName = $user ? trim(($user->first_name ?? '') . ' ' . ($user->last_name ?? '')) : 'System';
|
$userName = $user ? trim(($user->first_name ?? '') . ' ' . ($user->last_name ?? '')) : 'System';
|
||||||
|
|
@ -3441,7 +3552,12 @@ class Medical extends BaseController
|
||||||
$caseId = (int) ($invoiceRow['case_id'] ?? 0);
|
$caseId = (int) ($invoiceRow['case_id'] ?? 0);
|
||||||
$isWalkInOrRegistered = $ipdId === 0 && $caseId === 0 && in_array($customerType, [0, 1], true);
|
$isWalkInOrRegistered = $ipdId === 0 && $caseId === 0 && in_array($customerType, [0, 1], true);
|
||||||
|
|
||||||
if ($isPastDate && $isWalkInOrRegistered && ! $this->canPharmacyPermission('pharmacy.invoice.edit-old')) {
|
if (
|
||||||
|
$isPastDate
|
||||||
|
&& $isWalkInOrRegistered
|
||||||
|
&& ! $this->canPharmacyPermission('pharmacy.invoice.edit-old')
|
||||||
|
&& ! $this->canPharmacyPermission('pharmacy.invoice.admin')
|
||||||
|
) {
|
||||||
$reason = 'No permission to edit past Walk-in/Registered pharmacy invoice.';
|
$reason = 'No permission to edit past Walk-in/Registered pharmacy invoice.';
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -6209,7 +6325,6 @@ class Medical extends BaseController
|
||||||
|
|
||||||
$key = $this->normalizeCompactKey($value);
|
$key = $this->normalizeCompactKey($value);
|
||||||
$map = [
|
$map = [
|
||||||
'tab' => 'Tablet',
|
|
||||||
'tabs' => 'Tablet',
|
'tabs' => 'Tablet',
|
||||||
'tablet' => 'Tablet',
|
'tablet' => 'Tablet',
|
||||||
'tablets' => 'Tablet',
|
'tablets' => 'Tablet',
|
||||||
|
|
|
||||||
|
|
@ -51,11 +51,12 @@
|
||||||
<div class="mt-4">
|
<div class="mt-4">
|
||||||
<label class="form-label">Permissions</label>
|
<label class="form-label">Permissions</label>
|
||||||
<div class="alert alert-info py-2 mb-2">
|
<div class="alert alert-info py-2 mb-2">
|
||||||
Pharmacy module access is controlled by <strong>pharmacy.access</strong>.
|
Pharmacy module access is controlled by <strong>pharmacy.access</strong>. Editing past Walk-in/Registered pharmacy invoices requires <strong>pharmacy.invoice.edit-old</strong> (or <strong>pharmacy.invoice.admin</strong>). Discount caps can be granted with <strong>pharmacy.invoice.discount.10</strong>, <strong>pharmacy.invoice.discount.20</strong>, <strong>pharmacy.invoice.discount.30</strong>, or full override using <strong>pharmacy.invoice.admin</strong>. Base user discount can be set in hospital setting key <strong>PHARMACY_NORMAL_MAX_DISCOUNT_PERCENT</strong>.
|
||||||
</div>
|
</div>
|
||||||
<div class="border rounded p-3 bg-light">
|
<div class="border rounded p-3 bg-light">
|
||||||
<?php
|
<?php
|
||||||
$selectedPermissions = [];
|
$selectedPermissions = [];
|
||||||
|
$permissions = $permissions ?? [];
|
||||||
if (! empty($selectedUser)) {
|
if (! empty($selectedUser)) {
|
||||||
$selectedPermissions = $selectedUser->getPermissions() ?? [];
|
$selectedPermissions = $selectedUser->getPermissions() ?? [];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,19 @@
|
||||||
|
|
||||||
$doctorName = trim((string) ($invoice->doc_name ?? ''));
|
$doctorName = trim((string) ($invoice->doc_name ?? ''));
|
||||||
$doctorLabel = $doctorName !== '' ? (preg_match('/^dr\.?\s*/i', $doctorName) ? $doctorName : 'Dr. ' . $doctorName) : '-';
|
$doctorLabel = $doctorName !== '' ? (preg_match('/^dr\.?\s*/i', $doctorName) ? $doctorName : 'Dr. ' . $doctorName) : '-';
|
||||||
|
$items = $items ?? [];
|
||||||
|
$rowCount = count($items);
|
||||||
|
$baseGrossTotal = 0.0;
|
||||||
|
$baseDiscountTotal = 0.0;
|
||||||
|
if (! empty($items)) {
|
||||||
|
foreach ($items as $printItem) {
|
||||||
|
$baseGrossTotal += (float) ($printItem->amount ?? 0);
|
||||||
|
$baseDiscountTotal += (float) ($printItem->disc_amount ?? 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$invoiceDiscountTotal = (float) (($invoice->discount_amount ?? 0) + ($invoice->disc_amount ?? 0) + ($invoice->item_discount_amount ?? 0));
|
||||||
|
$extraInvoiceDiscountTotal = max(0.0, $invoiceDiscountTotal - $baseDiscountTotal);
|
||||||
|
$allocatedExtraDiscountTotal = 0.0;
|
||||||
?>
|
?>
|
||||||
<div class="print-actions">
|
<div class="print-actions">
|
||||||
<button onclick="window.print()">Print</button>
|
<button onclick="window.print()">Print</button>
|
||||||
|
|
@ -79,8 +92,23 @@
|
||||||
<?php foreach ($items as $idx => $item): ?>
|
<?php foreach ($items as $idx => $item): ?>
|
||||||
<?php
|
<?php
|
||||||
$rowGross = (float) ($item->amount ?? 0);
|
$rowGross = (float) ($item->amount ?? 0);
|
||||||
$rowDisc = (float) ($item->disc_amount ?? 0);
|
$baseRowDisc = (float) ($item->disc_amount ?? 0);
|
||||||
$rowNet = (float) ($item->tamount ?? 0);
|
$baseRowNet = (float) ($item->twdisc_amount ?? $item->tamount ?? ($item->net_amount ?? 0));
|
||||||
|
$remainingExtraDiscount = max(0.0, $extraInvoiceDiscountTotal - $allocatedExtraDiscountTotal);
|
||||||
|
$allocExtraDisc = 0.0;
|
||||||
|
if ($remainingExtraDiscount > 0 && $baseGrossTotal > 0) {
|
||||||
|
if ((int) $idx === $rowCount - 1) {
|
||||||
|
$allocExtraDisc = $remainingExtraDiscount;
|
||||||
|
} else {
|
||||||
|
$allocExtraDisc = round($extraInvoiceDiscountTotal * ($rowGross / $baseGrossTotal), 2);
|
||||||
|
if ($allocExtraDisc > $remainingExtraDiscount) {
|
||||||
|
$allocExtraDisc = $remainingExtraDiscount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$allocatedExtraDiscountTotal += $allocExtraDisc;
|
||||||
|
$rowDisc = $baseRowDisc + $allocExtraDisc;
|
||||||
|
$rowNet = max(0.0, $baseRowNet - $allocExtraDisc);
|
||||||
$gross += $rowGross;
|
$gross += $rowGross;
|
||||||
$discount += $rowDisc;
|
$discount += $rowDisc;
|
||||||
$net += $rowNet;
|
$net += $rowNet;
|
||||||
|
|
@ -103,17 +131,26 @@
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
</tbody>
|
</tbody>
|
||||||
<tfoot>
|
<tfoot>
|
||||||
|
<?php
|
||||||
|
$printGrossTotal = (float) ($invoice->gross_amount ?? $gross);
|
||||||
|
$printDiscountTotal = (float) (($invoice->discount_amount ?? 0) + ($invoice->disc_amount ?? 0) + ($invoice->item_discount_amount ?? 0));
|
||||||
|
$printDiscountTotal = $printDiscountTotal > 0 ? $printDiscountTotal : $discount;
|
||||||
|
$printNetTotal = $printGrossTotal - $printDiscountTotal;
|
||||||
|
if ($printNetTotal < 0) {
|
||||||
|
$printNetTotal = 0.0;
|
||||||
|
}
|
||||||
|
?>
|
||||||
<tr class="totals">
|
<tr class="totals">
|
||||||
<td colspan="6" class="text-end">Gross</td>
|
<td colspan="6" class="text-end">Gross</td>
|
||||||
<td colspan="2" class="text-end"><?= esc(number_format((float)($invoice->gross_amount ?? $gross), 2)) ?></td>
|
<td colspan="2" class="text-end"><?= esc(number_format($printGrossTotal, 2)) ?></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr class="totals">
|
<tr class="totals">
|
||||||
<td colspan="6" class="text-end">Discount</td>
|
<td colspan="6" class="text-end">Discount</td>
|
||||||
<td colspan="2" class="text-end"><?= esc(number_format((float)($invoice->disc_amount ?? $discount), 2)) ?></td>
|
<td colspan="2" class="text-end"><?= esc(number_format($printDiscountTotal, 2)) ?></td>
|
||||||
</tr>
|
</tr>
|
||||||
<tr class="totals">
|
<tr class="totals">
|
||||||
<td colspan="6" class="text-end">Net Amount</td>
|
<td colspan="6" class="text-end">Net Amount</td>
|
||||||
<td colspan="2" class="text-end"><?= esc(number_format((float)($invoice->net_amount ?? $net), 2)) ?></td>
|
<td colspan="2" class="text-end"><?= esc(number_format($printNetTotal, 2)) ?></td>
|
||||||
</tr>
|
</tr>
|
||||||
</tfoot>
|
</tfoot>
|
||||||
</table>
|
</table>
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ $customerCode = trim((string) ($invoice->patient_code ?? ''));
|
||||||
$customerPhone = trim((string) ($invoice->inv_phone_number ?? ($patient->mphone1 ?? '')));
|
$customerPhone = trim((string) ($invoice->inv_phone_number ?? ($patient->mphone1 ?? '')));
|
||||||
$doctorName = trim((string) ($invoice->doc_name ?? ''));
|
$doctorName = trim((string) ($invoice->doc_name ?? ''));
|
||||||
$doctorLabel = $doctorName !== '' ? (preg_match('/^dr\.?\s*/i', $doctorName) ? $doctorName : 'Dr. ' . $doctorName) : '-';
|
$doctorLabel = $doctorName !== '' ? (preg_match('/^dr\.?\s*/i', $doctorName) ? $doctorName : 'Dr. ' . $doctorName) : '-';
|
||||||
|
$items = $items ?? [];
|
||||||
$addressLine = $pharmacyAddress;
|
$addressLine = $pharmacyAddress;
|
||||||
if ($pharmacyState !== '') {
|
if ($pharmacyState !== '') {
|
||||||
$addressLine .= ($addressLine !== '' ? ', ' : '') . $pharmacyState;
|
$addressLine .= ($addressLine !== '' ? ', ' : '') . $pharmacyState;
|
||||||
|
|
@ -26,6 +27,18 @@ $discountTotal = 0.0;
|
||||||
$cgstTotal = 0.0;
|
$cgstTotal = 0.0;
|
||||||
$sgstTotal = 0.0;
|
$sgstTotal = 0.0;
|
||||||
$netTotal = 0.0;
|
$netTotal = 0.0;
|
||||||
|
$invoiceLevelDiscountTotal = (float) (($invoice->discount_amount ?? 0) + ($invoice->disc_amount ?? 0) + ($invoice->item_discount_amount ?? 0));
|
||||||
|
$itemCount = count($items);
|
||||||
|
$baseGrossTotal = 0.0;
|
||||||
|
$baseDiscountTotal = 0.0;
|
||||||
|
if (! empty($items)) {
|
||||||
|
foreach ($items as $printItem) {
|
||||||
|
$baseGrossTotal += (float) ($printItem->amount ?? 0);
|
||||||
|
$baseDiscountTotal += (float) ($printItem->disc_amount ?? 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$extraInvoiceDiscountTotal = max(0.0, $invoiceLevelDiscountTotal - $baseDiscountTotal);
|
||||||
|
$allocatedExtraDiscountTotal = 0.0;
|
||||||
|
|
||||||
$compact = in_array((int) ($printFormat ?? 0), [1, 2, 3], true);
|
$compact = in_array((int) ($printFormat ?? 0), [1, 2, 3], true);
|
||||||
$baseFont = $compact ? '10px' : '11px';
|
$baseFont = $compact ? '10px' : '11px';
|
||||||
|
|
@ -129,8 +142,25 @@ $tdPad = $compact ? '4px 4px' : '5px 5px';
|
||||||
<?php foreach ($items as $index => $item): ?>
|
<?php foreach ($items as $index => $item): ?>
|
||||||
<?php
|
<?php
|
||||||
$gross = (float) ($item->amount ?? 0);
|
$gross = (float) ($item->amount ?? 0);
|
||||||
$disc = (float) ($item->disc_amount ?? ($item->twdisc_amount ?? 0));
|
$baseDisc = (float) ($item->disc_amount ?? 0);
|
||||||
$net = (float) ($item->twdisc_amount ?? $item->tamount ?? ($item->net_amount ?? 0));
|
$baseNet = (float) ($item->twdisc_amount ?? $item->tamount ?? ($item->net_amount ?? 0));
|
||||||
|
|
||||||
|
$remainingExtraDiscount = max(0.0, $extraInvoiceDiscountTotal - $allocatedExtraDiscountTotal);
|
||||||
|
$allocExtraDisc = 0.0;
|
||||||
|
if ($remainingExtraDiscount > 0 && $baseGrossTotal > 0) {
|
||||||
|
if ((int) $index === $itemCount - 1) {
|
||||||
|
$allocExtraDisc = $remainingExtraDiscount;
|
||||||
|
} else {
|
||||||
|
$allocExtraDisc = round($extraInvoiceDiscountTotal * ($gross / $baseGrossTotal), 2);
|
||||||
|
if ($allocExtraDisc > $remainingExtraDiscount) {
|
||||||
|
$allocExtraDisc = $remainingExtraDiscount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$allocatedExtraDiscountTotal += $allocExtraDisc;
|
||||||
|
|
||||||
|
$disc = $baseDisc + $allocExtraDisc;
|
||||||
|
$net = max(0.0, $baseNet - $allocExtraDisc);
|
||||||
|
|
||||||
$cgstPer = (float) ($item->CGST_per ?? 0);
|
$cgstPer = (float) ($item->CGST_per ?? 0);
|
||||||
$sgstPer = (float) ($item->SGST_per ?? 0);
|
$sgstPer = (float) ($item->SGST_per ?? 0);
|
||||||
|
|
@ -179,8 +209,10 @@ $tdPad = $compact ? '4px 4px' : '5px 5px';
|
||||||
|
|
||||||
<?php
|
<?php
|
||||||
$grossFinal = (float) ($invoice->gross_amount ?? $grossTotal);
|
$grossFinal = (float) ($invoice->gross_amount ?? $grossTotal);
|
||||||
$discFinal = (float) ($invoice->disc_amount ?? $discountTotal);
|
$invoiceDiscount = (float) (($invoice->discount_amount ?? 0) + ($invoice->disc_amount ?? 0) + ($invoice->item_discount_amount ?? 0));
|
||||||
$netFinal = (float) ($invoice->net_amount ?? $netTotal);
|
$discFinal = $invoiceDiscount > 0 ? $invoiceDiscount : $discountTotal;
|
||||||
|
$netFromSummary = $grossFinal - $discFinal;
|
||||||
|
$netFinal = $netFromSummary >= 0 ? $netFromSummary : 0.0;
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<table class="summary">
|
<table class="summary">
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,8 @@
|
||||||
$deduction = (float) ($paymentSummary['extra_discount'] ?? ($invoice->discount_amount ?? 0));
|
$deduction = (float) ($paymentSummary['extra_discount'] ?? ($invoice->discount_amount ?? 0));
|
||||||
$deductionRemark = (string) ($paymentSummary['discount_remark'] ?? ($invoice->discount_remark ?? ''));
|
$deductionRemark = (string) ($paymentSummary['discount_remark'] ?? ($invoice->discount_remark ?? ''));
|
||||||
$allowPaymentMode = ((int) ($invoice->ipd_credit ?? 0) === 0) && ((int) ($invoice->case_credit ?? 0) === 0) && ((int) ($invoice->group_invoice_id ?? 0) === 0);
|
$allowPaymentMode = ((int) ($invoice->ipd_credit ?? 0) === 0) && ((int) ($invoice->case_credit ?? 0) === 0) && ((int) ($invoice->group_invoice_id ?? 0) === 0);
|
||||||
|
$discountPercentLimit = (float) ($discountPercentLimit ?? 10.0);
|
||||||
|
$discountAmountLimit = (float) ($discountAmountLimit ?? (((float) ($invoice->gross_amount ?? 0)) * $discountPercentLimit / 100));
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<div class="card border-0" id="medical-final-invoice">
|
<div class="card border-0" id="medical-final-invoice">
|
||||||
|
|
@ -145,6 +147,9 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="table-responsive mb-3">
|
<div class="table-responsive mb-3">
|
||||||
|
<div class="small text-muted mb-2">
|
||||||
|
Max allowed deduction for your login: <?= esc(number_format($discountPercentLimit, 2)) ?>% (<?= esc(number_format($discountAmountLimit, 2)) ?>)
|
||||||
|
</div>
|
||||||
<table class="table table-sm table-striped table-bordered align-middle mb-0">
|
<table class="table table-sm table-striped table-bordered align-middle mb-0">
|
||||||
<tr>
|
<tr>
|
||||||
<th style="width: 18px">#</th>
|
<th style="width: 18px">#</th>
|
||||||
|
|
@ -335,9 +340,10 @@
|
||||||
btnDed.addEventListener('click', function () {
|
btnDed.addEventListener('click', function () {
|
||||||
var grossAmount = parseFloat('<?= (float)($invoice->gross_amount ?? 0) ?>');
|
var grossAmount = parseFloat('<?= (float)($invoice->gross_amount ?? 0) ?>');
|
||||||
var discountAmount = parseFloat(document.getElementById('input_dis_amt').value || '0');
|
var discountAmount = parseFloat(document.getElementById('input_dis_amt').value || '0');
|
||||||
var maxDiscount = grossAmount * 0.12;
|
var discountPercentLimit = parseFloat('<?= (float) ($discountPercentLimit ?? 10.0) ?>');
|
||||||
|
var maxDiscount = grossAmount * discountPercentLimit / 100;
|
||||||
if (discountAmount > maxDiscount) {
|
if (discountAmount > maxDiscount) {
|
||||||
showError('Discount Amount is greater than allowed limit. Max : ' + maxDiscount.toFixed(2));
|
showError('Discount Amount is greater than allowed limit. Max : ' + maxDiscount.toFixed(2) + ' (' + discountPercentLimit.toFixed(2).replace(/\.00$/, '') + '%)');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user