feat: implement product creation workflow with variants, attribute definitions, and validation logic
This commit is contained in:
@@ -2,7 +2,114 @@
|
||||
|
||||
namespace App\Domains\Catalog\Services;
|
||||
|
||||
use App\Domains\Catalog\Models\Product;
|
||||
use App\Domains\Tenant\Models\Tenant;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
class ProductService
|
||||
{
|
||||
// Reserved for product domain business logic.
|
||||
/**
|
||||
* Create a product along with its variants and variant definitions.
|
||||
*
|
||||
* @param array<string, mixed> $data
|
||||
*/
|
||||
public function createProductWithVariants(Tenant $tenant, array $data): Product
|
||||
{
|
||||
return DB::transaction(function () use ($tenant, $data) {
|
||||
$variantsData = $data['variants'] ?? [];
|
||||
unset($data['variants']);
|
||||
|
||||
$attributeIds = $data['attribute_ids'] ?? [];
|
||||
unset($data['attribute_ids']);
|
||||
|
||||
/** @var Product $product */
|
||||
$product = Product::query()->create([
|
||||
...$data,
|
||||
'tenant_codigo' => $tenant->codigo,
|
||||
]);
|
||||
|
||||
foreach ($variantsData as $variantData) {
|
||||
$definitions = $variantData['definitions'] ?? [];
|
||||
unset($variantData['definitions']);
|
||||
|
||||
$variant = $product->variants()->create($variantData);
|
||||
$variant->definitions()->createMany($definitions);
|
||||
}
|
||||
|
||||
$attributeIdsFromVariants = collect($variantsData)->flatMap(function ($variant) {
|
||||
return collect($variant['definitions'] ?? [])->pluck('attribute_id');
|
||||
})->unique()->toArray();
|
||||
|
||||
$allAttributeIds = array_unique(array_merge($attributeIds, $attributeIdsFromVariants));
|
||||
$product->attributes()->sync($allAttributeIds);
|
||||
|
||||
return $product->load(['variants.definitions.attribute', 'attributes']);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a product along with its variants and variant definitions.
|
||||
*
|
||||
* @param array<string, mixed> $data
|
||||
*/
|
||||
public function updateProductWithVariants(Product $product, array $data): Product
|
||||
{
|
||||
return DB::transaction(function () use ($product, $data) {
|
||||
$hasVariants = array_key_exists('variants', $data);
|
||||
$variantsData = $data['variants'] ?? [];
|
||||
unset($data['variants']);
|
||||
|
||||
$hasAttributeIds = array_key_exists('attribute_ids', $data);
|
||||
$attributeIds = $data['attribute_ids'] ?? [];
|
||||
unset($data['attribute_ids']);
|
||||
|
||||
$product->update($data);
|
||||
|
||||
if ($hasVariants) {
|
||||
$existingVariantIds = $product->variants()->pluck('id')->toArray();
|
||||
$incomingVariantIds = [];
|
||||
|
||||
foreach ($variantsData as $variantData) {
|
||||
$definitions = $variantData['definitions'] ?? [];
|
||||
unset($variantData['definitions']);
|
||||
|
||||
$variantId = $variantData['id'] ?? null;
|
||||
|
||||
if ($variantId && in_array($variantId, $existingVariantIds)) {
|
||||
$variant = $product->variants()->findOrFail($variantId);
|
||||
$variant->update($variantData);
|
||||
$incomingVariantIds[] = (int) $variantId;
|
||||
} else {
|
||||
$variant = $product->variants()->create($variantData);
|
||||
$incomingVariantIds[] = $variant->id;
|
||||
}
|
||||
|
||||
$variant->definitions()->delete();
|
||||
$variant->definitions()->createMany($definitions);
|
||||
}
|
||||
|
||||
$variantsToDelete = array_diff($existingVariantIds, $incomingVariantIds);
|
||||
if (!empty($variantsToDelete)) {
|
||||
$product->variants()->whereIn('id', $variantsToDelete)->delete();
|
||||
}
|
||||
}
|
||||
|
||||
if ($hasAttributeIds || $hasVariants) {
|
||||
$explicitIds = $hasAttributeIds ? $attributeIds : $product->attributes()->pluck('attribute_id')->toArray();
|
||||
|
||||
$variantIds = $product->variants()->pluck('id')->toArray();
|
||||
$attributeIdsFromVariants = DB::table('productos_variantes_values')
|
||||
->whereIn('producto_variante_id', $variantIds)
|
||||
->pluck('attribute_id')
|
||||
->unique()
|
||||
->toArray();
|
||||
|
||||
$allAttributeIds = array_unique(array_merge($explicitIds, $attributeIdsFromVariants));
|
||||
$product->attributes()->sync($allAttributeIds);
|
||||
}
|
||||
|
||||
return $product->load(['variants.definitions.attribute', 'attributes']);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user