PluginProbe
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler / 1.5.0
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler v1.5.0
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.0, at app/Services/Renderer/Receipt/ThankYouRender.php

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