PluginProbe
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler / 1.5.3
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler v1.5.3
1.6.6 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 All 49 releases
fluent-cart / app / Services / Renderer / Receipt / ThankYouRender.php

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

1,385 lines 61.2 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 ?>
494 <div class="fct-meta-line fct-thank-you-page-order-items-total-shipping">
495 <div class="fct-meta-line-label fct-thank-you-page-order-items-total-label">
496 <?php echo esc_html__('Shipping', 'fluent-cart'); ?>
497 </div>
498 <div class="fct-meta-line-value fct-thank-you-page-order-items-total-value"><?php echo esc_html(Helper::toDecimal($displayShipping)); ?></div>
499 </div>
500 <?php
501 }
502
503 public function renderFees()
504 {
505 $order = Arr::get($this->config, 'order', null);
506 if (!$order || $order->fee_total <= 0) {
507 return;
508 }
509 $feeItems = $order->feeItems()->get();
510 foreach ($feeItems as $feeItem): ?>
511 <div class="fct-meta-line fct-thank-you-page-order-items-total-fee">
512 <div class="fct-meta-line-label fct-thank-you-page-order-items-total-label">
513 <?php echo esc_html($feeItem->title); ?>
514 </div>
515 <div class="fct-meta-line-value fct-thank-you-page-order-items-total-value">
516 <?php echo esc_html(Helper::toDecimal($feeItem->subtotal)); ?>
517 </div>
518 </div>
519 <?php endforeach;
520 }
521
522 public function renderRefund()
523 {
524 $order = Arr::get($this->config, 'order', null);
525
526 if ($order->total_refund > 0): ?>
527 <div class="fct-meta-line fct-thank-you-page-order-items-total-refund">
528 <div class="fct-meta-line-label fct-thank-you-page-order-items-total-label">
529 <?php echo esc_html__('Refund', 'fluent-cart'); ?>
530 </div>
531 <div class="fct-meta-line-value fct-thank-you-page-order-items-total-value">
532 - <?php echo esc_html(Helper::toDecimal($order->total_refund)); ?>
533 </div>
534 </div>
535 <?php endif;
536 }
537
538 public function renderTotal()
539 {
540 $order = Arr::get($this->config, 'order', null);
541 $displayTotal = (int) $order->total_amount - (int) $order->total_refund;
542 if ($order->isReverseChargeTaxOrder()) {
543 $rcAdj = (int) Arr::get($this->getMemoizedTaxSummary($order), 'rcTotalAdjustment', 0);
544 if ($rcAdj > 0) {
545 $displayTotal = max(0, $displayTotal - $rcAdj);
546 }
547 }
548 ?>
549 <div class="fct-meta-line fct-thank-you-page-order-items-total-total">
550 <div class="fct-meta-line-label fct-thank-you-page-order-items-total-label">
551 <?php echo esc_html__('Total', 'fluent-cart'); ?>
552 </div>
553 <div class="fct-meta-line-value fct-thank-you-page-order-items-total-value">
554 <?php echo esc_html(Helper::toDecimal($displayTotal)); ?>
555 </div>
556 </div>
557 <?php
558 }
559
560 public function renderPaymentMethod()
561 {
562 $order = Arr::get($this->config, 'order', null);
563 $transaction = $order->getLatestTransaction();
564 ?>
565 <div class="fct-meta-line fct-thank-you-page-order-items-total-payment-method">
566 <div class="fct-meta-line-label fct-thank-you-page-order-items-total-label">
567 <?php echo esc_html__('Payment Method', 'fluent-cart'); ?>
568 </div>
569 <div class="fct-meta-line-value fct-thank-you-page-order-items-total-value">
570 <?php if ($transaction->card_last_4) :
571 echo esc_html($transaction->card_brand) . ' ' . esc_html($transaction->card_last_4);
572 else:
573 $title = $transaction->payment_method;
574 $gateway = GatewayManager::getInstance($transaction->payment_method);
575 $title = $gateway ? $gateway->getMeta('title') : $title;
576 echo esc_html($title);
577 endif; ?>
578 </div>
579 </div>
580 <?php
581 }
582
583 public function renderSubscriptionItems()
584 {
585 $order = Arr::get($this->config, 'order', null);
586 $subscriptions = $order->subscriptions;
587
588 if ($subscriptions->count() == 0) {
589 return;
590 }
591 ?>
592 <div class="fct-thank-you-page-order-items-subscriptions">
593 <p class="fct-thank-you-page-order-items-subscriptions-heading">
594 <?php echo esc_html__('Subscription Details', 'fluent-cart'); ?>
595 </p>
596
597 <table class="fct-thank-you-page-order-items-subscriptions-table" role="presentation">
598 <tbody>
599 <?php foreach ($subscriptions as $subs): ?>
600 <tr>
601 <td class="fct-thank-you-page-order-items-subscriptions-table-file">
602 <p>
603 <?php echo esc_html($subs->display_item_name); ?>
604 </p>
605 </td>
606
607 <td class="fct-thank-you-page-order-items-subscriptions-billing-infos">
608 <div>
609 <?php if (!empty($subs->payment_info)) : ?>
610 <span>
611 <?php echo $subs->payment_info; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
612 </span>
613 <?php endif; ?>
614
615 <?php if (!empty($subs->next_billing_date)) : ?>
616 <p class="fct-thank-you-page-order-items-subscriptions-billing-infos-next-billing"><?php
617 echo sprintf(
618 /* translators: 1: Next billing date */
619 esc_html__('- Auto renews on %1$s', 'fluent-cart'),
620 esc_html(
621 \FluentCart\App\Services\DateTime\DateTime::gmtToTimezone($subs->next_billing_date)->format('M d, Y h:i A')
622 )
623 );
624 ?>
625 </p>
626 <?php endif; ?>
627 </div>
628 </td>
629 </tr>
630 <?php endforeach; ?>
631 </tbody>
632 </table>
633 </div>
634
635
636 <?php
637 // App::make('view')->render('invoice.parts.subscription_items', [
638 // 'subscriptions' => $order->subscriptions,
639 // 'order' => $order
640 // ]);
641 }
642
643 public function renderDownloads()
644 {
645 $order = Arr::get($this->config, 'order', null);
646 $downloads = $order->getDownloads();
647 if (!$downloads) {
648 return;
649 }
650 ?>
651 <div class="fct-thank-you-page-order-items-downloads">
652 <p class="fct-thank-you-page-order-items-downloads-heading">
653 <?php echo esc_html__('Downloads', 'fluent-cart'); ?>
654 </p>
655
656 <table class="fct-thank-you-page-order-items-downloads-table"
657 role="presentation">
658 <tbody>
659 <tr>
660 <td>
661 <table role="presentation" width="100%">
662 <tbody>
663 <?php foreach ($downloads as $downloadItem): ?>
664 <tr>
665 <td>
666 <?php if ($downloadItem['downloads']): ?>
667
668 <table role="presentation" width="100%">
669 <tbody>
670 <?php foreach ($downloadItem['downloads'] as $download): ?>
671 <tr>
672 <td class="fct-thank-you-page-order-items-downloads-table-file">
673 <p>
674 <?php echo esc_html($download['title']); ?>
675 <?php if ($download['file_size']): ?>
676 <span>(<?php echo esc_html(Helper::readableFileSize($download['file_size'])); ?>)</span>
677 <?php endif; ?>
678 </p>
679 </td>
680 <td class="fct-thank-you-page-order-items-downloads-button">
681 <a href="<?php echo esc_url($download['download_url'] ?? ''); ?>">
682 <?php echo esc_html__('Download', 'fluent-cart'); ?>
683 </a>
684 </td>
685 </tr>
686 <?php endforeach; ?>
687 </tbody>
688 </table>
689
690 <?php endif; ?>
691
692 </td>
693 </tr>
694 <?php endforeach; ?>
695 </tbody>
696 </table>
697 </td>
698 </tr>
699 </tbody>
700 </table>
701 </div>
702
703 <?php $this->renderDownloadsNotice(); ?>
704
705 <?php
706 }
707
708 public function renderDownloadsNotice($show_notice = false)
709 {
710 $showNotice = $show_notice ?? true;
711 ?>
712 <?php if (!$showNotice) {
713 return;
714 } ?>
715 <table
716 class="fct-thank-you-page-order-items-downloads-notice"
717 role="presentation">
718 <tbody>
719 <tr>
720 <td>
721 <p class="fct-thank-you-page-order-items-downloads-notice-title">
722 <?php echo esc_html__('Important', 'fluent-cart'); ?>
723 </p>
724 <p class="fct-thank-you-page-order-items-downloads-notice-content">
725 <?php echo esc_html__('This download link is valid for 7 days. After that, you can download the files again from your account
726 on our website.', 'fluent-cart'); ?>
727 </p>
728 </td>
729 </tr>
730 </tbody>
731 </table>
732 <?php
733 }
734
735 public function renderLicenseNotice($show_notice = false)
736 {
737 $showNotice = $show_notice ?? true;
738 ?>
739 <?php if (!$showNotice) {
740 return;
741 } ?>
742 <table
743 class="fct-thank-you-page-order-items-downloads-notice"
744 role="presentation">
745 <tbody>
746 <tr>
747 <td>
748 <p class="fct-thank-you-page-order-items-downloads-notice-title">
749 <?php echo esc_html__('Important', 'fluent-cart'); ?>
750 </p>
751 <p class="fct-thank-you-page-order-items-downloads-notice-content">
752 <?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'); ?>
753 </p>
754 </td>
755 </tr>
756 </tbody>
757 </table>
758 <?php
759 }
760
761 public function renderLicenses()
762 {
763 $order = Arr::get($this->config, 'order', null);
764 $licenses = $order->getLicenses();
765 if (!$licenses || $licenses->count() == 0) {
766 return;
767 }
768 ?>
769 <div class="fct-thank-you-page-order-items-licenses">
770 <p class="fct-thank-you-page-order-items-licenses-heading">
771 <?php echo esc_html__('Licenses', 'fluent-cart'); ?>
772 </p>
773 <table class="fct-thank-you-page-order-items-licenses-table" role="presentation">
774 <tbody>
775 <tr>
776 <td>
777 <table role="presentation">
778 <tbody>
779
780 <?php foreach ($licenses as $license): ?>
781 <tr>
782 <td class="fct-thank-you-page-order-items-licenses-table-file">
783 <p>
784 <?php echo esc_html($license->productVariant->variation_title); ?>:
785 <?php echo esc_html($license->license_key); ?>
786 </p>
787 </td>
788 </tr>
789 <?php endforeach; ?>
790 </tbody>
791 </table>
792 </td>
793 </tr>
794 </tbody>
795 </table>
796 </div>
797
798 <?php $this->renderLicenseNotice(); ?>
799 <?php
800 }
801
802 public function renderAddress()
803 {
804 $order = Arr::get($this->config, 'order', null);
805 ?>
806 <div class="fct-thank-you-page-order-items-addresses">
807 <?php $this->renderBillToAddress(); ?>
808 <?php if ($order->fulfillment_type === 'physical') : ?>
809 <?php $this->renderShipToAddress(); ?>
810 <?php endif; ?>
811 </div>
812 <?php
813 }
814
815 public function renderBillToAddress()
816 {
817 $order = Arr::get($this->config, 'order', null);
818 ?>
819 <div class="fct-thank-you-page-order-items-addresses-bill-to">
820 <h5>
821 <?php echo esc_html__('Bill To', 'fluent-cart'); ?>
822 </h5>
823 <?php
824 if (!empty($order->billing_address)) :
825 ?>
826 <div class="fct-thank-you-page-order-items-addresses-bill-to-address">
827 <?php echo esc_html($order->billing_address->getAddressAsText()); ?>
828 </div>
829
830 <div class="fct-thank-you-page-order-items-addresses-bill-to-email">
831 <?php echo esc_html($order->customer->email); ?>
832 </div>
833 <?php else: ?>
834 <div class="fct-thank-you-page-order-items-addresses-bill-to-name">
835 <?php echo esc_html($order->customer->full_name); ?>
836 </div>
837 <div class="fct-thank-you-page-order-items-addresses-bill-to-email">
838 <?php echo esc_html($order->customer->email); ?>
839 </div>
840 <?php endif; ?>
841 <?php
842 $phoneNumber = Arr::get($order->billing_address->meta ?? [], 'other_data.phone', '');
843 if ($phoneNumber !== ''):
844 ?>
845 <div class="fct-thank-you-page-order-items-addresses-bill-to-phone">
846 <?php echo esc_html($phoneNumber); ?>
847 </div>
848 <?php endif; ?>
849 <?php
850 $companyName = $order->billing_address
851 ? Arr::get($order->billing_address->meta ?? [], 'other_data.company_name', '')
852 : '';
853 if ($companyName === '') {
854 $companyName = $order->getCustomerTaxName();
855 }
856 if ($companyName !== ''):
857 ?>
858 <div class="fct-thank-you-page-order-items-addresses-bill-to-company-name">
859 <?php echo esc_html($companyName); ?>
860 </div>
861 <?php endif; ?>
862 <?php
863 $legalRegId = $order->billing_address
864 ? Arr::get($order->billing_address->meta ?? [], 'other_data.legal_registration_id', '')
865 : '';
866 if ($legalRegId === '') {
867 $legalRegId = Arr::get($order->getBusinessInfo(), 'legal_registration_id', '');
868 }
869 if ($legalRegId !== ''):
870 ?>
871 <div class="fct-thank-you-page-order-items-addresses-bill-to-legal-reg">
872 <?php echo esc_html__('Reg. ID', 'fluent-cart') . ': ' . esc_html($legalRegId); ?>
873 </div>
874 <?php endif; ?>
875 <div class="fct-thank-you-page-order-items-addresses-bill-to-vat-number">
876 <?php
877 $vatNumber = $order->getCustomerTaxNumber();
878 if ($vatNumber !== '') {
879 $vatLabel = __('VAT/Tax ID', 'fluent-cart');
880 echo esc_html($vatLabel) . ': ' . esc_html($vatNumber);
881 }
882 ?>
883 </div>
884 <?php
885 $reverseChargeDeclaration = Arr::get($order->getBusinessInfo(), 'reverse_charge_declaration', '');
886 if ($reverseChargeDeclaration !== ''):
887 ?>
888 <div class="fct-thank-you-page-order-items-addresses-bill-to-reverse-charge">
889 <strong><?php echo esc_html__('Reverse Charge Declaration', 'fluent-cart'); ?>:</strong>
890 <?php echo esc_html($reverseChargeDeclaration); ?>
891 </div>
892 <?php endif; ?>
893 </div>
894 <?php
895 }
896
897 public function renderShipToAddress()
898 {
899 $order = Arr::get($this->config, 'order', null);
900 ?>
901 <div class="fct-thank-you-page-order-items-addresses-ship-to">
902 <h5 class="fct-thank-you-page-order-items-addresses-ship-to-title">
903 <?php echo esc_html__('Ship To', 'fluent-cart'); ?>
904 </h5>
905 <?php if (!empty($order->shipping_address)) : ?>
906 <div class="fct-thank-you-page-order-items-addresses-ship-to-address">
907 <?php echo esc_html($order->shipping_address->getAddressAsText()); ?>
908 </div>
909 <!-- show phone number -->
910 <?php
911 $phone = Arr::get($order->shipping_address->meta ?? [], 'other_data.phone', '');
912 if ($phone !== ''):?>
913 <div class="fct-thank-you-page-order-items-addresses-ship-to-phone">
914 <?php echo esc_html($phone); ?>
915 </div>
916 <?php endif; ?>
917 <?php else: ?>
918 <div class="fct-thank-you-page-order-items-addresses-ship-to-name">
919 <?php echo esc_html($order->customer->full_name); ?>
920 </div>
921 <div class="fct-thank-you-page-order-items-addresses-ship-to-email">
922 <?php echo esc_html($order->customer->email); ?>
923 </div>
924 <?php endif; ?>
925 </div>
926 <?php
927 }
928
929 public function renderFooter()
930 {
931 ?>
932 <div class="fct-thank-you-page-footer">
933 <?php do_action('fluent_cart/receipt/thank_you/before_footer_buttons', $this->config); ?>
934 <?php $this->renderViewOrderButton(); ?>
935 <?php $this->renderDownloadReceiptButton(); ?>
936 <?php do_action('fluent_cart/receipt/thank_you/after_footer_buttons', $this->config); ?>
937 </div>
938 <?php
939 }
940
941 public function renderViewOrderButton()
942 {
943 $order = Arr::get($this->config, 'order', null);
944 $profilePage = $this->settings->getCustomerProfilePage();
945
946 ?>
947 <a
948 class="fct-thank-you-page-view-order-button"
949 href="<?php echo esc_url($profilePage . 'order/' . $order->uuid); ?>">
950 <?php echo esc_html__('View Order', 'fluent-cart'); ?>
951 </a>
952 <?php
953 }
954
955 public function renderDownloadReceiptButton()
956 {
957 $order = Arr::get($this->config, 'order', null);
958 ?>
959 <a
960 class="fct-thank-you-page-download-receipt-button"
961 href="<?php echo esc_url(\FluentCart\App\Services\URL::appendQueryParams(
962 home_url(),
963 [
964 'fluent-cart' => 'receipt',
965 'order_hash' => $order->uuid,
966 'download' => 1
967 ]
968 )) ?>">
969 <?php echo esc_html__('Download Receipt', 'fluent-cart'); ?>
970 </a>
971 <?php
972 }
973
974 /**
975 * Build a parent → bundle items relationship from flat order items
976 *
977 * Converts a flat order items list into:
978 * - Parent items
979 * - Each parent contains a ` bundle_items ` array
980 *
981 * @param array $orderItems
982 * @return array
983 */
984 protected function buildBundleItemsTree($orderItems)
985 {
986 if (!$orderItems) {
987 return [];
988 }
989
990 $parents = [];
991 $childrenByParent = [];
992
993 // Separate parents and children
994 foreach ($orderItems as $item) {
995 $parentId = Arr::get($item, 'line_meta.bundle_parent_item_id', null);
996
997 // If bundle child → group by parent ID
998 if ($parentId) {
999 $childrenByParent[$parentId][] = $item;
1000
1001 // Otherwise it's a parent item
1002 } else {
1003 $item['bundle_items'] = [];
1004 $parents[$item['id']] = $item;
1005 }
1006 }
1007
1008 // Attach children to their parent
1009 foreach ($childrenByParent as $parentId => $children) {
1010 if (isset($parents[$parentId])) {
1011 $parents[$parentId]['bundle_items'] = $children;
1012 }
1013 }
1014
1015 // Re-index a final array
1016 return array_values($parents);
1017 }
1018
1019 public function renderBundleProducts($item)
1020 {
1021 //dd($item);
1022 if (!$item['bundle_items']) {
1023 return;
1024 }
1025
1026 $total = count($item['bundle_items']);
1027 ?>
1028 <div class="fct-bundle-products" data-fluent-cart-collapsibles>
1029 <h4 class="fct-bundle-products-title">
1030 <?php echo esc_html__('Bundle of', 'fluent-cart') . ':'; ?>
1031 </h4>
1032
1033 <div class="fct-bundle-products-list">
1034 <?php foreach (array_slice($item['bundle_items'], 0, 2) as $bundleItem): ?>
1035 <p>
1036 <?php echo esc_html(Arr::get($bundleItem, 'title', '')); ?>
1037 </p>
1038 <?php endforeach; ?>
1039
1040 <?php if ($total > 2): ?>
1041 <div class="fct-bundle-products-more">
1042 <div class="fct-bundle-products-more-list">
1043 <?php foreach (array_slice($item['bundle_items'], 2) as $bundleItem): ?>
1044 <p>
1045 <?php echo esc_html(Arr::get($bundleItem, 'title', '')); ?>
1046 </p>
1047 <?php endforeach; ?>
1048 </div>
1049 </div>
1050 <?php endif; ?>
1051 </div>
1052
1053 <?php if ($total > 2) : ?>
1054 <a href="#" class="fct-see-more-btn" data-fluent-cart-collapsible-toggle>
1055 <span class="see-more-text">
1056 <?php echo esc_html__('See More', 'fluent-cart'); ?>
1057 <svg xmlns="http://www.w3.org/2000/svg" width="12" height="7" viewBox="0 0 12 7" fill="none">
1058 <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"/>
1059 </svg>
1060 </span>
1061
1062 <span class="see-less-text">
1063 <?php echo esc_html__('See Less', 'fluent-cart'); ?>
1064 <svg xmlns="http://www.w3.org/2000/svg" width="12" height="7" viewBox="0 0 14 8" fill="none">
1065 <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"/>
1066 </svg>
1067 </span>
1068 </a>
1069 <?php endif; ?>
1070 </div>
1071 <?php
1072 }
1073
1074 public function renderTaxSummaryBox()
1075 {
1076 $order = Arr::get($this->config, 'order', null);
1077 $summary = $this->getMemoizedTaxSummary($order);
1078 if (!$summary['shouldRender']) {
1079 return;
1080 }
1081
1082 $tyIsSimplified = (($summary['displayMode'] ?? '') === 'simplified') && !empty($summary['simpleLine']);
1083
1084 if ($tyIsSimplified) :
1085 ?>
1086 <div class="fct-meta-line fct-thank-you-tax-simple-line">
1087 <div class="fct-meta-line-label fct-thank-you-page-order-items-total-label fct-thank-you-tax-simple-label">
1088 <span><?php echo esc_html($summary['simpleLine']['label']); ?></span>
1089 <?php if (!empty($summary['simpleLine']['hasDetails'])) : ?>
1090 <details class="fct-thank-you-tax-details">
1091 <summary class="fct-thank-you-tax-toggle"><?php echo esc_html__('See details', 'fluent-cart'); ?> &#9662;</summary>
1092 <div class="fct-thank-you-tax-summary fct-thank-you-tax-floating">
1093 <?php $this->renderTaxBreakdownCardInner($summary); ?>
1094 </div>
1095 </details>
1096 <?php endif; ?>
1097 </div>
1098 <div class="fct-meta-line-value fct-thank-you-page-order-items-total-value"><?php echo esc_html($summary['simpleLine']['value']); ?></div>
1099 </div>
1100 <?php
1101 else :
1102 ?>
1103 <div class="fct-thank-you-tax-summary">
1104 <?php $this->renderTaxBreakdownCardInner($summary); ?>
1105 </div>
1106 <?php
1107 endif;
1108 }
1109
1110 private function renderTaxBreakdownCardInner($summary)
1111 {
1112 ?>
1113 <div class="fct-thank-you-tax-summary-header">
1114 <span class="fct-thank-you-tax-summary-title">
1115 <?php if (!empty(Arr::get($summary, 'foldedRateLines', []))): ?>
1116 <?php echo esc_html__('Tax breakdown by rate', 'fluent-cart'); ?>
1117 <?php else: ?>
1118 <?php echo esc_html__('TAX SUMMARY', 'fluent-cart'); ?>
1119 <?php endif; ?>
1120 </span>
1121 <span class="fct-item-tax-hint" tabindex="0"
1122 aria-label="<?php echo esc_attr__('Tax breakdown explanation', 'fluent-cart'); ?>">
1123 <span class="fct-item-tax-hint-icon">i</span>
1124 <span class="fct-item-tax-hint-tooltip">
1125 <?php echo esc_html__('Inclusive tax is embedded in item prices. Exclusive tax is added on top.', 'fluent-cart'); ?>
1126 </span>
1127 </span>
1128 </div>
1129
1130 <?php
1131 $tyFoldedRateLines = Arr::get($summary, 'foldedRateLines', []);
1132 $tyIsReverseCharge = !empty($summary['isReverseCharge']);
1133 $rcReversedTotal = (int) Arr::get($summary, 'reversedTaxTotal', 0);
1134 $rcReversedShipping = (int) Arr::get($summary, 'reversedShippingTax', 0);
1135 $rcReversedValue = $rcReversedTotal > 0
1136 ? Helper::toDecimal($rcReversedTotal)
1137 : __('Charge reversed', 'fluent-cart');
1138 ?>
1139 <?php if (!empty($tyFoldedRateLines)): ?>
1140 <?php
1141 $tyIncludedInPrices = (int) Arr::get($summary, 'includedInPrices', 0);
1142 $tyPayableTax = (int) Arr::get($summary, 'payableTax', 0);
1143 $tyTotalOrderTax = (int) Arr::get($summary, 'totalOrderTax', 0);
1144 ?>
1145 <div style="display:grid;grid-template-columns:minmax(0,1fr) 92px 64px;column-gap:12px;align-items:start;">
1146 <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>
1147 <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>
1148 <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>
1149 </div>
1150 <?php foreach ($tyFoldedRateLines as $tyFoldedLine): ?>
1151 <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;">
1152 <span style="min-width:0;white-space:normal;overflow-wrap:anywhere;word-break:break-word;"><?php echo esc_html($tyFoldedLine['label']); ?></span>
1153 <span style="text-align:right;color:#94a3b8;white-space:nowrap;"><?php echo esc_html(Helper::toDecimal($tyFoldedLine['base'])); ?></span>
1154 <span style="text-align:right;white-space:nowrap;"><?php echo esc_html(Helper::toDecimal($tyFoldedLine['tax'])); ?></span>
1155 </div>
1156 <?php endforeach; ?>
1157 <?php if ($tyIsReverseCharge): ?>
1158 <div class="fct-thank-you-tax-summary-row fct-thank-you-tax-summary-row--total">
1159 <span><?php echo esc_html__('VAT reversed', 'fluent-cart'); ?></span>
1160 <span><?php echo esc_html($rcReversedValue); ?></span>
1161 </div>
1162 <?php else: ?>
1163 <div class="fct-thank-you-tax-summary-row fct-thank-you-tax-summary-row--total">
1164 <span><?php echo esc_html__('Total tax', 'fluent-cart'); ?></span>
1165 <span><?php echo esc_html(Helper::toDecimal($tyTotalOrderTax)); ?></span>
1166 </div>
1167 <?php if ($tyIncludedInPrices > 0): ?>
1168 <div class="fct-thank-you-tax-summary-row fct-thank-you-tax-summary-row--muted">
1169 <span><?php echo esc_html__('of which included in prices', 'fluent-cart'); ?></span>
1170 <span><?php echo esc_html(Helper::toDecimal($tyIncludedInPrices)); ?></span>
1171 </div>
1172 <?php endif; ?>
1173 <?php if ($tyPayableTax > 0 && $tyIncludedInPrices > 0): ?>
1174 <div class="fct-thank-you-tax-summary-row fct-thank-you-tax-summary-row--total">
1175 <span><?php echo esc_html__('Payable now (added)', 'fluent-cart'); ?></span>
1176 <span><?php echo esc_html(Helper::toDecimal($tyPayableTax)); ?></span>
1177 </div>
1178 <?php endif; ?>
1179 <?php endif; ?>
1180 <?php elseif ($tyIsReverseCharge): ?>
1181 <?php if ($summary['showRcShippingRow'] && $rcReversedShipping > 0): ?>
1182 <div class="fct-thank-you-tax-summary-row fct-thank-you-tax-summary-row--muted">
1183 <span><?php echo esc_html__('Added on shipping', 'fluent-cart'); ?></span>
1184 <span style="text-decoration:line-through;opacity:0.6;"><?php echo esc_html(Helper::toDecimal($rcReversedShipping)); ?></span>
1185 </div>
1186 <?php endif; ?>
1187 <div class="fct-thank-you-tax-summary-row fct-thank-you-tax-summary-row--total">
1188 <span><?php echo esc_html__('Tax reversed', 'fluent-cart'); ?></span>
1189 <span><?php echo esc_html($rcReversedValue); ?></span>
1190 </div>
1191 <?php else: ?>
1192 <?php
1193 $tyFeeRows = Arr::get($summary, 'feeTaxLineRows', []);
1194 $taxRateLines = Arr::get($summary, 'taxRateLines', []);
1195 $shippingTaxLines = Arr::get($summary, 'shippingTaxLines', []);
1196 ?>
1197 <?php
1198 $productTaxRowCount = !empty($taxRateLines)
1199 ? count($taxRateLines)
1200 : (int) ($summary['inclusiveTax'] > 0) + (int) ($summary['exclusiveTax'] > 0);
1201 $rowCount = $productTaxRowCount + count($tyFeeRows) + (int) ($summary['shippingTax'] > 0);
1202 $shouldShowBreakdown = !empty($taxRateLines)
1203 || !empty($shippingTaxLines)
1204 || $rowCount >= 2
1205 || ($rowCount === 1 && !($summary['payableTax'] > 0 || $summary['inclusiveTax'] > 0 || (int) Arr::get($summary, 'inclusiveFeeTax', 0) > 0));
1206 ?>
1207 <?php if (!empty($taxRateLines) && $shouldShowBreakdown): ?>
1208 <?php foreach ($taxRateLines as $taxLine) : ?>
1209 <div class="fct-thank-you-tax-summary-row<?php echo !empty($taxLine['inclusive']) ? ' fct-thank-you-tax-summary-row--muted' : ''; ?>">
1210 <span><?php echo esc_html($taxLine['label']); ?></span>
1211 <span><?php echo esc_html(Helper::toDecimal($taxLine['order_tax'])); ?></span>
1212 </div>
1213 <?php endforeach; ?>
1214 <?php endif; ?>
1215 <?php if (empty($taxRateLines) && $summary['inclusiveTax'] > 0 && $shouldShowBreakdown): ?>
1216 <div class="fct-thank-you-tax-summary-row fct-thank-you-tax-summary-row--muted">
1217 <span><?php echo esc_html__('Included in item prices', 'fluent-cart'); ?></span>
1218 <span><?php echo esc_html(Helper::toDecimal($summary['inclusiveTax'])); ?></span>
1219 </div>
1220 <?php endif; ?>
1221 <?php if (empty($taxRateLines) && $summary['exclusiveTax'] > 0 && $shouldShowBreakdown): ?>
1222 <div class="fct-thank-you-tax-summary-row">
1223 <span><?php echo esc_html__('Added on products', 'fluent-cart'); ?></span>
1224 <span><?php echo esc_html(Helper::toDecimal($summary['exclusiveTax'])); ?></span>
1225 </div>
1226 <?php endif; ?>
1227 <?php if ($shouldShowBreakdown) : ?>
1228 <?php foreach ($tyFeeRows as $feeRow) : ?>
1229 <div class="fct-thank-you-tax-summary-row<?php echo $feeRow['inclusive'] ? ' fct-thank-you-tax-summary-row--muted' : ''; ?>">
1230 <span><?php echo esc_html($feeRow['display_label']); ?></span>
1231 <span><?php echo esc_html(Helper::toDecimal($feeRow['tax_amount'])); ?></span>
1232 </div>
1233 <?php endforeach; ?>
1234 <?php endif; ?>
1235 <?php if ($summary['shippingTax'] > 0 && $shouldShowBreakdown):
1236 $isShippingInclusive = (bool) Arr::get($summary, 'isShippingInclusive', false);
1237 $shippingRowClass = 'fct-thank-you-tax-summary-row' . ($isShippingInclusive ? ' fct-thank-you-tax-summary-row--muted' : '');
1238 if (!empty($shippingTaxLines)):
1239 foreach ($shippingTaxLines as $shLine): ?>
1240 <div class="<?php echo esc_attr($shippingRowClass); ?>">
1241 <span><?php echo esc_html($shLine['label']); ?></span>
1242 <span><?php echo esc_html(Helper::toDecimal($shLine['shipping_tax'])); ?></span>
1243 </div>
1244 <?php endforeach;
1245 else: ?>
1246 <div class="<?php echo esc_attr($shippingRowClass); ?>">
1247 <span>
1248 <?php if ($isShippingInclusive): ?>
1249 <?php echo esc_html__('Included in shipping prices', 'fluent-cart'); ?>
1250 <?php else: ?>
1251 <?php echo esc_html__('Added on shipping', 'fluent-cart'); ?>
1252 <?php endif; ?>
1253 </span>
1254 <span><?php echo esc_html(Helper::toDecimal($summary['shippingTax'])); ?></span>
1255 </div>
1256 <?php endif; ?>
1257 <?php endif; ?>
1258 <?php if ($summary['payableTax'] > 0): ?>
1259 <div class="fct-thank-you-tax-summary-row fct-thank-you-tax-summary-row--total">
1260 <span><?php echo esc_html__('Total payable tax', 'fluent-cart'); ?></span>
1261 <span><?php echo esc_html(Helper::toDecimal($summary['payableTax'])); ?></span>
1262 </div>
1263 <?php endif; ?>
1264 <?php if ($summary['inclusiveTax'] > 0 || $summary['inclusiveFeeTax'] > 0): ?>
1265 <div class="fct-thank-you-tax-summary-row fct-thank-you-tax-summary-row--muted">
1266 <span><?php echo esc_html__('Total tax in this order', 'fluent-cart'); ?></span>
1267 <span><?php echo esc_html(Helper::toDecimal($summary['totalOrderTax'])); ?></span>
1268 </div>
1269 <?php endif; ?>
1270 <?php endif; ?>
1271 <?php
1272 }
1273
1274 public function renderItemTaxPill($item, $order)
1275 {
1276 $rates = TaxSummaryHelper::getItemTaxRates($item);
1277 $isReversed = $order->isReverseChargeTaxOrder();
1278 $rcMode = $order->getOrderRcMode();
1279
1280 if (!empty($rates)) {
1281 $this->renderTaxRatePills($rates, $isReversed, $rcMode);
1282 return;
1283 }
1284
1285 // Fallback: existing aggregate pill for old orders without tax_config
1286 $taxAmount = (int) ($item['tax_amount'] ?? 0);
1287 if ($taxAmount <= 0) {
1288 return;
1289 }
1290 $isInclusive = TaxSummaryHelper::isPrimaryTaxInclusive($order);
1291 $pillClass = $isInclusive ? 'fct-tax-pill--inclusive' : 'fct-tax-pill--exclusive';
1292 $reversedClass = ($isReversed && (!$isInclusive || $rcMode === 'dynamic')) ? ' is-reversed' : '';
1293 ?>
1294 <div class="fct-item-tax-pills">
1295 <div class="fct-item-tax-pill-row">
1296 <span class="fct-tax-pill <?php echo esc_attr($pillClass); ?>">
1297 <?php echo $isInclusive ? esc_html__('Incl.', 'fluent-cart') : esc_html__('Add.', 'fluent-cart'); ?>
1298 </span>
1299 <span class="fct-item-tax-pill-amount <?php echo esc_attr(($isInclusive ? 'is-inclusive' : 'is-exclusive') . $reversedClass); ?>">
1300 <?php if ($isInclusive): ?>
1301 <?php echo esc_html__('incl.', 'fluent-cart'); ?> <?php echo esc_html(Helper::toDecimal($taxAmount)); ?>
1302 <?php else: ?>
1303 + <?php echo esc_html(Helper::toDecimal($taxAmount)); ?>
1304 <?php endif; ?>
1305 </span>
1306 </div>
1307 </div>
1308 <?php
1309 }
1310
1311 public function renderItemSetupFeeTaxPills($item, $order)
1312 {
1313 $isSubscription = $item['payment_type'] === 'subscription'
1314 || !empty(Arr::get($item, 'other_info.signup_fee'));
1315
1316 if (!$isSubscription) {
1317 return;
1318 }
1319
1320 $isReversed = $order->isReverseChargeTaxOrder();
1321 $rcMode = $order->getOrderRcMode();
1322 $signupFeeItem = null;
1323 if ($order->order_items) {
1324 $signupFeeItem = $order->order_items
1325 ->where('payment_type', 'signup_fee')
1326 ->where('object_id', $item['object_id'])
1327 ->first();
1328 }
1329
1330 if ($signupFeeItem) {
1331 $rates = TaxSummaryHelper::getItemTaxRates($signupFeeItem->toArray());
1332 if (!empty($rates)) {
1333 $this->renderTaxRatePills($rates, $isReversed, $rcMode);
1334 return;
1335 }
1336 }
1337
1338 $signupFeeTax = (int) Arr::get($item, 'other_info.signup_fee_tax', 0);
1339 if ($signupFeeTax <= 0) {
1340 return;
1341 }
1342 $sfIsInclusive = TaxSummaryHelper::isPrimaryTaxInclusive($order);
1343 $reversedClass = ($isReversed && (!$sfIsInclusive || $rcMode === 'dynamic')) ? ' is-reversed' : '';
1344 ?>
1345 <div class="fct-item-tax-pills">
1346 <div class="fct-item-tax-pill-row">
1347 <span class="fct-item-tax-pill-amount<?php echo esc_attr($reversedClass); ?>"><?php
1348 /* translators: %1$s: formatted setup fee tax amount */
1349 echo sprintf(esc_html__('Setup fee tax: %1$s', 'fluent-cart'), esc_html(Helper::toDecimal($signupFeeTax)));
1350 ?></span>
1351 </div>
1352 </div>
1353 <?php
1354 }
1355
1356 private function renderTaxRatePills(array $rates, bool $isReversed = false, string $rcMode = 'fixed')
1357 {
1358 ?>
1359 <div class="fct-item-tax-pills">
1360 <?php foreach ($rates as $rate) : ?>
1361 <?php
1362 $pillClass = $rate['inclusive'] ? 'fct-tax-pill--inclusive' : 'fct-tax-pill--exclusive';
1363 $percent = rtrim(rtrim(number_format($rate['rate_percent'], 3, '.', ''), '0'), '.');
1364 $rateIsInclusive = !empty($rate['inclusive']);
1365 $rateReversedClass = ($isReversed && (!$rateIsInclusive || $rcMode === 'dynamic')) ? ' is-reversed' : '';
1366 ?>
1367 <div class="fct-item-tax-pill-row">
1368 <span class="fct-tax-pill <?php echo esc_attr($pillClass); ?>">
1369 <?php echo esc_html($rate['label']) . ' (' . esc_html($percent) . '%)'; ?>
1370 </span>
1371 <span class="fct-item-tax-pill-amount <?php echo esc_attr(($rate['inclusive'] ? 'is-inclusive' : 'is-exclusive') . $rateReversedClass); ?>">
1372 <?php if ($rate['inclusive']): ?>
1373 <?php echo esc_html__('incl.', 'fluent-cart'); ?> <?php echo esc_html(Helper::toDecimal($rate['tax_amount'])); ?>
1374 <?php else: ?>
1375 + <?php echo esc_html(Helper::toDecimal($rate['tax_amount'])); ?>
1376 <?php endif; ?>
1377 </span>
1378 </div>
1379 <?php endforeach; ?>
1380 </div>
1381 <?php
1382 }
1383
1384 }
1385