Spaces:
Running
Running
Rename easypay/includes/ReceiptGenerator.php to easypay/includes/ReceiptGenerator_old.php
71043d4 verified | class ReceiptGenerator | |
| { | |
| private $fontPath; | |
| private $logoPath; | |
| public function __construct() | |
| { | |
| if (!extension_loaded('gd')) { | |
| throw new Exception("The PHP GD extension is not enabled. Please enable it in your php.ini or install php-gd."); | |
| } | |
| // Try to find a suitable font | |
| $fonts = [ | |
| 'C:/Windows/Fonts/arial.ttf', | |
| '/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf', | |
| '/usr/share/fonts/truetype/liberation/LiberationSans-Regular.ttf', | |
| '/usr/share/fonts/TTF/arial.ttf' | |
| ]; | |
| $this->fontPath = null; | |
| foreach ($fonts as $font) { | |
| if (file_exists($font)) { | |
| $this->fontPath = $font; | |
| break; | |
| } | |
| } | |
| $this->logoPath = __DIR__ . '/../assets/logo.png'; | |
| } | |
| public function generate($data) | |
| { | |
| $width = 800; | |
| // Calculate dynamic height | |
| $baseHeight = 450; | |
| $rowHeight = 40; | |
| $numRows = count($data['allocations'] ?? []); | |
| $height = $baseHeight + ($numRows * $rowHeight) + 150; | |
| $image = imagecreatetruecolor($width, $height); | |
| // Colors | |
| $white = imagecolorallocate($image, 255, 255, 255); | |
| $black = imagecolorallocate($image, 0, 0, 0); | |
| $grey = imagecolorallocate($image, 100, 100, 100); | |
| $lightGrey = imagecolorallocate($image, 240, 240, 240); | |
| imagefilledrectangle($image, 0, 0, $width, $height, $white); | |
| // Logo | |
| if (file_exists($this->logoPath)) { | |
| $logo = @imagecreatefrompng($this->logoPath); | |
| if ($logo) { | |
| $logoW = imagesx($logo); | |
| $logoH = imagesy($logo); | |
| $targetW = 100; | |
| $targetH = ($targetW / $logoW) * $logoH; | |
| imagecopyresampled($image, $logo, 40, 30, 0, 0, (int) $targetW, (int) $targetH, (int) $logoW, (int) $logoH); | |
| } | |
| } | |
| // School Name Logic | |
| $schoolName = "ACE JUNIOR COLLEGE"; | |
| $levelName = isset($data['level_name']) ? strtoupper($data['level_name']) : ''; | |
| // Check for Senior classes (SSS 1, SSS 2, SSS 3, or Senior) | |
| if (strpos($levelName, 'SSS') !== false || strpos($levelName, 'SENIOR') !== false) { | |
| $schoolName = "ACE SENIOR COLLEGE"; | |
| } | |
| // Header | |
| $this->centerText($image, 18, 50, $schoolName, $black); | |
| $this->centerText($image, 10, 75, "...education for excellence", $grey); | |
| $this->centerText($image, 10, 100, "1, Ebute - Igbogbo Road, Ipakodo, Ikorodu, Lagos, Nigeria", $black); | |
| $this->centerText($image, 10, 120, "Phone No(s): 08027449739, 08077275777", $black); | |
| $this->centerText($image, 10, 140, "mailto:info@acecollege.com.ng https://www.acecollege.com.ng", $black); | |
| // Receipt Title | |
| $titleY = 180; | |
| $receiptNo = $data['receipt_no'] ?? 'N/A'; | |
| $this->centerText($image, 12, $titleY, "SCHOOL FEES RECEIPT - REFERENCE NO: $receiptNo", $black); | |
| // Session Info | |
| $session = $data['allocations'][0]['academic_session'] ?? '----'; | |
| $term = $data['allocations'][0]['term_of_session'] ?? '-'; | |
| $nextSession = is_numeric($session) ? ($session + 1) : ''; | |
| $levelPart = isset($data['level_name']) ? ' - ' . strtoupper($data['level_name']) : ''; | |
| $sessionStr = "$session/$nextSession ACADEMIC SESSION, TERM $term" . $levelPart; | |
| $this->centerText($image, 10, $titleY + 25, $sessionStr, $grey); | |
| // Student Box | |
| $boxY = 230; | |
| imagerectangle($image, 40, $boxY, $width - 40, $boxY + 40, $grey); | |
| // We expect student_name to be passed in $data. If not, fallback. | |
| $studentName = isset($data['student_name']) ? strtoupper($data['student_name']) : (isset($data['student_code']) ? "STUDENT CODE: " . $data['student_code'] : 'UNKNOWN STUDENT'); | |
| $this->centerText($image, 14, $boxY + 26, $studentName, $grey); | |
| // Table Header | |
| $tableY = 300; | |
| $cols = [40, 350, 480, 590, 700]; // x positions | |
| imageline($image, 40, $tableY, $width - 40, $tableY, $black); | |
| imageline($image, 40, $tableY + 30, $width - 40, $tableY + 30, $black); | |
| if ($this->fontPath) { | |
| imagettftext($image, 9, 0, $cols[0], $tableY + 20, $black, $this->fontPath, "FEE DESCRIPTION"); | |
| imagettftext($image, 9, 0, $cols[1], $tableY + 20, $black, $this->fontPath, "AMOUNT BILLED"); | |
| imagettftext($image, 9, 0, $cols[2], $tableY + 20, $black, $this->fontPath, "AMOUNT PAID"); | |
| imagettftext($image, 9, 0, $cols[3], $tableY + 20, $black, $this->fontPath, "PAID TO DATE"); | |
| imagettftext($image, 9, 0, $cols[4], $tableY + 20, $black, $this->fontPath, "TO BALANCE"); | |
| } else { | |
| imagestring($image, 3, $cols[0], $tableY + 5, "FEE DESCRIPTION", $black); | |
| imagestring($image, 3, $cols[1], $tableY + 5, "AMOUNT BILLED", $black); | |
| imagestring($image, 3, $cols[2], $tableY + 5, "AMOUNT PAID", $black); | |
| imagestring($image, 3, $cols[3], $tableY + 5, "PAID TO DATE", $black); | |
| imagestring($image, 3, $cols[4], $tableY + 5, "TO BALANCE", $black); | |
| } | |
| // Rows | |
| $currY = $tableY + 30; | |
| $totalBilled = 0; | |
| $totalPaidToDate = 0; | |
| $totalBalance = 0; | |
| if (isset($data['allocations']) && is_array($data['allocations'])) { | |
| foreach ($data['allocations'] as $alloc) { | |
| $desc = $alloc['description']; | |
| $billedVal = $alloc['amount_billed'] ?? 0; | |
| $paidVal = $alloc['amount'] ?? 0; | |
| $paidToDateVal = $alloc['total_paid_to_date'] ?? 0; | |
| $balanceVal = $alloc['balance'] ?? 0; | |
| $totalBilled += $billedVal; | |
| $totalPaidToDate += $paidToDateVal; | |
| $totalBalance += $balanceVal; | |
| $billed = number_format($billedVal, 2); | |
| $paid = number_format($paidVal, 2); | |
| $paidToDate = number_format($paidToDateVal, 2); | |
| $balance = number_format($balanceVal, 2); | |
| $currY += 30; | |
| if ($this->fontPath) { | |
| imagettftext($image, 9, 0, $cols[0], $currY, $black, $this->fontPath, substr($desc, 0, 40)); | |
| } else { | |
| imagestring($image, 3, $cols[0], $currY - 10, substr($desc, 0, 40), $black); | |
| } | |
| $this->rightAlignText($image, 9, $cols[2] - 20, $currY, $billed, $black); | |
| $this->rightAlignText($image, 9, $cols[3] - 20, $currY, $paid, $black); | |
| $this->rightAlignText($image, 9, $cols[4] - 20, $currY, $paidToDate, $black); | |
| $this->rightAlignText($image, 9, $width - 40, $currY, $balance, $black); | |
| } | |
| } | |
| // Total Row | |
| $currY += 20; | |
| imageline($image, 40, $currY, $width - 40, $currY, $black); | |
| $currY += 26; // Adjusted for vertical centering (moved up from 30) | |
| $totalPaid = number_format($data['total_paid'] ?? 0, 2); | |
| $totalBilledStr = number_format($totalBilled, 2); | |
| $totalPaidToDateStr = number_format($totalPaidToDate, 2); | |
| $totalBalanceStr = number_format($totalBalance, 2); | |
| // Show all totals | |
| $this->rightAlignText($image, 10, $cols[2] - 20, $currY, $totalBilledStr, $grey); | |
| $this->rightAlignText($image, 10, $cols[3] - 20, $currY, $totalPaid, $grey); | |
| $this->rightAlignText($image, 10, $cols[4] - 20, $currY, $totalPaidToDateStr, $grey); | |
| $this->rightAlignText($image, 10, $width - 40, $currY, $totalBalanceStr, $grey); | |
| imageline($image, 40, $currY + 14, $width - 40, $currY + 14, $black); | |
| // Footer | |
| $footerY = $currY + 50; | |
| if ($this->fontPath) { | |
| imagettftext($image, 9, 0, 40, $footerY, $black, $this->fontPath, "RECEIPT DULY VERIFIED BY"); | |
| imagettftext($image, 9, 0, 40, $footerY + 20, $black, $this->fontPath, "BURSAR'S OFFICE"); | |
| } else { | |
| imagestring($image, 3, 40, $footerY - 10, "RECEIPT DULY VERIFIED BY", $black); | |
| imagestring($image, 3, 40, $footerY + 10, "BURSAR'S OFFICE", $black); | |
| } | |
| $receivedY = $footerY; | |
| $this->rightAlignText($image, 9, $width - 40, $receivedY, "RECEIVED IN", $black); | |
| $this->rightAlignText($image, 9, $width - 40, $receivedY + 15, "BANK", $black); | |
| $this->rightAlignText($image, 9, $width - 40, $receivedY + 40, "RECEIVED ON", $black); | |
| $dateStr = isset($data['payment_date']) ? strtoupper(date("F d, Y", strtotime($data['payment_date']))) : date("F d, Y"); | |
| $this->rightAlignText($image, 9, $width - 40, $receivedY + 55, $dateStr, $black); | |
| ob_start(); | |
| imagepng($image); | |
| $content = ob_get_clean(); | |
| imagedestroy($image); | |
| return $content; | |
| } | |
| public function generateBase64($data) | |
| { | |
| $content = $this->generate($data); | |
| return base64_encode($content); | |
| } | |
| private function centerText($image, $size, $y, $text, $color) | |
| { | |
| if ($this->fontPath) { | |
| try { | |
| $box = imagettfbbox($size, 0, $this->fontPath, $text); | |
| $textW = $box[2] - $box[0]; | |
| $x = (int) ((imagesx($image) - $textW) / 2); | |
| imagettftext($image, $size, 0, $x, (int) $y, $color, $this->fontPath, $text); | |
| return; | |
| } catch (Exception $e) { | |
| // Fallthrough to built-in font | |
| } | |
| } | |
| // Fallback or if fontPath is missing | |
| // gd builtin font sizes are 1-5. Map approx size. | |
| $gdSize = (int) min(5, max(1, floor($size / 3))); | |
| $charWidth = imagefontwidth($gdSize); | |
| $textW = strlen($text) * $charWidth; | |
| $x = (int) ((imagesx($image) - $textW) / 2); | |
| imagestring($image, $gdSize, $x, (int) $y, $text, $color); | |
| } | |
| private function rightAlignText($image, $size, $rightX, $y, $text, $color) | |
| { | |
| if ($this->fontPath) { | |
| try { | |
| $box = imagettfbbox($size, 0, $this->fontPath, $text); | |
| $textW = $box[2] - $box[0]; | |
| $x = (int) ($rightX - $textW); | |
| imagettftext($image, $size, 0, $x, (int) $y, $color, $this->fontPath, $text); | |
| return; | |
| } catch (Exception $e) { | |
| // Fallthrough | |
| } | |
| } | |
| $gdSize = (int) min(5, max(1, floor($size / 3))); | |
| $charWidth = imagefontwidth($gdSize); | |
| $x = (int) ($rightX - (strlen($text) * $charWidth)); | |
| imagestring($image, $gdSize, $x, (int) $y, $text, $color); | |
| } | |
| } | |