Enhance report actions with grouped controls and PDF exports

This commit is contained in:
DevSoftTech Server 2026-03-22 04:01:06 +05:30
parent a519525fa3
commit 50e2a4f145
8 changed files with 478 additions and 23 deletions

View File

@ -652,6 +652,8 @@ $routes->get('Report/report_total_payment_app_show/(:segment)/(:segment)/(:segme
$routes->get('Report/report_total_payment_app_show/(:segment)/(:segment)/(:segment)/(:num)', 'Report::report_total_payment_app_show/$1/$2/$3/$4');
$routes->get('Report/report_total_payment_app_show/(:segment)/(:segment)/(:segment)/(:segment)', 'Report::report_total_payment_app_show/$1/$2/$3/$4');
$routes->get('Report/report_total_payment_app_show/(:segment)/(:segment)/(:segment)/(:segment)/(:num)', 'Report::report_total_payment_app_show/$1/$2/$3/$4/$5');
$routes->get('Report/report_total_payment_total_amount_show/(:segment)/(:segment)/(:segment)', 'Report::report_total_payment_total_amount_show/$1/$2/$3');
$routes->get('Report/report_total_payment_total_amount_show/(:segment)/(:segment)/(:segment)/(:num)', 'Report::report_total_payment_total_amount_show/$1/$2/$3/$4');
$routes->get('Report/billing_operations_report', 'Report::billing_operations_report');
$routes->get('Report/billing_operations_report_data/(:segment)/(:segment)', 'Report::billing_operations_report_data/$1/$2');

View File

@ -2,6 +2,8 @@
namespace App\Controllers;
use Mpdf\Mpdf;
class Report extends BaseController
{
public function index()
@ -103,6 +105,151 @@ class Report extends BaseController
return $this->response->setBody('');
}
if ($output === 2) {
$mpdfTempDir = WRITEPATH . 'cache' . DIRECTORY_SEPARATOR . 'mpdf';
if (! is_dir($mpdfTempDir)) {
mkdir($mpdfTempDir, 0755, true);
}
$mpdf = new Mpdf([
'tempDir' => $mpdfTempDir,
'format' => 'A4-L',
'margin_top' => 8,
'margin_bottom' => 8,
'margin_left' => 8,
'margin_right' => 8,
]);
$pdfHtml = '<style>'
. 'body{font-family:Arial,sans-serif;color:#111;font-size:12px;}'
. 'table{width:100%;border-collapse:collapse;}'
. 'th,td{border:1px solid #9aa4ad;padding:6px 8px;}'
. 'th{text-align:left;background:#f5f6f7;}'
. '.text-end{text-align:right;}'
. '.table-warning td,.table-warning th{background:#fff6cc !important;}'
. '</style>'
. '<h3 style="margin:0 0 10px 0;">Collection Report</h3>'
. $content;
$mpdf->WriteHTML($pdfHtml);
$fileName = 'Collection_Report_' . date('Ymd_His') . '.pdf';
return $this->response
->setHeader('Content-Type', 'application/pdf')
->setHeader('Content-Disposition', 'inline; filename="' . $fileName . '"')
->setBody($mpdf->Output($fileName, 'S'));
}
return $this->response->setBody($content);
}
public function report_total_payment_total_amount_show(
string $dateRange,
string $employeeIds,
string $payModeId,
int $output = 0
) {
[$minRange, $maxRange] = $this->parseDateRange($dateRange);
$builder = $this->db->table('payment_history p');
$builder->select('p.update_by_id as user_id')
->select('COALESCE(u.username, p.update_by) as user_name', false)
->select('SUM(CASE WHEN p.credit_debit = 0 AND p.payof_type = 1 THEN p.amount ELSE 0 END) as opd_amount', false)
->select('SUM(CASE WHEN p.credit_debit = 0 AND p.payof_type = 2 THEN p.amount ELSE 0 END) as charge_amount', false)
->select('SUM(CASE WHEN p.credit_debit = 0 AND p.payof_type = 4 THEN p.amount ELSE 0 END) as ipd_amount', false)
->select('SUM(CASE WHEN p.credit_debit = 0 AND p.payof_type = 3 THEN p.amount ELSE 0 END) as org_amount', false)
->select('SUM(CASE WHEN p.credit_debit = 1 THEN p.amount ELSE 0 END) as return_amount', false)
->select('SUM(CASE WHEN p.credit_debit = 0 THEN p.amount ELSE 0 END) - SUM(CASE WHEN p.credit_debit = 1 THEN p.amount ELSE 0 END) as total_amount', false)
->join('users u', 'u.id = p.update_by_id', 'left')
->where('p.payment_date >=', $minRange)
->where('p.payment_date <=', $maxRange);
$empList = $this->normalizeIdList($employeeIds);
if (! empty($empList)) {
$builder->whereIn('p.update_by_id', $empList);
}
$payMode = (int) $payModeId;
if ($payMode < 1) {
$builder->whereIn('p.payment_mode', [1, 2]);
} else {
$builder->where('p.payment_mode', $payMode);
}
$rows = $builder
->groupBy(['p.update_by_id', 'u.username'])
->orderBy('u.username', 'ASC')
->orderBy('p.update_by_id', 'ASC')
->get()
->getResult();
$totals = [
'opd_amount' => 0.0,
'charge_amount' => 0.0,
'ipd_amount' => 0.0,
'org_amount' => 0.0,
'return_amount' => 0.0,
'total_amount' => 0.0,
];
foreach ($rows as $row) {
$totals['opd_amount'] += (float) ($row->opd_amount ?? 0);
$totals['charge_amount'] += (float) ($row->charge_amount ?? 0);
$totals['ipd_amount'] += (float) ($row->ipd_amount ?? 0);
$totals['org_amount'] += (float) ($row->org_amount ?? 0);
$totals['return_amount'] += (float) ($row->return_amount ?? 0);
$totals['total_amount'] += (float) ($row->total_amount ?? 0);
}
$content = view('report/collection_report_total_table', [
'rows' => $rows,
'totals' => $totals,
'min_range' => $minRange,
'max_range' => $maxRange,
]);
if ($output === 1) {
ExportExcel($content, 'Collection_Report_Total_' . date('YmdHis'));
return $this->response->setBody('');
}
if ($output === 2) {
$mpdfTempDir = WRITEPATH . 'cache' . DIRECTORY_SEPARATOR . 'mpdf';
if (! is_dir($mpdfTempDir)) {
mkdir($mpdfTempDir, 0755, true);
}
$mpdf = new Mpdf([
'tempDir' => $mpdfTempDir,
'format' => 'A4-L',
'margin_top' => 8,
'margin_bottom' => 8,
'margin_left' => 8,
'margin_right' => 8,
]);
$pdfHtml = '<style>'
. 'body{font-family:Arial,sans-serif;color:#111;font-size:12px;}'
. 'table{width:100%;border-collapse:collapse;}'
. 'th,td{border:1px solid #9aa4ad;padding:6px 8px;}'
. 'th{text-align:left;background:#f5f6f7;}'
. '.text-end{text-align:right;}'
. '.table-warning td,.table-warning th{background:#fff6cc !important;}'
. '</style>'
. '<h3 style="margin:0 0 10px 0;">Collection Report - Total Amount</h3>'
. $content;
$mpdf->WriteHTML($pdfHtml);
$fileName = 'Collection_Report_Total_' . date('Ymd_His') . '.pdf';
return $this->response
->setHeader('Content-Type', 'application/pdf')
->setHeader('Content-Disposition', 'inline; filename="' . $fileName . '"')
->setBody($mpdf->Output($fileName, 'S'));
}
return $this->response->setBody($content);
}
@ -327,6 +474,42 @@ class Report extends BaseController
return $this->response->setBody('');
}
if ($output === 2) {
$mpdfTempDir = WRITEPATH . 'cache' . DIRECTORY_SEPARATOR . 'mpdf';
if (! is_dir($mpdfTempDir)) {
mkdir($mpdfTempDir, 0755, true);
}
$mpdf = new Mpdf([
'tempDir' => $mpdfTempDir,
'format' => 'A4-L',
'margin_top' => 8,
'margin_bottom' => 8,
'margin_left' => 8,
'margin_right' => 8,
]);
$pdfHtml = '<style>'
. 'body{font-family:Arial,sans-serif;color:#111;font-size:12px;}'
. 'table{width:100%;border-collapse:collapse;}'
. 'th,td{border:1px solid #9aa4ad;padding:6px 8px;}'
. 'th{text-align:left;background:#f5f6f7;}'
. '.text-end{text-align:right;}'
. '.table-light td,.table-light th{background:#f5f6f7 !important;}'
. '</style>'
. '<h3 style="margin:0 0 10px 0;">Billing Operations Report</h3>'
. $content;
$mpdf->WriteHTML($pdfHtml);
$fileName = 'Billing_Operations_Report_' . date('Ymd_His') . '.pdf';
return $this->response
->setHeader('Content-Type', 'application/pdf')
->setHeader('Content-Disposition', 'inline; filename="' . $fileName . '"')
->setBody($mpdf->Output($fileName, 'S'));
}
return $this->response->setBody($content);
}
@ -465,6 +648,42 @@ class Report extends BaseController
return $this->response->setBody('');
}
if ($output === 2) {
$mpdfTempDir = WRITEPATH . 'cache' . DIRECTORY_SEPARATOR . 'mpdf';
if (! is_dir($mpdfTempDir)) {
mkdir($mpdfTempDir, 0755, true);
}
$mpdf = new Mpdf([
'tempDir' => $mpdfTempDir,
'format' => 'A4',
'margin_top' => 8,
'margin_bottom' => 8,
'margin_left' => 8,
'margin_right' => 8,
]);
$pdfHtml = '<style>'
. 'body{font-family:Arial,sans-serif;color:#111;font-size:12px;}'
. 'table{width:100%;border-collapse:collapse;}'
. 'th,td{border:1px solid #9aa4ad;padding:6px 8px;}'
. 'th{text-align:left;background:#f5f6f7;}'
. '.text-end{text-align:right;}'
. '.table-light td,.table-light th{background:#f5f6f7 !important;}'
. '</style>'
. '<h3 style="margin:0 0 10px 0;">Document Issue Report</h3>'
. $content;
$mpdf->WriteHTML($pdfHtml);
$fileName = 'Document_Issue_Report_' . date('Ymd_His') . '.pdf';
return $this->response
->setHeader('Content-Type', 'application/pdf')
->setHeader('Content-Disposition', 'inline; filename="' . $fileName . '"')
->setBody($mpdf->Output($fileName, 'S'));
}
return $this->response->setBody($content);
}
@ -476,12 +695,18 @@ class Report extends BaseController
) {
[$minRange, $maxRange] = $this->parseDateRange($dateRange);
$netAmountExpr = "ROUND(IF(m.invoice_status=1, (t.item_amount - (t.item_amount * m.discount_amount / NULLIF(m.total_amount, 0))), 0), 2)";
$builder = $this->db->table('invoice_master m');
$builder->select('y.group_desc, t.item_name')
->select('COUNT(t.id) as no_test', false)
->select('SUM(t.item_qty) as no_qty', false)
->select('SUM(ROUND(IF(m.invoice_status=1, (t.item_amount - (t.item_amount * m.discount_amount / m.total_amount)), 0), 2)) as total_amount', false)
->select('SUM(' . $netAmountExpr . ') as total_amount', false)
->select('SUM(IF(m.invoice_status=1, t.item_amount, 0)) as total_act_amount', false)
->select('SUM(CASE WHEN m.ipd_id = 0 AND IFNULL(m.insurance_case_id, 0) = 0 THEN ' . $netAmountExpr . ' ELSE 0 END) as direct_patient_amount', false)
->select('SUM(CASE WHEN m.ipd_id > 0 AND IFNULL(m.insurance_case_id, 0) = 0 THEN ' . $netAmountExpr . ' ELSE 0 END) as ipd_direct_amount', false)
->select('SUM(CASE WHEN m.ipd_id > 0 AND IFNULL(m.insurance_case_id, 0) > 0 THEN ' . $netAmountExpr . ' ELSE 0 END) as ipd_tpa_amount', false)
->select('SUM(CASE WHEN m.ipd_id = 0 AND IFNULL(m.insurance_case_id, 0) > 0 THEN ' . $netAmountExpr . ' ELSE 0 END) as org_credit_amount', false)
->join('invoice_item t', 'm.id = t.inv_master_id', 'inner')
->join('hc_item_type y', 't.item_type = y.itype_id', 'inner')
->where('y.is_ipd_opd IN (0, 1)', null, false)
@ -530,6 +755,45 @@ class Report extends BaseController
return $this->response->setBody('');
}
if ($output === 2) {
$mpdfTempDir = WRITEPATH . 'cache' . DIRECTORY_SEPARATOR . 'mpdf';
if (! is_dir($mpdfTempDir)) {
mkdir($mpdfTempDir, 0755, true);
}
$mpdf = new Mpdf([
'tempDir' => $mpdfTempDir,
'format' => 'A4-L',
'margin_top' => 8,
'margin_bottom' => 8,
'margin_left' => 8,
'margin_right' => 8,
]);
$pdfHtml = '<style>'
. 'body{font-family:Arial,sans-serif;color:#111;font-size:12px;}'
. 'table{width:100%;border-collapse:collapse;}'
. 'th,td{border:1px solid #9aa4ad;padding:6px 8px;}'
. 'th{background:#f5f6f7;text-align:left;}'
. '.text-end{text-align:right;}'
. '.table-info td,.table-info th{background:#d9edf7 !important;}'
. '.table-secondary td,.table-secondary th{background:#eceff1 !important;}'
. '.table-primary td,.table-primary th{background:#dbe9ff !important;}'
. '.mb-3{margin-bottom:12px;}'
. '</style>'
. '<h3 style="margin:0 0 10px 0;">Diagnosis Report</h3>'
. $content;
$mpdf->WriteHTML($pdfHtml);
$fileName = 'Diagnosis_Report_' . date('Ymd_His') . '.pdf';
return $this->response
->setHeader('Content-Type', 'application/pdf')
->setHeader('Content-Disposition', 'inline; filename="' . $fileName . '"')
->setBody($mpdf->Output($fileName, 'S'));
}
return $this->response->setBody($content);
}

View File

@ -24,9 +24,12 @@ $doctors = $doctors ?? [];
<?php endforeach; ?>
</select>
</div>
<div class="col-md-2 d-flex gap-2">
<button type="button" class="btn btn-primary w-100" id="billing_show">Show</button>
<button type="button" class="btn btn-outline-primary w-100" id="billing_export">Export</button>
<div class="col-md-2">
<div class="btn-group w-100" role="group" aria-label="Billing report actions">
<button type="button" class="btn btn-primary" id="billing_show">Show</button>
<button type="button" class="btn btn-outline-primary" id="billing_export">Export</button>
<button type="button" class="btn btn-outline-danger" id="billing_pdf">PDF</button>
</div>
</div>
</div>
</div>
@ -85,6 +88,11 @@ $doctors = $doctors ?? [];
window.open(buildUrl(true), '_blank');
});
document.getElementById('billing_pdf').addEventListener('click', function() {
var url = buildUrl(false) + '/2';
window.open(url, '_blank');
});
$('.select2').select2({
theme: 'bootstrap4',
width: '100%'

View File

@ -36,9 +36,17 @@ $payModes = $pay_modes ?? [];
</div>
</div>
<div class="mt-3 d-flex gap-2">
<button type="button" class="btn btn-primary" id="show_report">Show</button>
<button type="button" class="btn btn-outline-primary" id="export_report">Export</button>
<div class="mt-3 d-flex flex-wrap gap-2">
<div class="btn-group" role="group" aria-label="Collection details actions">
<button type="button" class="btn btn-primary" id="show_report">Show Details</button>
<button type="button" class="btn btn-outline-primary" id="export_report">Details Export</button>
<button type="button" class="btn btn-outline-danger" id="pdf_report">Details PDF</button>
</div>
<div class="btn-group" role="group" aria-label="Collection total actions">
<button type="button" class="btn btn-warning" id="show_total_amount">Show Total Amount</button>
<button type="button" class="btn btn-outline-primary" id="total_export_report">Total Export</button>
<button type="button" class="btn btn-outline-danger" id="total_pdf_report">Total PDF</button>
</div>
</div>
</div>
</div>
@ -78,7 +86,7 @@ $payModes = $pay_modes ?? [];
document.getElementById('report_start').value = toInputValue(start);
document.getElementById('report_end').value = toInputValue(end);
function buildQuery() {
function buildBaseQuery() {
var startVal = toRangeValue(document.getElementById('report_start').value, toInputValue(start));
var endVal = toRangeValue(document.getElementById('report_end').value, toInputValue(end));
var dateRange = startVal + 'S' + endVal;
@ -93,17 +101,50 @@ $payModes = $pay_modes ?? [];
var empList = empValues.length ? empValues.join('S') : '0';
var payMode = document.getElementById('paymode_id').value || '0';
return '<?= base_url('Report/report_total_payment_app_show') ?>/'
+ encodeURIComponent(dateRange) + '/' + empList + '/' + payMode;
return {
dateRange: encodeURIComponent(dateRange),
empList: empList,
payMode: payMode,
};
}
function buildDetailQuery() {
var q = buildBaseQuery();
return '<?= base_url('Report/report_total_payment_app_show') ?>/' + q.dateRange + '/' + q.empList + '/' + q.payMode;
}
function buildTotalQuery() {
var q = buildBaseQuery();
return '<?= base_url('Report/report_total_payment_total_amount_show') ?>/' + q.dateRange + '/' + q.empList + '/' + q.payMode;
}
document.getElementById('show_report').addEventListener('click', function() {
var url = buildQuery();
var url = buildDetailQuery();
load_form_div(url, 'report_result');
});
document.getElementById('show_total_amount').addEventListener('click', function() {
var totalUrl = buildTotalQuery();
load_form_div(totalUrl, 'report_result');
});
document.getElementById('export_report').addEventListener('click', function() {
var url = buildQuery() + '/1';
var url = buildDetailQuery() + '/0/1';
window.open(url, '_blank');
});
document.getElementById('pdf_report').addEventListener('click', function() {
var url = buildDetailQuery() + '/0/2';
window.open(url, '_blank');
});
document.getElementById('total_export_report').addEventListener('click', function() {
var url = buildTotalQuery() + '/1';
window.open(url, '_blank');
});
document.getElementById('total_pdf_report').addEventListener('click', function() {
var url = buildTotalQuery() + '/2';
window.open(url, '_blank');
});

View File

@ -0,0 +1,67 @@
<?php
$rows = $rows ?? [];
$totals = $totals ?? [
'opd_amount' => 0,
'charge_amount' => 0,
'ipd_amount' => 0,
'org_amount' => 0,
'return_amount' => 0,
'total_amount' => 0,
];
$minRange = $min_range ?? '';
$maxRange = $max_range ?? '';
?>
<p class="mb-2"><strong>Date Range:</strong> <?= esc($minRange) ?> to <?= esc($maxRange) ?></p>
<?php if (empty($rows)) : ?>
<div class="text-muted">No records found for the selected filters.</div>
<?php else : ?>
<table class="table table-bordered table-sm align-middle">
<thead class="table-warning">
<tr>
<th>User ID</th>
<th class="text-end">OPD Amount</th>
<th class="text-end">Charge Amount</th>
<th class="text-end">IPD Amount</th>
<th class="text-end">ORG Amount</th>
<th class="text-end">Return Amount</th>
<th class="text-end">Total</th>
</tr>
</thead>
<tbody>
<?php foreach ($rows as $row) : ?>
<tr>
<td>
<?php
$userName = trim((string) ($row->user_name ?? ''));
$userId = (int) ($row->user_id ?? 0);
$userLabel = $userName !== '' ? $userName : 'Unknown';
if ($userId > 0) {
$userLabel .= '[' . $userId . ']';
}
?>
<?= esc($userLabel) ?>
</td>
<td class="text-end"><?= esc(number_format((float) ($row->opd_amount ?? 0), 2)) ?></td>
<td class="text-end"><?= esc(number_format((float) ($row->charge_amount ?? 0), 2)) ?></td>
<td class="text-end"><?= esc(number_format((float) ($row->ipd_amount ?? 0), 2)) ?></td>
<td class="text-end"><?= esc(number_format((float) ($row->org_amount ?? 0), 2)) ?></td>
<td class="text-end"><?= esc(number_format((float) ($row->return_amount ?? 0), 2)) ?></td>
<td class="text-end"><?= esc(number_format((float) ($row->total_amount ?? 0), 2)) ?></td>
</tr>
<?php endforeach; ?>
</tbody>
<tfoot>
<tr class="table-warning">
<th>Total</th>
<th class="text-end"><?= esc(number_format((float) ($totals['opd_amount'] ?? 0), 2)) ?></th>
<th class="text-end"><?= esc(number_format((float) ($totals['charge_amount'] ?? 0), 2)) ?></th>
<th class="text-end"><?= esc(number_format((float) ($totals['ipd_amount'] ?? 0), 2)) ?></th>
<th class="text-end"><?= esc(number_format((float) ($totals['org_amount'] ?? 0), 2)) ?></th>
<th class="text-end"><?= esc(number_format((float) ($totals['return_amount'] ?? 0), 2)) ?></th>
<th class="text-end"><?= esc(number_format((float) ($totals['total_amount'] ?? 0), 2)) ?></th>
</tr>
</tfoot>
</table>
<?php endif; ?>

View File

@ -35,9 +35,12 @@ $itemTypes = $item_types ?? [];
</div>
</div>
<div class="mt-3 d-flex gap-2">
<button type="button" class="btn btn-primary" id="show_report">Show</button>
<button type="button" class="btn btn-outline-primary" id="export_report">Export</button>
<div class="mt-3">
<div class="btn-group" role="group" aria-label="Diagnosis report actions">
<button type="button" class="btn btn-primary" id="show_report">Show</button>
<button type="button" class="btn btn-outline-primary" id="export_report">Export</button>
<button type="button" class="btn btn-outline-danger" id="pdf_report">PDF</button>
</div>
</div>
</div>
</div>
@ -107,6 +110,11 @@ $itemTypes = $item_types ?? [];
window.open(url, '_blank');
});
document.getElementById('pdf_report').addEventListener('click', function() {
var url = buildQuery() + '/2';
window.open(url, '_blank');
});
// Initialize Select2
$('.select2').select2({
theme: 'bootstrap4',

View File

@ -3,10 +3,27 @@ $rows = $rows ?? [];
$minRange = $min_range ?? '';
$maxRange = $max_range ?? '';
$invoiceTypeLabel = $invoice_type_label ?? 'All Types';
$formatIndianDateTime = static function ($value): string {
$value = trim((string) $value);
if ($value === '') {
return '';
}
$timestamp = strtotime($value);
if ($timestamp === false) {
return $value;
}
return date('d-m-Y H:i:s', $timestamp);
};
$minRangeDisplay = $formatIndianDateTime($minRange);
$maxRangeDisplay = $formatIndianDateTime($maxRange);
?>
<div class="mb-3">
<p><strong>Date Range:</strong> <?= esc($minRange) ?> to <?= esc($maxRange) ?></p>
<p><strong>Date Range:</strong> <?= esc($minRangeDisplay) ?> to <?= esc($maxRangeDisplay) ?></p>
<p><strong>Invoice Type:</strong> <?= esc($invoiceTypeLabel) ?></p>
</div>
@ -17,11 +34,14 @@ $invoiceTypeLabel = $invoice_type_label ?? 'All Types';
<thead class="table-light">
<tr>
<th style="width: 50px;">#</th>
<th>Diagnosis Group</th>
<th>Test Name</th>
<th class="text-end" style="width: 120px;">No. of Qty</th>
<th class="text-end" style="width: 120px;">Amount</th>
<th class="text-end" style="width: 120px;">Cost Amt</th>
<th class="text-end" style="width: 140px;">Direct Patient Amt</th>
<th class="text-end" style="width: 130px;">IPD Direct Amt</th>
<th class="text-end" style="width: 120px;">IPD TPA Amt</th>
<th class="text-end" style="width: 120px;">Org Credit Amt</th>
</tr>
</thead>
<tbody>
@ -30,9 +50,17 @@ $invoiceTypeLabel = $invoice_type_label ?? 'All Types';
$diagnosisHeadTotal = 0.0;
$diagnosisActHeadTotal = 0.0;
$diagnosisQtyTotal = 0.0;
$diagnosisDirectPatientTotal = 0.0;
$diagnosisIpdDirectTotal = 0.0;
$diagnosisIpdTpaTotal = 0.0;
$diagnosisOrgCreditTotal = 0.0;
$grandTotal = 0.0;
$grandActTotal = 0.0;
$grandQtyTotal = 0.0;
$grandDirectPatientTotal = 0.0;
$grandIpdDirectTotal = 0.0;
$grandIpdTpaTotal = 0.0;
$grandOrgCreditTotal = 0.0;
$rowCount = count($rows);
$rowNum = 0;
@ -43,6 +71,10 @@ $invoiceTypeLabel = $invoice_type_label ?? 'All Types';
$noQty = (float) ($row->no_qty ?? 0);
$totalAmount = (float) ($row->total_amount ?? 0);
$totalActAmount = (float) ($row->total_act_amount ?? 0);
$directPatientAmount = (float) ($row->direct_patient_amount ?? 0);
$ipdDirectAmount = (float) ($row->ipd_direct_amount ?? 0);
$ipdTpaAmount = (float) ($row->ipd_tpa_amount ?? 0);
$orgCreditAmount = (float) ($row->org_credit_amount ?? 0);
// Diagnosis group header
if ($groupDesc !== $diagnosisHead) {
@ -50,19 +82,27 @@ $invoiceTypeLabel = $invoice_type_label ?? 'All Types';
if ($diagnosisHead !== '') {
echo '<tr class="table-secondary">';
echo '<td></td>';
echo '<td colspan="2"><strong>Total of ' . esc($diagnosisHead) . '</strong></td>';
echo '<td><strong>Total of ' . esc($diagnosisHead) . '</strong></td>';
echo '<td class="text-end"><strong>' . number_format($diagnosisQtyTotal, 0) . '</strong></td>';
echo '<td class="text-end"><strong>' . number_format($diagnosisHeadTotal, 2) . '</strong></td>';
echo '<td class="text-end"><strong>' . number_format($diagnosisActHeadTotal, 2) . '</strong></td>';
echo '<td class="text-end"><strong>' . number_format($diagnosisDirectPatientTotal, 2) . '</strong></td>';
echo '<td class="text-end"><strong>' . number_format($diagnosisIpdDirectTotal, 2) . '</strong></td>';
echo '<td class="text-end"><strong>' . number_format($diagnosisIpdTpaTotal, 2) . '</strong></td>';
echo '<td class="text-end"><strong>' . number_format($diagnosisOrgCreditTotal, 2) . '</strong></td>';
echo '</tr>';
$diagnosisHeadTotal = 0.0;
$diagnosisActHeadTotal = 0.0;
$diagnosisQtyTotal = 0.0;
$diagnosisDirectPatientTotal = 0.0;
$diagnosisIpdDirectTotal = 0.0;
$diagnosisIpdTpaTotal = 0.0;
$diagnosisOrgCreditTotal = 0.0;
}
echo '<tr class="table-info">';
echo '<td colspan="6"><strong>' . esc($groupDesc) . '</strong></td>';
echo '<td colspan="9"><strong>' . esc($groupDesc) . '</strong></td>';
echo '</tr>';
$diagnosisHead = $groupDesc;
}
@ -71,40 +111,59 @@ $invoiceTypeLabel = $invoice_type_label ?? 'All Types';
$rowNum++;
echo '<tr>';
echo '<td>' . $rowNum . '</td>';
echo '<td></td>';
echo '<td>' . esc($itemName) . '</td>';
echo '<td class="text-end">' . number_format($noQty, 0) . '</td>';
echo '<td class="text-end">' . number_format($totalAmount, 2) . '</td>';
echo '<td class="text-end">' . number_format($totalActAmount, 2) . '</td>';
echo '<td class="text-end">' . number_format($directPatientAmount, 2) . '</td>';
echo '<td class="text-end">' . number_format($ipdDirectAmount, 2) . '</td>';
echo '<td class="text-end">' . number_format($ipdTpaAmount, 2) . '</td>';
echo '<td class="text-end">' . number_format($orgCreditAmount, 2) . '</td>';
echo '</tr>';
// Update totals
$diagnosisHeadTotal += $totalAmount;
$diagnosisActHeadTotal += $totalActAmount;
$diagnosisQtyTotal += $noQty;
$diagnosisDirectPatientTotal += $directPatientAmount;
$diagnosisIpdDirectTotal += $ipdDirectAmount;
$diagnosisIpdTpaTotal += $ipdTpaAmount;
$diagnosisOrgCreditTotal += $orgCreditAmount;
$grandTotal += $totalAmount;
$grandActTotal += $totalActAmount;
$grandQtyTotal += $noQty;
$grandDirectPatientTotal += $directPatientAmount;
$grandIpdDirectTotal += $ipdDirectAmount;
$grandIpdTpaTotal += $ipdTpaAmount;
$grandOrgCreditTotal += $orgCreditAmount;
}
// Show last group total
if ($diagnosisHead !== '' && $rowCount > 0) {
echo '<tr class="table-secondary">';
echo '<td></td>';
echo '<td colspan="2"><strong>Total of ' . esc($diagnosisHead) . '</strong></td>';
echo '<td><strong>Total of ' . esc($diagnosisHead) . '</strong></td>';
echo '<td class="text-end"><strong>' . number_format($diagnosisQtyTotal, 0) . '</strong></td>';
echo '<td class="text-end"><strong>' . number_format($diagnosisHeadTotal, 2) . '</strong></td>';
echo '<td class="text-end"><strong>' . number_format($diagnosisActHeadTotal, 2) . '</strong></td>';
echo '<td class="text-end"><strong>' . number_format($diagnosisDirectPatientTotal, 2) . '</strong></td>';
echo '<td class="text-end"><strong>' . number_format($diagnosisIpdDirectTotal, 2) . '</strong></td>';
echo '<td class="text-end"><strong>' . number_format($diagnosisIpdTpaTotal, 2) . '</strong></td>';
echo '<td class="text-end"><strong>' . number_format($diagnosisOrgCreditTotal, 2) . '</strong></td>';
echo '</tr>';
}
?>
</tbody>
<tfoot class="table-primary">
<tr>
<th colspan="3"><strong>Grand Total</strong></th>
<th colspan="2"><strong>Grand Total</strong></th>
<th class="text-end"><strong><?= number_format($grandQtyTotal, 0) ?></strong></th>
<th class="text-end"><strong><?= number_format($grandTotal, 2) ?></strong></th>
<th class="text-end"><strong><?= number_format($grandActTotal, 2) ?></strong></th>
<th class="text-end"><strong><?= number_format($grandDirectPatientTotal, 2) ?></strong></th>
<th class="text-end"><strong><?= number_format($grandIpdDirectTotal, 2) ?></strong></th>
<th class="text-end"><strong><?= number_format($grandIpdTpaTotal, 2) ?></strong></th>
<th class="text-end"><strong><?= number_format($grandOrgCreditTotal, 2) ?></strong></th>
</tr>
</tfoot>
</table>

View File

@ -29,9 +29,10 @@ $doclist = $doclist ?? [];
<input type="text" class="form-control" id="uhid_filter" placeholder="UHID / PCode">
</div>
<div class="col-md-3">
<div class="d-flex gap-2">
<div class="btn-group" role="group" aria-label="Document report actions">
<button type="button" class="btn btn-primary" id="showreport">Show</button>
<button type="button" class="btn btn-outline-primary" id="showreportexport">Export</button>
<button type="button" class="btn btn-outline-danger" id="showreportpdf">PDF</button>
</div>
</div>
</div>
@ -81,5 +82,10 @@ $doclist = $doclist ?? [];
document.getElementById('showreportexport').addEventListener('click', function() {
window.open(buildUrl(true), '_blank');
});
document.getElementById('showreportpdf').addEventListener('click', function() {
var pdfUrl = buildUrl(false) + '/2';
window.open(pdfUrl, '_blank');
});
})();
</script>