feat: implement multi-tenant cart functionality and add image validation helper

This commit is contained in:
ncoronel 2026-07-01 15:38:12 -03:00
parent 3285015841
commit 4943e68606
5 changed files with 69 additions and 17 deletions

View File

@ -48,6 +48,7 @@ class CartItemResource extends JsonResource
'cantidad' => $this->cantidad, 'cantidad' => $this->cantidad,
'precio_unitario' => $this->formatMoney($product?->precio), 'precio_unitario' => $this->formatMoney($product?->precio),
'product_id' => $product?->id, 'product_id' => $product?->id,
'product_variant_id' => $this->producto_variante_id,
'product' => $product === null ? null : [ 'product' => $product === null ? null : [
'nombre' => $productName, 'nombre' => $productName,
'imagen' => $imageUrl, 'imagen' => $imageUrl,

View File

@ -21,6 +21,10 @@ class ImageOrBase64Rule implements ValidationRule
if (is_string($value)) { if (is_string($value)) {
$payload = trim($value); $payload = trim($value);
if (\Illuminate\Support\Str::isUuid($payload)) {
return;
}
if ($payload === '') { if ($payload === '') {
$fail("The :attribute must not be empty."); $fail("The :attribute must not be empty.");
return; return;

View File

@ -13,7 +13,9 @@ return Application::configure(basePath: dirname(__DIR__))
health: '/up', health: '/up',
) )
->withMiddleware(function (Middleware $middleware): void { ->withMiddleware(function (Middleware $middleware): void {
// $middleware->encryptCookies(except: [
'guest_token',
]);
}) })
->withExceptions(function (Exceptions $exceptions): void { ->withExceptions(function (Exceptions $exceptions): void {
$exceptions->shouldRenderJsonWhen( $exceptions->shouldRenderJsonWhen(

Binary file not shown.

View File

@ -72,7 +72,7 @@ class CartControllerTest extends TestCase
$this->assertDatabaseHas('carritos', [ $this->assertDatabaseHas('carritos', [
'tenant_codigo' => 'acme', 'tenant_codigo' => 'acme',
'guest_token' => $response->getCookie('guest_token')?->getValue(), 'guest_token' => $response->getCookie('guest_token', false)?->getValue(),
'status' => 'active', 'status' => 'active',
]); ]);
@ -96,13 +96,22 @@ class CartControllerTest extends TestCase
'cantidad' => 2, 'cantidad' => 2,
]); ]);
$guestToken = $firstResponse->getCookie('guest_token')?->getValue(); $guestToken = $firstResponse->getCookie('guest_token', false)?->getValue();
$this->withCookie('guest_token', $guestToken) $response = $this->call(
->postJson('/api/tenants/acme/cart/items', [ 'POST',
'/api/tenants/acme/cart/items',
[],
['guest_token' => $guestToken],
[],
['HTTP_Accept' => 'application/json', 'CONTENT_TYPE' => 'application/json'],
json_encode([
'product_variant_id' => $variant->id, 'product_variant_id' => $variant->id,
'cantidad' => 3, 'cantidad' => 3,
]) ])
);
$response
->assertOk() ->assertOk()
->assertJsonPath('data.items.0.cantidad', 5) ->assertJsonPath('data.items.0.cantidad', 5)
->assertJsonPath('data.subtotal', '125.00'); ->assertJsonPath('data.subtotal', '125.00');
@ -128,12 +137,21 @@ class CartControllerTest extends TestCase
'cantidad' => 2, 'cantidad' => 2,
]); ]);
$guestToken = $createResponse->getCookie('guest_token')?->getValue(); $guestToken = $createResponse->getCookie('guest_token', false)?->getValue();
$this->withCookie('guest_token', $guestToken) $response = $this->call(
->patchJson("/api/tenants/acme/cart/items/{$variant->id}", [ 'PATCH',
"/api/tenants/acme/cart/items/{$variant->id}",
[],
['guest_token' => $guestToken],
[],
['HTTP_Accept' => 'application/json', 'CONTENT_TYPE' => 'application/json'],
json_encode([
'cantidad' => 5, 'cantidad' => 5,
]) ])
);
$response
->assertOk() ->assertOk()
->assertJsonPath('data.items.0.cantidad', 5) ->assertJsonPath('data.items.0.cantidad', 5)
->assertJsonPath('data.subtotal', '75.00'); ->assertJsonPath('data.subtotal', '75.00');
@ -157,10 +175,18 @@ class CartControllerTest extends TestCase
'cantidad' => 4, 'cantidad' => 4,
]); ]);
$guestToken = $createResponse->getCookie('guest_token')?->getValue(); $guestToken = $createResponse->getCookie('guest_token', false)?->getValue();
$this->withCookie('guest_token', $guestToken) $response = $this->call(
->deleteJson("/api/tenants/acme/cart/items/{$variant->id}") 'DELETE',
"/api/tenants/acme/cart/items/{$variant->id}",
[],
['guest_token' => $guestToken],
[],
['HTTP_Accept' => 'application/json', 'CONTENT_TYPE' => 'application/json']
);
$response
->assertOk() ->assertOk()
->assertJsonPath('data.items', []) ->assertJsonPath('data.items', [])
->assertJsonPath('data.subtotal', '0.00'); ->assertJsonPath('data.subtotal', '0.00');
@ -249,20 +275,38 @@ class CartControllerTest extends TestCase
'cantidad' => 2, 'cantidad' => 2,
]); ]);
$guestToken = $response->getCookie('guest_token')?->getValue(); $guestToken = $response->getCookie('guest_token', false)?->getValue();
$this->withCookie('guest_token', $guestToken) $response1 = $this->call(
->postJson('/api/tenants/acme/cart/items', [ 'POST',
'/api/tenants/acme/cart/items',
[],
['guest_token' => $guestToken],
[],
['HTTP_Accept' => 'application/json', 'CONTENT_TYPE' => 'application/json'],
json_encode([
'product_variant_id' => $variant->id, 'product_variant_id' => $variant->id,
'cantidad' => 1, 'cantidad' => 1,
]) ])
);
$response1
->assertUnprocessable() ->assertUnprocessable()
->assertJsonValidationErrors(['cantidad']); ->assertJsonValidationErrors(['cantidad']);
$this->withCookie('guest_token', $guestToken) $response2 = $this->call(
->patchJson("/api/tenants/acme/cart/items/{$variant->id}", [ 'PATCH',
"/api/tenants/acme/cart/items/{$variant->id}",
[],
['guest_token' => $guestToken],
[],
['HTTP_Accept' => 'application/json', 'CONTENT_TYPE' => 'application/json'],
json_encode([
'cantidad' => 3, 'cantidad' => 3,
]) ])
);
$response2
->assertUnprocessable() ->assertUnprocessable()
->assertJsonValidationErrors(['cantidad']); ->assertJsonValidationErrors(['cantidad']);
} }
@ -330,7 +374,8 @@ class CartControllerTest extends TestCase
'secondary_color' => '#222222', 'secondary_color' => '#222222',
'danger_color' => '#333333', 'danger_color' => '#333333',
'success_color' => '#28a745', 'success_color' => '#28a745',
'header_footer_bg_color' => '#444444', 'header_bg_color' => '#444444',
'footer_bg_color' => '#444444',
'header_logo_id' => $headerAttachment->id, 'header_logo_id' => $headerAttachment->id,
'footer_logo_id' => $footerAttachment->id, 'footer_logo_id' => $footerAttachment->id,
]); ]);