feat: update product and variant resources to improve variant selection handling and response structure
This commit is contained in:
@@ -59,7 +59,7 @@ class ProductController extends Controller
|
|||||||
protected function resolveScopedProduct(Tenant $tenant, Product $product): Product
|
protected function resolveScopedProduct(Tenant $tenant, Product $product): Product
|
||||||
{
|
{
|
||||||
if ($product->tenant_codigo !== $tenant->codigo) {
|
if ($product->tenant_codigo !== $tenant->codigo) {
|
||||||
throw new NotFoundHttpException('Product not found for tenant.');
|
throw new NotFoundHttpException('Product not found.');
|
||||||
}
|
}
|
||||||
|
|
||||||
return $product;
|
return $product;
|
||||||
|
|||||||
@@ -34,19 +34,7 @@ class ProductResource extends JsonResource
|
|||||||
'variants' => ProductVariantResource::collection($this->whenLoaded('variants')),
|
'variants' => ProductVariantResource::collection($this->whenLoaded('variants')),
|
||||||
'variant' => $this->when(
|
'variant' => $this->when(
|
||||||
$this->getSelectedVariant() !== null,
|
$this->getSelectedVariant() !== null,
|
||||||
function () {
|
fn () => ProductVariantResource::make($this->getSelectedVariant())
|
||||||
$selectedVariant = $this->getSelectedVariant();
|
|
||||||
|
|
||||||
return [
|
|
||||||
'variant_id' => $selectedVariant->id,
|
|
||||||
'images' => $selectedVariant->attachments->isNotEmpty()
|
|
||||||
? $selectedVariant->attachments->map(fn ($attachment) => $attachment->getTemporaryUrl(1440))->values()
|
|
||||||
: $this->attachments->map(fn ($attachment) => $attachment->getTemporaryUrl(1440))->values(),
|
|
||||||
'attributes' => $selectedVariant->definitions->mapWithKeys(function ($definition) {
|
|
||||||
return [$definition->productAttribute?->attribute?->codigo => $definition->value];
|
|
||||||
})->toArray(),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,10 +17,17 @@ class ProductVariantResource extends JsonResource
|
|||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'id' => $this->id,
|
'id' => $this->id,
|
||||||
'producto_id' => $this->producto_id,
|
|
||||||
'stock' => $this->stock,
|
'stock' => $this->stock,
|
||||||
'product' => ProductResource::make($this->whenLoaded('product')),
|
'product' => ProductResource::make($this->whenLoaded('product')),
|
||||||
'definitions' => ProductVariantDefinitionResource::collection($this->whenLoaded('definitions')),
|
'definitions' => $this->whenLoaded(
|
||||||
|
'definitions',
|
||||||
|
fn () => $this->definitions
|
||||||
|
->mapWithKeys(fn ($definition) => [
|
||||||
|
$definition->productAttribute?->attribute?->codigo => $definition->value,
|
||||||
|
])
|
||||||
|
->filter(fn ($value, $key) => $key !== null)
|
||||||
|
->toArray()
|
||||||
|
),
|
||||||
'images' => $this->whenLoaded('attachments', function () {
|
'images' => $this->whenLoaded('attachments', function () {
|
||||||
if ($this->attachments->isNotEmpty()) {
|
if ($this->attachments->isNotEmpty()) {
|
||||||
return $this->attachments
|
return $this->attachments
|
||||||
|
|||||||
@@ -286,6 +286,7 @@ class ProductService
|
|||||||
'brand',
|
'brand',
|
||||||
'category',
|
'category',
|
||||||
'attributes.options',
|
'attributes.options',
|
||||||
|
'variants.definitions.productAttribute.attribute.options',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$selectedVariantQuery = $product->variants()
|
$selectedVariantQuery = $product->variants()
|
||||||
|
|||||||
@@ -389,7 +389,7 @@ class ProductControllerTest extends TestCase
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function test_it_returns_product_detail_with_variants_and_default_variant(): void
|
public function test_it_returns_product_detail_with_variants_and_selected_variant_resource(): void
|
||||||
{
|
{
|
||||||
// 1. Create a product
|
// 1. Create a product
|
||||||
$product = Product::create([
|
$product = Product::create([
|
||||||
@@ -436,26 +436,36 @@ class ProductControllerTest extends TestCase
|
|||||||
|
|
||||||
$response->assertOk();
|
$response->assertOk();
|
||||||
|
|
||||||
// 4. Assert default_variant structure and data
|
// 4. Assert selected variant resource structure and data
|
||||||
$response->assertJsonStructure([
|
$response->assertJsonStructure([
|
||||||
'data' => [
|
'data' => [
|
||||||
'id',
|
'id',
|
||||||
'nombre',
|
'nombre',
|
||||||
'default_variant' => [
|
'variant' => [
|
||||||
'variant_id',
|
'id',
|
||||||
|
'producto_id',
|
||||||
|
'stock',
|
||||||
'images',
|
'images',
|
||||||
'attributes' => [
|
'definitions' => [
|
||||||
'talle',
|
'*' => [
|
||||||
'color',
|
'id',
|
||||||
|
'producto_variante_id',
|
||||||
|
'products_attribute_id',
|
||||||
|
'attribute_id',
|
||||||
|
'value',
|
||||||
|
'attribute',
|
||||||
|
'metadata',
|
||||||
|
],
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$response->assertJsonPath('data.default_variant.variant_id', $variant->id);
|
$response->assertJsonPath('data.variant.id', $variant->id);
|
||||||
$response->assertJsonPath('data.default_variant.attributes.talle', 'S');
|
$response->assertJsonPath('data.variant.producto_id', $product->id);
|
||||||
$response->assertJsonPath('data.default_variant.attributes.color', 'Azul');
|
$response->assertJsonPath('data.variant.stock', 10);
|
||||||
$response->assertJsonCount(1, 'data.default_variant.images');
|
$response->assertJsonCount(1, 'data.variant.images');
|
||||||
|
$response->assertJsonCount(2, 'data.variant.definitions');
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function createTenant(string $codigo, string $nombre, string $dominio): Tenant
|
protected function createTenant(string $codigo, string $nombre, string $dominio): Tenant
|
||||||
|
|||||||
Reference in New Issue
Block a user