feat(migration): enhance Mutual SMEP catalog seeding with featured groups and highlighted products

This commit is contained in:
2026-09-24 12:56:23 -03:00
parent c3def0678f
commit 92170b72f2
2 changed files with 171 additions and 17 deletions

View File

@@ -15,7 +15,34 @@ return new class extends Migration
private const BRAND_MARKER = 'Provisioned by Mutual SMEP catalog migration v1.';
private const FEATURED_GROUP_CODE = 'productos-smep';
/** @var list<array{code: string, category: string}> */
private const FEATURED_GROUPS = [
['code' => 'smep-dormitorio-y-blanco', 'category' => 'Dormitorio y Blanco'],
['code' => 'smep-electrodomesticos', 'category' => 'Electrodomésticos'],
['code' => 'smep-climatizacion', 'category' => 'Climatización'],
['code' => 'smep-tecnologia', 'category' => 'Tecnología'],
['code' => 'smep-bicicletas-y-aire-libre', 'category' => 'Bicicletas y Aire Libre'],
['code' => 'smep-bazar', 'category' => 'Bazar'],
];
private const HIGHLIGHTED_GROUP_CODE = 'productos-destacados-smep';
/** @var list<string> */
private const HIGHLIGHTED_PRODUCT_SLUGS = [
'acolchado-kavanagh-simil-plumon-reversible',
'acolchado-sense-duo-bitono-corderito',
'colchon-inducol-constanza',
'edredon-lisboa-jean-cartier',
'frazada-kavanagh-premium-soft',
'kit-edredon-alaska-corderito',
'motorola-g15',
'smart-tv-noblex-50-dr50-x8500-google-tv',
'heladera-gafa-hgf-368afp-330-lt-color-plata',
'cafetera-express-atma-ceat-5418p-1-litro',
'split-3300-w-tcl-taca-3300fcsa-frio-calor',
'bicicleta-venzo-loki-r29-fd-21-v-shimano',
'termo-stanley-1-l-adventure-go-to-con-tapon',
];
/** @var list<string> */
private array $storedPaths = [];
@@ -121,16 +148,7 @@ return new class extends Migration
}
}
DB::table('featured_groups')->insert([
'tenant_code' => self::TENANT_CODE,
'code' => self::FEATURED_GROUP_CODE,
'source_type' => 'all',
'category_id' => null,
'product_layout' => 'column_with_image',
'group_layout' => 'paginated',
'group_name' => 'Productos',
'group_order' => 1,
]);
$this->createFeaturedGroups();
});
} catch (Throwable $throwable) {
Storage::disk('s3')->delete($this->storedPaths);
@@ -172,7 +190,10 @@ return new class extends Migration
): void {
DB::table('featured_groups')
->where('tenant_code', self::TENANT_CODE)
->where('code', self::FEATURED_GROUP_CODE)
->whereIn('code', [
self::HIGHLIGHTED_GROUP_CODE,
...array_column(self::FEATURED_GROUPS, 'code'),
])
->delete();
DB::table('catalog_items')->whereIn('id', $catalogItemIds)->delete();
DB::table('inventories')
@@ -306,6 +327,84 @@ return new class extends Migration
]);
}
private function createFeaturedGroups(): void
{
$this->createHighlightedGroup();
foreach (self::FEATURED_GROUPS as $order => $group) {
$categoryId = DB::table('categorias')
->where('tenant_code', self::TENANT_CODE)
->whereNull('categoria_id')
->where('nombre', $group['category'])
->value('id');
if ($categoryId === null) {
throw new RuntimeException("Parent category '{$group['category']}' not found for Mutual SMEP.");
}
$featuredGroupId = DB::table('featured_groups')->insertGetId([
'tenant_code' => self::TENANT_CODE,
'code' => $group['code'],
'source_type' => 'manual',
'category_id' => $categoryId,
'product_layout' => 'column_with_image',
'group_layout' => 'carousel',
'group_name' => $group['category'],
'group_order' => $order + 2,
]);
$catalogItemIds = DB::table('catalog_items')
->join('categorias', 'categorias.id', '=', 'catalog_items.category_id')
->where('catalog_items.tenant_code', self::TENANT_CODE)
->where('categorias.tenant_code', self::TENANT_CODE)
->where('categorias.categoria_id', $categoryId)
->orderBy('catalog_items.group_order')
->orderBy('catalog_items.id')
->pluck('catalog_items.id');
foreach ($catalogItemIds as $itemOrder => $catalogItemId) {
DB::table('featured_items')->insert([
'featured_group_id' => $featuredGroupId,
'catalog_item_id' => $catalogItemId,
'order' => $itemOrder + 1,
]);
}
}
}
private function createHighlightedGroup(): void
{
$featuredGroupId = DB::table('featured_groups')->insertGetId([
'tenant_code' => self::TENANT_CODE,
'code' => self::HIGHLIGHTED_GROUP_CODE,
'source_type' => 'manual',
'category_id' => null,
'product_layout' => 'column_with_image',
'group_layout' => 'carousel',
'group_name' => 'Productos destacados',
'group_order' => 1,
]);
$catalogItemIds = DB::table('catalog_items')
->where('tenant_code', self::TENANT_CODE)
->whereIn('slug', self::HIGHLIGHTED_PRODUCT_SLUGS)
->pluck('id', 'slug');
foreach (self::HIGHLIGHTED_PRODUCT_SLUGS as $order => $slug) {
$catalogItemId = $catalogItemIds->get($slug);
if ($catalogItemId === null) {
throw new RuntimeException("Highlighted product '{$slug}' not found for Mutual SMEP.");
}
DB::table('featured_items')->insert([
'featured_group_id' => $featuredGroupId,
'catalog_item_id' => $catalogItemId,
'order' => $order + 1,
]);
}
}
/** @param list<string> $images */
private function attachImages(int $catalogItemId, ?int $variantId, array $images): void
{

View File

@@ -23,6 +23,7 @@ class SeedMutualSmepCatalogTest extends TestCase
protected function tearDown(): void
{
foreach ([
'featured_items',
'featured_groups',
'catalog_items_attachments',
'attachments',
@@ -61,11 +62,58 @@ class SeedMutualSmepCatalogTest extends TestCase
511,
count(Storage::disk('s3')->allFiles('tenants/mutual_smep/catalog-v1')),
);
$this->assertDatabaseHas('featured_groups', [
'tenant_code' => 'mutual_smep',
'code' => 'productos-smep',
'source_type' => 'all',
]);
$this->assertDatabaseCount('featured_groups', 7);
$this->assertSame([
'Productos destacados',
'Dormitorio y Blanco',
'Electrodomésticos',
'Climatización',
'Tecnología',
'Bicicletas y Aire Libre',
'Bazar',
], DB::table('featured_groups')->orderBy('group_order')->pluck('group_name')->all());
DB::table('featured_groups')->orderBy('group_order')->each(function (object $group): void {
$this->assertSame('manual', $group->source_type);
$this->assertSame('carousel', $group->group_layout);
$this->assertSame('column_with_image', $group->product_layout);
if ($group->code === 'productos-destacados-smep') {
$this->assertNull($group->category_id);
} else {
$this->assertNotNull($group->category_id);
$this->assertDatabaseHas('categorias', [
'id' => $group->category_id,
'tenant_code' => 'mutual_smep',
'categoria_id' => null,
'nombre' => $group->group_name,
]);
}
$this->assertGreaterThan(
0,
DB::table('featured_items')->where('featured_group_id', $group->id)->count(),
);
});
$highlightedGroupId = DB::table('featured_groups')
->where('code', 'productos-destacados-smep')
->value('id');
$highlightedSlugs = DB::table('featured_items')
->join('catalog_items', 'catalog_items.id', '=', 'featured_items.catalog_item_id')
->where('featured_items.featured_group_id', $highlightedGroupId)
->orderBy('featured_items.order')
->pluck('catalog_items.slug')
->all();
$variantProductSlugs = DB::table('catalog_items')
->whereExists(fn ($query) => $query
->selectRaw('1')
->from('variantes')
->whereColumn('variantes.catalog_item_id', 'catalog_items.id'))
->pluck('slug')
->all();
$this->assertCount(13, $highlightedSlugs);
$this->assertSame([], array_values(array_diff($variantProductSlugs, $highlightedSlugs)));
$this->assertSame(155, DB::table('featured_items')->count());
$this->assertDatabaseHas('catalog_items', [
'tenant_code' => 'mutual_smep',
'slug' => 'motorola-g15',
@@ -77,6 +125,7 @@ class SeedMutualSmepCatalogTest extends TestCase
$migration->down();
foreach ([
'featured_items',
'featured_groups',
'catalog_items_attachments',
'attachments',
@@ -226,5 +275,11 @@ class SeedMutualSmepCatalogTest extends TestCase
$table->string('group_name');
$table->unsignedInteger('group_order')->default(0);
});
Schema::create('featured_items', function (Blueprint $table): void {
$table->id();
$table->foreignId('featured_group_id')->constrained('featured_groups')->cascadeOnDelete();
$table->foreignId('catalog_item_id')->constrained('catalog_items')->cascadeOnDelete();
$table->unsignedInteger('order')->default(0);
});
}
}