Fix legacy billing prints and pathology template compatibility

This commit is contained in:
DevSoftTech Server 2026-03-21 02:23:31 +05:30
parent 300ec0e5cf
commit addef91468
13 changed files with 1498 additions and 15 deletions

View File

@ -289,6 +289,11 @@ service('auth')->routes($routes);
// Legacy compatibility: some IPD charge screens still refresh via old IpdNew URL.
$routes->get('IpdNew/show_ipd_items/(:num)', 'Billing\\Ipd::panelTab/$1/ipd-charges');
$routes->get('IpdNew/show_ipd_items/(:num)/(:num)', 'Billing\\Ipd::panelTab/$1/ipd-charges');
// Legacy compatibility: patient profile still calls old new-IPD URL.
$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');
// 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');
@ -407,6 +412,7 @@ $routes->group('billing', function($routes) {
$routes->post('charges/cancel-invoice/(:num)', 'Billing\\Charges::cancel_invoice/$1');
$routes->post('charges/update-correction', 'Billing\\Charges::update_correction_charges');
$routes->get('charges/show/(:num)', 'Billing\\Charges::show/$1');
$routes->get('charges/print_invoice/(:num)/(:num)', 'Billing\\Charges::print_invoice/$1/$2');
$routes->post('charges/delete', 'Billing\\Charges::delete');
$routes->post('charges/update-discount', 'Billing\\Charges::updateDiscount');
});

View File

@ -119,6 +119,7 @@ class CaseMaster extends BaseController
'input_insurance_id' => 'required|min_length[2]|max_length[30]',
'input_card_holder_name' => 'required|min_length[2]|max_length[50]',
];
$validation = service('validation');
$validation->setRules($rules);
if (! $validation->withRequest($this->request)->run()) {
$errorText = implode("\n", $validation->getErrors());

View File

@ -4,6 +4,7 @@ namespace App\Controllers\Billing;
use App\Controllers\BaseController;
use App\Models\InvoiceModel;
use Mpdf\Mpdf;
class Charges extends BaseController
{
@ -1017,4 +1018,116 @@ class Charges extends BaseController
return $this->response->setJSON(['update' => 1]);
}
public function print_invoice(int $invoiceId, int $printMode = 0)
{
if ($resp = $this->requirePermission('billing.charges.view')) {
return $resp;
}
// Retrieve all invoice data (same as show method)
$invoiceModel = new InvoiceModel();
$invoiceModel->updateInvoiceFinal($invoiceId);
$sql = "select i.*,t.group_desc from invoice_item i join hc_item_type t on i.item_type=t.itype_id
where i.inv_master_id=" . (int) $invoiceId;
$query = $this->db->query($sql);
$data['invoiceDetails'] = $query->getResult();
$sql = "select *,
(case payment_mode when 1 then 'Cash' when 2 then 'Bank Card/Online' when 3 then 'IPD Credit' when 4 then 'Org. Credit' else 'Pending' end) as Payment_type_str
from invoice_master where id=" . (int) $invoiceId;
$query = $this->db->query($sql);
$data['invoice_master'] = $query->getResult();
if (empty($data['invoice_master'])) {
return $this->response->setStatusCode(404)->setBody('Invoice not found');
}
$insCompId = (int) ($data['invoice_master'][0]->insurance_id ?? 0);
$insId = (int) ($data['invoice_master'][0]->insurance_card_id ?? 0);
$sql = "select * from hc_insurance_card where id=" . $insId;
$query = $this->db->query($sql);
$data['hc_insurance_card'] = $query->getResult();
$sql = "select * from hc_insurance where id=" . $insCompId;
$query = $this->db->query($sql);
$data['insurance'] = $query->getResult();
$sql = "select p.*,f.full_path as profile_picture
from patient_master p
left join file_upload_data f on p.profile_file_id=f.id
where p.id=" . (int) ($data['invoice_master'][0]->attach_id ?? 0);
$query = $this->db->query($sql);
$data['patient_master'] = $query->getResult();
if (!empty($data['patient_master'])) {
$row = $data['patient_master'][0];
$row->age = get_age_1($row->dob ?? null, $row->age ?? '', $row->age_in_month ?? '', $row->estimate_dob ?? '');
$row->xgender = ($row->gender ?? 0) == 1 ? 'Male' : 'Female';
}
$sql = "select * from ipd_master where ipd_status=0 and p_id=" . (int) ($data['invoice_master'][0]->attach_id ?? 0);
if (($data['invoice_master'][0]->ipd_id ?? 0) > 0) {
$sql = "select * from ipd_master where id=" . (int) $data['invoice_master'][0]->ipd_id;
}
$query = $this->db->query($sql);
$data['ipd_master'] = $query->getResult();
$sql = "select * from organization_case_master where case_type=0 and status=0 and p_id=" . (int) ($data['invoice_master'][0]->attach_id ?? 0);
if (($data['invoice_master'][0]->insurance_case_id ?? 0) > 0) {
$sql = "select * from organization_case_master where case_type=0 and id=" . (int) $data['invoice_master'][0]->insurance_case_id;
} elseif (count($data['ipd_master'] ?? []) > 0) {
if (($data['ipd_master'][0]->case_id ?? 0) > 0) {
$sql = "select * from organization_case_master where case_type=0 and id=" . (int) $data['ipd_master'][0]->case_id;
}
}
$query = $this->db->query($sql);
$data['case_master'] = $query->getResult();
$sql = "select *,
(case payment_mode when 1 then 'Cash' when 2 then 'Bank Card' when 3 then 'Org Credit' when 4 then 'Adjustment' else 'Pending' end) as Payment_type_str
from payment_history where payof_type=2 and payof_id=" . (int) $invoiceId;
$query = $this->db->query($sql);
$data['payment_history_details'] = $query->getResult();
// Generate PDF using mPDF
$mpdfTempDir = WRITEPATH . 'cache' . DIRECTORY_SEPARATOR . 'mpdf';
if (!is_dir($mpdfTempDir)) {
mkdir($mpdfTempDir, 0755, true);
}
if ($printMode === 1) {
// Legacy behavior: A4 landscape with two copies side-by-side in one page.
$htmlContent = view('billing/charges/invoice_pdf_double', $data);
$mpdf = new Mpdf([
'tempDir' => $mpdfTempDir,
'format' => 'A4-L',
'margin_top' => 12,
'margin_bottom' => 10,
'margin_left' => 5,
'margin_right' => 5,
]);
$mpdf->WriteHTML($htmlContent);
} else {
$htmlContent = view('billing/charges/invoice_pdf_template', $data);
$mpdf = new Mpdf([
'tempDir' => $mpdfTempDir,
'format' => 'A4',
'margin_top' => 10,
'margin_bottom' => 10,
'margin_left' => 10,
'margin_right' => 10,
]);
$mpdf->WriteHTML($htmlContent);
}
$invoiceCode = (string) ($data['invoice_master'][0]->invoice_code ?? 'Invoice');
$fileName = $invoiceCode . '.pdf';
return $this->response
->setHeader('Content-Type', 'application/pdf')
->setHeader('Content-Disposition', 'inline; filename="' . $fileName . '"')
->setBody($mpdf->Output($fileName, 'S'));
}
}

View File

@ -170,6 +170,205 @@ class Ipd extends BaseController
return view('billing/ipd/panel', $panelData);
}
public function legacyAddIpd(int $patientId)
{
$permission = $this->requireAnyPermission([
'billing.access',
'billing.ipd.current-admission',
'billing.ipd.invoice',
]);
if ($permission) {
return $permission;
}
$patientId = (int) $patientId;
if ($patientId <= 0) {
return redirect()->to(base_url('billing/ipd/current-admission'));
}
$activeIpd = $this->db->table('ipd_master')
->select('id')
->where('p_id', $patientId)
->where('ipd_status', 0)
->orderBy('id', 'DESC')
->get(1)
->getRowArray();
if (! empty($activeIpd['id'])) {
return redirect()->to(base_url('billing/ipd/panel/' . (int) $activeIpd['id']));
}
$data = $this->buildLegacyIpdRegistrationData($patientId);
if (empty($data['person_info'])) {
return $this->response->setStatusCode(404)->setBody('Patient not found');
}
return view('billing/ipd/legacy_registration', $data);
}
public function legacyAddNew()
{
$permission = $this->requireAnyPermission([
'billing.access',
'billing.ipd.current-admission',
'billing.ipd.invoice',
]);
if ($permission) {
return $permission;
}
if (! $this->request->isAJAX()) {
return $this->response->setStatusCode(400)->setJSON([
'insertid' => 0,
'error_text' => 'Invalid request',
]);
}
$patientId = (int) ($this->request->getPost('pid') ?? 0);
$docList = $this->request->getPost('doc_id');
$docList = is_array($docList) ? array_values(array_filter(array_map('intval', $docList), static fn ($id) => $id > 0)) : [];
if ($patientId <= 0 || empty($docList)) {
return $this->response->setJSON([
'insertid' => 0,
'error_text' => 'Please select at least one doctor.',
]);
}
$registerDateInput = (string) ($this->request->getPost('res_date') ?? '');
$registerDate = $registerDateInput !== '' ? str_to_MysqlDate($registerDateInput) : date('Y-m-d');
$master = [
'p_id' => $patientId,
'P_name' => (string) ($this->request->getPost('pname') ?? ''),
'relation' => (string) ($this->request->getPost('r_relation') ?? ''),
'contact_person_Name' => (string) ($this->request->getPost('rp_name') ?? ''),
'insurance_id' => (int) ($this->request->getPost('insur_list') ?? 0),
'policy_no' => (string) ($this->request->getPost('insur_no') ?? ''),
'register_date' => $registerDate,
'problem' => (string) ($this->request->getPost('problem') ?? ''),
'remark' => (string) ($this->request->getPost('remark') ?? ''),
'P_mobile1' => (string) ($this->request->getPost('phone1') ?? ''),
'P_mobile2' => (string) ($this->request->getPost('phone2') ?? ''),
'case_type' => (int) ($this->request->getPost('optionsRadios_mlc') ?? 0),
'case_id' => (int) ($this->request->getPost('optionsRadios_org') ?? 0),
'reg_time' => (string) ($this->request->getPost('res_time') ?? date('H:i')),
'refer_by' => (int) ($this->request->getPost('refer_by_list') ?? 0),
'dept_id' => (int) ($this->request->getPost('dept_id') ?? 0),
];
$insertId = $this->ipdEditModel->insertIpd([
'master' => $master,
'doc_list' => $docList,
]);
if ($insertId > 0) {
$roomId = (int) ($this->request->getPost('room_list') ?? 0);
if ($roomId > 0) {
$this->ipdEditModel->bedAssign([
'ipd_id' => $insertId,
'Fdate' => date('Y-m-d H:i:s'),
'TDate' => date('Y-m-d H:i:s'),
'bed_id' => $roomId,
]);
}
$caseId = (int) ($master['case_id'] ?? 0);
if ($caseId > 0 && $this->db->tableExists('organization_case_master')) {
$this->db->table('organization_case_master')
->where('id', $caseId)
->update(['ipd_id' => $insertId]);
}
}
return $this->response->setJSON([
'insertid' => (int) $insertId,
]);
}
private function buildLegacyIpdRegistrationData(int $patientId): array
{
$person = $this->db->table('patient_master')
->select("*, if(gender=1,'Male','FeMale') as xgender", false)
->where('id', $patientId)
->get()
->getRow();
if ($person) {
$person->age = get_age_1(
$person->dob ?? null,
$person->age ?? '',
$person->age_in_month ?? '',
$person->estimate_dob ?? ''
);
}
$docSpecList = $this->db->query(
"select d.id, d.p_fname, group_concat(m.SpecName) as SpecName
from doctor_master d
join doc_spec s on d.id = s.doc_id
join med_spec m on s.med_spec_id = m.id
where d.active = 1
group by d.id
order by d.p_fname"
)->getResult();
$ipdBedList = [];
if ($this->db->tableExists('bed_master')) {
$ipdBedList = $this->db->query(
"select b.id,
concat('Bed No:', coalesce(b.bed_number, b.bed_code), '/', '[', coalesce(w.ward_name, ''), ']') as Bed_Desc
from bed_master b
left join ward_master w on w.id = b.ward_id
where b.bed_status = 'available'
order by b.bed_number, b.id"
)->getResult();
} elseif ($this->db->tableExists('hc_bed_master')) {
$ipdBedList = $this->db->query(
"select id, concat('Bed No:', coalesce(bed_no, bed_number), '/', '[', coalesce(room_name, ward_name), ']') as Bed_Desc
from hc_bed_master
where ifnull(bed_used_p_id,0)=0"
)->getResult();
}
$caseMaster = [];
if ($this->db->tableExists('organization_case_master')) {
$caseMaster = $this->db->table('organization_case_master')
->where('status', 0)
->where('case_type', 1)
->where('ipd_id', 0)
->where('p_id', $patientId)
->get()
->getResult();
}
$referMaster = [];
if ($this->db->tableExists('refer_master')) {
$referMaster = $this->db->table('refer_master')
->where('active', 1)
->orderBy('f_name', 'ASC')
->get()
->getResult();
}
$hcDepartment = [];
if ($this->db->tableExists('hc_department')) {
$hcDepartment = $this->db->table('hc_department')
->orderBy('vName', 'ASC')
->get()
->getResult();
}
return [
'person_info' => $person,
'doc_spec_l' => $docSpecList,
'ipd_bed_list' => $ipdBedList,
'case_master' => $caseMaster,
'refer_master' => $referMaster,
'hc_department' => $hcDepartment,
];
}
public function panelTab(int $ipdId, string $tab)
{
$permission = $this->requireAnyPermission([

View File

@ -860,7 +860,7 @@ class Diagnosis extends BaseController
$dataLabTestList = $this->db->query($itemSql, [$labReqId])->getResult();
$repoFormat = $this->db->table('lab_repo')
->select('mstRepoKey, Title, HTMLData')
->select('mstRepoKey, Title, HTMLData, RTFData')
->where('mstRepoKey', (int) $labRequest->lab_repo_id)
->get()
->getRow();
@ -869,7 +869,10 @@ class Diagnosis extends BaseController
? $repoFormat->Title
: ($labRequest->report_name ?? 'Lab Report');
$reportString = $repoFormat->HTMLData ?? '';
$reportString = (string) ($repoFormat->HTMLData ?? '');
if (trim($reportString) === '') {
$reportString = (string) ($repoFormat->RTFData ?? '');
}
$reportHeader = '<table border="0" cellpadding="1" cellspacing="1" style="width:100%"><tbody><tr><td><h3>' .
htmlspecialchars((string) $reportTitle, ENT_QUOTES, 'UTF-8') .
'</h3></td></tr></tbody></table>';
@ -971,7 +974,7 @@ class Diagnosis extends BaseController
}
$repoFormat = $this->db->table('lab_repo')
->select('Title, HTMLData')
->select('Title, HTMLData, RTFData')
->where('mstRepoKey', (int) ($labRequest->lab_repo_id ?? 0))
->get()
->getRow();
@ -981,6 +984,9 @@ class Diagnosis extends BaseController
: (string) ($labRequest->report_name ?? 'Radiology Report');
$reportString = (string) ($repoFormat->HTMLData ?? '');
if (trim($reportString) === '') {
$reportString = (string) ($repoFormat->RTFData ?? '');
}
$reportHeader = '<table border="0" cellpadding="1" cellspacing="1" style="width:100%"><tbody><tr><td><h3>' .
htmlspecialchars($reportTitle, ENT_QUOTES, 'UTF-8') .
'</h3></td></tr></tbody></table>';

View File

@ -81,6 +81,47 @@ class Template extends BaseController
return $map[$modality] ?? null;
}
private function buildDefaultPathologyTemplate(string $reportName): string
{
$name = strtolower(trim($reportName));
$isCbc = str_contains($name, 'cbc') || str_contains($name, 'complete blood count') || str_contains($name, 'hemogram');
if (! $isCbc) {
return '';
}
return <<<HTML
<p><strong>COMPLETE BLOOD COUNT (CBC)</strong></p>
<table style="width:100%;border-collapse:collapse;font-size:12px;" border="1" cellpadding="6" cellspacing="0">
<thead>
<tr style="background:#f4f6f8;">
<th style="text-align:left;">Investigation</th>
<th style="text-align:center;">Result</th>
<th style="text-align:center;">Unit</th>
<th style="text-align:center;">Reference Range</th>
</tr>
</thead>
<tbody>
<tr><td>Hemoglobin (Hb)</td><td style="text-align:center;">&nbsp;</td><td style="text-align:center;">g/dL</td><td style="text-align:center;">12.0 - 16.0</td></tr>
<tr><td>Total WBC Count (TLC)</td><td style="text-align:center;">&nbsp;</td><td style="text-align:center;">/cumm</td><td style="text-align:center;">4,000 - 11,000</td></tr>
<tr><td>Neutrophils</td><td style="text-align:center;">&nbsp;</td><td style="text-align:center;">%</td><td style="text-align:center;">40 - 75</td></tr>
<tr><td>Lymphocytes</td><td style="text-align:center;">&nbsp;</td><td style="text-align:center;">%</td><td style="text-align:center;">20 - 40</td></tr>
<tr><td>Eosinophils</td><td style="text-align:center;">&nbsp;</td><td style="text-align:center;">%</td><td style="text-align:center;">1 - 6</td></tr>
<tr><td>Monocytes</td><td style="text-align:center;">&nbsp;</td><td style="text-align:center;">%</td><td style="text-align:center;">2 - 10</td></tr>
<tr><td>Basophils</td><td style="text-align:center;">&nbsp;</td><td style="text-align:center;">%</td><td style="text-align:center;">0 - 2</td></tr>
<tr><td>RBC Count</td><td style="text-align:center;">&nbsp;</td><td style="text-align:center;">million/cumm</td><td style="text-align:center;">4.0 - 5.5</td></tr>
<tr><td>PCV (HCT)</td><td style="text-align:center;">&nbsp;</td><td style="text-align:center;">%</td><td style="text-align:center;">36 - 46</td></tr>
<tr><td>MCV</td><td style="text-align:center;">&nbsp;</td><td style="text-align:center;">fL</td><td style="text-align:center;">80 - 100</td></tr>
<tr><td>MCH</td><td style="text-align:center;">&nbsp;</td><td style="text-align:center;">pg</td><td style="text-align:center;">27 - 32</td></tr>
<tr><td>MCHC</td><td style="text-align:center;">&nbsp;</td><td style="text-align:center;">g/dL</td><td style="text-align:center;">31 - 36</td></tr>
<tr><td>Platelet Count</td><td style="text-align:center;">&nbsp;</td><td style="text-align:center;">lakh/cumm</td><td style="text-align:center;">1.5 - 4.5</td></tr>
<tr><td>ESR</td><td style="text-align:center;">&nbsp;</td><td style="text-align:center;">mm/hr</td><td style="text-align:center;">0 - 20</td></tr>
</tbody>
</table>
<p><strong>Peripheral Smear:</strong> Normocytic normochromic RBCs. No hemoparasite seen.</p>
HTML;
}
private function requireModalityPermission(int $modality)
{
$permission = $this->permissionForModality($modality);
@ -194,6 +235,24 @@ class Template extends BaseController
$query = $this->db->query($sql);
$data['labReport_master'] = $query->getResult();
if (! empty($data['labReport_master'])) {
$existingHtml = trim((string) ($data['labReport_master'][0]->HTMLData ?? ''));
if ($existingHtml === '') {
$legacyHtml = trim((string) ($data['labReport_master'][0]->RTFData ?? ''));
if ($legacyHtml !== '') {
$data['labReport_master'][0]->HTMLData = $legacyHtml;
$existingHtml = $legacyHtml;
}
}
if ($existingHtml === '') {
$defaultHtml = $this->buildDefaultPathologyTemplate((string) ($data['labReport_master'][0]->Title ?? ''));
if ($defaultHtml !== '') {
$data['labReport_master'][0]->HTMLData = $defaultHtml;
}
}
}
$itemId = 0;
if (! empty($data['labReport_master'])) {
$itemId = (int) ($data['labReport_master'][0]->charge_id ?? 0);
@ -264,6 +323,13 @@ class Template extends BaseController
$groupId = (int) $this->request->getPost('group_id');
$htmlData = (string) $this->request->getPost('HTMLData');
if (trim($htmlData) === '') {
$defaultHtml = $this->buildDefaultPathologyTemplate($inputReportName);
if ($defaultHtml !== '') {
$htmlData = $defaultHtml;
}
}
if ($repoId <= 0 || $inputReportName === '') {
return $this->response->setJSON([
'update_record' => 0,
@ -277,6 +343,7 @@ class Template extends BaseController
'GrpKey' => $groupId,
'charge_id' => $chargeId,
'HTMLData' => $htmlData,
'RTFData' => $htmlData,
], $repoId);
return $this->response->setJSON([
@ -303,6 +370,13 @@ class Template extends BaseController
$groupId = (int) $this->request->getPost('group_id');
$htmlData = (string) $this->request->getPost('HTMLData');
if (trim($htmlData) === '') {
$defaultHtml = $this->buildDefaultPathologyTemplate($inputReportName);
if ($defaultHtml !== '') {
$htmlData = $defaultHtml;
}
}
if ($inputReportName === '') {
return $this->response->setJSON([
'insertid' => 0,
@ -316,6 +390,7 @@ class Template extends BaseController
'GrpKey' => $groupId,
'charge_id' => $chargeId,
'HTMLData' => $htmlData,
'RTFData' => $htmlData,
]);
return $this->response->setJSON([

View File

@ -56,11 +56,15 @@ class IpdModel extends Model
$docList = $data['doc_list'] ?? [];
if (! empty($docList)) {
foreach ($docList as $docId) {
$this->db->table('ipd_master_doc_list')->insert([
$docPayload = $this->filterTableDataByExistingColumns('ipd_master_doc_list', [
'doc_id' => $docId,
'ipd_id' => $insertId,
'log' => 'Insert By :' . $userSignature,
]);
if (! empty($docPayload)) {
$this->db->table('ipd_master_doc_list')->insert($docPayload);
}
}
}
@ -69,6 +73,11 @@ class IpdModel extends Model
public function addIpdDoc(array $docData): int
{
$docData = $this->filterTableDataByExistingColumns('ipd_master_doc_list', $docData);
if (empty($docData)) {
return 0;
}
$inserted = $this->db->table('ipd_master_doc_list')->insert($docData);
return $inserted ? (int) $this->db->insertID() : 0;
@ -101,22 +110,93 @@ class IpdModel extends Model
return 1;
}
private function filterTableDataByExistingColumns(string $table, array $data): array
{
if (! $this->db->tableExists($table)) {
return [];
}
$fields = $this->db->getFieldNames($table) ?? [];
if (empty($fields)) {
return $data;
}
return array_intersect_key($data, array_flip($fields));
}
public function bedAssign(array $data): int
{
$inserted = $this->db->table('ipd_bed_assign')->insert($data);
if (! $inserted) {
$ipdId = (int) ($data['ipd_id'] ?? 0);
$bedId = (int) ($data['bed_id'] ?? 0);
$fromDate = (string) ($data['Fdate'] ?? date('Y-m-d H:i:s'));
$toDate = (string) ($data['TDate'] ?? $fromDate);
if ($ipdId <= 0 || $bedId <= 0) {
return 0;
}
$insertId = (int) $this->db->insertID();
$insertId = 0;
$this->db->table('hc_bed_master')
->where('bed_used_p_id', $data['ipd_id'])
->update(['bed_used_p_id' => 0]);
if ($this->db->tableExists('bed_assignment_history')) {
$wardId = null;
if ($this->db->tableExists('bed_master') && in_array('ward_id', $this->db->getFieldNames('bed_master') ?? [], true)) {
$bedRow = $this->db->table('bed_master')
->select('ward_id')
->where('id', $bedId)
->get()
->getRowArray();
$wardId = isset($bedRow['ward_id']) ? (int) $bedRow['ward_id'] : null;
}
$this->db->table('hc_bed_master')
->where('id', $data['bed_id'])
->update(['bed_used_p_id' => $data['ipd_id']]);
$assignedBy = (int) ($this->getUserIdentity()['id'] ?? 0);
$inserted = $this->db->table('bed_assignment_history')->insert([
'ipd_id' => $ipdId,
'bed_id' => $bedId,
'assignment_type' => 'admission',
'assigned_date' => $fromDate,
'discharged_date' => $toDate,
'assigned_by' => $assignedBy > 0 ? $assignedBy : null,
'ward_id' => $wardId,
]);
if (! $inserted) {
return 0;
}
$insertId = (int) $this->db->insertID();
} elseif ($this->db->tableExists('ipd_bed_assign')) {
$inserted = $this->db->table('ipd_bed_assign')->insert([
'ipd_id' => $ipdId,
'Fdate' => $fromDate,
'TDate' => $toDate,
'bed_id' => $bedId,
]);
if (! $inserted) {
return 0;
}
$insertId = (int) $this->db->insertID();
} else {
return 0;
}
if ($this->db->tableExists('hc_bed_master') && in_array('bed_used_p_id', $this->db->getFieldNames('hc_bed_master') ?? [], true)) {
$this->db->table('hc_bed_master')
->where('bed_used_p_id', $ipdId)
->update(['bed_used_p_id' => 0]);
$this->db->table('hc_bed_master')
->where('id', $bedId)
->update(['bed_used_p_id' => $ipdId]);
}
if ($this->db->tableExists('bed_master') && in_array('bed_status', $this->db->getFieldNames('bed_master') ?? [], true)) {
$this->db->table('bed_master')
->where('id', $bedId)
->update(['bed_status' => 'occupied']);
}
return $insertId;
}

View File

@ -1,4 +1,53 @@
<div class="card">
<style>
.insurance-form-theme {
border: 0;
border-radius: 14px;
overflow: hidden;
box-shadow: 0 14px 32px rgba(15, 23, 42, 0.08);
}
.insurance-form-theme > .card-header {
background: linear-gradient(120deg, #1d4ed8 0%, #0ea5e9 55%, #22c55e 100%);
color: #ffffff;
border-bottom: 0;
padding: 14px 16px;
}
.insurance-form-theme > .card-header .card-title {
font-weight: 700;
letter-spacing: .2px;
}
.insurance-form-theme > .card-body {
background: #f8fafc;
padding: 18px;
}
.insurance-form-theme .form-label {
font-weight: 600;
color: #0f172a;
}
.insurance-form-theme .form-control {
border-radius: 10px;
border: 1px solid #cbd5e1;
box-shadow: none;
transition: border-color .2s ease, box-shadow .2s ease;
}
.insurance-form-theme .form-control:focus {
border-color: #0284c7;
box-shadow: 0 0 0 3px rgba(2, 132, 199, 0.16);
}
.insurance-form-theme #btn_update {
border-radius: 10px;
padding: 10px 16px;
font-weight: 600;
}
</style>
<div class="card insurance-form-theme">
<div class="card-header d-flex align-items-center justify-content-between flex-wrap gap-2">
<h3 class="card-title mb-0">Insurance Company - Add New</h3>
<div class="card-tools ms-auto">

View File

@ -1,5 +1,62 @@
<style>
.insurance-form-theme {
border: 0;
border-radius: 14px;
overflow: hidden;
box-shadow: 0 14px 32px rgba(15, 23, 42, 0.08);
}
.insurance-form-theme > .card-header {
background: linear-gradient(120deg, #1d4ed8 0%, #0ea5e9 55%, #22c55e 100%);
color: #ffffff;
border-bottom: 0;
padding: 14px 16px;
}
.insurance-form-theme > .card-body {
background: #f8fafc;
padding: 18px;
}
.insurance-form-theme .form-label {
font-weight: 600;
color: #0f172a;
}
.insurance-form-theme .form-control {
border-radius: 10px;
border: 1px solid #cbd5e1;
box-shadow: none;
transition: border-color .2s ease, box-shadow .2s ease;
}
.insurance-form-theme .form-control:focus {
border-color: #0284c7;
box-shadow: 0 0 0 3px rgba(2, 132, 199, 0.16);
}
.insurance-form-theme .card .card-header {
background: #e2e8f0;
border-bottom: 1px solid #cbd5e1;
}
.insurance-form-theme .card .card-title {
font-weight: 700;
}
.insurance-form-theme .form-check {
padding: 6px 0 6px 1.6rem;
}
.insurance-form-theme #btn_update {
border-radius: 10px;
padding: 10px 18px;
font-weight: 600;
}
</style>
<?php if (! empty($data_insurance)) : ?>
<div class="card">
<div class="card insurance-form-theme">
<div class="card-header d-flex align-items-center justify-content-between flex-wrap gap-2">
<h3 class="card-title mb-0">Insurance Company - <?= esc($data_insurance[0]->ins_company_name ?? '') ?></h3>
<div class="card-tools ms-auto">

View File

@ -123,6 +123,22 @@
</section>
</form>
<!-- Print Buttons Section -->
<div class="card mt-3">
<div class="card-body p-3">
<div class="row g-2">
<div class="col-md-12">
<a href="<?= base_url('billing/charges/print_invoice') ?>/<?= esc($invoice_master[0]->id ?? 0) ?>/0" target="_blank" class="btn btn-primary">
<i class="fas fa-print"></i> Print A4
</a>
<a href="<?= base_url('billing/charges/print_invoice') ?>/<?= esc($invoice_master[0]->id ?? 0) ?>/1" target="_blank" class="btn btn-primary">
<i class="fas fa-print"></i> Print Double Copy
</a>
</div>
</div>
</div>
</div>
<?php if (($invoice_master[0]->payment_status ?? 0) == 0 && $canChargePay) : ?>
<div class="card">
<div class="card-body p-3">

View File

@ -0,0 +1,216 @@
<?php
$invoice = $invoice_master[0] ?? null;
$patient = $patient_master[0] ?? null;
$caseRow = $case_master[0] ?? null;
$hospitalName = defined('H_Name') ? (string) constant('H_Name') : 'Hospital';
$hospitalAddress1 = defined('H_address_1') ? (string) constant('H_address_1') : '';
$hospitalAddress2 = defined('H_address_2') ? (string) constant('H_address_2') : '';
$hospitalPhone = defined('H_phone_No') ? (string) constant('H_phone_No') : '';
$hospitalLogoName = defined('H_logo') ? trim((string) constant('H_logo')) : '';
$logoPathCandidates = [];
if ($hospitalLogoName !== '') {
$logoPathCandidates[] = FCPATH . 'assets/images/' . $hospitalLogoName;
$logoPathCandidates[] = FCPATH . 'assets/img/' . $hospitalLogoName;
}
$logoPathCandidates[] = FCPATH . 'assets/img/logo.png';
$logoSrc = '';
foreach ($logoPathCandidates as $candidate) {
if (is_file($candidate)) {
$logoSrc = str_replace('\\', '/', $candidate);
break;
}
}
$invoiceCode = (string) ($invoice->invoice_code ?? '');
$invoiceDate = (string) ($invoice->inv_date ?? '');
$grossAmount = (float) ($invoice->total_amount ?? 0);
$discount = (float) ($invoice->discount_amount ?? 0);
$netAmount = (float) ($invoice->net_amount ?? 0);
$amountReceived = (float) ($invoice->payment_part_received ?? 0);
$balanceAmount = (float) ($invoice->payment_part_balance ?? $netAmount);
$orgCaseInfo = '';
if (!empty($caseRow)) {
$shortName = (string) ($caseRow->short_name ?? '');
$caseCode = (string) ($caseRow->case_id_code ?? '');
if ($shortName !== '') {
$orgCaseInfo .= 'Org. Name : ' . $shortName . '<br>';
}
if ($caseCode !== '') {
$orgCaseInfo .= 'Org. ID : ' . $caseCode;
}
}
$qrParts = [
(string) ($patient->p_code ?? ''),
$invoiceCode,
'TAmt-' . number_format($netAmount, 2, '.', ''),
'P-' . date('Y-m-d H:i:s'),
];
$qrContent = implode(':', array_filter($qrParts, static fn ($v) => trim((string) $v) !== ''));
$paymentHistory = $payment_history_details ?? [];
if (!function_exists('convertNumberToWords')) {
function convertNumberToWords($num)
{
$num = (int) round((float) $num);
$ones = ['', 'One', 'Two', 'Three', 'Four', 'Five', 'Six', 'Seven', 'Eight', 'Nine'];
$teens = ['Ten', 'Eleven', 'Twelve', 'Thirteen', 'Fourteen', 'Fifteen', 'Sixteen', 'Seventeen', 'Eighteen', 'Nineteen'];
$tens = ['', '', 'Twenty', 'Thirty', 'Forty', 'Fifty', 'Sixty', 'Seventy', 'Eighty', 'Ninety'];
if ($num === 0) return 'Zero';
if ($num < 0) return 'Negative ' . convertNumberToWords(-$num);
if ($num < 10) return $ones[$num];
if ($num < 20) return $teens[$num - 10];
if ($num < 100) return $tens[(int) ($num / 10)] . ($num % 10 ? ' ' . $ones[$num % 10] : '');
if ($num < 1000) return $ones[(int) ($num / 100)] . ' Hundred' . ($num % 100 ? ' ' . convertNumberToWords($num % 100) : '');
if ($num < 100000) return convertNumberToWords((int) ($num / 1000)) . ' Thousand' . ($num % 1000 ? ' ' . convertNumberToWords($num % 1000) : '');
if ($num < 10000000) return convertNumberToWords((int) ($num / 100000)) . ' Lakh' . ($num % 100000 ? ' ' . convertNumberToWords($num % 100000) : '');
return convertNumberToWords((int) ($num / 10000000)) . ' Crore' . ($num % 10000000 ? ' ' . convertNumberToWords($num % 10000000) : '');
}
}
?>
<style>
@page {
sheet-size: A4-L;
margin-top: 0.7cm;
margin-bottom: 0.8cm;
margin-left: 0.4cm;
margin-right: 0.4cm;
}
body { font-family: dejavusans, freeserif, sans-serif; font-size: 11.5px; color: #111; }
.main { width: 100%; }
.half { width: 50%; vertical-align: top; }
.left-border { border-right: 1px solid #ddd; }
.head-wrap { border: 1px solid #ddd; }
.hname { font-size: 19px; font-weight: 700; margin-bottom: 2px; }
.hline { font-size: 12px; }
.inv-title { font-size: 27px; font-weight: 700; text-align: right; color: #2b3f54; }
.small { font-size: 10.5px; }
.tbl { width: 100%; border-collapse: collapse; font-size: 11px; }
.tbl th, .tbl td { border: 1px solid #222; padding: 3px 5px; }
.tbl th { font-weight: 700; }
.right { text-align: right; }
.sign { margin-top: 18px; text-align: right; }
</style>
<table class="main" cellspacing="6" cellpadding="0">
<tr>
<?php foreach (['', ' [LAB COPY]'] as $copyLabel) : ?>
<td class="half <?= $copyLabel === '' ? 'left-border' : '' ?>">
<table class="tbl" style="border:none;">
<tr>
<td style="border:none; width:16%; vertical-align: top;">
<?php if ($logoSrc !== '') : ?>
<img style="width:65px;" src="<?= esc($logoSrc) ?>" alt="logo">
<?php endif; ?>
</td>
<td style="border:none; width:62%; vertical-align: top;">
<div class="hname"><?= esc($hospitalName) ?></div>
<div class="hline"><?= esc(trim($hospitalAddress1 . ', ' . $hospitalAddress2, ', ')) ?></div>
<?php if ($hospitalPhone !== '') : ?>
<div class="hline">Phone: <?= esc($hospitalPhone) ?></div>
<?php endif; ?>
</td>
<td style="border:none; width:22%; text-align:right; vertical-align: top;">
<div class="inv-title">INVOICE</div>
<div><?= esc($invoiceCode . $copyLabel) ?></div>
<?php if ($qrContent !== '') : ?>
<barcode code="<?= esc($qrContent) ?>" size="0.75" type="QR" error="M" class="barcode" />
<?php endif; ?>
</td>
</tr>
</table>
<table style="width:100%; margin-top:8px;" cellspacing="0" cellpadding="0">
<tr>
<td style="width:50%; vertical-align:top;">
Bill To<br>
UHID : <?= esc((string) ($patient->p_code ?? '')) ?><br>
Name : <strong><?= esc(strtoupper((string) ($patient->p_fname ?? ''))) ?></strong><br>
<?= esc((string) ($patient->p_relative ?? '')) ?> <?= esc(strtoupper((string) ($patient->p_rname ?? ''))) ?><br>
Sex : <strong><?= esc((string) ($patient->xgender ?? '')) ?> <?= esc((string) ($patient->age ?? '')) ?></strong>
P.No. : <?= esc((string) ($patient->mphone1 ?? '')) ?>
</td>
<td style="width:50%; text-align:right; vertical-align:top;">
<?= $orgCaseInfo ?>
<?php if ($orgCaseInfo !== '') : ?><br><?php endif; ?>
Address : <?= esc((string) (($patient->add1 ?? '') . ',' . ($patient->city ?? ''))) ?><br>
Date : <strong><?= esc($invoiceDate) ?></strong><br>
<strong>Refer By :</strong> Dr.<?= esc((string) ($invoice->refer_by_other ?? '')) ?>
</td>
</tr>
</table>
<hr>
<table class="tbl">
<tr>
<th style="width:4%;">#</th>
<th style="width:24%;">Charges Group</th>
<th style="width:31%;">Charge Name</th>
<th style="width:13%;" class="right">Rate</th>
<th style="width:10%;" class="right">Qty</th>
<th style="width:18%;" class="right">Amt.</th>
</tr>
<?php $srno = 1; foreach (($invoiceDetails ?? []) as $row) : ?>
<tr>
<td><?= $srno ?></td>
<td><?= esc((string) ($row->group_desc ?? '')) ?></td>
<td><?= esc((string) ($row->item_name ?? '')) ?></td>
<td class="right"><?= esc((string) ($row->item_rate ?? '')) ?></td>
<td class="right"><?= esc((string) ($row->item_qty ?? '')) ?></td>
<td class="right"><?= esc(number_format((float) ($row->item_amount ?? 0), 2, '.', '')) ?></td>
</tr>
<?php $srno++; endforeach; ?>
<tr>
<td>#</td><td></td><td></td><td></td>
<td>Gross Total</td>
<td class="right"><?= esc(number_format($grossAmount, 2, '.', '')) ?></td>
</tr>
<?php if ($discount > 0) : ?>
<tr>
<td>#</td><td>Deduction</td><td><?= esc((string) ($invoice->discount_desc ?? '')) ?></td><td></td><td></td>
<td class="right">-<?= esc(number_format($discount, 2, '.', '')) ?></td>
</tr>
<?php endif; ?>
<tr>
<th>#</th><th></th><th></th><th></th>
<th>Net Amount</th>
<th class="right"><?= esc(number_format($netAmount, 2, '.', '')) ?></th>
</tr>
</table>
<hr>
<div class="small">
Amount received : <?= esc(number_format($amountReceived, 2, '.', '')) ?>
/ Balance Amount : <?= esc(number_format($balanceAmount, 2, '.', '')) ?>
/ Net Amount : <?= esc(number_format($netAmount, 2, '.', '')) ?>
</div>
<div style="margin-top:5px;">
<strong>Amount in Words :</strong> Rs. <?= esc(convertNumberToWords($netAmount)) ?> Only<br>
<strong>Prepared By :</strong> <?= esc((string) ($invoice->prepared_by ?? '')) ?>
</div>
<div style="margin-top:5px;">
<?php if ((int) ($invoice->payment_mode ?? 0) > 2) : ?>
<strong>Payment Details [<?= esc((string) ($invoice->Payment_type_str ?? '')) ?>]</strong>
<?php else : ?>
<strong>Payment Details [Payment No.:Mode of Payment:Amount]:</strong>
<?php foreach ($paymentHistory as $ph) : ?>
[<?= esc((string) ($ph->id ?? '')) ?>:<?= esc((string) ($ph->Payment_type_str ?? '')) ?>:<?= esc(number_format((float) ($ph->amount ?? 0), 2, '.', '')) ?>]/
<?php endforeach; ?>
<?php endif; ?>
</div>
<div class="sign">
<strong>Signature</strong><br>
Date : <?= esc((string) ($invoice->confirm_invoice_datetime ?? date('Y-m-d H:i:s'))) ?>
</div>
</td>
<?php endforeach; ?>
</tr>
</table>

View File

@ -0,0 +1,293 @@
<?php
$invoice = $invoice_master[0] ?? null;
$patient = $patient_master[0] ?? null;
$insuranceRow = $insurance[0] ?? null;
$caseRow = $case_master[0] ?? null;
$hospitalName = defined('H_Name') ? (string) constant('H_Name') : 'Hospital';
$hospitalAddress1 = defined('H_address_1') ? (string) constant('H_address_1') : '';
$hospitalAddress2 = defined('H_address_2') ? (string) constant('H_address_2') : '';
$hospitalPhone = defined('H_phone_No') ? (string) constant('H_phone_No') : '';
$hospitalEmail = defined('H_Email') ? (string) constant('H_Email') : '';
$hospitalLogoName = defined('H_logo') ? trim((string) constant('H_logo')) : '';
$hospitalNameLen = function_exists('mb_strlen') ? mb_strlen($hospitalName) : strlen($hospitalName);
$hospitalNameFontSize = 20;
if ($hospitalNameLen > 42) {
$hospitalNameFontSize = 14;
} elseif ($hospitalNameLen > 36) {
$hospitalNameFontSize = 16;
} elseif ($hospitalNameLen > 30) {
$hospitalNameFontSize = 18;
}
$invoiceCode = (string) ($invoice->invoice_code ?? '');
$invoiceDate = (string) ($invoice->inv_date ?? '');
$printedOn = date('d-m-Y h:i:s A');
$invoiceStatus = ((int) ($invoice->invoice_status ?? 0) === 1) ? 'Paid' : (((int) ($invoice->invoice_status ?? 0) === 2) ? 'Cancelled' : 'Pending');
$currencyPrefix = 'Rs.';
$grossAmount = (float) ($invoice->total_amount ?? 0);
$discount = (float) ($invoice->discount_amount ?? 0);
$netAmount = (float) ($invoice->net_amount ?? 0);
$logoPathCandidates = [];
if ($hospitalLogoName !== '') {
$logoPathCandidates[] = FCPATH . 'assets/images/' . $hospitalLogoName;
$logoPathCandidates[] = FCPATH . 'assets/img/' . $hospitalLogoName;
}
$logoPathCandidates[] = FCPATH . 'assets/img/logo.png';
$logoSrc = '';
foreach ($logoPathCandidates as $candidate) {
if (is_file($candidate)) {
$logoSrc = str_replace('\\', '/', $candidate);
break;
}
}
$qrParts = [
'Hospital:' . $hospitalName,
'HospitalPhone:' . $hospitalPhone,
'Invoice:' . $invoiceCode,
'Patient:' . (string) ($patient->p_code ?? ''),
'Name:' . trim((string) ($patient->p_fname ?? '')),
'Date:' . $invoiceDate,
'Net:' . number_format($netAmount, 2, '.', ''),
'Status:' . $invoiceStatus,
];
$qrContent = implode(' | ', array_filter($qrParts, static fn ($v) => trim((string) $v) !== ''));
$qrPackageAvailable = class_exists('\\Mpdf\\QrCode\\QrCode');
/**
* Convert numbers to words (basic implementation for Indian system)
* Wrapped with function_exists to prevent redeclaration when rendering multiple times
*/
if (!function_exists('convertNumberToWords')) {
function convertNumberToWords($num) {
$ones = ['', 'One', 'Two', 'Three', 'Four', 'Five', 'Six', 'Seven', 'Eight', 'Nine'];
$teens = ['Ten', 'Eleven', 'Twelve', 'Thirteen', 'Fourteen', 'Fifteen', 'Sixteen', 'Seventeen', 'Eighteen', 'Nineteen'];
$tens = ['', '', 'Twenty', 'Thirty', 'Forty', 'Fifty', 'Sixty', 'Seventy', 'Eighty', 'Ninety'];
if ($num == 0) return 'Zero';
if ($num < 0) return 'Negative ' . convertNumberToWords(-$num);
if ($num < 10) return $ones[$num];
if ($num < 20) return $teens[$num - 10];
if ($num < 100) return $tens[(int)($num / 10)] . ($num % 10 ? ' ' . $ones[$num % 10] : '');
if ($num < 1000) return $ones[(int)($num / 100)] . ' Hundred' . ($num % 100 ? ' ' . convertNumberToWords($num % 100) : '');
if ($num < 100000) return convertNumberToWords((int)($num / 1000)) . ' Thousand' . ($num % 1000 ? ' ' . convertNumberToWords($num % 1000) : '');
if ($num < 10000000) return convertNumberToWords((int)($num / 100000)) . ' Lakh' . ($num % 100000 ? ' ' . convertNumberToWords($num % 100000) : '');
if ($num < 1000000000) return convertNumberToWords((int)($num / 10000000)) . ' Crore' . ($num % 10000000 ? ' ' . convertNumberToWords($num % 10000000) : '');
return (string)$num;
}
}
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Invoice</title>
<style>
body { font-family: dejavusans, freeserif, sans-serif; font-size: 10.5px; color: #111; }
.wrap { width: 100%; }
.top { width: 100%; border-bottom: 2px solid #1f2d3a; padding-bottom: 9px; margin-bottom: 10px; }
.top td { vertical-align: top; }
.top-logo { text-align: left; }
.logo-img { max-width: 92px; max-height: 92px; }
.hospital-name { font-weight: 700; color: #1f2d3a; letter-spacing: 0.2px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.hospital-line { font-size: 9.8px; color: #334; line-height: 1.45; }
.invoice-title { text-align: right; font-size: 20px; font-weight: 700; color: #1f2d3a; letter-spacing: 0.4px; }
.invoice-sub { text-align: right; font-size: 9.6px; color: #556; margin-top: 2px; }
.invoice-status { text-align: right; margin-top: 5px; }
.status-chip { display: inline-block; border: 1px solid #8ea2b7; background: #eef3f8; color: #2b3a4b; padding: 2px 8px; font-size: 9.6px; font-weight: 700; border-radius: 10px; }
.qr-cell { text-align: right; }
.qr-block { display: inline-block; text-align: center; margin-top: 2px; }
.qr-label { font-size: 8.8px; color: #5a6776; margin-top: 2px; }
.meta { width: 100%; margin-bottom: 8px; border-collapse: separate; border-spacing: 0; }
.meta td { vertical-align: top; padding: 7px 8px; border: 1px solid #d6dee8; }
.meta-three td { width: 33.33%; }
.meta-two td { width: 50%; }
.meta-title { font-size: 10.5px; font-weight: 700; color: #1f2d3a; margin-bottom: 4px; text-transform: uppercase; }
.line { margin-bottom: 2px; }
.label { font-weight: 700; color: #1c2a39; }
.charges { width: 100%; border-collapse: collapse; margin-top: 8px; }
.charges th { background: #edf3f9; border: 1px solid #c5d1de; font-size: 10px; padding: 7px 6px; text-align: left; text-transform: uppercase; }
.charges td { border: 1px solid #d3dde8; padding: 7px 6px; }
.amount { text-align: right; white-space: nowrap; }
.totals-wrap { width: 100%; margin-top: 10px; }
.totals-left { width: 58%; vertical-align: top; font-size: 9.6px; color: #4b5968; }
.totals-right { width: 42%; vertical-align: top; }
.summary { width: 100%; border-collapse: collapse; }
.summary td { border: 1px solid #d0dae5; padding: 6px 8px; }
.summary .key { background: #f7f9fc; font-weight: 700; color: #2e3f51; }
.summary .val { text-align: right; width: 36%; font-weight: 700; }
.summary .net-row .key,
.summary .net-row .val { background: #edf3f9; font-size: 11px; }
.footer { margin-top: 16px; border-top: 1px solid #d0dae5; padding-top: 8px; }
.footer-left { float:left; width:60%; font-size: 9.6px; color: #4c5968; }
.footer-right { float:right; width:35%; text-align:right; }
.sign-line { margin-top: 18px; border-top: 1px solid #9aabbd; padding-top: 3px; font-size: 9.8px; color: #2d3c4b; }
.payment-details { font-size: 9.6px; color: #445; margin-top: 4px; line-height: 1.6; }
.amount-words { font-weight: 700; color: #1f2d3a; }
</style>
</head>
<body>
<div class="wrap">
<table class="top" cellspacing="0" cellpadding="0">
<tr>
<td style="width:14%;" class="top-logo">
<?php if ($logoSrc !== '') : ?>
<img class="logo-img" src="<?= esc($logoSrc) ?>" alt="Hospital Logo" />
<?php endif; ?>
</td>
<td style="width:66%;">
<div class="hospital-name" style="font-size: <?= (int) $hospitalNameFontSize ?>px;"><?= esc($hospitalName) ?></div>
<?php if ($hospitalAddress1 !== '' || $hospitalAddress2 !== '') : ?>
<div class="hospital-line"><?= esc(trim($hospitalAddress1 . ', ' . $hospitalAddress2, ', ')) ?></div>
<?php endif; ?>
<?php if ($hospitalPhone !== '' || $hospitalEmail !== '') : ?>
<div class="hospital-line">
<?= $hospitalPhone !== '' ? ('Phone: ' . esc($hospitalPhone)) : '' ?>
<?= ($hospitalPhone !== '' && $hospitalEmail !== '') ? ' | ' : '' ?>
<?= $hospitalEmail !== '' ? ('Email: ' . esc($hospitalEmail)) : '' ?>
</div>
<?php endif; ?>
</td>
<td style="width:20%;" class="qr-cell">
<div class="invoice-title">INVOICE</div>
<div class="invoice-sub"><?= esc($invoiceCode) ?></div>
<div class="invoice-status">
<div class="status-chip"><?= esc($invoiceStatus) ?></div>
</div>
<?php if ($qrContent !== '' && $qrPackageAvailable) : ?>
<div class="qr-block">
<barcode code="<?= esc($qrContent) ?>" size="0.62" type="QR" error="M" class="barcode" />
<div class="qr-label">Scan for info</div>
</div>
<?php endif; ?>
</td>
</tr>
</table>
<table class="meta meta-three" cellspacing="0" cellpadding="0">
<tr>
<td>
<div class="meta-title">Patient Details</div>
<div class="line"><span class="label">Patient ID:</span> <?= esc((string) ($patient->p_code ?? '')) ?></div>
<div class="line"><span class="label">Name:</span> <?= esc(trim((string) ($patient->p_fname ?? ''))) ?></div>
<div class="line"><span class="label">Gender:</span> <?= esc((string) ($patient->xgender ?? '')) ?></div>
<div class="line"><span class="label">Age:</span> <?= esc((string) ($patient->age ?? '')) ?></div>
<div class="line"><span class="label">Phone:</span> <?= esc((string) ($patient->mphone1 ?? '')) ?></div>
</td>
<td>
<div class="meta-title">Refer Details</div>
<div class="line"><span class="label">Refer By:</span> <?= esc((string) ($invoice->refer_by_other ?? '')) ?></div>
<div class="line"><span class="label">Invoice Date:</span> <?= esc($invoiceDate) ?></div>
<div class="line"><span class="label">Printed On:</span> <?= esc($printedOn) ?></div>
</td>
<td>
<div class="meta-title">Invoice Details</div>
<div class="line"><span class="label">Invoice ID:</span> <?= esc($invoiceCode) ?></div>
<div class="line"><span class="label">Status:</span> <?= esc($invoiceStatus) ?></div>
<div class="line"><span class="label">Payment Mode:</span> <?php
$mode = (int) ($invoice->payment_mode ?? 0);
echo $mode === 1 ? 'Cash' : ($mode === 2 ? 'Bank Card/Online' : ($mode === 3 ? 'IPD Credit' : ($mode === 4 ? 'Org. Credit' : 'Pending')));
?></div>
</td>
</tr>
</table>
<?php if (!empty($insuranceRow) || !empty($caseRow)) : ?>
<table class="meta meta-two" cellspacing="0" cellpadding="0" style="margin-top:-2px;">
<tr>
<td>
<div class="meta-title">Insurance / Organization</div>
<?php if (!empty($insuranceRow)) : ?>
<div class="line"><span class="label">Insurance:</span> <?= esc((string) ($insuranceRow->ins_company_name ?? '')) ?></div>
<?php endif; ?>
<?php if (!empty($caseRow)) : ?>
<div class="line"><span class="label">Org. Case No:</span> <?= esc((string) ($caseRow->case_id_code ?? '')) ?></div>
<?php endif; ?>
</td>
<td></td>
</tr>
</table>
<?php endif; ?>
<table class="charges">
<thead>
<tr>
<th style="width:5%;">#</th>
<th style="width:20%;">Charges Group</th>
<th style="width:30%;">Charge Name</th>
<th style="width:15%;">Rate</th>
<th style="width:15%;">Qty</th>
<th style="width:15%;" class="amount">Amount</th>
</tr>
</thead>
<tbody>
<?php $srno = 1; foreach ($invoiceDetails as $row) : ?>
<tr>
<td><?= $srno ?></td>
<td><?= esc((string) ($row->group_desc ?? '')) ?></td>
<td><?= esc((string) ($row->item_name ?? '')) ?></td>
<td class="amount"><?= esc((string) ($row->item_rate ?? '')) ?></td>
<td class="amount"><?= esc((string) ($row->item_qty ?? '')) ?></td>
<td class="amount"><?= esc($currencyPrefix) ?> <?= number_format((float) ($row->item_amount ?? 0), 2) ?></td>
</tr>
<?php $srno++; endforeach; ?>
<?php if ($discount > 0) : ?>
<tr>
<td colspan="5"><span class="label">Discount</span><?= !empty($invoice->discount_desc ?? '') ? (' - ' . esc((string) ($invoice->discount_desc ?? ''))) : '' ?></td>
<td class="amount">-<?= esc($currencyPrefix) ?> <?= number_format($discount, 2) ?></td>
</tr>
<?php endif; ?>
</tbody>
</table>
<table class="totals-wrap" cellspacing="0" cellpadding="0">
<tr>
<td class="totals-left">
<div class="payment-details">
<div><span class="label">Amount received:</span> <?= esc($currencyPrefix) ?> <?= number_format(0, 2) ?> | <span class="label">Balance Amount:</span> <?= esc($currencyPrefix) ?> <?= number_format($netAmount, 2) ?> | <span class="label">Net Amount:</span> <?= esc($currencyPrefix) ?> <?= number_format($netAmount, 2) ?></div>
<div style="margin-top:6px;"><span class="amount-words">Amount in Words: </span><?php
$amountInWords = convertNumberToWords((int)$netAmount);
echo esc($amountInWords) . ' Only';
?></div>
</div>
</td>
<td class="totals-right">
<table class="summary" cellspacing="0" cellpadding="0">
<tr>
<td class="key">Gross Total</td>
<td class="val"><?= esc($currencyPrefix) ?> <?= number_format($grossAmount, 2) ?></td>
</tr>
<?php if ($discount > 0) : ?>
<tr>
<td class="key">Discount</td>
<td class="val">-<?= esc($currencyPrefix) ?> <?= number_format($discount, 2) ?></td>
</tr>
<?php endif; ?>
<tr class="net-row">
<td class="key">Net Amount</td>
<td class="val"><?= esc($currencyPrefix) ?> <?= number_format($netAmount, 2) ?></td>
</tr>
</table>
</td>
</tr>
</table>
<div class="footer">
<div class="footer-left">
<div>This is a computer-generated invoice.</div>
<div>For billing assistance, contact hospital reception.</div>
</div>
<div class="footer-right">
<div class="sign-line">Authorized Signatory</div>
</div>
<div style="clear:both;"></div>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,372 @@
<style>
.ipd-reg-shell .ipd-modern-box {
border: 0;
border-radius: 14px;
overflow: hidden;
box-shadow: 0 14px 30px rgba(15, 23, 42, 0.08);
}
.ipd-reg-shell .ipd-modern-box > .box-header {
background: linear-gradient(120deg, #0f766e 0%, #0ea5a3 55%, #22c55e 100%);
color: #ffffff;
padding: 14px 18px;
border-bottom: 0;
}
.ipd-reg-shell .ipd-modern-box > .box-header .box-title p {
margin: 0;
font-size: 14px;
line-height: 1.5;
}
.ipd-reg-shell .box-body {
background: #f8fafc;
padding: 18px;
}
.ipd-reg-shell .form-group > label {
font-weight: 600;
color: #0f172a;
margin-bottom: 6px;
}
.ipd-reg-shell .form-control {
border-radius: 10px;
border: 1px solid #cbd5e1;
box-shadow: none;
transition: border-color .2s ease, box-shadow .2s ease;
}
.ipd-reg-shell .form-control:focus {
border-color: #0891b2;
box-shadow: 0 0 0 3px rgba(8, 145, 178, 0.15);
}
.ipd-reg-shell .input-group-addon {
border-radius: 10px 0 0 10px;
border-color: #cbd5e1;
background: #f1f5f9;
color: #334155;
}
.ipd-reg-shell .doctor-pick-list {
max-height: 220px;
overflow: auto;
padding: 10px;
background: #ffffff;
border: 1px solid #e2e8f0;
border-radius: 10px;
}
.ipd-reg-shell .doctor-pick-list label {
display: block;
padding: 3px 0;
margin: 0;
font-weight: 500;
}
.ipd-reg-shell .box .box-header {
background: #e2e8f0;
border-bottom: 1px solid #cbd5e1;
}
.ipd-reg-shell #btnnextconfirm {
border-radius: 10px;
padding: 10px 16px;
font-weight: 600;
background: linear-gradient(120deg, #0c4a6e 0%, #0369a1 100%);
border: 0;
}
</style>
<section class="content-header">
<h1>
IPD
<small>Registration</small>
</h1>
<ol class="breadcrumb">
<li><a href="#"><i class="fa fa-dashboard"></i> Home</a></li>
<li class="active">OPD</li>
</ol>
</section>
<?php if (empty($person_info)): ?>
<div class="alert alert-danger">Patient not found.</div>
<?php else: ?>
<form action="<?= base_url('IpdNew/AddNew') ?>" role="form" class="form1 ipd-reg-shell" method="post" accept-charset="utf-8">
<?= csrf_field() ?>
<div class="box box-danger ipd-modern-box">
<div class="box-header">
<div class="box-title">
<p>
<strong>Name :</strong><?= esc($person_info->p_fname ?? '') ?>
<strong><?= esc($person_info->p_relative ?? '') ?> </strong><?= esc($person_info->p_rname ?? '') ?>
<strong>/ Age :</strong><?= esc($person_info->age ?? '') ?>
<strong>/ Gender :</strong><?= esc($person_info->xgender ?? '') ?>
<strong>/ P Code :</strong><?= esc($person_info->p_code ?? '') ?>
</p>
<input type="hidden" id="pid" name="pid" value="<?= esc($person_info->id ?? 0) ?>" />
<input type="hidden" id="pname" name="pname" value="<?= esc($person_info->p_fname ?? '') ?>" />
</div>
</div>
<div class="box-body">
<div class="jsError"></div>
<div class="row">
<div class="col-md-3">
<div class="form-group">
<label>Relative or Responsible Person Name</label>
<input type="text" class="form-control" id="rp_name" name="rp_name" placeholder="Name" value="">
</div>
</div>
<div class="col-md-3">
<div class="form-group">
<label>Relation</label>
<input type="text" class="form-control" id="r_relation" name="r_relation" placeholder="Relation" value="">
</div>
</div>
</div>
<div class="row">
<div class="col-md-3">
<div class="form-group">
<label>Phone No. 1</label>
<div class="input-group">
<div class="input-group-addon">
<i class="fa fa-phone"></i>
</div>
<input type="text" name="phone1" id="phone1" class="form-control" data-inputmask='"mask": "9999999999"' data-mask value="<?= esc($person_info->mphone1 ?? '') ?>">
</div>
</div>
</div>
<div class="col-md-3">
<div class="form-group">
<label>Phone No. 2</label>
<div class="input-group">
<div class="input-group-addon">
<i class="fa fa-phone"></i>
</div>
<input type="text" name="phone2" id="phone2" class="form-control" data-inputmask='"mask": "9999999999"' data-mask>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-3">
<div class="form-group">
<label>Date</label>
<div class="input-group date">
<div class="input-group-addon">
<i class="fa fa-calendar"></i>
</div>
<input id="res_date_display" class="form-control pull-right" type="date" value="<?= date('Y-m-d') ?>" required>
<input id="res_date" name="res_date" type="hidden" value="<?= date('d/m/Y') ?>" />
</div>
</div>
</div>
<div class="col-md-3">
<div>
<div class="form-group">
<label>Time: (24 Hour Format)</label>
<div class="input-group">
<input id="res_time" name="res_time" class="form-control" type="time" value="<?= date('H:i') ?>" step="60" required>
<div class="input-group-addon">
<i class="fa fa-clock-o"></i>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-3">
<div class="form-group">
<div class="radio">
<label>
<input name="optionsRadios_mlc" id="options_mlc1" value="0" type="radio" checked="checked">
NON MLC
</label>
<label>
<input name="optionsRadios_mlc" id="options_mlc2" value="1" type="radio">
MLC
</label>
</div>
</div>
</div>
</div>
<?php if (!empty($case_master)): ?>
<div class="row">
<div class="col-md-3">
<div class="form-group">
<div class="radio">
<label>
<input name="optionsRadios_org" id="options_org1" value="0" type="radio">
Cash
</label>
<label>
<input name="optionsRadios_org" id="options_morg2" value="<?= esc($case_master[0]->id ?? 0) ?>" type="radio" checked="checked">
Org. Credit : <?= esc($case_master[0]->case_id_code ?? '') ?>
</label>
</div>
</div>
</div>
</div>
<?php else: ?>
<input name="optionsRadios_org" id="options_morg2" value="0" type="hidden">
<?php endif; ?>
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label>Department </label>
<select class="form-control" name="dept_id" id="dept_id">
<option value="0">Select Department</option>
<?php foreach ($hc_department as $row): ?>
<option value="<?= esc($row->iId ?? 0) ?>"><?= esc($row->vName ?? '') ?></option>
<?php endforeach; ?>
</select>
</div>
</div>
</div>
<hr />
<div class="row">
<div class="col-md-6">
<div class="form-group doctor-pick-list">
<label>Doctor </label>
<br />
<?php foreach ($doc_spec_l as $row): ?>
<label><input type="checkbox" name="doc_id[]" class="flat-red" value="<?= esc($row->id ?? 0) ?>"> <?= esc($row->p_fname ?? '') ?> [<i><?= esc($row->SpecName ?? '') ?></i>]</label><br/>
<?php endforeach; ?>
</div>
</div>
</div>
<hr />
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label>Request Room Type</label>
<select class="form-control" name="room_list" id="room_list">
<option value="0">Select BED</option>
<?php foreach ($ipd_bed_list as $row): ?>
<option value="<?= esc($row->id ?? 0) ?>"><?= esc($row->Bed_Desc ?? '') ?></option>
<?php endforeach; ?>
</select>
</div>
</div>
</div>
<hr />
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label>Refer By</label>
<select class="form-control" name="refer_by_list" id="refer_by_list">
<option value="0">Select Refer By</option>
<?php foreach ($refer_master as $row): ?>
<option value="<?= esc($row->id ?? 0) ?>"><?= esc(trim(($row->title ?? '') . ' ' . ($row->f_name ?? ''))) ?></option>
<?php endforeach; ?>
</select>
</div>
</div>
</div>
<hr />
<div class="row">
<div class="col-md-6">
<div class="form-group">
<label>Reason of visit / Problem / Diagnosis</label>
<input class="form-control" type="text" id="problem" name="problem" />
</div>
<div class="row">
<div class="col-md-12">
<div class="box">
<div class="box-header">
<h3 class="box-title">Remarks
<small>Write some about the problem</small>
</h3>
<div class="pull-right box-tools">
<button type="button" class="btn btn-default btn-sm" data-widget="collapse" data-toggle="tooltip" title="Collapse">
<i class="fa fa-minus"></i></button>
<button type="button" class="btn btn-default btn-sm" data-widget="remove" data-toggle="tooltip" title="Remove">
<i class="fa fa-times"></i></button>
</div>
</div>
<div class="box-body pad">
<textarea id="remark" name="remark" class="textarea" placeholder="Place some text here" style="width: 100%; height: 200px; font-size: 14px; line-height: 18px; border: 1px solid #dddddd; padding: 10px;"></textarea>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-6">
<div class="form-group">
<button type="submit" class="btn btn-primary" id="btnnextconfirm">Confirm And Go for Admit</button>
</div>
</div>
</div>
</div>
<div class="box-footer"></div>
</div>
</div>
</div>
</form>
<script>
$(function() {
function formatLegacyDate(dateValue) {
if (!dateValue) {
return '';
}
var parts = String(dateValue).split('-');
if (parts.length !== 3) {
return dateValue;
}
return [parts[2], parts[1], parts[0]].join('/');
}
function syncLegacyDateField() {
$('#res_date').val(formatLegacyDate($('#res_date_display').val()));
}
syncLegacyDateField();
$('#res_date_display').on('change', syncLegacyDateField);
$('#res_date_display, #res_time').on('focus click', function() {
if (typeof this.showPicker === 'function') {
this.showPicker();
}
});
if ($.fn && typeof $.fn.datepicker === 'function') {
$('#res_date_display').datepicker('destroy');
}
});
$(document).ready(function() {
$('form.form1').on('submit', function(form) {
form.preventDefault();
$('#res_date').val((function(dateValue) {
if (!dateValue) {
return '';
}
var parts = String(dateValue).split('-');
return parts.length === 3 ? [parts[2], parts[1], parts[0]].join('/') : dateValue;
})($('#res_date_display').val()));
var room_list = $('#room_list').val();
if (room_list === '' || room_list === '0') {
alert('Please Select Room');
return;
}
$.post('<?= base_url('IpdNew/AddNew') ?>', $('form.form1').serialize(), function(data) {
if (Number(data.insertid || 0) === 0) {
$('div.jsError').html(data.error_text || 'Unable to admit patient.');
} else {
load_form('<?= base_url('IpdNew/ipd_panel') ?>/' + data.insertid);
}
}, 'json');
});
});
</script>
<?php endif; ?>