feat: Introduce source type for featured groups; add category association and implement FeaturedGroupService for item sourcing

This commit is contained in:
2026-08-04 13:17:00 -03:00
parent 8aa3a26ee7
commit 84e45bb964
13 changed files with 260 additions and 136 deletions

View File

@@ -4,9 +4,11 @@ namespace Tests\Feature\Catalog;
use App\Domains\Attachable\Enums\AttachmentType;
use App\Domains\Attachable\Models\Attachment;
use App\Domains\Catalog\Enums\FeaturedGroupSource;
use App\Domains\Catalog\Enums\GroupLayout;
use App\Domains\Catalog\Enums\ProductLayout;
use App\Domains\Catalog\Models\CatalogItem;
use App\Domains\Catalog\Models\Category;
use App\Domains\Catalog\Models\FeaturedGroup;
use App\Domains\Catalog\Models\Inventory;
use App\Domains\Tenant\Models\Tenant;
@@ -198,6 +200,46 @@ class CatalogControllerTest extends TestCase
->assertJsonPath('0.nombre', 'carousel Item 1');
}
public function test_groups_can_source_items_from_a_category_or_the_entire_catalog(): void
{
$tenant = $this->createTenant('catalog-sources');
$category = Category::query()->create([
'tenant_code' => $tenant->codigo,
'nombre' => 'Food',
]);
FeaturedGroup::query()->create([
'tenant_code' => $tenant->codigo,
'source_type' => FeaturedGroupSource::Category,
'category_id' => $category->id,
'product_layout' => ProductLayout::Row,
'group_layout' => GroupLayout::Simple,
'group_name' => 'Food',
'group_order' => 0,
]);
FeaturedGroup::query()->create([
'tenant_code' => $tenant->codigo,
'source_type' => FeaturedGroupSource::All,
'product_layout' => ProductLayout::Row,
'group_layout' => GroupLayout::Paginated,
'group_name' => 'All products',
'group_order' => 1,
]);
$food = $this->createItem($tenant, 'Hamburger');
$food->category()->associate($category)->save();
$this->createItem($tenant, 'Parking');
$this->getJson("/api/tenants/{$tenant->codigo}/catalog")
->assertOk()
->assertJsonPath('0.title', 'Food')
->assertJsonCount(1, '0.items')
->assertJsonPath('0.items.0.nombre', 'Hamburger')
->assertJsonPath('1.title', 'All products')
->assertJsonCount(2, '1.items.data')
->assertJsonPath('1.items.meta.total', 2);
}
private function createGroup(
Tenant $tenant,
ProductLayout $layout,

View File

@@ -79,6 +79,8 @@ class CatalogSchemaTest extends TestCase
$this->assertEqualsCanonicalizing([
'id',
'tenant_code',
'source_type',
'category_id',
'product_layout',
'group_layout',
'group_name',

View File

@@ -6,6 +6,7 @@ use App\Domains\Attachable\Enums\AttachmentType;
use App\Domains\Attachable\Models\Attachment;
use App\Domains\Catalog\Enums\CatalogItemType;
use App\Domains\Catalog\Enums\EventProductType;
use App\Domains\Catalog\Enums\FeaturedGroupSource;
use App\Domains\Catalog\Enums\GroupLayout;
use App\Domains\Catalog\Enums\ProductLayout;
use App\Domains\Catalog\Models\Attribute;
@@ -174,7 +175,7 @@ class FiestaFutbolInfantilProductSeederTest extends TestCase
$this->assertSame(9, CatalogItem::query()->where('tenant_code', $tenant->codigo)->count());
$this->assertSame(10, Inventory::query()->count());
$this->assertSame(
['Entradas', 'Estacionamiento', 'Gastronomía'],
['Bebidas', 'Comidas', 'Entradas', 'Estacionamiento', 'Gastronomía'],
Category::query()
->where('tenant_code', $tenant->codigo)
->orderBy('nombre')
@@ -194,7 +195,7 @@ class FiestaFutbolInfantilProductSeederTest extends TestCase
$featuredGroups = FeaturedGroup::query()
->where('tenant_code', $tenant->codigo)
->with('featuredItems.catalogItem')
->with('category.catalogItems')
->orderBy('group_order')
->get();
@@ -207,21 +208,23 @@ class FiestaFutbolInfantilProductSeederTest extends TestCase
],
$featuredGroups
->mapWithKeys(fn (FeaturedGroup $group): array => [
$group->group_name => $group->featuredItems->pluck('catalogItem.slug')->all(),
$group->group_name => $group->category->catalogItems->pluck('slug')->all(),
])
->all()
);
$this->assertSame(
[
['Entradas', ProductLayout::Row, GroupLayout::SimpleVertical, 0],
['Estacionamiento', ProductLayout::ColumnWithCart, GroupLayout::Simple, 1],
['Comidas', ProductLayout::ColumnWithCart, GroupLayout::Simple, 2],
['Bebidas', ProductLayout::ColumnWithCart, GroupLayout::Simple, 3],
['Entradas', FeaturedGroupSource::Category, 'Entradas', ProductLayout::Row, GroupLayout::SimpleVertical, 0],
['Estacionamiento', FeaturedGroupSource::Category, 'Estacionamiento', ProductLayout::ColumnWithCart, GroupLayout::Simple, 1],
['Comidas', FeaturedGroupSource::Category, 'Comidas', ProductLayout::ColumnWithCart, GroupLayout::Simple, 2],
['Bebidas', FeaturedGroupSource::Category, 'Bebidas', ProductLayout::ColumnWithCart, GroupLayout::Simple, 3],
],
$featuredGroups
->map(fn (FeaturedGroup $group): array => [
$group->group_name,
$group->source_type,
$group->category->nombre,
$group->product_layout,
$group->group_layout,
$group->group_order,

View File

@@ -4,6 +4,7 @@ namespace Tests\Feature\Seeders;
use App\Domains\Attachable\Enums\AttachmentType;
use App\Domains\Attachable\Models\Attachment;
use App\Domains\Catalog\Enums\FeaturedGroupSource;
use App\Domains\Catalog\Enums\GroupLayout;
use App\Domains\Catalog\Enums\ProductLayout;
use App\Domains\Catalog\Models\CatalogItem;
@@ -70,16 +71,14 @@ class ProductCatalogFromImagesSeederTest extends TestCase
$this->assertNotNull($paginatedGroup);
$this->assertSame(ProductLayout::ColumnWithImage, $paginatedGroup->product_layout);
$this->assertSame(GroupLayout::Paginated, $paginatedGroup->group_layout);
$this->assertSame(0, $paginatedGroup->group_order);
$this->assertSame(
CatalogItem::query()->where('tenant_code', $tenant->codigo)->orderBy('id')->pluck('slug')->all(),
$paginatedGroup->featuredItems->pluck('catalogItem.slug')->all(),
);
$this->assertCount(10, $paginatedGroup->featuredItems);
$this->assertSame(FeaturedGroupSource::All, $paginatedGroup->source_type);
$this->assertSame(2, $paginatedGroup->group_order);
$this->assertCount(0, $paginatedGroup->featuredItems);
$this->assertNotNull($carouselGroup);
$this->assertSame(ProductLayout::ColumnWithImage, $carouselGroup->product_layout);
$this->assertSame(GroupLayout::Carousel, $carouselGroup->group_layout);
$this->assertSame(FeaturedGroupSource::Manual, $carouselGroup->source_type);
$this->assertSame(1, $carouselGroup->group_order);
$this->assertCount(5, $carouselGroup->featuredItems);
$this->assertCount(

View File

@@ -5,6 +5,7 @@ namespace Tests\Unit\Catalog;
use App\Domains\Attachable\Models\Attachment;
use App\Domains\Catalog\Enums\CatalogItemType;
use App\Domains\Catalog\Enums\EventProductType;
use App\Domains\Catalog\Enums\FeaturedGroupSource;
use App\Domains\Catalog\Enums\GroupLayout;
use App\Domains\Catalog\Enums\InventoryPolicy;
use App\Domains\Catalog\Enums\ProductLayout;
@@ -104,6 +105,8 @@ class CatalogModelsTest extends TestCase
{
$group = new FeaturedGroup;
$group->setRawAttributes([
'source_type' => FeaturedGroupSource::Category->value,
'category_id' => '4',
'product_layout' => ProductLayout::ColumnWithImage->value,
'group_layout' => GroupLayout::SimpleVertical->value,
'group_order' => '2',
@@ -118,9 +121,12 @@ class CatalogModelsTest extends TestCase
$this->assertSame('featured_groups', $group->getTable());
$this->assertFalse($group->usesTimestamps());
$this->assertSame(ProductLayout::ColumnWithImage, $group->product_layout);
$this->assertSame(FeaturedGroupSource::Category, $group->source_type);
$this->assertSame(4, $group->category_id);
$this->assertSame(GroupLayout::SimpleVertical, $group->group_layout);
$this->assertSame(2, $group->group_order);
$this->assertInstanceOf(Tenant::class, $group->tenant()->getRelated());
$this->assertInstanceOf(Category::class, $group->category()->getRelated());
$this->assertInstanceOf(FeaturedItem::class, $group->featuredItems()->getRelated());
$this->assertSame('featured_items', $featuredItem->getTable());