Files
mercadodevida/work/current.md
2026-08-22 11:43:42 +02:00

16 KiB
Raw Blame History

Feature actual: F-143 (Reporting: contracts, filters and RBAC)

F-138 cerrada (2026-08-22) — auto-seed default price row on variant creation

  • POST /products(:id/variants) create ahora inserta inmediatamente una fila default en pricing_variant_prices (net_unit_amount_cents=0, vat_rate='general', currency='EUR') vía PricingService.seedVariantPrice (inyectado en CreateProductVariant, best-effort, ON CONFLICT DO NOTHING). Cierra la ventana 404 de GET /pricing/variants/:id. Backend-only, sin migración.
  • Fuente: pricing seedVariantPrice (ports+service+PgPricingRepository), catalog CreateProductVariant seed (best-effort), CatalogRoutesDeps += pricing, build-app.ts hoist pricing const; + tests variant-use-cases.test.ts (3) + AC itest en catalog.itest.ts.
  • Gates: implementer / reviewer APPROVED / security APPROVED / qa APPROVED / leader close .
  • Verificación: tsc --noEmit 0 errores; npm test 209 passed / 57 skipped (+3 nuevos); lint:boundaries sin violaciones nuevas (R1 preexistente security.routes.ts → log-broadcaster no introducido); ./scripts/verify.sh verde (pre-close + post-close tras corregir leader-close.json verdict CLOSED→APPROVED).
  • Commit: feat(F-138): completed feature (fb01593, amendado).

F-154 cerrada (2026-08-22) — separate customers from internal users

  • GET /users (Customers) now returns storefront customers only (identity_users.role = 'customer' filtro literal en PgProfileRepository.listCustomers, COUNT + SELECT). GET /users/:id owner-or-admin inalterado.
  • GET /admin/users (Users) now returns internos/backoffice only (role <> 'customer' base literal; ?role=admin|editor afinando dentro de internos; ?role=customer → vacío).
  • Frontend: dropdown de Users quita opción customer (backend ya fuerza la separación). Customers page sin cambio (llama /users → ahora customer-only).
  • Tests: 6 nuevos unitarios (mock, sin DB) en pg-profile-repository.test.ts (3) + security.routes.test.ts (3). users.itest.ts AC2/AC3 flip: /users devuelve ben (customer) no ana (admin). Full suite 206 passed / 56 skipped, sin regresiones.
  • Gates: implementer / reviewer APPROVED / security APPROVED / qa APPROVED / leader close .
  • tsc --noEmit 0 errores (API + apps/admin); eslint/prettier limpios en archivos tocados; lint:boundaries sin violaciones NUEVAS (R1 preexistente en security.routes.ts → log-broadcaster, no introducido por F-154, verificado via git diff); verify.sh exit 0.
  • Commit: feat(F-154): completed feature.

F-153 cerrada (2026-08-22) — customer email on order view

  • Asocia el email del cliente (identity_users.email, NOT NULL) al order read model vía LEFT JOIN identity_users en el repo, y lo expone en serializeOrder (detail + lista) y en la notificación del force-transition admin (usa order.email; se elimina el lookup inline).
  • OrderView.email?: string | null (additivo, opcional en fixtures de test → serializado como null). Sin migración. Boundary intacta (orders→identity_users es referencia SQL, no import TS).
  • Tests: 3 nuevos en pg-order-repository.test.ts (email resuelto vía JOIN, null sin usuario vinculado, undefined cuando no existe). Suite 200 passed / 56 skipped, sin regresiones.
  • Gates: implementer / reviewer APPROVED / security APPROVED / qa APPROVED / leader close .
  • tsc --noEmit 0 errores; eslint 0; prettier baseline-only; lint:boundaries sin violaciones nuevas; verify.sh exit 0.
  • Commit: feat(F-153): completed feature + chore: reset runtime after F-153.
  • Pendiente siguiente por orden: F-154 (separate customers from internal users).

Sesión 2026-08-22 — F-152 cerrada (emails on account creation + order confirmation)

  • F-152 cerrada: welcome email (account_created) on POST /auth/register y order confirmation email on POST /payments/webhook (PaymentSucceeded). Best-effort (fire-and-forget + request.log.warn), idempotent (gate outcome.kind === "processed"), XSS-safe (buildWelcomeEmail escapea name), SMTP config de store_settings.
  • Gates: implementer / reviewer APPROVED / security APPROVED / qa APPROVED / leader close .
  • tsc --noEmit 0 errores; prettier+eslint limpios en archivos tocados; lint:boundaries sin nuevas violaciones; 197 tests ; git diff --check ; verify.sh exit 0.
  • Commits: feat(F-152): completed feature + chore: reset runtime after F-152 (push omitido, sin remote origin).
  • runtime-status.json reseteado a idle.
  • Pendiente siguiente por orden: F-153 (customer email missing).

Sesión 2026-08-22 — F-156 cerrada (CMS dynamic rendering)

Backlog: 269 features, 212 done, 57 pending, 0 in_progress, 0 blocked.

  • F-156 cerrada: CMS content-managed pages (/about, /contact, /shipping) dejan de servir caché stale. fetchPage usa { cache: 'no-store' } y las páginas exportan dynamic = 'force-dynamic'; el fallback estático y el RBAC se mantienen.
  • Gates: implementer / reviewer APPROVED / security APPROVED / qa APPROVED / leader close .
  • Verificado runtime: curl -sI /about → 200 con Cache-Control: private, no-cache, no-store, max-age=0, must-revalidate; verificador temporal de DB apareció y desapareció sin rebuild.
  • verify.sh green; cambios commiteados como feat(F-156): completed feature; runtime-status.json reseteado a idle.
  • Pendientes inmediatos por orden sugerido: F-152 (emails account creation/order confirmation) → F-153 (customer email missing) → F-154 (separate customers from internal users). Los tickets Reporting P0 pendientes son F-143..F-150.

Sesión 2026-08-21 — Reporting preparado y builds Next estabilizados

Backlog: 264 features, 209 done, 55 pending, 0 in_progress, 0 blocked.

  • F-141 cerrada: raíces turbopack/outputFileTracingRoot explícitas en customer frontend y páginas de catálogo dinámicas para que el build no dependa del API.
  • F-142 cerrada: docs/reporting/REPORTING_ARCHITECTURE.md y docs/reporting/REPORTING_TASKS.md entregados tras analizar modelos reales, datos faltantes, API, rendimiento, caché, RBAC y roadmap P0-P3.
  • Tickets Reporting P0 abiertos: F-143..F-150; todos pending.
  • verify.sh exit 0 y runtime-status.json reseteado a idle.
  • Próximo ciclo: iniciar F-143 (contracts, filtros, comparación y RBAC de Reporting) antes de implementar dashboards.

Sesión 2026-08-21 — backlog cerrado (nota inicial, desfasada)

Backlog: 185 features (185 done, 0 pending, 0 in_progress) según la nota original.

Últimas features cerradas en esa nota: F-117, F-116, F-115, F-112, F-100.

Tras esa nota se cerraron 18 features adicionales (F-118..F-135) sin actualizar current.md. Quedan reflejadas en backlog/features.json y en work/history.md.

F-117 cerrada (2026-08-21)

Fix de F-116: renombre las 9 categorías que quedaron en mayúsculas (FRUTAS Y VERDURAS, SNACKS, GRANOLA, SUPLEMENTS, FACIAL, CORPORAL, ASEO PERSONAL, HIERBAS MEDICINALES, PROVEEDORES). Re-ejecución idempotente.

F-116 cerrada (2026-08-21)

Traducción de las 30 categorías legacy a Español Title Case (Alimentación, Cosmética, Bebidas, Vino, Cerveza, Macrobiótica, etc.). Slugs conservados.

F-115 cerrada (2026-08-21)

Rever de F-100: SKU-MV-{uuid} restaurado en creación de producto y lazy migration. Eliminado endpoint /products/sku:generate y el editor de SKU en admin.

F-112 cerrada (2026-08-21)

Disclaimer de contenido asistido por IA en la ficha de producto. Migración 040 añade catalog_products.ai_assisted. Flag se activa automáticamente al generar contenido con IA. Frontend muestra el <aside> con los dos avisos.

F-100 cerrada (2026-08-21)

SKU automático desde el título. Helper puro sku.ts con generateSkuFromTitle + uniqueSku (9 tests). Endpoint POST /products/sku:generate y helper mantenido como utilidad para F-117.

F-112 cerrada (2026-08-21)

Disclaimer de contenido asistido por IA en la ficha de producto. Migración 040 añade catalog_products.ai_assisted boolean NOT NULL DEFAULT false. Flag se activa automáticamente al generar contenido con IA (POST /products/:id/generate-seo). Frontend (apps/frontend) muestra el <aside> con los dos avisos requeridos cuando el flag está en true. Tests: 160 → 169.

F-100 cerrada (2026-08-21)

SKU automático desde el título. Helper puro src/modules/catalog/domain/sku.ts con generateSkuFromTitle + uniqueSku (9 tests). POST /products y la migración perezosa de variantes ahora generan SKUs tipo MV-ESPELTA-ECOLOGICA en lugar de SKU-MV-${uuid}. Endpoint admin POST /products/sku:generate para preview. UI admin: SKU editable + botón regenerar en PriceStockSection.

F-114 cerrada (2026-08-21)

Importa las 76 categorías de oc_category_description de OpenCart. Crea 39 categorías nuevas y 32 marcas (nombres de marca van al módulo brands_brands), excluye marcadores legacy y duplicados. Script idempotente en scripts/seed-legacy-categories.mjs. Helpers puros en src/modules/categories/legacy/legacy-catalog.ts con 15 tests. Catálogo: 12→51 categorías, 5→37 marcas.

F-113 cerrada y desplegada (2026-08-21)

Email al cliente en procesando/enviado con tracking y courier editable. Bug fixed: UI admin → /orders/:id/transitions/admin. Courier persistido (orders_orders.courier, migración 039). Lista editable en store_settings.shipping_couriers. SHIPPED exige tracking y courier. Tests: 135 → 145. Deploy manual.

Última incidencia resuelta (2026-08-20)

F-099 en build. El sistema deja de simular el envío de recuperación en logs y añade SMTP configurable desde Ajustes → SMTP / Email. También se incorporan generación de descripción normal vacía, proxy de logs con cookie httpOnly y navegación de login/logout solo con icono y tooltip.

Última incidencia resuelta (2026-08-20)

F-095 cerrada con todos los gates aprobados. Las imágenes URL se descargan y almacenan en uploads locales antes de adjuntarse.

Incidencia anterior (2026-08-20)

Añadir una imagen por URL devolvía 400 porque el flujo hacía un PATCH vacío del producto y adjuntaba directamente la URL remota.

Última incidencia resuelta (2026-08-20)

F-094 cerrada con todos los gates aprobados. Publicar permite crear variantes y explica SKU/EAN, precios y stock.

Incidencia anterior (2026-08-20)

Precios e Inventario indicaban que las variantes se creaban desde Publicar, pero Publicar no ofrecía creación ni explicación.

Última incidencia resuelta (2026-08-20)

F-093 cerrada con todos los gates aprobados. Inventario busca ahora por EAN o nombre de producto.

Incidencia anterior (2026-08-20)

La búsqueda de Inventario enviaba q, pero el listado admin solo filtraba por nombre de producto.

Última incidencia resuelta (2026-08-20)

F-092 cerrada con todos los gates aprobados. Fecha de caducidad está ahora en General; backend y admin fueron reconstruidos y desplegados.

Incidencia anterior (2026-08-20)

Fecha de caducidad estaba en la pestaña SEO de la ficha de producto. F-092 la movió a General sin cambiar el estado, payload ni guardado.

Última incidencia resuelta (2026-08-20)

F-091 cerrada con todos los gates aprobados. Los conflictos de SKU/EAN indican ahora qué campo está duplicado y Enter + blur no generan PATCH simultáneos.

Incidencia anterior (2026-08-20)

El PATCH de variantes devolvía 409 PRODUCT_VARIANT_CODE_EXISTS cuando el SKU o EAN ya estaba usado por otra variante. El editor mostraba solo Error y la combinación Enter + blur podía intentar enviar dos veces.

Última incidencia resuelta (2026-08-20)

F-090 cerrada con todos los gates aprobados. El listado ya recibe marca/caducidad y los valores SKU/EAN guardados permanecen visibles tras salir del campo.

Incidencia anterior (2026-08-20)

El listado admin mostraba para marca/caducidad porque la serialización del catálogo omitía ambos campos. En el editor de producto, SKU/EAN se guardaban en rows pero la vista no editable usaba el array variants inicial y volvía a mostrar valores antiguos.

Última incidencia resuelta (2026-08-20)

F-089 cerrada con todos los gates aprobados. El enlace del listado admin apunta ahora a http://192.168.18.93:3003/products/<slug>, ruta del frontend customer.

Incidencia anterior (2026-08-20)

El enlace de producto del listado admin apuntaba a http://192.168.18.93:3003/productos/<slug>, pero el frontend customer usa /products/<slug>. F-089 corrigió únicamente ese path.

Última incidencia resuelta (2026-08-20)

F-088 cerrada con todos los gates aprobados. El admin responde HTTP 200 en http://192.168.18.93:3004/.

Symptom reportado por el operador (2026-08-20)

http://192.168.18.93:3004/ERR_CONNECTION_REFUSED. El servicio admin del monolito no se mantiene en pie. Diagnóstico:

  • monolith.sh prod status → admin exited during startup, log: Could not find a production build in the '.next' directory.
  • apps/admin/.next/ existe pero no contiene BUILD_ID ni required-server-files.json.
  • npx tsc --noEmit en apps/adminerror TS2353 en tax-rates/page.tsx(59,33): 'appliesTo' does not exist in type 'Partial<{ name: string; ratePercent: number; active: boolean; }>'.

Root cause

F-085 añadió el handler saveTipo que llama a taxApi.update(id, { appliesTo }) y extendió la página con UI de edición inline, pero olvidó extender la firma de taxApi.update en apps/admin/src/lib/api-client.ts. Resultado: next build aborta por typecheck, no se genera BUILD_ID, next start falla y el admin no puede servir nada en :3004. El backend en pricing.routes.ts ya valida y persiste appliesTo, así que el fix es 100% frontend (type only).

Fix

Ampliar la firma Partial<{...}> de taxApi.update para aceptar appliesTo: 'general' | 'reduced' | 'super-reduced' (mismo enum que el backend). Después: npm run build en apps/admin produce BUILD_ID, monolith.sh prod mantiene el admin vivo y http://192.168.18.93:3004/ responde 200.

Pending tickets (2026-08-21)

Pendientes: F-100 (descartable, sustituida por F-109), F-101, F-102, F-107, F-108, F-109, F-110, F-111, F-112.

Orden sugerido: F-108 → F-109 → F-107 → F-110 → F-111 → F-101 → F-102 → F-112.

Redefiniciones de intake del operador (2026-08-21)

  • F-101 (alcance reducido): El renderizado actual de descripciones IA ya funciona. Solo queda justificar el texto de la descripción en la ficha de producto del frontend. NO hace falta conversión Markdown→HTML.
  • F-102 (redefinida): El peso del producto es 1 por unidad (si pide 3, peso = 3 × peso unitario). Lo llamado "pack" es en realidad un selector de compra mínima: cantidad mínima de compra por producto; el frontend bloquea la compra por debajo de ese mínimo. Además, nueva opción de envío: límite de envío gratuito por rango de peso en cada tipo de envío y un max weight por tipo de envío.
  • F-112 (nueva): Disclaimer de contenido IA en fichas de producto del frontend:
    • "Parte del contenido de esta ficha puede haber sido generado o asistido mediante inteligencia artificial y revisado antes de su publicación."
    • "La composición y características del producto pueden cambiar. Consulta siempre la etiqueta y la información del fabricante antes de consumirlo o utilizarlo."

Nota de intake (2026-08-20)

El operador reportó ERR_CONNECTION_REFUSED en :3004. El triage lo une a F-085 (cambio parcial sin actualizar la firma TS). Se crea F-088 para reparar la regresión sin reabrir F-085, y se ejecuta por orquestra secuencial.