Add IPD status management with strict ipd_status check
- Update isIpdDischargedInvoice to check ONLY ipd_status field (remove fallback checks) - Add IPD status toggle UI in discharge panel (Active/Discharged control) - Create toggleIpdStatus controller method with permission check - Add billing.ipd.status.manage permission for controlling bill edit lock - Allows editing bills when needed by toggling status independently of discharge_date - Auto-releases bed when setting status to discharged
This commit is contained in:
parent
15458715a8
commit
c437652b79
|
|
@ -131,6 +131,7 @@ class AuthGroups extends ShieldAuthGroups
|
|||
'billing.ipd.admission.edit' => 'Can edit IPD admission details (date, mode, department, refer, doctors, contact, clinical notes)',
|
||||
'billing.ipd.bill.print' => 'Can print IPD bill variants',
|
||||
'billing.ipd.discharge.edit' => 'Can edit IPD discharge process details (discount, extra charges, status, date, time)',
|
||||
'billing.ipd.status.manage' => 'Can toggle IPD status between Active and Discharged (controls bill edit lock)',
|
||||
'settings.bed_status.view' => 'Can view bed status and bed management screens',
|
||||
'settings.charges.access' => 'Can access charges settings',
|
||||
'reports.access' => 'Can access reports section',
|
||||
|
|
|
|||
|
|
@ -879,6 +879,57 @@ class Ipd extends BaseController
|
|||
return $this->buildDischargeProcessResponse($ipdId, 'Discharge status updated.');
|
||||
}
|
||||
|
||||
public function toggleIpdStatus(int $ipdId)
|
||||
{
|
||||
$permission = $this->requireAnyPermission([
|
||||
'billing.ipd.status.manage',
|
||||
]);
|
||||
if ($permission) {
|
||||
return $permission;
|
||||
}
|
||||
|
||||
if (! $this->request->isAJAX()) {
|
||||
return $this->response->setStatusCode(400)->setJSON(['update' => 0, 'message' => 'Invalid request']);
|
||||
}
|
||||
|
||||
$fieldMap = $this->getIpdFieldMap();
|
||||
if (! isset($fieldMap['ipd_status'])) {
|
||||
return $this->response->setStatusCode(422)->setJSON([
|
||||
'update' => 0,
|
||||
'message' => 'ipd_status field not available in schema'
|
||||
]);
|
||||
}
|
||||
|
||||
$newStatus = (int) ($this->request->getPost('ipd_status') ?? -1);
|
||||
if ($newStatus !== 0 && $newStatus !== 1) {
|
||||
return $this->response->setStatusCode(422)->setJSON([
|
||||
'update' => 0,
|
||||
'message' => 'Invalid status value (must be 0 or 1)'
|
||||
]);
|
||||
}
|
||||
|
||||
// Get current status
|
||||
$currentIpd = $this->ipdModel->getById($ipdId);
|
||||
if (! $currentIpd) {
|
||||
return $this->response->setStatusCode(404)->setJSON(['update' => 0, 'message' => 'IPD not found']);
|
||||
}
|
||||
|
||||
$currentStatus = (int) ($currentIpd['ipd_status'] ?? 0);
|
||||
|
||||
// Update status
|
||||
$update = ['ipd_status' => $newStatus];
|
||||
$this->ipdEditModel->updateIpd($update, $ipdId);
|
||||
|
||||
// Release bed when setting to discharged (status = 1)
|
||||
if ($newStatus === 1 && $currentStatus === 0) {
|
||||
$this->ipdEditModel->releaseBed($ipdId);
|
||||
}
|
||||
|
||||
$statusText = $newStatus === 0 ? 'Active (Bills unlocked)' : 'Discharged (Bills locked)';
|
||||
|
||||
return $this->buildDischargeProcessResponse($ipdId, 'IPD status set to: ' . $statusText);
|
||||
}
|
||||
|
||||
public function billPrint(int $ipdId, int $mode = 1)
|
||||
{
|
||||
$permission = $this->requireAnyPermission([
|
||||
|
|
|
|||
|
|
@ -3511,21 +3511,10 @@ class Medical extends BaseController
|
|||
return false;
|
||||
}
|
||||
|
||||
foreach (['ipd_status', 'discharge_status', 'discharg_status', 'is_discharged'] as $statusCol) {
|
||||
if (in_array($statusCol, $ipdFields, true) && (int) ($ipd[$statusCol] ?? 0) !== 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (['discharge_date', 'discharge_datetime', 'discharged_at'] as $dateCol) {
|
||||
if (! in_array($dateCol, $ipdFields, true)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$value = trim((string) ($ipd[$dateCol] ?? ''));
|
||||
if ($value !== '' && $value !== '0000-00-00' && $value !== '0000-00-00 00:00:00') {
|
||||
return true;
|
||||
}
|
||||
// PRIMARY CHECK ONLY: ipd_status = 1 means discharged
|
||||
// No fallback checks - this gives flexibility to edit bills even if discharge_date is set
|
||||
if (in_array('ipd_status', $ipdFields, true)) {
|
||||
return (int) ($ipd['ipd_status'] ?? 0) === 1;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -22,6 +22,25 @@ if (strlen($dischargeTime) > 5) {
|
|||
}
|
||||
?>
|
||||
|
||||
<?php
|
||||
$currentIpdStatus = (int) ($ipd->ipd_status ?? 0);
|
||||
$canManageIpdStatus = auth()->user()?->can('billing.ipd.status.manage') ?? false;
|
||||
?>
|
||||
|
||||
<?php if ($canManageIpdStatus) : ?>
|
||||
<div class="alert alert-warning border-warning d-flex align-items-center gap-3 mb-3">
|
||||
<div class="flex-grow-1">
|
||||
<strong>IPD Status Control:</strong>
|
||||
Current status is <strong><?= $currentIpdStatus === 0 ? 'Active (Bills can be edited)' : 'Discharged (Bills are locked)' ?></strong>
|
||||
</div>
|
||||
<div>
|
||||
<button type="button" class="btn btn-sm <?= $currentIpdStatus === 0 ? 'btn-danger' : 'btn-success' ?> js-toggle-ipd-status" data-current="<?= $currentIpdStatus ?>">
|
||||
<?= $currentIpdStatus === 0 ? 'Lock Bills (Set Discharged)' : 'Unlock Bills (Set Active)' ?>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="row g-3">
|
||||
<div class="col-lg-6">
|
||||
<div class="card h-100">
|
||||
|
|
@ -228,6 +247,38 @@ if (strlen($dischargeTime) > 5) {
|
|||
alert(msg);
|
||||
});
|
||||
});
|
||||
|
||||
$(document).on('click', '#tab_discharge_content .js-toggle-ipd-status', function() {
|
||||
var currentStatus = Number($(this).data('current') || 0);
|
||||
var newStatus = currentStatus === 0 ? 1 : 0;
|
||||
var action = newStatus === 1 ? 'lock bills (set discharged)' : 'unlock bills (set active)';
|
||||
|
||||
if (!confirm('Are you sure you want to ' + action + '?\n\nThis will ' + (newStatus === 1 ? 'PREVENT' : 'ALLOW') + ' editing of IPD charges and medical bills.')) {
|
||||
return;
|
||||
}
|
||||
|
||||
post('<?= site_url('billing/ipd/panel/' . $ipdId . '/discharge/toggle-status') ?>', {
|
||||
ipd_status: newStatus
|
||||
}).done(function(response) {
|
||||
if (response && Number(response.update || 0) === 1) {
|
||||
refreshDischargeTab(response);
|
||||
if (typeof window.notify === 'function') {
|
||||
window.notify('success', 'IPD Status', response.message || 'Status updated successfully');
|
||||
}
|
||||
// Refresh entire panel to update other tabs
|
||||
setTimeout(function() {
|
||||
if (typeof window.loadIpdPanel === 'function') {
|
||||
window.loadIpdPanel(ipdId);
|
||||
}
|
||||
}, 500);
|
||||
} else {
|
||||
alert(response.message || 'Unable to update IPD status');
|
||||
}
|
||||
}).fail(function(xhr) {
|
||||
var msg = (xhr.responseJSON && xhr.responseJSON.message) ? xhr.responseJSON.message : 'Unable to update IPD status';
|
||||
alert(msg);
|
||||
});
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
<?php else : ?>
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user