Saltar a contenido

Inventario de funcionalidades

Qué hace hoy el storefront, de la gestión de contenido a la operativa de venta. Es un inventario de lo implementado en este repositorio, no de lo que podría hacer Medusa. Donde la lógica vive en el backend se aclara.

Leyenda de origen: CMS = Payload · MED = Medusa V2 · ALG = Algolia · SF = lógica propia del storefront.


1. Gestión de contenido (Payload CMS)

El contenido editorial no está en el código: se arma en Payload y el storefront lo renderiza. Cliente en src/lib/payload.ts (login usuario/clave, JWT cacheado en memoria).

Funcionalidad Origen Dónde
Home editable — hero, bloques y grillas definidos en Payload CMS getHomepage()
Páginas por slug — cualquier página institucional en /{countryCode}/{slug} CMS getPageBySlug(), ruta [slug]/page.tsx
Menú de navegación principal — árbol de ítems con enlaces a categoría, colección, filtro o URL propia CMS navigation-service.ts (global main-navigation)
Header configurable CMS header-service.ts (global header)
Formularios dinámicos — definidos en Payload, con mensaje de confirmación y email de respuesta CMS getPayloadForm(), extractConfirmationMessage(), extractEmailMessage()
Renderizado de texto enriquecido (Lexical de Payload) SF modules/common/components/RichText/

Bloques de contenido soportados

Implementados en el renderizador de [slug]/page.tsx. Un blockType no contemplado se ignora en producción y avisa en pantalla en desarrollo.

hero · content · richText · mediaBlock (incluye modo fullscreen) · cta · banner · archive (por selección o por consulta) · formBlock / form · productGrid / cuadriculaProductos · slider / heroSlider

Los campos de formulario soportados son text, email, textarea, select y checkbox.


2. Catálogo y búsqueda

Conviven dos motores: Algolia para búsqueda y navegación filtrada, Medusa para categorías, colecciones y la ficha de producto.

Funcionalidad Origen Notas
Búsqueda con autocompletado ALG SearchBar, SearchModal, índice de query suggestions aparte
Grilla de tienda con InstantSearch ALG algolia-store-template, scroll infinito y paginación
Filtros facetados — sidebar de categorías, rango de precio, atributos ALG algolia-sidebar, algolia-store-filters, mobile-filter
Ordenamiento de resultados ALG refinement-list/sort-products
Filtros sincronizados con la URL SF parse-search-params.ts, enrutador de InstantSearch
Navegación por categorías MED categories/[...category], jerarquía anidada
Colecciones MED collections/[handle]
Tarjeta de producto con badge de descuento SF calcula sobre special_price / regular_price, y sobre el tipo OFERTA. Solo se muestra si supera el 5%, y se oculta si una etiqueta del CMS ocupa su esquina
Etiquetas de producto en la tarjeta CMS + ALG Texto, estilo, zona, orden y vigencia en la colección product-badges de Payload; se cruzan con los product_tags de Algolia. lib/product-badges.ts, product-badge. Contrato en el RF-008 del repo del CMS
Tarjeta sin prefetch SF El enlace de la tarjeta no precarga la ficha: en producción era un pedido al servidor, y a Medusa, por cada tarjeta visible. Ver ADR-0009

3. Ficha de producto

Funcionalidad Origen Notas
URL propia por variante — products/[handle]/[[...variantId]] SF Ruta opcional catch-all: se comparte el enlace de una variante concreta y la página abre con esa variante seleccionada
Galería de imágenes MED image-gallery
Selección de variantes con títulos y atributos SF variant-helpers.ts (variantOptionsToKeymap, variantHasStock)
Descripción por variante SF variant-description
Precio con precio especial y porcentaje de descuento SF product-price, get-precentage-diff.ts
Disponibilidad por sucursal SF product-availability: lee stock_aviadores y stock_multiplaza de la metadata de la variante y muestra stock en Aviadores del Chaco y Shopping Multiplaza
Pestañas de información MED product-tabs
Productos relacionados ALG related-products: misma categoría que el producto (metadata.category de Medusa), con stock, consultado desde el navegador con scroll infinito. Muestra también otras variantes del mismo producto
Simulador de cuotas SF Ver §8

4. Carrito

Funcionalidad Origen Notas
Alta, modificación y baja de líneas MED addToCart, updateLineItem, deleteLineItem
Carrito persistente por cookie MED _medusa_cart_id, HTTP-only
Códigos de promoción MED applyPromotions, removeDiscount, submitPromotionForm
Gift cards MED applyGiftCard, removeGiftCard
Nudge de envío gratis — cuánto falta para alcanzar el umbral SF free-shipping-price-nudge, calcula monto restante y porcentaje
Traspaso del carrito al iniciar sesión MED transferCart()
Cambio de región recalculando el carrito MED updateRegion()

5. Checkout

Flujo por pasos con ?step= en la URL: dirección → entrega → pago → revisión.

5.1 Direcciones y geografía

Funcionalidad Origen Notas
Selector de departamento y ciudad de Paraguay SF + MED department-select y city-select; las ciudades se filtran por el departamento elegido. Datos desde getGeoZones() (lib/data/geozones.ts)
Dirección de envío y de facturación por separado MED shipping-address, billing_address
Reutilización de direcciones guardadas MED address-select

5.2 Envíos y promesas de entrega

Es la parte con más lógica propia.

Funcionalidad Origen Notas
Envío a domicilio vs. retiro en sucursal SF + MED Se separan las opciones por service_zone.fulfillment_set.type === "pickup" y se presentan como dos grupos distintos
Promesa de entrega calculada por sucursal SF calculateMaxDeliveryTimes() en checkout/components/shipping/: recorre los ítems del carrito y toma el máximo tiempo de entrega. Para el proveedor interno (supplier_id = 1) usa t_entrega_aviadores y t_entrega_multi de la metadata de cada variante; para proveedores externos, t_entrega aplica a ambas sucursales
Promesa expresada en horas hábiles SF El texto distingue "Retiro inmediato en horas hábiles" de una cantidad de horas, con singular/plural
Precios de envío calculados en vivo MED calculatePriceForShippingOption(), resuelto por opción con Promise.allSettled
Listado de opciones según el carrito MED listCartShippingMethods()

El cálculo depende de que la metadata de cada variante venga cargada desde Medusa (supplier_id, t_entrega, t_entrega_aviadores, t_entrega_multi, stock_aviadores, stock_multiplaza). Si falta, la promesa queda en 0.

5.3 Pagos

Los proveedores que el storefront sabe representar están en src/lib/constants.tsx. Quién está habilitado lo decide Medusa, no este repo.

Método provider_id Estado
Bancard QR pp_bancard_qr_bancard_qr En uso. Se paga en el paso de revisión; el pedido nace pagado — ver abajo
Tarjeta (Bancard vPOS) pp_bancard_vpos_bancard_vpos Iframe de Bancard en el paso de revisión (historia #149)
Transferencia bancaria pp_bank_transfer_bank_transfer En uso. Con descuento aplicado por el backend (código TRANSFERED_PAYMENT)
Pago manual pp_system_default Disponible
Stripe (tarjeta, iDeal, Bancontact) pp_stripe_* Código heredado del starter, inactivo
PayPal pp_paypal_paypal Código heredado del starter, inactivo

Flujo Bancard (modules/checkout/components/bancard-qr-panel/ y bancard-vpos-frame/): en el paso de revisión abre el intento de pago en el backend (reserva de stock y carrito bloqueado), muestra el QR con su cuenta regresiva o el iframe de tarjeta, y escucha el resultado en tiempo real por SSE contra /payment-events/{sessionId} (use-bancard-payment-sse.ts, reconexión hasta 5 intentos) con sondeo de respaldo. El pedido lo crea el backend al confirmar el pago; finishPaidCheckout cierra el checkout y redirige. Maneja pagado, rechazado, vencido y cancelado.

El guaraní (pyg) está declarado como moneda sin división por 100.


6. Pedidos y post-venta

Funcionalidad Origen Notas
Confirmación de pedido MED order/[id]/confirmed
Historial y detalle de pedidos MED account/@dashboard/orders
Panel de transferencia bancaria con los datos para pagar SF order/components/bank-transfer-panel
Detalle de envío y de pago del pedido MED shipping-details, payment-details
Transferencia de pedido entre cuentas — solicitar, aceptar y rechazar por token MED createTransferRequest, acceptTransferRequest, declineTransferRequest; rutas order/[id]/transfer/[token]/{accept,decline}

7. Cuentas de cliente

Funcionalidad Origen Notas
Registro e inicio de sesión con email MED JWT en cookie _medusa_jwt HTTP-only
Login con Google (OAuth) SF + MED google-login-button, callback en auth/google/callback, createGoogleCustomer() y refreshGoogleAuth()
Recuperación y reseteo de contraseña MED forgot-password, reset-password
Perfil: nombre, email, teléfono, contraseña, dirección de facturación MED account-info y componentes profile-*
Libreta de direcciones (alta, edición, baja) MED address-book, address-card
Panel con rutas paralelas @dashboard / @login SF Renderiza uno u otro según sesión

8. Financiación — formulario de crédito

Funcionalidad propia, sin equivalente en el starter.

Funcionalidad Origen Notas
Simulador de cuotas SF installment-calculator.ts: cuota = (precio / factor) / meses, redondeada al millar. Plazos y factores tabulados, monto mínimo 1.000.000 Gs
Cálculo de total financiado y % de recargo SF calculateTotalWithFinancing(), calculateSurchargePercent()
Solicitud de crédito en modal SF + CMS CreditButton, CreditModal, CreditRequestForm; la configuración del formulario viene de Payload (getCreditFormSettings())
Proxy server-side hacia Payload SF app/api/credit-form/route.ts — evita exponer credenciales del CMS al navegador
Protección antibot reCAPTCHA v3 SF lib/providers/recaptcha-provider.tsx, montado en el layout raíz

9. Transversal

Funcionalidad Origen Notas
Enrutamiento por región SF + MED middleware.ts: mapa país → región cacheado 1 h, redirección a /{countryCode}. Región por defecto py
Cache con tags por usuario SF _medusa_cache_id, tags carts-<id>, products-<id>, etc., revalidados tras cada mutación
Botón flotante de WhatsApp SF WhatsAppButton, número 595974670000 hardcodeado
Footer editable SF layout/templates/footer
Skeletons de carga SF modules/skeletons/
Sitemap SF next-sitemap.js
Despliegue en Docker SF Dockerfile con npm sobre repo yarn — ver ADR-0003

Puntos a revisar

Detectados durante el inventario, sin acción tomada:

  • Número de WhatsApp hardcodeado en el componente. Debería ser variable de entorno o venir de Payload.
  • Sucursales hardcodeadas. Aviadores del Chaco y Multiplaza aparecen por nombre en el cálculo de promesas de entrega y en la disponibilidad. Agregar una tercera sucursal hoy exige tocar código.
  • Código muerto de Stripe y PayPal heredado del starter, dos majors atrás. Ver Deuda con el upstream.
  • Dos clientes de Algolia (lib/algolia.ts y lib/search-client.ts) y dos plantillas de tienda conviviendo (algolia-store-template e instantsearch-store-template) — verificar si alguna quedó sin uso.