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.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
← All changes | app/Hooks/Handlers/CustomCheckout/CustomCheckout.php +69 -34 1.5.4 → 1.6.5 View file →
@@ -93,42 +93,10 @@
93 93
94 94 $instantCart = CartHelper::generateCartFromCustomVariation($newItem, $orderItem->quantity);
95 95
96 96 } else {
97 - $items = [];
98 - $productItems = $order->order_items->filter(function ($orderItem) {
99 - return !in_array($orderItem->payment_type, ['fee', 'signup_fee']);
100 - });
101 - foreach ($productItems as $orderItem) {
102 - $itemData = ProductItemService::getItem([
103 - 'order_id' => $orderItem->order_id,
104 - 'product_id' => $orderItem->post_id,
105 - 'variation_id' => $orderItem->object_id,
106 - ]);
107 - if (!$itemData || !$itemData->variation) {
108 - die('Failed to load product data for custom checkout!');
109 - }
110 - $item = $itemData->variation->toArray();
111 -
112 -
113 - Arr::set($item, 'coupon_discount', (string)($orderItem->discount_total)); // item discount total is always coupon discount + manual discount
114 - Arr::set($item, 'tax_amount', $orderItem->tax_amount);
115 - Arr::set($item, 'post_title', $orderItem->post_title);
116 - Arr::set($item, 'variation_type', $itemData->variation->product_detail->variation_type);
117 -
118 - if ($itemManualDiscountTotal) {
119 - $subtotal = Arr::get($orderItem, 'subtotal');
120 - $manualDiscount = ($subtotal * $itemManualDiscountTotal) / $order->subtotal;
121 - $couponDiscount = max(0, $orderItem->discount_total - $manualDiscount);
122 - Arr::set($item, 'manual_discount', $manualDiscount);
123 - Arr::set($item, 'coupon_discount', $couponDiscount);
124 - }
125 -
126 - $items[] = CartHelper::generateCartItemCustomItem($item, $orderItem->quantity);
127 - }
128 -
129 97 $instantCart = new Cart();
130 - $instantCart->cart_data = $items;
98 + $instantCart->cart_data = static::buildOneTimeCartItems($order, $itemManualDiscountTotal);
131 99 }
132 100
133 101 $primaryBillingAddress = [];
134 102 if ($order->billing_address) {
@@ -178,13 +146,23 @@
178 146 '__cart_notices' => [
179 147 [
180 148 'id' => 'custom_payment_notice',
181 149 'type' => 'info',
182 - 'content' => 'You are making payment for your order (#' . $order->uuid . ').',
150 + 'content' => sprintf(
151 + /* translators: %1$s: the order UUID. */
152 + __('You are making payment for your order (#%1$s).', 'fluent-cart'),
153 + $order->uuid
154 + ),
183 155 ]
184 156 ]
185 157 ];
186 158
159 + if ($order->type === Status::ORDER_TYPE_RENEWAL) {
160 + $checkoutData['renewal_order'] = [
161 + 'due_date' => $order->getMeta('due_date'),
162 + ];
163 + }
164 +
187 165 if ($prorateCredit > 0) {
188 166 $checkoutData['prorate_credit'] = [
189 167 'amount' => $prorateCredit,
190 168 'title' => __('Prorate Credit', 'fluent-cart'),
@@ -212,6 +190,63 @@
212 190 );
213 191
214 192 wp_redirect($checkoutUrl);
215 193 exit();
194 + }
195 +
196 + /**
197 + * Build cart items for a one-time (non-subscription) order re-pay, priced at the
198 + * order's own unit_price rather than the current catalogue price.
199 + */
200 + protected static function buildOneTimeCartItems(Order $order, $itemManualDiscountTotal)
201 + {
202 + $items = [];
203 + $productItems = $order->order_items->filter(function ($orderItem) {
204 + return !in_array($orderItem->payment_type, ['fee', 'signup_fee']);
205 + });
206 +
207 + foreach ($productItems as $orderItem) {
208 + $itemData = ProductItemService::getItem([
209 + 'order_id' => $orderItem->order_id,
210 + 'product_id' => $orderItem->post_id,
211 + 'variation_id' => $orderItem->object_id,
212 + ]);
213 + if (!$itemData || !$itemData->variation) {
214 + die('Failed to load product data for custom checkout!');
215 + }
216 + $item = $itemData->variation->toArray();
217 +
218 + Arr::set($item, 'coupon_discount', (string)($orderItem->discount_total)); // item discount total is always coupon discount + manual discount
219 + Arr::set($item, 'tax_amount', $orderItem->tax_amount);
220 + Arr::set($item, 'post_title', $orderItem->post_title);
221 + Arr::set($item, 'variation_type', $itemData->variation->product_detail->variation_type);
222 +
223 + // Use the order item's unit_price, not the current catalogue price — the order
224 + // may carry a price agreed at purchase time (adjusted unit_price, since expired
225 + // catalogue price) that differs from what the product sells for today.
226 + Arr::set($item, 'item_price', $orderItem->unit_price);
227 +
228 + // For renewal invoices, also strip trial_days so CheckoutProcessor doesn't
229 + // apply trial (0) pricing on a renewal.
230 + if ($order->type === Status::ORDER_TYPE_RENEWAL) {
231 + $otherInfo = Arr::get($item, 'other_info', []);
232 + $otherInfo['trial_days'] = 0;
233 + Arr::set($item, 'other_info', $otherInfo);
234 + }
235 +
236 + if ($itemManualDiscountTotal) {
237 + // Use the order item's own stored split rather than proportionally
238 + // redistributing the order-level manual_discount_total — a manual
239 + // discount concentrated on one item must stay on that item, or this
240 + // reconstruction both keeps it there AND leaves a duplicate slice
241 + // behind as "coupon_discount" on it.
242 + $manualDiscount = max(0, (int) $orderItem->discount_total - (int) $orderItem->coupon_discount);
243 + Arr::set($item, 'manual_discount', $manualDiscount);
244 + Arr::set($item, 'coupon_discount', (int) $orderItem->coupon_discount);
245 + }
246 +
247 + $items[] = CartHelper::generateCartItemCustomItem($item, $orderItem->quantity);
248 + }
249 +
250 + return $items;
216 251 }
217 252 }