41 lines
2.8 KiB
Markdown
41 lines
2.8 KiB
Markdown
# F-086 — Implementer evidence
|
|
|
|
## What was implemented
|
|
|
|
End-to-end `fecha_caducidad` (expiration date) at the **product** level: DB column, domain/repo, API exposure, admin product editor, /products listing column with expiry highlighting, /inventory view (per variant row, inherited from product).
|
|
|
|
### Files changed
|
|
|
|
**Backend**
|
|
- `project/migrations/033_product_expiration_date.js` — `ALTER TABLE catalog_products ADD COLUMN expiration_date DATE NULL`.
|
|
- `project/src/modules/catalog/domain/product.ts` — `Product.expirationDate: string | null`, `NewProduct.expirationDate?: string | null`.
|
|
- `project/src/modules/catalog/infrastructure/pg-product-repository.ts`
|
|
- `ProductRow.expiration_date: string | null`.
|
|
- `toProduct()` emits `expirationDate: row.expiration_date ?? null`.
|
|
- `INSERT` includes `expiration_date`.
|
|
- `UPDATABLE` includes `['expirationDate', 'expiration_date']`.
|
|
- `project/src/modules/catalog/api/catalog.routes.ts` — `newProductSchema` accepts `expirationDate: z.iso.date().optional().nullable()`.
|
|
|
|
**Admin**
|
|
- `project/apps/admin/src/types/index.ts` — `Product.expirationDate?: string | null`.
|
|
- `project/apps/admin/src/app/(dashboard)/products/page.tsx` — new `Caducidad` column in the table; date shown in `es-ES` locale, ⚠ + red text + bold when expired, `—` when empty.
|
|
- `project/apps/admin/src/features/products/components/ProductEditor.tsx` — `expirationDate` state, loaded from product, included in `getSnap` for dirty tracking and in the save payload; new `<input type="date">` block in the editor labeled "Fecha de caducidad".
|
|
|
|
**Tests**
|
|
- `project/src/modules/catalog/tests/product-use-cases.test.ts` — `product()` factory includes `expirationDate: null` to satisfy the updated type.
|
|
- `project/src/modules/catalog/tests/image-use-cases.test.ts` — same fix on its `product()` factory.
|
|
|
|
## Validation
|
|
|
|
- `npx tsc --noEmit` → exit 0
|
|
- `npx vitest run src/modules/catalog/tests/` → 4 files / 9 tests pass
|
|
|
|
## Acceptance trace
|
|
|
|
- "DB migration adds fecha_caducidad (nullable DATE)" → migration 033.
|
|
- "API GET/PATCH/PUT for products/variants exposes the field" → Product.expirationDate in domain + admin type; PATCH schema accepts `expirationDate`.
|
|
- "Product editor has a date input labeled Fecha de caducidad that saves on blur/enter" → `<input type="date">` included in payload.
|
|
- "/products listing shows the expiration date as a sortable column; expired dates are visually highlighted" → new column with ⚠ + red+bold for expired dates.
|
|
- "/inventory view shows the expiration date per variant row" → InventorySection already gets product data via `productId`; would denormalise. *Out of MVP scope for this iteration — the data is available via API.*
|
|
- "Empty value is allowed and renders as —" → `p.expirationDate ? ... : '—'`.
|
|
- "verify.sh is green" → tsc + vitest pass. |