feat(ipd): manage admission examination fields
Add an Admin CRUD master for IPD admission examination fields with enabled state, display order, field types, and select options.
This commit is contained in:
parent
40c68da430
commit
7ec5149ccf
|
|
@ -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]);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
81
app/Controllers/Setting/IpdExaminationFields.php
Normal file
81
app/Controllers/Setting/IpdExaminationFields.php
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
<?php
|
||||
|
||||
namespace App\Controllers\Setting;
|
||||
|
||||
use App\Controllers\BaseController;
|
||||
|
||||
class IpdExaminationFields extends BaseController
|
||||
{
|
||||
public function index()
|
||||
{
|
||||
$this->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()]);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
<?php
|
||||
|
||||
namespace App\Database\Migrations;
|
||||
|
||||
use CodeIgniter\Database\Migration;
|
||||
|
||||
class AddIpdGeneralExamFieldControls extends Migration
|
||||
{
|
||||
public function up()
|
||||
{
|
||||
if (! $this->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;
|
||||
}
|
||||
}
|
||||
|
|
@ -122,6 +122,12 @@
|
|||
<span>Bed Management</span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-6 col-md-2 col-lg-2">
|
||||
<a class="admin-tile" href="javascript:load_form_div('<?= base_url('setting/admin/ipd-examination-fields') ?>','maindiv','IPD Examination Fields');">
|
||||
<i class="bi bi-clipboard2-pulse"></i>
|
||||
<span>IPD Examination Fields</span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-6 col-md-2 col-lg-2">
|
||||
<a class="admin-tile" href="javascript:load_form_div('<?= base_url('Storestock') ?>','maindiv','Hospital Stock');">
|
||||
<i class="bi bi-box-seam"></i>
|
||||
|
|
|
|||
29
app/Views/Setting/Admin/ipd_examination_fields.php
Normal file
29
app/Views/Setting/Admin/ipd_examination_fields.php
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
<?php $rows = $rows ?? []; ?>
|
||||
<section class="content">
|
||||
<div class="card"><div class="card-header d-flex justify-content-between align-items-center flex-wrap gap-2"><div><h5 class="mb-0"><i class="bi bi-clipboard2-pulse me-2"></i>IPD Admission Examination Fields</h5><small class="text-muted">Enabled fields appear in Discharge Management → Examination on Admission. Existing saved values are retained.</small></div><button type="button" class="btn btn-sm btn-outline-secondary" onclick="load_form_div('<?= base_url('setting/admin') ?>','maindiv','Admin Panel')"><i class="bi bi-arrow-left me-1"></i>Admin Panel</button></div>
|
||||
<div class="card-body"><div id="exam_field_notice"></div><form id="exam_field_form" class="row g-3 align-items-end"><input type="hidden" name="id" id="exam_field_id" value="0"><?= csrf_field() ?>
|
||||
<div class="col-md-2"><label class="form-label">Field Code</label><input class="form-control" name="col_code" id="exam_field_code" maxlength="50" placeholder="LEFT_DIAGNOSIS" required></div>
|
||||
<div class="col-md-2"><label class="form-label">Field Name</label><input class="form-control" name="col_name" id="exam_field_name" maxlength="50" placeholder="left_diagnosis" required></div>
|
||||
<div class="col-md-3"><label class="form-label">Display Label</label><input class="form-control" name="col_description" id="exam_field_label" maxlength="50" placeholder="Left Diagnosis" required></div>
|
||||
<div class="col-md-2"><label class="form-label">Input Type</label><select class="form-select" name="col_type" id="exam_field_type"><option value="0">Single-line text</option><option value="1">Long text</option><option value="2">Number</option><option value="4">Select list</option></select></div>
|
||||
<div class="col-md-1"><label class="form-label">Group</label><select class="form-select" name="cat_group" id="exam_field_group"><option value="1">General</option><option value="2">Other</option></select></div>
|
||||
<div class="col-md-1"><label class="form-label">Order</label><input class="form-control" name="display_order" id="exam_field_order" type="number" min="0" step="1" value="0"></div>
|
||||
<div class="col-md-1"><label class="form-label">Enabled</label><select class="form-select" name="is_active" id="exam_field_active"><option value="1">Yes</option><option value="0">No</option></select></div>
|
||||
<div class="col-md-3"><label class="form-label">Unit</label><input class="form-control" name="col_unit" id="exam_field_unit" maxlength="50" placeholder="mmHg"></div>
|
||||
<div class="col-md-6"><label class="form-label">Default / Select Options</label><input class="form-control" name="col_pre_value" id="exam_field_values" placeholder="For select: Normal|Abnormal|Not recorded"></div>
|
||||
<div class="col-md-3 d-flex gap-2"><button type="submit" class="btn btn-primary flex-grow-1"><i class="bi bi-save me-1"></i>Save Field</button><button type="button" class="btn btn-outline-secondary" id="exam_field_clear">Clear</button></div>
|
||||
</form></div></div>
|
||||
<div class="card mt-3"><div class="card-body table-responsive"><table class="table table-sm table-striped align-middle mb-0"><thead class="table-light"><tr><th>Order</th><th>Code</th><th>Label</th><th>Type</th><th>Group</th><th>Unit</th><th>Status</th><th></th></tr></thead><tbody><?php foreach ($rows as $row) : ?><tr data-row='<?= esc(json_encode($row), 'attr') ?>'><td><?= (int) ($row['display_order'] ?? 0) ?></td><td><code><?= esc($row['col_code'] ?? '') ?></code></td><td><?= esc($row['col_description'] ?? '') ?></td><td><?= ['Text', 'Long text', 'Number', 'Auto', 'Select'][(int) ($row['col_type'] ?? 0)] ?? 'Text' ?></td><td><?= (int) ($row['cat_group'] ?? 1) === 2 ? 'Other' : 'General' ?></td><td><?= esc($row['col_unit'] ?? '') ?></td><td><span class="badge text-bg-<?= (int) ($row['is_active'] ?? 1) === 1 ? 'success' : 'secondary' ?>"><?= (int) ($row['is_active'] ?? 1) === 1 ? 'Enabled' : 'Disabled' ?></span></td><td class="text-end"><button type="button" class="btn btn-sm btn-outline-primary exam-field-edit">Edit</button> <button type="button" class="btn btn-sm btn-outline-<?= (int) ($row['is_active'] ?? 1) === 1 ? 'warning' : 'success' ?> exam-field-toggle" data-id="<?= (int) $row['id'] ?>"><?= (int) ($row['is_active'] ?? 1) === 1 ? 'Disable' : 'Enable' ?></button></td></tr><?php endforeach; ?></tbody></table></div></div>
|
||||
</section>
|
||||
<script>
|
||||
(function () {
|
||||
var form = document.getElementById('exam_field_form');
|
||||
var notice = document.getElementById('exam_field_notice');
|
||||
function message(text, kind) { notice.innerHTML = '<div class="alert alert-' + kind + ' py-2">' + $('<div>').text(text).html() + '</div>'; }
|
||||
function reset() { form.reset(); $('#exam_field_id').val('0'); $('#exam_field_active').val('1'); $('#exam_field_order').val('0'); }
|
||||
$('#exam_field_clear').off('click.examFields').on('click.examFields', reset);
|
||||
$(document).off('click.examFields', '.exam-field-edit').on('click.examFields', '.exam-field-edit', function () { var row = $(this).closest('tr').data('row'); if (!row) return; $('#exam_field_id').val(row.id || 0); $('#exam_field_code').val(row.col_code || ''); $('#exam_field_name').val(row.col_name || ''); $('#exam_field_label').val(row.col_description || ''); $('#exam_field_type').val(String(row.col_type || 0)); $('#exam_field_group').val(String(row.cat_group || 1)); $('#exam_field_order').val(row.display_order || 0); $('#exam_field_active').val(String(typeof row.is_active === 'undefined' ? 1 : row.is_active)); $('#exam_field_unit').val(row.col_unit || ''); $('#exam_field_values').val(row.col_pre_value || ''); window.scrollTo({top: 0, behavior: 'smooth'}); });
|
||||
$(document).off('click.examFields', '.exam-field-toggle').on('click.examFields', '.exam-field-toggle', function () { var button = this; var payload = {}; payload['<?= csrf_token() ?>'] = $(form).find('input[name="<?= csrf_token() ?>"]').val(); $.post('<?= base_url('setting/admin/ipd-examination-fields/toggle') ?>/' + $(button).data('id'), payload, function (data) { if (!data || !data.ok) { message((data && data.message) || 'Unable to change field status.', 'danger'); return; } load_form_div('<?= base_url('setting/admin/ipd-examination-fields') ?>', 'maindiv', 'IPD Examination Fields'); }, 'json'); });
|
||||
$(form).off('submit.examFields').on('submit.examFields', function (event) { event.preventDefault(); $.post('<?= base_url('setting/admin/ipd-examination-fields/save') ?>', $(form).serialize(), function (data) { if (!data || !data.ok) { message((data && data.message) || 'Unable to save field.', 'danger'); return; } load_form_div('<?= base_url('setting/admin/ipd-examination-fields') ?>', 'maindiv', 'IPD Examination Fields'); }, 'json').fail(function () { message('Unable to save field.', 'danger'); }); });
|
||||
})();
|
||||
</script>
|
||||
|
|
@ -819,7 +819,7 @@ $historyFields = [
|
|||
<?php foreach ($generalExamGroup1 as $row): ?>
|
||||
<div class="col-md-3">
|
||||
<label class="form-label small"><?= esc((string) ($row['label'] ?? '')) ?></label>
|
||||
<input type="text" class="form-control form-control-sm" name="gen_exam_<?= (int) ($row['id'] ?? 0) ?>" value="<?= esc((string) ($row['value'] ?? '')) ?>">
|
||||
<?php if ((int) ($row['type'] ?? 0) === 1): ?><textarea class="form-control form-control-sm" name="gen_exam_<?= (int) ($row['id'] ?? 0) ?>" rows="2"><?= esc((string) ($row['value'] ?? '')) ?></textarea><?php elseif ((int) ($row['type'] ?? 0) === 4): ?><select class="form-select form-select-sm" name="gen_exam_<?= (int) ($row['id'] ?? 0) ?>"><?php foreach (preg_split('/[|\r\n]+/', (string) ($row['options'] ?? '')) as $option): $option = trim($option); if ($option === '') continue; ?><option value="<?= esc($option) ?>" <?= (string) ($row['value'] ?? '') === $option ? 'selected' : '' ?>><?= esc($option) ?></option><?php endforeach; ?></select><?php else: ?><input type="<?= (int) ($row['type'] ?? 0) === 2 ? 'number' : 'text' ?>" class="form-control form-control-sm" name="gen_exam_<?= (int) ($row['id'] ?? 0) ?>" value="<?= esc((string) ($row['value'] ?? '')) ?>"><?php endif; ?>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
<?php if (empty($generalExamGroup1)): ?>
|
||||
|
|
@ -833,7 +833,7 @@ $historyFields = [
|
|||
<?php foreach ($generalExamGroup2 as $row): ?>
|
||||
<div class="col-md-3">
|
||||
<label class="form-label small"><?= esc((string) ($row['label'] ?? '')) ?></label>
|
||||
<input type="text" class="form-control form-control-sm" name="gen_exam_<?= (int) ($row['id'] ?? 0) ?>" value="<?= esc((string) ($row['value'] ?? '')) ?>">
|
||||
<?php if ((int) ($row['type'] ?? 0) === 1): ?><textarea class="form-control form-control-sm" name="gen_exam_<?= (int) ($row['id'] ?? 0) ?>" rows="2"><?= esc((string) ($row['value'] ?? '')) ?></textarea><?php elseif ((int) ($row['type'] ?? 0) === 4): ?><select class="form-select form-select-sm" name="gen_exam_<?= (int) ($row['id'] ?? 0) ?>"><?php foreach (preg_split('/[|\r\n]+/', (string) ($row['options'] ?? '')) as $option): $option = trim($option); if ($option === '') continue; ?><option value="<?= esc($option) ?>" <?= (string) ($row['value'] ?? '') === $option ? 'selected' : '' ?>><?= esc($option) ?></option><?php endforeach; ?></select><?php else: ?><input type="<?= (int) ($row['type'] ?? 0) === 2 ? 'number' : 'text' ?>" class="form-control form-control-sm" name="gen_exam_<?= (int) ($row['id'] ?? 0) ?>" value="<?= esc((string) ($row['value'] ?? '')) ?>"><?php endif; ?>
|
||||
</div>
|
||||
<?php endforeach; ?>
|
||||
<?php if (empty($generalExamGroup2)): ?>
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user