feat: Update product seeder to include inventory policy and improve code readability

This commit is contained in:
2026-07-16 09:07:05 -03:00
parent 10157d7c63
commit 18c80b075b
2 changed files with 30 additions and 34 deletions

View File

@@ -2,28 +2,30 @@
namespace Database\Seeders; namespace Database\Seeders;
use App\Domains\Catalog\Enums\InventoryPolicy;
use App\Domains\Catalog\Models\Attribute;
use App\Domains\Catalog\Models\Category; use App\Domains\Catalog\Models\Category;
use App\Domains\Catalog\Models\Product;
use App\Domains\Catalog\Services\ProductService; use App\Domains\Catalog\Services\ProductService;
use App\Domains\Tenant\Models\Tenant; use App\Domains\Tenant\Models\Tenant;
use Illuminate\Database\Seeder; use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
use RuntimeException; use RuntimeException;
class FiestaFutbolInfantilProductSeeder extends Seeder class FiestaFutbolInfantilProductSeeder extends Seeder
{ {
public function __construct(private readonly ProductService $productService) public function __construct(private readonly ProductService $productService) {}
{
}
public function run(): void public function run(): void
{ {
$tenant = Tenant::query()->where('codigo', 'fiesta_futbol_infantil')->first(); $tenant = Tenant::query()->where('codigo', 'fiesta_futbol_infantil')->first();
if (!$tenant) { if (! $tenant) {
throw new RuntimeException("Tenant 'fiesta_futbol_infantil' no encontrado."); throw new RuntimeException("Tenant 'fiesta_futbol_infantil' no encontrado.");
} }
// Delete existing products for this tenant // Delete existing products for this tenant
$existingProducts = \App\Domains\Catalog\Models\Product::query() $existingProducts = Product::query()
->where('tenant_codigo', $tenant->codigo) ->where('tenant_codigo', $tenant->codigo)
->get(); ->get();
@@ -43,30 +45,32 @@ class FiestaFutbolInfantilProductSeeder extends Seeder
'nombre' => 'Entrada General', 'nombre' => 'Entrada General',
'descripcion' => 'Acceso total al predio. No incluye acceso a estacionamiento. Niños menores de 5 años ingresan gratis.', 'descripcion' => 'Acceso total al predio. No incluye acceso a estacionamiento. Niños menores de 5 años ingresan gratis.',
'precio' => 10000, 'precio' => 10000,
'stock' => null, 'stock' => 0,
'attribute_ids' => [\App\Domains\Catalog\Models\Attribute::where('codigo', 'fecha')->where('tenant_codigo', $tenant->codigo)->first()?->id], 'inventory_policy' => InventoryPolicy::Unlimited->value,
'attribute_ids' => [Attribute::where('codigo', 'fecha')->where('tenant_codigo', $tenant->codigo)->first()?->id],
]); ]);
foreach ($dates as $date) { foreach ($dates as $date) {
$this->productService->createVariant($entrada, [ $this->productService->createVariant($entrada, [
'stock' => null, 'stock' => 0,
'inventory_policy' => InventoryPolicy::Unlimited->value,
'has_tickets' => true, 'has_tickets' => true,
'minimum_use_date' => $date . ' 00:00:00', 'minimum_use_date' => $date.' 00:00:00',
'maximum_use_date' => $date . ' 23:59:59', 'maximum_use_date' => $date.' 23:59:59',
'definitions' => [ 'definitions' => [
[ [
'products_attribute_id' => \Illuminate\Support\Facades\DB::table('products_attributes') 'products_attribute_id' => DB::table('products_attributes')
->where('product_id', $entrada->id) ->where('product_id', $entrada->id)
->first()?->id, ->first()?->id,
'value' => $date, 'value' => $date,
] ],
], ],
]); ]);
} }
// Other products without variants // Other products without variants
$gastronomiaCategory = Category::firstOrCreate(['nombre' => 'Gastronomía', 'tenant_code' => null]); $gastronomiaCategory = Category::firstOrCreate(['nombre' => 'Gastronomía', 'tenant_code' => null]);
$simpleProducts = [ $simpleProducts = [
['slug' => 'hamburguesa-papa-frita', 'nombre' => 'Hamburguesa con papa frita', 'precio' => 8000, 'cat' => $gastronomiaCategory->id], ['slug' => 'hamburguesa-papa-frita', 'nombre' => 'Hamburguesa con papa frita', 'precio' => 8000, 'cat' => $gastronomiaCategory->id],
['slug' => 'pancho', 'nombre' => 'Pancho', 'precio' => 4000, 'cat' => $gastronomiaCategory->id], ['slug' => 'pancho', 'nombre' => 'Pancho', 'precio' => 4000, 'cat' => $gastronomiaCategory->id],
@@ -77,26 +81,15 @@ class FiestaFutbolInfantilProductSeeder extends Seeder
]; ];
foreach ($simpleProducts as $p) { foreach ($simpleProducts as $p) {
$prod = $this->productService->create($tenant, [ $this->productService->create($tenant, [
'categoria_id' => $p['cat'], 'categoria_id' => $p['cat'],
'slug' => $p['slug'], 'slug' => $p['slug'],
'nombre' => $p['nombre'], 'nombre' => $p['nombre'],
'descripcion' => $p['nombre'], 'descripcion' => $p['nombre'],
'precio' => $p['precio'], 'precio' => $p['precio'],
'stock' => null, 'stock' => 0,
'inventory_policy' => InventoryPolicy::Unlimited->value,
]); ]);
// To ensure the variant gets stock null and has_tickets if needed.
// The default placeholder variant is created by ProductService::create with the given stock.
// But if we want stock=null, we should update the variant.
$variant = $prod->variants()->first();
if ($variant) {
$variant->stock = null;
$variant->save();
}
} }
// Also update the stock to null for the placeholder variant of Entrada General (or delete it, since we created specific variants)
// Actually ProductService deletes placeholder variants if we add a variant with definitions!
} }
} }

View File

@@ -2,6 +2,7 @@
namespace Database\Seeders; namespace Database\Seeders;
use App\Domains\Catalog\Enums\InventoryPolicy;
use App\Domains\Catalog\Models\Attribute; use App\Domains\Catalog\Models\Attribute;
use App\Domains\Catalog\Models\Brand; use App\Domains\Catalog\Models\Brand;
use App\Domains\Catalog\Models\Category; use App\Domains\Catalog\Models\Category;
@@ -64,9 +65,7 @@ class ProductCatalogFromImagesSeeder extends Seeder
'istockphoto-1675347112-2048x2048.jpg', 'istockphoto-1675347112-2048x2048.jpg',
]; ];
public function __construct(private readonly ProductService $productService) public function __construct(private readonly ProductService $productService) {}
{
}
/** /**
* Run the database seeds. * Run the database seeds.
@@ -162,9 +161,9 @@ class ProductCatalogFromImagesSeeder extends Seeder
} }
/** /**
* @param array{attribute_codes: array<int, string>, brand_name: string|null, category_name: string, color: string|null, description: string, product_name: string, product_slug: string, type: string} $metadata * @param array{attribute_codes: array<int, string>, brand_name: string|null, category_name: string, color: string|null, description: string, product_name: string, product_slug: string, type: string} $metadata
* @param array{price: int} $pricing * @param array{price: int} $pricing
* @param array<int, array{files: array<int, \SplFileInfo>, group_key: string, metadata: array{attribute_codes: array<int, string>, brand_name: string|null, category_name: string, color: string|null, description: string, product_name: string, product_slug: string, type: string}, stock: int}> $variantGroups * @param array<int, array{files: array<int, \SplFileInfo>, group_key: string, metadata: array{attribute_codes: array<int, string>, brand_name: string|null, category_name: string, color: string|null, description: string, product_name: string, product_slug: string, type: string}, stock: int}> $variantGroups
*/ */
private function seedProduct(Tenant $tenant, array $metadata, array $pricing, array $variantGroups): void private function seedProduct(Tenant $tenant, array $metadata, array $pricing, array $variantGroups): void
{ {
@@ -206,6 +205,7 @@ class ProductCatalogFromImagesSeeder extends Seeder
'nombre' => $metadata['product_name'], 'nombre' => $metadata['product_name'],
'descripcion' => $metadata['description'], 'descripcion' => $metadata['description'],
'precio' => $pricing['price'], 'precio' => $pricing['price'],
'inventory_policy' => InventoryPolicy::Tracked->value,
'attribute_ids' => array_values($attributeIds->all()), 'attribute_ids' => array_values($attributeIds->all()),
]); ]);
@@ -226,9 +226,11 @@ class ProductCatalogFromImagesSeeder extends Seeder
if ($attributeIds->isEmpty()) { if ($attributeIds->isEmpty()) {
$this->productService->createVariant($product, [ $this->productService->createVariant($product, [
'stock' => $variantGroup['stock'], 'stock' => $variantGroup['stock'],
'inventory_policy' => InventoryPolicy::Tracked->value,
'definitions' => [], 'definitions' => [],
'images' => $images, 'images' => $images,
]); ]);
continue; continue;
} }
@@ -280,6 +282,7 @@ class ProductCatalogFromImagesSeeder extends Seeder
$this->productService->createVariant($product, [ $this->productService->createVariant($product, [
'stock' => $stock, 'stock' => $stock,
'inventory_policy' => InventoryPolicy::Tracked->value,
'definitions' => $definitions, 'definitions' => $definitions,
'images' => $images, 'images' => $images,
]); ]);
@@ -288,7 +291,7 @@ class ProductCatalogFromImagesSeeder extends Seeder
} }
/** /**
* @param array<int, array{files: array<int, \SplFileInfo>, group_key: string, metadata: array{attribute_codes: array<int, string>, brand_name: string|null, category_name: string, color: string|null, description: string, product_name: string, product_slug: string, type: string}, stock: int}> $variantGroups * @param array<int, array{files: array<int, \SplFileInfo>, group_key: string, metadata: array{attribute_codes: array<int, string>, brand_name: string|null, category_name: string, color: string|null, description: string, product_name: string, product_slug: string, type: string}, stock: int}> $variantGroups
* @return array{attribute_codes: array<int, string>, brand_name: string|null, category_name: string, color: string|null, description: string, product_name: string, product_slug: string, type: string} * @return array{attribute_codes: array<int, string>, brand_name: string|null, category_name: string, color: string|null, description: string, product_name: string, product_slug: string, type: string}
*/ */
private function buildProductMetadata(string $productKey, array $variantGroups): array private function buildProductMetadata(string $productKey, array $variantGroups): array