diff --git a/app/Config/Routes.php b/app/Config/Routes.php index 54f3e96..9558ec9 100644 --- a/app/Config/Routes.php +++ b/app/Config/Routes.php @@ -1289,6 +1289,9 @@ $routes->group('setting', static function($routes) { $routes->post('admin/abdm-gateway/test', 'Setting\\AbdmGatewaySettings::testConnection', ['filter' => $settingsAdminFilter]); $routes->get('admin/abdm-report-doctors', 'Setting\\AbdmReportDoctorSettings::index', ['filter' => $settingsAdminFilter]); $routes->post('admin/abdm-report-doctors/save', 'Setting\\AbdmReportDoctorSettings::save', ['filter' => $settingsAdminFilter]); + $routes->get('admin/ipd-examination-fields', 'Setting\IpdExaminationFields::index', ['filter' => 'permission:ipd_discharge.master.manage']); + $routes->post('admin/ipd-examination-fields/save', 'Setting\IpdExaminationFields::save', ['filter' => ['permission:ipd_discharge.master.manage', 'csrf']]); + $routes->post('admin/ipd-examination-fields/toggle/(:num)', 'Setting\IpdExaminationFields::toggle/$1', ['filter' => ['permission:ipd_discharge.master.manage', 'csrf']]); $routes->get('admin/hospital-profile', 'Setting\\HospitalProfile::index'); $routes->get('admin/system-ops', 'SystemOps::index', ['filter' => $settingsAdminFilter]); $routes->get('admin/system-ops/panel', 'SystemOps::panel', ['filter' => $settingsAdminFilter]); diff --git a/app/Controllers/Ipd_discharge.php b/app/Controllers/Ipd_discharge.php index 496032b..d73c252 100644 --- a/app/Controllers/Ipd_discharge.php +++ b/app/Controllers/Ipd_discharge.php @@ -4169,11 +4169,18 @@ class Ipd_discharge extends BaseController if ($this->tableHasColumns('ipd_discharge_general_exam_col', ['id', 'col_description'])) { $generalBuilder = $this->db->table('ipd_discharge_general_exam_col') ->select('id,col_description,col_name,col_pre_value,cat_group') + ->orderBy($this->db->fieldExists('display_order', 'ipd_discharge_general_exam_col') ? 'display_order' : 'id', 'ASC') ->orderBy('id', 'ASC'); if ($this->db->fieldExists('col_unit', 'ipd_discharge_general_exam_col')) { $generalBuilder->select('col_unit'); } + if ($this->db->fieldExists('col_type', 'ipd_discharge_general_exam_col')) { + $generalBuilder->select('col_type'); + } + if ($this->db->fieldExists('is_active', 'ipd_discharge_general_exam_col')) { + $generalBuilder->where('is_active', 1); + } $generalCols = $generalBuilder->get()->getResultArray(); @@ -4199,6 +4206,8 @@ class Ipd_discharge extends BaseController 'label' => (string) ($row['col_description'] ?? $row['col_name'] ?? ('Exam ' . $colId)), 'value' => (string) ($rdataMap[$colId] ?? (string) ($row['col_pre_value'] ?? '')), 'unit' => trim((string) ($row['col_unit'] ?? '')), + 'type' => (int) ($row['col_type'] ?? 0), + 'options' => (string) ($row['col_pre_value'] ?? ''), ]; $generalAll[] = $item; @@ -6676,11 +6685,13 @@ class Ipd_discharge extends BaseController // Examination on Admission (General Examination values). if ($this->tableHasColumns('ipd_discharge_general_exam_col', ['id', 'col_name']) && $this->tableHasColumns('ipd_discharge_1_b', ['ipd_d_id', 'col_id', 'short_head', 'rdata'])) { - $generalCols = $this->db->table('ipd_discharge_general_exam_col') + $generalBuilder = $this->db->table('ipd_discharge_general_exam_col') ->select('id,col_name') - ->orderBy('id', 'ASC') - ->get() - ->getResultArray(); + ->orderBy('id', 'ASC'); + if ($this->db->fieldExists('is_active', 'ipd_discharge_general_exam_col')) { + $generalBuilder->where('is_active', 1); + } + $generalCols = $generalBuilder->get()->getResultArray(); foreach ($generalCols as $col) { $colId = (int) ($col['id'] ?? 0); diff --git a/app/Controllers/Setting/IpdExaminationFields.php b/app/Controllers/Setting/IpdExaminationFields.php new file mode 100644 index 0000000..b16ef53 --- /dev/null +++ b/app/Controllers/Setting/IpdExaminationFields.php @@ -0,0 +1,81 @@ +ensureColumns(); + return view('Setting/Admin/ipd_examination_fields', [ + 'rows' => $this->db->table('ipd_discharge_general_exam_col')->orderBy('cat_group')->orderBy('display_order')->orderBy('id')->get()->getResultArray(), + ]); + } + + public function save() + { + $this->ensureColumns(); + $id = (int) ($this->request->getPost('id') ?? 0); + $code = strtoupper(trim((string) ($this->request->getPost('col_code') ?? ''))); + $name = trim((string) ($this->request->getPost('col_name') ?? '')); + $label = trim((string) ($this->request->getPost('col_description') ?? '')); + if ($code === '' || ! preg_match('/^[A-Z][A-Z0-9_]{1,49}$/', $code) || $name === '' || $label === '') { + return $this->reply(false, 'Code, field name, and label are required. Use letters, numbers, and underscore in code.'); + } + + $duplicate = $this->db->table('ipd_discharge_general_exam_col')->where('col_code', $code); + if ($id > 0) { + $duplicate->where('id !=', $id); + } + if ($duplicate->countAllResults() > 0) { + return $this->reply(false, 'Field code already exists.'); + } + + $data = [ + 'col_code' => $code, + 'col_name' => $name, + 'col_description' => $label, + 'col_unit' => trim((string) ($this->request->getPost('col_unit') ?? '')), + 'col_type' => max(0, min(4, (int) ($this->request->getPost('col_type') ?? 0))), + 'col_pre_value' => trim((string) ($this->request->getPost('col_pre_value') ?? '')), + 'cat_group' => (int) ($this->request->getPost('cat_group') ?? 1) === 2 ? 2 : 1, + 'is_active' => (int) ($this->request->getPost('is_active') ?? 0) === 1 ? 1 : 0, + 'display_order' => max(0, (int) ($this->request->getPost('display_order') ?? 0)), + ]; + $saved = $id > 0 + ? (bool) $this->db->table('ipd_discharge_general_exam_col')->where('id', $id)->update($data) + : (bool) $this->db->table('ipd_discharge_general_exam_col')->insert($data); + + return $this->reply($saved, $saved ? 'Examination field saved.' : 'Unable to save examination field.'); + } + + public function toggle(int $id) + { + $this->ensureColumns(); + $row = $this->db->table('ipd_discharge_general_exam_col')->select('id,is_active')->where('id', $id)->get()->getRowArray(); + if ($row === null) { + return $this->reply(false, 'Examination field not found.'); + } + $active = (int) ($row['is_active'] ?? 0) === 1 ? 0 : 1; + $saved = (bool) $this->db->table('ipd_discharge_general_exam_col')->where('id', $id)->update(['is_active' => $active]); + return $this->reply($saved, $saved ? ($active ? 'Field enabled.' : 'Field disabled.') : 'Unable to update field status.'); + } + + private function ensureColumns(): void + { + if (! $this->db->fieldExists('is_active', 'ipd_discharge_general_exam_col')) { + $this->db->query('ALTER TABLE ipd_discharge_general_exam_col ADD COLUMN is_active TINYINT(1) NOT NULL DEFAULT 1 AFTER cat_group'); + } + if (! $this->db->fieldExists('display_order', 'ipd_discharge_general_exam_col')) { + $this->db->query('ALTER TABLE ipd_discharge_general_exam_col ADD COLUMN display_order INT NOT NULL DEFAULT 0 AFTER is_active'); + $this->db->query('UPDATE ipd_discharge_general_exam_col SET display_order = id WHERE display_order = 0'); + } + } + + private function reply(bool $ok, string $message) + { + return $this->response->setJSON(['ok' => $ok ? 1 : 0, 'message' => $message, 'csrfName' => csrf_token(), 'csrfHash' => csrf_hash()]); + } +} \ No newline at end of file diff --git a/app/Database/Migrations/2026-08-24-000003_AddIpdGeneralExamFieldControls.php b/app/Database/Migrations/2026-08-24-000003_AddIpdGeneralExamFieldControls.php new file mode 100644 index 0000000..0e8095d --- /dev/null +++ b/app/Database/Migrations/2026-08-24-000003_AddIpdGeneralExamFieldControls.php @@ -0,0 +1,42 @@ +tableExists('ipd_discharge_general_exam_col')) { + return; + } + if (! $this->fieldExists('is_active', 'ipd_discharge_general_exam_col')) { + $this->db->query('ALTER TABLE ipd_discharge_general_exam_col ADD COLUMN is_active TINYINT(1) NOT NULL DEFAULT 1 AFTER cat_group'); + } + if (! $this->fieldExists('display_order', 'ipd_discharge_general_exam_col')) { + $this->db->query('ALTER TABLE ipd_discharge_general_exam_col ADD COLUMN display_order INT NOT NULL DEFAULT 0 AFTER is_active'); + $this->db->query('UPDATE ipd_discharge_general_exam_col SET display_order = id WHERE display_order = 0'); + } + } + + public function down() + { + if ($this->tableExists('ipd_discharge_general_exam_col') && $this->fieldExists('display_order', 'ipd_discharge_general_exam_col')) { + $this->db->query('ALTER TABLE ipd_discharge_general_exam_col DROP COLUMN display_order'); + } + if ($this->tableExists('ipd_discharge_general_exam_col') && $this->fieldExists('is_active', 'ipd_discharge_general_exam_col')) { + $this->db->query('ALTER TABLE ipd_discharge_general_exam_col DROP COLUMN is_active'); + } + } + + private function tableExists(string $table): bool + { + return $this->db->query('SHOW TABLES LIKE ' . $this->db->escape($table))->getRowArray() !== null; + } + + private function fieldExists(string $field, string $table): bool + { + return $this->db->query('SHOW COLUMNS FROM `' . $table . '` LIKE ' . $this->db->escape($field))->getRowArray() !== null; + } +} \ No newline at end of file diff --git a/app/Views/Setting/Admin/index.php b/app/Views/Setting/Admin/index.php index 33689eb..a4cf7af 100644 --- a/app/Views/Setting/Admin/index.php +++ b/app/Views/Setting/Admin/index.php @@ -122,6 +122,12 @@ Bed Management +
+ + + IPD Examination Fields + +
diff --git a/app/Views/Setting/Admin/ipd_examination_fields.php b/app/Views/Setting/Admin/ipd_examination_fields.php new file mode 100644 index 0000000..187a1f7 --- /dev/null +++ b/app/Views/Setting/Admin/ipd_examination_fields.php @@ -0,0 +1,29 @@ + +
+
IPD Admission Examination Fields
Enabled fields appear in Discharge Management → Examination on Admission. Existing saved values are retained.
+
+
+
+
+
+
+
+
+
+
+
+
+
'>
OrderCodeLabelTypeGroupUnitStatus
+
+ \ No newline at end of file diff --git a/app/Views/billing/ipd/discharge_create.php b/app/Views/billing/ipd/discharge_create.php index 59171d2..5a20e95 100644 --- a/app/Views/billing/ipd/discharge_create.php +++ b/app/Views/billing/ipd/discharge_create.php @@ -819,7 +819,7 @@ $historyFields = [
- +
@@ -833,7 +833,7 @@ $historyFields = [
- +