diff --git a/app/Config/AuthGroups.php b/app/Config/AuthGroups.php index fafa0ca..8dc4703 100644 --- a/app/Config/AuthGroups.php +++ b/app/Config/AuthGroups.php @@ -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', diff --git a/app/Config/Routes.php b/app/Config/Routes.php index dada871..52ea8a2 100644 --- a/app/Config/Routes.php +++ b/app/Config/Routes.php @@ -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'); diff --git a/app/Controllers/Billing/Ipd.php b/app/Controllers/Billing/Ipd.php index b7d5294..2082480 100644 --- a/app/Controllers/Billing/Ipd.php +++ b/app/Controllers/Billing/Ipd.php @@ -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', diff --git a/app/Controllers/IpdPatient.php b/app/Controllers/IpdPatient.php index 06967b5..1173d39 100644 --- a/app/Controllers/IpdPatient.php +++ b/app/Controllers/IpdPatient.php @@ -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', diff --git a/app/Controllers/Ipd_discharge.php b/app/Controllers/Ipd_discharge.php index 81c8427..c51ee0c 100644 --- a/app/Controllers/Ipd_discharge.php +++ b/app/Controllers/Ipd_discharge.php @@ -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', diff --git a/app/Database/Migrations/2026-08-10-000005_AddIpdNursingAndDischargePermissions.php b/app/Database/Migrations/2026-08-10-000005_AddIpdNursingAndDischargePermissions.php new file mode 100644 index 0000000..15ed0e0 --- /dev/null +++ b/app/Database/Migrations/2026-08-10-000005_AddIpdNursingAndDischargePermissions.php @@ -0,0 +1,130 @@ +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; + } +} \ No newline at end of file diff --git a/app/Views/partials/sidebar.php b/app/Views/partials/sidebar.php index 704ace2..60555b9 100644 --- a/app/Views/partials/sidebar.php +++ b/app/Views/partials/sidebar.php @@ -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')) { - +