feat: refactor cart and purchase handling to support polymorphic buyable types and improve code readability
This commit is contained in:
@@ -2,11 +2,11 @@
|
||||
|
||||
namespace App\Domains\Cart\Controllers;
|
||||
|
||||
use App\Domains\Cart\Models\CartItem;
|
||||
use App\Domains\Cart\Requests\AddCartItemRequest;
|
||||
use App\Domains\Cart\Requests\UpdateCartItemQuantityRequest;
|
||||
use App\Domains\Cart\Resources\CartResource;
|
||||
use App\Domains\Cart\Services\CartService;
|
||||
use App\Domains\Catalog\Models\ProductVariant;
|
||||
use App\Domains\Tenant\Models\Tenant;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
@@ -16,8 +16,7 @@ class CartController extends Controller
|
||||
{
|
||||
public function __construct(
|
||||
protected CartService $cartService,
|
||||
) {
|
||||
}
|
||||
) {}
|
||||
|
||||
public function show(Request $request, Tenant $tenant): CartResource
|
||||
{
|
||||
@@ -48,7 +47,7 @@ class CartController extends Controller
|
||||
public function updateItemQuantity(
|
||||
UpdateCartItemQuantityRequest $request,
|
||||
Tenant $tenant,
|
||||
\App\Domains\Cart\Models\CartItem $cartItem,
|
||||
CartItem $cartItem,
|
||||
): CartResource {
|
||||
return CartResource::make(
|
||||
$this->cartService->updateItemQuantity(
|
||||
@@ -60,7 +59,7 @@ class CartController extends Controller
|
||||
)->additional(['message' => 'Cantidad de producto actualizada.']);
|
||||
}
|
||||
|
||||
public function removeItem(Request $request, Tenant $tenant, \App\Domains\Cart\Models\CartItem $cartItem): CartResource
|
||||
public function removeItem(Request $request, Tenant $tenant, CartItem $cartItem): CartResource
|
||||
{
|
||||
return CartResource::make(
|
||||
$this->cartService->removeItem($tenant, $request, $cartItem->getKey())
|
||||
|
||||
@@ -2,7 +2,10 @@
|
||||
|
||||
namespace App\Domains\Cart\Requests;
|
||||
|
||||
use App\Domains\Bundle\Models\Bundle;
|
||||
use App\Domains\Catalog\Models\ProductVariant;
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
class AddCartItemRequest extends FormRequest
|
||||
{
|
||||
@@ -17,7 +20,7 @@ class AddCartItemRequest extends FormRequest
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'buyable_type' => ['required', 'string', \Illuminate\Validation\Rule::in(['variant', 'bundle'])],
|
||||
'buyable_type' => ['required', 'string', Rule::in(['variant', 'bundle'])],
|
||||
'buyable_id' => ['required', 'integer'],
|
||||
'cantidad' => ['required', 'integer', 'min:1'],
|
||||
];
|
||||
@@ -26,8 +29,8 @@ class AddCartItemRequest extends FormRequest
|
||||
public function mappedBuyableType(): string
|
||||
{
|
||||
return match ($this->input('buyable_type')) {
|
||||
'variant' => \App\Domains\Catalog\Models\ProductVariant::class,
|
||||
'bundle' => \App\Domains\Bundle\Models\Bundle::class,
|
||||
'variant' => ProductVariant::class,
|
||||
'bundle' => Bundle::class,
|
||||
default => throw new \InvalidArgumentException('Invalid buyable type'),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -18,6 +18,8 @@ class UpdateCartItemQuantityRequest extends FormRequest
|
||||
{
|
||||
return [
|
||||
'cantidad' => ['required', 'integer', 'min:1'],
|
||||
'buyable_type' => ['prohibited'],
|
||||
'buyable_id' => ['prohibited'],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,11 +2,12 @@
|
||||
|
||||
namespace App\Domains\Cart\Resources;
|
||||
|
||||
use App\Domains\Cart\Models\Cart;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Resources\Json\JsonResource;
|
||||
|
||||
/**
|
||||
* @mixin \App\Domains\Cart\Models\Cart
|
||||
* @mixin Cart
|
||||
*/
|
||||
class CartResource extends JsonResource
|
||||
{
|
||||
@@ -20,7 +21,7 @@ class CartResource extends JsonResource
|
||||
: collect();
|
||||
|
||||
$subtotal = $items->reduce(
|
||||
fn (float $carry, $item): float => $carry + ((float) ($item->variant?->product?->precio ?? 0) * $item->cantidad),
|
||||
fn (float $carry, $item): float => $carry + ((float) ($item->buyable?->getPrice() ?? 0) * $item->cantidad),
|
||||
0.0,
|
||||
);
|
||||
|
||||
|
||||
@@ -2,10 +2,14 @@
|
||||
|
||||
namespace App\Domains\Cart\Services;
|
||||
|
||||
use App\Domains\Cart\Models\Cart;
|
||||
use App\Domains\Auth\Models\User;
|
||||
use App\Domains\Bundle\Models\Bundle;
|
||||
use App\Domains\Cart\Models\Cart;
|
||||
use App\Domains\Catalog\Models\ProductVariant;
|
||||
use App\Domains\Tenant\Models\Tenant;
|
||||
use Illuminate\Database\Eloquent\Relations\MorphTo;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Str;
|
||||
use Symfony\Component\HttpFoundation\Cookie;
|
||||
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||
@@ -93,9 +97,16 @@ class CartService
|
||||
protected function loadCart(Cart $cart): Cart
|
||||
{
|
||||
return $cart->fresh()->load([
|
||||
'items.variant.product',
|
||||
'items.variant.definitions.productAttribute.attribute',
|
||||
'items.variant.attachments',
|
||||
'items.buyable' => function (MorphTo $morphTo): void {
|
||||
$morphTo->morphWith([
|
||||
ProductVariant::class => [
|
||||
'product',
|
||||
'definitions.productAttribute.attribute',
|
||||
'attachments',
|
||||
],
|
||||
Bundle::class => ['items.variant'],
|
||||
]);
|
||||
},
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -104,7 +115,7 @@ class CartService
|
||||
*/
|
||||
protected function resolveIdentity(Request $request, bool $generateGuestToken = false): ?array
|
||||
{
|
||||
$user = $request->user() ?? \Illuminate\Support\Facades\Auth::guard('sanctum')->user();
|
||||
$user = $request->user() ?? Auth::guard('sanctum')->user();
|
||||
|
||||
if ($user instanceof User) {
|
||||
return [
|
||||
@@ -201,5 +212,4 @@ class CartService
|
||||
|
||||
return Cart::query()->firstOrCreate($attributes, ['status' => 'active']);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user