Spaces:
Running
Running
| require_once 'db_config.php'; | |
| require_once 'includes/ReceiptGenerator.php'; | |
| // Prevent output from messing up image headers | |
| ob_start(); | |
| ini_set('display_errors', 0); | |
| error_reporting(E_ALL & ~E_DEPRECATED & ~E_NOTICE); | |
| // Validate input | |
| $receiptNo = $_GET['receipt_no'] ?? ''; | |
| if (empty($receiptNo)) { | |
| die("Receipt number is required."); | |
| } | |
| try { | |
| // 1. Fetch Receipt Meta Info (Student, Date) | |
| $sqlInfo = "SELECT pr.student_id, pr.payment_date, | |
| sr.last_name, sr.first_name, sr.other_name, sr.student_code, | |
| al.level_name | |
| FROM tb_account_payment_registers pr | |
| JOIN tb_student_registrations sr ON pr.student_id = sr.id | |
| LEFT JOIN tb_academic_levels al ON sr.level_id = al.id | |
| WHERE pr.receipt_no = :receipt_no | |
| LIMIT 1"; | |
| $stmt = $pdo->prepare($sqlInfo); | |
| $stmt->execute(['receipt_no' => $receiptNo]); | |
| $receiptInfo = $stmt->fetch(PDO::FETCH_ASSOC); | |
| if (!$receiptInfo) { | |
| die("Receipt not found."); | |
| } | |
| $studentId = $receiptInfo['student_id']; | |
| $paymentDate = $receiptInfo['payment_date']; | |
| // 2. Fetch All Fees for Student (from receivables) | |
| $sqlFees = "SELECT ar.fee_id, ar.actual_value as amount_billed, | |
| ar.academic_session, ar.term_of_session, | |
| sf.description as fee_description | |
| FROM tb_account_receivables ar | |
| JOIN tb_account_school_fees sf ON ar.fee_id = sf.id | |
| WHERE ar.student_id = :sid | |
| ORDER BY ar.academic_session ASC, ar.term_of_session ASC"; | |
| $stmtFees = $pdo->prepare($sqlFees); | |
| $stmtFees->execute(['sid' => $studentId]); | |
| $allFees = $stmtFees->fetchAll(PDO::FETCH_ASSOC); | |
| $allocations = []; | |
| $receiptTotalPaid = 0; | |
| foreach ($allFees as $fee) { | |
| // Calculate Paid To Date (up to this receipt's date) | |
| $sqlPaid = "SELECT SUM(amount_paid) as total_paid | |
| FROM tb_account_payment_registers | |
| WHERE student_id = :sid | |
| AND fee_id = :fid | |
| AND academic_session = :as | |
| AND term_of_session = :ts | |
| AND payment_date <= :pd"; | |
| $stmtPaid = $pdo->prepare($sqlPaid); | |
| $stmtPaid->execute([ | |
| 'sid' => $studentId, | |
| 'fid' => $fee['fee_id'], | |
| 'as' => $fee['academic_session'], | |
| 'ts' => $fee['term_of_session'], | |
| 'pd' => $paymentDate | |
| ]); | |
| $paidResult = $stmtPaid->fetch(PDO::FETCH_ASSOC); | |
| $paidToDate = floatval($paidResult['total_paid'] ?? 0); | |
| // Calculate Amount paid IN THIS RECEIPT (for total calculation) | |
| $sqlReceiptPay = "SELECT SUM(amount_paid) as receipt_paid | |
| FROM tb_account_payment_registers | |
| WHERE receipt_no = :rno | |
| AND fee_id = :fid | |
| AND academic_session = :as | |
| AND term_of_session = :ts"; | |
| $stmtReceiptPay = $pdo->prepare($sqlReceiptPay); | |
| $stmtReceiptPay->execute([ | |
| 'rno' => $receiptNo, | |
| 'fid' => $fee['fee_id'], | |
| 'as' => $fee['academic_session'], | |
| 'ts' => $fee['term_of_session'] | |
| ]); | |
| $receiptPayResult = $stmtReceiptPay->fetch(PDO::FETCH_ASSOC); | |
| $paidInReceipt = floatval($receiptPayResult['receipt_paid'] ?? 0); | |
| $receiptTotalPaid += $paidInReceipt; | |
| $balance = floatval($fee['amount_billed']) - $paidToDate; | |
| // Condition: Show if (Balance > 0) OR (PaidInReceipt > 0) | |
| // Helps filter out old fully paid fees, but keeps current payments even if they zeroed the balance | |
| if ($balance > 0.001 || $paidInReceipt > 0.001) { | |
| $allocations[] = [ | |
| 'description' => $fee['fee_description'], | |
| 'academic_session' => $fee['academic_session'], | |
| 'term_of_session' => $fee['term_of_session'], | |
| 'amount_billed' => floatval($fee['amount_billed']), | |
| 'amount' => $paidInReceipt, | |
| 'total_paid_to_date' => $paidToDate, | |
| 'balance' => $balance | |
| ]; | |
| } | |
| } | |
| // 3. Prepare data structure for generator | |
| $data = [ | |
| 'receipt_no' => $receiptNo, | |
| 'student_name' => trim($receiptInfo['last_name'] . ' ' . $receiptInfo['first_name'] . ' ' . ($receiptInfo['other_name'] ?? '')), | |
| 'student_code' => $receiptInfo['student_code'], | |
| 'level_name' => $receiptInfo['level_name'] ?? '', | |
| 'payment_date' => $paymentDate, | |
| 'total_paid' => $receiptTotalPaid, | |
| 'allocations' => $allocations | |
| ]; | |
| // 4. Generate Image | |
| $generator = new ReceiptGenerator(); | |
| $imageData = $generator->generate($data); | |
| // 5. Output | |
| ob_end_clean(); // Discard any warnings/output buffered so far | |
| header('Content-Type: image/png'); | |
| header('Content-Disposition: attachment; filename="receipt_' . $receiptNo . '.png"'); | |
| header('Content-Length: ' . strlen($imageData)); | |
| echo $imageData; | |
| } catch (Exception $e) { | |
| die("Error generating receipt: " . $e->getMessage()); | |
| } |