Commit Graph
764 Commits
Author SHA1 Message Date
devopsandClaude Sonnet 5 f2e0c02013 fix(commerce-backend): regenerar package-lock.json con epayco-sdk-node
El commit anterior agregó epayco-sdk-node a package.json pero el
lockfile nunca se actualizó (se generó localmente con
--package-lock=false para evitar un problema no relacionado del
registry en este entorno) -- npm ci en el Dockerfile exige que el
lockfile esté sincronizado con package.json y rompió el build en CI.
Regenerado con npm install normal; confirmado que npm ci (el comando
real del Dockerfile) ahora sí instala limpio.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01THZFwPzrwv6VAbuwmaf5vR
2026-09-07 04:16:52 +00:00
devops d4716382d3 Merge fix/epayco-pse-reemplaza-payu into main
Build and Push Medusa / Escaneo de Secretos (Gitleaks) (push) Successful in 30s
Build and Push Frontend / Escaneo de Secretos (Gitleaks) (push) Successful in 23s
Build and Push Medusa / Construir y publicar Medusa (push) Failing after 4m19s
Build and Push Frontend / Construir y Subir Imagen (push) Successful in 18m42s
2026-09-07 03:58:44 +00:00
devopsandClaude Sonnet 5 12c4afa09c fix(payments): reemplazar PayU LatAm por ePayco como pasarela PSE
PayU LatAm (integrado en el commit anterior) resultó inviable: Rapyd
compró ese negocio completo en LatAm/África en 2023, y el registro real
del usuario quedó en la plataforma de Rapyd (board.rapyd.net,
credenciales access_key/secret_key incompatibles con el módulo ya
construido, API completamente distinta). Se evaluó reconstruir contra
Rapyd, pero el usuario comparó costos para su volumen real (~8
ventas/mes) y encontró que ePayco cobra menos en PSE. Se investigó
ePayco en vivo: es 100% de Davivienda desde 2024, acepta liquidación a
cualquier banco colombiano (no exige Bancolombia/Nequi como Wompi) y da
tarifa preferencial a cuentas Davivienda -- el usuario ya tiene una.
Mejor encaje de negocio y más barato que PayU/Rapyd. Confirmado como
elección definitiva.

- src/modules/epayco-pse/ reemplaza a src/modules/payu-pse/: mismo
  contrato AbstractPaymentProvider (initiatePayment/authorizePayment
  "pending_authorization"/getWebhookActionAndData con firma SHA256
  verificada), pero envuelve el SDK oficial `epayco-sdk-node` en vez de
  llamar la API cruda -- leyendo el código fuente del SDK (no la
  documentación pública, que resultó desactualizada en más de un campo)
  se confirmó que el protocolo real de ePayco para PSE es bastante más
  particular de lo que sugieren los ejemplos: cada campo del payload se
  cifra con AES usando la private key del comercio, más un login previo
  que da un bearer token que también viaja en la misma request.
  Reimplementar esto a mano tenía mucho más riesgo de error que delegar
  en el SDK mantenido por el propio proveedor.
- Corregido en el camino: el método real para listar bancos es
  `bank.getBanks()`, no `pseBank()` (así aparecía en un resumen de
  búsqueda, pero no existe en el SDK real -- confirmado leyendo
  node_modules/epayco-sdk-node/lib/resources/bank.js directamente). El
  campo real para la URL de confirmación es `method_confirmation`
  (con guión bajo en medio), no `metodoconfirmacion` como mostraba la
  documentación pública -- confirmado contra tests/bank.js del propio
  paquete.
- retrievePayment sí se implementó esta vez (endpoint de validación de
  ePayco documentado); refundPayment sigue sin implementar -- ese
  endpoint no quedó verificado en vivo, tira error explícito en vez de
  fingir éxito.
- Frontend: el step de pago recupera el selector de banco + tipo de
  persona + documento (a diferencia del diseño que se había planeado
  para Rapyd, donde esos datos se recolectaban en la página del propio
  Rapyd/SafetyPay) -- ePayco sí necesita esos campos de nuestro lado,
  como PayU.
- Dos puntos quedan sin verificar contra un sandbox real (anotados en
  el código con qué hacer si fallan): el nombre exacto del campo con la
  URL del banco en la respuesta de bank.create() (initiatePayment tira
  un error con el payload completo si no matchea ningún candidato
  probado), y si p_cust_id_cliente/p_key del webhook son iguales a las
  API keys o valores aparte del dashboard de ePayco.

Verificado: build real de Medusa con las 7 env vars EPAYCO_* dummy,
smoke test del wrapper del SDK cargando y la verificación de firma
dando el resultado esperado contra un caso conocido, typecheck+lint+
build completo del frontend.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01THZFwPzrwv6VAbuwmaf5vR
2026-09-07 03:58:33 +00:00
gitea-actions f0b4245676 chore(gitops): deploy Medusa v1.0.229 [skip ci] 2026-09-07 02:24:57 +00:00
devops e9e78e64c1 chore: release v1.0.230 [skip ci] 2026-09-07 02:02:25 +00:00
devops 95cf791737 Merge feat/payu-pse-pago into main
Build and Push Frontend / Escaneo de Secretos (Gitleaks) (push) Successful in 1m8s
Build and Push Frontend / Construir y Subir Imagen (push) Successful in 14m42s
Build and Push Medusa / Escaneo de Secretos (Gitleaks) (push) Successful in 22s
Build and Push Medusa / Construir y publicar Medusa (push) Successful in 19m56s
2026-09-07 01:18:06 +00:00
devopsandClaude Sonnet 5 2ceea23f40 feat(payments): integrar PayU LatAm (PSE) como pasarela de pagos
ADR 0009 ya había decidido PayU LatAm como proveedor (única opción que
no exige cuenta Bancolombia/Nequi) y confirmado que no existe ningún
plugin real de Medusa para su API -- los paquetes que aparecen
buscando "PayU" son para PayU Polonia/CEE, API completamente distinta
(clientId/posId/secondKey vs. apiLogin/apiKey/merchantId/accountId).
Este commit implementa esa decisión: módulo de pago custom
(AbstractPaymentProvider) para PSE (transferencia bancaria), primer
alcance del método de pago -- Nequi/Daviplata quedan fuera por ahora.

Backend (commerce-backend):
- src/modules/payu-pse/: initiatePayment arma y postea SUBMIT_TRANSACTION
  contra la API real de PayU LatAm; authorizePayment devuelve
  "pending_authorization" (PSE es async, la confirmación real llega por
  webhook, no en el momento de completar el carrito); getWebhookActionAndData
  valida la firma MD5 del webhook antes de confiar en cualquier
  confirmación de pago -- falla cerrado si no matchea. refundPayment/
  retrievePayment tiran error explícito en vez de simular éxito: esos
  endpoints de PayU no quedaron verificados en vivo y hay dinero real de
  por medio.
- No hace falta un subscriber propio para completar la orden -- el
  subscriber nativo de Medusa (payment-webhook + process-payment-workflow)
  ya hace ese trabajo con los métodos de arriba bien implementados
  (confirmado leyendo el código fuente instalado de @medusajs/medusa
  2.18.0, no la documentación).
- Correlación webhook↔sesión: Medusa inyecta su propio session_id en
  `data` antes de initiatePayment; se usa ese mismo valor como
  referenceCode de PayU, así el reference_sale que vuelve en el webhook
  ya es directamente el session_id de Medusa.
- src/lib/payu.ts: cliente HTTP + firmas (orden y webhook, fórmulas
  distintas, confirmadas contra el SDK PHP oficial de PayU).
- src/api/store/payments/pse-banks/route.ts: lista de bancos PSE,
  cacheada en memoria.
- medusa-config.ts, Dockerfile, configmap/secrets.template: 7 env vars
  nuevas (PAYU_API_LOGIN/API_KEY/MERCHANT_ID/ACCOUNT_ID/ENV/RESPONSE_URL/
  NOTIFY_URL), dummies de build agregados, secrets con placeholder
  "CAMBIAR".

Frontend (ecommerce):
- Nuevo step "payment" en components/checkout/checkout-client.tsx
  (reemplaza al step "review" que solo ofrecía WhatsApp): selector de
  banco, tipo de persona (N/J), tipo/número de documento, botón "Pagar
  con PSE" que crea la sesión de pago, completa el carrito y redirige
  al banco (navegación completa, no iframe -- así lo exige PayU).
  WhatsApp queda como respaldo manual si falla la iniciación del pago.
- lib/headless/providers/medusa-payment.ts + 3 rutas proxy nuevas bajo
  app/api/cart/, mismo patrón que el resto del carrito
  (medusaCartFetch, ahora exportado desde medusa-cart.ts).
- app/checkout/pse/return/: página de vuelta del banco -- nunca afirma
  éxito, la confirmación real es el webhook async.

Arranca contra las credenciales de sandbox genéricas y públicas de
PayU (developers.payulatam.com) mientras el usuario termina su propio
registro de comercio -- swap de las 4 credenciales via secret cuando
estén listas, sin cambios de código.

Verificado: build real de Medusa con las env vars dummy (no solo tsc),
tipos de AbstractPaymentProvider/WebhookActionResult/PaymentActions
confirmados contra @medusajs/utils y @medusajs/types instalados
(node_modules limpiado después), typecheck + lint + build completo del
frontend, páginas nuevas renderizando sin error. Pendiente: prueba
end-to-end contra el sandbox real de PayU (necesita el backend
desplegado) y habilitar el provider en la región Colombia desde el
Admin.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01THZFwPzrwv6VAbuwmaf5vR
2026-09-07 01:17:22 +00:00
devops 4d1804eeeb chore: release v1.0.228 [skip ci] 2026-09-06 21:46:27 +00:00
gitea-actions 9b8b96fd02 chore(gitops): deploy Medusa v1.0.227 [skip ci] 2026-09-06 21:31:24 +00:00
devops 313bb2eab4 Merge fix/navbar-departamentos-hover-gap into main
Build and Push Medusa / Escaneo de Secretos (Gitleaks) (push) Successful in 27s
Build and Push Frontend / Escaneo de Secretos (Gitleaks) (push) Successful in 23s
Build and Push Medusa / Construir y publicar Medusa (push) Successful in 26m6s
Build and Push Frontend / Construir y Subir Imagen (push) Successful in 14m54s
2026-09-06 21:04:24 +00:00
devops 710da06c0a Merge fix/catalog-sidebar-scroll into main 2026-09-06 21:04:23 +00:00
devops 9d08169092 Merge fix/product-import-dedupe-por-titulo into main 2026-09-06 21:04:23 +00:00
devopsandClaude Sonnet 5 1aa7802a61 fix(navbar): el menú Departamentos no se cierra al mover el cursor hacia él
El panel del mega-menu tenía mt-1 respecto al botón -- como es
position:absolute no suma a la altura del contenedor que escucha
mouseenter/mouseleave, así que ese margen quedaba como una franja
muerta: mover el cursor del botón hacia el panel disparaba
mouseleave a mitad de camino y cerraba el menú antes de poder hacer
clic en una categoría (reportado en vivo).

Se elimina el gap (mt-1) y se agrega un delay de 200ms antes de cerrar,
cancelable si el cursor vuelve a entrar, como margen extra para
movimientos rápidos o en diagonal cerca del borde.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01THZFwPzrwv6VAbuwmaf5vR
2026-09-06 21:04:16 +00:00
devopsandClaude Sonnet 5 b83722e9c5 fix(catalog): scroll propio en el sidebar de filtros
El <aside> de Filtros es sticky pero sin altura máxima ni overflow
propio -- con 30+ categorías más marca/edad/precio, el panel se pasa
del viewport y queda inalcanzable (reportado en vivo: había que bajar
el zoom del navegador para ver "Marca"/"Edad"/"Precio").

overflow-y-auto + max-h acotado al viewport (solo en lg, que es donde
aplica sticky) le da scroll propio al panel sin depender del scroll de
la página.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01THZFwPzrwv6VAbuwmaf5vR
2026-09-06 21:04:04 +00:00
devopsandClaude Sonnet 5 8d543f5eb1 fix(product-import): no duplicar producto al re-importar el mismo título
Re-subir la misma fila de CSV (ej. para agregar más fotos o actualizar
la descripción de un producto ya cargado) creaba un producto nuevo con
handle distinto -- confirmado en vivo re-importando "Hello Kitty &
Friends" para sumar fotos: quedaron dos productos con el mismo título
en la tienda.

Ahora, si el título coincide (case-insensitive/trim) con un producto ya
importado, se actualiza ese producto en vez de crear uno: las fotos
nuevas se agregan a las que ya tenía (no se reemplazan) y la
descripción se actualiza si la fila trae una. No toca
precio/cantidad/categoría/colección del producto existente.

El duplicado ya creado se fusionó en vivo (fotos movidas al original,
duplicado borrado) sin esperar este deploy.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01THZFwPzrwv6VAbuwmaf5vR
2026-09-06 21:03:56 +00:00
devops df791e0c28 chore: release v1.0.226 [skip ci] 2026-09-06 19:55:30 +00:00
gitea-actions feda1283d4 chore(gitops): deploy Medusa v1.0.225 [skip ci] 2026-09-06 19:46:05 +00:00
devops 8fd0514e76 Merge feat/product-gallery-hover-zoom into main
Build and Push Medusa / Escaneo de Secretos (Gitleaks) (push) Successful in 21s
Build and Push Frontend / Escaneo de Secretos (Gitleaks) (push) Successful in 19s
Build and Push Medusa / Construir y publicar Medusa (push) Successful in 23m54s
Build and Push Frontend / Construir y Subir Imagen (push) Successful in 9m11s
2026-09-06 19:19:19 +00:00
devops 1cde29b344 Merge fix/product-import-crear-categoria-coleccion into main 2026-09-06 19:19:18 +00:00
devopsandClaude Sonnet 5 8517102b63 feat(product-gallery): zoom automático de la imagen al pasar el cursor
Antes el único zoom era el modal interactivo (click -> Dialog con scale/
drag). Ahora la imagen principal también hace zoom estilo lupa (2.2x)
que sigue la posición del cursor con mousemove/transform-origin, sin
tocar el modal existente (sigue abriéndose igual con el click).

Solo mouse -- mousemove no dispara de forma continua en touch, así que
en mobile simplemente no aparece el efecto, sin romper nada ahí.

Verificado: tsc --noEmit limpio, página de producto renderiza 200 con
datos mock y el nuevo markup presente. No se pudo verificar visualmente
el hover en un navegador real (sin chromium-cli ni claude-in-chrome
disponibles en este shell headless).

Co-Authored-By: Claude Sonnet 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01THZFwPzrwv6VAbuwmaf5vR
2026-09-06 19:18:11 +00:00
devopsandClaude Sonnet 5 7773bcdecf fix(product-import): crear categoría/colección si no existe en vez de descartarla en silencio
El importador solo enlazaba categoría/colección cuando el nombre del CSV
matcheaba exacto (case-insensitive) una ya existente -- si no había match,
category_ids/collection_id quedaban undefined sin ningún error. Así quedó
el producto "Hello Kitty & Friends" importado sin colección: la colección
nunca existió en la tienda, el importador nunca la creó ni avisó.

Ahora, si el nombre no matchea, se crea la categoría/colección nueva
(createProductCategoriesWorkflow / createCollectionsWorkflow) con el mismo
slugify() ASCII-safe que ya usa el handle del producto, por la misma razón:
el default de Medusa no quita tildes/eñes y rompe la ruta pública.

El producto ya importado se corrigió en caliente vía Admin API (colección
creada + enlazada + handle corregido de "hello-kitty-&-friends" a
"hello-kitty-friends"), sin esperar este deploy.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01THZFwPzrwv6VAbuwmaf5vR
2026-09-06 19:17:47 +00:00
gitea-actions c62ad626cc chore(gitops): deploy Docs Portal v1.0.224 [skip ci] 2026-09-06 17:27:30 +00:00
devopsandClaude Sonnet 5 8835d8ca0c docs(tmux-host): documentar Dockerfile + healthcheck cada 30 min
Build and Push Docs Portal / Escaneo de Secretos (Gitleaks) (push) Successful in 23s
Build and Push Docs Portal / Construir y publicar Docs Portal (push) Successful in 8m57s
Actualiza sesion-tmux-persistente.md: la imagen de tmux-host ahora se
construye desde scripts/tmux-host/Dockerfile (WORKDIR fijo en la raiz
del lab) en vez del docker run inline anterior, y se agrega la seccion
del chequeo de salud en background (red + sesion tmux, cada 30 min,
notificacion via el mismo canal de Telegram del lab-agent). Actualiza
tambien la tabla "Que sobrevive a que" para reflejar la auto-recuperacion
de la sesion tmux.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_012xyPak6HWFmBCqXrvFsejL
2026-09-06 17:18:10 +00:00
gitea-actions 997a00c284 chore(gitops): deploy Medusa v1.0.223 [skip ci] 2026-09-06 17:16:31 +00:00
devopsandClaude Sonnet 5 0fb904b9ac Merge fix/adr0006-import-handle-ascii-safe into main
Build and Push Medusa / Escaneo de Secretos (Gitleaks) (push) Successful in 40s
Build and Push Medusa / Construir y publicar Medusa (push) Successful in 29m54s
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01SEsGCsCmxkyXi9XctNdrT1
2026-09-06 03:43:55 +00:00
devopsandClaude Sonnet 5 a5ede05d96 fix(product-import): generar handle ASCII-safe en vez del default de Medusa
3 productos importados con título acentuado (ñ/tildes) quedaron con handle
no-ASCII y daban 404 real al entrar por shop.cruzcloud.net -- el tunel/
ingress público rompe rutas con UTF-8 no-ASCII en el path, confirmado en
vivo comparando el mismo request directo al servicio (200 OK) contra el
dominio público (404). Se genera el handle explícito (slugify propio,
sin dependencia nueva) con sufijo único por fila para evitar colisiones
entre títulos parecidos. Los 3 productos ya publicados con handle roto
se corrigieron en caliente vía Admin API, sin esperar este deploy.

Co-Authored-By: Claude Sonnet 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01SEsGCsCmxkyXi9XctNdrT1
2026-09-06 03:43:47 +00:00
devopsandClaude Sonnet 5 63746eb090 Merge origin/main (chore: deploy Medusa v1.0.222) into local main
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01SEsGCsCmxkyXi9XctNdrT1
2026-09-06 03:21:58 +00:00
devopsandClaude Sonnet 5 2ca00d032d Merge fix/adr0008-doc-estado-final-palette-amendment into main
Co-Authored-By: Claude Sonnet 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01SEsGCsCmxkyXi9XctNdrT1
2026-09-06 03:21:43 +00:00
devopsandClaude Sonnet 5 cb15749448 docs(adr-0008): registrar pivote de paleta azul/amarillo y estado real por sub-fase
La spec original (Navy #122844/Coral #D85A30) fue reemplazada en producción
el mismo día por una paleta azul/amarillo estilo Walmart
(fix/adr0008-walmart-palette-blue-yellow), pero nunca quedó documentada
como enmienda. Se agrega §8 con los valores reales vigentes en globals.css
y §9 con auditoría por sub-fase contra el código en main: sub-fases 1-4
completas, sub-fase 5 parcial (product-purchase migrado, cart-drawer y
wishlist-drawer sin tocar, alias de compatibilidad de button.tsx sin
eliminar).

Co-Authored-By: Claude Sonnet 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01SEsGCsCmxkyXi9XctNdrT1
2026-09-06 03:21:36 +00:00
gitea-actions 9e1adf4627 chore(gitops): deploy Medusa v1.0.222 [skip ci] 2026-09-04 14:18:07 +00:00
devops 0ad74b6b70 Merge branch 'chore/product-import-flat-bucket-note' into main
Build and Push Medusa / Escaneo de Secretos (Gitleaks) (push) Successful in 26s
Build and Push Medusa / Construir y publicar Medusa (push) Successful in 23m5s
2026-09-04 13:54:31 +00:00
devops d1d007fc7d chore(commerce-backend): corregir comentario sobre carpeta de fotos importadas
El S3 file provider de Medusa descarta cualquier subcarpeta del
filename (usa solo path.parse().name + ulid, confirmado leyendo
@medusajs/file-s3/dist/services/s3-file.js) -- no existe una carpeta
import-products/ separada como decia el comentario original. El bucket
(ari-products) es plano, igual para todas las fotos del catalogo.
Confirmado en vivo con una importacion real de 3 productos.
2026-09-04 13:54:23 +00:00
gitea-actions 11ac6d7949 chore(gitops): deploy Medusa v1.0.221 [skip ci] 2026-09-04 05:27:25 +00:00
devops 093ae419d5 Merge branch 'fix/product-import-category-select' into main
Build and Push Medusa / Escaneo de Secretos (Gitleaks) (push) Successful in 22s
Build and Push Medusa / Construir y publicar Medusa (push) Successful in 16m51s
2026-09-04 04:35:28 +00:00
devops 2b0d50c3d0 fix(commerce-backend): traer name/title explicito en el importador
listProductCategories({})/listProductCollections({}) sin select
explicito devolvian name/title undefined (a diferencia de la capa HTTP
del Admin API, que si los trae completos por defecto) -- causaba un 500
"Cannot read properties of undefined (reading 'toLowerCase')" en
cualquier import real. Confirmado en vivo con una prueba de importacion
de 3 productos antes de este fix.

De paso, se agrega un filtro defensivo antes del .map() para que una
categoria/coleccion sin nombre no tumbe el import entero.
2026-09-04 04:35:20 +00:00
gitea-actions 8126bb3d81 chore(gitops): deploy Medusa v1.0.220 [skip ci] 2026-09-02 21:53:50 +00:00
devops dedf4f0963 Merge branch 'feat/product-import' into main
Build and Push Medusa / Escaneo de Secretos (Gitleaks) (push) Successful in 59s
Build and Push Medusa / Construir y publicar Medusa (push) Successful in 26m14s
2026-09-01 03:47:43 +00:00
devops 1cd1078cdf feat(commerce-backend): importador masivo de productos via CSV
Nueva pagina "Importacion" en Medusa Admin para cargar varios productos
de una sola vez (comprados en Amazon/eBay/etc, no dropshipping
automatizado -- se evaluo y descarto raspar catalogos de terceros sin
autorizacion por riesgo de copyright/ToS).

src/api/admin/product-import/route.ts: GET sirve la plantilla CSV
descargable, POST procesa fila por fila (una foto rota o categoria mal
escrita no tumba el resto del archivo). Cada foto se descarga del origen
y se re-aloja en el mismo MinIO/S3 del NAS que ya usa el catalogo
(prefijo import-products/, separado de ari-products/), se crea el
registro de inventario con la cantidad indicada y el producto queda
vinculado con el mismo patron "Presentacion"/"Estandar" que usa el resto
del catalogo -- el storefront no necesita cambios.

src/lib/csv.ts: parser CSV propio (RFC4180), sin sumar dependencia nueva.

Workflows y servicios de modulo (uploadFilesWorkflow,
createInventoryItemsWorkflow, createProductsWorkflow, stock-location/
fulfillment/sales-channel/product module services) verificados contra
los .d.ts reales instalados, no solo contra documentacion.
2026-09-01 03:47:32 +00:00
devops 601378a77e chore: release v1.0.219 [skip ci] 2026-08-29 20:31:52 +00:00
devops 1dccd0aa6a Merge branch 'feat/out-of-stock-ui' into main
Build and Push Frontend / Escaneo de Secretos (Gitleaks) (push) Successful in 20s
Build and Push Frontend / Construir y Subir Imagen (push) Successful in 8m30s
2026-08-29 20:23:02 +00:00
devops 474ac3795b fix(ecommerce): deshabilitar compra y mostrar "Agotado" sin stock real
variant.available (calculado en lib/headless/providers/medusa.ts a
partir de manage_inventory/allow_backorder/inventory_quantity) ya
llegaba correcto hasta el componente, pero ningun boton de compra lo
usaba -- se podia seguir agregando al carrito un producto con stock 0.

Afecta product-purchase.tsx (pagina de producto), mobile-add-to-cart.tsx
(barra fija mobile) y product-card.tsx (tarjetas de catalogo): boton
deshabilitado + label "Agotado" en los tres, mas badge/overlay en la
tarjeta de catalogo.
2026-08-29 20:22:55 +00:00
gitea-actions bb2ad3c317 chore(gitops): deploy Medusa v1.0.218 [skip ci] 2026-08-29 19:19:15 +00:00
devops 578f085334 Merge branch 'fix/inventory-panel-ts-error' into main
Build and Push Medusa / Escaneo de Secretos (Gitleaks) (push) Successful in 25s
Build and Push Medusa / Construir y publicar Medusa (push) Successful in 18m56s
2026-08-29 18:59:55 +00:00
devops ce4842f375 fix(commerce-backend): corregir tipo de callback en location_levels.find
TS2769: la anotacion explicita {location_id: string} no calzaba con el
tipo Maybe<InventoryLevel> que infiere query.graph para location_levels.
Se quita la anotacion y se deja inferir, con optional chaining.
2026-08-29 18:59:48 +00:00
devops 2cce671049 Merge branch 'feat/inventory-panel' into main
Build and Push Medusa / Escaneo de Secretos (Gitleaks) (push) Successful in 32s
Build and Push Medusa / Construir y publicar Medusa (push) Failing after 4m52s
2026-08-29 17:56:51 +00:00
devops 22f97ee12e feat(commerce-backend): panel simplificado de inventario en Medusa Admin
Nueva pestana "Inventario" en el sidebar del Admin (src/admin/routes/
inventario), pensada para un usuario no tecnico: una fila por producto
(catalogo real confirmado 1 variante por producto), switch para activar
seguimiento de stock, input de cantidad que guarda solo, badge de stock
bajo (<=5 unidades) y activacion/desactivacion en bloque por seleccion.
No reemplaza la vista nativa de Inventory de Medusa, es un atajo.

Backend: src/api/admin/inventory-panel/route.ts + workflow propio
src/workflows/attach-inventory-item-to-variant.ts para vincular un
InventoryItem nuevo a una variante existente (Medusa no lo hace solo al
togglear manage_inventory en un producto ya creado -- confirmado en vivo
contra un producto [DEMO] antes de escribir el codigo).

Nombres de campos y workflows verificados contra los .d.ts reales
instalados en el pod (no solo contra la documentacion, que no cubre bien
este flujo de vincular inventario a una variante existente).
2026-08-29 17:56:44 +00:00
devops 42c90d8534 chore: release v1.0.216 [skip ci] 2026-08-29 17:10:35 +00:00
devops cd8d2edd8f Merge branch 'feat/google-oauth-frontend' into main
Build and Push Frontend / Escaneo de Secretos (Gitleaks) (push) Successful in 20s
Build and Push Frontend / Construir y Subir Imagen (push) Successful in 8m39s
2026-08-29 17:01:39 +00:00
devops 77389aea19 feat(ecommerce): login con Google para clientes
Implementa el flujo completo de OAuth social de Medusa para el
storefront: boton "Continuar con Google" en account-dialog, ruta proxy
que arranca el flujo (GET /api/customer/google/start) y pagina de
callback en /auth/google/callback (coincide con GOOGLE_CALLBACK_URL del
secret) que resuelve el code/state contra el backend, decodifica el JWT
para distinguir cliente nuevo vs existente, crea el customer si hace
falta y refresca el token a sesion final -- mismo patron de
store/customer-store.ts que login/register por email.

Flujo verificado en vivo contra el backend ya desplegado (GET
/auth/customer/google, /auth/customer/google/callback con state
invalido, /auth/token/refresh con bearer invalido) antes de escribir el
codigo, no solo contra la documentacion.
2026-08-29 17:01:32 +00:00
gitea-actions 7ce11ecbb4 chore(gitops): deploy Medusa v1.0.215 [skip ci] 2026-08-29 16:34:34 +00:00