Files
mercadodevida/work/artifacts/F-069/implementer.md
2026-08-19 18:09:23 +02:00

5.0 KiB

F-069 — Implementer evidence

Scope delivered

Shipping method names ("Estandar", "Express 24h") and prices lived in shipping_methods, but the descriptive text the storefront checkout shows under each method was hardcoded in CheckoutClient.tsx. Admin edits to the name and price did update the catalog, but the marketing description ("Entrega 3-5 días laborables") could not be changed without a code deploy. This fix makes the description a first-class field on shipping_methods and edits it from the admin.

Changes

Migration

project/migrations/029_shipping_method_description.js (new)

ALTER TABLE shipping_methods
  ADD COLUMN IF NOT EXISTS description text;

Applied via node-pg-migrate up.

Backend

project/src/modules/shipping/api/shipping.routes.ts

  • methodBodySchema accepts an optional description string (max 500 chars).
  • POST /shipping/methods writes the new column.
  • GET /admin/shipping/methods returns description per row.
  • PATCH /admin/shipping/methods/:id accepts a description patch.
  • New public GET /shipping/methods?country=…&postalCode=… joins shipping_zones (active, country + postal prefix match) and shipping_methods (active) and returns the catalogue the storefront checkout needs. The response includes description for each method.

Admin UI

project/apps/admin/src/lib/api-client.ts

  • ShippingMethod type gains description: string | null.
  • createMethod / updateMethod payloads accept description.

project/apps/admin/src/app/(dashboard)/shipping/page.tsx

  • MethodRow shows the truncated description under the method name.
  • MethodForm gains a description input below the name; both create and update paths persist it.

Storefront proxy

project/frontend/src/app/api/shipping/methods/route.ts (new)

Thin GET proxy that forwards query params to the backend /shipping/methods.

Checkout

project/frontend/src/components/checkout/CheckoutClient.tsx

  • New ShippingMethod interface.
  • New useEffect that fetches /api/shipping/methods on mount and defaults the selection to the first method.
  • The "Método de envío" radio list now renders one card per real method from the API: name, optional description, optional "Envío gratis aplicado" badge when freeShippingThresholdCents is met, and the formatted price. The hardcoded [{id:'standard',…},{id:'express',…}] array is gone.
  • The summary panel and the order payload both source the cost from the selected method (selectedShippingMethod?.baseCostCents ?? 0) instead of a hardcoded 899 / 499.

Acceptance traceability

Acceptance criterion How it is met
Shipping methods table has a description column Migration 029 added shipping_methods.description text.
Admin can edit description from /shipping MethodForm has a description input; shippingApi.createMethod / updateMethod payloads include description; admin GET returns the field; PATCH writes it.
Storefront /checkout fetches methods and shows the description under each one CheckoutClient calls fetch('/api/shipping/methods') on mount; each radio card renders opt.description.
Public endpoint returns methods with description GET /shipping/methods?country=ES returns two methods, each with the description we just wrote. Verified end-to-end with curl.
verify.sh is green Exit 0.

Manual verification

# Public catalogue after the admin edits the descriptions
$ curl 'http://192.168.18.93:3000/shipping/methods?country=ES'
{
  "items": [
    { "id": "c57cf1bc-…", "name": "Estandar",  "baseCostCents": 599,
      "description": "Entrega 3-5 días laborables",
      "freeShippingThresholdCents": 5900 },
    { "id": "1d3979fb-…", "name": "Express 24h", "baseCostCents": 999,
      "description": "Entrega al día siguiente" }
  ]
}

# Admin list reflects the same
$ curl 'http://192.168.18.93:3004/api/admin/shipping/methods' -b /tmp/admin_cookies.txt
[ same shape, both with description populated ]

Build verification

  • npm run typecheck (backend) — exit 0
  • npm run build (backend) — exit 0
  • npm test (backend) — 124 passed, 56 skipped
  • npx tsc --noEmit (frontend / admin) — exit 0
  • Migration node-pg-migrate up — applied
  • monolith.sh prod restart backend admin frontend → 200 on all
  • ./scripts/verify.sh — exit 0

Files touched

project/migrations/029_shipping_method_description.js                          (new)
project/src/modules/shipping/api/shipping.routes.ts                            (description field + public GET)
project/apps/admin/src/lib/api-client.ts                                      (ShippingMethod.description)
project/apps/admin/src/app/(dashboard)/shipping/page.tsx                      (MethodRow + MethodForm description)
project/frontend/src/app/api/shipping/methods/route.ts                        (new proxy)
project/frontend/src/components/checkout/CheckoutClient.tsx                   (fetch + render real methods)