PluginProbe
Yatra – Travel Booking & Tour Operator Software / 3.0.16
Yatra – Travel Booking & Tour Operator Software v3.0.16
3.0.16 3.0.15 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 All 84 releases
yatra / app / Services / NotificationService.php

NotificationService.php in Yatra – Travel Booking & Tour Operator Software 3.0.16, at app/Services/NotificationService.php

230 lines 8.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Notification Service
4 *
5 * Admin / customer emails for booking lifecycle events. Enable/disable and copy are controlled
6 * under Yatra → Email → Templates (settings-backed flags), not Settings → Notifications.
7 *
8 * @package Yatra\Services
9 * @since 3.0.0
10 */
11
12 declare(strict_types=1);
13
14 namespace Yatra\Services;
15
16 use Yatra\Repositories\BookingRepository;
17
18 class NotificationService
19 {
20 /**
21 * Send booking created notification (admin: {@see TransactionalEmailTemplateService::TYPE_ADMIN_NEW_BOOKING}).
22 */
23 public static function sendBookingCreatedNotification(int $bookingId, $bookingData): void
24 {
25 self::notifyAdminNewBooking($bookingId, $bookingData);
26 }
27
28 /**
29 * Send payment completed notification (admin + customer templates).
30 */
31 public static function sendPaymentCompletedNotification(array $paymentData): void
32 {
33 self::notifyAdminPaymentReceived($paymentData);
34 self::notifyCustomerPaymentReceived($paymentData);
35 }
36
37 /**
38 * Send booking cancellation notification (admin template; customer email uses transactional templates from BookingService).
39 */
40 public static function sendCancellationNotification(int $bookingId, $bookingData): void
41 {
42 self::notifyAdminCancellation($bookingId, $bookingData);
43 }
44
45 /**
46 * Resend just the customer payment-received email (part- or full-payment
47 * template, exactly as the automated flow chooses it). Public entry for the
48 * admin "resend email" action.
49 */
50 public static function resendCustomerPaymentEmail(array $paymentData): void
51 {
52 self::notifyCustomerPaymentReceived($paymentData);
53 }
54
55 /**
56 * Resend just the admin payment-received notification. Public entry for the
57 * admin "resend email" action.
58 */
59 public static function resendAdminPaymentEmail(array $paymentData): void
60 {
61 self::notifyAdminPaymentReceived($paymentData);
62 }
63
64 /**
65 * Notify admin of new booking
66 */
67 private static function notifyAdminNewBooking(int $bookingId, $bookingData): void
68 {
69 if (!apply_filters('yatra_notify_admin_new_booking', true, $bookingId, $bookingData)) {
70 return;
71 }
72
73 $admin_email = SettingsService::getString('admin_email', (string) get_option('admin_email', ''));
74 if ($admin_email === '' || !is_email($admin_email)) {
75 return;
76 }
77
78 $repository = new BookingRepository();
79 $booking = $repository->findWithTrip($bookingId);
80 if (!$booking) {
81 return;
82 }
83
84 $adminNotifyContext = [
85 'booking_id' => $bookingId,
86 'reference' => $booking->reference ?? '',
87 'source' => 'yatra_booking_created',
88 ];
89 if (!apply_filters('yatra_send_checkout_admin_notification', true, $adminNotifyContext)) {
90 return;
91 }
92
93 $variables = TransactionalEmailTemplateService::variablesFromBooking($booking);
94
95 TransactionalEmailTemplateService::sendIfEnabled(
96 TransactionalEmailTemplateService::TYPE_ADMIN_NEW_BOOKING,
97 $admin_email,
98 $variables
99 );
100 }
101
102 /**
103 * Notify admin of payment received (template: admin_payment_received).
104 */
105 private static function notifyAdminPaymentReceived(array $paymentData): void
106 {
107 $admin_email = SettingsService::getString('admin_email', (string) get_option('admin_email', ''));
108 if ($admin_email === '' || !is_email($admin_email)) {
109 return;
110 }
111
112 $bookingRepository = new BookingRepository();
113 $booking = $bookingRepository->findWithTrip((int) ($paymentData['booking_id'] ?? 0));
114 if (!$booking) {
115 return;
116 }
117
118 $vars = TransactionalEmailTemplateService::variablesFromBooking($booking);
119 $vars['payment_amount_formatted'] = yatra_format_price((float) ($paymentData['amount'] ?? 0));
120 // Name the gateway the way the customer saw it at checkout (the
121 // operator's Gateway Title), not its internal id — a Stripe capture
122 // passes the slug "stripe" here. A manually recorded payment passes
123 // free text ("Credit Card"), which is not a gateway id and is returned
124 // unchanged.
125 $vars['payment_method'] = yatra_payment_gateway_label(
126 isset($paymentData['payment_method']) ? (string) $paymentData['payment_method'] : null,
127 __('Online payment', 'yatra')
128 );
129 $vars['transaction_id'] = (string) ($paymentData['transaction_id'] ?? '');
130
131 TransactionalEmailTemplateService::sendIfEnabled(
132 TransactionalEmailTemplateService::TYPE_ADMIN_PAYMENT_RECEIVED,
133 $admin_email,
134 $vars
135 );
136 }
137
138 /**
139 * Which payment email to send: the part-payment template or the full one.
140 *
141 * Defaults to the long-standing single template. The part-payment template
142 * is used only when ALL of these hold, so an existing site sees no change
143 * until its operator opts in:
144 *
145 * 1. a balance is genuinely still outstanding on the booking,
146 * 2. deposits / partial payments are switched on at all, and
147 * 3. the operator has enabled the separate part-payment template —
148 * either the free "Partial Payment Received" toggle, or (Pro Email
149 * Automation) the active "Partial Payment Received" DB template. On a
150 * Pro site the Email → Templates switch only writes the Pro row, so
151 * the free toggle stays at its default and must not be the sole gate.
152 */
153 private static function paymentTemplateTypeFor(object $booking): string
154 {
155 $full = TransactionalEmailTemplateService::TYPE_PAYMENT_CONFIRMATION;
156 $partial = TransactionalEmailTemplateService::TYPE_PARTIAL_PAYMENT_RECEIVED;
157
158 // Nothing left to pay → this is the full-payment confirmation.
159 if ((float) ($booking->amount_due ?? 0) <= 0) {
160 return $full;
161 }
162
163 if (!yatra_partial_payments_enabled()) {
164 return $full;
165 }
166
167 $partialEnabled = SettingsService::isEnabled('email_template_partial_payment')
168 || (bool) apply_filters('yatra_pro_email_automation_owns_transactional_type', false, $partial);
169
170 return $partialEnabled ? $partial : $full;
171 }
172
173 /**
174 * Notify customer of payment received
175 */
176 private static function notifyCustomerPaymentReceived(array $paymentData): void
177 {
178 $bookingRepository = new BookingRepository();
179 $booking = $bookingRepository->findWithTrip((int) ($paymentData['booking_id'] ?? 0));
180
181 if (!$booking || empty($booking->contact_email)) {
182 return;
183 }
184
185 $vars = TransactionalEmailTemplateService::variablesFromBooking($booking);
186 $vars['payment_amount_formatted'] = yatra_format_price((float) ($paymentData['amount'] ?? 0));
187 // Name the gateway the way the customer saw it at checkout (the
188 // operator's Gateway Title), not its internal id — a Stripe capture
189 // passes the slug "stripe" here. A manually recorded payment passes
190 // free text ("Credit Card"), which is not a gateway id and is returned
191 // unchanged.
192 $vars['payment_method'] = yatra_payment_gateway_label(
193 isset($paymentData['payment_method']) ? (string) $paymentData['payment_method'] : null,
194 __('Online payment', 'yatra')
195 );
196 $vars['transaction_id'] = (string) ($paymentData['transaction_id'] ?? '');
197
198 TransactionalEmailTemplateService::sendIfEnabled(
199 self::paymentTemplateTypeFor($booking),
200 $booking->contact_email,
201 $vars
202 );
203 }
204
205 /**
206 * Notify admin of cancellation
207 */
208 private static function notifyAdminCancellation(int $bookingId, $bookingData): void
209 {
210 $admin_email = SettingsService::getString('admin_email', (string) get_option('admin_email', ''));
211 if ($admin_email === '' || !is_email($admin_email)) {
212 return;
213 }
214
215 $repository = new BookingRepository();
216 $booking = $repository->findWithTrip($bookingId);
217 if (!$booking) {
218 return;
219 }
220
221 $variables = TransactionalEmailTemplateService::variablesFromBooking($booking);
222
223 TransactionalEmailTemplateService::sendIfEnabled(
224 TransactionalEmailTemplateService::TYPE_ADMIN_BOOKING_CANCELLED,
225 $admin_email,
226 $variables
227 );
228 }
229 }
230