# FEATURE GAP MATRIX **Project**: MercadoDeVida vNext **Inspected**: 2026-08-17 **Backend**: project/src/ | **Storefront**: project/frontend/src/ | **Admin**: project/apps/admin/src/ --- ## FEATURE A — Expiration Tracking | Aspect | Status | Details | |--------|--------|---------| | Product model | ⚠️ PARTIAL | Has `ProductState`, no `expiration_tracking_enabled` | | Inventory model | ⚠️ PARTIAL | `inventory_stock` at variant level only; no lots | | Inventory repository | ✅ EXISTS | `PgInventoryRepository` (variant-level) | | Lot model | ❌ MISSING | `inventory_lots` table does not exist | | Lot repository | ❌ MISSING | No lot-level persistence | | LotService | ❌ MISSING | Domain service for FEFO + expiry validation | | InventoryService extended | ❌ MISSING | Delegates to LotService for expiry products | | Checkout integration | ✅ EXISTS | Uses `InventoryServicePort` — boundary correct | | GET /inventory/lots | ❌ MISSING | Need this route | | POST /inventory/lots | ❌ MISSING | Need this route | | PATCH /inventory/lots/:id | ❌ MISSING | Need this route | | DELETE /inventory/lots/:id | ❌ MISSING | Need this route | | GET /inventory/lots with filter | ❌ MISSING | Need ?filter=expiring\|expired\|all | | Admin product editor | ⚠️ PARTIAL | Has General/Pricing/Inventory/Images/SEO/Publish tabs; no expiry toggle | | Admin inventory view | ⚠️ PARTIAL | Shows variant stock; no lots | | Admin expiry filters | ❌ MISSING | Need filter tabs in /admin/inventory | | Audit for lot mutations | ⚠️ PARTIAL | `AuditLogger` exists; new operation types needed | | Feature flag | ✅ EXISTS | `FLAG_EXPIRY_TRACKING` can be used | | DB migration | ❌ MISSING | inventory_lots table, column on catalog_products | **Backend blockers**: None — can implement in isolation **DB blocker**: EXP-DB-001 must run before EXP-BE-005 (InventoryService extension) --- ## FEATURE B — Brand Migration | Aspect | Status | Details | |--------|--------|---------| | Tailwind @theme tokens | ✅ EXISTS | `--color-primary: #2D6A4F`, `--color-accent: #E76F51`, fonts set | | Google Fonts (Inter + Playfair) | ✅ EXISTS | Loaded in globals.css | | businessConfig | ❌ MISSING | No single source of truth for company info | | Official logo | ❌ MISSING | Not downloaded; no file in /public/images | | Header component | ✅ EXISTS | Has logo slot; needs actual logo + businessConfig | | Footer component | ✅ EXISTS | Needs businessConfig + social links | | /about page | ✅ EXISTS | Has placeholder content; needs legacy migration | | /contact page | ✅ EXISTS | Has placeholder content; needs real contact info | | /shipping page | ✅ EXISTS | Needs enhancement with real policy | | /terms page | ✅ EXISTS | Needs legacy migration + legal review | | /privacy page | ✅ EXISTS | Needs creation from scratch | | /cookies page | ✅ EXISTS | Needs creation from scratch | | /legal page | ⚠️ PARTIAL | May not exist | | Legacy redirect map | ⚠️ PARTIAL | Partially mapped; needs full sitemap extraction | | next.config.ts redirects | ⚠️ PARTIAL | Some routes exist; needs completion + product slugs | | sitemap.ts | ✅ EXISTS | Needs updating to include migrated routes | | robots.ts | ✅ EXISTS | Needs updating for new site structure | | Admin sidebar logo | ⚠️ PARTIAL | Has inline SVG; needs real logo | | Admin branding | ✅ EXISTS | Same tokens as storefront | **Backend blockers**: None **⚠️ Warning**: Legal pages require human review before publishing --- ## FEATURE C — Bulk Update | Aspect | Status | Details | |--------|--------|---------| | BulkOperationHandler port | ❌ MISSING | Interface for pluggable handlers | | Price handlers (5 ops) | ❌ MISSING | SET, INCREASE/DECREASE (%, fixed) | | Category handlers (3 ops) | ❌ MISSING | ADD, REMOVE, REPLACE | | BulkService orchestrator | ❌ MISSING | preview() + execute() + audit | | BulkProductRepository | ❌ MISSING | Batch read with pricing join | | Bulk API routes | ❌ MISSING | POST /admin/bulk/preview, POST /admin/bulk/execute | | PricingService | ✅ EXISTS | `netUnitAmountCents`, VAT calculation | | ProductRepository | ✅ EXISTS | Has `update(id, patch)` | | Category API | ✅ EXISTS | Categories managed via product.categoryIds | | AuditLogger | ✅ EXISTS | `security_audit_log` table exists | | RBAC | ✅ EXISTS | `permissions.ts` with `products.bulk_update` can be added | | Feature flag | ✅ EXISTS | `FLAG_ADMIN_BULK_UPDATE` can be used | | Admin product list | ✅ EXISTS | Checkbox selection is feasible | | Admin bulk update page | ❌ MISSING | New /admin/bulk-update route | | Navigation entry | ⚠️ PARTIAL | Need to add to NAV_ITEMS | **Backend blockers**: None — all components can be built in isolation **⚠️ Critical**: No bulk update should be exposed without confirmation UI --- ## API Changes Required ### New Endpoints (Backend) | Endpoint | Method | Auth | Purpose | |----------|--------|------|---------| | `/inventory/lots` | GET | admin | List lots with filter | | `/inventory/lots` | POST | admin | Create lot | | `/inventory/lots/:id` | PATCH | admin | Update lot | | `/inventory/lots/:id` | DELETE | admin | Delete lot | | `/admin/bulk/preview` | POST | admin | Dry-run bulk operation | | `/admin/bulk/execute` | POST | admin | Execute bulk operation | ### Modified Endpoints | Endpoint | Change | Reason | |---------|--------|--------| | `GET /products/:id` | + `expiration_tracking_enabled` field | Product expiry policy | | `PATCH /products/:id` | + accepts `expiration_tracking_enabled` | Set product expiry policy | | `PUT /inventory/:variantId/stock` | Consider deprecating in favor of lots | For expiry products | ### No Changes Required - `POST /cart`, `POST /checkout` — use InventoryServicePort unchanged - `GET /products/search` — unchanged - `GET /categories/tree` — unchanged - `GET /brands` — unchanged --- ## Database Changes Required ### New Tables | Table | Purpose | |-------|---------| | `inventory_lots` | Per-arrival stock with expiration date | | `inventory_lot_movements` | Optional: movement tracking per lot | ### Modified Tables | Table | Change | Default | |-------|--------|---------| | `catalog_products` | + `expiration_tracking_enabled boolean` | `false` | | `inventory_movements` | + `lot_id uuid` (nullable) | `NULL` | | `inventory_movements` | + new operation types | — | ### Indexes | Index | Table | Columns | |-------|-------|---------| | `inventory_lots_variant_id_idx` | `inventory_lots` | `variant_id` | | `inventory_lots_expiration_idx` | `inventory_lots` | `expiration_date` (partial) | --- ## STOREFRONT Changes ### Expected: NONE **Expiration**: Checkout uses `InventoryServicePort` unchanged. No lot querying from frontend. No expiration display requirement from product team. **Branding**: Storefront touches every visual component (Header, Footer, pages). Changes scoped to: tokens, logo, static pages, redirects. **Bulk Update**: ZERO storefront changes. Bulk update is an Admin-only feature. Storefront automatically reflects updated prices/categories because it reads from the same backend. --- ## Cross-Feature Impact ``` FEATURE A (Expiration) ┌─ EXP-BE-005 (InventoryService extension) │ └─ Checkout uses InventoryServicePort → NO CHANGE to checkout code │ └─ Unit test regression required │ └─ EXP-ADM-002/003/004 (Admin lot UI) └─ Uses new lot API routes FEATURE B (Branding) ┌─ Token updates may touch frontend + admin globals.css │ └─ Build verification required on both apps │ └─ Redirects in next.config.ts └─ May conflict with existing routes → verify no overlap FEATURE C (Bulk Update) ┌─ Bulk write to catalog_products (prices, categories) │ └─ Storefront reads same DB → no code change needed │ └─ New admin route /admin/bulk-update └─ No conflict with existing routes ``` --- ## Implementation Order ``` 1. EXPIRATION ├─ BE: EXP-BE-001 (product column) ──┐ ├─ BE: EXP-BE-002 (lot model) ──────────┼── parallel └─ DB: EXP-DB-001 (run migrations) ────┘ │ 2. EXPIRATION ├─ BE: EXP-BE-003 (LotService) ────────▶ EXP-BE-004 (lot routes) │ │ └─ BE: EXP-BE-005 (InventoryService) ◀──────┘ │ 3. BRAND + BULK (parallel) ├─ BRAND: BRAND-FE-001..003 (assets, config) ──▶ BRAND-FE-004..009 (pages, redirects) └─ BULK: BULK-BE-001..008 (all backend) ──────────────────▶ BULK-ADM-001..005 │ 4. ALL FEATURES ├─ QA: EXP-QA-001 + BULK-QA-001 (E2E regression) ├─ BRAND: Legal pages human review └─ FLAGS: Flip feature flags when ready ``` --- ## Feature Flags Needed | Flag | Feature | Default | |------|---------|---------| | `expiration_tracking` | Expiration tracking (lot model + FEFO) | `false` | | `admin_bulk_update` | Bulk update module in admin | `false` | Branding has no feature flag — purely additive changes that cannot break existing functionality.