| @@ -42,8 +42,27 @@ | ||
| 42 | 42 | self::notifyAdminCancellation($bookingId, $bookingData); |
| 43 | 43 | } |
| 44 | 44 | |
| 45 | 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 | + /** | |
| 46 | 65 | * Notify admin of new booking |
| 47 | 66 | */ |
| 48 | 67 | private static function notifyAdminNewBooking(int $bookingId, $bookingData): void |
| 49 | 68 | { |
| @@ -97,9 +116,17 @@ | ||
| 97 | 116 | } |
| 98 | 117 | |
| 99 | 118 | $vars = TransactionalEmailTemplateService::variablesFromBooking($booking); |
| 100 | 119 | $vars['payment_amount_formatted'] = yatra_format_price((float) ($paymentData['amount'] ?? 0)); |
| 101 | - $vars['payment_method'] = (string) ($paymentData['payment_method'] ?? __('Online payment', 'yatra')); | |
| 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 | + ); | |
| 102 | 129 | $vars['transaction_id'] = (string) ($paymentData['transaction_id'] ?? ''); |
| 103 | 130 | |
| 104 | 131 | TransactionalEmailTemplateService::sendIfEnabled( |
| 105 | 132 | TransactionalEmailTemplateService::TYPE_ADMIN_PAYMENT_RECEIVED, |
| @@ -108,8 +135,43 @@ | ||
| 108 | 135 | ); |
| 109 | 136 | } |
| 110 | 137 | |
| 111 | 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 | + /** | |
| 112 | 174 | * Notify customer of payment received |
| 113 | 175 | */ |
| 114 | 176 | private static function notifyCustomerPaymentReceived(array $paymentData): void |
| 115 | 177 | { |
| @@ -121,13 +183,21 @@ | ||
| 121 | 183 | } |
| 122 | 184 | |
| 123 | 185 | $vars = TransactionalEmailTemplateService::variablesFromBooking($booking); |
| 124 | 186 | $vars['payment_amount_formatted'] = yatra_format_price((float) ($paymentData['amount'] ?? 0)); |
| 125 | - $vars['payment_method'] = (string) ($paymentData['payment_method'] ?? __('Online payment', 'yatra')); | |
| 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 | + ); | |
| 126 | 196 | $vars['transaction_id'] = (string) ($paymentData['transaction_id'] ?? ''); |
| 127 | 197 | |
| 128 | 198 | TransactionalEmailTemplateService::sendIfEnabled( |
| 129 | - TransactionalEmailTemplateService::TYPE_PAYMENT_CONFIRMATION, | |
| 199 | + self::paymentTemplateTypeFor($booking), | |
| 130 | 200 | $booking->contact_email, |
| 131 | 201 | $vars |
| 132 | 202 | ); |
| 133 | 203 | } |