Skip to content

Commit

Permalink
Grouped products support
Browse files Browse the repository at this point in the history
  • Loading branch information
royduin committed Mar 24, 2022
1 parent cbd708d commit 615ce9c
Show file tree
Hide file tree
Showing 8 changed files with 102 additions and 12 deletions.
5 changes: 4 additions & 1 deletion resources/js/components/Product/AddToCart.vue
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,10 @@
},
async add() {
if (Object.values(this.product.children).length && window.location.pathname !== this.product.url && !config.show_swatches) {
if ('children' in this.product
&& Object.values(this.product.children).length
&& window.location.pathname !== this.product.url
&& !config.show_swatches) {
Turbolinks.visit(this.product.url)
return;
}
Expand Down
3 changes: 2 additions & 1 deletion resources/views/product/overview.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@
<div class="p-3 my-5 sm:mt-0 bg-gray-200 rounded prose prose-green max-w-none" itemprop="description">
{!! $product->description !!}
</div>
@include('rapidez::product.partials.addtocart')
@includeWhen($product->type == 'grouped', 'rapidez::product.partials.grouped')
@includeWhen($product->type !== 'grouped', 'rapidez::product.partials.addtocart')
</div>
</div>

Expand Down
42 changes: 42 additions & 0 deletions resources/views/product/partials/grouped.blade.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<div class="grid grid-cols-3 gap-3 grid-cols-[auto_max-content_max-content]">
<div class="contents" v-for="product in config.product.grouped">
<add-to-cart :product="config.product.grouped[product.id]" :default-qty="{{ $product->qty_increments }}" v-cloak>
<div class="contents" slot-scope="{ qty, changeQty, options, error, add, disabledOptions, simpleProduct, adding, added }">
<div>
@{{ simpleProduct.name }}
<div class="flex items-center space-x-3 font-bold">
<div>@{{ (simpleProduct.special_price || simpleProduct.price) | price }}</div>
<div class="line-through" v-if="simpleProduct.special_price">@{{ simpleProduct.price | price }}</div>
</div>
</div>

@if(!$product->in_stock)
<p class="text-red-600">@lang('Sorry! This product is currently out of stock.')</p>
@else
<x-rapidez::select
name="qty"
label="Quantity"
v-bind:value="qty"
v-on:input="changeQty"
class="w-auto"
labelClass="flex items-center mr-3 sr-only"
wrapperClass="flex"
>
<option v-for="index in 10" :value="index * simpleProduct.qty_increments">
@{{ index * simpleProduct.qty_increments }}
</option>
</x-rapidez::select>

<x-rapidez::button class="flex items-center" v-on:click="add" dusk="add-to-cart">
<x-heroicon-o-shopping-cart class="h-5 w-5 mr-2" v-if="!adding && !added" />
<x-heroicon-o-refresh class="h-5 w-5 mr-2 animate-spin" v-if="adding" />
<x-heroicon-o-check class="h-5 w-5 mr-2" v-if="added" />
<span v-if="!adding && !added">@lang('Add to cart')</span>
<span v-if="adding">@lang('Adding')...</span>
<span v-if="added">@lang('Added')</span>
</x-rapidez::button>
@endif
</div>
</add-to-cart>
</div>
</div>
4 changes: 2 additions & 2 deletions src/Commands/ValidateCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ public function validateMagentoSettings()
$superAttributesCount = count($attributeModel::getCachedWhere(fn ($attribute) => $attribute['super']));
$joinCount = ($superAttributesCount * 2) + (count($nonFlatAttributes) * 3) + 4;

if ($joinCount > 61) {
$this->error('Most likely the queries needed for Rapidez will exceed 61 joins when indexing or viewing products so you have to reduce them by adding more attributes to the flat tables');
if ($joinCount > 58) {
$this->error('Most likely the queries needed for Rapidez will exceed 58 joins when indexing or viewing products so you have to reduce them by adding more attributes to the flat tables');
}

$this->info('The validation finished, if there where any errors; fix them before you continue. See: https://rapidez.io/docs/0.x/installation#flat-tables');
Expand Down
2 changes: 1 addition & 1 deletion src/Http/Controllers/ProductController.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public function show(int $productId)
->withEventyGlobalScopes('productpage.scopes')
->findOrFail($productId);

$attributes = ['id', 'name', 'sku', 'super_attributes', 'children', 'price', 'special_price', 'images', 'url'];
$attributes = ['id', 'name', 'sku', 'super_attributes', 'children', 'grouped', 'price', 'special_price', 'images', 'url'];
$attributes = Eventy::filter('productpage.frontend.attributes', $attributes);

foreach ($product->super_attributes ?: [] as $superAttribute) {
Expand Down
19 changes: 13 additions & 6 deletions src/Models/Product.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use Rapidez\Core\Models\Scopes\Product\WithProductAttributesScope;
use Rapidez\Core\Models\Scopes\Product\WithProductCategoryIdsScope;
use Rapidez\Core\Models\Scopes\Product\WithProductChildrenScope;
use Rapidez\Core\Models\Scopes\Product\WithProductGroupedScope;
use Rapidez\Core\Models\Scopes\Product\WithProductRelationIdsScope;
use Rapidez\Core\Models\Scopes\Product\WithProductStockScope;
use Rapidez\Core\Models\Scopes\Product\WithProductSuperAttributesScope;
Expand Down Expand Up @@ -39,9 +40,10 @@ protected static function booting(): void
static::addGlobalScope(new WithProductCategoryIdsScope());
static::addGlobalScope(new WithProductRelationIdsScope());
static::addGlobalScope(new WithProductChildrenScope());
static::addGlobalScope(new WithProductGroupedScope());
static::addGlobalScope('defaults', function (Builder $builder) {
$builder
->whereNotIn($builder->getQuery()->from.'.type_id', ['grouped', 'bundle'])
->whereNotIn($builder->getQuery()->from.'.type_id', ['bundle'])
->groupBy($builder->getQuery()->from.'.entity_id');
});
}
Expand All @@ -62,6 +64,7 @@ public function getCasts(): array
'relation_ids' => CommaSeparatedToArray::class,
'upsell_ids' => CommaSeparatedToArray::class,
'children' => Children::class,
'grouped' => Children::class,
'qty_increments' => 'int',
],
$this->getSuperAttributeCasts(),
Expand Down Expand Up @@ -91,16 +94,20 @@ public function scopeByIds(Builder $query, array $productIds): Builder

public function getPriceAttribute($price)
{
if (!(array) $this->children) {
return $price;
if ($this->type == 'configurable') {
return collect($this->children)->min->price;
}

return collect($this->children)->min->price;
if ($this->type == 'grouped') {
return collect($this->grouped)->min->price;
}

return $price;
}

public function getSpecialPriceAttribute($specialPrice)
{
if (!(array) $this->children) {
if (!in_array($this->type, ['configurable', 'grouped'])) {
if ($this->special_from_date && $this->special_from_date > now()->toDateString()) {
return null;
}
Expand All @@ -112,7 +119,7 @@ public function getSpecialPriceAttribute($specialPrice)
return $specialPrice !== $this->price ? $specialPrice : null;
}

return collect($this->children)->filter(function ($child) {
return collect($this->type == 'configurable' ? $this->children : $this->grouped)->filter(function ($child) {
if (!$child->special_price) {
return false;
}
Expand Down
3 changes: 2 additions & 1 deletion src/Models/Scopes/Product/WithProductAttributesScope.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ public function apply(Builder $builder, Model $model)

$builder
->addSelect($builder->getQuery()->from.'.entity_id AS id')
->addSelect($builder->getQuery()->from.'.sku');
->addSelect($builder->getQuery()->from.'.sku')
->addSelect($builder->getQuery()->from.'.type_id AS type');

foreach ($attributes as $attribute) {
$attribute = (object) $attribute;
Expand Down
36 changes: 36 additions & 0 deletions src/Models/Scopes/Product/WithProductGroupedScope.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

namespace Rapidez\Core\Models\Scopes\Product;

use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Scope;
use Illuminate\Support\Facades\DB;
use TorMorten\Eventy\Facades\Eventy;

class WithProductGroupedScope implements Scope
{
public function apply(Builder $builder, Model $model)
{
$builder
->selectRaw('JSON_REMOVE(JSON_OBJECTAGG(IFNULL(grouped.entity_id, "null__"), JSON_OBJECT(
'.Eventy::filter('product.grouped.select', <<<QUERY
"id", grouped.entity_id,
"sku", grouped.sku,
"name", grouped.name,
"price", grouped.price,
"special_price", grouped.special_price,
"special_from_date", DATE(grouped.special_from_date),
"special_to_date", DATE(grouped.special_to_date),
"in_stock", grouped_stock.is_in_stock,
"qty_increments", IFNULL(NULLIF(grouped_stock.qty_increments, 0), 1)
QUERY).'
)), "$.null__") AS grouped')
->leftJoin('catalog_product_link', function ($join) use ($model) {
$join->on('catalog_product_link.product_id', '=', $model->getTable().'.entity_id')
->where('link_type_id', 3);
})
->leftJoin($model->getTable().' as grouped', 'linked_product_id', '=', 'grouped.entity_id')
->leftJoin('cataloginventory_stock_item AS grouped_stock', 'grouped.entity_id', '=', 'grouped_stock.product_id');
}
}

0 comments on commit 615ce9c

Please sign in to comment.