PluginProbe
Yatra – Travel Booking & Tour Operator Software / trunk
Yatra – Travel Booking & Tour Operator Software vtrunk
3.0.14 3.0.14.1 3.0.14.2 3.0.12 3.0.13 3.0.11 3.0.10 3.0.9 3.0.8 3.0.7 3.0.6 3.0.5 3.0.5.1 3.0.4 3.0.3 3.0.2.9 3.0.2.7 3.0.2.8 3.0.2.6 trunk 1.0.0 2.0.0 2.0.1 2.0.10 2.0.11 All 82 releases
yatra / templates / pdf / invoice.php

invoice.php in Yatra – Travel Booking & Tour Operator Software trunk, at templates/pdf/invoice.php

256 lines 13.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 $companyName = (string) ($company_name ?? '');
4 if ($companyName === '' && function_exists('yatra_get_brand_name')) {
5 $companyName = yatra_get_brand_name();
6 }
7 $companyAddress = (string) ($company_address ?? '');
8 // Settings keep the business address in separate fields (street, city, state,
9 // postcode, country); documents only ever printed the street, so everything after
10 // it was missing and the address looked cut off at its last line. Prefer the
11 // composed lines, falling back to the raw street for any caller not passing them.
12 $companyAddressLines = (isset($company_address_lines) && is_array($company_address_lines))
13 ? array_values(array_filter(array_map('strval', $company_address_lines), static function ($line) {
14 return trim($line) !== '';
15 }))
16 : array_values(array_filter(preg_split('/\R/', $companyAddress) ?: [], static function ($line) {
17 return trim($line) !== '';
18 }));
19 $companyEmail = (string) ($company_email ?? '');
20 $companyPhone = (string) ($company_phone ?? '');
21
22 $customerName = (string) ($customer_name ?? '');
23 $customerEmail = (string) ($customer_email ?? '');
24
25 // The customer's postal address, one entry per line. Absent on older callers,
26 // so an empty list simply renders nothing.
27 $customerAddressLines = (isset($customer_address_lines) && is_array($customer_address_lines))
28 ? array_filter(array_map('strval', $customer_address_lines), static function ($line) {
29 return trim($line) !== '';
30 })
31 : [];
32
33 $paymentRef = (string) ($payment_ref ?? '');
34 $paymentDate = (string) ($payment_date ?? '');
35 $paymentStatus = (string) ($payment_status ?? '');
36 $statusClass = (string) ($status_class ?? 'pending');
37
38 $tripTitle = (string) ($trip_title ?? '');
39 $paymentMethod = (string) ($payment_method ?? '');
40 $bookingRef = (string) ($booking_ref ?? '');
41 $travelDate = (string) ($travel_date ?? '');
42
43 $currencySymbol = (string) ($currency_symbol ?? '');
44 $amount = (string) ($amount ?? '0.00');
45 $bookingTotal = (string) ($booking_total ?? '0.00');
46 $amountPaid = (string) ($amount_paid ?? '0.00');
47 $amountDue = (string) ($amount_due ?? '0.00');
48
49 // Structured payment instructions (e.g. bank-transfer details) provided by a
50 // gateway via the yatra_invoice_payment_instructions filter. Shape:
51 // ['title' => string, 'rows' => [['label'=>.., 'value'=>..], ...], 'note' => string]
52 $paymentInstructions = (isset($payment_instructions) && is_array($payment_instructions)) ? $payment_instructions : [];
53
54
55 // Optional logo + header colour supplied by the White Label module.
56 // Unbranded sites keep this document's original header colour and show no logo.
57 $pdfBranding = function_exists('yatra_get_pdf_branding')
58 ? yatra_get_pdf_branding('#1e40af')
59 : ['logo_url' => '', 'header_color' => '#1e40af'];
60 $brandLogoUrl = (string) ($pdfBranding['logo_url'] ?? '');
61 $brandHeaderColor = (string) ($pdfBranding['header_color'] ?? '#1e40af');
62
63 ?><!DOCTYPE html>
64 <html lang="en">
65 <head>
66 <meta charset="UTF-8">
67 <meta name="viewport" content="width=device-width, initial-scale=1.0">
68 <title><?php echo esc_html__('Invoice', 'yatra'); ?> - <?php echo htmlspecialchars($bookingRef !== '' ? $bookingRef : $paymentRef, ENT_QUOTES, 'UTF-8'); ?></title>
69 <style>
70 @page { size: A4 portrait; margin: 0mm; }
71 * { margin: 0; padding: 0; box-sizing: border-box; }
72 body { margin: 0; padding: 0; font-family: "Noto Sans Devanagari", "Noto Sans Arabic", "Noto Sans CJK", "DejaVu Sans", sans-serif; font-size: 12px; color: #111; }
73 .content { padding: 12mm 12mm 14mm 12mm; }
74
75 .header { width: 100%; border-collapse: collapse; }
76 .header td { vertical-align: top; }
77 .brand { background: <?php echo htmlspecialchars($brandHeaderColor, ENT_QUOTES, 'UTF-8'); ?>; color: #fff; padding: 6mm 6mm; }
78 .brand-logo { max-height: 18mm; max-width: 60mm; margin-bottom: 3mm; }
79 .brand h1 { font-size: 18px; font-weight: 700; margin: 0; }
80 .brand p { font-size: 11px; margin-top: 4px; }
81
82 .panel { width: 100%; border: 1px solid #e5e7eb; border-collapse: collapse; margin-top: 6mm; margin-bottom: 6mm; }
83 .panel td { padding: 5mm 5mm; vertical-align: top; }
84 .panel h3 { font-size: 11px; text-transform: uppercase; color: #6b7280; margin-bottom: 8px; letter-spacing: 0.5px; }
85 .muted { color: #6b7280; }
86
87 .details { width: 100%; border-collapse: collapse; }
88 .details td { padding: 1.5mm 0; vertical-align: top; }
89 .details .k { width: 18mm; white-space: nowrap; font-weight: 700; }
90 .details .v { white-space: nowrap; }
91 .details .v-wrap { white-space: normal; }
92
93 .badge { display: inline-block; padding: 2px 10px; font-size: 10px; border-radius: 12px; border: 1px solid #e5e7eb; margin-left: 6px; vertical-align: middle; line-height: 1.4; }
94 .badge-paid { background: #d1fae5; color: #065f46; border-color: #a7f3d0; }
95 .badge-partial { background: #dbeafe; color: #1e40af; border-color: #bfdbfe; }
96 .badge-pending { background: #fef3c7; color: #92400e; border-color: #fde68a; }
97
98 .items { width: 100%; border-collapse: collapse; margin-top: 4mm; }
99 .items th { text-align: left; font-size: 10px; text-transform: uppercase; color: #6b7280; background: #f9fafb; border-bottom: 1px solid #e5e7eb; padding: 10px 12px; }
100 .items td { border-bottom: 1px solid #e5e7eb; padding: 12px; vertical-align: top; }
101 .right { text-align: right; }
102
103 .totals { width: 100%; border-collapse: collapse; margin-top: 6mm; }
104 .totals td { padding: 7px 12px; }
105 .totals .label { color: #374151; }
106 .totals .value { text-align: right; }
107 .totals .grand { font-weight: 700; color: #1e40af; border-top: 2px solid #1e40af; padding-top: 12px; }
108 </style>
109 </head>
110 <body>
111 <table class="header">
112 <tr>
113 <td class="brand">
114 <?php if ($brandLogoUrl !== ''): ?>
115 <img class="brand-logo" src="<?php echo htmlspecialchars($brandLogoUrl, ENT_QUOTES, 'UTF-8'); ?>" alt="">
116 <?php endif; ?>
117 <h1><?php echo htmlspecialchars($companyName, ENT_QUOTES, 'UTF-8'); ?></h1>
118 <p><?php esc_html_e('Payment Invoice', 'yatra'); ?></p>
119 </td>
120 </tr>
121 </table>
122
123 <div class="content">
124 <table class="panel">
125 <tr>
126 <td style="width: 40%;">
127 <h3><?php esc_html_e('Invoice To', 'yatra'); ?></h3>
128 <div><strong><?php echo htmlspecialchars($customerName, ENT_QUOTES, 'UTF-8'); ?></strong></div>
129 <?php foreach ($customerAddressLines as $addressLine): ?>
130 <div class="muted"><?php echo htmlspecialchars($addressLine, ENT_QUOTES, 'UTF-8'); ?></div>
131 <?php endforeach; ?>
132 <div class="muted"><?php echo htmlspecialchars($customerEmail, ENT_QUOTES, 'UTF-8'); ?></div>
133 </td>
134 <td style="width: 30%;">
135 <h3><?php esc_html_e('Invoice Details', 'yatra'); ?></h3>
136 <table class="details">
137 <tr>
138 <td class="k"><?php esc_html_e('Invoice #:', 'yatra'); ?></td>
139 <?php // Always the booking reference — consistent whether the invoice is
140 // downloaded from the confirmation page or after a payment. Previously
141 // this used $paymentRef, which the post-payment path set to the payment
142 // number (PAY-xxxxxx), so the invoice number changed per download. ?>
143 <td class="v-wrap"><?php echo htmlspecialchars($bookingRef !== '' ? $bookingRef : $paymentRef, ENT_QUOTES, 'UTF-8'); ?></td>
144 </tr>
145 <tr>
146 <td class="k"><?php esc_html_e('Date:', 'yatra'); ?></td>
147 <td class="v"><?php echo htmlspecialchars($paymentDate, ENT_QUOTES, 'UTF-8'); ?></td>
148 </tr>
149 <tr>
150 <td class="k"><?php esc_html_e('Status:', 'yatra'); ?></td>
151 <td class="v"><span class="badge badge-<?php echo htmlspecialchars($statusClass, ENT_QUOTES, 'UTF-8'); ?>"><?php echo htmlspecialchars($paymentStatus, ENT_QUOTES, 'UTF-8'); ?></span></td>
152 </tr>
153 </table>
154 </td>
155 <td style="width: 30%;">
156 <h3><?php esc_html_e('Company', 'yatra'); ?></h3>
157 <div><?php echo htmlspecialchars($companyName, ENT_QUOTES, 'UTF-8'); ?></div>
158 <?php foreach ($companyAddressLines as $companyAddressLine): ?>
159 <div class="muted"><?php echo htmlspecialchars($companyAddressLine, ENT_QUOTES, 'UTF-8'); ?></div>
160 <?php endforeach; ?>
161 <?php if ($companyEmail !== ''): ?>
162 <div class="muted"><?php echo htmlspecialchars($companyEmail, ENT_QUOTES, 'UTF-8'); ?></div>
163 <?php endif; ?>
164 <?php if ($companyPhone !== ''): ?>
165 <div class="muted"><?php echo htmlspecialchars($companyPhone, ENT_QUOTES, 'UTF-8'); ?></div>
166 <?php endif; ?>
167 </td>
168 </tr>
169 </table>
170
171 <table class="items">
172 <thead>
173 <tr>
174 <th><?php esc_html_e('Description', 'yatra'); ?></th>
175 <th><?php esc_html_e('Booking Ref', 'yatra'); ?></th>
176 <th><?php esc_html_e('Travel Date', 'yatra'); ?></th>
177 <th class="right"><?php esc_html_e('Amount', 'yatra'); ?></th>
178 </tr>
179 </thead>
180 <tbody>
181 <tr>
182 <td>
183 <div><strong><?php echo htmlspecialchars($tripTitle, ENT_QUOTES, 'UTF-8'); ?></strong></div>
184 <div class="muted"><?php esc_html_e('Payment via', 'yatra'); ?> <?php echo htmlspecialchars($paymentMethod, ENT_QUOTES, 'UTF-8'); ?></div>
185 </td>
186 <td><?php echo htmlspecialchars($bookingRef, ENT_QUOTES, 'UTF-8'); ?></td>
187 <td><?php echo htmlspecialchars($travelDate, ENT_QUOTES, 'UTF-8'); ?></td>
188 <td class="right"><strong><?php echo htmlspecialchars($amount, ENT_QUOTES, 'UTF-8'); ?></strong></td>
189 </tr>
190 </tbody>
191 </table>
192
193 <table class="totals">
194 <?php if (!empty($tax_breakdown)): ?>
195 <tr>
196 <td class="label"><?php esc_html_e('Subtotal', 'yatra'); ?></td>
197 <td class="value"><?php echo htmlspecialchars($subtotal, ENT_QUOTES, 'UTF-8'); ?></td>
198 </tr>
199 <?php foreach ($tax_breakdown as $tax): ?>
200 <tr>
201 <td class="label"><?php echo htmlspecialchars($tax['name'], ENT_QUOTES, 'UTF-8'); ?> (<?php echo htmlspecialchars($tax['rate'], ENT_QUOTES, 'UTF-8'); ?>%)</td>
202 <td class="value"><?php echo htmlspecialchars($tax['amount'], ENT_QUOTES, 'UTF-8'); ?></td>
203 </tr>
204 <?php endforeach; ?>
205 <?php endif; ?>
206 <tr>
207 <td class="label"><?php esc_html_e('Booking Total', 'yatra'); ?></td>
208 <td class="value"><?php echo htmlspecialchars($bookingTotal, ENT_QUOTES, 'UTF-8'); ?></td>
209 </tr>
210 <tr>
211 <td class="label"><?php esc_html_e('Total Paid', 'yatra'); ?></td>
212 <td class="value"><?php echo htmlspecialchars($amountPaid, ENT_QUOTES, 'UTF-8'); ?></td>
213 </tr>
214 <tr>
215 <td class="label"><?php esc_html_e('Balance Due', 'yatra'); ?></td>
216 <td class="value"><?php echo htmlspecialchars($amountDue, ENT_QUOTES, 'UTF-8'); ?></td>
217 </tr>
218 <tr>
219 <td class="label grand"><?php esc_html_e('This Payment', 'yatra'); ?></td>
220 <td class="value grand"><?php echo htmlspecialchars($amount, ENT_QUOTES, 'UTF-8'); ?></td>
221 </tr>
222 </table>
223
224 <?php if (!empty($paymentInstructions['rows']) && is_array($paymentInstructions['rows'])): ?>
225 <table class="panel" style="margin-top: 6mm;">
226 <tr>
227 <td>
228 <h3><?php echo htmlspecialchars((string) ($paymentInstructions['title'] ?? __('Payment Instructions', 'yatra')), ENT_QUOTES, 'UTF-8'); ?></h3>
229 <table class="details">
230 <?php foreach ($paymentInstructions['rows'] as $piRow): ?>
231 <?php if (!is_array($piRow)) { continue; } ?>
232 <tr>
233 <?php
234 // A gateway may supply its label with or without a
235 // trailing colon (Bank Transfer reuses the colon-suffixed
236 // strings from the confirmation page so a single
237 // translation covers both). Normalise so neither form
238 // renders "Label::".
239 $piLabel = rtrim(trim((string) ($piRow['label'] ?? '')), ':');
240 ?>
241 <td class="k" style="width: 40mm;"><?php echo htmlspecialchars($piLabel, ENT_QUOTES, 'UTF-8'); ?>:</td>
242 <td class="v-wrap"><?php echo htmlspecialchars((string) ($piRow['value'] ?? ''), ENT_QUOTES, 'UTF-8'); ?></td>
243 </tr>
244 <?php endforeach; ?>
245 </table>
246 <?php if (!empty($paymentInstructions['note'])): ?>
247 <p class="muted" style="margin-top: 4mm;"><?php echo htmlspecialchars((string) $paymentInstructions['note'], ENT_QUOTES, 'UTF-8'); ?></p>
248 <?php endif; ?>
249 </td>
250 </tr>
251 </table>
252 <?php endif; ?>
253 </div>
254 </body>
255 </html>
256