From d6a17cb44998673ca2179c611d05ccdd7dce0096 Mon Sep 17 00:00:00 2001 From: ncoronel Date: Wed, 1 Jul 2026 10:02:26 -0300 Subject: [PATCH] feat: add is_default field to product variants and implement default variant management logic in ProductService --- app/Domains/Catalog/Models/ProductVariant.php | 2 ++ .../Catalog/Services/ProductService.php | 13 ++++++--- ...s_default_to_productos_variantes_table.php | 28 +++++++++++++++++++ .../Feature/Catalog/ProductControllerTest.php | 10 +++++-- 4 files changed, 47 insertions(+), 6 deletions(-) create mode 100644 database/migrations/2026_07_01_100000_add_is_default_to_productos_variantes_table.php diff --git a/app/Domains/Catalog/Models/ProductVariant.php b/app/Domains/Catalog/Models/ProductVariant.php index 559c0f2..abb481b 100644 --- a/app/Domains/Catalog/Models/ProductVariant.php +++ b/app/Domains/Catalog/Models/ProductVariant.php @@ -13,6 +13,7 @@ use Illuminate\Database\Eloquent\Relations\HasMany; #[Fillable([ 'producto_id', 'stock', + 'is_default', ])] class ProductVariant extends Model { @@ -25,6 +26,7 @@ class ProductVariant extends Model return [ 'producto_id' => 'integer', 'stock' => 'integer', + 'is_default' => 'boolean', ]; } diff --git a/app/Domains/Catalog/Services/ProductService.php b/app/Domains/Catalog/Services/ProductService.php index 063fbef..1df6c08 100644 --- a/app/Domains/Catalog/Services/ProductService.php +++ b/app/Domains/Catalog/Services/ProductService.php @@ -44,6 +44,7 @@ class ProductService // Create default variant with stock $this->createVariant($product, [ 'stock' => $stock, + 'is_default' => true, 'definitions' => [], ]); @@ -116,11 +117,14 @@ class ProductService $images = $data['images'] ?? []; unset($data['images']); - // If the variant being created has definitions, it is a real variant. - // Remove any default variants (those without definitions). + // Determine if the variant being created is a default one $hasDefinitions = ! empty($data['definitions']); - if ($hasDefinitions) { - $defaultVariants = $product->variants()->whereDoesntHave('definitions')->get(); + $isDefault = $data['is_default'] ?? (! $hasDefinitions); + $data['is_default'] = $isDefault; + + // If the variant being created is not a default variant, remove any existing default variants + if (! $isDefault) { + $defaultVariants = $product->variants()->where('is_default', true)->get(); foreach ($defaultVariants as $defaultVariant) { $this->deleteVariantAttachments($defaultVariant); $product->deleteVariant($defaultVariant); @@ -176,6 +180,7 @@ class ProductService if ($product->variants()->count() === 0) { $product->createVariant([ 'stock' => 0, + 'is_default' => true, 'definitions' => [], ]); } diff --git a/database/migrations/2026_07_01_100000_add_is_default_to_productos_variantes_table.php b/database/migrations/2026_07_01_100000_add_is_default_to_productos_variantes_table.php new file mode 100644 index 0000000..c88f72d --- /dev/null +++ b/database/migrations/2026_07_01_100000_add_is_default_to_productos_variantes_table.php @@ -0,0 +1,28 @@ +boolean('is_default')->default(false)->after('stock'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('productos_variantes', function (Blueprint $table) { + $table->dropColumn('is_default'); + }); + } +}; diff --git a/tests/Feature/Catalog/ProductControllerTest.php b/tests/Feature/Catalog/ProductControllerTest.php index f81017f..5688cd6 100644 --- a/tests/Feature/Catalog/ProductControllerTest.php +++ b/tests/Feature/Catalog/ProductControllerTest.php @@ -635,6 +635,7 @@ class ProductControllerTest extends TestCase $variant = $product->variants()->first(); $this->assertEquals(15, $variant->stock); + $this->assertTrue($variant->is_default); // Should have no definitions $this->assertEquals(0, $variant->definitions()->count()); } @@ -653,6 +654,7 @@ class ProductControllerTest extends TestCase $defaultVariant = $product->variants()->create([ 'stock' => 10, + 'is_default' => true, ]); $this->assertEquals(1, $product->variants()->count()); @@ -678,7 +680,9 @@ class ProductControllerTest extends TestCase // Only the new variant should remain $this->assertEquals(1, $product->variants()->count()); - $this->assertEquals(5, $product->variants()->first()->stock); + $newVariant = $product->variants()->first(); + $this->assertEquals(5, $newVariant->stock); + $this->assertFalse($newVariant->is_default); } public function test_it_restores_default_variant_when_all_variants_are_deleted(): void @@ -695,6 +699,7 @@ class ProductControllerTest extends TestCase $realVariant = $product->createVariant([ 'stock' => 5, + 'is_default' => false, 'definitions' => [ [ 'products_attribute_id' => $productAttributes['size']->id, @@ -709,10 +714,11 @@ class ProductControllerTest extends TestCase $response = $this->deleteJson("/api/tenants/{$this->tenant->codigo}/productos/{$product->id}/variants/{$realVariant->id}"); $response->assertNoContent(); - // A default variant should be recreated with stock 0 + // A default variant should be recreated with stock 0 and is_default = true $this->assertEquals(1, $product->variants()->count()); $defaultVariant = $product->variants()->first(); $this->assertEquals(0, $defaultVariant->stock); + $this->assertTrue($defaultVariant->is_default); $this->assertEquals(0, $defaultVariant->definitions()->count()); }