38960-vm/api/billing.php
2026-03-21 07:38:35 +00:00

275 lines
9.3 KiB
PHP

<?php
require_once __DIR__ . '/../db/config.php';
header('Content-Type: application/json');
$db = db();
$action = $_POST['action'] ?? $_GET['action'] ?? '';
if ($action === 'get_bill_details') {
$visit_id = $_GET['visit_id'] ?? 0;
$bill_id_param = $_GET['bill_id'] ?? 0;
if (!$visit_id && !$bill_id_param) {
echo json_encode(['success' => false, 'error' => 'Visit ID or Bill ID required']);
exit;
}
try {
if ($bill_id_param) {
$stmt = $db->prepare("SELECT visit_id FROM bills WHERE id = ?");
$stmt->execute([$bill_id_param]);
$visit_id = $stmt->fetchColumn();
if (!$visit_id) {
echo json_encode(['success' => false, 'error' => 'Bill not found']);
exit;
}
}
// 1. Get Visit & Patient Info
$stmt = $db->prepare("
SELECT v.*, p.name as patient_name, p.insurance_company_id, ic.name_en as insurance_name
FROM visits v
JOIN patients p ON v.patient_id = p.id
LEFT JOIN insurance_companies ic ON p.insurance_company_id = ic.id
WHERE v.id = ?
");
$stmt->execute([$visit_id]);
$visit = $stmt->fetch();
if (!$visit) {
echo json_encode(['success' => false, 'error' => 'Visit not found']);
exit;
}
// 2. Get or Create Bill
$stmt = $db->prepare("SELECT * FROM bills WHERE visit_id = ?");
$stmt->execute([$visit_id]);
$bill = $stmt->fetch();
if (!$bill) {
$stmt = $db->prepare("INSERT INTO bills (patient_id, visit_id, status, created_at) VALUES (?, ?, 'Pending', NOW())");
$stmt->execute([$visit['patient_id'], $visit_id]);
$bill_id = $db->lastInsertId();
// Re-fetch
$stmt = $db->prepare("SELECT * FROM bills WHERE id = ?");
$stmt->execute([$bill_id]);
$bill = $stmt->fetch();
} else {
$bill_id = $bill['id'];
}
// --- AUTO-ADD ITEMS FROM OTHER DEPARTMENTS ---
// Fetch existing items to prevent duplicates
$stmt = $db->prepare("SELECT description FROM bill_items WHERE bill_id = ?");
$stmt->execute([$bill_id]);
$existing_items = $stmt->fetchAll(PDO::FETCH_COLUMN);
// Helper to check and add
$added_count = 0;
// 1. X-Rays
$stmt = $db->prepare("
SELECT xt.name_en, xt.price
FROM xray_inquiry_items xii
JOIN xray_inquiries xi ON xii.inquiry_id = xi.id
JOIN xray_tests xt ON xii.xray_id = xt.id
WHERE xi.visit_id = ?
");
$stmt->execute([$visit_id]);
$xrays = $stmt->fetchAll();
foreach ($xrays as $x) {
$desc = "X-Ray: " . $x['name_en'];
if (!in_array($desc, $existing_items)) {
$stmt = $db->prepare("INSERT INTO bill_items (bill_id, description, amount) VALUES (?, ?, ?)");
$stmt->execute([$bill_id, $desc, $x['price']]);
$existing_items[] = $desc; // Update local cache
$added_count++;
}
}
// 2. Labs
$stmt = $db->prepare("
SELECT lt.name_en, lt.price
FROM inquiry_tests it
JOIN laboratory_inquiries li ON it.inquiry_id = li.id
JOIN laboratory_tests lt ON it.test_id = lt.id
WHERE li.visit_id = ?
");
$stmt->execute([$visit_id]);
$labs = $stmt->fetchAll();
foreach ($labs as $l) {
$desc = "Lab: " . $l['name_en'];
if (!in_array($desc, $existing_items)) {
$stmt = $db->prepare("INSERT INTO bill_items (bill_id, description, amount) VALUES (?, ?, ?)");
$stmt->execute([$bill_id, $desc, $l['price']]);
$existing_items[] = $desc;
$added_count++;
}
}
// 3. Drugs (Prescriptions)
$stmt = $db->prepare("
SELECT vp.drug_name, d.price
FROM visit_prescriptions vp
LEFT JOIN drugs d ON (vp.drug_name = d.name_en OR vp.drug_name = d.name_ar)
WHERE vp.visit_id = ?
");
$stmt->execute([$visit_id]);
$drugs = $stmt->fetchAll();
foreach ($drugs as $d) {
$price = $d['price'] ?: 0; // Default to 0 if not found
$desc = "Pharmacy: " . $d['drug_name'];
if (!in_array($desc, $existing_items)) {
$stmt = $db->prepare("INSERT INTO bill_items (bill_id, description, amount) VALUES (?, ?, ?)");
$stmt->execute([$bill_id, $desc, $price]);
$existing_items[] = $desc;
$added_count++;
}
}
// If items were added, update the bill total
if ($added_count > 0) {
updateBillTotal($db, $bill_id);
// Re-fetch bill to get updated total if needed (though calculate total below handles it)
$stmt = $db->prepare("SELECT * FROM bills WHERE id = ?");
$stmt->execute([$bill_id]);
$bill = $stmt->fetch();
}
// ---------------------------------------------
// 3. Get Bill Items (Fresh)
$stmt = $db->prepare("SELECT * FROM bill_items WHERE bill_id = ?");
$stmt->execute([$bill['id']]);
$items = $stmt->fetchAll();
// 4. Calculate Totals (if not synced)
$total = 0;
foreach ($items as $item) {
$total += $item['amount'];
}
// Return Data
echo json_encode([
'success' => true,
'visit' => $visit,
'bill' => $bill,
'items' => $items,
'calculated_total' => $total,
'has_insurance' => !empty($visit['insurance_company_id']),
'insurance_name' => $visit['insurance_name']
]);
} catch (Exception $e) {
echo json_encode(['success' => false, 'error' => $e->getMessage()]);
}
}
elseif ($action === 'add_item') {
$bill_id = $_POST['bill_id'] ?? 0;
$description = $_POST['description'] ?? '';
$amount = $_POST['amount'] ?? 0;
if (!$bill_id || !$description || !$amount) {
echo json_encode(['success' => false, 'error' => 'Missing fields']);
exit;
}
try {
$stmt = $db->prepare("INSERT INTO bill_items (bill_id, description, amount) VALUES (?, ?, ?)");
$stmt->execute([$bill_id, $description, $amount]);
// Update Bill Total
updateBillTotal($db, $bill_id);
echo json_encode(['success' => true]);
} catch (Exception $e) {
echo json_encode(['success' => false, 'error' => $e->getMessage()]);
}
}
elseif ($action === 'remove_item') {
$item_id = $_POST['item_id'] ?? 0;
if (!$item_id) {
echo json_encode(['success' => false, 'error' => 'Item ID required']);
exit;
}
try {
// Get bill_id first
$stmt = $db->prepare("SELECT bill_id FROM bill_items WHERE id = ?");
$stmt->execute([$item_id]);
$row = $stmt->fetch();
if ($row) {
$stmt = $db->prepare("DELETE FROM bill_items WHERE id = ?");
$stmt->execute([$item_id]);
updateBillTotal($db, $row['bill_id']);
}
echo json_encode(['success' => true]);
} catch (Exception $e) {
echo json_encode(['success' => false, 'error' => $e->getMessage()]);
}
}
elseif ($action === 'update_totals') {
$bill_id = $_POST['bill_id'] ?? 0;
$insurance_covered = $_POST['insurance_covered'] ?? 0;
$patient_payable = $_POST['patient_payable'] ?? 0;
try {
$stmt = $db->prepare("UPDATE bills SET insurance_covered = ?, patient_payable = ? WHERE id = ?");
$stmt->execute([$insurance_covered, $patient_payable, $bill_id]);
echo json_encode(['success' => true]);
} catch (Exception $e) {
echo json_encode(['success' => false, 'error' => $e->getMessage()]);
}
}
elseif ($action === 'complete_payment') {
$bill_id = $_POST['bill_id'] ?? 0;
$payment_method = $_POST['payment_method'] ?? 'Cash';
$notes = $_POST['notes'] ?? '';
try {
$db->beginTransaction();
// Update Bill
$stmt = $db->prepare("UPDATE bills SET status = 'Paid', payment_method = ?, notes = ? WHERE id = ?");
$stmt->execute([$payment_method, $notes, $bill_id]);
// Get Visit ID
$stmt = $db->prepare("SELECT visit_id FROM bills WHERE id = ?");
$stmt->execute([$bill_id]);
$bill = $stmt->fetch();
// Update Visit
if ($bill && $bill['visit_id']) {
$stmt = $db->prepare("UPDATE visits SET status = 'Completed', checkout_time = NOW() WHERE id = ?");
$stmt->execute([$bill['visit_id']]);
}
$db->commit();
echo json_encode(['success' => true]);
} catch (Exception $e) {
$db->rollBack();
echo json_encode(['success' => false, 'error' => $e->getMessage()]);
}
}
function updateBillTotal($db, $bill_id) {
$stmt = $db->prepare("SELECT SUM(amount) FROM bill_items WHERE bill_id = ?");
$stmt->execute([$bill_id]);
$total = $stmt->fetchColumn() ?: 0;
$stmt = $db->prepare("UPDATE bills SET total_amount = ? WHERE id = ?");
$stmt->execute([$total, $bill_id]);
}