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]); }