diff --git a/app/Config/Routes.php b/app/Config/Routes.php index be384ea..0c7732e 100644 --- a/app/Config/Routes.php +++ b/app/Config/Routes.php @@ -459,6 +459,7 @@ $routes->group('billing', function($routes) { $routes->post('ipd/nursing-charge/delete/(:num)/(:num)', 'Billing\\Ipd::deleteNursingCharge/$1/$2'); $routes->post('ipd/charge/package/(:num)', 'Billing\\Ipd::updateIpdChargePackage/$1'); $routes->post('ipd/package/add/(:num)', 'Billing\\Ipd::addIpdPackage/$1'); + $routes->get('ipd/medical-bill/(:num)/(:num)', 'Billing\\Ipd::medicalBillDetails/$1/$2'); $routes->post('ipd/medical-bill/credit-type/(:num)', 'Billing\\Ipd::updateMedicalBillCreditType/$1'); $routes->get('ipd/panel/(:num)/ayushman/search', 'Billing\Ipd::searchAyushmanPackages/$1'); $routes->post('ipd/panel/(:num)/ayushman/map/(:num)', 'Billing\Ipd::saveAyushmanPackageMapping/$1/$2'); diff --git a/app/Controllers/Billing/Ipd.php b/app/Controllers/Billing/Ipd.php index 67a705c..b7d5294 100644 --- a/app/Controllers/Billing/Ipd.php +++ b/app/Controllers/Billing/Ipd.php @@ -1976,6 +1976,28 @@ class Ipd extends BaseController return $this->response->setJSON(['ok' => $result === 1]); } + public function medicalBillDetails(int $ipdId, int $invoiceId) + { + $permission = $this->requireAnyPermission([ + 'billing.access', + 'billing.ipd.invoice', + ]); + if ($permission) { + return $permission; + } + + if (! $this->request->isAJAX()) { + return $this->response->setStatusCode(400)->setBody('Invalid request'); + } + + $details = $this->ipdModel->getMedicalBillDetails($ipdId, $invoiceId); + if (empty($details)) { + return $this->response->setStatusCode(404)->setBody('Medical bill not found for this admission.'); + } + + return view('billing/ipd/panel_medical_bill_details', $details); + } + public function updateMedicalBillCreditType(int $invoiceId) { $permission = $this->requireAnyPermission([ @@ -1999,14 +2021,21 @@ class Ipd extends BaseController return $this->response->setStatusCode(422)->setJSON(['ok' => false, 'error' => 'Medical bill credit type column not available']); } + $ipdId = (int) ($this->request->getPost('ipd_id') ?? 0); + if ($ipdId <= 0) { + return $this->response->setStatusCode(422)->setJSON(['ok' => false, 'error' => 'IPD admission is required']); + } + $invoice = $this->db->table('invoice_med_master') - ->select('id,ipd_id') + ->select('id,ipd_id,ipd_credit') ->where('id', $invoiceId) + ->where('ipd_id', $ipdId) + ->where('ipd_credit', 1) ->get(1) ->getRowArray(); if (empty($invoice)) { - return $this->response->setStatusCode(404)->setJSON(['ok' => false, 'error' => 'Medical bill not found']); + return $this->response->setStatusCode(404)->setJSON(['ok' => false, 'error' => 'IPD credit bill not found for this admission']); } $creditType = (int) ($this->request->getPost('ipd_credit_type') ?? 0) === 1 ? 1 : 0; @@ -2014,25 +2043,30 @@ class Ipd extends BaseController 'ipd_credit_type' => $creditType, ]; - if (in_array('ipd_credit', $fields, true)) { - $update['ipd_credit'] = 1; - } - if (in_array('ipd_credit_type_update', $fields, true)) { $user = function_exists('auth') ? auth()->user() : null; $userId = (int) ($user->id ?? 0); $userName = (string) ($user->username ?? $user->email ?? 'user'); - $update['ipd_credit_type_update'] = $userName . '[' . $userId . '] D:' . date('d-m-Y h:i:s'); + $typeLabel = $creditType === 1 ? 'Include in Bill' : 'In Package'; + $update['ipd_credit_type_update'] = $typeLabel . ' by ' . $userName . '[' . $userId . '] D:' . date('d-m-Y H:i:s'); } - $this->db->table('invoice_med_master') + $updated = $this->db->table('invoice_med_master') ->where('id', $invoiceId) + ->where('ipd_id', $ipdId) + ->where('ipd_credit', 1) ->update($update); + if (! $updated) { + return $this->response->setStatusCode(500)->setJSON(['ok' => false, 'error' => 'Unable to update medical bill type']); + } + + $this->recalculateIpdBillingSafely($ipdId, 'medical-bill.credit-type'); + return $this->response->setJSON([ 'ok' => true, 'invoice_id' => $invoiceId, - 'ipd_id' => (int) ($invoice['ipd_id'] ?? 0), + 'ipd_id' => $ipdId, 'ipd_credit_type' => $creditType, ]); } diff --git a/app/Models/IpdBillingModel.php b/app/Models/IpdBillingModel.php index 407fb96..03e685a 100644 --- a/app/Models/IpdBillingModel.php +++ b/app/Models/IpdBillingModel.php @@ -677,12 +677,37 @@ class IpdBillingModel extends Model public function getMedicalBills(int $ipdId): array { return $this->db->table('invoice_med_master') + ->where('ipd_id >', 0) ->where('ipd_id', $ipdId) + ->where('ipd_credit', 1) ->orderBy('id', 'DESC') ->get() ->getResult(); } + public function getMedicalBillDetails(int $ipdId, int $invoiceId): array + { + $invoice = $this->db->table('invoice_med_master') + ->where('id', $invoiceId) + ->where('ipd_id', $ipdId) + ->where('ipd_credit', 1) + ->get(1) + ->getRow(); + + if ($invoice === null) { + return []; + } + + return [ + 'invoice' => $invoice, + 'items' => $this->db->table('inv_med_item') + ->where('inv_med_id', $invoiceId) + ->orderBy('id', 'ASC') + ->get() + ->getResult(), + ]; + } + public function getBillDetails(int $ipdId): array { return $this->db->table('ipd_master') diff --git a/app/Views/billing/ipd/panel_medical_bill_details.php b/app/Views/billing/ipd/panel_medical_bill_details.php new file mode 100644 index 0000000..45aa964 --- /dev/null +++ b/app/Views/billing/ipd/panel_medical_bill_details.php @@ -0,0 +1,56 @@ + $items */ +$invoiceCode = (string) ($invoice->inv_med_code ?? $invoice->id ?? ''); +?> + +
+
+ Invoice ID: + + Print + +
+
+
+ + + + + + + + + + + + + $item) : ?> + item_Name ?? $item->item_name ?? '')); + $formulation = trim((string) ($item->formulation ?? '')); + ?> + + + + + + + + + + + + + + + + + + + + +
#Item NameQty.PriceAmount
qty ?? '') ?>price ?? 0), 2) ?>tamount ?? 0), 2) ?>
No invoice items found.
Totalnet_amount ?? 0), 2) ?>
+
+
+
diff --git a/app/Views/billing/ipd/panel_medical_bills.php b/app/Views/billing/ipd/panel_medical_bills.php index 73e92ae..23d5d05 100644 --- a/app/Views/billing/ipd/panel_medical_bills.php +++ b/app/Views/billing/ipd/panel_medical_bills.php @@ -1,3 +1,9 @@ +id ?? 0); +$csrfName = csrf_token(); +$csrfHash = csrf_hash(); +?> +
@@ -6,7 +12,8 @@ - + + @@ -17,15 +24,85 @@ - - + + + - +
Invoice Code Date AmountStatusBill TypeAction
inv_med_code ?? $row->id ?? '') ?> inv_date ?? '') ?>net_amount ?? '') ?>payment_status ?? 0) > 0) ? 'Paid' : 'Pending' ?>net_amount ?? 0), 2) ?> + ipd_credit_type ?? 0) === 1; ?> +
+ + onchange="ipdMedicalBillsToggleType(this, id ?>)"> + +
+
+ +
No medical bills found.No IPD credit medical bills found.
+ +
+ + diff --git a/app/Views/billing/ipd/panel_package.php b/app/Views/billing/ipd/panel_package.php index d8df374..5768cb1 100644 --- a/app/Views/billing/ipd/panel_package.php +++ b/app/Views/billing/ipd/panel_package.php @@ -542,6 +542,7 @@ $ayushmanChecklistItems = $ayushman_checklist_items ?? []; function ipdMedicalBillToggleType(checkbox, invoiceId) { var payload = {}; payload[ipdPackageCsrfName] = ipdPackageCsrfHash; + payload.ipd_id = ipdPackageIpdId; payload.ipd_credit_type = checkbox.checked ? 1 : 0; $.post(ipdMedicalBillCreditTypeUrlBase + '/' + invoiceId, payload, function(resp) {