| @@ -675,8 +675,13 @@ | ||
| 675 | 675 | if ($newStatus === 'confirmed' && $oldStatus !== 'confirmed' |
| 676 | 676 | && function_exists('yatra_trigger_booking_confirmed')) { |
| 677 | 677 | yatra_trigger_booking_confirmed($id, $oldStatus); |
| 678 | 678 | } |
| 679 | + | |
| 680 | + if ($newStatus === 'cancelled' && $oldStatus !== 'cancelled' | |
| 681 | + && function_exists('yatra_trigger_booking_cancelled')) { | |
| 682 | + yatra_trigger_booking_cancelled($id, $oldStatus); | |
| 683 | + } | |
| 679 | 684 | } |
| 680 | 685 | |
| 681 | 686 | // Return the fresh booking so the REST controller's `$result['data']` |
| 682 | 687 | // is defined (previously absent → "Undefined array key data" warning). |
| @@ -917,8 +922,12 @@ | ||
| 917 | 922 | if ($status === 'confirmed' && $oldStatus !== 'confirmed') { |
| 918 | 923 | \yatra_trigger_booking_confirmed($id, $oldStatus); |
| 919 | 924 | } |
| 920 | 925 | |
| 926 | + if ($status === 'cancelled' && $oldStatus !== 'cancelled') { | |
| 927 | + \yatra_trigger_booking_cancelled($id, $oldStatus); | |
| 928 | + } | |
| 929 | + | |
| 921 | 930 | return [ |
| 922 | 931 | 'success' => true, |
| 923 | 932 | 'message' => sprintf( |
| 924 | 933 | /* translators: %s: new booking status. */ |
| @@ -1253,10 +1262,39 @@ | ||
| 1253 | 1262 | ); |
| 1254 | 1263 | } |
| 1255 | 1264 | |
| 1256 | 1265 | /** |
| 1266 | + * Send the "your booking has been confirmed" transactional email. | |
| 1267 | + * | |
| 1268 | + * Shared by the manual / programmatic status-change path ({@see updateStatus()} | |
| 1269 | + * → sendStatusChangeNotification()) and the asynchronous payment-completion | |
| 1270 | + * paths (via {@see yatra_trigger_booking_confirmed()}), which set a booking to | |
| 1271 | + * `confirmed` with a direct DB write and never pass through updateStatus(). | |
| 1272 | + * Gated by the template's enabled flag (`sendIfEnabled`). | |
| 1273 | + * | |
| 1274 | + * @param int $bookingId Booking ID. | |
| 1275 | + */ | |
| 1276 | + public function sendBookingConfirmedEmail(int $bookingId): void | |
| 1277 | + { | |
| 1278 | + $booking = $this->bookingRepository->findWithTrip($bookingId); | |
| 1279 | + | |
| 1280 | + if (!$booking || empty($booking->contact_email)) { | |
| 1281 | + return; | |
| 1282 | + } | |
| 1283 | + | |
| 1284 | + $vars = TransactionalEmailTemplateService::variablesFromBooking($booking); | |
| 1285 | + $vars['intro_paragraph'] = __('Your booking has been confirmed! Here are your details:', 'yatra'); | |
| 1286 | + $vars['transactional_context'] = 'status_confirmed'; | |
| 1287 | + TransactionalEmailTemplateService::sendIfEnabled( | |
| 1288 | + TransactionalEmailTemplateService::TYPE_BOOKING_CONFIRMATION, | |
| 1289 | + $booking->contact_email, | |
| 1290 | + $vars | |
| 1291 | + ); | |
| 1292 | + } | |
| 1293 | + | |
| 1294 | + /** | |
| 1257 | 1295 | * Send status change notification |
| 1258 | - * | |
| 1296 | + * | |
| 1259 | 1297 | * @param int $bookingId Booking ID |
| 1260 | 1298 | * @param string $oldStatus Previous status |
| 1261 | 1299 | * @param string $newStatus New status |
| 1262 | 1300 | */ |
| @@ -1287,16 +1325,9 @@ | ||
| 1287 | 1325 | return; |
| 1288 | 1326 | } |
| 1289 | 1327 | |
| 1290 | 1328 | if ($newStatus === 'confirmed') { |
| 1291 | - $vars = TransactionalEmailTemplateService::variablesFromBooking($booking); | |
| 1292 | - $vars['intro_paragraph'] = __('Your booking has been confirmed! Here are your details:', 'yatra'); | |
| 1293 | - $vars['transactional_context'] = 'status_confirmed'; | |
| 1294 | - TransactionalEmailTemplateService::sendIfEnabled( | |
| 1295 | - TransactionalEmailTemplateService::TYPE_BOOKING_CONFIRMATION, | |
| 1296 | - $booking->contact_email, | |
| 1297 | - $vars | |
| 1298 | - ); | |
| 1329 | + $this->sendBookingConfirmedEmail($bookingId); | |
| 1299 | 1330 | |
| 1300 | 1331 | return; |
| 1301 | 1332 | } |
| 1302 | 1333 | |
| @@ -1380,9 +1411,20 @@ | ||
| 1380 | 1411 | } |
| 1381 | 1412 | |
| 1382 | 1413 | switch ($emailType) { |
| 1383 | 1414 | case 'confirmation': |
| 1384 | - $this->sendBookingConfirmationEmail($bookingId); | |
| 1415 | + // Resend the email that matches the booking's CURRENT state so it | |
| 1416 | + // is identical to the automated one. A confirmed booking (or a | |
| 1417 | + // completed one — it was confirmed before it travelled) gets the | |
| 1418 | + // "booking confirmed" email (status_confirmed context → the | |
| 1419 | + // `booking_confirmed` / booking.confirmed template); anything | |
| 1420 | + // still pending gets the initial "booking received" email | |
| 1421 | + // (booking_created context → the `booking_confirmation` template). | |
| 1422 | + if (in_array((string) ($booking->status ?? ''), ['confirmed', 'completed'], true)) { | |
| 1423 | + $this->sendBookingConfirmedEmail($bookingId); | |
| 1424 | + } else { | |
| 1425 | + $this->sendBookingConfirmationEmail($bookingId); | |
| 1426 | + } | |
| 1385 | 1427 | break; |
| 1386 | 1428 | |
| 1387 | 1429 | case 'reminder': |
| 1388 | 1430 | $this->sendBookingReminderEmail($booking); |