Add new product images and implement SeedMutualSmepCatalogTest for catalog migration

- Added multiple new product images for smart TVs, audio devices, and accessories in WEBP format.
- Created a new test class SeedMutualSmepCatalogTest to validate the catalog migration process.
- Implemented setup and teardown methods to manage database schema and data during tests.
- Verified the integrity of catalog items, inventories, and associated attributes after migration.
This commit is contained in:
2026-09-24 12:41:24 -03:00
parent 16e2ca679c
commit 74b72a7d4e
516 changed files with 3953 additions and 0 deletions

View File

@@ -0,0 +1,230 @@
<?php
namespace Tests\Feature\Migrations;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Facades\Storage;
use Tests\TestCase;
class SeedMutualSmepCatalogTest extends TestCase
{
protected function setUp(): void
{
parent::setUp();
Storage::fake('s3');
$this->createSchema();
DB::table('tenants')->insert(['codigo' => 'mutual_smep']);
$this->seedCategoriesAndAttributes();
}
protected function tearDown(): void
{
foreach ([
'featured_groups',
'catalog_items_attachments',
'attachments',
'variant_values',
'item_attributes',
'variantes',
'catalog_items',
'inventories',
'brands',
'attribute',
'categorias',
'tenants',
] as $table) {
Schema::dropIfExists($table);
}
parent::tearDown();
}
public function test_it_loads_and_rolls_back_the_complete_catalog(): void
{
$migration = require database_path(
'migrations/2026_09_24_030000_seed_mutual_smep_catalog.php'
);
$migration->up();
$this->assertSame(142, DB::table('catalog_items')->count());
$this->assertSame(150, DB::table('inventories')->count());
$this->assertSame(15, DB::table('variantes')->count());
$this->assertSame(8, DB::table('item_attributes')->count());
$this->assertSame(17, DB::table('variant_values')->count());
$this->assertSame(511, DB::table('attachments')->count());
$this->assertSame(511, DB::table('catalog_items_attachments')->count());
$this->assertSame(
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->assertDatabaseHas('catalog_items', [
'tenant_code' => 'mutual_smep',
'slug' => 'motorola-g15',
'precio' => 330000,
]);
$this->assertSame(10, DB::table('inventories')->min('real_stock'));
$this->assertSame(10, DB::table('inventories')->max('real_stock'));
$migration->down();
foreach ([
'featured_groups',
'catalog_items_attachments',
'attachments',
'variant_values',
'item_attributes',
'variantes',
'catalog_items',
'inventories',
'brands',
] as $table) {
$this->assertSame(0, DB::table($table)->count(), $table);
}
$this->assertSame([], Storage::disk('s3')->allFiles('tenants/mutual_smep/catalog-v1'));
}
private function seedCategoriesAndAttributes(): void
{
$manifest = json_decode(
(string) file_get_contents(database_path('data/mutual_smep_catalog_v1.json')),
true,
flags: JSON_THROW_ON_ERROR,
);
$parents = [];
foreach ($manifest['items'] as $item) {
$parentName = $item['parent_category'];
$parentId = $parents[$parentName] ??= DB::table('categorias')->insertGetId([
'tenant_code' => 'mutual_smep',
'categoria_id' => null,
'nombre' => $parentName,
]);
DB::table('categorias')->insertOrIgnore([
'tenant_code' => 'mutual_smep',
'categoria_id' => $parentId,
'nombre' => $item['category'],
]);
}
foreach (['color', 'medida_cama', 'almacenamiento', 'memoria_ram', 'rodado'] as $code) {
DB::table('attribute')->insert([
'tenant_codigo' => 'mutual_smep',
'codigo' => $code,
'nombre' => $code,
]);
}
}
private function createSchema(): void
{
Schema::create('tenants', fn (Blueprint $table) => $table->string('codigo')->primary());
Schema::create('categorias', function (Blueprint $table): void {
$table->id();
$table->string('tenant_code');
$table->unsignedBigInteger('categoria_id')->nullable();
$table->string('nombre');
$table->unique(['tenant_code', 'categoria_id', 'nombre']);
});
Schema::create('attribute', function (Blueprint $table): void {
$table->id();
$table->string('tenant_codigo');
$table->string('codigo');
$table->string('nombre');
});
Schema::create('brands', function (Blueprint $table): void {
$table->id();
$table->string('tenant_codigo');
$table->string('nombre');
$table->text('descripcion')->nullable();
$table->timestamps();
});
Schema::create('inventories', function (Blueprint $table): void {
$table->id();
$table->unsignedBigInteger('sold_units')->default(0);
$table->unsignedBigInteger('refunded_units')->default(0);
$table->unsignedInteger('reserved_stock')->default(0);
$table->unsignedInteger('real_stock')->default(0);
});
Schema::create('catalog_items', function (Blueprint $table): void {
$table->id();
$table->string('tenant_code');
$table->unsignedBigInteger('category_id')->nullable();
$table->unsignedBigInteger('brand_id')->nullable();
$table->unsignedBigInteger('inventory_id')->nullable();
$table->string('type');
$table->string('slug');
$table->string('nombre');
$table->unsignedInteger('group_order')->default(0);
$table->text('descripcion')->nullable();
$table->decimal('precio', 10, 2);
$table->string('inventory_policy');
$table->string('inventory_subject');
$table->boolean('has_tickets')->default(false);
$table->unique(['tenant_code', 'slug']);
});
Schema::create('variantes', function (Blueprint $table): void {
$table->id();
$table->foreignId('catalog_item_id')->constrained('catalog_items')->cascadeOnDelete();
$table->unsignedBigInteger('inventory_id');
$table->text('descripcion')->nullable();
$table->decimal('precio', 10, 2)->nullable();
});
Schema::create('item_attributes', function (Blueprint $table): void {
$table->id();
$table->foreignId('catalog_item_id')->constrained('catalog_items')->cascadeOnDelete();
$table->unsignedBigInteger('attribute_id');
$table->boolean('allow_multi_select')->default(false);
$table->unsignedInteger('sort_order')->default(0);
$table->boolean('show_in_selector')->default(true);
$table->string('ticket_label')->nullable();
$table->timestamps();
});
Schema::create('variant_values', function (Blueprint $table): void {
$table->id();
$table->foreignId('variant_id')->constrained('variantes')->cascadeOnDelete();
$table->foreignId('item_attribute_id')->constrained('item_attributes')->cascadeOnDelete();
$table->text('value')->nullable();
$table->timestamps();
});
Schema::create('attachments', function (Blueprint $table): void {
$table->id();
$table->uuid('key')->unique();
$table->string('path');
$table->string('filename');
$table->string('type');
$table->string('mime_type');
$table->string('extension')->nullable();
$table->unsignedBigInteger('size')->default(0);
$table->timestamps();
});
Schema::create('catalog_items_attachments', function (Blueprint $table): void {
$table->id();
$table->foreignId('variant_id')->nullable()->constrained('variantes')->cascadeOnDelete();
$table->foreignId('catalog_item_id')->constrained('catalog_items')->cascadeOnDelete();
$table->foreignId('attachment_id')->constrained('attachments')->cascadeOnDelete();
$table->unsignedInteger('orden')->default(0);
$table->boolean('is_enabled')->default(true);
});
Schema::create('featured_groups', function (Blueprint $table): void {
$table->id();
$table->string('tenant_code');
$table->string('code');
$table->string('source_type');
$table->unsignedBigInteger('category_id')->nullable();
$table->string('product_layout');
$table->string('group_layout');
$table->string('group_name');
$table->unsignedInteger('group_order')->default(0);
});
}
}