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
methodBodySchemaaccepts an optionaldescriptionstring (max 500 chars).POST /shipping/methodswrites the new column.GET /admin/shipping/methodsreturnsdescriptionper row.PATCH /admin/shipping/methods/:idaccepts adescriptionpatch.- New public
GET /shipping/methods?country=…&postalCode=…joinsshipping_zones(active, country + postal prefix match) andshipping_methods(active) and returns the catalogue the storefront checkout needs. The response includesdescriptionfor each method.
Admin UI
project/apps/admin/src/lib/api-client.ts
ShippingMethodtype gainsdescription: string | null.createMethod/updateMethodpayloads acceptdescription.
project/apps/admin/src/app/(dashboard)/shipping/page.tsx
MethodRowshows the truncated description under the method name.MethodFormgains 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
ShippingMethodinterface. - New
useEffectthat fetches/api/shipping/methodson 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
freeShippingThresholdCentsis 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 hardcoded899 / 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 0npm run build(backend) — exit 0npm test(backend) — 124 passed, 56 skippednpx 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)