*/ public function toArray(Request $request): array { /** @var Buyable|null $buyable */ $buyable = $this->buyable; $quantity = (int) ($this->cantidad ?? 0); $unitPrice = $this->resolveUnitPrice(); $lineTotal = $this->resolveLineTotal($unitPrice, $quantity); $variant = $buyable instanceof ProductVariant ? $buyable : null; $imageUrl = null; $attributes = []; if ($this->buyable_type === ProductVariant::class && $buyable) { $imageUrl = $this->resolveImageUrl($buyable); $attributes = $this->resolveAttributes($buyable); } return [ 'id' => $this->id, 'quantity' => $quantity, 'unit_price' => $this->formatMoney($unitPrice), 'line_total' => $this->formatMoney($lineTotal), 'buyable_type' => $this->mapBuyableTypeToAlias($this->buyable_type), 'buyable_id' => $this->buyable_id, 'product' => $variant === null ? null : [ 'id' => $variant->product?->id, 'nombre' => $variant->product?->nombre, 'slug' => $variant->product?->slug, 'imagen' => $imageUrl, ], 'variant' => $variant === null ? null : [ 'id' => $variant->id, 'attributes' => $attributes, ], 'item_details' => $buyable === null ? null : [ 'nombre' => $buyable->getName(), 'imagen' => $imageUrl, 'attributes' => $attributes, ], ]; } protected function mapBuyableTypeToAlias(?string $type): string { return match ($type) { ProductVariant::class => 'variant', Bundle::class => 'bundle', default => 'unknown', }; } protected function resolveUnitPrice(): float { if ($this->resource instanceof PurchaseItem) { return (float) ($this->precio_unitario ?? 0); } if ($this->resource instanceof CartItem) { return (float) ($this->buyable?->getPrice() ?? 0); } return 0.0; } protected function resolveLineTotal(float $unitPrice, int $quantity): float { if ($this->resource instanceof PurchaseItem) { return (float) ($this->total ?? 0); } return $unitPrice * $quantity; } protected function resolveImageUrl($buyable): ?string { if (! $buyable->relationLoaded('attachments')) { return null; } $attachment = $buyable->attachments->first(); if ($attachment === null) { return null; } return $attachment->getTemporaryUrl(1440); } /** * @return array */ protected function resolveAttributes($buyable): array { if (! $buyable->relationLoaded('definitions')) { return []; } return $buyable->definitions ->map(function ($definition): array { return [ 'name' => (string) ($definition->productAttribute?->attribute?->nombre ?? ''), 'value' => $definition->value, ]; }) ->filter(fn (array $attribute): bool => $attribute['name'] !== '' || $attribute['value'] !== null) ->values() ->all(); } protected function formatMoney(float|int|string|null $amount): ?string { if ($amount === null) { return null; } return number_format((float) $amount, 2, '.', ''); } }