devsofttech_hms_ci4/app/Models/IpdBillingModel.php

610 lines
22 KiB
PHP

<?php
namespace App\Models;
use CodeIgniter\Model;
class IpdBillingModel extends Model
{
protected $table = 'v_ipd_list';
public function getCurrentAdmissions(): array
{
$builder = $this->baseIpdListQuery();
$builder->select("i.id,i.ipd_code,p.p_code,p.p_fname,p.p_rname,")
->select("concat('Bed No :',b.bed_number,'[',w.ward_name,']') as Bed_Desc,")
->select("date_format(i.register_date,'%d-%m-%Y') as str_register_date,")
->select("if(i.ipd_status = 0,(to_days(sysdate()) - to_days(i.register_date)),(to_days(i.discharge_date) - to_days(i.register_date))) as no_days,")
->select("ipd_doc_list.doc_name as doc_name,")
->select("if((o.id is not null),in_master.short_name,'Direct') as admit_type,")
->select("if((o.id is not null),concat(s.app_status,'/',o.org_approved_amount),'') as Org_Status,")
->select("o.insurance_no_1 as insurance_no_1,")
->select("i.charge_amount as charge_amount,i.med_amount as med_amount,i.total_paid_amount as paid_amount,")
->select("(i.total_paid_amount - (i.charge_amount + i.med_amount)) as balance,")
->select("s.color as color", false)
->where('i.ipd_status', 0);
return $builder->get()->getResult();
}
public function getIpdTableData(array $request): array
{
$columns = [
'ipd_code',
'p_code',
'p_fname',
'admit_type',
'insurance_no_1',
'doc_name',
'Disstatus',
'str_register_date',
'str_discharge_date',
'status_desc',
];
$totalBuilder = $this->baseIpdListQuery();
$totalData = $totalBuilder->countAllResults();
$filteredBuilder = $this->baseIpdListQuery();
$this->applyDataTableFilters($filteredBuilder, $request);
$totalFiltered = $filteredBuilder->countAllResults();
$dataBuilder = $this->baseIpdListQuery();
$this->applyDataTableFilters($dataBuilder, $request);
$orderColumn = $columns[0];
$orderDir = 'desc';
if (! empty($request['order'][0]['column']) && is_numeric($request['order'][0]['column'])) {
$orderIndex = (int) $request['order'][0]['column'];
$orderColumn = $columns[$orderIndex] ?? $columns[0];
$orderDir = ($request['order'][0]['dir'] ?? 'desc') === 'asc' ? 'asc' : 'desc';
}
$start = isset($request['start']) ? (int) $request['start'] : 0;
$length = isset($request['length']) ? (int) $request['length'] : 10;
$rows = $dataBuilder
->select(
"i.ipd_code,p.p_code,p.p_fname,
if((o.id is not null),in_master.short_name,'Direct') as admit_type,
o.insurance_no_1 as insurance_no_1,
ipd_doc_list.doc_name as doc_name,
if(i.ipd_status = 1,'Discharged','Admit') as Disstatus,
date_format(i.register_date,'%d-%m-%Y') as str_register_date,
date_format(i.discharge_date,'%d-%m-%Y') as str_discharge_date,
d.status_desc as status_desc",
false
)
->orderBy($orderColumn, $orderDir)
->limit($length, $start)
->get()
->getResultArray();
$data = [];
foreach ($rows as $row) {
$item = [];
foreach ($columns as $column) {
$item[] = $row[$column] ?? '';
}
$data[] = $item;
}
return [
'draw' => (int) ($request['draw'] ?? 0),
'recordsTotal' => (int) $totalData,
'recordsFiltered' => (int) $totalFiltered,
'data' => $data,
];
}
public function getCashBalanceReport(string $start, string $end): array
{
$builder = $this->baseIpdListQuery();
$builder
->select("i.ipd_code,p.p_fname,date_format(i.register_date,'%d-%m-%Y') as str_register_date,")
->select("p.p_code,concat(i.contact_person_Name,'M:',i.P_mobile1,' ;',p.mphone1,' ;',i.P_mobile2) as Contact_info,")
->select("date_format(i.discharge_date,'%d-%m-%Y') as str_discharge_date,")
->select("if((o.id is not null),in_master.short_name,'Direct') as admit_type,")
->select("ipd_doc_list.doc_name as doc_name,")
->select("concat('Bed No :',b.bed_number,'[',w.ward_name,']') as Bed_Desc,")
->select("if((o.id is not null),'0','1') as Direct_Cust,")
->select("i.net_amount,i.balance_amount,(i.org_amount_recived+i.total_paid_amount) as sum_of_paid",
false)
->where('i.balance_amount >', 0, false)
->where('i.ipd_status', 1)
->where('o.id', null)
->where("i.register_date >=", $start)
->where("i.register_date <=", $end)
->groupBy('p.id,ipd_doc_list.doc_list')
->orderBy('i.id');
return $builder->get()->getResult();
}
public function getIpdPanelInfo(int $ipdId): array
{
$ipdInfo = $this->db->table('ipd_master i')
->select("i.*, date_format(i.register_date,'%d-%m-%Y') as str_register_date,")
->select("date_format(i.discharge_date,'%d-%m-%Y') as str_discharge_date,")
->select("if(i.ipd_status = 0,(to_days(sysdate()) - to_days(i.register_date)),(to_days(i.discharge_date) - to_days(i.register_date))) as no_days,")
->select("in_master.ins_company_name as ins_company_name", false)
->select("in_master.short_name as ins_short_name", false)
->select("o.case_id_code as case_id_code", false)
->select("o.insurance_no as insurance_no", false)
->select("o.insurance_no_1 as insurance_no_1", false)
->select("o.insurance_no_2 as insurance_no_2", false)
->join('organization_case_master o', 'i.case_id = o.id', 'left')
->join('hc_insurance in_master', 'in_master.id = o.insurance_id', 'left')
->where('i.id', $ipdId)
->get()
->getRow();
if (! $ipdInfo) {
return [];
}
$patient = $this->db->table('patient_master p')
->select("p.*, if(p.gender = 1, 'Male', 'Female') as xgender", false)
->where('p.id', $ipdInfo->p_id)
->get()
->getRow();
return [
'ipd_info' => $ipdInfo,
'person_info' => $patient,
];
}
public function getIpdCharges(int $ipdId): array
{
return $this->db->table('ipd_invoice_item i')
->select('i.*, t.group_desc')
->join('ipd_item_type t', 'i.item_type = t.itype_id', 'left')
->where('i.ipd_id', $ipdId)
->orderBy('i.id', 'DESC')
->get()
->getResult();
}
public function getIpdChargesGrouped(int $ipdId): array
{
return $this->db->table('ipd_invoice_item i')
->select('t.group_desc, i.*, sum(i.item_amount) as xAmount')
->join('ipd_item_type t', 'i.item_type = t.itype_id', 'left')
->where('i.ipd_id', $ipdId)
->groupBy('i.item_type,i.id')
->orderBy('i.item_type', 'ASC')
->orderBy('i.id', 'ASC')
->get()
->getResult();
}
public function getIpdChargesTotal(int $ipdId): float
{
$row = $this->db->table('ipd_invoice_item')
->select('sum(item_amount) as total_amount')
->where('ipd_id', $ipdId)
->get()
->getRow();
return (float) ($row->total_amount ?? 0);
}
public function getIpdCaseMeta(int $ipdId): array
{
$row = $this->db->table('ipd_master i')
->select('o.insurance_id')
->join('organization_case_master o', 'i.case_id = o.id', 'left')
->where('i.id', $ipdId)
->get()
->getRowArray();
return $row ?? [];
}
public function getIpdDoctorList(): array
{
return $this->db->table('doctor_master d')
->select("d.id, d.p_fname, concat(d.p_fname,' [',group_concat(m.SpecName),']') as DocSpecName", false)
->join('doc_spec s', 'd.id = s.doc_id', 'inner')
->join('med_spec m', 's.med_spec_id = m.id', 'inner')
->where('d.active', 1)
->groupBy('d.id')
->orderBy('d.p_fname', 'ASC')
->get()
->getResult();
}
public function getDoctorVisitFeeTypes(): array
{
if (! $this->db->tableExists('doc_ipd_fee_type')) {
return [];
}
return $this->db->table('doc_ipd_fee_type')
->select('id, fee_type')
->orderBy('fee_type', 'ASC')
->get()
->getResultArray();
}
public function getDoctorVisitFeeMap(array $doctorIds): array
{
if (empty($doctorIds) || ! $this->db->tableExists('doc_ipd_fee') || ! $this->db->tableExists('doc_ipd_fee_type')) {
return [];
}
$builder = $this->db->table('doc_ipd_fee d')
->select('d.doc_id, d.doc_fee_type as fee_type_id, d.doc_fee_desc, d.amount, t.fee_type')
->join('doc_ipd_fee_type t', 't.id = d.doc_fee_type', 'left')
->whereIn('d.doc_id', array_map('intval', $doctorIds));
if ($this->db->fieldExists('isdelete', 'doc_ipd_fee')) {
$builder->where('d.isdelete', 0);
}
$rows = $builder->orderBy('d.id', 'ASC')->get()->getResultArray();
$map = [];
foreach ($rows as $row) {
$docId = (int) ($row['doc_id'] ?? 0);
$feeTypeId = (int) ($row['fee_type_id'] ?? 0);
if ($docId <= 0 || $feeTypeId <= 0) {
continue;
}
$feeType = (string) ($row['fee_type'] ?? '');
$feeDesc = trim((string) ($row['doc_fee_desc'] ?? ''));
if ($feeDesc === '') {
$feeDesc = $feeType;
}
$map[$docId][$feeTypeId] = [
'fee_type_id' => $feeTypeId,
'fee_type' => $feeType,
'fee_desc' => $feeDesc,
'amount' => (float) ($row['amount'] ?? 0),
];
}
return $map;
}
public function getDoctorVisitFeeDetail(int $docId, int $feeTypeId = 0): ?array
{
if ($docId <= 0 || ! $this->db->tableExists('doc_ipd_fee') || ! $this->db->tableExists('doc_ipd_fee_type')) {
return null;
}
$builder = $this->db->table('doc_ipd_fee d')
->select('d.id, d.doc_id, d.doc_fee_type as fee_type_id, d.doc_fee_desc, d.amount, t.fee_type')
->join('doc_ipd_fee_type t', 't.id = d.doc_fee_type', 'left')
->where('d.doc_id', $docId);
if ($this->db->fieldExists('isdelete', 'doc_ipd_fee')) {
$builder->where('d.isdelete', 0);
}
if ($feeTypeId > 0) {
$builder->where('d.doc_fee_type', $feeTypeId);
}
$row = $builder->orderBy('d.id', 'ASC')->get()->getRowArray();
if (! is_array($row) || empty($row)) {
return null;
}
$feeType = (string) ($row['fee_type'] ?? '');
$feeDesc = trim((string) ($row['doc_fee_desc'] ?? ''));
if ($feeDesc === '') {
$feeDesc = $feeType;
}
return [
'id' => (int) ($row['id'] ?? 0),
'doc_id' => (int) ($row['doc_id'] ?? 0),
'fee_type_id' => (int) ($row['fee_type_id'] ?? 0),
'fee_type' => $feeType,
'fee_desc' => $feeDesc,
'amount' => (float) ($row['amount'] ?? 0),
];
}
public function getBankPaymentSources(): array
{
return $this->db->table('hospital_bank m')
->select('s.id,s.pay_type,m.bank_name')
->join('hospital_bank_payment_source s', 'm.id = s.bank_id')
->get()
->getResult();
}
public function getDoctorNameById(int $docId): string
{
$row = $this->db->table('doctor_master')
->select('p_fname')
->where('id', $docId)
->get()
->getRow();
return (string) ($row->p_fname ?? '');
}
public function getIpdPackages(int $ipdId): array
{
return $this->db->table('ipd_package')
->where('ipd_id', $ipdId)
->orderBy('id', 'DESC')
->get()
->getResult();
}
public function getIpdInvoiceItems(int $ipdId, bool $excludePackage = false): array
{
$builder = $this->db->table('ipd_invoice_item i')
->select('t.group_desc,i.*')
->join('ipd_item_type t', 'i.item_type = t.itype_id', 'left')
->where('i.ipd_id', $ipdId);
if ($excludePackage) {
$builder->where('i.package_id', 0);
}
return $builder
->orderBy('t.group_desc', 'ASC')
->orderBy('i.id', 'ASC')
->get()
->getResult();
}
public function getIpdInvoiceCharges(int $ipdId): array
{
return $this->db->table('invoice_master i')
->select('l.group_desc as Charge_type,t.item_name as idesc,t.item_rate,')
->select('t.org_code as orgcode,sum(t.item_qty) as no_qty,sum(t.item_amount) as amount', false)
->join('invoice_item t', 't.inv_master_id = i.id')
->join('hc_item_type l', 't.item_type = l.itype_id', 'left')
->where('i.ipd_id', $ipdId)
->where('i.ipd_include', 1)
->groupBy('i.ipd_id,t.item_id,t.item_rate,l.group_desc,t.org_code,t.item_name')
->orderBy('Charge_type', 'ASC')
->get()
->getResult();
}
public function getIpdMedicalCredits(int $ipdId): array
{
return $this->db->table('invoice_med_master')
->where('ipd_credit', 1)
->where('ipd_credit_type', 1)
->where('ipd_id', $ipdId)
->orderBy('id', 'DESC')
->get()
->getResult();
}
public function getIpdInsurance(int $ipdId): array
{
$row = $this->db->table('ipd_master i')
->select('ins.*')
->join('organization_case_master o', 'i.case_id = o.id', 'left')
->join('hc_insurance ins', 'ins.id = o.insurance_id', 'left')
->where('i.id', $ipdId)
->get()
->getRowArray();
return $row ?? [];
}
public function getPackageListForInsurance(int $insuranceId): array
{
return $this->db->table('package p')
->select('p.id,p.ipd_pakage_name,p.Pakage_Min_Amount,i.hc_insurance_id,')
->select('i.code,if(i.hc_insurance_id is null,p.Pakage_Min_Amount,i.i_amount) as amount1', false)
->select("if(i.hc_insurance_id is null,Concat(' Rs. ',p.Pakage_Min_Amount),Concat('[ Rs. ',i.i_amount,' /Org.Code ',i.code,']')) as org_code", false)
->join(
'package_insurance i',
'p.id = i.hc_items_id and i.hc_insurance_id = ' . (int) $insuranceId,
'left'
)
->orderBy('p.ipd_pakage_name', 'ASC')
->get()
->getResult();
}
public function getPackageWithInsurance(int $packageId, int $insuranceId): ?object
{
return $this->db->table('package p')
->select('p.id,p.ipd_pakage_name,p.Pakage_Min_Amount,p.Pakage_description,')
->select('i.hc_insurance_id,i.code,if(i.hc_insurance_id is null,p.Pakage_Min_Amount,i.i_amount) as amount1', false)
->join(
'package_insurance i',
'p.id = i.hc_items_id and i.hc_insurance_id = ' . (int) $insuranceId,
'left'
)
->where('p.id', $packageId)
->get()
->getRow();
}
public function getDiagnosisCharges(int $ipdId): array
{
return $this->db->table('invoice_master i')
->select("i.id as inv_id,i.invoice_code,sum(t.item_amount) as amount,i.refer_by_other,")
->select("date_format(i.inv_date,'%d-%m-%Y') as str_date,i.ipd_include,")
->select('group_concat(distinct c.group_desc) as charge_list', false)
->join('invoice_item t', 'i.id = t.inv_master_id', 'left')
->join('hc_item_type c', 't.item_type = c.itype_id', 'left')
->where('i.payment_status', 1)
->where('i.ipd_id', $ipdId)
->groupBy('i.id')
->orderBy('i.id', 'DESC')
->get()
->getResult();
}
public function getPayments(int $ipdId): array
{
return $this->db->table('payment_history')
->select("*,date_format(payment_date,'%d-%M-%Y') as pay_date_str,")
->select("concat(if(payment_mode=1,'Cash','BANK'),if(credit_debit=0,'','-Return')) as pay_mode", false)
->where('payof_type', 4)
->where('payof_id', $ipdId)
->orderBy('id', 'DESC')
->get()
->getResult();
}
public function getMedicalBills(int $ipdId): array
{
return $this->db->table('invoice_med_master')
->where('ipd_id', $ipdId)
->orderBy('id', 'DESC')
->get()
->getResult();
}
public function getBillDetails(int $ipdId): array
{
return $this->db->table('ipd_master')
->where('id', $ipdId)
->get()
->getResult();
}
public function getDischargeInfo(int $ipdId): array
{
return $this->db->table('ipd_master i')
->select('i.*, d.status_desc')
->join('ipd_discharg_status d', 'i.discarge_patient_status = d.id', 'left')
->where('i.id', $ipdId)
->get()
->getResult();
}
public function getNursingChargeHistory(int $ipdId): array
{
if (! $this->db->tableExists('nursing_ipd_charges')) {
return [];
}
$builder = $this->db->table('nursing_ipd_charges')
->select('charge_id, item_name, item_type, doctor_name, visit_date, visit_time, qty, rate, amount, remarks, include_in_bill')
->where('ipd_id', $ipdId);
if ($this->db->fieldExists('include_in_bill', 'nursing_ipd_charges')) {
$builder->where('include_in_bill', 1);
}
return $builder
->orderBy('charge_id', 'DESC')
->get()
->getResultArray();
}
private function baseIpdListQuery()
{
$builder = $this->db->table('ipd_master i');
$builder->join('patient_master p', 'i.p_id = p.id');
$builder->join('ipd_discharg_status d', 'i.discarge_patient_status = d.id');
$builder->join(
'(organization_case_master o join hc_insurance in_master on in_master.id = o.insurance_id'
. ' join org_approved_status s on o.org_approved_status_id = s.id)',
'i.case_id = o.id',
'left',
false
);
$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
);
$builder->join('bed_assignment_history bah', 'bah.id = bah_latest.id', 'left');
$builder->join('bed_master b', 'b.id = bah.bed_id', 'left');
$builder->join('ward_master w', 'w.id = bah.ward_id', 'left');
$builder->join(
"(select i.ipd_id,
group_concat(distinct concat_ws(' ', 'Dr.', d.p_fname, d.p_mname, d.p_lname)) as doc_name,
group_concat(distinct d.id) as doc_list
from ipd_master_doc_list i
join doctor_master d on i.doc_id = d.id
group by i.ipd_id) ipd_doc_list",
'i.id = ipd_doc_list.ipd_id',
'left',
false
);
return $builder;
}
private function applyDataTableFilters($builder, array $request): void
{
$columns = $request['columns'] ?? [];
$ipdCode = trim((string) ($columns[0]['search']['value'] ?? ''));
if ($ipdCode !== '') {
$builder->like('ipd_code', $ipdCode, 'both');
}
$pCode = trim((string) ($columns[1]['search']['value'] ?? ''));
if ($pCode !== '') {
$builder->like('p_code', $pCode, 'after');
}
$pName = trim((string) ($columns[2]['search']['value'] ?? ''));
if ($pName !== '') {
$builder->like('p_fname', $pName, 'both');
}
$admitType = trim((string) ($columns[3]['search']['value'] ?? ''));
if ($admitType !== '') {
$builder->groupStart()
->like('in_master.short_name', $admitType, 'both')
->orLike('in_master.ins_company_name', $admitType, 'both')
->orLike("if((o.id is not null),in_master.short_name,'Direct')", $admitType, 'both', null, false)
->groupEnd();
}
$claimNo = trim((string) ($columns[4]['search']['value'] ?? ''));
if ($claimNo !== '') {
$builder->like('insurance_no_1', $claimNo, 'both');
}
$docName = trim((string) ($columns[5]['search']['value'] ?? ''));
if ($docName !== '') {
$builder->like('doc_name', $docName, 'both');
}
$dateFilter = trim((string) ($columns[7]['search']['value'] ?? ''));
if ($dateFilter !== '') {
$rangeParts = explode('/', $dateFilter);
if (count($rangeParts) === 3) {
[$start, $end, $type] = $rangeParts;
$escapedStart = $this->db->escape($start);
$escapedEnd = $this->db->escape($end);
if ($type === '0') {
$builder->where("Date(i.register_date) >=", $escapedStart, false)
->where("Date(i.register_date) <=", $escapedEnd, false);
} elseif ($type === '1') {
$builder->where("Date(i.discharge_date) >=", $escapedStart, false)
->where("Date(i.discharge_date) <=", $escapedEnd, false);
} else {
$builder
->groupStart()
->groupStart()
->where("Date(i.register_date) >=", $escapedStart, false)
->where("Date(i.register_date) <=", $escapedEnd, false)
->groupEnd()
->orGroupStart()
->where("Date(i.discharge_date) >=", $escapedStart, false)
->where("Date(i.discharge_date) <=", $escapedEnd, false)
->groupEnd()
->groupEnd();
}
}
}
}
}