@php $isFreeGift = (bool) ($cartItem->options['is_free_gift'] ?? false); $productUrl = $product->original_product->url; $unitPrice = EcommerceHelper::isTaxEnabled() ? $cartItem->priceTax : $cartItem->price; $lineTotal = $unitPrice * $cartItem->qty; $lineOfferAmount = 0; $lineOfferPercent = 0; $lineOfferDiscountQty = 0; $lineOfferType = null; if (! $isFreeGift) { $cartContents = \Botble\Ecommerce\Facades\Cart::instance('cart')->content(); $cartProductIds = $cartContents->pluck('id')->map(fn ($id) => (int) $id)->unique()->values(); $dbCartProducts = \Botble\Ecommerce\Models\Product::query() ->whereIn('id', $cartProductIds->all()) ->with(['variationInfo', 'variationInfo.configurableProduct']) ->get(); $cartProducts = collect($productItems ?? ($products ?? [])) ->merge(\Botble\Ecommerce\Facades\Cart::instance('cart')->products()) ->merge($dbCartProducts) ->filter() ->unique(fn ($product) => (int) $product->id) ->values(); $buyXGetYPercentPromotions = \Botble\Ecommerce\Models\Discount::query() ->where('type', \Botble\Ecommerce\Enums\DiscountTypeEnum::PROMOTION) ->where('type_option', \Botble\Ecommerce\Enums\DiscountTypeOptionEnum::BUY_X_GET_Y_DISCOUNT) ->where('start_date', '<=', \Carbon\Carbon::now()) ->where(fn($query) => $query->whereNull('end_date')->orWhere('end_date', '>=', \Carbon\Carbon::now())) ->with('products') ->get(); foreach ($buyXGetYPercentPromotions as $promotion) { $buyProductIds = $promotion->products->pluck('id')->map(fn($id) => (int)$id)->all(); if (empty($buyProductIds)) continue; $buyQuantity = max((int)$promotion->product_quantity, 1); $buyCartQuantity = 0; foreach ($cartContents as $ci) { if ((bool)($ci->options['is_free_gift'] ?? false)) continue; $ciProduct = $cartProducts->firstWhere('id', $ci->id); if (!$ciProduct) continue; if (in_array((int)$ci->id, $buyProductIds, true) || in_array((int)$ciProduct->original_product->id, $buyProductIds, true)) { $buyCartQuantity += (int)$ci->qty; } } $eligibleQty = (int)floor($buyCartQuantity / $buyQuantity); if ($eligibleQty < 1) continue; foreach (\Illuminate\Support\Arr::wrap(data_get($promotion->apply_conditions, 'free_products', [])) as $offerProduct) { $offerProductId = (int)data_get($offerProduct, 'product_id'); $discountPercent = min(max((float)data_get($offerProduct, 'discount_percent', $promotion->value), 1), 100); $remainingQty = $eligibleQty; foreach ($cartContents as $ci) { if ($remainingQty < 1 || (bool)($ci->options['is_free_gift'] ?? false)) continue; $ciProduct = $cartProducts->firstWhere('id', $ci->id); if (!$ciProduct) continue; if ((int)$ci->id !== $offerProductId && (int)$ciProduct->original_product->id !== $offerProductId) { continue; } $discountQty = min((int)$ci->qty, $remainingQty); if ($ci->rowId === $cartItem->rowId) { $lineOfferAmount += $unitPrice * ($discountPercent / 100) * $discountQty; $lineOfferPercent = $discountPercent; $lineOfferDiscountQty += $discountQty; $lineOfferType = 'buy_x_get_y_percent'; } $remainingQty -= $discountQty; } } } } if ($externalLineOffer = ($checkoutLineOffers[$cartItem->rowId] ?? null)) { $lineOfferAmount = (float) ($externalLineOffer['amount'] ?? 0); $lineOfferPercent = (float) ($externalLineOffer['percent'] ?? 0); $lineOfferDiscountQty = (int) ($externalLineOffer['discount_qty'] ?? 0); $lineOfferType = $externalLineOffer['type'] ?? null; } $lineOfferAmount = min((float)$lineOfferAmount, (float)$lineTotal); $lineOfferDiscountQty = min((int) $lineOfferDiscountQty, (int) $cartItem->qty); $lineOfferRegularQty = max((int) $cartItem->qty - $lineOfferDiscountQty, 0); $shouldRenderSplitCheckoutRows = ! $isFreeGift && $lineOfferAmount > 0 && $lineOfferType === 'buy_x_get_y_percent' && $lineOfferDiscountQty > 0 && $lineOfferRegularQty > 0; $discountedUnitPrice = $lineOfferDiscountQty > 0 ? max((($unitPrice * $lineOfferDiscountQty) - $lineOfferAmount) / $lineOfferDiscountQty, 0) : $unitPrice; @endphp @if ($shouldRenderSplitCheckoutRows)
{{ $product->original_product->name }} {{ $lineOfferDiscountQty }}

{{ $product->original_product->name }}

@if($product->variation_attributes)

{{ $product->variation_attributes }}

@endif @include(EcommerceHelper::viewPath('includes.cart-item-options-extras'), ['options' => $cartItem->options]) {{ format_price($unitPrice) }} {{ format_price($discountedUnitPrice) }} {{ __('Offer') }} {{ (float)$lineOfferPercent }}% {{ __('off') }}

{{ format_price($unitPrice * $lineOfferDiscountQty) }} {{ format_price(($unitPrice * $lineOfferDiscountQty) - $lineOfferAmount) }}

{{ $product->original_product->name }} {{ $lineOfferRegularQty }}

{{ $product->original_product->name }}

@if($product->variation_attributes)

{{ $product->variation_attributes }}

@endif @include(EcommerceHelper::viewPath('includes.cart-item-options-extras'), ['options' => $cartItem->options]) @if (get_ecommerce_setting('checkout_product_quantity_editable', true))
@endif {{ format_price($unitPrice) }}

{{ format_price($unitPrice * $lineOfferRegularQty) }}

@else
@php $isFreeGift = (bool) ($cartItem->options['is_free_gift'] ?? false); $productUrl = $product->original_product->url; @endphp
{{ $product->original_product->name }} {{ $cartItem->qty }}
{!! apply_filters('ecommerce_cart_before_item_content', null, $cartItem) !!}

{{ $product->original_product->name }} @if ($isFreeGift) 🎁 {{ __('Free Gift') }} @endif @if ($product->isOutOfStock()) ({!! BaseHelper::clean($product->stock_status_html) !!}) @endif

@if($product->variation_attributes)

{{ $product->variation_attributes }}

@endif @if (get_ecommerce_setting('checkout_product_quantity_editable', true) && ! $isFreeGift)
@endif @include(EcommerceHelper::viewPath('includes.cart-item-options-extras'), [ 'options' => $cartItem->options, ]) @if (!empty($cartItem->options['options'])) {!! render_product_options_html($cartItem->options['options'], $product->original_price) !!} @endif {!! apply_filters('ecommerce_cart_after_item_content', null, $cartItem) !!} @php $unitPrice = EcommerceHelper::isTaxEnabled() ? $cartItem->priceTax : $cartItem->price; $lineTotal = $unitPrice * $cartItem->qty; $giftOriginalPrice = (float) ($cartItem->options['gift_original_price'] ?? $unitPrice); $lineOfferAmount = 0; $lineOfferPercent = 0; $lineOfferDiscountQty = 0; $lineOfferType = null; if (! $isFreeGift) { $cartContents = \Botble\Ecommerce\Facades\Cart::instance('cart')->content(); $cartProductIds = $cartContents->pluck('id')->map(fn ($id) => (int) $id)->unique()->values(); $dbCartProducts = \Botble\Ecommerce\Models\Product::query() ->whereIn('id', $cartProductIds->all()) ->with(['variationInfo', 'variationInfo.configurableProduct']) ->get(); $cartProducts = collect($productItems ?? ($products ?? [])) ->merge(\Botble\Ecommerce\Facades\Cart::instance('cart')->products()) ->merge($dbCartProducts) ->filter() ->unique(fn ($product) => (int) $product->id) ->values(); $buyXGetYPercentPromotions = \Botble\Ecommerce\Models\Discount::query() ->where('type', \Botble\Ecommerce\Enums\DiscountTypeEnum::PROMOTION) ->where('type_option', \Botble\Ecommerce\Enums\DiscountTypeOptionEnum::BUY_X_GET_Y_DISCOUNT) ->where('start_date', '<=', \Carbon\Carbon::now()) ->where(fn($query) => $query->whereNull('end_date')->orWhere('end_date', '>=', \Carbon\Carbon::now())) ->with('products') ->get(); foreach ($buyXGetYPercentPromotions as $promotion) { $buyProductIds = $promotion->products->pluck('id')->map(fn($id) => (int)$id)->all(); if (empty($buyProductIds)) continue; $buyQuantity = max((int)$promotion->product_quantity, 1); $buyCartQuantity = 0; foreach ($cartContents as $ci) { if ((bool)($ci->options['is_free_gift'] ?? false)) continue; $ciProduct = $cartProducts->firstWhere('id', $ci->id); if (!$ciProduct) continue; if ( in_array((int)$ci->id, $buyProductIds, true) || in_array((int)$ciProduct->original_product->id, $buyProductIds, true) ) { $buyCartQuantity += (int)$ci->qty; } } $eligibleQty = (int)floor($buyCartQuantity / $buyQuantity); if ($eligibleQty < 1) continue; foreach (\Illuminate\Support\Arr::wrap(data_get($promotion->apply_conditions, 'free_products', [])) as $offerProduct) { $offerProductId = (int)data_get($offerProduct, 'product_id'); $discountPercent = min(max((float)data_get($offerProduct, 'discount_percent', $promotion->value), 1), 100); $remainingQty = $eligibleQty; foreach ($cartContents as $ci) { if ($remainingQty < 1 || (bool)($ci->options['is_free_gift'] ?? false)) continue; $ciProduct = $cartProducts->firstWhere('id', $ci->id); if (!$ciProduct) continue; if ( (int)$ci->id !== $offerProductId && (int)$ciProduct->original_product->id !== $offerProductId ) { continue; } $discountQty = min((int)$ci->qty, $remainingQty); if ($ci->rowId === $cartItem->rowId) { $lineOfferAmount += $unitPrice * ($discountPercent / 100) * $discountQty; $lineOfferPercent = $discountPercent; $lineOfferDiscountQty += $discountQty; $lineOfferType = 'buy_x_get_y_percent'; } $remainingQty -= $discountQty; } } } $quantityBasedPromotions = \Botble\Ecommerce\Models\Discount::query() ->where('type', \Botble\Ecommerce\Enums\DiscountTypeEnum::PROMOTION) ->where('type_option', \Botble\Ecommerce\Enums\DiscountTypeOptionEnum::QUANTITY_BASED) ->where('start_date', '<=', \Carbon\Carbon::now()) ->where(fn($query) => $query->whereNull('end_date')->orWhere('end_date', '>=', \Carbon\Carbon::now())) ->with(['products', 'productCollections', 'productCategories']) ->get(); $cartRawTotal = \Botble\Ecommerce\Facades\Cart::instance('cart')->rawSubTotal(); foreach ($quantityBasedPromotions as $promotion) { if ( $promotion->target === \Botble\Ecommerce\Enums\DiscountTargetEnum::MINIMUM_ORDER_AMOUNT && (float) $promotion->min_order_price > (float) $cartRawTotal ) { continue; } $eligibleCartItems = $cartContents ->reject(fn($ci) => (bool)($ci->options['is_free_gift'] ?? false)) ->filter(function ($ci) use ($promotion, $cartProducts) { $ciProduct = $cartProducts->firstWhere('id', $ci->id); return match ($promotion->target) { \Botble\Ecommerce\Enums\DiscountTargetEnum::SPECIFIC_PRODUCT, \Botble\Ecommerce\Enums\DiscountTargetEnum::PRODUCT_VARIANT => in_array( (int)$ci->id, $promotion->products->pluck('id')->map(fn($id) => (int)$id)->all(), true ) || ($ciProduct && in_array( (int)$ciProduct->original_product->id, $promotion->products->pluck('id')->map(fn($id) => (int)$id)->all(), true )), \Botble\Ecommerce\Enums\DiscountTargetEnum::PRODUCT_COLLECTIONS => $ciProduct && $ciProduct->original_product ->productCollections() ->pluck('ec_product_collections.id') ->intersect($promotion->productCollections->pluck('id')) ->isNotEmpty(), \Botble\Ecommerce\Enums\DiscountTargetEnum::PRODUCT_CATEGORIES => $ciProduct && $ciProduct->original_product ->categories() ->pluck('ec_product_categories.id') ->intersect($promotion->productCategories->pluck('id')) ->isNotEmpty(), default => true, }; }); $discountPercent = min(max((float)$promotion->value, 0), 100); if ( $discountPercent <= 0 || $eligibleCartItems->sum('qty') < max((int)$promotion->product_quantity, 1) || ! $eligibleCartItems->contains(fn($ci) => $ci->rowId === $cartItem->rowId) ) { continue; } $lineOfferAmount += $unitPrice * (int)$cartItem->qty * ($discountPercent / 100); $lineOfferPercent = $lineOfferPercent ?: $discountPercent; $lineOfferDiscountQty = (int) $cartItem->qty; $lineOfferType = $lineOfferType ?: 'quantity_based'; } } if ($externalLineOffer = ($checkoutLineOffers[$cartItem->rowId] ?? null)) { $lineOfferAmount = (float) ($externalLineOffer['amount'] ?? 0); $lineOfferPercent = (float) ($externalLineOffer['percent'] ?? 0); $lineOfferDiscountQty = (int) ($externalLineOffer['discount_qty'] ?? 0); $lineOfferType = $externalLineOffer['type'] ?? null; } $lineOfferAmount = min((float)$lineOfferAmount, (float)$lineTotal); $lineTotalAfterOffer = max((float)$lineTotal - $lineOfferAmount, 0); $lineOfferDiscountQty = min((int) $lineOfferDiscountQty, (int) $cartItem->qty); $lineOfferRegularQty = max((int) $cartItem->qty - $lineOfferDiscountQty, 0); $shouldSplitOfferLine = $lineOfferAmount > 0 && $lineOfferType === 'buy_x_get_y_percent' && $lineOfferDiscountQty > 0 && $lineOfferRegularQty > 0; $discountedUnitPrice = $lineOfferDiscountQty > 0 ? max((($unitPrice * $lineOfferDiscountQty) - $lineOfferAmount) / $lineOfferDiscountQty, 0) : $unitPrice; @endphp @if ($isFreeGift) {{ __('Free') }} @if ($giftOriginalPrice > 0) {{ format_price($giftOriginalPrice) }} @endif @elseif ($shouldSplitOfferLine)
{{ __('Qty') }} {{ $lineOfferDiscountQty }}: {{ format_price($unitPrice) }} {{ format_price($discountedUnitPrice) }} {{ __('Offer') }} {{ (float)$lineOfferPercent }}% {{ __('off') }}
{{ __('Qty') }} {{ $lineOfferRegularQty }}: {{ format_price($unitPrice) }}
@elseif ($lineOfferAmount > 0) {{ format_price($unitPrice) }} {{ format_price($lineTotalAfterOffer / max((int)$cartItem->qty, 1)) }} {{ (float)$lineOfferPercent }}% {{ __('off') }} @else {{ format_price($unitPrice) }} @endif

@if ($isFreeGift) {{ __('FREE') }} @elseif ($shouldSplitOfferLine) {{ format_price($unitPrice * $lineOfferDiscountQty) }} {{ format_price(($unitPrice * $lineOfferDiscountQty) - $lineOfferAmount) }} {{ format_price($unitPrice * $lineOfferRegularQty) }} @elseif ($lineOfferAmount > 0) {{ format_price($lineTotal) }} {{ format_price($lineTotalAfterOffer) }} @else {{ format_price($lineTotal) }} @endif

@endif