Restore legacy HMS flows and add IPD document master templates
This commit is contained in:
parent
7ee67ff537
commit
99ec71677a
|
|
@ -150,7 +150,7 @@ class App extends BaseConfig
|
|||
* @see https://www.php.net/manual/en/timezones.php for list of timezones
|
||||
* supported by PHP.
|
||||
*/
|
||||
public string $appTimezone = 'UTC';
|
||||
public string $appTimezone = 'Asia/Kolkata';
|
||||
|
||||
/**
|
||||
* --------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -294,6 +294,10 @@ $routes->get('IpdNew/addipd/(:num)', 'Billing\\Ipd::legacyAddIpd/$1');
|
|||
$routes->post('IpdNew/AddNew', 'Billing\\Ipd::legacyAddNew');
|
||||
$routes->post('IpdNew/addnew', 'Billing\\Ipd::legacyAddNew');
|
||||
$routes->get('IpdNew/ipd_panel/(:num)', 'Billing\\Ipd::panel/$1');
|
||||
$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');
|
||||
$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->match(['get', 'post'], 'Ipd_discharge/ipd_select/(:num)', 'Ipd_discharge::ipd_select/$1');
|
||||
|
|
@ -346,6 +350,8 @@ $routes->group('billing', function($routes) {
|
|||
$routes->post('ipd/panel/(:num)/discharge/charge/(:num)', 'Billing\\Ipd::updateDischargeCharge/$1/$2');
|
||||
$routes->get('ipd/bill-print/(:num)', 'Billing\\Ipd::billPrint/$1');
|
||||
$routes->get('ipd/bill-print/(:num)/(:num)', 'Billing\\Ipd::billPrint/$1/$2');
|
||||
$routes->get('ipd/show-form/(:num)', 'Billing\\Ipd::showIpdForm/$1/1');
|
||||
$routes->get('ipd/show-form/(:num)/(:num)', 'Billing\\Ipd::showIpdForm/$1/$2');
|
||||
$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');
|
||||
|
|
@ -457,6 +463,7 @@ $routes->post('Opd/showfee', 'Opd::showfee');
|
|||
$routes->post('Opd/confirm_opd', 'Opd::confirm_opd');
|
||||
$routes->post('Opd/confirm_payment', 'Opd::confirm_payment');
|
||||
$routes->post('Opd/opd_discount_update/(:num)', 'Opd::opd_discount_update/$1');
|
||||
$routes->post('Opd/opd_cancel/(:num)', 'Opd::opd_cancel/$1');
|
||||
$routes->match(['get', 'post'], 'Opd/opd_load_doc/(:num)', 'Opd::opd_load_doc/$1');
|
||||
$routes->match(['get', 'post'], 'Opd/opd_file_last_list', 'Opd::opd_file_last_list');
|
||||
$routes->match(['get', 'post'], 'Opd/opd_file_last_list/(:num)', 'Opd::opd_file_last_list/$1');
|
||||
|
|
@ -599,6 +606,8 @@ $routes->get('Opd_prescription/show_medical_item/(:num)', 'Opd_prescription::sho
|
|||
$routes->get('Opd_prescription/prescribed_dose/(:num)/(:num)', 'Opd_prescription::prescribed_dose/$1/$2');
|
||||
|
||||
$routes->get('Invoice/list_req_payment', 'Invoice::list_req_payment');
|
||||
$routes->get('Invoice/opdlist', 'Invoice::opdlist');
|
||||
$routes->get('Invoice/chargeslist', 'Invoice::chargeslist');
|
||||
$routes->post('Invoice/getRequestTable', 'Invoice::getRequestTable');
|
||||
$routes->get('Invoice/payment_form/(:num)', 'Invoice::payment_form/$1');
|
||||
$routes->post('Invoice/req_payment_process', 'Invoice::req_payment_process');
|
||||
|
|
@ -633,6 +642,8 @@ $routes->post('Lab_Admin/test_item_search', 'Setting\Template::test_item_search'
|
|||
|
||||
$routes->match(['get', 'post'], 'setting/template/discharge_templates', 'Setting\Template::discharge_templates');
|
||||
$routes->get('setting/template/discharge_templates/delete/(:num)', 'Setting\Template::discharge_template_delete/$1');
|
||||
$routes->match(['get', 'post'], 'setting/template/ipd_document_templates', 'Setting\Template::ipd_document_templates');
|
||||
$routes->get('setting/template/ipd_document_templates/delete/(:num)', 'Setting\Template::ipd_document_template_delete/$1');
|
||||
$routes->match(['get', 'post'], 'setting/template/diagnosis_print_settings', 'Setting\Template::diagnosis_print_settings');
|
||||
$routes->match(['get', 'post'], 'setting/template/diagnosis_print_settings/(:num)', 'Setting\Template::diagnosis_print_settings/$1');
|
||||
$routes->match(['get', 'post'], 'setting/template/document_print_settings', 'Setting\Template::document_print_settings');
|
||||
|
|
@ -901,6 +912,13 @@ $routes->group('setting', static function($routes) {
|
|||
$routes->post('admin/reffer/types/update', 'Setting\\Reffer::updateType');
|
||||
$routes->post('admin/reffer/types/delete', 'Setting\\Reffer::deleteType');
|
||||
$routes->get('admin/bed-management', 'Setting\\BedManagement::index');
|
||||
$routes->get('admin/departments', 'Setting\\BedManagement::departments');
|
||||
$routes->post('admin/departments/save', 'Setting\\BedManagement::saveDepartment');
|
||||
$routes->post('admin/departments/delete', 'Setting\\BedManagement::deleteDepartment');
|
||||
$routes->get('admin/wards', 'Setting\\BedManagement::wards');
|
||||
$routes->get('admin/bed-status', 'Setting\\BedManagement::bedStatus');
|
||||
$routes->post('admin/wards/save', 'Setting\\BedManagement::saveWard');
|
||||
$routes->post('admin/wards/delete', 'Setting\\BedManagement::deleteWard');
|
||||
$routes->get('admin/bed-categories', 'Setting\\BedManagement::categories');
|
||||
$routes->post('admin/bed-categories/save', 'Setting\\BedManagement::saveCategory');
|
||||
$routes->post('admin/bed-categories/delete', 'Setting\\BedManagement::deleteCategory');
|
||||
|
|
|
|||
|
|
@ -474,6 +474,13 @@ class Ipd extends BaseController
|
|||
return view('billing/ipd/panel_discharge', $panelData);
|
||||
}
|
||||
|
||||
if ($tab === 'documents') {
|
||||
return view('billing/ipd/panel_documents', [
|
||||
'ipd_id' => $ipdId,
|
||||
'ipd_info' => $panelData['ipd_info'] ?? null,
|
||||
]);
|
||||
}
|
||||
|
||||
return view('billing/ipd/panel_placeholder', [
|
||||
'title' => ucwords(str_replace('-', ' ', $tab)),
|
||||
]);
|
||||
|
|
@ -792,6 +799,67 @@ class Ipd extends BaseController
|
|||
->setBody($mpdf->Output($fileName, 'S'));
|
||||
}
|
||||
|
||||
public function showIpdForm(int $ipdId, int $formNo = 1)
|
||||
{
|
||||
$permission = $this->requireAnyPermission([
|
||||
'billing.ipd.bill.print',
|
||||
'billing.ipd.invoice',
|
||||
]);
|
||||
if ($permission) {
|
||||
return $permission;
|
||||
}
|
||||
|
||||
$formMeta = $this->getIpdFormMeta($formNo);
|
||||
if ($formMeta === null) {
|
||||
return $this->response->setStatusCode(404)->setBody('Unsupported form ID');
|
||||
}
|
||||
|
||||
$data = $this->buildIpdPrintableFormData($ipdId, $formNo);
|
||||
if ($data === null) {
|
||||
return $this->response->setStatusCode(404)->setBody('IPD not found');
|
||||
}
|
||||
|
||||
$html = view('billing/ipd/ipd_form_print', $data);
|
||||
$customTemplate = $this->getActiveIpdDocumentTemplate($formNo);
|
||||
if ($customTemplate !== null) {
|
||||
$html = $this->renderIpdDocumentTemplateHtml($customTemplate, $data);
|
||||
}
|
||||
|
||||
$mpdfTempDir = WRITEPATH . 'cache' . DIRECTORY_SEPARATOR . 'mpdf';
|
||||
if (! is_dir($mpdfTempDir)) {
|
||||
mkdir($mpdfTempDir, 0755, true);
|
||||
}
|
||||
|
||||
$mpdfConfig = [
|
||||
'tempDir' => $mpdfTempDir,
|
||||
'margin_top' => 8,
|
||||
'margin_bottom' => 8,
|
||||
'margin_left' => 8,
|
||||
'margin_right' => 8,
|
||||
];
|
||||
|
||||
if (in_array($formNo, [10, 11], true)) {
|
||||
$mpdfConfig['format'] = $formNo === 10 ? [50.8, 152.4] : [50.8, 203.2];
|
||||
$mpdfConfig['margin_top'] = 2;
|
||||
$mpdfConfig['margin_bottom'] = 2;
|
||||
$mpdfConfig['margin_left'] = 2;
|
||||
$mpdfConfig['margin_right'] = 2;
|
||||
} else {
|
||||
$mpdfConfig['format'] = 'A4';
|
||||
}
|
||||
|
||||
$mpdf = new Mpdf($mpdfConfig);
|
||||
$mpdf->WriteHTML($html);
|
||||
|
||||
$ipdCode = (string) ($data['ipd_info']->ipd_code ?? ('IPD-' . $ipdId));
|
||||
$fileName = 'IPD_Form_' . (int) $formNo . '_' . preg_replace('/[^A-Za-z0-9_\-]/', '_', $ipdCode) . '.pdf';
|
||||
|
||||
return $this->response
|
||||
->setHeader('Content-Type', 'application/pdf')
|
||||
->setHeader('Content-Disposition', 'inline; filename="' . $fileName . '"')
|
||||
->setBody($mpdf->Output($fileName, 'S'));
|
||||
}
|
||||
|
||||
public function addIpdCharge(int $ipdId)
|
||||
{
|
||||
$permission = $this->requireAnyPermission([
|
||||
|
|
@ -1775,6 +1843,157 @@ class Ipd extends BaseController
|
|||
return [$start, $end];
|
||||
}
|
||||
|
||||
private function getIpdFormMeta(int $formNo): ?array
|
||||
{
|
||||
$meta = [
|
||||
1 => ['title' => 'Face Form'],
|
||||
3 => ['title' => 'Self Declaration Form'],
|
||||
5 => ['title' => 'Admission Assessment Form'],
|
||||
8 => ['title' => 'Progress Notes and Doctor Order'],
|
||||
9 => ['title' => 'Fluid In / Out'],
|
||||
10 => ['title' => 'Sticker [2 x 6]'],
|
||||
11 => ['title' => 'Sticker [2 x 8]'],
|
||||
];
|
||||
|
||||
return $meta[$formNo] ?? null;
|
||||
}
|
||||
|
||||
private function buildIpdPrintableFormData(int $ipdId, int $formNo): ?array
|
||||
{
|
||||
$panelData = $this->ipdModel->getIpdPanelInfo($ipdId);
|
||||
if (empty($panelData)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$ipdInfo = $panelData['ipd_info'] ?? null;
|
||||
$personInfo = $panelData['person_info'] ?? null;
|
||||
if ($ipdInfo === null || $personInfo === null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$personInfo->age = get_age_1(
|
||||
$personInfo->dob ?? null,
|
||||
$personInfo->age ?? '',
|
||||
$personInfo->age_in_month ?? '',
|
||||
$personInfo->estimate_dob ?? ''
|
||||
);
|
||||
|
||||
$doctorRows = [];
|
||||
if ($this->db->tableExists('ipd_master_doc_list') && $this->db->tableExists('doctor_master')) {
|
||||
$doctorRows = $this->db->table('ipd_master_doc_list l')
|
||||
->select("concat_ws(' ', 'Dr.', d.p_fname, d.p_mname, d.p_lname) as doc_name", false)
|
||||
->join('doctor_master d', 'd.id = l.doc_id', 'inner')
|
||||
->where('l.ipd_id', $ipdId)
|
||||
->groupBy('d.id, d.p_fname, d.p_mname, d.p_lname')
|
||||
->orderBy('d.p_fname', 'ASC')
|
||||
->get()
|
||||
->getResultArray();
|
||||
}
|
||||
|
||||
$doctorNames = array_values(array_filter(array_map(
|
||||
static fn ($row) => trim((string) ($row['doc_name'] ?? '')),
|
||||
$doctorRows
|
||||
)));
|
||||
|
||||
if (empty($doctorNames)) {
|
||||
$fallbackDoctor = trim((string) ($ipdInfo->r_doc_name ?? ''));
|
||||
if ($fallbackDoctor !== '') {
|
||||
$doctorNames[] = $fallbackDoctor;
|
||||
}
|
||||
}
|
||||
|
||||
$insuranceName = trim((string) ($ipdInfo->ins_company_name ?? ''));
|
||||
if ($insuranceName === '' && $this->db->tableExists('organization_case_master')) {
|
||||
$insuranceRow = $this->db->table('organization_case_master o')
|
||||
->select('h.ins_company_name')
|
||||
->join('hc_insurance h', 'h.id = o.insurance_id', 'left')
|
||||
->where('o.id', (int) ($ipdInfo->case_id ?? 0))
|
||||
->get()
|
||||
->getRowArray();
|
||||
$insuranceName = trim((string) ($insuranceRow['ins_company_name'] ?? ''));
|
||||
}
|
||||
|
||||
$hospitalName = defined('H_Name') ? (string) constant('H_Name') : 'Hospital';
|
||||
$hospitalAddress = defined('H_address_1') ? (string) constant('H_address_1') : '';
|
||||
|
||||
return [
|
||||
'form_no' => $formNo,
|
||||
'form_meta' => $this->getIpdFormMeta($formNo),
|
||||
'ipd_info' => $ipdInfo,
|
||||
'person_info' => $personInfo,
|
||||
'doctor_names' => $doctorNames,
|
||||
'insurance_name' => $insuranceName,
|
||||
'hospital_name' => $hospitalName,
|
||||
'hospital_address' => $hospitalAddress,
|
||||
'generated_at' => date('d-m-Y h:i A'),
|
||||
];
|
||||
}
|
||||
|
||||
private function getActiveIpdDocumentTemplate(int $formNo): ?array
|
||||
{
|
||||
if (! $this->db->tableExists('ipd_document_templates')) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$row = $this->db->table('ipd_document_templates')
|
||||
->select('id, form_no, template_name, template_html')
|
||||
->where('form_no', $formNo)
|
||||
->where('status', 1)
|
||||
->orderBy('id', 'DESC')
|
||||
->get(1)
|
||||
->getRowArray();
|
||||
|
||||
if (! is_array($row) || empty($row)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $row;
|
||||
}
|
||||
|
||||
private function renderIpdDocumentTemplateHtml(array $templateRow, array $data): string
|
||||
{
|
||||
$templateHtml = (string) ($templateRow['template_html'] ?? '');
|
||||
if (trim($templateHtml) === '') {
|
||||
return view('billing/ipd/ipd_form_print', $data);
|
||||
}
|
||||
|
||||
$formMeta = $data['form_meta'] ?? [];
|
||||
$ipd = $data['ipd_info'] ?? null;
|
||||
$person = $data['person_info'] ?? null;
|
||||
$doctorNames = is_array($data['doctor_names'] ?? null) ? $data['doctor_names'] : [];
|
||||
|
||||
$patientName = trim((string) (($person->title ?? '') . ' ' . ($person->p_fname ?? '')));
|
||||
if ($patientName === '') {
|
||||
$patientName = '-';
|
||||
}
|
||||
|
||||
$age = (string) ($person->age ?? '-');
|
||||
$gender = (string) ($person->xgender ?? '-');
|
||||
$ageGender = trim($age . ' / ' . $gender);
|
||||
if ($ageGender === '/') {
|
||||
$ageGender = '-';
|
||||
}
|
||||
|
||||
$replacements = [
|
||||
'{{FORM_TITLE}}' => esc((string) ($formMeta['title'] ?? 'IPD Form')),
|
||||
'{{HOSPITAL_NAME}}' => esc((string) ($data['hospital_name'] ?? 'Hospital')),
|
||||
'{{HOSPITAL_ADDRESS}}' => esc((string) ($data['hospital_address'] ?? '')),
|
||||
'{{PATIENT_NAME}}' => esc($patientName),
|
||||
'{{AGE}}' => esc($age),
|
||||
'{{GENDER}}' => esc($gender),
|
||||
'{{AGE_GENDER}}' => esc($ageGender),
|
||||
'{{UHID}}' => esc((string) ($person->p_code ?? '-')),
|
||||
'{{IPD_CODE}}' => esc((string) ($ipd->ipd_code ?? '-')),
|
||||
'{{ADMIT_DATE}}' => esc((string) ($ipd->str_register_date ?? ($ipd->register_date ?? '-'))),
|
||||
'{{DOCTORS}}' => esc(! empty($doctorNames) ? implode(', ', $doctorNames) : '-'),
|
||||
'{{INSURANCE_NAME}}' => esc((string) ($data['insurance_name'] ?? 'Direct')),
|
||||
'{{CURRENT_DATE}}' => esc(date('d-m-Y')),
|
||||
'{{CURRENT_DATETIME}}' => esc((string) ($data['generated_at'] ?? date('d-m-Y h:i A'))),
|
||||
];
|
||||
|
||||
return strtr($templateHtml, $replacements);
|
||||
}
|
||||
|
||||
private function calculateCashBalanceTotals(array $rows): array
|
||||
{
|
||||
$totalPaid = 0.0;
|
||||
|
|
|
|||
|
|
@ -21,6 +21,64 @@ class Invoice extends BaseController
|
|||
return view('Invoice/payment_request_list');
|
||||
}
|
||||
|
||||
public function opdlist()
|
||||
{
|
||||
$search = trim((string) $this->request->getGet('q'));
|
||||
|
||||
$builder = $this->db->table('opd_master o')
|
||||
->select('o.opd_id, o.opd_code, o.P_name, o.p_id, o.doc_name, o.apointment_date, o.payment_status, o.payment_mode, o.insurance_id')
|
||||
->select('p.p_code, p.mphone1, p.email1')
|
||||
->join('patient_master p', 'p.id = o.p_id', 'left')
|
||||
->orderBy('o.opd_id', 'DESC')
|
||||
->limit(200);
|
||||
|
||||
if ($search !== '') {
|
||||
$builder->groupStart()
|
||||
->like('o.opd_code', $search, 'both')
|
||||
->orLike('p.p_code', $search, 'both')
|
||||
->orLike('o.P_name', $search, 'both')
|
||||
->orLike('p.mphone1', $search, 'both')
|
||||
->orLike('p.email1', $search, 'both')
|
||||
->groupEnd();
|
||||
}
|
||||
|
||||
$rows = $builder->get()->getResult();
|
||||
|
||||
return view('Invoice/opd_invoice_list', [
|
||||
'search' => $search,
|
||||
'rows' => $rows,
|
||||
]);
|
||||
}
|
||||
|
||||
public function chargeslist()
|
||||
{
|
||||
$search = trim((string) $this->request->getGet('q'));
|
||||
|
||||
$builder = $this->db->table('invoice_master i')
|
||||
->select('i.id as inv_id, i.invoice_code, i.inv_date, i.attach_id, i.insurance_id, i.invoice_status, i.payment_mode, i.payment_part_balance, i.net_amount, i.refer_by_other')
|
||||
->select('p.p_code, p.p_fname, p.mphone1, p.email1')
|
||||
->join('patient_master p', 'p.id = i.attach_id and i.attach_type=0', 'left')
|
||||
->orderBy('i.id', 'DESC')
|
||||
->limit(200);
|
||||
|
||||
if ($search !== '') {
|
||||
$builder->groupStart()
|
||||
->like('i.invoice_code', $search, 'both')
|
||||
->orLike('p.p_code', $search, 'both')
|
||||
->orLike('p.p_fname', $search, 'both')
|
||||
->orLike('p.mphone1', $search, 'both')
|
||||
->orLike('p.email1', $search, 'both')
|
||||
->groupEnd();
|
||||
}
|
||||
|
||||
$rows = $builder->get()->getResult();
|
||||
|
||||
return view('Invoice/charges_invoice_list', [
|
||||
'search' => $search,
|
||||
'rows' => $rows,
|
||||
]);
|
||||
}
|
||||
|
||||
public function getRequestTable()
|
||||
{
|
||||
if (! $this->request->isAJAX()) {
|
||||
|
|
|
|||
|
|
@ -1204,6 +1204,12 @@ class Opd extends BaseController
|
|||
$query = $this->db->query($sql);
|
||||
$data['payment_history'] = $query->getResult();
|
||||
|
||||
$sql = "select id,payment_date,insert_time,payment_mode,credit_debit,amount,remark,card_tran_id,update_by,
|
||||
(case payment_mode when 0 then 'Zero Amount' when 1 then 'Cash' when 2 then 'Bank/Online' when 3 then 'Return Cash' when 4 then 'Bank Return' else 'Other' end) as payment_mode_str
|
||||
from payment_history where payof_type=1 and payof_id=" . (int) $opdId . " order by id desc";
|
||||
$query = $this->db->query($sql);
|
||||
$data['payment_history_rows'] = $query->getResult();
|
||||
|
||||
$paidAmount = 0;
|
||||
if (!empty($data['payment_history']) && $data['payment_history'][0]->paid_amount) {
|
||||
$paidAmount = (float) $data['payment_history'][0]->paid_amount;
|
||||
|
|
@ -2923,6 +2929,95 @@ class Opd extends BaseController
|
|||
]);
|
||||
}
|
||||
|
||||
public function opd_cancel(int $opdId)
|
||||
{
|
||||
if (! $this->request->isAJAX()) {
|
||||
return $this->response->setStatusCode(400)->setJSON([
|
||||
'update' => 0,
|
||||
'error_text' => 'Invalid request',
|
||||
]);
|
||||
}
|
||||
|
||||
$opdId = (int) ($this->request->getPost('oid') ?? $opdId);
|
||||
if ($opdId <= 0) {
|
||||
return $this->response->setJSON([
|
||||
'update' => 0,
|
||||
'error_text' => 'Invalid OPD ID',
|
||||
'csrfName' => csrf_token(),
|
||||
'csrfHash' => csrf_hash(),
|
||||
]);
|
||||
}
|
||||
|
||||
$opdRow = $this->db->table('opd_master')->where('opd_id', $opdId)->get(1)->getRowArray();
|
||||
if (empty($opdRow)) {
|
||||
return $this->response->setJSON([
|
||||
'update' => 0,
|
||||
'error_text' => 'OPD not found',
|
||||
'csrfName' => csrf_token(),
|
||||
'csrfHash' => csrf_hash(),
|
||||
]);
|
||||
}
|
||||
|
||||
$user = auth()->user();
|
||||
$userId = (int) ($user->id ?? 0);
|
||||
$userName = (string) ($user->username ?? $user->email ?? 'User');
|
||||
$userLabel = $userName . '[' . $userId . ']:T-' . date('d-m-Y H:i:s');
|
||||
|
||||
$remarkInput = trim((string) $this->request->getPost('input_remark'));
|
||||
$remarkPrefix = $remarkInput !== '' ? $remarkInput : 'Cancel OPD';
|
||||
$statusRemark = $remarkPrefix . ' [Update By:' . $userLabel . ']';
|
||||
|
||||
$sql = "select coalesce(sum(if(credit_debit>0,amount*-1,amount)),0) as paid_amount
|
||||
from payment_history where payof_type=1 and payof_id=" . (int) $opdId;
|
||||
$query = $this->db->query($sql);
|
||||
$paymentHistory = $query->getResult();
|
||||
$paidAmount = (float) ($paymentHistory[0]->paid_amount ?? 0);
|
||||
|
||||
$refundPaymentId = 0;
|
||||
$this->db->transStart();
|
||||
|
||||
if ($paidAmount > 0 && (int) ($opdRow['opd_status'] ?? 0) !== 3) {
|
||||
$paymentModel = new PaymentModel();
|
||||
$refundPaymentId = $paymentModel->insertPayment([
|
||||
'payment_mode' => '1',
|
||||
'payof_type' => '1',
|
||||
'payof_id' => $opdId,
|
||||
'payof_code' => (string) ($opdRow['opd_code'] ?? ''),
|
||||
'credit_debit' => '1',
|
||||
'amount' => $paidAmount,
|
||||
'payment_date' => date('Y-m-d H:i:s'),
|
||||
'remark' => 'Refund: ' . $remarkPrefix,
|
||||
'update_by' => $userLabel,
|
||||
'update_by_id' => $userId,
|
||||
]);
|
||||
}
|
||||
|
||||
$this->db->table('opd_master')
|
||||
->where('opd_id', $opdId)
|
||||
->update([
|
||||
'opd_status' => '3',
|
||||
'opd_status_remark' => $statusRemark,
|
||||
]);
|
||||
|
||||
$this->db->transComplete();
|
||||
if (! $this->db->transStatus()) {
|
||||
return $this->response->setJSON([
|
||||
'update' => 0,
|
||||
'error_text' => 'Unable to cancel OPD. Please retry.',
|
||||
'csrfName' => csrf_token(),
|
||||
'csrfHash' => csrf_hash(),
|
||||
]);
|
||||
}
|
||||
|
||||
return $this->response->setJSON([
|
||||
'update' => 1,
|
||||
'showcontent' => 'OPD cancelled' . ($refundPaymentId > 0 ? ' and refund posted' : ''),
|
||||
'refund_payment_id' => $refundPaymentId,
|
||||
'csrfName' => csrf_token(),
|
||||
'csrfHash' => csrf_hash(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load scan/upload modal context for a specific OPD record.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -48,6 +48,341 @@ class BedManagement extends BaseController
|
|||
return $builder->countAllResults() > 0;
|
||||
}
|
||||
|
||||
private function wardCodeExists(string $wardCode, int $excludeId = 0): bool
|
||||
{
|
||||
$builder = $this->db->table('ward_master')->where('ward_code', $wardCode);
|
||||
if ($excludeId > 0) {
|
||||
$builder->where('id !=', $excludeId);
|
||||
}
|
||||
|
||||
return $builder->countAllResults() > 0;
|
||||
}
|
||||
|
||||
public function wards(): string
|
||||
{
|
||||
$departments = [(object) [
|
||||
'iId' => 0,
|
||||
'vName' => 'All Department',
|
||||
]];
|
||||
|
||||
if ($this->db->tableExists('hc_department')) {
|
||||
$departmentRows = $this->db->table('hc_department')
|
||||
->orderBy('vName', 'ASC')
|
||||
->get()
|
||||
->getResult();
|
||||
|
||||
$departments = array_merge($departments, $departmentRows);
|
||||
}
|
||||
|
||||
$wardBuilder = $this->db->table('ward_master w')
|
||||
->orderBy('w.ward_name', 'ASC');
|
||||
|
||||
if ($this->db->tableExists('hc_department')) {
|
||||
$wardBuilder->select('w.*, COALESCE(d.vName, "All Department") AS department_name', false)
|
||||
->join('hc_department d', 'd.iId = w.department_id', 'left');
|
||||
} else {
|
||||
$wardBuilder->select('w.*, "All Department" AS department_name', false);
|
||||
}
|
||||
|
||||
$wardRows = $wardBuilder->get()->getResult();
|
||||
|
||||
return view('Setting/Bed/ward_list', [
|
||||
'wards' => $wardRows,
|
||||
'departments' => $departments,
|
||||
]);
|
||||
}
|
||||
|
||||
public function saveWard()
|
||||
{
|
||||
if (! $this->request->isAJAX()) {
|
||||
return $this->response->setJSON(['update' => 0, 'error_text' => 'Invalid request']);
|
||||
}
|
||||
|
||||
$id = (int) $this->request->getPost('id');
|
||||
$wardCode = trim((string) $this->request->getPost('ward_code'));
|
||||
$wardName = trim((string) $this->request->getPost('ward_name'));
|
||||
$departmentIdRaw = $this->request->getPost('department_id');
|
||||
$departmentId = $departmentIdRaw === null || $departmentIdRaw === '' ? 0 : (int) $departmentIdRaw;
|
||||
|
||||
if ($wardCode === '' || $wardName === '') {
|
||||
return $this->response->setJSON(['update' => 0, 'error_text' => 'Ward code and ward name are required.']);
|
||||
}
|
||||
|
||||
if ($this->wardCodeExists($wardCode, $id)) {
|
||||
return $this->response->setJSON(['update' => 0, 'error_text' => 'Ward code already exists.']);
|
||||
}
|
||||
|
||||
if ($departmentId > 0 && $this->db->tableExists('hc_department')) {
|
||||
$departmentExists = $this->db->table('hc_department')
|
||||
->where('iId', $departmentId)
|
||||
->countAllResults();
|
||||
|
||||
if ($departmentExists <= 0) {
|
||||
return $this->response->setJSON(['update' => 0, 'error_text' => 'Invalid department selected.']);
|
||||
}
|
||||
}
|
||||
|
||||
$user = auth()->user();
|
||||
$data = [
|
||||
'ward_code' => $wardCode,
|
||||
'ward_name' => $wardName,
|
||||
'department_id' => $departmentId,
|
||||
'building_id' => $this->request->getPost('building_id') ?: null,
|
||||
'floor_number' => $this->request->getPost('floor_number') ?: null,
|
||||
'ward_type' => $this->request->getPost('ward_type') ?: 'General',
|
||||
'gender_type' => $this->request->getPost('gender_type') ?: 'unisex',
|
||||
'ward_category' => $this->request->getPost('ward_category') ?: 'adult',
|
||||
'total_capacity' => $this->request->getPost('total_capacity') ?: 0,
|
||||
'nurse_station_location' => $this->request->getPost('nurse_station_location'),
|
||||
'has_oxygen' => $this->request->getPost('has_oxygen') ? 1 : 0,
|
||||
'has_suction' => $this->request->getPost('has_suction') ? 1 : 0,
|
||||
'has_monitor' => $this->request->getPost('has_monitor') ? 1 : 0,
|
||||
'status' => $this->request->getPost('status') ?: 'active',
|
||||
'remarks' => $this->request->getPost('remarks'),
|
||||
];
|
||||
|
||||
$model = new WardModel();
|
||||
if ($id > 0) {
|
||||
$updated = $model->update($id, $data);
|
||||
|
||||
return $this->response->setJSON([
|
||||
'update' => $updated ? 1 : 0,
|
||||
'showcontent' => $updated ? 'Data Saved successfully' : 'Please check',
|
||||
'csrfName' => csrf_token(),
|
||||
'csrfHash' => csrf_hash(),
|
||||
]);
|
||||
}
|
||||
|
||||
$data['created_by'] = $user->id ?? null;
|
||||
$insertId = $model->insert($data);
|
||||
|
||||
return $this->response->setJSON([
|
||||
'insertid' => $insertId,
|
||||
'error_text' => $insertId > 0 ? '' : 'Please check',
|
||||
'csrfName' => csrf_token(),
|
||||
'csrfHash' => csrf_hash(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function deleteWard()
|
||||
{
|
||||
if (! $this->request->isAJAX()) {
|
||||
return $this->response->setJSON(['update' => 0, 'error_text' => 'Invalid request']);
|
||||
}
|
||||
|
||||
$id = (int) $this->request->getPost('id');
|
||||
if ($id <= 0) {
|
||||
return $this->response->setJSON(['update' => 0, 'error_text' => 'Invalid ward ID']);
|
||||
}
|
||||
|
||||
$bedCount = $this->db->table('bed_master')
|
||||
->where('ward_id', $id)
|
||||
->countAllResults();
|
||||
|
||||
if ($bedCount > 0) {
|
||||
return $this->response->setJSON([
|
||||
'update' => 0,
|
||||
'error_text' => $bedCount . ' bed(s) are mapped with this ward. Cannot delete.',
|
||||
'csrfName' => csrf_token(),
|
||||
'csrfHash' => csrf_hash(),
|
||||
]);
|
||||
}
|
||||
|
||||
$model = new WardModel();
|
||||
$deleted = $model->delete($id);
|
||||
|
||||
return $this->response->setJSON([
|
||||
'update' => $deleted ? 1 : 0,
|
||||
'error_text' => $deleted ? '' : 'Delete failed. Please try again.',
|
||||
'csrfName' => csrf_token(),
|
||||
'csrfHash' => csrf_hash(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function departments(): string
|
||||
{
|
||||
if (! $this->db->tableExists('hc_department')) {
|
||||
return view('Setting/Bed/department_list', [
|
||||
'departments' => [],
|
||||
'tableMissing' => true,
|
||||
]);
|
||||
}
|
||||
|
||||
$departmentRows = $this->db->table('hc_department')
|
||||
->orderBy('vName', 'ASC')
|
||||
->get()
|
||||
->getResult();
|
||||
|
||||
return view('Setting/Bed/department_list', [
|
||||
'departments' => $departmentRows,
|
||||
'tableMissing' => false,
|
||||
]);
|
||||
}
|
||||
|
||||
public function saveDepartment()
|
||||
{
|
||||
if (! $this->request->isAJAX()) {
|
||||
return $this->response->setJSON(['update' => 0, 'error_text' => 'Invalid request']);
|
||||
}
|
||||
|
||||
if (! $this->db->tableExists('hc_department')) {
|
||||
return $this->response->setJSON(['update' => 0, 'error_text' => 'Department table not found.']);
|
||||
}
|
||||
|
||||
$id = (int) $this->request->getPost('id');
|
||||
$name = trim((string) $this->request->getPost('department_name'));
|
||||
$typeId = $this->request->getPost('hc_type_id');
|
||||
$typeId = $typeId === null || $typeId === '' ? null : (int) $typeId;
|
||||
|
||||
if ($name === '') {
|
||||
return $this->response->setJSON(['update' => 0, 'error_text' => 'Department name is required.']);
|
||||
}
|
||||
|
||||
$duplicate = $this->db->table('hc_department')
|
||||
->where('vName', $name);
|
||||
if ($id > 0) {
|
||||
$duplicate->where('iId !=', $id);
|
||||
}
|
||||
|
||||
if ($duplicate->countAllResults() > 0) {
|
||||
return $this->response->setJSON(['update' => 0, 'error_text' => 'Department name already exists.']);
|
||||
}
|
||||
|
||||
$payload = [
|
||||
'vName' => $name,
|
||||
'hc_type_id' => $typeId,
|
||||
];
|
||||
|
||||
if ($id > 0) {
|
||||
$updated = $this->db->table('hc_department')
|
||||
->where('iId', $id)
|
||||
->update($payload);
|
||||
|
||||
return $this->response->setJSON([
|
||||
'update' => $updated ? 1 : 0,
|
||||
'showcontent' => $updated ? 'Data Saved successfully' : 'Please check',
|
||||
'csrfName' => csrf_token(),
|
||||
'csrfHash' => csrf_hash(),
|
||||
]);
|
||||
}
|
||||
|
||||
$inserted = $this->db->table('hc_department')->insert($payload);
|
||||
$insertId = $inserted ? (int) $this->db->insertID() : 0;
|
||||
|
||||
return $this->response->setJSON([
|
||||
'insertid' => $insertId,
|
||||
'error_text' => $insertId > 0 ? '' : 'Please check',
|
||||
'csrfName' => csrf_token(),
|
||||
'csrfHash' => csrf_hash(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function deleteDepartment()
|
||||
{
|
||||
if (! $this->request->isAJAX()) {
|
||||
return $this->response->setJSON(['update' => 0, 'error_text' => 'Invalid request']);
|
||||
}
|
||||
|
||||
if (! $this->db->tableExists('hc_department')) {
|
||||
return $this->response->setJSON(['update' => 0, 'error_text' => 'Department table not found.']);
|
||||
}
|
||||
|
||||
$id = (int) $this->request->getPost('id');
|
||||
if ($id <= 0) {
|
||||
return $this->response->setJSON(['update' => 0, 'error_text' => 'Invalid department ID']);
|
||||
}
|
||||
|
||||
$wardCount = $this->db->table('ward_master')
|
||||
->where('department_id', $id)
|
||||
->countAllResults();
|
||||
|
||||
if ($wardCount > 0) {
|
||||
return $this->response->setJSON([
|
||||
'update' => 0,
|
||||
'error_text' => $wardCount . ' ward(s) use this department. Cannot delete.',
|
||||
'csrfName' => csrf_token(),
|
||||
'csrfHash' => csrf_hash(),
|
||||
]);
|
||||
}
|
||||
|
||||
$this->db->table('hc_department')->where('iId', $id)->delete();
|
||||
$deleted = $this->db->affectedRows() > 0;
|
||||
|
||||
return $this->response->setJSON([
|
||||
'update' => $deleted ? 1 : 0,
|
||||
'error_text' => $deleted ? '' : 'Delete failed. Please try again.',
|
||||
'csrfName' => csrf_token(),
|
||||
'csrfHash' => csrf_hash(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function bedStatus(): string
|
||||
{
|
||||
$departments = [(object) ['iId' => 0, 'vName' => 'All Department']];
|
||||
if ($this->db->tableExists('hc_department')) {
|
||||
$departments = array_merge(
|
||||
$departments,
|
||||
$this->db->table('hc_department')->orderBy('vName', 'ASC')->get()->getResult()
|
||||
);
|
||||
}
|
||||
|
||||
$wards = $this->db->table('ward_master')
|
||||
->select('id, ward_name, department_id')
|
||||
->orderBy('ward_name', 'ASC')
|
||||
->get()
|
||||
->getResult();
|
||||
|
||||
$builder = $this->db->table('ipd_master i')
|
||||
->select('i.id as ipd_id, i.ipd_code, i.register_date, i.p_id')
|
||||
->where('i.ipd_status', 0)
|
||||
->orderBy('i.id', 'DESC');
|
||||
|
||||
if ($this->db->tableExists('patient_master')) {
|
||||
$builder->select('p.p_code, p.p_fname, p.p_lname, p.mphone1, p.mphone2')
|
||||
->join('patient_master p', 'p.id = i.p_id', 'left');
|
||||
}
|
||||
|
||||
if ($this->db->tableExists('bed_assignment_history')) {
|
||||
$builder->join(
|
||||
'(select max(id) as id, ipd_id from bed_assignment_history group by ipd_id) bah_latest',
|
||||
'bah_latest.ipd_id = i.id',
|
||||
'left',
|
||||
false
|
||||
)->join('bed_assignment_history bah', 'bah.id = bah_latest.id', 'left');
|
||||
|
||||
if ($this->db->tableExists('bed_master')) {
|
||||
$builder->join('bed_master b', 'b.id = bah.bed_id', 'left');
|
||||
}
|
||||
if ($this->db->tableExists('ward_master')) {
|
||||
$builder->join('ward_master w', 'w.id = bah.ward_id', 'left');
|
||||
}
|
||||
} else {
|
||||
if ($this->db->tableExists('bed_master')) {
|
||||
$builder->join('bed_master b', 'b.current_ipd_id = i.id', 'left');
|
||||
}
|
||||
if ($this->db->tableExists('ward_master')) {
|
||||
$builder->join('ward_master w', 'w.id = b.ward_id', 'left');
|
||||
}
|
||||
}
|
||||
|
||||
$builder->select('b.bed_number, b.bed_code, w.id as ward_id, w.ward_name, w.department_id');
|
||||
|
||||
if ($this->db->tableExists('hc_department')) {
|
||||
$builder->select('d.vName as department_name')
|
||||
->join('hc_department d', 'd.iId = w.department_id', 'left');
|
||||
} else {
|
||||
$builder->select('"All Department" as department_name', false);
|
||||
}
|
||||
|
||||
$rows = $builder->get()->getResult();
|
||||
|
||||
return view('Setting/Bed/bed_status_list', [
|
||||
'rows' => $rows,
|
||||
'departments' => $departments,
|
||||
'wards' => $wards,
|
||||
]);
|
||||
}
|
||||
|
||||
public function categories(): string
|
||||
{
|
||||
$model = new BedCategoryModel();
|
||||
|
|
@ -72,34 +407,35 @@ class BedManagement extends BaseController
|
|||
}
|
||||
|
||||
$data = [
|
||||
'category_code' => $code,
|
||||
'category_name' => $name,
|
||||
'category_type' => $this->request->getPost('category_type'),
|
||||
'base_charge_per_day' => $this->request->getPost('base_charge_per_day') ?? 0,
|
||||
'category_code' => $code,
|
||||
'category_name' => $name,
|
||||
'category_type' => $this->request->getPost('category_type'),
|
||||
'base_charge_per_day' => $this->request->getPost('base_charge_per_day') ?? 0,
|
||||
'nursing_charge_per_day' => $this->request->getPost('nursing_charge_per_day') ?? 0,
|
||||
'amenities' => $this->request->getPost('amenities'),
|
||||
'description' => $this->request->getPost('description'),
|
||||
'status' => $this->request->getPost('status') ?? 'active',
|
||||
'amenities' => $this->request->getPost('amenities'),
|
||||
'description' => $this->request->getPost('description'),
|
||||
'status' => $this->request->getPost('status') ?? 'active',
|
||||
];
|
||||
|
||||
$model = new BedCategoryModel();
|
||||
if ($id > 0) {
|
||||
$updated = $model->update($id, $data);
|
||||
|
||||
return $this->response->setJSON([
|
||||
'update' => $updated ? 1 : 0,
|
||||
'update' => $updated ? 1 : 0,
|
||||
'showcontent' => $updated ? 'Data Saved successfully' : 'Please check',
|
||||
'csrfName' => csrf_token(),
|
||||
'csrfHash' => csrf_hash(),
|
||||
'csrfName' => csrf_token(),
|
||||
'csrfHash' => csrf_hash(),
|
||||
]);
|
||||
}
|
||||
|
||||
$insertId = $model->insert($data);
|
||||
|
||||
return $this->response->setJSON([
|
||||
'insertid' => $insertId,
|
||||
'insertid' => $insertId,
|
||||
'error_text' => $insertId > 0 ? '' : 'Please check',
|
||||
'csrfName' => csrf_token(),
|
||||
'csrfHash' => csrf_hash(),
|
||||
'csrfName' => csrf_token(),
|
||||
'csrfHash' => csrf_hash(),
|
||||
]);
|
||||
}
|
||||
|
||||
|
|
@ -114,26 +450,41 @@ class BedManagement extends BaseController
|
|||
return $this->response->setJSON(['update' => 0, 'error_text' => 'Invalid category ID']);
|
||||
}
|
||||
|
||||
$model = new BedCategoryModel();
|
||||
// Block deletion if any beds in this category are currently occupied by IPD patients
|
||||
$inUseCount = $this->db->table('bed_master')
|
||||
->where('bed_category_id', $id)
|
||||
->where('current_ipd_id IS NOT NULL', null, false)
|
||||
->countAllResults();
|
||||
|
||||
if ($inUseCount > 0) {
|
||||
return $this->response->setJSON([
|
||||
'update' => 0,
|
||||
'error_text' => "{$inUseCount} bed(s) in this category are currently occupied by IPD patient(s). Cannot delete.",
|
||||
'csrfName' => csrf_token(),
|
||||
'csrfHash' => csrf_hash(),
|
||||
]);
|
||||
}
|
||||
|
||||
$model = new BedCategoryModel();
|
||||
$deleted = $model->delete($id);
|
||||
|
||||
return $this->response->setJSON([
|
||||
'update' => $deleted ? 1 : 0,
|
||||
'error_text' => $deleted ? '' : 'Please check',
|
||||
'csrfName' => csrf_token(),
|
||||
'csrfHash' => csrf_hash(),
|
||||
'update' => $deleted ? 1 : 0,
|
||||
'error_text' => $deleted ? '' : 'Delete failed. Please try again.',
|
||||
'csrfName' => csrf_token(),
|
||||
'csrfHash' => csrf_hash(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function beds(): string
|
||||
{
|
||||
$bedModel = new BedMasterModel();
|
||||
$wardModel = new WardModel();
|
||||
$bedModel = new BedMasterModel();
|
||||
$wardModel = new WardModel();
|
||||
$categoryModel = new BedCategoryModel();
|
||||
|
||||
return view('Setting/Bed/bed_list', [
|
||||
'beds' => $bedModel->getAllWithRelations(),
|
||||
'wards' => $wardModel->getAllActive(),
|
||||
'beds' => $bedModel->getAllWithRelations(),
|
||||
'wards' => $wardModel->getAllActive(),
|
||||
'categories' => $categoryModel->getAll(),
|
||||
]);
|
||||
}
|
||||
|
|
@ -144,10 +495,10 @@ class BedManagement extends BaseController
|
|||
return $this->response->setJSON(['update' => 0, 'error_text' => 'Invalid request']);
|
||||
}
|
||||
|
||||
$id = (int) $this->request->getPost('id');
|
||||
$bedCode = trim((string) $this->request->getPost('bed_code'));
|
||||
$bedNumber = trim((string) $this->request->getPost('bed_number'));
|
||||
$wardId = (int) $this->request->getPost('ward_id');
|
||||
$id = (int) $this->request->getPost('id');
|
||||
$bedCode = trim((string) $this->request->getPost('bed_code'));
|
||||
$bedNumber = trim((string) $this->request->getPost('bed_number'));
|
||||
$wardId = (int) $this->request->getPost('ward_id');
|
||||
$categoryId = (int) $this->request->getPost('bed_category_id');
|
||||
|
||||
if ($bedCode === '' || $bedNumber === '' || $wardId <= 0 || $categoryId <= 0) {
|
||||
|
|
@ -163,41 +514,42 @@ class BedManagement extends BaseController
|
|||
}
|
||||
|
||||
$data = [
|
||||
'bed_code' => $bedCode,
|
||||
'bed_number' => $bedNumber,
|
||||
'ward_id' => $wardId,
|
||||
'bed_category_id' => $categoryId,
|
||||
'bed_status' => $this->request->getPost('bed_status') ?? 'available',
|
||||
'bed_position' => $this->request->getPost('bed_position'),
|
||||
'has_oxygen' => $this->request->getPost('has_oxygen') ? 1 : 0,
|
||||
'has_suction' => $this->request->getPost('has_suction') ? 1 : 0,
|
||||
'has_monitor' => $this->request->getPost('has_monitor') ? 1 : 0,
|
||||
'has_ventilator' => $this->request->getPost('has_ventilator') ? 1 : 0,
|
||||
'is_isolation_bed' => $this->request->getPost('is_isolation_bed') ? 1 : 0,
|
||||
'base_charge_override' => $this->request->getPost('base_charge_override') ?: null,
|
||||
'bed_code' => $bedCode,
|
||||
'bed_number' => $bedNumber,
|
||||
'ward_id' => $wardId,
|
||||
'bed_category_id' => $categoryId,
|
||||
'bed_status' => $this->request->getPost('bed_status') ?? 'available',
|
||||
'bed_position' => $this->request->getPost('bed_position'),
|
||||
'has_oxygen' => $this->request->getPost('has_oxygen') ? 1 : 0,
|
||||
'has_suction' => $this->request->getPost('has_suction') ? 1 : 0,
|
||||
'has_monitor' => $this->request->getPost('has_monitor') ? 1 : 0,
|
||||
'has_ventilator' => $this->request->getPost('has_ventilator') ? 1 : 0,
|
||||
'is_isolation_bed' => $this->request->getPost('is_isolation_bed') ? 1 : 0,
|
||||
'base_charge_override' => $this->request->getPost('base_charge_override') ?: null,
|
||||
'nursing_charge_override' => $this->request->getPost('nursing_charge_override') ?: null,
|
||||
'status' => $this->request->getPost('status') ?? 'active',
|
||||
'remarks' => $this->request->getPost('remarks'),
|
||||
'status' => $this->request->getPost('status') ?? 'active',
|
||||
'remarks' => $this->request->getPost('remarks'),
|
||||
];
|
||||
|
||||
$model = new BedMasterModel();
|
||||
if ($id > 0) {
|
||||
$updated = $model->update($id, $data);
|
||||
|
||||
return $this->response->setJSON([
|
||||
'update' => $updated ? 1 : 0,
|
||||
'update' => $updated ? 1 : 0,
|
||||
'showcontent' => $updated ? 'Data Saved successfully' : 'Please check',
|
||||
'csrfName' => csrf_token(),
|
||||
'csrfHash' => csrf_hash(),
|
||||
'csrfName' => csrf_token(),
|
||||
'csrfHash' => csrf_hash(),
|
||||
]);
|
||||
}
|
||||
|
||||
$insertId = $model->insert($data);
|
||||
|
||||
return $this->response->setJSON([
|
||||
'insertid' => $insertId,
|
||||
'insertid' => $insertId,
|
||||
'error_text' => $insertId > 0 ? '' : 'Please check',
|
||||
'csrfName' => csrf_token(),
|
||||
'csrfHash' => csrf_hash(),
|
||||
'csrfName' => csrf_token(),
|
||||
'csrfHash' => csrf_hash(),
|
||||
]);
|
||||
}
|
||||
|
||||
|
|
@ -212,20 +564,20 @@ class BedManagement extends BaseController
|
|||
return $this->response->setJSON(['update' => 0, 'error_text' => 'Invalid bed ID']);
|
||||
}
|
||||
|
||||
$model = new BedMasterModel();
|
||||
$model = new BedMasterModel();
|
||||
$deleted = $model->delete($id);
|
||||
|
||||
return $this->response->setJSON([
|
||||
'update' => $deleted ? 1 : 0,
|
||||
'update' => $deleted ? 1 : 0,
|
||||
'error_text' => $deleted ? '' : 'Please check',
|
||||
'csrfName' => csrf_token(),
|
||||
'csrfHash' => csrf_hash(),
|
||||
'csrfName' => csrf_token(),
|
||||
'csrfHash' => csrf_hash(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function maintenance(): string
|
||||
{
|
||||
$bedModel = new BedMasterModel();
|
||||
$bedModel = new BedMasterModel();
|
||||
$maintenanceModel = new BedMaintenanceLogModel();
|
||||
|
||||
return view('Setting/Bed/maintenance_list', [
|
||||
|
|
@ -240,45 +592,46 @@ class BedManagement extends BaseController
|
|||
return $this->response->setJSON(['update' => 0, 'error_text' => 'Invalid request']);
|
||||
}
|
||||
|
||||
$id = (int) $this->request->getPost('id');
|
||||
$id = (int) $this->request->getPost('id');
|
||||
$bedId = (int) $this->request->getPost('bed_id');
|
||||
$type = trim((string) $this->request->getPost('maintenance_type'));
|
||||
$type = trim((string) $this->request->getPost('maintenance_type'));
|
||||
|
||||
if ($bedId <= 0 || $type === '') {
|
||||
return $this->response->setJSON(['update' => 0, 'error_text' => 'Bed and maintenance type are required.']);
|
||||
}
|
||||
|
||||
$data = [
|
||||
'bed_id' => $bedId,
|
||||
'maintenance_type' => $type,
|
||||
'scheduled_date' => $this->request->getPost('scheduled_date') ?: null,
|
||||
'completed_date' => $this->normalizeDateTime($this->request->getPost('completed_date')),
|
||||
'performed_by' => $this->request->getPost('performed_by'),
|
||||
'issue_description' => $this->request->getPost('issue_description'),
|
||||
'action_taken' => $this->request->getPost('action_taken'),
|
||||
'bed_id' => $bedId,
|
||||
'maintenance_type' => $type,
|
||||
'scheduled_date' => $this->request->getPost('scheduled_date') ?: null,
|
||||
'completed_date' => $this->normalizeDateTime($this->request->getPost('completed_date')),
|
||||
'performed_by' => $this->request->getPost('performed_by'),
|
||||
'issue_description' => $this->request->getPost('issue_description'),
|
||||
'action_taken' => $this->request->getPost('action_taken'),
|
||||
'next_maintenance_date' => $this->request->getPost('next_maintenance_date') ?: null,
|
||||
'cost' => $this->request->getPost('cost') ?: 0,
|
||||
'status' => $this->request->getPost('status') ?? 'pending',
|
||||
'cost' => $this->request->getPost('cost') ?: 0,
|
||||
'status' => $this->request->getPost('status') ?? 'pending',
|
||||
];
|
||||
|
||||
$model = new BedMaintenanceLogModel();
|
||||
if ($id > 0) {
|
||||
$updated = $model->update($id, $data);
|
||||
|
||||
return $this->response->setJSON([
|
||||
'update' => $updated ? 1 : 0,
|
||||
'update' => $updated ? 1 : 0,
|
||||
'showcontent' => $updated ? 'Data Saved successfully' : 'Please check',
|
||||
'csrfName' => csrf_token(),
|
||||
'csrfHash' => csrf_hash(),
|
||||
'csrfName' => csrf_token(),
|
||||
'csrfHash' => csrf_hash(),
|
||||
]);
|
||||
}
|
||||
|
||||
$insertId = $model->insert($data);
|
||||
|
||||
return $this->response->setJSON([
|
||||
'insertid' => $insertId,
|
||||
'insertid' => $insertId,
|
||||
'error_text' => $insertId > 0 ? '' : 'Please check',
|
||||
'csrfName' => csrf_token(),
|
||||
'csrfHash' => csrf_hash(),
|
||||
'csrfName' => csrf_token(),
|
||||
'csrfHash' => csrf_hash(),
|
||||
]);
|
||||
}
|
||||
|
||||
|
|
@ -293,27 +646,27 @@ class BedManagement extends BaseController
|
|||
return $this->response->setJSON(['update' => 0, 'error_text' => 'Invalid maintenance ID']);
|
||||
}
|
||||
|
||||
$model = new BedMaintenanceLogModel();
|
||||
$model = new BedMaintenanceLogModel();
|
||||
$deleted = $model->delete($id);
|
||||
|
||||
return $this->response->setJSON([
|
||||
'update' => $deleted ? 1 : 0,
|
||||
'update' => $deleted ? 1 : 0,
|
||||
'error_text' => $deleted ? '' : 'Please check',
|
||||
'csrfName' => csrf_token(),
|
||||
'csrfHash' => csrf_hash(),
|
||||
'csrfName' => csrf_token(),
|
||||
'csrfHash' => csrf_hash(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function assignmentHistory(): string
|
||||
{
|
||||
$model = new BedAssignmentHistoryModel();
|
||||
$bedModel = new BedMasterModel();
|
||||
$model = new BedAssignmentHistoryModel();
|
||||
$bedModel = new BedMasterModel();
|
||||
$wardModel = new WardModel();
|
||||
|
||||
return view('Setting/Bed/assignment_history', [
|
||||
'assignments' => $model->getAllWithRelations(),
|
||||
'beds' => $bedModel->getAllWithRelations(),
|
||||
'wards' => $wardModel->getAllActive(),
|
||||
'beds' => $bedModel->getAllWithRelations(),
|
||||
'wards' => $wardModel->getAllActive(),
|
||||
]);
|
||||
}
|
||||
|
||||
|
|
@ -323,10 +676,10 @@ class BedManagement extends BaseController
|
|||
return $this->response->setJSON(['update' => 0, 'error_text' => 'Invalid request']);
|
||||
}
|
||||
|
||||
$id = (int) $this->request->getPost('id');
|
||||
$bedId = (int) $this->request->getPost('bed_id');
|
||||
$wardId = (int) $this->request->getPost('ward_id');
|
||||
$type = trim((string) $this->request->getPost('assignment_type'));
|
||||
$id = (int) $this->request->getPost('id');
|
||||
$bedId = (int) $this->request->getPost('bed_id');
|
||||
$wardId = (int) $this->request->getPost('ward_id');
|
||||
$type = trim((string) $this->request->getPost('assignment_type'));
|
||||
$assignedDate = $this->normalizeDateTime($this->request->getPost('assigned_date'));
|
||||
|
||||
if ($bedId <= 0 || $wardId <= 0 || $type === '' || $assignedDate === null) {
|
||||
|
|
@ -334,39 +687,40 @@ class BedManagement extends BaseController
|
|||
}
|
||||
|
||||
$data = [
|
||||
'ipd_id' => $this->request->getPost('ipd_id') ?: null,
|
||||
'bed_id' => $bedId,
|
||||
'assignment_type' => $type,
|
||||
'assigned_date' => $assignedDate,
|
||||
'discharged_date' => $this->normalizeDateTime($this->request->getPost('discharged_date')),
|
||||
'assigned_by' => $this->request->getPost('assigned_by') ?: null,
|
||||
'transfer_reason' => $this->request->getPost('transfer_reason'),
|
||||
'ipd_id' => $this->request->getPost('ipd_id') ?: null,
|
||||
'bed_id' => $bedId,
|
||||
'assignment_type' => $type,
|
||||
'assigned_date' => $assignedDate,
|
||||
'discharged_date' => $this->normalizeDateTime($this->request->getPost('discharged_date')),
|
||||
'assigned_by' => $this->request->getPost('assigned_by') ?: null,
|
||||
'transfer_reason' => $this->request->getPost('transfer_reason'),
|
||||
'transfer_from_bed_id' => $this->request->getPost('transfer_from_bed_id') ?: null,
|
||||
'remarks' => $this->request->getPost('remarks'),
|
||||
'ward_id' => $wardId,
|
||||
'released_date' => $this->normalizeDateTime($this->request->getPost('released_date')),
|
||||
'total_days' => $this->request->getPost('total_days') ?: 0,
|
||||
'release_reason' => $this->request->getPost('release_reason'),
|
||||
'remarks' => $this->request->getPost('remarks'),
|
||||
'ward_id' => $wardId,
|
||||
'released_date' => $this->normalizeDateTime($this->request->getPost('released_date')),
|
||||
'total_days' => $this->request->getPost('total_days') ?: 0,
|
||||
'release_reason' => $this->request->getPost('release_reason'),
|
||||
];
|
||||
|
||||
$model = new BedAssignmentHistoryModel();
|
||||
if ($id > 0) {
|
||||
$updated = $model->update($id, $data);
|
||||
|
||||
return $this->response->setJSON([
|
||||
'update' => $updated ? 1 : 0,
|
||||
'update' => $updated ? 1 : 0,
|
||||
'showcontent' => $updated ? 'Data Saved successfully' : 'Please check',
|
||||
'csrfName' => csrf_token(),
|
||||
'csrfHash' => csrf_hash(),
|
||||
'csrfName' => csrf_token(),
|
||||
'csrfHash' => csrf_hash(),
|
||||
]);
|
||||
}
|
||||
|
||||
$insertId = $model->insert($data);
|
||||
|
||||
return $this->response->setJSON([
|
||||
'insertid' => $insertId,
|
||||
'insertid' => $insertId,
|
||||
'error_text' => $insertId > 0 ? '' : 'Please check',
|
||||
'csrfName' => csrf_token(),
|
||||
'csrfHash' => csrf_hash(),
|
||||
'csrfName' => csrf_token(),
|
||||
'csrfHash' => csrf_hash(),
|
||||
]);
|
||||
}
|
||||
|
||||
|
|
@ -381,14 +735,14 @@ class BedManagement extends BaseController
|
|||
return $this->response->setJSON(['update' => 0, 'error_text' => 'Invalid assignment ID']);
|
||||
}
|
||||
|
||||
$model = new BedAssignmentHistoryModel();
|
||||
$model = new BedAssignmentHistoryModel();
|
||||
$deleted = $model->delete($id);
|
||||
|
||||
return $this->response->setJSON([
|
||||
'update' => $deleted ? 1 : 0,
|
||||
'update' => $deleted ? 1 : 0,
|
||||
'error_text' => $deleted ? '' : 'Please check',
|
||||
'csrfName' => csrf_token(),
|
||||
'csrfHash' => csrf_hash(),
|
||||
'csrfName' => csrf_token(),
|
||||
'csrfHash' => csrf_hash(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
|
@ -1346,4 +1346,343 @@ HTML;
|
|||
|
||||
return redirect()->to(base_url('setting/template/discharge_templates'));
|
||||
}
|
||||
|
||||
private function ensureIpdDocumentTemplateTable(): void
|
||||
{
|
||||
if ($this->db->tableExists('ipd_document_templates')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$sql = "CREATE TABLE IF NOT EXISTS ipd_document_templates (
|
||||
id INT NOT NULL AUTO_INCREMENT,
|
||||
form_no INT NOT NULL,
|
||||
template_name VARCHAR(160) NOT NULL,
|
||||
template_html LONGTEXT NOT NULL,
|
||||
status TINYINT(1) NOT NULL DEFAULT 1,
|
||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (id),
|
||||
KEY idx_form_no (form_no),
|
||||
KEY idx_status (status)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4";
|
||||
|
||||
$this->db->query($sql);
|
||||
}
|
||||
|
||||
private function defaultIpdDocumentTemplates(): array
|
||||
{
|
||||
return [
|
||||
[
|
||||
'form_no' => 1,
|
||||
'template_name' => 'Legacy Face Form (IPD2)',
|
||||
'template_html' => <<<'HTML'
|
||||
<style>
|
||||
.ipd-form { font-size: 12px; line-height: 1.35; }
|
||||
.ipd-form h3 { margin: 0 0 10px 0; text-align: center; }
|
||||
.ipd-form table { width: 100%; border-collapse: collapse; }
|
||||
.ipd-form .meta td { border: 1px solid #444; padding: 6px; vertical-align: top; }
|
||||
</style>
|
||||
<div class="ipd-form">
|
||||
<h3>BED HEAD TICKET</h3>
|
||||
<table class="meta">
|
||||
<tr>
|
||||
<td style="width:50%;">
|
||||
<b>Patient Information</b><br><br>
|
||||
<b>Patient Name:</b> {{PATIENT_NAME}}<br>
|
||||
<b>Age/Gender:</b> {{AGE_GENDER}}<br>
|
||||
<b>UHID:</b> {{UHID}}<br>
|
||||
<b>IPD Code:</b> {{IPD_CODE}}<br>
|
||||
<b>Date And Time of Admission:</b> {{ADMIT_DATE}}
|
||||
</td>
|
||||
<td style="width:50%;">
|
||||
<b>Hospital:</b> {{HOSPITAL_NAME}}<br>
|
||||
<b>Address:</b> {{HOSPITAL_ADDRESS}}<br>
|
||||
<b>Doctors:</b> {{DOCTORS}}<br>
|
||||
<b>Insurance:</b> {{INSURANCE_NAME}}
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<h3 style="font-size:18px;margin-top:12px;">सहमति पत्र</h3>
|
||||
<p style="font-size:15px;">
|
||||
मैं इलाज कराने का/की इच्छुक हूँ। मैं {{HOSPITAL_NAME}} के चिकित्सक और उनके सहायकों को अपना उपचार,
|
||||
परीक्षण, परामर्श, जांच, औषधि देने एवं आवश्यक चिकित्सा प्रक्रियाएं करने की स्वीकृति देता/देती हूँ।
|
||||
मुझे बीमारी, संभावित जटिलताओं और उपचार में होने वाले खर्च के बारे में समझा दिया गया है।
|
||||
</p>
|
||||
|
||||
<p style="margin-top:18px;">हस्ताक्षर / अंगूठा निशान: __________________________</p>
|
||||
<p>नाम: __________________________ मरीज से संबंध: __________________________</p>
|
||||
<p>पता: __________________________ फ़ोन नंबर: __________________________</p>
|
||||
</div>
|
||||
HTML,
|
||||
],
|
||||
[
|
||||
'form_no' => 3,
|
||||
'template_name' => 'Legacy Self Declaration (IPD2)',
|
||||
'template_html' => <<<'HTML'
|
||||
<div style="font-size:12px;line-height:1.35;">
|
||||
<h3 style="text-align:center;margin:0 0 10px 0;">SELF DECLARATION FROM HEALTH INSURANCE CARD HOLDER</h3>
|
||||
<h3 style="text-align:center;margin:0 0 10px 0;">मेडिक्लेम बीमा कार्ड धारक द्वारा स्वघोषणा</h3>
|
||||
|
||||
<table border="1" cellpadding="6" cellspacing="0" style="width:100%;border-collapse:collapse;">
|
||||
<tr>
|
||||
<td><b>Patient Name:</b> {{PATIENT_NAME}}</td>
|
||||
<td><b>UHID:</b> {{UHID}}</td>
|
||||
<td><b>IPD:</b> {{IPD_CODE}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Age/Gender:</b> {{AGE_GENDER}}</td>
|
||||
<td><b>Admission:</b> {{ADMIT_DATE}}</td>
|
||||
<td><b>Insurance:</b> {{INSURANCE_NAME}}</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<p style="margin-top:12px;">
|
||||
मैं __________________________ यह घोषणा करता/करती हूँ कि मरीज {{PATIENT_NAME}} का मेडिक्लेम {{INSURANCE_NAME}} में है,
|
||||
और भर्ती दिनांक {{ADMIT_DATE}} को हुई है। मैंने आवश्यक दस्तावेज जमा कर दिए हैं और यदि क्लेम पूर्ण/आंशिक स्वीकृत नहीं होता
|
||||
है तो शेष देय राशि का भुगतान स्वयं करूँगा/करूँगी।
|
||||
</p>
|
||||
|
||||
<p>हस्ताक्षर / अंगूठा निशान: __________________________</p>
|
||||
<p>नाम: __________________________ मरीज से संबंध: __________________________</p>
|
||||
<p>पता: __________________________ फ़ोन नंबर: __________________________</p>
|
||||
<p>दिनांक: {{CURRENT_DATE}}</p>
|
||||
</div>
|
||||
HTML,
|
||||
],
|
||||
[
|
||||
'form_no' => 5,
|
||||
'template_name' => 'Legacy Admission History & Physical Assessment',
|
||||
'template_html' => <<<'HTML'
|
||||
<div style="font-size:11px;line-height:1.3;">
|
||||
<h3 style="text-align:center;margin:0 0 8px 0;">ADMISSION HISTORY AND PHYSICAL ASSESSMENT FORM</h3>
|
||||
<p><b>Patient:</b> {{PATIENT_NAME}} <b>Age/Gender:</b> {{AGE_GENDER}} <b>UHID:</b> {{UHID}} <b>IPD:</b> {{IPD_CODE}} <b>Admit Date:</b> {{ADMIT_DATE}}</p>
|
||||
<p><b>Diagnosis:</b> ______________________________________________</p>
|
||||
<p><b>Time of Patient Arrival:</b> ____________ <b>Time of Doctor Assessment:</b> ____________</p>
|
||||
<p><b>Consciousness:</b> [ ] Awake [ ] Alert [ ] In pain [ ] Response to verbal commands [ ] Unresponsive</p>
|
||||
<p><b>GCS:</b> E___ V___ M___ <b>Airway/Breathing:</b> [ ] Clear [ ] Noisy [ ] Stridor [ ] Obstruction</p>
|
||||
<p><b>Allergic To:</b> ______________________________________________</p>
|
||||
<p><b>Present Complaints:</b></p>
|
||||
<div style="border:1px solid #666;height:52px;"></div>
|
||||
|
||||
<p style="margin-top:8px;"><b>Past Medical History:</b></p>
|
||||
<table border="1" cellpadding="4" cellspacing="0" style="width:100%;border-collapse:collapse;">
|
||||
<tr><td style="width:25%;">Diabetes / Metabolic</td><td style="width:25%;"></td><td style="width:25%;">Jaundice / CLD</td><td style="width:25%;"></td></tr>
|
||||
<tr><td>Hypertension / IHD</td><td></td><td>Osteoarthritis</td><td></td></tr>
|
||||
<tr><td>Asthma / COPD / TB</td><td></td><td>Tuberculosis</td><td></td></tr>
|
||||
<tr><td colspan="4">Others:</td></tr>
|
||||
</table>
|
||||
|
||||
<p><b>Drug History:</b></p>
|
||||
<div style="border:1px solid #666;height:42px;"></div>
|
||||
<p><b>Past Surgical History:</b></p>
|
||||
<div style="border:1px solid #666;height:42px;"></div>
|
||||
|
||||
<p><b>Declaration:</b> I hereby declare that the facts recorded above are accurate to the best of my knowledge.</p>
|
||||
<p>Name of Patient/Relative: ________________________ Signature: ________________________</p>
|
||||
<p>Date: {{CURRENT_DATE}}</p>
|
||||
</div>
|
||||
HTML,
|
||||
],
|
||||
[
|
||||
'form_no' => 8,
|
||||
'template_name' => 'Legacy Progress Notes and Doctor Order',
|
||||
'template_html' => <<<'HTML'
|
||||
<div style="font-size:11px;line-height:1.3;">
|
||||
<h3 style="text-align:center;margin:0 0 8px 0;">PROGRESS NOTES AND DOCTOR'S ORDER</h3>
|
||||
<p><b>Name:</b> {{PATIENT_NAME}} <b>IPD:</b> {{IPD_CODE}} <b>UHID:</b> {{UHID}} <b>Age/Gender:</b> {{AGE_GENDER}}</p>
|
||||
<hr>
|
||||
<table border="1" cellpadding="5" cellspacing="0" style="width:100%;border-collapse:collapse;">
|
||||
<tr>
|
||||
<th style="width:18%;text-align:center;">DATE</th>
|
||||
<th style="text-align:center;">PROGRESS NOTES AND DOCTOR'S ORDER</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="height:420px;"></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
HTML,
|
||||
],
|
||||
[
|
||||
'form_no' => 9,
|
||||
'template_name' => 'Legacy Oral / Enteral Intake Output Chart',
|
||||
'template_html' => <<<'HTML'
|
||||
<div style="font-size:11px;line-height:1.25;">
|
||||
<h3 style="text-align:center;margin:0 0 8px 0;">ORAL / ENTERAL INTAKE & OUTPUT CHART</h3>
|
||||
<p><b>Name:</b> {{PATIENT_NAME}} <b>IPD:</b> {{IPD_CODE}} <b>UHID:</b> {{UHID}} <b>Age/Gender:</b> {{AGE_GENDER}}</p>
|
||||
<hr>
|
||||
<table border="1" cellpadding="4" cellspacing="0" style="width:100%;border-collapse:collapse;">
|
||||
<tr>
|
||||
<th style="width:6%;">SR.No.</th>
|
||||
<th style="width:10%;">Date</th>
|
||||
<th style="width:8%;">Time</th>
|
||||
<th style="width:17%;">Description</th>
|
||||
<th style="width:7%;">Vol.</th>
|
||||
<th style="width:7%;">Vol.</th>
|
||||
<th style="width:7%;">Total</th>
|
||||
<th style="width:7%;">Urine</th>
|
||||
<th style="width:7%;">Stool</th>
|
||||
<th style="width:7%;">Other</th>
|
||||
<th style="width:7%;">Other</th>
|
||||
<th style="width:7%;">Other</th>
|
||||
<th style="width:7%;">Total</th>
|
||||
</tr>
|
||||
<tr><td>1</td><td style="height:24px;"></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
|
||||
<tr><td>2</td><td style="height:24px;"></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
|
||||
<tr><td>3</td><td style="height:24px;"></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
|
||||
<tr><td>4</td><td style="height:24px;"></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
|
||||
<tr><td>5</td><td style="height:24px;"></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td></tr>
|
||||
</table>
|
||||
</div>
|
||||
HTML,
|
||||
],
|
||||
[
|
||||
'form_no' => 10,
|
||||
'template_name' => 'Legacy Sticker [2 x 6]',
|
||||
'template_html' => <<<'HTML'
|
||||
<div style="font-size:9px;border:1px dashed #444;padding:4px;line-height:1.25;">
|
||||
<div><b>{{HOSPITAL_NAME}}</b></div>
|
||||
<div><b>Patient Name:</b> {{PATIENT_NAME}}</div>
|
||||
<div><b>Age / Gender:</b> {{AGE_GENDER}}</div>
|
||||
<div><b>UHID / Patient ID:</b> {{UHID}}</div>
|
||||
<div><b>IPD Code:</b> {{IPD_CODE}}</div>
|
||||
<div><b>Dept./Doctor:</b> {{DOCTORS}}</div>
|
||||
<div><b>Date of Admission:</b> {{ADMIT_DATE}}</div>
|
||||
</div>
|
||||
HTML,
|
||||
],
|
||||
[
|
||||
'form_no' => 11,
|
||||
'template_name' => 'Legacy Sticker [2 x 8]',
|
||||
'template_html' => <<<'HTML'
|
||||
<div style="font-size:9px;border:1px dashed #444;padding:4px;line-height:1.25;">
|
||||
<div><b>{{HOSPITAL_NAME}}</b></div>
|
||||
<div><b>{{HOSPITAL_ADDRESS}}</b></div>
|
||||
<div><b>Patient Name:</b> {{PATIENT_NAME}}</div>
|
||||
<div><b>Age / Gender:</b> {{AGE_GENDER}}</div>
|
||||
<div><b>UHID / Patient ID:</b> {{UHID}}</div>
|
||||
<div><b>IPD Code:</b> {{IPD_CODE}}</div>
|
||||
<div><b>Dept./Doctor:</b> {{DOCTORS}}</div>
|
||||
<div><b>Date of Admission:</b> {{ADMIT_DATE}}</div>
|
||||
<div><b>Insurance:</b> {{INSURANCE_NAME}}</div>
|
||||
</div>
|
||||
HTML,
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
private function ensureDefaultIpdDocumentTemplatesSeeded(): void
|
||||
{
|
||||
$this->ensureIpdDocumentTemplateTable();
|
||||
if (! $this->db->tableExists('ipd_document_templates')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$table = $this->db->table('ipd_document_templates');
|
||||
foreach ($this->defaultIpdDocumentTemplates() as $row) {
|
||||
$formNo = (int) ($row['form_no'] ?? 0);
|
||||
$templateName = (string) ($row['template_name'] ?? '');
|
||||
if ($formNo <= 0 || $templateName === '') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$exists = $this->db->table('ipd_document_templates')
|
||||
->where('form_no', $formNo)
|
||||
->where('template_name', $templateName)
|
||||
->countAllResults();
|
||||
|
||||
if ($exists > 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$table->insert([
|
||||
'form_no' => $formNo,
|
||||
'template_name' => $templateName,
|
||||
'template_html' => (string) ($row['template_html'] ?? ''),
|
||||
'status' => 1,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
public function ipd_document_templates()
|
||||
{
|
||||
if ($resp = $this->requireAnyPermission(['template.discharge'])) {
|
||||
return $resp;
|
||||
}
|
||||
|
||||
$this->ensureDefaultIpdDocumentTemplatesSeeded();
|
||||
|
||||
$notice = '';
|
||||
$noticeType = 'success';
|
||||
|
||||
if (strtolower($this->request->getMethod()) === 'post') {
|
||||
$id = (int) ($this->request->getPost('id') ?? 0);
|
||||
$formNo = (int) ($this->request->getPost('form_no') ?? 0);
|
||||
$templateName = trim((string) ($this->request->getPost('template_name') ?? ''));
|
||||
$templateHtml = (string) ($this->request->getPost('template_html') ?? '');
|
||||
$status = (int) ($this->request->getPost('status') ?? 1) === 1 ? 1 : 0;
|
||||
|
||||
if (! in_array($formNo, [1, 3, 5, 8, 9, 10, 11], true)) {
|
||||
$notice = 'Invalid form number.';
|
||||
$noticeType = 'danger';
|
||||
} elseif ($templateName === '' || trim($templateHtml) === '') {
|
||||
$notice = 'Form number, template name and HTML are required.';
|
||||
$noticeType = 'danger';
|
||||
} else {
|
||||
$table = $this->db->table('ipd_document_templates');
|
||||
$data = [
|
||||
'form_no' => $formNo,
|
||||
'template_name' => $templateName,
|
||||
'template_html' => $templateHtml,
|
||||
'status' => $status,
|
||||
];
|
||||
|
||||
if ($id > 0) {
|
||||
$table->where('id', $id)->update($data);
|
||||
$notice = 'Template updated.';
|
||||
} else {
|
||||
$table->insert($data);
|
||||
$notice = 'Template created.';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$editId = (int) ($this->request->getGet('edit') ?? 0);
|
||||
$editRow = [];
|
||||
if ($editId > 0) {
|
||||
$editRow = $this->db->table('ipd_document_templates')
|
||||
->where('id', $editId)
|
||||
->get(1)
|
||||
->getRowArray() ?? [];
|
||||
}
|
||||
|
||||
$rows = $this->db->table('ipd_document_templates')
|
||||
->orderBy('form_no', 'ASC')
|
||||
->orderBy('id', 'ASC')
|
||||
->get()
|
||||
->getResultArray();
|
||||
|
||||
return view('Setting/Template/ipd_document_templates', [
|
||||
'rows' => $rows,
|
||||
'edit_row' => $editRow,
|
||||
'notice' => $notice,
|
||||
'notice_type' => $noticeType,
|
||||
]);
|
||||
}
|
||||
|
||||
public function ipd_document_template_delete(int $id)
|
||||
{
|
||||
if ($resp = $this->requireAnyPermission(['template.discharge'])) {
|
||||
return $resp;
|
||||
}
|
||||
|
||||
$id = (int) $id;
|
||||
if ($id > 0 && $this->db->tableExists('ipd_document_templates')) {
|
||||
$this->db->table('ipd_document_templates')->where('id', $id)->delete();
|
||||
}
|
||||
|
||||
return redirect()->to(base_url('setting/template/ipd_document_templates'));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,13 @@
|
|||
|
||||
function str_to_MysqlDate(string $strDate): string
|
||||
{
|
||||
$strDate = trim($strDate);
|
||||
|
||||
if ($strDate !== '') {
|
||||
if (preg_match('/^\d{4}-\d{2}-\d{2}$/', $strDate) === 1) {
|
||||
return $strDate;
|
||||
}
|
||||
|
||||
$date = explode('/', $strDate);
|
||||
if (count($date) === 3) {
|
||||
return $date[2] . '-' . $date[1] . '-' . $date[0];
|
||||
|
|
|
|||
|
|
@ -6,8 +6,9 @@ use CodeIgniter\Model;
|
|||
|
||||
class BedCategoryModel extends Model
|
||||
{
|
||||
protected $table = 'bed_category_master';
|
||||
protected $primaryKey = 'id';
|
||||
protected $table = 'bed_category_master';
|
||||
protected $primaryKey = 'id';
|
||||
protected $returnType = 'object';
|
||||
protected $allowedFields = [
|
||||
'category_code',
|
||||
'category_name',
|
||||
|
|
|
|||
|
|
@ -6,8 +6,9 @@ use CodeIgniter\Model;
|
|||
|
||||
class BedMasterModel extends Model
|
||||
{
|
||||
protected $table = 'bed_master';
|
||||
protected $table = 'bed_master';
|
||||
protected $primaryKey = 'id';
|
||||
protected $returnType = 'object';
|
||||
protected $allowedFields = [
|
||||
'bed_code',
|
||||
'bed_number',
|
||||
|
|
|
|||
|
|
@ -6,8 +6,9 @@ use CodeIgniter\Model;
|
|||
|
||||
class WardModel extends Model
|
||||
{
|
||||
protected $table = 'ward_master';
|
||||
protected $table = 'ward_master';
|
||||
protected $primaryKey = 'id';
|
||||
protected $returnType = 'object';
|
||||
protected $allowedFields = [
|
||||
'ward_code',
|
||||
'ward_name',
|
||||
|
|
@ -27,6 +28,11 @@ class WardModel extends Model
|
|||
'created_by',
|
||||
];
|
||||
|
||||
public function getAll(): array
|
||||
{
|
||||
return $this->orderBy('ward_name', 'ASC')->findAll();
|
||||
}
|
||||
|
||||
public function getAllActive(): array
|
||||
{
|
||||
return $this->where('status', 'active')
|
||||
|
|
|
|||
69
app/Views/Invoice/charges_invoice_list.php
Normal file
69
app/Views/Invoice/charges_invoice_list.php
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
<div class="card">
|
||||
<div class="card-header d-flex align-items-center justify-content-between flex-wrap gap-2">
|
||||
<h3 class="card-title mb-0">Charges Invoice List</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form class="row g-2 mb-3" onsubmit="event.preventDefault(); chargesInvoiceSearch();">
|
||||
<div class="col-md-6">
|
||||
<input type="text" class="form-control" id="charges_invoice_search" value="<?= esc($search ?? '') ?>" placeholder="Search by Invoice Code, Patient Code, Name, Mobile, Email">
|
||||
</div>
|
||||
<div class="col-md-6 d-flex gap-2">
|
||||
<button type="button" class="btn btn-primary" onclick="chargesInvoiceSearch()">Search</button>
|
||||
<button type="button" class="btn btn-light" onclick="load_form('<?= base_url('Invoice/chargeslist') ?>','Charges Invoice')">Reset</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped table-hover align-middle" id="chargesInvoiceTable">
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
<th>Invoice Code</th>
|
||||
<th>Patient</th>
|
||||
<th>Patient Code</th>
|
||||
<th>Date</th>
|
||||
<th>Mobile</th>
|
||||
<th>Type</th>
|
||||
<th>Amount</th>
|
||||
<th>Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach (($rows ?? []) as $row): ?>
|
||||
<?php
|
||||
$invType = ((int) ($row->insurance_id ?? 0) > 1) ? 'Org.' : 'Direct';
|
||||
$invDate = ! empty($row->inv_date) ? date('d-m-Y', strtotime((string) $row->inv_date)) : '-';
|
||||
?>
|
||||
<tr>
|
||||
<td><?= esc((string) ($row->invoice_code ?? '-')) ?></td>
|
||||
<td><?= esc((string) ($row->p_fname ?? '-')) ?></td>
|
||||
<td><?= esc((string) ($row->p_code ?? '-')) ?></td>
|
||||
<td><?= esc($invDate) ?></td>
|
||||
<td><?= esc((string) ($row->mphone1 ?? '-')) ?></td>
|
||||
<td><?= esc($invType) ?></td>
|
||||
<td><?= esc(number_format((float) ($row->net_amount ?? 0), 2, '.', '')) ?></td>
|
||||
<td>
|
||||
<button type="button" class="btn btn-outline-primary btn-sm" onclick="load_form('<?= base_url('billing/charges/show') ?>/<?= (int) ($row->inv_id ?? 0) ?>','Charges Invoice');">Open</button>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function chargesInvoiceSearch() {
|
||||
var q = (document.getElementById('charges_invoice_search') || {}).value || '';
|
||||
load_form('<?= base_url('Invoice/chargeslist') ?>?q=' + encodeURIComponent(q), 'Charges Invoice');
|
||||
}
|
||||
|
||||
(function() {
|
||||
if (window.jQuery && $.fn && $.fn.DataTable) {
|
||||
$('#chargesInvoiceTable').DataTable({
|
||||
pageLength: 25,
|
||||
order: [[0, 'desc']]
|
||||
});
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
69
app/Views/Invoice/opd_invoice_list.php
Normal file
69
app/Views/Invoice/opd_invoice_list.php
Normal file
|
|
@ -0,0 +1,69 @@
|
|||
<div class="card">
|
||||
<div class="card-header d-flex align-items-center justify-content-between flex-wrap gap-2">
|
||||
<h3 class="card-title mb-0">OPD Invoice List</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form class="row g-2 mb-3" onsubmit="event.preventDefault(); opdInvoiceSearch();">
|
||||
<div class="col-md-6">
|
||||
<input type="text" class="form-control" id="opd_invoice_search" value="<?= esc($search ?? '') ?>" placeholder="Search by OPD Code, Patient Code, Name, Mobile, Email">
|
||||
</div>
|
||||
<div class="col-md-6 d-flex gap-2">
|
||||
<button type="button" class="btn btn-primary" onclick="opdInvoiceSearch()">Search</button>
|
||||
<button type="button" class="btn btn-light" onclick="load_form('<?= base_url('Invoice/opdlist') ?>','OPD Invoice')">Reset</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped table-hover align-middle" id="opdInvoiceTable">
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
<th>OPD Code</th>
|
||||
<th>Patient</th>
|
||||
<th>Patient Code</th>
|
||||
<th>Date</th>
|
||||
<th>Doctor</th>
|
||||
<th>Mobile</th>
|
||||
<th>Type</th>
|
||||
<th>Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach (($rows ?? []) as $row): ?>
|
||||
<?php
|
||||
$invType = ((int) ($row->insurance_id ?? 0) > 1) ? 'Org.' : 'Direct';
|
||||
$opdDate = ! empty($row->apointment_date) ? date('d-m-Y', strtotime((string) $row->apointment_date)) : '-';
|
||||
?>
|
||||
<tr>
|
||||
<td><?= esc((string) ($row->opd_code ?? '-')) ?></td>
|
||||
<td><?= esc((string) ($row->P_name ?? '-')) ?></td>
|
||||
<td><?= esc((string) ($row->p_code ?? '-')) ?></td>
|
||||
<td><?= esc($opdDate) ?></td>
|
||||
<td><?= esc((string) ($row->doc_name ?? '-')) ?></td>
|
||||
<td><?= esc((string) ($row->mphone1 ?? '-')) ?></td>
|
||||
<td><?= esc($invType) ?></td>
|
||||
<td>
|
||||
<button type="button" class="btn btn-outline-primary btn-sm" onclick="load_form('<?= base_url('Opd/invoice') ?>/<?= (int) ($row->opd_id ?? 0) ?>','OPD Invoice');">Open</button>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
function opdInvoiceSearch() {
|
||||
var q = (document.getElementById('opd_invoice_search') || {}).value || '';
|
||||
load_form('<?= base_url('Invoice/opdlist') ?>?q=' + encodeURIComponent(q), 'OPD Invoice');
|
||||
}
|
||||
|
||||
(function() {
|
||||
if (window.jQuery && $.fn && $.fn.DataTable) {
|
||||
$('#opdInvoiceTable').DataTable({
|
||||
pageLength: 25,
|
||||
order: [[0, 'desc']]
|
||||
});
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
|
|
@ -1,10 +1,16 @@
|
|||
<div class="card">
|
||||
<div class="card-header d-flex align-items-center justify-content-between flex-wrap gap-2">
|
||||
<h3 class="card-title mb-0">Bed Master</h3>
|
||||
<button class="btn btn-light" type="button" onclick="load_form_div('<?= base_url('setting/admin/bed-management') ?>','maindiv','Bed Management');">
|
||||
<i class="bi bi-arrow-left"></i>
|
||||
Back
|
||||
</button>
|
||||
<div class="d-flex align-items-center gap-2">
|
||||
<button class="btn btn-outline-primary" type="button" onclick="load_form_div('<?= base_url('setting/admin/bed-status') ?>','maindiv','Bed Status');">
|
||||
<i class="bi bi-geo-alt"></i>
|
||||
Bed Status
|
||||
</button>
|
||||
<button class="btn btn-light" type="button" onclick="load_form_div('<?= base_url('setting/admin/bed-management') ?>','maindiv','Bed Management');">
|
||||
<i class="bi bi-arrow-left"></i>
|
||||
Back
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div id="bedAlert" class="alert alert-danger d-none"></div>
|
||||
|
|
@ -28,6 +34,9 @@
|
|||
<option value="<?= esc($ward->id ?? 0) ?>"><?= esc($ward->ward_name ?? '') ?></option>
|
||||
<?php } ?>
|
||||
</select>
|
||||
<div class="mt-1">
|
||||
<button type="button" class="btn btn-link btn-sm p-0" onclick="load_form_div('<?= base_url('setting/admin/wards') ?>','maindiv','Wards');">Manage Wards</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<label class="form-label">Category</label>
|
||||
|
|
|
|||
115
app/Views/Setting/Bed/bed_status_list.php
Normal file
115
app/Views/Setting/Bed/bed_status_list.php
Normal file
|
|
@ -0,0 +1,115 @@
|
|||
<div class="card">
|
||||
<div class="card-header d-flex align-items-center flex-wrap gap-2">
|
||||
<h3 class="card-title mb-0">Bed Status (IPD Location Finder)</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div class="row g-2 mb-2">
|
||||
<div class="col-md-3">
|
||||
<select class="form-select" id="filterDepartment">
|
||||
<option value="">All Department</option>
|
||||
<?php foreach (($departments ?? []) as $department): ?>
|
||||
<?php $label = trim((string) ($department->vName ?? '')); ?>
|
||||
<?php if ($label === '') {
|
||||
continue;
|
||||
} ?>
|
||||
<option value="<?= esc($label) ?>"><?= esc($label) ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<select class="form-select" id="filterWard">
|
||||
<option value="">All Wards</option>
|
||||
<?php foreach (($wards ?? []) as $ward): ?>
|
||||
<option value="<?= esc((string) ($ward->ward_name ?? '')) ?>"><?= esc((string) ($ward->ward_name ?? '')) ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped table-hover align-middle" id="bedStatusTable">
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
<th>IPD Code</th>
|
||||
<th>Patient Code</th>
|
||||
<th>Patient Name</th>
|
||||
<th>Mobile</th>
|
||||
<th>Department</th>
|
||||
<th>Ward</th>
|
||||
<th>Bed No</th>
|
||||
<th>Admit Date</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach (($rows ?? []) as $row): ?>
|
||||
<?php
|
||||
$fullName = trim((string) (($row->p_fname ?? '') . ' ' . ($row->p_lname ?? '')));
|
||||
if ($fullName === '') {
|
||||
$fullName = '-';
|
||||
}
|
||||
$mobile = trim((string) ($row->mphone1 ?? ''));
|
||||
if ($mobile === '' || $mobile === '0') {
|
||||
$mobile = trim((string) ($row->mphone2 ?? ''));
|
||||
}
|
||||
if ($mobile === '' || $mobile === '0') {
|
||||
$mobile = '-';
|
||||
}
|
||||
$bedNo = trim((string) ($row->bed_number ?? ''));
|
||||
if ($bedNo === '' || $bedNo === '0') {
|
||||
$bedNo = trim((string) ($row->bed_code ?? ''));
|
||||
}
|
||||
if ($bedNo === '') {
|
||||
$bedNo = '-';
|
||||
}
|
||||
$departmentName = trim((string) ($row->department_name ?? ''));
|
||||
if ($departmentName === '') {
|
||||
$departmentName = 'All Department';
|
||||
}
|
||||
$wardName = trim((string) ($row->ward_name ?? ''));
|
||||
if ($wardName === '') {
|
||||
$wardName = '-';
|
||||
}
|
||||
$admitDate = trim((string) ($row->register_date ?? ''));
|
||||
if ($admitDate === '') {
|
||||
$admitDate = '-';
|
||||
}
|
||||
?>
|
||||
<tr>
|
||||
<td><?= esc((string) ($row->ipd_code ?? '-')) ?></td>
|
||||
<td><?= esc((string) ($row->p_code ?? '-')) ?></td>
|
||||
<td><?= esc($fullName) ?></td>
|
||||
<td><?= esc($mobile) ?></td>
|
||||
<td><?= esc($departmentName) ?></td>
|
||||
<td><?= esc($wardName) ?></td>
|
||||
<td><?= esc($bedNo) ?></td>
|
||||
<td><?= esc($admitDate) ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
(function() {
|
||||
if (!window.jQuery || !$.fn || !$.fn.DataTable) {
|
||||
return;
|
||||
}
|
||||
|
||||
var table = $('#bedStatusTable').DataTable({
|
||||
order: [[0, 'desc']],
|
||||
pageLength: 25
|
||||
});
|
||||
|
||||
function bindFilter(selector, columnIndex) {
|
||||
var $select = $(selector);
|
||||
$select.on('change', function() {
|
||||
var val = $.fn.dataTable.util.escapeRegex($(this).val());
|
||||
table.column(columnIndex).search(val ? '^' + val + '$' : '', true, false).draw();
|
||||
});
|
||||
}
|
||||
|
||||
bindFilter('#filterDepartment', 4);
|
||||
bindFilter('#filterWard', 5);
|
||||
})();
|
||||
</script>
|
||||
143
app/Views/Setting/Bed/department_list.php
Normal file
143
app/Views/Setting/Bed/department_list.php
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
<div class="card">
|
||||
<div class="card-header d-flex align-items-center justify-content-between flex-wrap gap-2">
|
||||
<h3 class="card-title mb-0">Department Master</h3>
|
||||
<button class="btn btn-light" type="button" onclick="load_form_div('<?= base_url('setting/admin/bed-management') ?>','maindiv','Bed Management');">
|
||||
<i class="bi bi-arrow-left"></i>
|
||||
Back
|
||||
</button>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<?php if (($tableMissing ?? false) === true): ?>
|
||||
<div class="alert alert-danger">Department table (hc_department) is not available in this database.</div>
|
||||
<?php else: ?>
|
||||
<div id="departmentAlert" class="alert alert-danger d-none"></div>
|
||||
<form id="departmentForm">
|
||||
<?= csrf_field() ?>
|
||||
<input type="hidden" id="department_id" name="id" value="0">
|
||||
<div class="row g-3">
|
||||
<div class="col-md-5">
|
||||
<label class="form-label">Department Name</label>
|
||||
<input class="form-control" id="department_name" name="department_name" required>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<label class="form-label">Department Type ID</label>
|
||||
<input class="form-control" id="hc_type_id" name="hc_type_id" type="number" min="0">
|
||||
</div>
|
||||
<div class="col-md-4 d-flex align-items-end gap-2">
|
||||
<button class="btn btn-primary" type="submit">Save Department</button>
|
||||
<button class="btn btn-light" type="button" id="resetDepartment">Clear</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<hr/>
|
||||
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped table-hover align-middle" id="departmentTable">
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
<th>ID</th>
|
||||
<th>Name</th>
|
||||
<th>Type ID</th>
|
||||
<th>Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach (($departments ?? []) as $row) {
|
||||
$payload = json_encode($row);
|
||||
?>
|
||||
<tr>
|
||||
<td><?= esc($row->iId ?? 0) ?></td>
|
||||
<td><?= esc($row->vName ?? '') ?></td>
|
||||
<td><?= esc($row->hc_type_id ?? '') ?></td>
|
||||
<td>
|
||||
<button class="btn btn-outline-secondary btn-sm edit-department" data-item="<?= esc($payload, 'attr') ?>">Edit</button>
|
||||
<button class="btn btn-outline-danger btn-sm delete-department" data-id="<?= esc($row->iId ?? 0) ?>">Delete</button>
|
||||
</td>
|
||||
</tr>
|
||||
<?php } ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
(function() {
|
||||
var form = document.getElementById('departmentForm');
|
||||
var resetButton = document.getElementById('resetDepartment');
|
||||
var alertBox = document.getElementById('departmentAlert');
|
||||
|
||||
if (!form || !window.jQuery) {
|
||||
return;
|
||||
}
|
||||
|
||||
function showAlert(message) {
|
||||
alertBox.textContent = message;
|
||||
alertBox.classList.remove('d-none');
|
||||
}
|
||||
|
||||
function clearAlert() {
|
||||
alertBox.textContent = '';
|
||||
alertBox.classList.add('d-none');
|
||||
}
|
||||
|
||||
function clearForm() {
|
||||
form.reset();
|
||||
$('#department_id').val(0);
|
||||
clearAlert();
|
||||
}
|
||||
|
||||
resetButton.addEventListener('click', clearForm);
|
||||
|
||||
$(form).on('submit', function(event) {
|
||||
event.preventDefault();
|
||||
clearAlert();
|
||||
|
||||
$.post('<?= base_url('setting/admin/departments/save') ?>', $(form).serialize())
|
||||
.done(function(resp) {
|
||||
if (resp && resp.error_text) {
|
||||
showAlert(resp.error_text);
|
||||
return;
|
||||
}
|
||||
load_form_div('<?= base_url('setting/admin/departments') ?>', 'maindiv', 'Departments');
|
||||
})
|
||||
.fail(function() {
|
||||
showAlert('Request failed.');
|
||||
});
|
||||
});
|
||||
|
||||
$('.edit-department').on('click', function() {
|
||||
var item = $(this).data('item');
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
|
||||
$('#department_id').val(item.iId || 0);
|
||||
$('#department_name').val(item.vName || '');
|
||||
$('#hc_type_id').val(item.hc_type_id || '');
|
||||
});
|
||||
|
||||
$('.delete-department').on('click', function() {
|
||||
if (!confirm('Delete this department?')) {
|
||||
return;
|
||||
}
|
||||
|
||||
clearAlert();
|
||||
$.post('<?= base_url('setting/admin/departments/delete') ?>', {
|
||||
id: $(this).data('id'),
|
||||
'<?= csrf_token() ?>': $('input[name="<?= csrf_token() ?>"]').first().val() || '<?= csrf_hash() ?>'
|
||||
}).done(function(resp) {
|
||||
if (resp && resp.error_text) {
|
||||
showAlert(resp.error_text);
|
||||
return;
|
||||
}
|
||||
load_form_div('<?= base_url('setting/admin/departments') ?>', 'maindiv', 'Departments');
|
||||
});
|
||||
});
|
||||
|
||||
if (window.jQuery && $.fn && $.fn.DataTable) {
|
||||
$('#departmentTable').DataTable();
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
|
|
@ -10,6 +10,24 @@
|
|||
</div>
|
||||
|
||||
<div class="row g-3">
|
||||
<div class="col-6 col-md-3">
|
||||
<a class="admin-tile" href="javascript:load_form_div('<?= base_url('setting/admin/bed-status') ?>','maindiv','Bed Status');">
|
||||
<i class="bi bi-geo-alt"></i>
|
||||
<span>Bed Status</span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-6 col-md-3">
|
||||
<a class="admin-tile" href="javascript:load_form_div('<?= base_url('setting/admin/departments') ?>','maindiv','Departments');">
|
||||
<i class="bi bi-diagram-2"></i>
|
||||
<span>Departments</span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-6 col-md-3">
|
||||
<a class="admin-tile" href="javascript:load_form_div('<?= base_url('setting/admin/wards') ?>','maindiv','Wards');">
|
||||
<i class="bi bi-diagram-3"></i>
|
||||
<span>Wards</span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-6 col-md-3">
|
||||
<a class="admin-tile" href="javascript:load_form_div('<?= base_url('setting/admin/bed-categories') ?>','maindiv','Bed Categories');">
|
||||
<i class="bi bi-layers"></i>
|
||||
|
|
|
|||
271
app/Views/Setting/Bed/ward_list.php
Normal file
271
app/Views/Setting/Bed/ward_list.php
Normal file
|
|
@ -0,0 +1,271 @@
|
|||
<div class="card">
|
||||
<div class="card-header d-flex align-items-center justify-content-between flex-wrap gap-2">
|
||||
<h3 class="card-title mb-0">Ward Master</h3>
|
||||
<button class="btn btn-light" type="button" onclick="load_form_div('<?= base_url('setting/admin/bed-management') ?>','maindiv','Bed Management');">
|
||||
<i class="bi bi-arrow-left"></i>
|
||||
Back
|
||||
</button>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<div id="wardAlert" class="alert alert-danger d-none"></div>
|
||||
<form id="wardForm">
|
||||
<?= csrf_field() ?>
|
||||
<input type="hidden" id="ward_id" name="id" value="0">
|
||||
<div class="row g-3">
|
||||
<div class="col-md-3">
|
||||
<label class="form-label">Ward Code</label>
|
||||
<input class="form-control" id="ward_code" name="ward_code" required>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<label class="form-label">Ward Name</label>
|
||||
<input class="form-control" id="ward_name" name="ward_name" required>
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<label class="form-label">Department</label>
|
||||
<select class="form-select" id="department_id" name="department_id">
|
||||
<?php foreach (($departments ?? []) as $department) { ?>
|
||||
<option value="<?= esc($department->iId ?? 0) ?>"><?= esc($department->vName ?? '') ?></option>
|
||||
<?php } ?>
|
||||
</select>
|
||||
<div class="mt-1">
|
||||
<button type="button" class="btn btn-link btn-sm p-0" onclick="load_form_div('<?= base_url('setting/admin/departments') ?>','maindiv','Departments');">Manage Departments</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<label class="form-label">Floor</label>
|
||||
<input class="form-control" id="floor_number" name="floor_number" type="number">
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<label class="form-label">Capacity</label>
|
||||
<input class="form-control" id="total_capacity" name="total_capacity" type="number" min="0" value="0">
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<label class="form-label">Ward Type</label>
|
||||
<select class="form-select" id="ward_type" name="ward_type">
|
||||
<option value="General">General</option>
|
||||
<option value="Private">Private</option>
|
||||
<option value="Semi-Private">Semi-Private</option>
|
||||
<option value="Deluxe">Deluxe</option>
|
||||
<option value="ICU">ICU</option>
|
||||
<option value="NICU">NICU</option>
|
||||
<option value="PICU">PICU</option>
|
||||
<option value="HDU">HDU</option>
|
||||
<option value="ICCU">ICCU</option>
|
||||
<option value="CCU">CCU</option>
|
||||
<option value="Emergency">Emergency</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<label class="form-label">Gender Type</label>
|
||||
<select class="form-select" id="gender_type" name="gender_type">
|
||||
<option value="unisex">Unisex</option>
|
||||
<option value="male">Male</option>
|
||||
<option value="female">Female</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<label class="form-label">Ward Category</label>
|
||||
<select class="form-select" id="ward_category" name="ward_category">
|
||||
<option value="adult">Adult</option>
|
||||
<option value="pediatric">Pediatric</option>
|
||||
<option value="maternity">Maternity</option>
|
||||
<option value="isolation">Isolation</option>
|
||||
<option value="surgical">Surgical</option>
|
||||
<option value="medical">Medical</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<label class="form-label">Status</label>
|
||||
<select class="form-select" id="status" name="status">
|
||||
<option value="active">Active</option>
|
||||
<option value="inactive">Inactive</option>
|
||||
<option value="under_maintenance">Under Maintenance</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label">Remarks</label>
|
||||
<input class="form-control" id="remarks" name="remarks">
|
||||
</div>
|
||||
<div class="col-md-6 d-flex align-items-end gap-3">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" id="has_oxygen" name="has_oxygen">
|
||||
<label class="form-check-label" for="has_oxygen">Oxygen</label>
|
||||
</div>
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" id="has_suction" name="has_suction">
|
||||
<label class="form-check-label" for="has_suction">Suction</label>
|
||||
</div>
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" id="has_monitor" name="has_monitor">
|
||||
<label class="form-check-label" for="has_monitor">Monitor</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-12 d-flex gap-2">
|
||||
<button class="btn btn-primary" type="submit">Save Ward</button>
|
||||
<button class="btn btn-light" type="button" id="resetWard">Clear</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<hr/>
|
||||
|
||||
<div class="row g-2 mb-2">
|
||||
<div class="col-md-3">
|
||||
<select class="form-select" id="filterWardType">
|
||||
<option value="">All Types</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<select class="form-select" id="filterWardStatus">
|
||||
<option value="">All Status</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped table-hover align-middle" id="wardTable">
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
<th>Code</th>
|
||||
<th>Name</th>
|
||||
<th>Department</th>
|
||||
<th>Type</th>
|
||||
<th>Capacity</th>
|
||||
<th>Status</th>
|
||||
<th>Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach (($wards ?? []) as $row) {
|
||||
$payload = json_encode($row);
|
||||
?>
|
||||
<tr>
|
||||
<td><?= esc($row->ward_code ?? '') ?></td>
|
||||
<td><?= esc($row->ward_name ?? '') ?></td>
|
||||
<td><?= esc($row->department_name ?? 'All Department') ?></td>
|
||||
<td><?= esc($row->ward_type ?? '') ?></td>
|
||||
<td><?= esc($row->total_capacity ?? 0) ?></td>
|
||||
<td><?= esc($row->status ?? '') ?></td>
|
||||
<td>
|
||||
<button class="btn btn-outline-secondary btn-sm edit-ward" data-item="<?= esc($payload, 'attr') ?>">Edit</button>
|
||||
<button class="btn btn-outline-danger btn-sm delete-ward" data-id="<?= esc($row->id ?? 0) ?>">Delete</button>
|
||||
</td>
|
||||
</tr>
|
||||
<?php } ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
(function() {
|
||||
var form = document.getElementById('wardForm');
|
||||
var resetButton = document.getElementById('resetWard');
|
||||
var alertBox = document.getElementById('wardAlert');
|
||||
|
||||
if (!form || !window.jQuery) {
|
||||
return;
|
||||
}
|
||||
|
||||
function showAlert(message) {
|
||||
alertBox.textContent = message;
|
||||
alertBox.classList.remove('d-none');
|
||||
}
|
||||
|
||||
function clearAlert() {
|
||||
alertBox.textContent = '';
|
||||
alertBox.classList.add('d-none');
|
||||
}
|
||||
|
||||
function clearForm() {
|
||||
form.reset();
|
||||
$('#ward_id').val(0);
|
||||
$('#total_capacity').val(0);
|
||||
clearAlert();
|
||||
}
|
||||
|
||||
resetButton.addEventListener('click', clearForm);
|
||||
|
||||
$(form).on('submit', function(event) {
|
||||
event.preventDefault();
|
||||
clearAlert();
|
||||
|
||||
$.post('<?= base_url('setting/admin/wards/save') ?>', $(form).serialize())
|
||||
.done(function(resp) {
|
||||
if (resp && resp.error_text) {
|
||||
showAlert(resp.error_text);
|
||||
return;
|
||||
}
|
||||
load_form_div('<?= base_url('setting/admin/wards') ?>', 'maindiv', 'Wards');
|
||||
})
|
||||
.fail(function() {
|
||||
showAlert('Request failed.');
|
||||
});
|
||||
});
|
||||
|
||||
$('.edit-ward').on('click', function() {
|
||||
var item = $(this).data('item');
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
|
||||
$('#ward_id').val(item.id || 0);
|
||||
$('#ward_code').val(item.ward_code || '');
|
||||
$('#ward_name').val(item.ward_name || '');
|
||||
$('#department_id').val(item.department_id !== undefined ? item.department_id : 0);
|
||||
$('#floor_number').val(item.floor_number || '');
|
||||
$('#total_capacity').val(item.total_capacity || 0);
|
||||
$('#ward_type').val(item.ward_type || 'General');
|
||||
$('#gender_type').val(item.gender_type || 'unisex');
|
||||
$('#ward_category').val(item.ward_category || 'adult');
|
||||
$('#status').val(item.status || 'active');
|
||||
$('#remarks').val(item.remarks || '');
|
||||
$('#has_oxygen').prop('checked', String(item.has_oxygen) === '1');
|
||||
$('#has_suction').prop('checked', String(item.has_suction) === '1');
|
||||
$('#has_monitor').prop('checked', String(item.has_monitor) === '1');
|
||||
});
|
||||
|
||||
$('.delete-ward').on('click', function() {
|
||||
if (!confirm('Delete this ward?')) {
|
||||
return;
|
||||
}
|
||||
|
||||
clearAlert();
|
||||
$.post('<?= base_url('setting/admin/wards/delete') ?>', {
|
||||
id: $(this).data('id'),
|
||||
'<?= csrf_token() ?>': $('input[name="<?= csrf_token() ?>"]').first().val() || '<?= csrf_hash() ?>'
|
||||
}).done(function(resp) {
|
||||
if (resp && resp.error_text) {
|
||||
showAlert(resp.error_text);
|
||||
return;
|
||||
}
|
||||
load_form_div('<?= base_url('setting/admin/wards') ?>', 'maindiv', 'Wards');
|
||||
});
|
||||
});
|
||||
|
||||
if (window.jQuery && $.fn && $.fn.DataTable) {
|
||||
var table = $('#wardTable').DataTable();
|
||||
|
||||
function initFilter(selectId, columnIndex) {
|
||||
var select = $(selectId);
|
||||
if (!select.length) {
|
||||
return;
|
||||
}
|
||||
var column = table.column(columnIndex);
|
||||
var values = column.data().unique().sort();
|
||||
values.each(function(d) {
|
||||
if (d !== null && d !== '') {
|
||||
select.append('<option value="' + d + '">' + d + '</option>');
|
||||
}
|
||||
});
|
||||
select.on('change', function() {
|
||||
var val = $.fn.dataTable.util.escapeRegex($(this).val());
|
||||
column.search(val ? '^' + val + '$' : '', true, false).draw();
|
||||
});
|
||||
}
|
||||
|
||||
initFilter('#filterWardType', 3);
|
||||
initFilter('#filterWardStatus', 5);
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
|
|
@ -11,6 +11,13 @@
|
|||
<div class="card-body">
|
||||
<?php $errors = $errors ?? session('errors'); ?>
|
||||
<?php $formData = $formData ?? []; ?>
|
||||
<?php
|
||||
$doctorDobValue = trim((string) ($formData['datepicker_dob'] ?? ''));
|
||||
if ($doctorDobValue !== '' && preg_match('/^\d{2}\/\d{2}\/\d{4}$/', $doctorDobValue) === 1) {
|
||||
[$dobDay, $dobMonth, $dobYear] = explode('/', $doctorDobValue);
|
||||
$doctorDobValue = $dobYear . '-' . $dobMonth . '-' . $dobDay;
|
||||
}
|
||||
?>
|
||||
<?php if (! empty($errors)) : ?>
|
||||
<div class="alert alert-danger">
|
||||
<?php foreach ((array) $errors as $error) : ?>
|
||||
|
|
@ -61,7 +68,7 @@
|
|||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label">Date of Birth</label>
|
||||
<input class="form-control datepicker" name="datepicker_dob" type="text" value="<?= esc($formData['datepicker_dob'] ?? '') ?>">
|
||||
<input class="form-control" name="datepicker_dob" type="date" value="<?= esc($doctorDobValue) ?>">
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
|
|
|
|||
|
|
@ -21,6 +21,12 @@ if (!empty($data) && !empty($data[0])) {
|
|||
}
|
||||
}
|
||||
?>
|
||||
<?php
|
||||
$doctorDobValue = '';
|
||||
if (!empty($data) && !empty($data[0]) && !empty($data[0]->dob)) {
|
||||
$doctorDobValue = trim((string) $data[0]->dob);
|
||||
}
|
||||
?>
|
||||
<?php if (! empty($data)) : ?>
|
||||
<div class="card">
|
||||
<div class="card-header d-flex align-items-center justify-content-between flex-wrap gap-2">
|
||||
|
|
@ -77,7 +83,7 @@ if (!empty($data) && !empty($data[0])) {
|
|||
</div>
|
||||
<div class="col-md-3">
|
||||
<label class="form-label">Date of Birth</label>
|
||||
<input class="form-control datepicker" name="datepicker_dob" value="<?= esc(MysqlDate_to_str($data[0]->dob ?? '')) ?>" type="text" />
|
||||
<input class="form-control" name="datepicker_dob" value="<?= esc($doctorDobValue) ?>" type="date" />
|
||||
</div>
|
||||
</div>
|
||||
<div class="row g-3 mt-1">
|
||||
|
|
|
|||
|
|
@ -206,6 +206,12 @@ $hasTemplateAccess = $canPathology || $canUltrasound || $canXray || $canCt || $c
|
|||
<span>IPD Discharge Template</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/template/ipd_document_templates') ?>','maindiv','IPD Document Master');">
|
||||
<span class="tile-icon"><i class="bi bi-file-earmark-richtext"></i></span>
|
||||
<span>IPD Document Master</span>
|
||||
</a>
|
||||
</div>
|
||||
<?php } ?>
|
||||
|
||||
<?php if ($canDiagnosisPrintTemplate) { ?>
|
||||
|
|
|
|||
173
app/Views/Setting/Template/ipd_document_templates.php
Normal file
173
app/Views/Setting/Template/ipd_document_templates.php
Normal file
|
|
@ -0,0 +1,173 @@
|
|||
<?php
|
||||
$rows = $rows ?? [];
|
||||
$edit = $edit_row ?? [];
|
||||
$notice = (string) ($notice ?? '');
|
||||
$noticeType = (string) ($notice_type ?? 'success');
|
||||
|
||||
$editId = (int) ($edit['id'] ?? 0);
|
||||
$formNo = (int) ($edit['form_no'] ?? 1);
|
||||
$templateName = (string) ($edit['template_name'] ?? '');
|
||||
$templateHtml = (string) ($edit['template_html'] ?? '<h3>{{FORM_TITLE}}</h3><p>{{PATIENT_NAME}}</p>');
|
||||
$status = (int) ($edit['status'] ?? 1);
|
||||
|
||||
$formMap = [
|
||||
1 => 'Print Face Form',
|
||||
3 => 'Self Declaration Form',
|
||||
5 => 'Admission Form',
|
||||
8 => 'Progress Notes',
|
||||
9 => 'Fluid In / Out',
|
||||
10 => 'Sticker [2 x 6]',
|
||||
11 => 'Sticker [2 x 8]',
|
||||
];
|
||||
?>
|
||||
|
||||
<section class="content">
|
||||
<div class="card border-0 shadow-sm">
|
||||
<div class="card-header bg-light d-flex justify-content-between align-items-center">
|
||||
<h6 class="mb-0">IPD Document Master</h6>
|
||||
<a class="btn btn-sm btn-outline-secondary" href="javascript:load_form_div('<?= base_url('setting/template/ipd_document_templates') ?>','maindiv','IPD Document Master');">Reset</a>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<?php if ($notice !== ''): ?>
|
||||
<div class="alert alert-<?= esc($noticeType) ?> py-2 mb-3"><?= esc($notice) ?></div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="alert alert-info py-2 small">
|
||||
Placeholders: <code>{{FORM_TITLE}}</code>, <code>{{HOSPITAL_NAME}}</code>, <code>{{HOSPITAL_ADDRESS}}</code>,
|
||||
<code>{{PATIENT_NAME}}</code>, <code>{{AGE}}</code>, <code>{{GENDER}}</code>, <code>{{AGE_GENDER}}</code>, <code>{{UHID}}</code>,
|
||||
<code>{{IPD_CODE}}</code>, <code>{{ADMIT_DATE}}</code>, <code>{{DOCTORS}}</code>, <code>{{INSURANCE_NAME}}</code>,
|
||||
<code>{{CURRENT_DATE}}</code>, <code>{{CURRENT_DATETIME}}</code>.
|
||||
</div>
|
||||
|
||||
<div class="alert alert-warning py-2 small">
|
||||
Local-language design supported. You can copy HTML blocks from old HMS files under <strong>old_code_ci3/views/IPD_Format</strong> and adapt them here.
|
||||
</div>
|
||||
|
||||
<form method="post" action="<?= base_url('setting/template/ipd_document_templates') ?>" class="mb-4" id="ipd_document_template_form">
|
||||
<?= csrf_field() ?>
|
||||
<input type="hidden" name="id" value="<?= $editId ?>">
|
||||
|
||||
<div class="row g-2">
|
||||
<div class="col-md-3">
|
||||
<label class="form-label small">Form</label>
|
||||
<select name="form_no" class="form-select form-select-sm" required>
|
||||
<?php foreach ($formMap as $id => $label): ?>
|
||||
<option value="<?= (int) $id ?>" <?= $formNo === (int) $id ? 'selected' : '' ?>><?= (int) $id ?> - <?= esc($label) ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<label class="form-label small">Template Name</label>
|
||||
<input type="text" name="template_name" class="form-control form-control-sm" value="<?= esc($templateName) ?>" required>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<label class="form-label small">Status</label>
|
||||
<select name="status" class="form-select form-select-sm">
|
||||
<option value="1" <?= $status === 1 ? 'selected' : '' ?>>Active</option>
|
||||
<option value="0" <?= $status === 0 ? 'selected' : '' ?>>Inactive</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-12">
|
||||
<label class="form-label small">Template HTML</label>
|
||||
<textarea name="template_html" id="ipd_document_template_editor" rows="12" class="form-control" required><?= esc($templateHtml) ?></textarea>
|
||||
<small class="text-muted">Use Source mode for raw HTML from legacy forms.</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-3 d-flex gap-2">
|
||||
<button type="submit" class="btn btn-primary btn-sm"><?= $editId > 0 ? 'Update Template' : 'Create Template' ?></button>
|
||||
<?php if ($editId > 0): ?>
|
||||
<a class="btn btn-outline-secondary btn-sm" href="javascript:load_form_div('<?= base_url('setting/template/ipd_document_templates') ?>','maindiv','IPD Document Master');">Cancel Edit</a>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div class="table-responsive">
|
||||
<table class="table table-sm table-bordered align-middle">
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
<th style="width:60px;">ID</th>
|
||||
<th style="width:140px;">Form</th>
|
||||
<th>Template Name</th>
|
||||
<th style="width:90px;">Status</th>
|
||||
<th style="width:180px;">Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php if (empty($rows)): ?>
|
||||
<tr><td colspan="5" class="text-center text-muted">No templates found.</td></tr>
|
||||
<?php else: ?>
|
||||
<?php foreach ($rows as $row): ?>
|
||||
<?php $fNo = (int) ($row['form_no'] ?? 0); ?>
|
||||
<tr>
|
||||
<td><?= (int) ($row['id'] ?? 0) ?></td>
|
||||
<td><?= $fNo ?> - <?= esc($formMap[$fNo] ?? 'Unknown') ?></td>
|
||||
<td><?= esc((string) ($row['template_name'] ?? '')) ?></td>
|
||||
<td><?= (int) ($row['status'] ?? 0) === 1 ? 'Active' : 'Inactive' ?></td>
|
||||
<td>
|
||||
<a class="btn btn-outline-primary btn-sm" href="javascript:load_form_div('<?= base_url('setting/template/ipd_document_templates?edit=' . (int) ($row['id'] ?? 0)) ?>','maindiv','IPD Document Master');">Edit</a>
|
||||
<a class="btn btn-outline-danger btn-sm" href="javascript:if(confirm('Delete this template?')) load_form_div('<?= base_url('setting/template/ipd_document_templates/delete/' . (int) ($row['id'] ?? 0)) ?>','maindiv','IPD Document Master');">Delete</a>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
<?php endif; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<script>
|
||||
(function () {
|
||||
var form = document.getElementById('ipd_document_template_form');
|
||||
var editorFieldId = 'ipd_document_template_editor';
|
||||
|
||||
function initEditor() {
|
||||
if (!window.CKEDITOR) {
|
||||
return;
|
||||
}
|
||||
|
||||
CKEDITOR.config.versionCheck = false;
|
||||
CKEDITOR.config.removePlugins = '';
|
||||
|
||||
if (CKEDITOR.instances[editorFieldId]) {
|
||||
CKEDITOR.instances[editorFieldId].destroy(true);
|
||||
}
|
||||
|
||||
if (document.getElementById(editorFieldId)) {
|
||||
CKEDITOR.replace(editorFieldId, {
|
||||
height: 420,
|
||||
toolbar: [
|
||||
{ name: 'document', items: ['Source'] },
|
||||
{ name: 'clipboard', items: ['Undo', 'Redo'] },
|
||||
{ name: 'basicstyles', items: ['Bold', 'Italic', 'Underline', 'RemoveFormat'] },
|
||||
{ name: 'paragraph', items: ['NumberedList', 'BulletedList', 'Outdent', 'Indent', 'Blockquote'] },
|
||||
{ name: 'links', items: ['Link', 'Unlink'] },
|
||||
{ name: 'insert', items: ['Table', 'HorizontalRule', 'SpecialChar'] },
|
||||
{ name: 'styles', items: ['Format', 'Font', 'FontSize'] },
|
||||
{ name: 'colors', items: ['TextColor', 'BGColor'] },
|
||||
{ name: 'tools', items: ['Maximize'] }
|
||||
]
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function syncEditor() {
|
||||
if (!window.CKEDITOR) {
|
||||
return;
|
||||
}
|
||||
if (CKEDITOR.instances[editorFieldId]) {
|
||||
CKEDITOR.instances[editorFieldId].updateElement();
|
||||
}
|
||||
}
|
||||
|
||||
initEditor();
|
||||
|
||||
if (form) {
|
||||
form.addEventListener('submit', function () {
|
||||
syncEditor();
|
||||
});
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
264
app/Views/billing/ipd/ipd_form_print.php
Normal file
264
app/Views/billing/ipd/ipd_form_print.php
Normal file
|
|
@ -0,0 +1,264 @@
|
|||
<?php
|
||||
$formNo = (int) ($form_no ?? 1);
|
||||
$formMeta = is_array($form_meta ?? null) ? $form_meta : ['title' => 'IPD Form'];
|
||||
$ipd = $ipd_info ?? null;
|
||||
$person = $person_info ?? null;
|
||||
$doctorList = is_array($doctor_names ?? null) ? $doctor_names : [];
|
||||
$doctorText = ! empty($doctorList) ? implode(', ', $doctorList) : '-';
|
||||
$insuranceText = trim((string) ($insurance_name ?? ''));
|
||||
$hospitalName = trim((string) ($hospital_name ?? 'Hospital'));
|
||||
$hospitalAddress = trim((string) ($hospital_address ?? ''));
|
||||
$generatedAt = (string) ($generated_at ?? date('d-m-Y h:i A'));
|
||||
|
||||
$patientName = trim((string) (($person->title ?? '') . ' ' . ($person->p_fname ?? '')));
|
||||
if ($patientName === '') {
|
||||
$patientName = '-';
|
||||
}
|
||||
$patientAge = (string) ($person->age ?? '-');
|
||||
$patientGender = (string) ($person->xgender ?? '-');
|
||||
$patientCode = (string) ($person->p_code ?? '-');
|
||||
$ipdCode = (string) ($ipd->ipd_code ?? '-');
|
||||
$admitDate = (string) ($ipd->str_register_date ?? '');
|
||||
if ($admitDate === '') {
|
||||
$admitDate = (string) ($ipd->register_date ?? '-');
|
||||
}
|
||||
?>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<style>
|
||||
body {
|
||||
font-family: DejaVu Sans, sans-serif;
|
||||
font-size: 11px;
|
||||
color: #111;
|
||||
line-height: 1.35;
|
||||
}
|
||||
|
||||
.doc-header {
|
||||
border-bottom: 1px solid #999;
|
||||
margin-bottom: 8px;
|
||||
padding-bottom: 6px;
|
||||
}
|
||||
|
||||
.doc-title {
|
||||
font-size: 16px;
|
||||
font-weight: 700;
|
||||
margin: 0 0 2px;
|
||||
}
|
||||
|
||||
.doc-subtitle {
|
||||
margin: 0;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.meta-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.meta-table td {
|
||||
border: 1px solid #bbb;
|
||||
padding: 4px 6px;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
margin: 10px 0 6px;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.grid-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
.grid-table th,
|
||||
.grid-table td {
|
||||
border: 1px solid #888;
|
||||
padding: 4px;
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.spacer-row td {
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
.sign-row {
|
||||
margin-top: 20px;
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
.sign-row td {
|
||||
width: 50%;
|
||||
padding-top: 20px;
|
||||
font-size: 10px;
|
||||
}
|
||||
|
||||
.sticker-wrap {
|
||||
border: 1px dashed #444;
|
||||
padding: 4px;
|
||||
margin: 0;
|
||||
page-break-inside: avoid;
|
||||
}
|
||||
|
||||
.sticker-title {
|
||||
margin: 0 0 3px;
|
||||
font-size: 11px;
|
||||
font-weight: 700;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.tiny {
|
||||
font-size: 9px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<?php if ($formNo === 10 || $formNo === 11) : ?>
|
||||
<div class="sticker-wrap">
|
||||
<p class="sticker-title"><?= esc($hospitalName) ?></p>
|
||||
<div class="tiny">
|
||||
<?php if ($hospitalAddress !== '') : ?>
|
||||
<div><?= esc($hospitalAddress) ?></div>
|
||||
<?php endif; ?>
|
||||
<div><strong>Patient:</strong> <?= esc($patientName) ?></div>
|
||||
<div><strong>Age/Gender:</strong> <?= esc($patientAge) ?> / <?= esc($patientGender) ?></div>
|
||||
<div><strong>UHID:</strong> <?= esc($patientCode) ?></div>
|
||||
<div><strong>IPD:</strong> <?= esc($ipdCode) ?></div>
|
||||
<div><strong>Doctor:</strong> <?= esc($doctorText) ?></div>
|
||||
<div><strong>Admit:</strong> <?= esc($admitDate) ?></div>
|
||||
<?php if ($insuranceText !== '') : ?>
|
||||
<div><strong>Insurance:</strong> <?= esc($insuranceText) ?></div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php else : ?>
|
||||
<div class="doc-header">
|
||||
<p class="doc-title"><?= esc($hospitalName) ?></p>
|
||||
<?php if ($hospitalAddress !== '') : ?>
|
||||
<p class="doc-subtitle"><?= esc($hospitalAddress) ?></p>
|
||||
<?php endif; ?>
|
||||
<p class="doc-subtitle"><strong><?= esc((string) ($formMeta['title'] ?? 'IPD Form')) ?></strong></p>
|
||||
</div>
|
||||
|
||||
<table class="meta-table">
|
||||
<tr>
|
||||
<td><strong>Patient Name:</strong> <?= esc($patientName) ?></td>
|
||||
<td><strong>Age / Gender:</strong> <?= esc($patientAge) ?> / <?= esc($patientGender) ?></td>
|
||||
<td><strong>UHID:</strong> <?= esc($patientCode) ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><strong>IPD Code:</strong> <?= esc($ipdCode) ?></td>
|
||||
<td><strong>Date of Admission:</strong> <?= esc($admitDate) ?></td>
|
||||
<td><strong>Doctor:</strong> <?= esc($doctorText) ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="3">
|
||||
<strong>Insurance:</strong> <?= esc($insuranceText !== '' ? $insuranceText : 'Direct') ?>
|
||||
<span style="float:right;"><strong>Generated:</strong> <?= esc($generatedAt) ?></span>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
<?php if ($formNo === 1) : ?>
|
||||
<div class="section-title">Patient Consent</div>
|
||||
<p>
|
||||
I willingly agree for treatment, examination, consultation, investigations, medication, and medically indicated procedures during this IPD admission.
|
||||
I confirm that the information shared with the treating team is true and complete to the best of my knowledge.
|
||||
</p>
|
||||
<p>
|
||||
I understand that the hospital may take emergency decisions in the patient's best interest when immediate care is required.
|
||||
I also agree to follow hospital rules regarding safety, infection control, and billing process.
|
||||
</p>
|
||||
<table class="sign-row">
|
||||
<tr>
|
||||
<td>Patient / Attendant Signature: ____________________</td>
|
||||
<td style="text-align:right;">Hospital Representative: ____________________</td>
|
||||
</tr>
|
||||
</table>
|
||||
<?php elseif ($formNo === 3) : ?>
|
||||
<div class="section-title">Self Declaration</div>
|
||||
<p>
|
||||
I, ____________________, declare that patient <?= esc($patientName) ?> is admitted under IPD code <?= esc($ipdCode) ?>
|
||||
on date <?= esc($admitDate) ?>.
|
||||
<?php if ($insuranceText !== '') : ?>
|
||||
The patient is covered under insurance provider <?= esc($insuranceText) ?>.
|
||||
<?php else : ?>
|
||||
This admission is under self / direct payment category.
|
||||
<?php endif; ?>
|
||||
</p>
|
||||
<p>
|
||||
I confirm that all submitted details and documents are genuine and I will remain responsible for any differences in authorization, exclusions, or final bill settlement.
|
||||
</p>
|
||||
<table class="sign-row">
|
||||
<tr>
|
||||
<td>Declarant Signature: ____________________</td>
|
||||
<td style="text-align:right;">Date: ____________________</td>
|
||||
</tr>
|
||||
</table>
|
||||
<?php elseif ($formNo === 5) : ?>
|
||||
<div class="section-title">Admission Assessment</div>
|
||||
<table class="grid-table">
|
||||
<tr><th style="width:35%;">Assessment Item</th><th>Observation</th></tr>
|
||||
<tr class="spacer-row"><td>Chief Complaint</td><td></td></tr>
|
||||
<tr class="spacer-row"><td>History of Present Illness</td><td></td></tr>
|
||||
<tr class="spacer-row"><td>Past Medical / Surgical History</td><td></td></tr>
|
||||
<tr class="spacer-row"><td>Allergy History</td><td></td></tr>
|
||||
<tr class="spacer-row"><td>Medication History</td><td></td></tr>
|
||||
<tr class="spacer-row"><td>Physical Examination</td><td></td></tr>
|
||||
<tr class="spacer-row"><td>Provisional Diagnosis</td><td></td></tr>
|
||||
<tr class="spacer-row"><td>Initial Plan</td><td></td></tr>
|
||||
</table>
|
||||
<?php elseif ($formNo === 8) : ?>
|
||||
<div class="section-title">Progress Notes and Doctor Order</div>
|
||||
<table class="grid-table">
|
||||
<tr>
|
||||
<th style="width:14%;">Date</th>
|
||||
<th style="width:14%;">Time</th>
|
||||
<th>Progress Notes / Orders</th>
|
||||
<th style="width:18%;">Doctor Sign</th>
|
||||
</tr>
|
||||
<?php for ($i = 0; $i < 18; $i++) : ?>
|
||||
<tr class="spacer-row">
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<?php endfor; ?>
|
||||
</table>
|
||||
<?php elseif ($formNo === 9) : ?>
|
||||
<div class="section-title">Fluid In / Out</div>
|
||||
<table class="grid-table">
|
||||
<tr>
|
||||
<th style="width:10%;">S.No.</th>
|
||||
<th style="width:20%;">Date / Time</th>
|
||||
<th style="width:20%;">Fluid In (ml)</th>
|
||||
<th style="width:20%;">Fluid Out (ml)</th>
|
||||
<th>Remark</th>
|
||||
</tr>
|
||||
<?php for ($i = 1; $i <= 24; $i++) : ?>
|
||||
<tr class="spacer-row">
|
||||
<td style="text-align:center;"><?= $i ?></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<?php endfor; ?>
|
||||
<tr>
|
||||
<td colspan="2" style="text-align:right;"><strong>Total</strong></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</table>
|
||||
<?php endif; ?>
|
||||
<?php endif; ?>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -180,6 +180,9 @@ if ($person) {
|
|||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link" data-bs-toggle="tab" data-bs-target="#tab_discharge" data-url="<?= site_url('billing/ipd/panel/' . (int) ($ipd->id ?? 0) . '/tab/discharge-process') ?>" type="button" role="tab">Discharge Process</button>
|
||||
</li>
|
||||
<li class="nav-item" role="presentation">
|
||||
<button class="nav-link" data-bs-toggle="tab" data-bs-target="#tab_documents" data-url="<?= site_url('billing/ipd/panel/' . (int) ($ipd->id ?? 0) . '/tab/documents') ?>" type="button" role="tab">Documents</button>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="tab-content">
|
||||
<div class="tab-pane fade show active" id="tab_admission" role="tabpanel">
|
||||
|
|
@ -209,6 +212,9 @@ if ($person) {
|
|||
<div class="tab-pane fade" id="tab_discharge" role="tabpanel">
|
||||
<div class="ipd-tab-panel" id="tab_discharge_content">Loading...</div>
|
||||
</div>
|
||||
<div class="tab-pane fade" id="tab_documents" role="tabpanel">
|
||||
<div class="ipd-tab-panel" id="tab_documents_content">Loading...</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
53
app/Views/billing/ipd/panel_documents.php
Normal file
53
app/Views/billing/ipd/panel_documents.php
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
<?php
|
||||
$ipdId = (int) ($ipd_id ?? 0);
|
||||
$ipdCode = (string) ($ipd_info->ipd_code ?? ('IPD-' . $ipdId));
|
||||
|
||||
$documents = [
|
||||
['id' => 1, 'label' => 'Print Face Form'],
|
||||
['id' => 5, 'label' => 'Admission Form'],
|
||||
['id' => 10, 'label' => 'Sticker [2 x 6]'],
|
||||
['id' => 11, 'label' => 'Sticker [2 x 8]'],
|
||||
['id' => 8, 'label' => 'Progress Notes'],
|
||||
['id' => 9, 'label' => 'Fluid In / Out'],
|
||||
['id' => 3, 'label' => 'Self Declaration Form'],
|
||||
];
|
||||
?>
|
||||
|
||||
<div class="card border-0 shadow-sm">
|
||||
<div class="card-body">
|
||||
<div class="d-flex flex-wrap justify-content-between align-items-center mb-3">
|
||||
<h6 class="mb-0">Pre-Print Documents</h6>
|
||||
<div class="d-flex align-items-center gap-2">
|
||||
<small class="text-muted">IPD: <?= esc($ipdCode) ?></small>
|
||||
<button type="button" class="btn btn-sm btn-outline-secondary" onclick="load_form_div('<?= base_url('setting/template/ipd_document_templates') ?>','maindiv','IPD Document Master');">
|
||||
<i class="bi bi-pencil-square"></i> Document Master
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="table-responsive">
|
||||
<table class="table table-sm table-striped align-middle mb-0">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 80px;">Form ID</th>
|
||||
<th>Document</th>
|
||||
<th style="width: 170px;" class="text-end">Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($documents as $document) : ?>
|
||||
<tr>
|
||||
<td><?= (int) $document['id'] ?></td>
|
||||
<td><?= esc($document['label']) ?></td>
|
||||
<td class="text-end">
|
||||
<a class="btn btn-sm btn-outline-primary" target="_blank" href="<?= site_url('IpdNew/show_ipd_form/' . $ipdId . '/' . (int) $document['id']) ?>">
|
||||
<i class="bi bi-printer"></i> Print
|
||||
</a>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -1,9 +1,16 @@
|
|||
<?php
|
||||
$canEdit = false;
|
||||
$user = auth()->user();
|
||||
if ($user && method_exists($user, 'inGroup')) {
|
||||
$canEdit = $user->inGroup('OPDEdit');
|
||||
if ($user) {
|
||||
if (method_exists($user, 'can') && $user->can('billing.opd.edit')) {
|
||||
$canEdit = true;
|
||||
}
|
||||
|
||||
if (! $canEdit && method_exists($user, 'inGroup')) {
|
||||
$canEdit = $user->inGroup('OPDEdit');
|
||||
}
|
||||
}
|
||||
$paymentHistoryRows = $payment_history_rows ?? [];
|
||||
?>
|
||||
<section class="content-header">
|
||||
<h1>OPD Invoice</h1>
|
||||
|
|
@ -223,6 +230,50 @@ if ($user && method_exists($user, 'inGroup')) {
|
|||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<hr />
|
||||
<div class="row g-3">
|
||||
<div class="col-12">
|
||||
<h5 class="mb-2">Payment History</h5>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-sm table-bordered align-middle">
|
||||
<thead class="table-light">
|
||||
<tr>
|
||||
<th>Date</th>
|
||||
<th>Type</th>
|
||||
<th>Mode</th>
|
||||
<th class="text-end">Amount</th>
|
||||
<th>Remark</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php if (!empty($paymentHistoryRows)) : ?>
|
||||
<?php foreach ($paymentHistoryRows as $historyRow) : ?>
|
||||
<?php
|
||||
$isRefund = (int) ($historyRow->credit_debit ?? 0) === 1;
|
||||
$historyDate = trim((string) ($historyRow->payment_date ?? ''));
|
||||
if ($historyDate === '') {
|
||||
$historyDate = trim((string) ($historyRow->insert_time ?? ''));
|
||||
}
|
||||
?>
|
||||
<tr>
|
||||
<td><?= esc($historyDate) ?></td>
|
||||
<td><?= $isRefund ? '<span class="text-danger">Refund</span>' : '<span class="text-success">Received</span>' ?></td>
|
||||
<td><?= esc($historyRow->payment_mode_str ?? '') ?></td>
|
||||
<td class="text-end"><?= esc(number_format((float) ($historyRow->amount ?? 0), 2, '.', '')) ?></td>
|
||||
<td><?= esc($historyRow->remark ?? '') ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
<?php else : ?>
|
||||
<tr>
|
||||
<td colspan="5" class="text-center text-muted">No payment history entries.</td>
|
||||
</tr>
|
||||
<?php endif; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php if ($canEdit && ((int) ($opd_master[0]->opd_status ?? 0) === 1 || (int) ($opd_master[0]->opd_status ?? 0) === 2)) : ?>
|
||||
<hr />
|
||||
<div class="row g-3">
|
||||
|
|
@ -419,7 +470,8 @@ if ($user && method_exists($user, 'inGroup')) {
|
|||
"oid": $('#oid').val(),
|
||||
"input_remark": $('#input_remark').val(),
|
||||
[csrf.name]: csrf.value
|
||||
}, function() {
|
||||
}, function(data) {
|
||||
updateCsrf(data);
|
||||
load_form('<?= base_url('Opd/invoice') ?>/' + $('#oid').val());
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,8 +39,24 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
$serverTimeZoneId = 'Asia/Kolkata';
|
||||
$serverNow = new DateTimeImmutable('now', new DateTimeZone($serverTimeZoneId));
|
||||
$serverTimeZoneLabel = trim((string) $serverNow->format('T'));
|
||||
if ($serverTimeZoneLabel === '' || $serverTimeZoneLabel === 'GMT') {
|
||||
$serverTimeZoneLabel = $serverTimeZoneId;
|
||||
}
|
||||
$serverEpochMs = (int) round(microtime(true) * 1000);
|
||||
$serverDisplayTime = $serverNow->format('d-m-Y h:i A') . ' (' . $serverTimeZoneLabel . ')';
|
||||
?>
|
||||
<ul class="d-flex align-items-center">
|
||||
<li class="nav-item pe-3 d-none d-md-flex align-items-center text-nowrap" title="Server time">
|
||||
<i class="bi bi-clock me-1"></i>
|
||||
<span id="header-server-datetime"
|
||||
data-server-epoch-ms="<?= esc((string) $serverEpochMs) ?>"
|
||||
data-server-timezone-id="<?= esc($serverTimeZoneId) ?>"
|
||||
data-server-timezone-label="<?= esc($serverTimeZoneLabel) ?>"><?= esc($serverDisplayTime) ?></span>
|
||||
</li>
|
||||
<li class="nav-item dropdown pe-3">
|
||||
<a class="nav-link nav-profile d-flex align-items-center pe-0" href="#" data-bs-toggle="dropdown">
|
||||
<img src="<?= base_url('assets/img/profile-img.jpg') ?>" alt="Profile" class="rounded-circle">
|
||||
|
|
@ -76,3 +92,94 @@
|
|||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
<script>
|
||||
(function () {
|
||||
var el = document.getElementById('header-server-datetime');
|
||||
if (!el) {
|
||||
return;
|
||||
}
|
||||
|
||||
var serverEpochMs = Number(el.getAttribute('data-server-epoch-ms') || '0');
|
||||
if (!Number.isFinite(serverEpochMs) || serverEpochMs <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
var tzId = String(el.getAttribute('data-server-timezone-id') || '');
|
||||
var tzLabel = String(el.getAttribute('data-server-timezone-label') || tzId || 'UTC');
|
||||
var dateCtor = window['Date'];
|
||||
var intlObj = window['Intl'];
|
||||
if (!dateCtor) {
|
||||
return;
|
||||
}
|
||||
|
||||
var clientBaseMs = dateCtor.now();
|
||||
|
||||
function pad2(value) {
|
||||
return String(value).padStart(2, '0');
|
||||
}
|
||||
|
||||
function formatServerDateTime(epochMs) {
|
||||
var dateObj = new dateCtor(epochMs);
|
||||
var parts = null;
|
||||
|
||||
try {
|
||||
if (!intlObj || !intlObj.DateTimeFormat) {
|
||||
throw new Error('Intl unavailable');
|
||||
}
|
||||
|
||||
parts = new intlObj.DateTimeFormat('en-GB', {
|
||||
timeZone: tzId || undefined,
|
||||
day: '2-digit',
|
||||
month: '2-digit',
|
||||
year: 'numeric',
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
hour12: true
|
||||
}).formatToParts(dateObj);
|
||||
} catch (e) {
|
||||
parts = null;
|
||||
}
|
||||
|
||||
if (parts) {
|
||||
var map = {};
|
||||
parts.forEach(function (part) {
|
||||
if (part.type !== 'literal') {
|
||||
map[part.type] = part.value;
|
||||
}
|
||||
});
|
||||
|
||||
var dd = map.day || pad2(dateObj.getDate());
|
||||
var mm = map.month || pad2(dateObj.getMonth() + 1);
|
||||
var yyyy = map.year || String(dateObj.getFullYear());
|
||||
var hh = map.hour || '12';
|
||||
var min = map.minute || pad2(dateObj.getMinutes());
|
||||
var period = String(map.dayPeriod || '').toUpperCase();
|
||||
if (period !== 'AM' && period !== 'PM') {
|
||||
period = dateObj.getHours() >= 12 ? 'PM' : 'AM';
|
||||
}
|
||||
|
||||
return dd + '-' + mm + '-' + yyyy + ' ' + hh + ':' + min + ' ' + period + ' (' + tzLabel + ')';
|
||||
}
|
||||
|
||||
var fallbackHours = dateObj.getHours();
|
||||
var fallbackPeriod = fallbackHours >= 12 ? 'PM' : 'AM';
|
||||
var fallbackHour12 = fallbackHours % 12;
|
||||
if (fallbackHour12 === 0) {
|
||||
fallbackHour12 = 12;
|
||||
}
|
||||
|
||||
return pad2(dateObj.getDate()) + '-' + pad2(dateObj.getMonth() + 1) + '-' + dateObj.getFullYear()
|
||||
+ ' ' + pad2(fallbackHour12) + ':' + pad2(dateObj.getMinutes()) + ' ' + fallbackPeriod + ' (' + tzLabel + ')';
|
||||
}
|
||||
|
||||
function refreshClock() {
|
||||
var nowMs = dateCtor.now();
|
||||
var currentServerMs = serverEpochMs + (nowMs - clientBaseMs);
|
||||
el.textContent = formatServerDateTime(currentServerMs);
|
||||
}
|
||||
|
||||
refreshClock();
|
||||
setInterval(refreshClock, 1000);
|
||||
})();
|
||||
</script>
|
||||
|
|
@ -107,6 +107,12 @@ if (! $canDiagnosis && $user && method_exists($user, 'inGroup')) {
|
|||
<span>Dashboard</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link collapsed" href="javascript:load_form('<?= base_url('setting/admin/bed-status') ?>','Bed Status');">
|
||||
<i class="bi bi-geo-alt"></i>
|
||||
<span>Bed Status</span>
|
||||
</a>
|
||||
</li>
|
||||
<?php if ($canBilling) { ?>
|
||||
|
||||
<li class="nav-heading">Billing</li>
|
||||
|
|
@ -115,6 +121,18 @@ if (! $canDiagnosis && $user && method_exists($user, 'inGroup')) {
|
|||
<i class="bi bi-person-lines-fill"></i>
|
||||
<span>Patient List</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link collapsed" href="javascript:load_form('<?= base_url('Invoice/opdlist') ?>','OPD Invoice')">
|
||||
<i class="bi bi-receipt"></i>
|
||||
<span>OPD Invoice</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link collapsed" href="javascript:load_form('<?= base_url('Invoice/chargeslist') ?>','Charges Invoice')">
|
||||
<i class="bi bi-journal-text"></i>
|
||||
<span>Charges Invoice</span>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link collapsed" href="javascript:load_form('<?= base_url('/billing/ipd') ?>','IPD List')">
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user