PluginProbe
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler / 1.7.1
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler v1.7.1
1.7.1 1.7.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 All 51 releases
← All changes | app/Services/OrderService.php +61 -5 1.3.25 → 1.7.1 View file →
@@ -6,8 +6,9 @@
6 6 use FluentCart\Api\StoreSettings;
7 7 use FluentCart\App\App;
8 8 use FluentCart\App\Helpers\AddressHelper;
9 9 use FluentCart\App\Helpers\Helper;
10 +use FluentCart\App\Helpers\Status;
10 11 use FluentCart\App\Models\Model;
11 12 use FluentCart\App\Models\Order;
12 13 use FluentCart\App\Models\OrderItem;
13 14 use FluentCart\App\Models\OrderMeta;
@@ -13,8 +14,11 @@
13 14 use FluentCart\App\Models\OrderMeta;
14 15 use FluentCart\App\Models\OrderTransaction;
15 16 use FluentCart\App\Models\ProductVariation;
16 17 use FluentCart\App\Models\Subscription;
18 +use FluentCart\App\Modules\Subscriptions\Services\SystemChargeService;
19 +use FluentCart\App\Services\Payments\PaymentHelper;
20 +use FluentCart\App\Services\Renderer\CheckoutFieldsSchema;
17 21 use FluentCart\Framework\Support\Arr;
18 22
19 23 class OrderService
20 24 {
@@ -25,8 +29,14 @@
25 29 * @return array
26 30 */
27 31 public static function groupSanitizedData($order_data = []): array
28 32 {
33 + // fct_billing_tax_id is the checkout field name for the VAT number; normalise it to
34 + // billing_vat_number so extractAddressData maps it into billing_address.vat_number
35 + if (isset($order_data['fct_billing_tax_id'])) {
36 + $order_data['billing_vat_number'] = $order_data['fct_billing_tax_id'];
37 + unset($order_data['fct_billing_tax_id']);
38 + }
29 39
30 40 $billingAddress = static::extractAddressData($order_data, 'billing_');
31 41 $shippingAddress = static::extractAddressData($order_data, 'shipping_');
32 42 $others = static::extractOtherData($order_data);
@@ -72,13 +82,24 @@
72 82 private static function finalizeAddress($address, $type): array
73 83 {
74 84 $fullName = Arr::get($address, 'full_name', '');
75 85 $name = Arr::get($address, 'name', '');
86 + $explicitFirstName = trim((string) Arr::get($address, 'first_name', ''));
87 + $explicitLastName = trim((string) Arr::get($address, 'last_name', ''));
76 88 $address['full_name'] = $fullName ?? $name;
77 89 $address['first_name'] = AddressHelper::guessFirstNameAndLastName($address['full_name']);
78 90 $address['type'] = $type;
79 91 $name = $fullName ?? $name;
80 - $address = array_merge($address, AddressHelper::guessFirstNameAndLastName($name));
92 +
93 + // In First/Last mode the customer typed both names, so keep them as
94 + // typed. Guessing from the joined name would turn "Alex" + "de Silva"
95 + // into "Alex de" + "Silva". Full-name-only addresses are still guessed.
96 + if (!CheckoutFieldsSchema::isFullNameRequired() && $explicitFirstName !== '') {
97 + $address['first_name'] = $explicitFirstName;
98 + $address['last_name'] = $explicitLastName;
99 + } else {
100 + $address = array_merge($address, AddressHelper::guessFirstNameAndLastName($name));
101 + }
81 102 $address['name'] = Arr::get($address, 'first_name', '') . ' ' . Arr::get($address, 'last_name', '');
82 103 return $address;
83 104 }
84 105
@@ -379,12 +400,12 @@
379 400 if ($paymentType == 'subscription') {
380 401 if ((int)Arr::get($orderItem, 'other_info.trial_days', 0) > 0) {
381 402 return (int)Arr::get($orderItem, 'other_info.signup_fee', 0);
382 403 }
383 - return intval(($orderItem['unit_price'] * $orderItem['quantity'])) + (int)Arr::get($orderItem, 'other_info.signup_fee', 0);
404 + return (int) Arr::get($orderItem, 'subtotal', intval($orderItem['unit_price'] * $orderItem['quantity'])) + (int)Arr::get($orderItem, 'other_info.signup_fee', 0);
384 405 }
385 406
386 - return intval(($orderItem['unit_price'] * $orderItem['quantity']));
407 + return (int) Arr::get($orderItem, 'subtotal', intval($orderItem['unit_price'] * $orderItem['quantity']));
387 408 }
388 409
389 410 /**
390 411 * Get the total amount of items.
@@ -612,12 +633,33 @@
612 633 'reactivate_url' => $subscription->getReactivateUrl(),
613 634 'can_upgrade' => $subscription->canUpgrade(),
614 635 'can_switch_payment_method' => $subscription->canSwitchPaymentMethod(),
615 636 'can_update_payment_method' => $subscription->canUpdatePaymentMethod(),
616 - 'item_name' => $subscription->item_name
637 + 'collection_method' => $subscription->collection_method,
638 + 'is_auto_charged' => $subscription->isSystem(),
639 + 'item_name' => $subscription->display_item_name
617 640 ];
618 641 }
619 642
643 + /**
644 + * A system renewal order still inside its auto-charge retry window has no
645 + * Pay Now — the charge is coming automatically. Other renewals unaffected.
646 + */
647 + protected static function renewalPayNowAllowed(Order $order): bool
648 + {
649 + if (!$order->parent_id) {
650 + return true;
651 + }
652 +
653 + $subscription = Subscription::query()->where('parent_order_id', $order->parent_id)->first();
654 +
655 + if (!$subscription || !$subscription->isSystem()) {
656 + return true;
657 + }
658 +
659 + return SystemChargeService::isExhausted($subscription, $order);
660 + }
661 +
620 662 public static function transformTransaction(OrderTransaction $transaction)
621 663 {
622 664 $data = [
623 665 'uuid' => $transaction->uuid,
@@ -638,13 +680,27 @@
638 680 if ($transaction->order && self::canGenerateReceiptPdf()) {
639 681 $data['receipt_view_url'] = $transaction->order->getReceiptViewUrl();
640 682 }
641 683
684 + if ($transaction->order
685 + && $transaction->order->type === Status::ORDER_TYPE_RENEWAL
686 + && $transaction->status === Status::TRANSACTION_PENDING
687 + && self::renewalPayNowAllowed($transaction->order)
688 + ) {
689 + $data['custom_checkout_url'] = add_query_arg([
690 + 'fluent-cart' => 'custom_checkout',
691 + 'order_hash' => $transaction->order->uuid,
692 + ], home_url('/'));
693 + }
694 +
642 695 return $data;
643 696 }
644 697
645 698 public static function canGenerateReceiptPdf(): bool
646 699 {
647 - return App::isProActive() && defined('FLUENT_PDF');
700 + return (bool) apply_filters(
701 + 'fluent_cart/pdf/can_generate_receipt',
702 + App::isProActive() && defined('FLUENT_PDF')
703 + );
648 704 }
649 705
650 706 }