feat: implement product and attribute management services with corresponding controllers and feature tests

This commit is contained in:
2026-06-29 11:37:22 -03:00
parent b5b57a753c
commit 9b7d728117
7 changed files with 365 additions and 137 deletions

View File

@@ -78,6 +78,23 @@ class AttributeControllerTest extends TestCase
->assertJsonValidationErrors(['options']);
}
public function test_it_throws_exception_when_creating_non_select_attribute_with_options_directly_on_model(): void
{
$tenant = $this->createTenant('acme2', 'Acme 2', 'acme2.com');
$this->expectException(\InvalidArgumentException::class);
$this->expectExceptionMessage('Options are only allowed for select and multiselect attributes.');
\App\Domains\Catalog\Models\Product::createAttribute($tenant, [
'codigo' => 'material2',
'nombre' => 'Material 2',
'type' => 'string',
'options' => [
['label' => 'Cotton', 'value' => 'cotton'],
],
]);
}
protected function createTenant(string $codigo, string $nombre, string $dominio): Tenant
{
$hdrKey = (string) \Illuminate\Support\Str::uuid();

View File

@@ -33,6 +33,10 @@ class ProductControllerTest extends TestCase
'is_required' => true,
'type' => 'select',
]);
$this->sizeAttr->options()->createMany([
['value' => 'S', 'label' => 'S'],
['value' => '38', 'label' => '38'],
]);
$this->colorAttr = Attribute::create([
'tenant_codigo' => $this->tenant->codigo,
@@ -41,6 +45,10 @@ class ProductControllerTest extends TestCase
'is_required' => true,
'type' => 'select',
]);
$this->colorAttr->options()->createMany([
['value' => 'Azul', 'label' => 'Azul'],
['value' => 'Rojo', 'label' => 'Rojo'],
]);
$this->extraAttr = Attribute::create([
'tenant_codigo' => $this->tenant->codigo,
@@ -340,6 +348,47 @@ class ProductControllerTest extends TestCase
$response->assertJsonValidationErrors(['definitions.0.attribute_id']);
}
public function test_it_throws_exception_when_variant_value_does_not_belong_to_attribute_options(): void
{
// 1. Create a select attribute with options
$selectAttr = Product::createAttribute($this->tenant, [
'codigo' => 'tamanho',
'nombre' => 'Tamanho',
'type' => 'select',
'options' => [
['value' => 'P', 'label' => 'Piqueno'],
['value' => 'M', 'label' => 'Medio'],
]
]);
// 2. Create product and associate attribute
$product = Product::create([
'tenant_codigo' => $this->tenant->codigo,
'categoria_id' => 1,
'slug' => 'test-prod-validation',
'nombre' => 'Test Prod Validation',
'precio' => 100.00,
]);
$product->attributes()->sync([$selectAttr->id]);
// 3. Expect exception when creating variant with invalid value 'G'
$this->expectException(\InvalidArgumentException::class);
$this->expectExceptionMessage("The value 'G' is not a valid option for the select attribute 'Tamanho'.");
$product->createVariant([
'slug' => 'test-prod-validation-g',
'nombre' => 'Test Prod Validation G',
'stock' => 5,
'precio' => 100.00,
'definitions' => [
[
'attribute_id' => $selectAttr->id,
'value' => 'G', // Invalid value
]
]
]);
}
protected function createTenant(string $codigo, string $nombre, string $dominio): Tenant
{
$hdrKey = (string) Str::uuid();