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 -33 1.4.1 → 1.6.5 View file →
@@ -93,41 +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 -
117 - if ($itemManualDiscountTotal) {
118 - $subtotal = Arr::get($orderItem, 'subtotal');
119 - $manualDiscount = ($subtotal * $itemManualDiscountTotal) / $order->subtotal;
120 - $couponDiscount = max(0, $orderItem->discount_total - $manualDiscount);
121 - Arr::set($item, 'manual_discount', $manualDiscount);
122 - Arr::set($item, 'coupon_discount', $couponDiscount);
123 - }
124 -
125 - $items[] = CartHelper::generateCartItemCustomItem($item, $orderItem->quantity);
126 - }
127 -
128 97 $instantCart = new Cart();
129 - $instantCart->cart_data = $items;
98 + $instantCart->cart_data = static::buildOneTimeCartItems($order, $itemManualDiscountTotal);
130 99 }
131 100
132 101 $primaryBillingAddress = [];
133 102 if ($order->billing_address) {
@@ -177,13 +146,23 @@
177 146 '__cart_notices' => [
178 147 [
179 148 'id' => 'custom_payment_notice',
180 149 'type' => 'info',
181 - '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 + ),
182 155 ]
183 156 ]
184 157 ];
185 158
159 + if ($order->type === Status::ORDER_TYPE_RENEWAL) {
160 + $checkoutData['renewal_order'] = [
161 + 'due_date' => $order->getMeta('due_date'),
162 + ];
163 + }
164 +
186 165 if ($prorateCredit > 0) {
187 166 $checkoutData['prorate_credit'] = [
188 167 'amount' => $prorateCredit,
189 168 'title' => __('Prorate Credit', 'fluent-cart'),
@@ -211,6 +190,63 @@
211 190 );
212 191
213 192 wp_redirect($checkoutUrl);
214 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;
215 251 }
216 252 }