feat: add IPD nursing and discharge permissions

This commit is contained in:
DevSoftTech Server 2026-08-10 00:55:18 +05:30
parent bd9b1771a9
commit 711b093487
7 changed files with 240 additions and 49 deletions

View File

@ -57,6 +57,10 @@ class AuthGroups extends ShieldAuthGroups
'title' => 'Doctor',
'description' => 'Clinical doctor access to OPD work, diagnosis reports, and immunization records.',
],
'nurse' => [
'title' => 'Nurse',
'description' => 'In-patient nursing records, bedside care, bed transfers, and nursing charges.',
],
'pharmacy_admin' => [
'title' => 'Pharmacy Admin',
'description' => 'Full pharmacy controls including old bill edits and discount overrides.',
@ -209,6 +213,13 @@ class AuthGroups extends ShieldAuthGroups
'billing.items.manage' => 'Can manage billing item masters',
'billing.packages.view' => 'Can view billing package masters',
'billing.packages.manage' => 'Can manage billing package masters',
'ipd_nursing.view' => 'Can view the IPD patient list, nursing workspace, and nursing charts',
'ipd_nursing.record.manage' => 'Can create and update nursing records, admission history, and scanned nursing entries',
'ipd_nursing.bed.transfer' => 'Can transfer admitted patients between beds',
'ipd_nursing.charge.manage' => 'Can add, update, and remove nursing and bedside charges',
'ipd_discharge.view' => 'Can search, preview, and print IPD discharge summaries',
'ipd_discharge.manage' => 'Can create and update IPD discharge summaries and personal section templates',
'ipd_discharge.master.manage' => 'Can manage shared discharge surgery, course, dietary, and ICD masters',
];
/**
@ -242,6 +253,8 @@ class AuthGroups extends ShieldAuthGroups
'template.*',
'hospital_stock.*',
'abdm.*',
'ipd_nursing.*',
'ipd_discharge.*',
],
'admin' => [
'admin.access',
@ -268,6 +281,8 @@ class AuthGroups extends ShieldAuthGroups
'template.*',
'hospital_stock.*',
'abdm.*',
'ipd_nursing.*',
'ipd_discharge.*',
],
'developer' => [
'admin.access',
@ -293,6 +308,8 @@ class AuthGroups extends ShieldAuthGroups
'template.*',
'hospital_stock.*',
'abdm.*',
'ipd_nursing.*',
'ipd_discharge.*',
],
'doctor' => [
'opd.doctor-panel.access',
@ -301,6 +318,16 @@ class AuthGroups extends ShieldAuthGroups
'doctor_work.immunization.record-manage',
'diagnosis.access',
'diagnosis.report.view',
'ipd_nursing.view',
'ipd_discharge.view',
'ipd_discharge.manage',
],
'nurse' => [
'ipd_nursing.view',
'ipd_nursing.record.manage',
'ipd_nursing.bed.transfer',
'ipd_nursing.charge.manage',
'ipd_discharge.view',
],
'pharmacy_admin' => [
'pharmacy.*',
@ -343,6 +370,7 @@ class AuthGroups extends ShieldAuthGroups
'billing.payment_request.manage',
'billing.refund.view',
'billing.refund.manage',
'ipd_discharge.view',
],
'accounts_officer' => [
'finance.workflow.view',

View File

@ -389,36 +389,36 @@ $routes->get('ipdNew/show_ipd_form/(:num)', 'Billing\\Ipd::showIpdForm/$1/1');
$routes->get('ipdNew/show_ipd_form/(:num)/(:num)', 'Billing\\Ipd::showIpdForm/$1/$2');
// Legacy compatibility: old discharge summary links should open current discharge tab.
$routes->get('Ipd_discharge/search_patient', 'Ipd_discharge::search_patient');
$routes->get('Ipd_discharge/search_patient_ajax', 'Ipd_discharge::search_patient_ajax');
$routes->get('Ipd_discharge/debug_ipd_fields/(:num)', 'Ipd_discharge::debug_ipd_fields/$1');
$routes->get('Ipd_discharge/debug_discharge_html/(:num)', 'Ipd_discharge::debug_discharge_html/$1');
$routes->get('Ipd_discharge/placeholder_preview', 'Ipd_discharge::placeholder_preview');
$routes->get('Ipd_discharge/placeholder_preview/(:num)', 'Ipd_discharge::placeholder_preview/$1');
$routes->match(['GET', 'POST'], 'Ipd_discharge/ipd_select/(:num)', 'Ipd_discharge::ipd_select/$1');
$routes->match(['GET', 'POST'], 'Ipd_discharge/ipd_select/(:num)/(:num)', 'Ipd_discharge::ipd_select/$1/$2');
$routes->get('Ipd_discharge/section_past_data', 'Ipd_discharge::section_past_data');
$routes->get('Ipd_discharge/section_template_list', 'Ipd_discharge::section_template_list');
$routes->post('Ipd_discharge/section_template_save', 'Ipd_discharge::section_template_save');
$routes->post('Ipd_discharge/section_template_remove', 'Ipd_discharge::section_template_remove');
$routes->get('Ipd_discharge/surgery_master_lookup', 'Ipd_discharge::surgery_master_lookup');
$routes->get('Ipd_discharge/surgery_master_list', 'Ipd_discharge::surgery_master_list');
$routes->post('Ipd_discharge/surgery_master_save', 'Ipd_discharge::surgery_master_save');
$routes->post('Ipd_discharge/surgery_master_delete', 'Ipd_discharge::surgery_master_delete');
$routes->get('Ipd_discharge/course_master_lookup', 'Ipd_discharge::course_master_lookup');
$routes->get('Ipd_discharge/course_master_list', 'Ipd_discharge::course_master_list');
$routes->post('Ipd_discharge/course_master_save', 'Ipd_discharge::course_master_save');
$routes->post('Ipd_discharge/course_master_delete', 'Ipd_discharge::course_master_delete');
$routes->get('Ipd_discharge/diagnosis_icd_lookup', 'Ipd_discharge::diagnosis_icd_lookup');
$routes->post('Ipd_discharge/diagnosis_icd_seed_starter', 'Ipd_discharge::diagnosis_icd_seed_starter');
$routes->post('Ipd_discharge/update_complaint_field', 'Ipd_discharge::update_complaint_field');
$routes->get('Ipd_discharge/dietary_master_list', 'Ipd_discharge::dietary_master_list');
$routes->post('Ipd_discharge/dietary_master_save', 'Ipd_discharge::dietary_master_save');
$routes->post('Ipd_discharge/dietary_master_delete', 'Ipd_discharge::dietary_master_delete');
$routes->match(['GET', 'POST'], 'Ipd_discharge/preview_discharge_report/(:num)', 'Ipd_discharge::preview_discharge_report/$1');
$routes->get('Ipd_discharge/show_discharge/(:num)', 'Ipd_discharge::show_discharge/$1');
$routes->get('Ipd_discharge/show_discharge/(:num)/(:num)', 'Ipd_discharge::show_discharge/$1/$2');
$routes->get('Ipd_discharge/show_file3/(:num)', 'Ipd_discharge::show_file3/$1');
$routes->get('Ipd_discharge/search_patient', 'Ipd_discharge::search_patient', ['filter' => 'permission:ipd_discharge.view,ipd_discharge.manage']);
$routes->get('Ipd_discharge/search_patient_ajax', 'Ipd_discharge::search_patient_ajax', ['filter' => 'permission:ipd_discharge.view,ipd_discharge.manage']);
$routes->get('Ipd_discharge/debug_ipd_fields/(:num)', 'Ipd_discharge::debug_ipd_fields/$1', ['filter' => 'permission:admin.access,admin.settings']);
$routes->get('Ipd_discharge/debug_discharge_html/(:num)', 'Ipd_discharge::debug_discharge_html/$1', ['filter' => 'permission:admin.access,admin.settings']);
$routes->get('Ipd_discharge/placeholder_preview', 'Ipd_discharge::placeholder_preview', ['filter' => 'permission:ipd_discharge.view,ipd_discharge.manage']);
$routes->get('Ipd_discharge/placeholder_preview/(:num)', 'Ipd_discharge::placeholder_preview/$1', ['filter' => 'permission:ipd_discharge.view,ipd_discharge.manage']);
$routes->match(['GET', 'POST'], 'Ipd_discharge/ipd_select/(:num)', 'Ipd_discharge::ipd_select/$1', ['filter' => 'permission:ipd_discharge.manage']);
$routes->match(['GET', 'POST'], 'Ipd_discharge/ipd_select/(:num)/(:num)', 'Ipd_discharge::ipd_select/$1/$2', ['filter' => 'permission:ipd_discharge.manage']);
$routes->get('Ipd_discharge/section_past_data', 'Ipd_discharge::section_past_data', ['filter' => 'permission:ipd_discharge.manage']);
$routes->get('Ipd_discharge/section_template_list', 'Ipd_discharge::section_template_list', ['filter' => 'permission:ipd_discharge.manage']);
$routes->post('Ipd_discharge/section_template_save', 'Ipd_discharge::section_template_save', ['filter' => 'permission:ipd_discharge.manage']);
$routes->post('Ipd_discharge/section_template_remove', 'Ipd_discharge::section_template_remove', ['filter' => 'permission:ipd_discharge.manage']);
$routes->get('Ipd_discharge/surgery_master_lookup', 'Ipd_discharge::surgery_master_lookup', ['filter' => 'permission:ipd_discharge.manage,ipd_discharge.master.manage']);
$routes->get('Ipd_discharge/surgery_master_list', 'Ipd_discharge::surgery_master_list', ['filter' => 'permission:ipd_discharge.manage,ipd_discharge.master.manage']);
$routes->post('Ipd_discharge/surgery_master_save', 'Ipd_discharge::surgery_master_save', ['filter' => 'permission:ipd_discharge.master.manage']);
$routes->post('Ipd_discharge/surgery_master_delete', 'Ipd_discharge::surgery_master_delete', ['filter' => 'permission:ipd_discharge.master.manage']);
$routes->get('Ipd_discharge/course_master_lookup', 'Ipd_discharge::course_master_lookup', ['filter' => 'permission:ipd_discharge.manage,ipd_discharge.master.manage']);
$routes->get('Ipd_discharge/course_master_list', 'Ipd_discharge::course_master_list', ['filter' => 'permission:ipd_discharge.manage,ipd_discharge.master.manage']);
$routes->post('Ipd_discharge/course_master_save', 'Ipd_discharge::course_master_save', ['filter' => 'permission:ipd_discharge.master.manage']);
$routes->post('Ipd_discharge/course_master_delete', 'Ipd_discharge::course_master_delete', ['filter' => 'permission:ipd_discharge.master.manage']);
$routes->get('Ipd_discharge/diagnosis_icd_lookup', 'Ipd_discharge::diagnosis_icd_lookup', ['filter' => 'permission:ipd_discharge.manage,ipd_discharge.master.manage']);
$routes->post('Ipd_discharge/diagnosis_icd_seed_starter', 'Ipd_discharge::diagnosis_icd_seed_starter', ['filter' => 'permission:ipd_discharge.master.manage']);
$routes->post('Ipd_discharge/update_complaint_field', 'Ipd_discharge::update_complaint_field', ['filter' => 'permission:ipd_discharge.manage']);
$routes->get('Ipd_discharge/dietary_master_list', 'Ipd_discharge::dietary_master_list', ['filter' => 'permission:ipd_discharge.manage,ipd_discharge.master.manage']);
$routes->post('Ipd_discharge/dietary_master_save', 'Ipd_discharge::dietary_master_save', ['filter' => 'permission:ipd_discharge.master.manage']);
$routes->post('Ipd_discharge/dietary_master_delete', 'Ipd_discharge::dietary_master_delete', ['filter' => 'permission:ipd_discharge.master.manage']);
$routes->match(['GET', 'POST'], 'Ipd_discharge/preview_discharge_report/(:num)', 'Ipd_discharge::preview_discharge_report/$1', ['filter' => 'permission:ipd_discharge.view,ipd_discharge.manage']);
$routes->get('Ipd_discharge/show_discharge/(:num)', 'Ipd_discharge::show_discharge/$1', ['filter' => 'permission:ipd_discharge.view,ipd_discharge.manage']);
$routes->get('Ipd_discharge/show_discharge/(:num)/(:num)', 'Ipd_discharge::show_discharge/$1/$2', ['filter' => 'permission:ipd_discharge.view,ipd_discharge.manage']);
$routes->get('Ipd_discharge/show_file3/(:num)', 'Ipd_discharge::show_file3/$1', ['filter' => 'permission:ipd_discharge.view,ipd_discharge.manage']);
// Legacy CI3 compatibility links for IPD bill print modes.
$routes->get('ipdNew/ipd_complete_invoice/(:num)', 'Billing\\Ipd::billPrint/$1/1');
@ -458,10 +458,10 @@ $routes->group('billing', function($routes) {
$routes->post('ipd/charge/add/(:num)', 'Billing\\Ipd::addIpdCharge/$1');
$routes->post('ipd/charge/update/(:num)', 'Billing\\Ipd::updateIpdCharge/$1');
$routes->post('ipd/charge/delete/(:num)', 'Billing\\Ipd::deleteIpdCharge/$1');
$routes->post('ipd/bedside-charge/add/(:num)', 'Billing\\Ipd::addBedsideCharge/$1');
$routes->post('ipd/doctor-visit/add/(:num)', 'Billing\\Ipd::addDoctorVisitCharge/$1');
$routes->post('ipd/nursing-charge/update/(:num)/(:num)', 'Billing\\Ipd::updateNursingCharge/$1/$2');
$routes->post('ipd/nursing-charge/delete/(:num)/(:num)', 'Billing\\Ipd::deleteNursingCharge/$1/$2');
$routes->post('ipd/bedside-charge/add/(:num)', 'Billing\\Ipd::addBedsideCharge/$1', ['filter' => 'permission:ipd_nursing.charge.manage']);
$routes->post('ipd/doctor-visit/add/(:num)', 'Billing\\Ipd::addDoctorVisitCharge/$1', ['filter' => 'permission:ipd_nursing.charge.manage']);
$routes->post('ipd/nursing-charge/update/(:num)/(:num)', 'Billing\\Ipd::updateNursingCharge/$1/$2', ['filter' => 'permission:ipd_nursing.charge.manage']);
$routes->post('ipd/nursing-charge/delete/(:num)/(:num)', 'Billing\\Ipd::deleteNursingCharge/$1/$2', ['filter' => 'permission:ipd_nursing.charge.manage']);
$routes->post('ipd/charge/package/(:num)', 'Billing\\Ipd::updateIpdChargePackage/$1');
$routes->post('ipd/package/add/(:num)', 'Billing\\Ipd::addIpdPackage/$1');
$routes->get('ipd/medical-bill/(:num)/(:num)', 'Billing\\Ipd::medicalBillDetails/$1/$2');
@ -564,21 +564,21 @@ $routes->post('patient/abdm_content_request_custom/(:num)', 'Patient::abdm_conte
$routes->post('charges/update-discount', 'Billing\\Charges::updateDiscount');
});
$routes->get('ipd/patient', 'IpdPatient::index');
$routes->get('ipd/patient/workspace/(:num)', 'IpdPatient::workspace/$1');
$routes->post('ipd/patient/nursing/save/(:num)', 'IpdPatient::saveNursingEntry/$1');
$routes->post('ipd/patient/history/save/(:num)', 'IpdPatient::saveAdmissionHistory/$1');
$routes->post('ipd/patient/nursing/scan/(:num)', 'IpdPatient::scanNursingPaper/$1');
$routes->post('ipd/patient/nursing/scan-save/(:num)', 'IpdPatient::saveScannedNursingEntries/$1');
$routes->get('ipd/patient/nursing/print/(:num)', 'IpdPatient::nursingChartPrint/$1');
$routes->post('ipd/patient/bed/transfer/(:num)', 'IpdPatient::bedTransfer/$1');
$routes->get('ipd/patient', 'IpdPatient::index', ['filter' => 'permission:ipd_nursing.view']);
$routes->get('ipd/patient/workspace/(:num)', 'IpdPatient::workspace/$1', ['filter' => 'permission:ipd_nursing.view']);
$routes->post('ipd/patient/nursing/save/(:num)', 'IpdPatient::saveNursingEntry/$1', ['filter' => 'permission:ipd_nursing.record.manage']);
$routes->post('ipd/patient/history/save/(:num)', 'IpdPatient::saveAdmissionHistory/$1', ['filter' => 'permission:ipd_nursing.record.manage']);
$routes->post('ipd/patient/nursing/scan/(:num)', 'IpdPatient::scanNursingPaper/$1', ['filter' => 'permission:ipd_nursing.record.manage']);
$routes->post('ipd/patient/nursing/scan-save/(:num)', 'IpdPatient::saveScannedNursingEntries/$1', ['filter' => 'permission:ipd_nursing.record.manage']);
$routes->get('ipd/patient/nursing/print/(:num)', 'IpdPatient::nursingChartPrint/$1', ['filter' => 'permission:ipd_nursing.view']);
$routes->post('ipd/patient/bed/transfer/(:num)', 'IpdPatient::bedTransfer/$1', ['filter' => 'permission:ipd_nursing.bed.transfer']);
$routes->get('nursing-bedside-items', 'Setting\\NursingBedsideItems::index');
$routes->get('nursing-bedside-items/(:num)', 'Setting\\NursingBedsideItems::get/$1');
$routes->post('nursing-bedside-items/save', 'Setting\\NursingBedsideItems::save');
$routes->get('nursing-bedside-items/insurance/(:num)', 'Setting\\NursingBedsideItems::insuranceList/$1');
$routes->post('nursing-bedside-items/insurance/add', 'Setting\\NursingBedsideItems::insuranceAdd');
$routes->post('nursing-bedside-items/insurance/remove', 'Setting\\NursingBedsideItems::insuranceRemove');
$routes->get('nursing-bedside-items', 'Setting\\NursingBedsideItems::index', ['filter' => 'permission:ipd_nursing.charge.manage']);
$routes->get('nursing-bedside-items/(:num)', 'Setting\\NursingBedsideItems::get/$1', ['filter' => 'permission:ipd_nursing.charge.manage']);
$routes->post('nursing-bedside-items/save', 'Setting\\NursingBedsideItems::save', ['filter' => 'permission:ipd_nursing.charge.manage']);
$routes->get('nursing-bedside-items/insurance/(:num)', 'Setting\\NursingBedsideItems::insuranceList/$1', ['filter' => 'permission:ipd_nursing.charge.manage']);
$routes->post('nursing-bedside-items/insurance/add', 'Setting\\NursingBedsideItems::insuranceAdd', ['filter' => 'permission:ipd_nursing.charge.manage']);
$routes->post('nursing-bedside-items/insurance/remove', 'Setting\\NursingBedsideItems::insuranceRemove', ['filter' => 'permission:ipd_nursing.charge.manage']);
$routes->get('Opd/addopd/(:num)', 'Opd::addopd/$1');
$routes->get('Opd/addopd/(:num)/(:num)', 'Opd::addopd/$1/$2');

View File

@ -1207,6 +1207,7 @@ class Ipd extends BaseController
public function addBedsideCharge(int $ipdId)
{
$permission = $this->requireAnyPermission([
'ipd_nursing.charge.manage',
'billing.access',
'billing.ipd.invoice',
'billing.ipd.current-admission',
@ -1323,6 +1324,7 @@ class Ipd extends BaseController
public function addDoctorVisitCharge(int $ipdId)
{
$permission = $this->requireAnyPermission([
'ipd_nursing.charge.manage',
'billing.access',
'billing.ipd.invoice',
'billing.ipd.current-admission',
@ -1467,6 +1469,7 @@ class Ipd extends BaseController
public function updateNursingCharge(int $ipdId, int $chargeId)
{
$permission = $this->requireAnyPermission([
'ipd_nursing.charge.manage',
'billing.access',
'billing.ipd.invoice',
'billing.ipd.current-admission',
@ -1554,6 +1557,7 @@ class Ipd extends BaseController
public function deleteNursingCharge(int $ipdId, int $chargeId)
{
$permission = $this->requireAnyPermission([
'ipd_nursing.charge.manage',
'billing.access',
'billing.ipd.invoice',
'billing.ipd.current-admission',

View File

@ -35,6 +35,7 @@ class IpdPatient extends BaseController
public function index()
{
$permission = $this->requireAnyPermission([
'ipd_nursing.view',
'billing.access',
'billing.ipd.current-admission',
'billing.ipd.invoice',
@ -51,6 +52,7 @@ class IpdPatient extends BaseController
public function workspace(int $ipdId)
{
$permission = $this->requireAnyPermission([
'ipd_nursing.view',
'billing.access',
'billing.ipd.current-admission',
'billing.ipd.invoice',
@ -128,6 +130,7 @@ class IpdPatient extends BaseController
public function saveAdmissionHistory(int $ipdId)
{
$permission = $this->requireAnyPermission([
'ipd_nursing.record.manage',
'billing.access',
'billing.ipd.current-admission',
'billing.ipd.invoice',
@ -238,6 +241,7 @@ class IpdPatient extends BaseController
public function saveNursingEntry(int $ipdId)
{
$permission = $this->requireAnyPermission([
'ipd_nursing.record.manage',
'billing.access',
'billing.ipd.current-admission',
'billing.ipd.invoice',
@ -337,6 +341,7 @@ class IpdPatient extends BaseController
public function scanNursingPaper(int $ipdId)
{
$permission = $this->requireAnyPermission([
'ipd_nursing.record.manage',
'billing.access',
'billing.ipd.current-admission',
'billing.ipd.invoice',
@ -417,6 +422,7 @@ class IpdPatient extends BaseController
public function saveScannedNursingEntries(int $ipdId)
{
$permission = $this->requireAnyPermission([
'ipd_nursing.record.manage',
'billing.access',
'billing.ipd.current-admission',
'billing.ipd.invoice',
@ -560,6 +566,7 @@ class IpdPatient extends BaseController
public function nursingChartPrint(int $ipdId)
{
$permission = $this->requireAnyPermission([
'ipd_nursing.view',
'billing.access',
'billing.ipd.current-admission',
'billing.ipd.invoice',
@ -850,6 +857,7 @@ class IpdPatient extends BaseController
public function bedTransfer(int $ipdId)
{
$permission = $this->requireAnyPermission([
'ipd_nursing.bed.transfer',
'billing.access',
'billing.ipd.current-admission',
'billing.ipd.invoice',

View File

@ -5272,6 +5272,7 @@ class Ipd_discharge extends BaseController
public function search_patient()
{
$permission = $this->requireAnyPermission([
'ipd_discharge.view',
'billing.access',
'billing.ipd.invoice',
'billing.ipd.current-admission',
@ -5286,6 +5287,7 @@ class Ipd_discharge extends BaseController
public function search_patient_ajax()
{
$permission = $this->requireAnyPermission([
'ipd_discharge.view',
'billing.access',
'billing.ipd.invoice',
'billing.ipd.current-admission',
@ -5472,6 +5474,7 @@ class Ipd_discharge extends BaseController
public function placeholder_preview(int $ipdId = 0)
{
$permission = $this->requireAnyPermission([
'ipd_discharge.view',
'billing.access',
'billing.ipd.invoice',
'billing.ipd.current-admission',
@ -5634,6 +5637,7 @@ class Ipd_discharge extends BaseController
public function ipd_select(int $ipdId, int $reCreate = 0)
{
$permission = $this->requireAnyPermission([
'ipd_discharge.manage',
'billing.access',
'billing.ipd.invoice',
'billing.ipd.current-admission',
@ -7040,6 +7044,7 @@ class Ipd_discharge extends BaseController
public function preview_discharge_report(int $ipdId)
{
$permission = $this->requireAnyPermission([
'ipd_discharge.view',
'billing.access',
'billing.ipd.invoice',
'billing.ipd.current-admission',
@ -7098,6 +7103,7 @@ class Ipd_discharge extends BaseController
public function show_discharge(int $ipdId, int $printType = 1)
{
$permission = $this->requireAnyPermission([
'ipd_discharge.view',
'billing.access',
'billing.ipd.invoice',
'billing.ipd.current-admission',

View File

@ -0,0 +1,130 @@
<?php
namespace App\Database\Migrations;
use App\Libraries\RoleRegistry;
use CodeIgniter\Database\Migration;
class AddIpdNursingAndDischargePermissions extends Migration
{
private const NEW_PERMISSIONS = [
'ipd_nursing.view',
'ipd_nursing.record.manage',
'ipd_nursing.bed.transfer',
'ipd_nursing.charge.manage',
'ipd_discharge.view',
'ipd_discharge.manage',
'ipd_discharge.master.manage',
];
public function up()
{
if (! $this->tableExists('auth_roles') || ! $this->tableExists('auth_role_permissions')) {
return;
}
$now = date('Y-m-d H:i:s');
$nurse = $this->db->table('auth_roles')->where('alias', 'nurse')->get(1)->getRowArray();
if ($nurse === null) {
$this->db->table('auth_roles')->insert([
'alias' => 'nurse',
'title' => 'Nurse',
'description' => 'In-patient nursing records, bedside care, bed transfers, and nursing charges.',
'is_active' => 1,
'is_builtin' => 1,
'created_at' => $now,
'updated_at' => $now,
]);
}
$roleGrants = [
'superadmin' => self::NEW_PERMISSIONS,
'admin' => self::NEW_PERMISSIONS,
'developer' => self::NEW_PERMISSIONS,
'nurse' => [
'ipd_nursing.view',
'ipd_nursing.record.manage',
'ipd_nursing.bed.transfer',
'ipd_nursing.charge.manage',
'ipd_discharge.view',
],
'doctor' => [
'ipd_nursing.view',
'ipd_discharge.view',
'ipd_discharge.manage',
],
'billing_cashier' => [
'ipd_discharge.view',
],
];
foreach ($roleGrants as $alias => $permissions) {
$role = $this->db->table('auth_roles')->select('id')->where('alias', $alias)->get(1)->getRowArray();
if ($role === null) {
continue;
}
foreach ($permissions as $permission) {
$this->insertRolePermission((int) $role['id'], $permission, $now);
}
}
if ($this->tableExists('auth_permissions_users')) {
$managerIds = array_column(
$this->db->table('auth_permissions_users')->select('user_id')->where('permission', 'users.manage-admins')->get()->getResultArray(),
'user_id'
);
foreach ($managerIds as $userId) {
foreach (self::NEW_PERMISSIONS as $permission) {
$exists = $this->db->table('auth_permissions_users')
->where('user_id', (int) $userId)
->where('permission', $permission)
->countAllResults();
if ($exists === 0) {
$this->db->table('auth_permissions_users')->insert([
'user_id' => (int) $userId,
'permission' => $permission,
'created_at' => $now,
]);
}
}
}
}
(new RoleRegistry($this->db))->publish();
}
public function down()
{
if ($this->tableExists('auth_permissions_users')) {
$this->db->table('auth_permissions_users')->whereIn('permission', self::NEW_PERMISSIONS)->delete();
}
if ($this->tableExists('auth_role_permissions')) {
$this->db->table('auth_role_permissions')->whereIn('permission', self::NEW_PERMISSIONS)->delete();
}
if ($this->tableExists('auth_roles')) {
$this->db->table('auth_roles')->where('alias', 'nurse')->where('is_builtin', 1)->delete();
(new RoleRegistry($this->db))->publish();
}
}
private function insertRolePermission(int $roleId, string $permission, string $createdAt): void
{
$exists = $this->db->table('auth_role_permissions')
->where('role_id', $roleId)
->where('permission', $permission)
->countAllResults();
if ($exists === 0) {
$this->db->table('auth_role_permissions')->insert([
'role_id' => $roleId,
'permission' => $permission,
'created_at' => $createdAt,
]);
}
}
private function tableExists(string $table): bool
{
return $this->db->query('SHOW TABLES LIKE ' . $this->db->escape($table))->getRowArray() !== null;
}
}

View File

@ -23,6 +23,17 @@ $canIpdBilling = $user && method_exists($user, 'can')
|| $user->can('billing.access'))
: false;
$canIpdNursing = $user && method_exists($user, 'can')
? ($user->can('ipd_nursing.view') || $user->can('ipd_nursing.*'))
: false;
$canIpdDischarge = $user && method_exists($user, 'can')
? ($user->can('ipd_discharge.view') || $user->can('ipd_discharge.manage') || $user->can('ipd_discharge.*'))
: false;
if ($user && method_exists($user, 'inGroup') && $user->inGroup('superadmin', 'admin', 'developer')) {
$canIpdNursing = true;
$canIpdDischarge = true;
}
$canBilling = false;
if ($user && method_exists($user, 'can')) {
$canBilling = $user->can('billing.access')
@ -307,20 +318,24 @@ if (! $canChargesSettings && $user && method_exists($user, 'inGroup')) {
</ul>
</li>
<?php } ?>
<?php if ($canIpdBilling) { ?>
<?php if ($canIpdNursing || $canIpdDischarge) { ?>
<li class="nav-heading">In-Patient & Nursing Care</li>
<?php if ($canIpdNursing) { ?>
<li class="nav-item">
<a class="nav-link collapsed" href="javascript:load_form('<?= base_url('/ipd/patient') ?>','IPD Patient List')">
<i class="bi bi-person-vcard"></i>
<span>IPD Patient List</span>
</a>
</li>
<?php } ?>
<?php if ($canIpdDischarge) { ?>
<li class="nav-item">
<a class="nav-link collapsed" href="javascript:load_form('<?= base_url('Ipd_discharge/search_patient') ?>','Discharge Management')">
<i class="bi bi-file-medical"></i>
<span>Discharge</span>
</a>
</li>
<?php } ?>
<?php } ?>
<?php if ($canDoctorWork) { ?>