221 lines
9.0 KiB
Markdown
221 lines
9.0 KiB
Markdown
# 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.
|