PluginProbe
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler / 1.6.1
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler v1.6.1
1.6.5 1.6.4 1.6.3 1.6.2 1.6.1 1.6.0 1.5.4 1.5.5 1.5.3 1.5.2 1.5.1 1.5.0 1.4.2 1.4.1 1.4.0 1.3.28 1.3.27 1.3.26 1.3.25 1.3.23 1.3.22 1.3.21 1.3.20 1.3.19 trunk All 48 releases
fluent-cart / app / Services / Renderer / Receipt / ThankYouRender.php

ThankYouRender.php in FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler 1.6.1, at app/Services/Renderer/Receipt/ThankYouRender.php

1,389 lines 61.4 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace FluentCart\App\Services\Renderer\Receipt;
4
5 use FluentCart\Api\StoreSettings;
6 use FluentCart\App\App;
7 use FluentCart\App\Helpers\Helper;
8 use FluentCart\App\Modules\Tax\TaxModule;
9 use FluentCart\App\Modules\Templating\AssetLoader;
10 use FluentCart\App\Vite;
11 use FluentCart\Framework\Support\Arr;
12 use FluentCart\App\Modules\PaymentMethods\Core\GatewayManager;
13
14 class ThankYouRender
15 {
16
17 protected $config = null;
18
19 protected $settings = null;
20
21 protected $is_first_time = false;
22
23 protected $order_operation = null;
24
25 private $fctTaxSummaryCache = [];
26
27 public function __construct($config)
28 {
29 $this->config = $config;
30
31 $this->is_first_time = Arr::get($this->config, 'is_first_time', false);
32 $this->order_operation = Arr::get($this->config, 'order_operation', false);
33
34 $this->settings = new StoreSettings();
35 AssetLoader::enqueueThankYouPageAssets();
36
37 }
38
39 private function getMemoizedTaxSummary($order)
40 {
41 if (!$order) {
42 return TaxSummaryHelper::computeTaxSummary($order);
43 }
44 $id = (int) $order->id;
45 if (!isset($this->fctTaxSummaryCache[$id])) {
46 $this->fctTaxSummaryCache[$id] = TaxSummaryHelper::computeTaxSummary($order);
47 }
48 return $this->fctTaxSummaryCache[$id];
49 }
50
51 public function renderWrapperStart()
52 {
53 ?>
54 <div class="fct-thank-you-page">
55 <div class="fct-thank-you-page-inner">
56 <div class="fct-thank-you-page-content email-template-content">
57 <?php
58 }
59
60 public function renderWrapperEnd()
61 {
62 ?>
63 </div>
64 </div>
65 </div>
66 <?php
67 }
68
69 public function render($hide_wrapper = false)
70 {
71 $order = Arr::get($this->config, 'order', null);
72
73 if (!$order) {
74 return;
75 }
76 ?>
77 <?php if (!$hide_wrapper) {
78 $this->renderWrapperStart();
79 } ?>
80 <?php do_action('fluent_cart/receipt/thank_you/before_header', $this->config); ?>
81 <?php $this->renderHeader(); ?>
82 <?php do_action('fluent_cart/receipt/thank_you/after_header', $this->config); ?>
83
84 <?php do_action('fluent_cart/receipt/thank_you/before_body', $this->config); ?>
85 <?php $this->renderBody(); ?>
86 <?php do_action('fluent_cart/receipt/thank_you/after_body', $this->config); ?>
87 <?php if (!$hide_wrapper) {
88 $this->renderWrapperEnd();
89 } ?>
90
91 <?php
92
93 $this->renderFooter();
94
95 do_action('fluent_cart/after_receipt', [
96 'order' => $order,
97 'is_first_time' => $this->is_first_time ?? false,
98 'order_operation' => $this->order_operation ?? null
99 ]);
100
101 if (!empty($this->is_first_time)) {
102 do_action('fluent_cart/after_receipt_first_time', [
103 'order' => $order,
104 'order_operation' => $this->order_operation ?? null
105 ]);
106 }
107 }
108
109 public function renderHeader()
110 {
111 $bgColor = '#d4edda';
112 $titleColor = '#155724';
113 $iconBg = '#155724bd';
114
115 $order = Arr::get($this->config, 'order', null);
116
117 if ($order->payment_status !== 'paid') {
118 $bgColor = '#fff3cd';
119 $titleColor = '#856404';
120 $iconBg = '#856404bd';
121 }
122 ?>
123 <div class="fct-thank-you-page-header" style="background: <?php echo esc_attr($bgColor); ?>;">
124 <?php if ($order->payment_status !== 'paid') : ?>
125 <div class="fct-thank-you-page-header-icon" style="background: <?php echo esc_attr($iconBg); ?>;">
126 <svg class="w-64 h-64" xmlns="http://www.w3.org/2000/svg"
127 viewBox="0 0 1024 1024" fill="currentColor">
128 <path
129 d="M480 674V192c0-18 14-32 32-32s32 14 32 32v482h-64zm0 63h64v60h-64v-60zM0 512C0 229 229 0 512 0s512 229 512 512-229 512-512 512S0 795 0 512zm961 0c0-247-202-448-449-448S64 265 64 512s201 448 448 448 449-201 449-448z"></path>
130 </svg>
131 </div>
132 <h1 class="fct-thank-you-page-header-title" style="color:<?php echo esc_attr($titleColor); ?>">
133 <?php echo esc_html__('Payment Pending!', 'fluent-cart'); ?>
134 </h1>
135
136 <?php else: ?>
137 <div class="fct-thank-you-page-header-icon" style="background: <?php echo esc_attr($iconBg); ?>;">
138 <svg viewBox="0 0 24 24" fill="none" stroke="currentColor"
139 stroke-width="3" stroke-linecap="round" stroke-linejoin="round">
140 <polyline points="20,6 9,17 4,12"></polyline>
141 </svg>
142 </div>
143 <h1 class="fct-thank-you-page-header-title" style="color:<?php echo esc_attr($titleColor); ?>;">
144 <?php echo esc_html__('Purchase Successful!', 'fluent-cart'); ?>
145 </h1>
146 <?php endif; ?>
147
148 <?php do_action('fluent_cart/receipt/thank_you/after_header_title', $this->config); ?>
149
150 </div>
151
152 <?php
153 }
154
155 public function renderBody()
156 {
157 $order = Arr::get($this->config, 'order', null);
158
159 if (!$order) {
160 return;
161 }
162 ?>
163 <div class="fct-thank-you-page-body">
164 <div class="fct-thank-you-page-body-inner">
165 <div class="fct-thank-you-page-body-content">
166 <div class="fct-thank-you-page-body-content-inner">
167 <?php do_action('fluent_cart/receipt/thank_you/before_order_header', $this->config); ?>
168 <?php $this->renderOrderHeader(); ?>
169 <?php do_action('fluent_cart/receipt/thank_you/after_order_header', $this->config); ?>
170
171 <?php $this->renderStoreTaxInformation(); ?>
172
173 <?php do_action('fluent_cart/receipt/thank_you/before_order_items', $this->config); ?>
174 <?php $this->renderOrderItems(); ?>
175 <?php do_action('fluent_cart/receipt/thank_you/after_order_items', $this->config); ?>
176
177 <?php $this->renderSubscriptionItems(); ?>
178
179 <?php $this->renderDownloads(); ?>
180
181 <?php $this->renderLicenses(); ?>
182
183 <?php $this->renderAddress(); ?>
184
185 <?php $this->renderThankYouPageInstructions(); ?>
186
187 </div>
188 </div>
189 </div>
190 </div>
191
192 <?php
193 }
194
195 public function renderOrderHeader()
196 {
197 $order = Arr::get($this->config, 'order', null);
198 $profilePage = $this->settings->getCustomerProfilePage();
199 ?>
200 <div class="no-print">
201 <div class="no-print-title">
202 <?php
203 echo sprintf(
204 /* translators: %s is the customer's full name */
205 esc_html__('Hello %s!', 'fluent-cart'),
206 esc_html($order->customer->full_name)
207 );
208 ?>
209 </div>
210 <?php if ($order->payment_status === 'paid') : ?>
211 <p>
212 <?php
213 printf(
214 '%s<strong style="color: #007bff;"><a href="%s">#%s</a></strong>%s',
215 esc_html__('Your order ', 'fluent-cart'),
216 esc_url($profilePage . 'order/' . $order->uuid),
217 esc_html($order->invoice_no),
218 esc_html__(' has been placed successfully.', 'fluent-cart')
219 );
220 ?>
221 </p>
222 <?php else: ?>
223 <p>
224
225 <?php
226 printf(
227 '<strong style="color: #007bff;"><a href="%s">%s</a></strong> %s <a style="color: #007bff;" target="_blank" href="%s">%s</a>.',
228 esc_url($profilePage . 'order/' . $order->uuid),
229 esc_html__('Your order', 'fluent-cart'),
230 esc_html__('has payment due. You can pay from', 'fluent-cart'),
231 esc_url(\FluentCart\App\Services\Payments\PaymentHelper::getCustomPaymentLink($order->uuid)),
232 esc_html__('here', 'fluent-cart')
233 );
234 ?>
235
236 </p>
237 <?php endif; ?>
238
239 </div>
240
241 <?php
242 }
243
244 public function renderStoreTaxInformation()
245 {
246 $order = Arr::get($this->config, 'order', null);
247
248 $orderTaxRates = $order->getPrimaryOrderTaxRate();
249 if ($order->tax_total > 0 || $orderTaxRates): ?>
250 <div class="fct_invoice_tax_content">
251 <?php
252 if ($orderTaxRates) {
253 $storeVatNumber = Arr::get($orderTaxRates->meta, 'store_vat_number', '');
254 $taxcountry = Arr::get($orderTaxRates->meta ?? [], 'tax_country', '');
255 if ($storeVatNumber !== '') {
256 echo '<p>' . esc_html(TaxModule::getCountryTaxTitle($taxcountry)) . ': ' . esc_html($storeVatNumber) . '</p>';
257 }
258 }
259 ?>
260 </div>
261 <?php endif;
262 }
263
264 public function renderOrderItems()
265 {
266 $order = Arr::get($this->config, 'order', null);
267
268 if ($order->order_items) : ?>
269 <div class="fct-thank-you-page-order-items">
270 <?php $this->renderOrderItemsHeader(); ?>
271
272 <?php $this->renderOrderItemsBody(); ?>
273 </div>
274 <?php endif;
275 }
276
277 public function renderOrderItemsHeader()
278 {
279 ?>
280 <div class="fct-thank-you-page-order-items-header">
281 <div class="fct-thank-you-page-order-items-header-row">
282 <?php echo esc_html__('Item', 'fluent-cart'); ?>
283 </div>
284 <div class="fct-thank-you-page-order-items-header-row">
285 <?php echo esc_html__('Total', 'fluent-cart'); ?>
286 </div>
287 </div>
288 <?php
289 }
290
291 public function renderOrderItemsBody()
292 {
293 $order = Arr::get($this->config, 'order', null);
294 $fctTaxDisplayMode = TaxSummaryHelper::getTaxDisplayMode();
295 ?>
296 <div class="fct-thank-you-page-order-items-body">
297 <?php
298 $order->loadMissing(['order_items']);
299 $orderItems = $order->getProductItems()->toArray();
300 $orderItems = $this->buildBundleItemsTree($orderItems);
301
302 foreach ($orderItems as $item) :
303 ?>
304 <div class="fct-thank-you-page-order-items-list">
305 <div class="fct-thank-you-page-order-items-list-title">
306 <p class="fct-thank-you-page-order-items-list-quantity">
307 <?php echo esc_html($item['post_title']); ?>
308 <?php if ($item['quantity'] > 1): ?>
309 <span>x <?php echo esc_html(Helper::translateNumber($item['quantity'])); ?></span>
310 <?php endif; ?>
311 </p>
312 <?php if (!empty($item['title']) && $item['title'] !== $item['post_title']): ?>
313 <p class="fct-thank-you-page-order-items-list-variant-title">
314 - <?php echo esc_html(!empty($item['variation_display_title']) ? $item['variation_display_title'] : $item['title']); ?>
315 </p>
316 <?php endif; ?>
317 <?php if ($item['payment_type'] === 'subscription' && !empty($item['payment_info'])): ?>
318 <p class="fct-thank-you-page-order-items-list-payment-info">
319 <?php echo wp_kses_post($item['payment_info']) ?>
320 </p>
321 <?php endif; ?>
322 <?php $this->renderBundleProducts($item); ?>
323 </div>
324 <div class="fct-thank-you-page-order-items-list-price">
325 <div class="fct-thank-you-page-order-items-list-price-inner">
326 <?php echo esc_html($item['formatted_total']); ?>
327 </div>
328 </div>
329 </div>
330
331 <div class="fct-thank-you-page-order-items-tax-info">
332 <?php if ($fctTaxDisplayMode !== 'simplified'): ?>
333 <?php $this->renderItemTaxPill($item, $order); ?>
334 <?php endif; ?>
335 <?php if (!empty($item['setup_info'])): ?>
336 <div class="fct-thank-you-page-order-items-setup-fee">
337 <div class="setup-fee">
338 <?php echo esc_html(Arr::get($item, 'other_info.signup_fee_name', '')); ?>
339 </div>
340
341 <div class="setup-fee-amount">
342 <?php echo esc_html(Helper::toDecimal(Arr::get($item, 'other_info.signup_fee', ''))); ?>
343 </div>
344 </div>
345 <?php endif; ?>
346 <?php if ($fctTaxDisplayMode !== 'simplified'): ?>
347 <?php $this->renderItemSetupFeeTaxPills($item, $order); ?>
348 <?php endif; ?>
349 </div>
350 <?php endforeach; ?>
351
352 <?php $this->renderOrderTotal(); ?>
353
354 <!-- tax note -->
355 <?php $this->renderTaxNote(); ?>
356
357 </div>
358 <?php
359 }
360
361 public function renderThankYouPageInstructions()
362 {
363 $order = Arr::get($this->config, 'order', null);
364 if (!$order) {
365 return;
366 }
367 $transaction = $order->getLatestTransaction();
368 $methodSlug = '';
369 $thankYouPageInstructions = '';
370 if ($transaction && !empty($transaction->payment_method)) {
371 $methodSlug = $transaction->payment_method;
372 }
373 if (GatewayManager::has($methodSlug)) {
374 $gatewayInstance = GatewayManager::getInstance($methodSlug);
375 if ($gatewayInstance && isset($gatewayInstance->settings)) {
376 $gatewaySettings = (array) $gatewayInstance->settings->get();
377 $thankYouPageInstructions = Arr::get($gatewaySettings, 'thank_you_page_instructions', '');
378 }
379 }
380
381 if (!empty($thankYouPageInstructions)) : ?>
382
383 <div style="max-width: 620px; margin: 15px auto 0; font-family: Arial, Helvetica, sans-serif;">
384 <div style="font-size: 14px; color: #2F3448; padding: 12px 0; border-top: 1px solid #e7eaee;">
385 <?php echo wp_kses_post($thankYouPageInstructions); ?>
386 </div>
387 </div>
388 <?php endif;
389 }
390
391 public function renderOrderTotal()
392 {
393 ?>
394 <div class="fct-thank-you-page-order-items-total">
395 <?php $this->renderSubtotal(); ?>
396 <?php $this->renderDiscount(); ?>
397 <?php $this->renderShipping(); ?>
398 <?php $this->renderFees(); ?>
399 <?php $this->renderTaxSummaryBox(); ?>
400
401 <?php $this->renderProrateCredit(); ?>
402 <?php $this->renderRefund(); ?>
403 <?php $this->renderTotal(); ?>
404 <?php $this->renderPaymentMethod(); ?>
405 </div>
406 <?php
407 }
408
409 public function renderTaxNote()
410 {
411 $order = Arr::get($this->config, 'order', null);
412 if ($order->isReverseChargeTaxOrder()): ?>
413 <div style="text-align: right; font-size: 14px; margin-top: 10px;">
414 <?php echo '*' . esc_html(TaxModule::getReverseChargeNoticeText()) ?>
415 </div>
416 <?php
417 endif;
418 }
419
420 public function renderSubtotal()
421 {
422 $order = Arr::get($this->config, 'order', null);
423 if ($order->subtotal != $order->total_amount || $order->tax_total > 0): ?>
424 <div class="fct-meta-line fct-thank-you-page-order-items-total-subtotal">
425 <div class="fct-meta-line-label fct-thank-you-page-order-items-total-label">
426 <?php echo esc_html__('Subtotal', 'fluent-cart'); ?>
427 </div>
428 <div class="fct-meta-line-value fct-thank-you-page-order-items-total-value"><?php echo esc_html(Helper::toDecimal($order->subtotal)); ?></div>
429 </div>
430 <?php endif;
431 }
432
433 public function renderDiscount()
434 {
435 $order = Arr::get($this->config, 'order', null);
436 $prorateCredit = (int) Arr::get($order->config, 'prorate_credit', 0);
437 $upgradeDiscount = $order->manual_discount_total - $prorateCredit;
438 // When the prorate credit IS the whole discount, label the row directly
439 // instead of showing "Discount" with a single redundant breakdown row.
440 $onlyProrateCredit = $prorateCredit > 0 && $upgradeDiscount <= 0 && $order->coupon_discount_total <= 0;
441
442 if ($order->manual_discount_total + $order->coupon_discount_total > 0): ?>
443 <div class="fct-meta-line fct-thank-you-page-order-items-total-discount">
444 <div class="fct-meta-line-label fct-thank-you-page-order-items-total-label">
445 <?php echo $onlyProrateCredit ? esc_html__('Prorate Credit', 'fluent-cart') : esc_html__('Discount', 'fluent-cart'); ?>
446 </div>
447 <div class="fct-meta-line-value fct-thank-you-page-order-items-total-value">
448 - <?php echo esc_html(Helper::toDecimal($order->manual_discount_total + $order->coupon_discount_total)); ?>
449 </div>
450 </div>
451 <?php if ($prorateCredit > 0 && $upgradeDiscount > 0): ?>
452 <div class="fct-meta-line" style="padding-left:12px;">
453 <div class="fct-meta-line-label" style="font-size:12px;color:rgb(107,114,128);">
454 <?php echo esc_html__('Upgrade Discount', 'fluent-cart'); ?>
455 </div>
456 <div class="fct-meta-line-value" style="font-size:12px;color:rgb(107,114,128);">
457 <?php echo esc_html(Helper::toDecimal($upgradeDiscount)); ?>
458 </div>
459 </div>
460 <?php endif; ?>
461 <?php if ($prorateCredit > 0 && !$onlyProrateCredit): ?>
462 <div class="fct-meta-line" style="padding-left:12px;">
463 <div class="fct-meta-line-label" style="font-size:12px;color:rgb(107,114,128);">
464 <?php echo esc_html__('Prorate Credit', 'fluent-cart'); ?>
465 </div>
466 <div class="fct-meta-line-value" style="font-size:12px;color:rgb(107,114,128);">
467 <?php echo esc_html(Helper::toDecimal($prorateCredit)); ?>
468 </div>
469 </div>
470 <?php endif; ?>
471 <?php endif;
472 }
473
474 public function renderProrateCredit()
475 {
476 // Rendered as a sub-row inside renderDiscount.
477 }
478
479 public function renderShipping()
480 {
481 $order = Arr::get($this->config, 'order', null);
482
483 if ($order->shipping_total <= 0) {
484 return;
485 }
486 $displayShipping = (int) $order->shipping_total;
487 if ($order->isReverseChargeTaxOrder()) {
488 $rcAdj = (int) Arr::get($this->getMemoizedTaxSummary($order), 'rcShippingAdjustment', 0);
489 if ($rcAdj > 0) {
490 $displayShipping = max(0, $displayShipping - $rcAdj);
491 }
492 }
493 $shippingMethodTitle = (string) Arr::get($order->config, 'shipping_method_title', '');
494 ?>
495 <div class="fct-meta-line fct-thank-you-page-order-items-total-shipping">
496 <div class="fct-meta-line-label fct-thank-you-page-order-items-total-label">
497 <?php echo esc_html__('Shipping', 'fluent-cart'); ?>
498 <?php if ($shippingMethodTitle): ?>
499 <span class="fct-shipping-method-name"><?php echo esc_html($shippingMethodTitle); ?></span>
500 <?php endif; ?>
501 </div>
502 <div class="fct-meta-line-value fct-thank-you-page-order-items-total-value"><?php echo esc_html(Helper::toDecimal($displayShipping)); ?></div>
503 </div>
504 <?php
505 }
506
507 public function renderFees()
508 {
509 $order = Arr::get($this->config, 'order', null);
510 if (!$order || $order->fee_total <= 0) {
511 return;
512 }
513 $feeItems = $order->feeItems()->get();
514 foreach ($feeItems as $feeItem): ?>
515 <div class="fct-meta-line fct-thank-you-page-order-items-total-fee">
516 <div class="fct-meta-line-label fct-thank-you-page-order-items-total-label">
517 <?php echo esc_html($feeItem->title); ?>
518 </div>
519 <div class="fct-meta-line-value fct-thank-you-page-order-items-total-value">
520 <?php echo esc_html(Helper::toDecimal($feeItem->subtotal)); ?>
521 </div>
522 </div>
523 <?php endforeach;
524 }
525
526 public function renderRefund()
527 {
528 $order = Arr::get($this->config, 'order', null);
529
530 if ($order->total_refund > 0): ?>
531 <div class="fct-meta-line fct-thank-you-page-order-items-total-refund">
532 <div class="fct-meta-line-label fct-thank-you-page-order-items-total-label">
533 <?php echo esc_html__('Refund', 'fluent-cart'); ?>
534 </div>
535 <div class="fct-meta-line-value fct-thank-you-page-order-items-total-value">
536 - <?php echo esc_html(Helper::toDecimal($order->total_refund)); ?>
537 </div>
538 </div>
539 <?php endif;
540 }
541
542 public function renderTotal()
543 {
544 $order = Arr::get($this->config, 'order', null);
545 $displayTotal = (int) $order->total_amount - (int) $order->total_refund;
546 if ($order->isReverseChargeTaxOrder()) {
547 $rcAdj = (int) Arr::get($this->getMemoizedTaxSummary($order), 'rcTotalAdjustment', 0);
548 if ($rcAdj > 0) {
549 $displayTotal = max(0, $displayTotal - $rcAdj);
550 }
551 }
552 ?>
553 <div class="fct-meta-line fct-thank-you-page-order-items-total-total">
554 <div class="fct-meta-line-label fct-thank-you-page-order-items-total-label">
555 <?php echo esc_html__('Total', 'fluent-cart'); ?>
556 </div>
557 <div class="fct-meta-line-value fct-thank-you-page-order-items-total-value">
558 <?php echo esc_html(Helper::toDecimal($displayTotal)); ?>
559 </div>
560 </div>
561 <?php
562 }
563
564 public function renderPaymentMethod()
565 {
566 $order = Arr::get($this->config, 'order', null);
567 $transaction = $order->getLatestTransaction();
568 ?>
569 <div class="fct-meta-line fct-thank-you-page-order-items-total-payment-method">
570 <div class="fct-meta-line-label fct-thank-you-page-order-items-total-label">
571 <?php echo esc_html__('Payment Method', 'fluent-cart'); ?>
572 </div>
573 <div class="fct-meta-line-value fct-thank-you-page-order-items-total-value">
574 <?php if ($transaction->card_last_4) :
575 echo esc_html($transaction->card_brand) . ' ' . esc_html($transaction->card_last_4);
576 else:
577 $title = $transaction->payment_method;
578 $gateway = GatewayManager::getInstance($transaction->payment_method);
579 $title = $gateway ? $gateway->getMeta('title') : $title;
580 echo esc_html($title);
581 endif; ?>
582 </div>
583 </div>
584 <?php
585 }
586
587 public function renderSubscriptionItems()
588 {
589 $order = Arr::get($this->config, 'order', null);
590 $subscriptions = $order->subscriptions;
591
592 if ($subscriptions->count() == 0) {
593 return;
594 }
595 ?>
596 <div class="fct-thank-you-page-order-items-subscriptions">
597 <p class="fct-thank-you-page-order-items-subscriptions-heading">
598 <?php echo esc_html__('Subscription Details', 'fluent-cart'); ?>
599 </p>
600
601 <table class="fct-thank-you-page-order-items-subscriptions-table" role="presentation">
602 <tbody>
603 <?php foreach ($subscriptions as $subs): ?>
604 <tr>
605 <td class="fct-thank-you-page-order-items-subscriptions-table-file">
606 <p>
607 <?php echo esc_html($subs->display_item_name); ?>
608 </p>
609 </td>
610
611 <td class="fct-thank-you-page-order-items-subscriptions-billing-infos">
612 <div>
613 <?php if (!empty($subs->payment_info)) : ?>
614 <span>
615 <?php echo $subs->payment_info; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
616 </span>
617 <?php endif; ?>
618
619 <?php if (!empty($subs->next_billing_date)) : ?>
620 <p class="fct-thank-you-page-order-items-subscriptions-billing-infos-next-billing"><?php
621 echo sprintf(
622 /* translators: 1: Next billing date */
623 esc_html__('- Auto renews on %1$s', 'fluent-cart'),
624 esc_html(
625 \FluentCart\App\Services\DateTime\DateTime::gmtToTimezone($subs->next_billing_date)->format('M d, Y h:i A')
626 )
627 );
628 ?>
629 </p>
630 <?php endif; ?>
631 </div>
632 </td>
633 </tr>
634 <?php endforeach; ?>
635 </tbody>
636 </table>
637 </div>
638
639
640 <?php
641 // App::make('view')->render('invoice.parts.subscription_items', [
642 // 'subscriptions' => $order->subscriptions,
643 // 'order' => $order
644 // ]);
645 }
646
647 public function renderDownloads()
648 {
649 $order = Arr::get($this->config, 'order', null);
650 $downloads = $order->getDownloads();
651 if (!$downloads) {
652 return;
653 }
654 ?>
655 <div class="fct-thank-you-page-order-items-downloads">
656 <p class="fct-thank-you-page-order-items-downloads-heading">
657 <?php echo esc_html__('Downloads', 'fluent-cart'); ?>
658 </p>
659
660 <table class="fct-thank-you-page-order-items-downloads-table"
661 role="presentation">
662 <tbody>
663 <tr>
664 <td>
665 <table role="presentation" width="100%">
666 <tbody>
667 <?php foreach ($downloads as $downloadItem): ?>
668 <tr>
669 <td>
670 <?php if ($downloadItem['downloads']): ?>
671
672 <table role="presentation" width="100%">
673 <tbody>
674 <?php foreach ($downloadItem['downloads'] as $download): ?>
675 <tr>
676 <td class="fct-thank-you-page-order-items-downloads-table-file">
677 <p>
678 <?php echo esc_html($download['title']); ?>
679 <?php if ($download['file_size']): ?>
680 <span>(<?php echo esc_html(Helper::readableFileSize($download['file_size'])); ?>)</span>
681 <?php endif; ?>
682 </p>
683 </td>
684 <td class="fct-thank-you-page-order-items-downloads-button">
685 <a href="<?php echo esc_url($download['download_url'] ?? ''); ?>">
686 <?php echo esc_html__('Download', 'fluent-cart'); ?>
687 </a>
688 </td>
689 </tr>
690 <?php endforeach; ?>
691 </tbody>
692 </table>
693
694 <?php endif; ?>
695
696 </td>
697 </tr>
698 <?php endforeach; ?>
699 </tbody>
700 </table>
701 </td>
702 </tr>
703 </tbody>
704 </table>
705 </div>
706
707 <?php $this->renderDownloadsNotice(); ?>
708
709 <?php
710 }
711
712 public function renderDownloadsNotice($show_notice = false)
713 {
714 $showNotice = $show_notice ?? true;
715 ?>
716 <?php if (!$showNotice) {
717 return;
718 } ?>
719 <table
720 class="fct-thank-you-page-order-items-downloads-notice"
721 role="presentation">
722 <tbody>
723 <tr>
724 <td>
725 <p class="fct-thank-you-page-order-items-downloads-notice-title">
726 <?php echo esc_html__('Important', 'fluent-cart'); ?>
727 </p>
728 <p class="fct-thank-you-page-order-items-downloads-notice-content">
729 <?php echo esc_html__('This download link is valid for 7 days. After that, you can download the files again from your account
730 on our website.', 'fluent-cart'); ?>
731 </p>
732 </td>
733 </tr>
734 </tbody>
735 </table>
736 <?php
737 }
738
739 public function renderLicenseNotice($show_notice = false)
740 {
741 $showNotice = $show_notice ?? true;
742 ?>
743 <?php if (!$showNotice) {
744 return;
745 } ?>
746 <table
747 class="fct-thank-you-page-order-items-downloads-notice"
748 role="presentation">
749 <tbody>
750 <tr>
751 <td>
752 <p class="fct-thank-you-page-order-items-downloads-notice-title">
753 <?php echo esc_html__('Important', 'fluent-cart'); ?>
754 </p>
755 <p class="fct-thank-you-page-order-items-downloads-notice-content">
756 <?php echo esc_html__('This download link is valid for 7 days. After that, you can download the files again from your account on our website.', 'fluent-cart'); ?>
757 </p>
758 </td>
759 </tr>
760 </tbody>
761 </table>
762 <?php
763 }
764
765 public function renderLicenses()
766 {
767 $order = Arr::get($this->config, 'order', null);
768 $licenses = $order->getLicenses();
769 if (!$licenses || $licenses->count() == 0) {
770 return;
771 }
772 ?>
773 <div class="fct-thank-you-page-order-items-licenses">
774 <p class="fct-thank-you-page-order-items-licenses-heading">
775 <?php echo esc_html__('Licenses', 'fluent-cart'); ?>
776 </p>
777 <table class="fct-thank-you-page-order-items-licenses-table" role="presentation">
778 <tbody>
779 <tr>
780 <td>
781 <table role="presentation">
782 <tbody>
783
784 <?php foreach ($licenses as $license): ?>
785 <tr>
786 <td class="fct-thank-you-page-order-items-licenses-table-file">
787 <p>
788 <?php echo esc_html($license->productVariant->variation_title); ?>:
789 <?php echo esc_html($license->license_key); ?>
790 </p>
791 </td>
792 </tr>
793 <?php endforeach; ?>
794 </tbody>
795 </table>
796 </td>
797 </tr>
798 </tbody>
799 </table>
800 </div>
801
802 <?php $this->renderLicenseNotice(); ?>
803 <?php
804 }
805
806 public function renderAddress()
807 {
808 $order = Arr::get($this->config, 'order', null);
809 ?>
810 <div class="fct-thank-you-page-order-items-addresses">
811 <?php $this->renderBillToAddress(); ?>
812 <?php if ($order->fulfillment_type === 'physical') : ?>
813 <?php $this->renderShipToAddress(); ?>
814 <?php endif; ?>
815 </div>
816 <?php
817 }
818
819 public function renderBillToAddress()
820 {
821 $order = Arr::get($this->config, 'order', null);
822 ?>
823 <div class="fct-thank-you-page-order-items-addresses-bill-to">
824 <h5>
825 <?php echo esc_html__('Bill To', 'fluent-cart'); ?>
826 </h5>
827 <?php
828 if (!empty($order->billing_address)) :
829 ?>
830 <div class="fct-thank-you-page-order-items-addresses-bill-to-address">
831 <?php echo esc_html($order->billing_address->getAddressAsText()); ?>
832 </div>
833
834 <div class="fct-thank-you-page-order-items-addresses-bill-to-email">
835 <?php echo esc_html($order->customer->email); ?>
836 </div>
837 <?php else: ?>
838 <div class="fct-thank-you-page-order-items-addresses-bill-to-name">
839 <?php echo esc_html($order->customer->full_name); ?>
840 </div>
841 <div class="fct-thank-you-page-order-items-addresses-bill-to-email">
842 <?php echo esc_html($order->customer->email); ?>
843 </div>
844 <?php endif; ?>
845 <?php
846 $phoneNumber = Arr::get($order->billing_address->meta ?? [], 'other_data.phone', '');
847 if ($phoneNumber !== ''):
848 ?>
849 <div class="fct-thank-you-page-order-items-addresses-bill-to-phone">
850 <?php echo esc_html($phoneNumber); ?>
851 </div>
852 <?php endif; ?>
853 <?php
854 $companyName = $order->billing_address
855 ? Arr::get($order->billing_address->meta ?? [], 'other_data.company_name', '')
856 : '';
857 if ($companyName === '') {
858 $companyName = $order->getCustomerTaxName();
859 }
860 if ($companyName !== ''):
861 ?>
862 <div class="fct-thank-you-page-order-items-addresses-bill-to-company-name">
863 <?php echo esc_html($companyName); ?>
864 </div>
865 <?php endif; ?>
866 <?php
867 $legalRegId = $order->billing_address
868 ? Arr::get($order->billing_address->meta ?? [], 'other_data.legal_registration_id', '')
869 : '';
870 if ($legalRegId === '') {
871 $legalRegId = Arr::get($order->getBusinessInfo(), 'legal_registration_id', '');
872 }
873 if ($legalRegId !== ''):
874 ?>
875 <div class="fct-thank-you-page-order-items-addresses-bill-to-legal-reg">
876 <?php echo esc_html__('Reg. ID', 'fluent-cart') . ': ' . esc_html($legalRegId); ?>
877 </div>
878 <?php endif; ?>
879 <div class="fct-thank-you-page-order-items-addresses-bill-to-vat-number">
880 <?php
881 $vatNumber = $order->getCustomerTaxNumber();
882 if ($vatNumber !== '') {
883 $vatLabel = __('VAT/Tax ID', 'fluent-cart');
884 echo esc_html($vatLabel) . ': ' . esc_html($vatNumber);
885 }
886 ?>
887 </div>
888 <?php
889 $reverseChargeDeclaration = Arr::get($order->getBusinessInfo(), 'reverse_charge_declaration', '');
890 if ($reverseChargeDeclaration !== ''):
891 ?>
892 <div class="fct-thank-you-page-order-items-addresses-bill-to-reverse-charge">
893 <strong><?php echo esc_html__('Reverse Charge Declaration', 'fluent-cart'); ?>:</strong>
894 <?php echo esc_html($reverseChargeDeclaration); ?>
895 </div>
896 <?php endif; ?>
897 </div>
898 <?php
899 }
900
901 public function renderShipToAddress()
902 {
903 $order = Arr::get($this->config, 'order', null);
904 ?>
905 <div class="fct-thank-you-page-order-items-addresses-ship-to">
906 <h5 class="fct-thank-you-page-order-items-addresses-ship-to-title">
907 <?php echo esc_html__('Ship To', 'fluent-cart'); ?>
908 </h5>
909 <?php if (!empty($order->shipping_address)) : ?>
910 <div class="fct-thank-you-page-order-items-addresses-ship-to-address">
911 <?php echo esc_html($order->shipping_address->getAddressAsText()); ?>
912 </div>
913 <!-- show phone number -->
914 <?php
915 $phone = Arr::get($order->shipping_address->meta ?? [], 'other_data.phone', '');
916 if ($phone !== ''):?>
917 <div class="fct-thank-you-page-order-items-addresses-ship-to-phone">
918 <?php echo esc_html($phone); ?>
919 </div>
920 <?php endif; ?>
921 <?php else: ?>
922 <div class="fct-thank-you-page-order-items-addresses-ship-to-name">
923 <?php echo esc_html($order->customer->full_name); ?>
924 </div>
925 <div class="fct-thank-you-page-order-items-addresses-ship-to-email">
926 <?php echo esc_html($order->customer->email); ?>
927 </div>
928 <?php endif; ?>
929 </div>
930 <?php
931 }
932
933 public function renderFooter()
934 {
935 ?>
936 <div class="fct-thank-you-page-footer">
937 <?php do_action('fluent_cart/receipt/thank_you/before_footer_buttons', $this->config); ?>
938 <?php $this->renderViewOrderButton(); ?>
939 <?php $this->renderDownloadReceiptButton(); ?>
940 <?php do_action('fluent_cart/receipt/thank_you/after_footer_buttons', $this->config); ?>
941 </div>
942 <?php
943 }
944
945 public function renderViewOrderButton()
946 {
947 $order = Arr::get($this->config, 'order', null);
948 $profilePage = $this->settings->getCustomerProfilePage();
949
950 ?>
951 <a
952 class="fct-thank-you-page-view-order-button"
953 href="<?php echo esc_url($profilePage . 'order/' . $order->uuid); ?>">
954 <?php echo esc_html__('View Order', 'fluent-cart'); ?>
955 </a>
956 <?php
957 }
958
959 public function renderDownloadReceiptButton()
960 {
961 $order = Arr::get($this->config, 'order', null);
962 ?>
963 <a
964 class="fct-thank-you-page-download-receipt-button"
965 href="<?php echo esc_url(\FluentCart\App\Services\URL::appendQueryParams(
966 home_url(),
967 [
968 'fluent-cart' => 'receipt',
969 'order_hash' => $order->uuid,
970 'download' => 1
971 ]
972 )) ?>">
973 <?php echo esc_html__('Download Receipt', 'fluent-cart'); ?>
974 </a>
975 <?php
976 }
977
978 /**
979 * Build a parent → bundle items relationship from flat order items
980 *
981 * Converts a flat order items list into:
982 * - Parent items
983 * - Each parent contains a ` bundle_items ` array
984 *
985 * @param array $orderItems
986 * @return array
987 */
988 protected function buildBundleItemsTree($orderItems)
989 {
990 if (!$orderItems) {
991 return [];
992 }
993
994 $parents = [];
995 $childrenByParent = [];
996
997 // Separate parents and children
998 foreach ($orderItems as $item) {
999 $parentId = Arr::get($item, 'line_meta.bundle_parent_item_id', null);
1000
1001 // If bundle child → group by parent ID
1002 if ($parentId) {
1003 $childrenByParent[$parentId][] = $item;
1004
1005 // Otherwise it's a parent item
1006 } else {
1007 $item['bundle_items'] = [];
1008 $parents[$item['id']] = $item;
1009 }
1010 }
1011
1012 // Attach children to their parent
1013 foreach ($childrenByParent as $parentId => $children) {
1014 if (isset($parents[$parentId])) {
1015 $parents[$parentId]['bundle_items'] = $children;
1016 }
1017 }
1018
1019 // Re-index a final array
1020 return array_values($parents);
1021 }
1022
1023 public function renderBundleProducts($item)
1024 {
1025 //dd($item);
1026 if (!$item['bundle_items']) {
1027 return;
1028 }
1029
1030 $total = count($item['bundle_items']);
1031 ?>
1032 <div class="fct-bundle-products" data-fluent-cart-collapsibles>
1033 <h4 class="fct-bundle-products-title">
1034 <?php echo esc_html__('Bundle of', 'fluent-cart') . ':'; ?>
1035 </h4>
1036
1037 <div class="fct-bundle-products-list">
1038 <?php foreach (array_slice($item['bundle_items'], 0, 2) as $bundleItem): ?>
1039 <p>
1040 <?php echo esc_html(Arr::get($bundleItem, 'title', '')); ?>
1041 </p>
1042 <?php endforeach; ?>
1043
1044 <?php if ($total > 2): ?>
1045 <div class="fct-bundle-products-more">
1046 <div class="fct-bundle-products-more-list">
1047 <?php foreach (array_slice($item['bundle_items'], 2) as $bundleItem): ?>
1048 <p>
1049 <?php echo esc_html(Arr::get($bundleItem, 'title', '')); ?>
1050 </p>
1051 <?php endforeach; ?>
1052 </div>
1053 </div>
1054 <?php endif; ?>
1055 </div>
1056
1057 <?php if ($total > 2) : ?>
1058 <a href="#" class="fct-see-more-btn" data-fluent-cart-collapsible-toggle>
1059 <span class="see-more-text">
1060 <?php echo esc_html__('See More', 'fluent-cart'); ?>
1061 <svg xmlns="http://www.w3.org/2000/svg" width="12" height="7" viewBox="0 0 12 7" fill="none">
1062 <path d="M0.75 0.75L5.04289 5.04289C5.37623 5.37623 5.54289 5.54289 5.75 5.54289C5.95711 5.54289 6.12377 5.37623 6.45711 5.04289L10.75 0.75" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
1063 </svg>
1064 </span>
1065
1066 <span class="see-less-text">
1067 <?php echo esc_html__('See Less', 'fluent-cart'); ?>
1068 <svg xmlns="http://www.w3.org/2000/svg" width="12" height="7" viewBox="0 0 14 8" fill="none">
1069 <path d="M0.75 6.54297L6.04289 1.25008C6.37623 0.916742 6.54289 0.750076 6.75 0.750076C6.95711 0.750076 7.12377 0.916742 7.45711 1.25008L12.75 6.54297" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
1070 </svg>
1071 </span>
1072 </a>
1073 <?php endif; ?>
1074 </div>
1075 <?php
1076 }
1077
1078 public function renderTaxSummaryBox()
1079 {
1080 $order = Arr::get($this->config, 'order', null);
1081 $summary = $this->getMemoizedTaxSummary($order);
1082 if (!$summary['shouldRender']) {
1083 return;
1084 }
1085
1086 $tyIsSimplified = (($summary['displayMode'] ?? '') === 'simplified') && !empty($summary['simpleLine']);
1087
1088 if ($tyIsSimplified) :
1089 ?>
1090 <div class="fct-meta-line fct-thank-you-tax-simple-line">
1091 <div class="fct-meta-line-label fct-thank-you-page-order-items-total-label fct-thank-you-tax-simple-label">
1092 <span><?php echo esc_html($summary['simpleLine']['label']); ?></span>
1093 <?php if (!empty($summary['simpleLine']['hasDetails'])) : ?>
1094 <details class="fct-thank-you-tax-details">
1095 <summary class="fct-thank-you-tax-toggle"><?php echo esc_html__('See details', 'fluent-cart'); ?> &#9662;</summary>
1096 <div class="fct-thank-you-tax-summary fct-thank-you-tax-floating">
1097 <?php $this->renderTaxBreakdownCardInner($summary); ?>
1098 </div>
1099 </details>
1100 <?php endif; ?>
1101 </div>
1102 <div class="fct-meta-line-value fct-thank-you-page-order-items-total-value"><?php echo esc_html($summary['simpleLine']['value']); ?></div>
1103 </div>
1104 <?php
1105 else :
1106 ?>
1107 <div class="fct-thank-you-tax-summary">
1108 <?php $this->renderTaxBreakdownCardInner($summary); ?>
1109 </div>
1110 <?php
1111 endif;
1112 }
1113
1114 private function renderTaxBreakdownCardInner($summary)
1115 {
1116 ?>
1117 <div class="fct-thank-you-tax-summary-header">
1118 <span class="fct-thank-you-tax-summary-title">
1119 <?php if (!empty(Arr::get($summary, 'foldedRateLines', []))): ?>
1120 <?php echo esc_html__('Tax breakdown by rate', 'fluent-cart'); ?>
1121 <?php else: ?>
1122 <?php echo esc_html__('TAX SUMMARY', 'fluent-cart'); ?>
1123 <?php endif; ?>
1124 </span>
1125 <span class="fct-item-tax-hint" tabindex="0"
1126 aria-label="<?php echo esc_attr__('Tax breakdown explanation', 'fluent-cart'); ?>">
1127 <span class="fct-item-tax-hint-icon">i</span>
1128 <span class="fct-item-tax-hint-tooltip">
1129 <?php echo esc_html__('Inclusive tax is embedded in item prices. Exclusive tax is added on top.', 'fluent-cart'); ?>
1130 </span>
1131 </span>
1132 </div>
1133
1134 <?php
1135 $tyFoldedRateLines = Arr::get($summary, 'foldedRateLines', []);
1136 $tyIsReverseCharge = !empty($summary['isReverseCharge']);
1137 $rcReversedTotal = (int) Arr::get($summary, 'reversedTaxTotal', 0);
1138 $rcReversedShipping = (int) Arr::get($summary, 'reversedShippingTax', 0);
1139 $rcReversedValue = $rcReversedTotal > 0
1140 ? Helper::toDecimal($rcReversedTotal)
1141 : __('Charge reversed', 'fluent-cart');
1142 ?>
1143 <?php if (!empty($tyFoldedRateLines)): ?>
1144 <?php
1145 $tyIncludedInPrices = (int) Arr::get($summary, 'includedInPrices', 0);
1146 $tyPayableTax = (int) Arr::get($summary, 'payableTax', 0);
1147 $tyTotalOrderTax = (int) Arr::get($summary, 'totalOrderTax', 0);
1148 ?>
1149 <div style="display:grid;grid-template-columns:minmax(0,1fr) 92px 64px;column-gap:12px;align-items:start;">
1150 <span style="min-width:0;font-size:11px;text-transform:uppercase;letter-spacing:0.04em;color:#94a3b8;"><?php echo esc_html__('Rate', 'fluent-cart'); ?></span>
1151 <span style="text-align:right;font-size:11px;text-transform:uppercase;letter-spacing:0.04em;color:#94a3b8;white-space:nowrap;"><?php echo esc_html__('Taxable base', 'fluent-cart'); ?></span>
1152 <span style="text-align:right;font-size:11px;text-transform:uppercase;letter-spacing:0.04em;color:#94a3b8;white-space:nowrap;"><?php echo esc_html__('Tax', 'fluent-cart'); ?></span>
1153 </div>
1154 <?php foreach ($tyFoldedRateLines as $tyFoldedLine): ?>
1155 <div class="fct-thank-you-tax-summary-row<?php echo !empty($tyFoldedLine['inclusive']) ? ' fct-thank-you-tax-summary-row--muted' : ''; ?>" style="display:grid;grid-template-columns:minmax(0,1fr) 92px 64px;column-gap:12px;align-items:start;">
1156 <span style="min-width:0;white-space:normal;overflow-wrap:anywhere;word-break:break-word;"><?php echo esc_html($tyFoldedLine['label']); ?></span>
1157 <span style="text-align:right;color:#94a3b8;white-space:nowrap;"><?php echo esc_html(Helper::toDecimal($tyFoldedLine['base'])); ?></span>
1158 <span style="text-align:right;white-space:nowrap;"><?php echo esc_html(Helper::toDecimal($tyFoldedLine['tax'])); ?></span>
1159 </div>
1160 <?php endforeach; ?>
1161 <?php if ($tyIsReverseCharge): ?>
1162 <div class="fct-thank-you-tax-summary-row fct-thank-you-tax-summary-row--total">
1163 <span><?php echo esc_html__('VAT reversed', 'fluent-cart'); ?></span>
1164 <span><?php echo esc_html($rcReversedValue); ?></span>
1165 </div>
1166 <?php else: ?>
1167 <div class="fct-thank-you-tax-summary-row fct-thank-you-tax-summary-row--total">
1168 <span><?php echo esc_html__('Total tax', 'fluent-cart'); ?></span>
1169 <span><?php echo esc_html(Helper::toDecimal($tyTotalOrderTax)); ?></span>
1170 </div>
1171 <?php if ($tyIncludedInPrices > 0): ?>
1172 <div class="fct-thank-you-tax-summary-row fct-thank-you-tax-summary-row--muted">
1173 <span><?php echo esc_html__('of which included in prices', 'fluent-cart'); ?></span>
1174 <span><?php echo esc_html(Helper::toDecimal($tyIncludedInPrices)); ?></span>
1175 </div>
1176 <?php endif; ?>
1177 <?php if ($tyPayableTax > 0 && $tyIncludedInPrices > 0): ?>
1178 <div class="fct-thank-you-tax-summary-row fct-thank-you-tax-summary-row--total">
1179 <span><?php echo esc_html__('Payable now (added)', 'fluent-cart'); ?></span>
1180 <span><?php echo esc_html(Helper::toDecimal($tyPayableTax)); ?></span>
1181 </div>
1182 <?php endif; ?>
1183 <?php endif; ?>
1184 <?php elseif ($tyIsReverseCharge): ?>
1185 <?php if ($summary['showRcShippingRow'] && $rcReversedShipping > 0): ?>
1186 <div class="fct-thank-you-tax-summary-row fct-thank-you-tax-summary-row--muted">
1187 <span><?php echo esc_html__('Added on shipping', 'fluent-cart'); ?></span>
1188 <span style="text-decoration:line-through;opacity:0.6;"><?php echo esc_html(Helper::toDecimal($rcReversedShipping)); ?></span>
1189 </div>
1190 <?php endif; ?>
1191 <div class="fct-thank-you-tax-summary-row fct-thank-you-tax-summary-row--total">
1192 <span><?php echo esc_html__('Tax reversed', 'fluent-cart'); ?></span>
1193 <span><?php echo esc_html($rcReversedValue); ?></span>
1194 </div>
1195 <?php else: ?>
1196 <?php
1197 $tyFeeRows = Arr::get($summary, 'feeTaxLineRows', []);
1198 $taxRateLines = Arr::get($summary, 'taxRateLines', []);
1199 $shippingTaxLines = Arr::get($summary, 'shippingTaxLines', []);
1200 ?>
1201 <?php
1202 $productTaxRowCount = !empty($taxRateLines)
1203 ? count($taxRateLines)
1204 : (int) ($summary['inclusiveTax'] > 0) + (int) ($summary['exclusiveTax'] > 0);
1205 $rowCount = $productTaxRowCount + count($tyFeeRows) + (int) ($summary['shippingTax'] > 0);
1206 $shouldShowBreakdown = !empty($taxRateLines)
1207 || !empty($shippingTaxLines)
1208 || $rowCount >= 2
1209 || ($rowCount === 1 && !($summary['payableTax'] > 0 || $summary['inclusiveTax'] > 0 || (int) Arr::get($summary, 'inclusiveFeeTax', 0) > 0));
1210 ?>
1211 <?php if (!empty($taxRateLines) && $shouldShowBreakdown): ?>
1212 <?php foreach ($taxRateLines as $taxLine) : ?>
1213 <div class="fct-thank-you-tax-summary-row<?php echo !empty($taxLine['inclusive']) ? ' fct-thank-you-tax-summary-row--muted' : ''; ?>">
1214 <span><?php echo esc_html($taxLine['label']); ?></span>
1215 <span><?php echo esc_html(Helper::toDecimal($taxLine['order_tax'])); ?></span>
1216 </div>
1217 <?php endforeach; ?>
1218 <?php endif; ?>
1219 <?php if (empty($taxRateLines) && $summary['inclusiveTax'] > 0 && $shouldShowBreakdown): ?>
1220 <div class="fct-thank-you-tax-summary-row fct-thank-you-tax-summary-row--muted">
1221 <span><?php echo esc_html__('Included in item prices', 'fluent-cart'); ?></span>
1222 <span><?php echo esc_html(Helper::toDecimal($summary['inclusiveTax'])); ?></span>
1223 </div>
1224 <?php endif; ?>
1225 <?php if (empty($taxRateLines) && $summary['exclusiveTax'] > 0 && $shouldShowBreakdown): ?>
1226 <div class="fct-thank-you-tax-summary-row">
1227 <span><?php echo esc_html__('Added on products', 'fluent-cart'); ?></span>
1228 <span><?php echo esc_html(Helper::toDecimal($summary['exclusiveTax'])); ?></span>
1229 </div>
1230 <?php endif; ?>
1231 <?php if ($shouldShowBreakdown) : ?>
1232 <?php foreach ($tyFeeRows as $feeRow) : ?>
1233 <div class="fct-thank-you-tax-summary-row<?php echo $feeRow['inclusive'] ? ' fct-thank-you-tax-summary-row--muted' : ''; ?>">
1234 <span><?php echo esc_html($feeRow['display_label']); ?></span>
1235 <span><?php echo esc_html(Helper::toDecimal($feeRow['tax_amount'])); ?></span>
1236 </div>
1237 <?php endforeach; ?>
1238 <?php endif; ?>
1239 <?php if ($summary['shippingTax'] > 0 && $shouldShowBreakdown):
1240 $isShippingInclusive = (bool) Arr::get($summary, 'isShippingInclusive', false);
1241 $shippingRowClass = 'fct-thank-you-tax-summary-row' . ($isShippingInclusive ? ' fct-thank-you-tax-summary-row--muted' : '');
1242 if (!empty($shippingTaxLines)):
1243 foreach ($shippingTaxLines as $shLine): ?>
1244 <div class="<?php echo esc_attr($shippingRowClass); ?>">
1245 <span><?php echo esc_html($shLine['label']); ?></span>
1246 <span><?php echo esc_html(Helper::toDecimal($shLine['shipping_tax'])); ?></span>
1247 </div>
1248 <?php endforeach;
1249 else: ?>
1250 <div class="<?php echo esc_attr($shippingRowClass); ?>">
1251 <span>
1252 <?php if ($isShippingInclusive): ?>
1253 <?php echo esc_html__('Included in shipping prices', 'fluent-cart'); ?>
1254 <?php else: ?>
1255 <?php echo esc_html__('Added on shipping', 'fluent-cart'); ?>
1256 <?php endif; ?>
1257 </span>
1258 <span><?php echo esc_html(Helper::toDecimal($summary['shippingTax'])); ?></span>
1259 </div>
1260 <?php endif; ?>
1261 <?php endif; ?>
1262 <?php if ($summary['payableTax'] > 0): ?>
1263 <div class="fct-thank-you-tax-summary-row fct-thank-you-tax-summary-row--total">
1264 <span><?php echo esc_html__('Total payable tax', 'fluent-cart'); ?></span>
1265 <span><?php echo esc_html(Helper::toDecimal($summary['payableTax'])); ?></span>
1266 </div>
1267 <?php endif; ?>
1268 <?php if ($summary['inclusiveTax'] > 0 || $summary['inclusiveFeeTax'] > 0): ?>
1269 <div class="fct-thank-you-tax-summary-row fct-thank-you-tax-summary-row--muted">
1270 <span><?php echo esc_html__('Total tax in this order', 'fluent-cart'); ?></span>
1271 <span><?php echo esc_html(Helper::toDecimal($summary['totalOrderTax'])); ?></span>
1272 </div>
1273 <?php endif; ?>
1274 <?php endif; ?>
1275 <?php
1276 }
1277
1278 public function renderItemTaxPill($item, $order)
1279 {
1280 $rates = TaxSummaryHelper::getItemTaxRates($item);
1281 $isReversed = $order->isReverseChargeTaxOrder();
1282 $rcMode = $order->getOrderRcMode();
1283
1284 if (!empty($rates)) {
1285 $this->renderTaxRatePills($rates, $isReversed, $rcMode);
1286 return;
1287 }
1288
1289 // Fallback: existing aggregate pill for old orders without tax_config
1290 $taxAmount = (int) ($item['tax_amount'] ?? 0);
1291 if ($taxAmount <= 0) {
1292 return;
1293 }
1294 $isInclusive = TaxSummaryHelper::isPrimaryTaxInclusive($order);
1295 $pillClass = $isInclusive ? 'fct-tax-pill--inclusive' : 'fct-tax-pill--exclusive';
1296 $reversedClass = ($isReversed && (!$isInclusive || $rcMode === 'dynamic')) ? ' is-reversed' : '';
1297 ?>
1298 <div class="fct-item-tax-pills">
1299 <div class="fct-item-tax-pill-row">
1300 <span class="fct-tax-pill <?php echo esc_attr($pillClass); ?>">
1301 <?php echo $isInclusive ? esc_html__('Incl.', 'fluent-cart') : esc_html__('Add.', 'fluent-cart'); ?>
1302 </span>
1303 <span class="fct-item-tax-pill-amount <?php echo esc_attr(($isInclusive ? 'is-inclusive' : 'is-exclusive') . $reversedClass); ?>">
1304 <?php if ($isInclusive): ?>
1305 <?php echo esc_html__('incl.', 'fluent-cart'); ?> <?php echo esc_html(Helper::toDecimal($taxAmount)); ?>
1306 <?php else: ?>
1307 + <?php echo esc_html(Helper::toDecimal($taxAmount)); ?>
1308 <?php endif; ?>
1309 </span>
1310 </div>
1311 </div>
1312 <?php
1313 }
1314
1315 public function renderItemSetupFeeTaxPills($item, $order)
1316 {
1317 $isSubscription = $item['payment_type'] === 'subscription'
1318 || !empty(Arr::get($item, 'other_info.signup_fee'));
1319
1320 if (!$isSubscription) {
1321 return;
1322 }
1323
1324 $isReversed = $order->isReverseChargeTaxOrder();
1325 $rcMode = $order->getOrderRcMode();
1326 $signupFeeItem = null;
1327 if ($order->order_items) {
1328 $signupFeeItem = $order->order_items
1329 ->where('payment_type', 'signup_fee')
1330 ->where('object_id', $item['object_id'])
1331 ->first();
1332 }
1333
1334 if ($signupFeeItem) {
1335 $rates = TaxSummaryHelper::getItemTaxRates($signupFeeItem->toArray());
1336 if (!empty($rates)) {
1337 $this->renderTaxRatePills($rates, $isReversed, $rcMode);
1338 return;
1339 }
1340 }
1341
1342 $signupFeeTax = (int) Arr::get($item, 'other_info.signup_fee_tax', 0);
1343 if ($signupFeeTax <= 0) {
1344 return;
1345 }
1346 $sfIsInclusive = TaxSummaryHelper::isPrimaryTaxInclusive($order);
1347 $reversedClass = ($isReversed && (!$sfIsInclusive || $rcMode === 'dynamic')) ? ' is-reversed' : '';
1348 ?>
1349 <div class="fct-item-tax-pills">
1350 <div class="fct-item-tax-pill-row">
1351 <span class="fct-item-tax-pill-amount<?php echo esc_attr($reversedClass); ?>"><?php
1352 /* translators: %1$s: formatted setup fee tax amount */
1353 echo sprintf(esc_html__('Setup fee tax: %1$s', 'fluent-cart'), esc_html(Helper::toDecimal($signupFeeTax)));
1354 ?></span>
1355 </div>
1356 </div>
1357 <?php
1358 }
1359
1360 private function renderTaxRatePills(array $rates, bool $isReversed = false, string $rcMode = 'fixed')
1361 {
1362 ?>
1363 <div class="fct-item-tax-pills">
1364 <?php foreach ($rates as $rate) : ?>
1365 <?php
1366 $pillClass = $rate['inclusive'] ? 'fct-tax-pill--inclusive' : 'fct-tax-pill--exclusive';
1367 $percent = rtrim(rtrim(number_format($rate['rate_percent'], 3, '.', ''), '0'), '.');
1368 $rateIsInclusive = !empty($rate['inclusive']);
1369 $rateReversedClass = ($isReversed && (!$rateIsInclusive || $rcMode === 'dynamic')) ? ' is-reversed' : '';
1370 ?>
1371 <div class="fct-item-tax-pill-row">
1372 <span class="fct-tax-pill <?php echo esc_attr($pillClass); ?>">
1373 <?php echo esc_html($rate['label']) . ' (' . esc_html($percent) . '%)'; ?>
1374 </span>
1375 <span class="fct-item-tax-pill-amount <?php echo esc_attr(($rate['inclusive'] ? 'is-inclusive' : 'is-exclusive') . $rateReversedClass); ?>">
1376 <?php if ($rate['inclusive']): ?>
1377 <?php echo esc_html__('incl.', 'fluent-cart'); ?> <?php echo esc_html(Helper::toDecimal($rate['tax_amount'])); ?>
1378 <?php else: ?>
1379 + <?php echo esc_html(Helper::toDecimal($rate['tax_amount'])); ?>
1380 <?php endif; ?>
1381 </span>
1382 </div>
1383 <?php endforeach; ?>
1384 </div>
1385 <?php
1386 }
1387
1388 }
1389