feat: update product resource and seeder to support variant groups and remove unused fields
This commit is contained in:
@@ -17,7 +17,7 @@ use RuntimeException;
|
||||
class ProductCatalogFromImagesSeeder extends Seeder
|
||||
{
|
||||
/**
|
||||
* @var array<string, array{price: int, stock: int}>
|
||||
* @var array<string, array{price: int, stock?: int, variant_groups?: array<string, array{stock: int}>}>
|
||||
*/
|
||||
private const PRODUCT_CATALOG = [
|
||||
'buzo_blanco_adidas' => ['price' => 89999, 'stock' => 12],
|
||||
@@ -25,10 +25,20 @@ class ProductCatalogFromImagesSeeder extends Seeder
|
||||
'buzo_gris_under_armour' => ['price' => 96999, 'stock' => 8],
|
||||
'buzo_negro_adidas' => ['price' => 91999, 'stock' => 9],
|
||||
'camiseta_rosario_central' => ['price' => 69999, 'stock' => 20],
|
||||
'pantalon_blanco' => ['price' => 55999, 'stock' => 14],
|
||||
'pantalon_negro' => ['price' => 57999, 'stock' => 14],
|
||||
'remera_blanca' => ['price' => 35999, 'stock' => 22],
|
||||
'remera_negra' => ['price' => 36999, 'stock' => 22],
|
||||
'pantalon' => [
|
||||
'price' => 55999,
|
||||
'variant_groups' => [
|
||||
'pantalon_blanco' => ['stock' => 14],
|
||||
'pantalon_negro' => ['stock' => 14],
|
||||
],
|
||||
],
|
||||
'remera' => [
|
||||
'price' => 35999,
|
||||
'variant_groups' => [
|
||||
'remera_blanca' => ['stock' => 22],
|
||||
'remera_negra' => ['stock' => 22],
|
||||
],
|
||||
],
|
||||
'zapatillas_lecoq' => ['price' => 109999, 'stock' => 6],
|
||||
'zapatillas_topper' => ['price' => 104999, 'stock' => 7],
|
||||
];
|
||||
@@ -84,28 +94,52 @@ class ProductCatalogFromImagesSeeder extends Seeder
|
||||
});
|
||||
|
||||
$productsToSeed = collect(self::PRODUCT_CATALOG)
|
||||
->map(function (array $pricing, string $groupKey) use ($groupedFiles, $tenant): array {
|
||||
$filesForGroup = $groupedFiles->get($groupKey);
|
||||
|
||||
if ($filesForGroup === null || $filesForGroup->isEmpty()) {
|
||||
throw new RuntimeException("No images found for catalog group '{$groupKey}'.");
|
||||
->map(function (array $catalogConfig, string $productKey) use ($groupedFiles): array {
|
||||
if (! isset($catalogConfig['variant_groups']) && ! array_key_exists('stock', $catalogConfig)) {
|
||||
throw new RuntimeException("Missing stock configuration for catalog product '{$productKey}'.");
|
||||
}
|
||||
|
||||
$metadata = $this->parseGroupKey($groupKey);
|
||||
$variantGroups = collect($catalogConfig['variant_groups'] ?? [
|
||||
$productKey => ['stock' => $catalogConfig['stock']],
|
||||
])
|
||||
->map(function (array $variantConfig, string $groupKey) use ($groupedFiles): array {
|
||||
$filesForGroup = $groupedFiles->get($groupKey);
|
||||
|
||||
if ($filesForGroup === null || $filesForGroup->isEmpty()) {
|
||||
throw new RuntimeException("No images found for catalog group '{$groupKey}'.");
|
||||
}
|
||||
|
||||
return [
|
||||
'group_key' => $groupKey,
|
||||
'stock' => $variantConfig['stock'],
|
||||
'files' => $filesForGroup->all(),
|
||||
'metadata' => $this->parseGroupKey($groupKey),
|
||||
];
|
||||
})
|
||||
->values()
|
||||
->all();
|
||||
|
||||
return [
|
||||
'group_key' => $groupKey,
|
||||
'pricing' => $pricing,
|
||||
'tenant' => $tenant,
|
||||
'files' => $filesForGroup->all(),
|
||||
'metadata' => $metadata,
|
||||
'pricing' => ['price' => $catalogConfig['price']],
|
||||
'metadata' => $this->buildProductMetadata($productKey, $variantGroups),
|
||||
'variant_groups' => $variantGroups,
|
||||
];
|
||||
})
|
||||
->values();
|
||||
|
||||
$productSlugsToDelete = $productsToSeed
|
||||
->flatMap(fn (array $catalogProduct): array => [
|
||||
$catalogProduct['metadata']['product_slug'],
|
||||
...collect($catalogProduct['variant_groups'])
|
||||
->pluck('group_key')
|
||||
->all(),
|
||||
])
|
||||
->unique()
|
||||
->values();
|
||||
|
||||
$existingProducts = Product::query()
|
||||
->where('tenant_codigo', $tenant->codigo)
|
||||
->whereIn('slug', $productsToSeed->pluck('metadata.product_slug'))
|
||||
->whereIn('slug', $productSlugsToDelete)
|
||||
->with(['attachments', 'variants.attachments'])
|
||||
->get();
|
||||
|
||||
@@ -118,17 +152,17 @@ class ProductCatalogFromImagesSeeder extends Seeder
|
||||
$tenant,
|
||||
$catalogProduct['metadata'],
|
||||
$catalogProduct['pricing'],
|
||||
$catalogProduct['files'],
|
||||
$catalogProduct['variant_groups'],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @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, stock: int} $pricing
|
||||
* @param array<int, \SplFileInfo> $files
|
||||
* @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
|
||||
*/
|
||||
private function seedProduct(Tenant $tenant, array $metadata, array $pricing, array $files): void
|
||||
private function seedProduct(Tenant $tenant, array $metadata, array $pricing, array $variantGroups): void
|
||||
{
|
||||
$brand = null;
|
||||
|
||||
@@ -175,38 +209,63 @@ class ProductCatalogFromImagesSeeder extends Seeder
|
||||
? self::SHOE_SIZES
|
||||
: self::CLOTHING_SIZES;
|
||||
|
||||
$images = array_map(
|
||||
fn (\SplFileInfo $file): UploadedFile => $this->createUploadedFile($file->getPathname()),
|
||||
$files
|
||||
);
|
||||
foreach ($variantGroups as $variantGroup) {
|
||||
$images = array_map(
|
||||
fn (\SplFileInfo $file): UploadedFile => $this->createUploadedFile($file->getPathname()),
|
||||
$variantGroup['files']
|
||||
);
|
||||
|
||||
foreach ($sizes as $size) {
|
||||
$definitions = [];
|
||||
foreach ($sizes as $size) {
|
||||
$definitions = [];
|
||||
|
||||
if (isset($attributeIds['color']) && $variantGroup['metadata']['color'] !== null) {
|
||||
$definitions[] = [
|
||||
'attribute_id' => $attributeIds['color'],
|
||||
'value' => $variantGroup['metadata']['color'],
|
||||
];
|
||||
}
|
||||
|
||||
$sizeAttributeCode = $metadata['type'] === 'zapatillas'
|
||||
? 'talle_numerico'
|
||||
: 'talle';
|
||||
|
||||
if (isset($attributeIds['color']) && $metadata['color'] !== null) {
|
||||
$definitions[] = [
|
||||
'attribute_id' => $attributeIds['color'],
|
||||
'value' => $metadata['color'],
|
||||
'attribute_id' => $attributeIds[$sizeAttributeCode],
|
||||
'value' => $size,
|
||||
];
|
||||
|
||||
$this->productService->createVariant($product, [
|
||||
'stock' => $variantGroup['stock'],
|
||||
'definitions' => $definitions,
|
||||
'images' => $images,
|
||||
]);
|
||||
}
|
||||
|
||||
$sizeAttributeCode = $metadata['type'] === 'zapatillas'
|
||||
? 'talle_numerico'
|
||||
: 'talle';
|
||||
|
||||
$definitions[] = [
|
||||
'attribute_id' => $attributeIds[$sizeAttributeCode],
|
||||
'value' => $size,
|
||||
];
|
||||
|
||||
$this->productService->createVariant($product, [
|
||||
'stock' => $pricing['stock'],
|
||||
'definitions' => $definitions,
|
||||
'images' => $images,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @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}
|
||||
*/
|
||||
private function buildProductMetadata(string $productKey, array $variantGroups): array
|
||||
{
|
||||
$metadata = $this->parseGroupKey($productKey);
|
||||
$hasColorVariants = collect($variantGroups)
|
||||
->contains(fn (array $variantGroup): bool => $variantGroup['metadata']['color'] !== null);
|
||||
|
||||
if ($hasColorVariants && ! in_array('color', $metadata['attribute_codes'], true)) {
|
||||
array_unshift($metadata['attribute_codes'], 'color');
|
||||
}
|
||||
|
||||
if ($hasColorVariants && $metadata['color'] === null) {
|
||||
$category = Str::lower($metadata['category_name']);
|
||||
$brandText = $metadata['brand_name'] !== null ? " {$metadata['brand_name']}" : '';
|
||||
$metadata['description'] = "Producto seed de {$category}{$brandText} con variantes por color y talle.";
|
||||
}
|
||||
|
||||
return $metadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* @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}
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user