Make IPD forms dynamic and stop stale OPD refresh polling
This commit is contained in:
parent
8bc9158e14
commit
2977192017
|
|
@ -400,36 +400,50 @@ class Ipd extends BaseController
|
|||
}
|
||||
|
||||
if ($tab === 'ipd-charges') {
|
||||
$this->syncNursingChargesToInvoice($ipdId);
|
||||
$panelData['ipd_charges_grouped'] = $this->ipdModel->getIpdChargesGrouped($ipdId);
|
||||
$panelData['ipd_charges_total'] = $this->ipdModel->getIpdChargesTotal($ipdId);
|
||||
$panelData['ipd_packages'] = $this->ipdModel->getIpdPackages($ipdId);
|
||||
try {
|
||||
$this->syncNursingChargesToInvoice($ipdId);
|
||||
$panelData['ipd_charges_grouped'] = $this->ipdModel->getIpdChargesGrouped($ipdId);
|
||||
$panelData['ipd_charges_total'] = $this->ipdModel->getIpdChargesTotal($ipdId);
|
||||
$panelData['ipd_packages'] = $this->ipdModel->getIpdPackages($ipdId);
|
||||
|
||||
$caseMeta = $this->ipdModel->getIpdCaseMeta($ipdId);
|
||||
$insCompId = (int) ($caseMeta['insurance_id'] ?? 0);
|
||||
if ($insCompId <= 0) {
|
||||
$insCompId = 1;
|
||||
}
|
||||
|
||||
$panelData['bedside_items_by_category'] = $this->nursingBedsideItemModel->getBillableGroupedByCategory($insCompId);
|
||||
|
||||
$panelData['ipd_insurance_id'] = $insCompId;
|
||||
$panelData['doc_list'] = $this->ipdModel->getIpdDoctorList();
|
||||
$doctorIds = array_map(static fn ($doc) => (int) ($doc->id ?? 0), $panelData['doc_list']);
|
||||
$doctorIds = array_values(array_filter($doctorIds, static fn ($id) => $id > 0));
|
||||
$panelData['doctor_visit_fee_types'] = $this->ipdModel->getDoctorVisitFeeTypes();
|
||||
$panelData['doctor_visit_fee_map'] = $this->ipdModel->getDoctorVisitFeeMap($doctorIds);
|
||||
$panelData['item_types'] = $this->itemIpdModel->getItemTypes();
|
||||
|
||||
$itemLists = [];
|
||||
foreach ($panelData['item_types'] as $type) {
|
||||
$typeId = (int) ($type->itype_id ?? 0);
|
||||
if ($typeId <= 0) {
|
||||
continue;
|
||||
$caseMeta = $this->ipdModel->getIpdCaseMeta($ipdId);
|
||||
$insCompId = (int) ($caseMeta['insurance_id'] ?? 0);
|
||||
if ($insCompId <= 0) {
|
||||
$insCompId = 1;
|
||||
}
|
||||
$itemLists[$typeId] = $this->itemIpdModel->getItemsByTypeWithInsurance($typeId, $insCompId);
|
||||
|
||||
$panelData['bedside_items_by_category'] = $this->nursingBedsideItemModel->getBillableGroupedByCategory($insCompId);
|
||||
|
||||
$panelData['ipd_insurance_id'] = $insCompId;
|
||||
$panelData['doc_list'] = $this->ipdModel->getIpdDoctorList();
|
||||
$doctorIds = array_map(static fn ($doc) => (int) ($doc->id ?? 0), $panelData['doc_list']);
|
||||
$doctorIds = array_values(array_filter($doctorIds, static fn ($id) => $id > 0));
|
||||
$panelData['doctor_visit_fee_types'] = $this->ipdModel->getDoctorVisitFeeTypes();
|
||||
$panelData['doctor_visit_fee_map'] = $this->ipdModel->getDoctorVisitFeeMap($doctorIds);
|
||||
$panelData['item_types'] = $this->itemIpdModel->getItemTypes();
|
||||
|
||||
$itemLists = [];
|
||||
foreach ($panelData['item_types'] as $type) {
|
||||
$typeId = (int) ($type->itype_id ?? 0);
|
||||
if ($typeId <= 0) {
|
||||
continue;
|
||||
}
|
||||
$itemLists[$typeId] = $this->itemIpdModel->getItemsByTypeWithInsurance($typeId, $insCompId);
|
||||
}
|
||||
$panelData['item_lists'] = $itemLists;
|
||||
} catch (\Throwable $e) {
|
||||
log_message('error', 'IPD Charges tab failed for IPD #' . $ipdId . ': ' . $e->getMessage());
|
||||
$panelData['ipd_charges_grouped'] = [];
|
||||
$panelData['ipd_charges_total'] = (object) ['total_amt' => 0, 'package_amt' => 0, 'patient_amt' => 0];
|
||||
$panelData['ipd_packages'] = [];
|
||||
$panelData['bedside_items_by_category'] = [];
|
||||
$panelData['ipd_insurance_id'] = 0;
|
||||
$panelData['doc_list'] = [];
|
||||
$panelData['doctor_visit_fee_types'] = [];
|
||||
$panelData['doctor_visit_fee_map'] = [];
|
||||
$panelData['item_types'] = [];
|
||||
$panelData['item_lists'] = [];
|
||||
}
|
||||
$panelData['item_lists'] = $itemLists;
|
||||
|
||||
return view('billing/ipd/panel_ipd_charges', $panelData);
|
||||
}
|
||||
|
|
@ -485,6 +499,7 @@ class Ipd extends BaseController
|
|||
return view('billing/ipd/panel_documents', [
|
||||
'ipd_id' => $ipdId,
|
||||
'ipd_info' => $panelData['ipd_info'] ?? null,
|
||||
'documents' => $this->getAvailableIpdDocuments(),
|
||||
]);
|
||||
}
|
||||
|
||||
|
|
@ -849,11 +864,6 @@ class Ipd extends BaseController
|
|||
return $permission;
|
||||
}
|
||||
|
||||
$formMeta = $this->getIpdFormMeta($formNo);
|
||||
if ($formMeta === null) {
|
||||
return $this->response->setStatusCode(404)->setBody('Unsupported form ID');
|
||||
}
|
||||
|
||||
$data = $this->buildIpdPrintableFormData($ipdId, $formNo);
|
||||
if ($data === null) {
|
||||
return $this->response->setStatusCode(404)->setBody('IPD not found');
|
||||
|
|
@ -2246,7 +2256,7 @@ class Ipd extends BaseController
|
|||
return [$start, $end];
|
||||
}
|
||||
|
||||
private function getIpdFormMeta(int $formNo): ?array
|
||||
private function getIpdFormMeta(int $formNo): array
|
||||
{
|
||||
$meta = [
|
||||
1 => ['title' => 'Face Form'],
|
||||
|
|
@ -2258,7 +2268,71 @@ class Ipd extends BaseController
|
|||
11 => ['title' => 'Sticker [2 x 8]'],
|
||||
];
|
||||
|
||||
return $meta[$formNo] ?? null;
|
||||
if (isset($meta[$formNo])) {
|
||||
return $meta[$formNo];
|
||||
}
|
||||
|
||||
$template = $this->getActiveIpdDocumentTemplate($formNo);
|
||||
if (is_array($template) && ! empty($template['template_name'])) {
|
||||
return ['title' => (string) $template['template_name']];
|
||||
}
|
||||
|
||||
return ['title' => 'IPD Form #' . $formNo];
|
||||
}
|
||||
|
||||
private function getAvailableIpdDocuments(): array
|
||||
{
|
||||
$default = [
|
||||
['id' => 1, 'label' => 'Print Face Form'],
|
||||
['id' => 5, 'label' => 'Admission Form'],
|
||||
['id' => 10, 'label' => 'Sticker [2 x 6]'],
|
||||
['id' => 11, 'label' => 'Sticker [2 x 8]'],
|
||||
['id' => 8, 'label' => 'Progress Notes'],
|
||||
['id' => 9, 'label' => 'Fluid In / Out'],
|
||||
['id' => 3, 'label' => 'Self Declaration Form'],
|
||||
];
|
||||
|
||||
if (! $this->db->tableExists('ipd_document_templates')) {
|
||||
return $default;
|
||||
}
|
||||
|
||||
$rows = $this->db->table('ipd_document_templates')
|
||||
->select('form_no, template_name, id')
|
||||
->where('status', 1)
|
||||
->orderBy('form_no', 'ASC')
|
||||
->orderBy('id', 'DESC')
|
||||
->get()
|
||||
->getResultArray();
|
||||
|
||||
if (empty($rows)) {
|
||||
return $default;
|
||||
}
|
||||
|
||||
$documents = [];
|
||||
foreach ($rows as $row) {
|
||||
$id = (int) ($row['form_no'] ?? 0);
|
||||
if ($id <= 0 || isset($documents[$id])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$label = trim((string) ($row['template_name'] ?? ''));
|
||||
if ($label === '') {
|
||||
$label = (string) ($this->getIpdFormMeta($id)['title'] ?? ('IPD Form #' . $id));
|
||||
}
|
||||
|
||||
$documents[$id] = [
|
||||
'id' => $id,
|
||||
'label' => $label,
|
||||
];
|
||||
}
|
||||
|
||||
if (empty($documents)) {
|
||||
return $default;
|
||||
}
|
||||
|
||||
ksort($documents);
|
||||
|
||||
return array_values($documents);
|
||||
}
|
||||
|
||||
private function buildIpdPrintableFormData(int $ipdId, int $formNo): ?array
|
||||
|
|
|
|||
|
|
@ -1730,8 +1730,8 @@ HTML,
|
|||
$marginFooter = max(0, min(25, (float) ($this->request->getPost('margin_footer_cm') ?? 0.5)));
|
||||
$status = (int) ($this->request->getPost('status') ?? 1) === 1 ? 1 : 0;
|
||||
|
||||
if (! in_array($formNo, [1, 3, 5, 8, 9, 10, 11], true)) {
|
||||
$notice = 'Invalid form number.';
|
||||
if ($formNo <= 0) {
|
||||
$notice = 'Form number must be a positive integer.';
|
||||
$noticeType = 'danger';
|
||||
} elseif ($templateName === '' || trim($templateHtml) === '') {
|
||||
$notice = 'Form number, template name and HTML are required.';
|
||||
|
|
|
|||
|
|
@ -31,6 +31,19 @@ $formMap = [
|
|||
10 => 'Sticker [2 x 6]',
|
||||
11 => 'Sticker [2 x 8]',
|
||||
];
|
||||
|
||||
$dynamicFormHints = [];
|
||||
foreach ($rows as $_row) {
|
||||
$fNo = (int) ($_row['form_no'] ?? 0);
|
||||
$tName = trim((string) ($_row['template_name'] ?? ''));
|
||||
if ($fNo <= 0 || $tName === '') {
|
||||
continue;
|
||||
}
|
||||
if (!isset($dynamicFormHints[$fNo])) {
|
||||
$dynamicFormHints[$fNo] = $tName;
|
||||
}
|
||||
}
|
||||
ksort($dynamicFormHints);
|
||||
?>
|
||||
|
||||
<section class="content">
|
||||
|
|
@ -65,12 +78,17 @@ $formMap = [
|
|||
|
||||
<div class="row g-2">
|
||||
<div class="col-md-3">
|
||||
<label class="form-label small">Form</label>
|
||||
<select name="form_no" class="form-select form-select-sm" required>
|
||||
<?php foreach ($formMap as $id => $label): ?>
|
||||
<option value="<?= (int) $id ?>" <?= $formNo === (int) $id ? 'selected' : '' ?>><?= (int) $id ?> - <?= esc($label) ?></option>
|
||||
<label class="form-label small">Form ID</label>
|
||||
<input type="number" name="form_no" list="ipd_form_suggestions" class="form-control form-control-sm" value="<?= (int) $formNo ?>" min="1" step="1" required>
|
||||
<datalist id="ipd_form_suggestions">
|
||||
<?php foreach ($dynamicFormHints as $id => $label): ?>
|
||||
<option value="<?= (int) $id ?>"><?= (int) $id ?> - <?= esc($label) ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
<?php foreach ($formMap as $id => $label): ?>
|
||||
<option value="<?= (int) $id ?>"><?= (int) $id ?> - <?= esc($label) ?></option>
|
||||
<?php endforeach; ?>
|
||||
</datalist>
|
||||
<small class="text-muted">Use any positive number (example: 12 for Treatment Chart, 13 for Vitals).</small>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label small">Template Name</label>
|
||||
|
|
|
|||
|
|
@ -2,15 +2,7 @@
|
|||
$ipdId = (int) ($ipd_id ?? 0);
|
||||
$ipdCode = (string) ($ipd_info->ipd_code ?? ('IPD-' . $ipdId));
|
||||
|
||||
$documents = [
|
||||
['id' => 1, 'label' => 'Print Face Form'],
|
||||
['id' => 5, 'label' => 'Admission Form'],
|
||||
['id' => 10, 'label' => 'Sticker [2 x 6]'],
|
||||
['id' => 11, 'label' => 'Sticker [2 x 8]'],
|
||||
['id' => 8, 'label' => 'Progress Notes'],
|
||||
['id' => 9, 'label' => 'Fluid In / Out'],
|
||||
['id' => 3, 'label' => 'Self Declaration Form'],
|
||||
];
|
||||
$documents = is_array($documents ?? null) ? $documents : [];
|
||||
?>
|
||||
|
||||
<div class="card border-0 shadow-sm">
|
||||
|
|
@ -35,6 +27,11 @@ $documents = [
|
|||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php if (empty($documents)) : ?>
|
||||
<tr>
|
||||
<td colspan="3" class="text-center text-muted py-3">No active document template found. Add templates from Document Master.</td>
|
||||
</tr>
|
||||
<?php endif; ?>
|
||||
<?php foreach ($documents as $document) : ?>
|
||||
<tr>
|
||||
<td><?= (int) $document['id'] ?></td>
|
||||
|
|
|
|||
|
|
@ -460,6 +460,14 @@ $mergedGroups = [
|
|||
}
|
||||
|
||||
function checkLiveUpdates() {
|
||||
if (!document.getElementById('opdAllTable')) {
|
||||
if (window.opdLiveMonitorTimer) {
|
||||
clearInterval(window.opdLiveMonitorTimer);
|
||||
window.opdLiveMonitorTimer = null;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (livePollInFlight || shouldSkipLiveCheck()) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -530,6 +538,13 @@ $mergedGroups = [
|
|||
window.opdLiveMonitorTimer = setInterval(checkLiveUpdates, livePollMs);
|
||||
}
|
||||
|
||||
function stopLiveUpdates() {
|
||||
if (window.opdLiveMonitorTimer) {
|
||||
clearInterval(window.opdLiveMonitorTimer);
|
||||
window.opdLiveMonitorTimer = null;
|
||||
}
|
||||
}
|
||||
|
||||
function setVitalMessage(type, text) {
|
||||
var $msg = $('#vital_msg');
|
||||
$msg.removeClass('text-muted text-success text-danger');
|
||||
|
|
@ -864,6 +879,10 @@ $mergedGroups = [
|
|||
reloadAppointmentList();
|
||||
});
|
||||
|
||||
$(window).off('beforeunload.opdlive').on('beforeunload.opdlive', function() {
|
||||
stopLiveUpdates();
|
||||
});
|
||||
|
||||
// Initialize
|
||||
registerOpdTableFilter();
|
||||
opdDataTable = initializeOpdTable();
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user