PluginProbe
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler / 1.6.5
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler v1.6.5
1.6.5 1.6.4 1.6.3 1.6.2 1.6.1 1.6.0 1.5.4 1.5.5 1.5.3 1.5.2 1.5.1 1.5.0 1.4.2 1.4.1 1.4.0 1.3.28 1.3.27 1.3.26 1.3.25 1.3.23 1.3.22 1.3.21 1.3.20 1.3.19 trunk All 48 releases
← All changes | app/Helpers/AdminOrderProcessor.php +63 -2 1.5.1 → 1.6.5 View file →
@@ -115,8 +115,12 @@
115 115 Arr::get($checkoutItem, 'post_id', 0)
116 116 );
117 117 }
118 118
119 + if (!isset($args['variation_type'])) {
120 + $args['variation_type'] = ($variation && $variation->product_detail) ? $variation->product_detail->variation_type : '';
121 + }
122 +
119 123 $item = [
120 124 'payment_type' => $paymentType,
121 125 'post_id' => Arr::get($checkoutItem, 'post_id'),
122 126 'object_id' => Arr::get($checkoutItem, 'object_id'),
@@ -271,13 +275,35 @@
271 275 'note' => Arr::get($this->args, 'note', ''),
272 276 'ip_address' => Arr::get($this->args, 'ip_address', ''),
273 277 'config' => [
274 278 'user_tz' => Arr::get($this->args, 'user_tz', ''),
279 + 'source' => 'admin',
275 280 ],
276 281 ];
277 282
278 283 $totalAmount = $orderData['subtotal'] - $orderData['coupon_discount_total'] - $orderData['manual_discount_total'] + $orderData['shipping_total'] + $orderData['tax_total'];
279 284 $orderData['total_amount'] = $totalAmount > 0 ? $totalAmount : 0;
285 +
286 + /**
287 + * Filter the prepared order data before it is used for order creation.
288 + *
289 + * This mirrors the frontend checkout hook so integrations can adjust
290 + * order payload fields consistently for manual admin orders too.
291 + *
292 + * @param array $orderData Prepared order data array.
293 + * @param array $context {
294 + * Additional context for the filter.
295 + *
296 + * @type array $items Formatted order items with prices and quantities.
297 + * @type array $args Admin order arguments: customer data, payment
298 + * method, shipping, tax, notes, and IP data.
299 + * }
300 + */
301 + $orderData = apply_filters('fluent_cart/checkout/order_data', $orderData, [
302 + 'items' => $this->formattedIOrderItems,
303 + 'args' => $this->args,
304 + ]);
305 +
280 306 $this->orderData = $orderData;
281 307 }
282 308
283 309
@@ -382,8 +408,37 @@
382 408 $subscriptionData = $this->subscriptionData;
383 409 $subscriptionData['customer_id'] = $customerId;
384 410 $subscriptionData['parent_order_id'] = $this->orderModel->id;
385 411 $this->subscriptionModel = Subscription::query()->create($subscriptionData);
412 +
413 + // bill_count counting can't tell "billed cycle" from "something else
414 + // charged alongside it." Must be decided at creation: payment-method switching
415 + // also sets is_trial_days_simulated, so the flag alone can't be trusted at runtime.
416 + $isSimulated = Arr::get($subscriptionData, 'config.is_trial_days_simulated', 'no') === 'yes';
417 + $trialDays = (int)Arr::get($subscriptionData, 'trial_days', 0);
418 + $billTimes = (int)$this->subscriptionModel->bill_times;
419 + $orderTotal = (int)$this->orderModel->total_amount;
420 +
421 + // Simulated trial, $0 first cycle: consumes a cycle but produces no
422 + // total > 0 transaction — add billed_cycles_offset so it still counts.
423 + if ($isSimulated
424 + && $billTimes > 0
425 + && (int)$this->subscriptionModel->signup_fee <= 0
426 + && !$orderTotal
427 + ) {
428 + $this->subscriptionModel->updateMeta('billed_cycles_offset', 1);
429 + }
430 +
431 + // Real trial with a signup fee: the initial charge is the signup fee only,
432 + // but it IS a total > 0 transaction linked to the subscription — mark
433 + // billed_cycles_deduction so it does NOT count as a cycle.
434 + if (!$isSimulated
435 + && $trialDays > 0
436 + && $billTimes > 0
437 + && $orderTotal > 0
438 + ) {
439 + $this->subscriptionModel->updateMeta('billed_cycles_deduction', 1);
440 + }
386 441 }
387 442
388 443 // Let's create the transaction
389 444 $transactionData = [
@@ -501,9 +556,9 @@
501 556 if ($firstPrice < $recurringPrice) {
502 557 Arr::set($item, 'other_info.trial_days', PaymentHelper::getIntervalDays(Arr::get($item, 'other_info.repeat_interval')));
503 558 Arr::set($item, 'other_info.signup_fee', $firstPrice);
504 559 Arr::set($item, 'other_info.manage_setup_fee', 'yes');
505 - Arr::set($item, 'other_info.times', Arr::get($item, 'other_info.times', 0) > 1 ? Arr::get($item, 'other_info.times', 0) - 1 : 0);
560 + // times stays the full installment count — the simulated trial cycle is installment #1
506 561 } else if ($firstPrice > $recurringPrice) {
507 562 Arr::set($item, 'other_info.signup_fee', $firstPrice - $recurringPrice);
508 563 Arr::set($item, 'other_info.manage_setup_fee', 'yes');
509 564 Arr::set($item, 'other_info.trial_days', 0);
@@ -529,11 +584,16 @@
529 584 'bill_count' => 0,
530 585 'quantity' => 1,
531 586 'variation_id' => Arr::get($item, 'object_id', 0),
532 587 'status' => Status::SUBSCRIPTION_PENDING,
588 + 'collection_method' => Status::SUBSCRIPTION_METHOD_MANUAL,
533 589 'config' => [
534 590 'currency' => $this->orderData['currency'],
535 591 'is_trial_days_simulated' => Arr::get($subscriptionPricing, 'is_trial_days_simulated', 'no'),
592 + // Snapshot the variant attribute map + variation type from the order
593 + // item so the subscription carries the same pa_* set behind its item_name.
594 + 'item_attributes' => Arr::get($item, 'other_info.item_attributes', []),
595 + 'variation_type' => Arr::get($item, 'other_info.variation_type', ''),
536 596 ]
537 597 ];
538 598
539 599 $this->subscriptionData = wp_parse_args($subscriptionPricing, $subscriptionItem);
@@ -665,9 +725,10 @@
665 725 $result['trial_days'] = $adjustedTrialDays;
666 726 $result['is_trial_days_simulated'] = 'yes';
667 727 $result['signup_fee'] = $firstCycleCost;
668 728 $result['manage_setup_fee'] = 'yes';
669 - $result['times'] = $times > 0 ? $times - 1 : 0;
729 + // bill_times stays the full installment count. The simulated trial cycle IS the
730 + // first installment; gateways derive remaining remote cycles from is_trial_days_simulated.
670 731 } else if ($firstCycleCost > $recurringAmount) {
671 732 $result['trial_days'] = 0;
672 733 $result['signup_fee'] = $firstCycleCost - $recurringAmount;
673 734 $result['manage_setup_fee'] = 'yes';