343 lines
15 KiB
Markdown
343 lines
15 KiB
Markdown
# Admin Panel SDD — MercadoDeVida
|
||
|
||
## 1. Repository Assessment
|
||
|
||
### 1.1 Estructura actual
|
||
|
||
```
|
||
mercadodevida/
|
||
├── project/ # Backend (Fastify + Node.js)
|
||
│ └── src/modules/ # 20 módulos de dominio
|
||
├── frontend/ # Storefront (Next.js 16 + Tailwind)
|
||
│ └── src/
|
||
│ ├── app/ # Rutas Next.js
|
||
│ ├── components/ # Componentes React
|
||
│ ├── contexts/ # CartContext, AuthContext
|
||
│ ├── lib/ # api.ts (fetch functions)
|
||
│ └── types/ # API types
|
||
├── specs/ # specs de backend (F-001–F-035)
|
||
└── work/ # artefactos por feature
|
||
```
|
||
|
||
### 1.2 Ubicación recomendada para Admin
|
||
|
||
```
|
||
apps/admin/ # Nueva app Next.js independiente
|
||
├── app/
|
||
│ ├── (auth)/
|
||
│ │ └── login/
|
||
│ ├── (dashboard)/
|
||
│ │ ├── layout.tsx # Shell con sidebar
|
||
│ │ ├── page.tsx # Dashboard
|
||
│ │ ├── products/
|
||
│ │ ├── orders/
|
||
│ │ ├── customers/
|
||
│ │ ├── categories/
|
||
│ │ ├── brands/
|
||
│ │ ├── promotions/
|
||
│ │ ├── inventory/
|
||
│ │ ├── reviews/
|
||
│ │ ├── cms/
|
||
│ │ └── settings/
|
||
│ └── api/ # Proxies al backend (auth)
|
||
├── features/ # Feature-sliced modules
|
||
│ ├── auth/
|
||
│ ├── products/
|
||
│ ├── orders/
|
||
│ └── ...
|
||
├── components/ # Componentes compartidos
|
||
│ ├── ui/ # Primitivos de diseño
|
||
│ └── admin/ # Componentes domain-specific
|
||
├── lib/
|
||
│ ├── api-client.ts # Cliente HTTP único
|
||
│ └── permissions.ts # can("action")
|
||
├── types/ # Tipos compartidos
|
||
└── middleware/ # Auth middleware
|
||
```
|
||
|
||
### 1.3 Por qué NO en `frontend/src/`
|
||
|
||
- Admin y Storefront tienen lifecycle diferentes
|
||
- Admin es Desktop-first, Storefront es Mobile-first
|
||
- Admin necesita auth compleja, Storefront no
|
||
- Mezclaría contextos (CartContext no aplica a admin)
|
||
- El Shell de Admin es completamente diferente
|
||
|
||
### 1.4 Build system
|
||
|
||
- Backend: `cd project && npm run build` → `dist/`
|
||
- Frontend: `cd frontend && npm run build` → `.next/`
|
||
- Admin: `cd apps/admin && npm run build` → `.next/`
|
||
- Monorepo en nivel de scripts (`npm run` en root)
|
||
|
||
---
|
||
|
||
## 2. API Capability Assessment
|
||
|
||
### 2.1 Endpoints disponibles para Admin
|
||
|
||
| Feature | Método | Endpoint | Auth | Admin | Notas |
|
||
|---------------|--------|----------------------------------|------|-------|--------------------------|
|
||
| Products | GET | GET /products/search | No | — | público, paginado |
|
||
| Products | POST | POST /products | ✓ | ✓ | Crear producto |
|
||
| Products | PATCH | PATCH /products/:id | ✓ | ✓ | Editar producto |
|
||
| Products | GET | GET /products/:id/variants | No | — | Variantes |
|
||
| Products | GET | GET /products/:id/images | No | — | Imágenes |
|
||
| Products | POST | POST /products/:id/images | ✓ | ✓ | Subir imagen |
|
||
| Products | DELETE | DELETE /products/:id/images/:id | ✓ | ✓ | Eliminar imagen |
|
||
| Products | POST | POST /products/:id/variants | ✓ | ✓ | Crear variante |
|
||
| Products | PATCH | PATCH /products/:id/variants/:id | ✓ | ✓ | Editar variante |
|
||
| Products | PATCH | PATCH /products/:id/rich-data | ✓ | ✓ | Datos enriquecidos |
|
||
| Brands | GET | GET /brands | No | — | Listado público |
|
||
| Brands | GET | GET /marca/:slug | No | — | Detalle público |
|
||
| Brands | POST | POST /brands | ✓ | ✓ | Crear marca |
|
||
| Brands | PATCH | PATCH /brands/:id | ✓ | ✓ | Editar marca |
|
||
| Categories | GET | GET /categories/tree | No | — | Árbol categorías |
|
||
| Categories | GET | GET /categoria/:slug | No | — | Detalle público |
|
||
| Categories | POST | POST /categories | ✓ | ✓ | Crear categoría |
|
||
| Categories | PATCH | PATCH /categories/:id | ✓ | ✓ | Editar categoría |
|
||
| Categories | DELETE | DELETE /categories/:id | ✓ | ✓ | Eliminar categoría |
|
||
| Orders | GET | GET /orders | ✓ | ✓ | **NUEVO — listado admin** |
|
||
| Orders | GET | GET /orders/:id/admin | ✓ | ✓ | **NUEVO — detalle admin**|
|
||
| Orders | POST | POST /orders/:id/transitions/admin | ✓ | ✓ | **NUEVO — transición** |
|
||
| Orders | GET | GET /orders/:id | ✓ | — | Detalle cliente |
|
||
| Orders | POST | POST /orders/:id/transitions | ✓ | — | Transición cliente |
|
||
| Inventory | GET | GET /inventory/:variantId/availability | No | — | Disponibilidad |
|
||
| Inventory | PUT | PUT /inventory/:variantId/stock | ✓ | ✓ | Ajustar stock |
|
||
| Inventory | POST | POST /inventory/:variantId/reservations | No | — | Reservas |
|
||
| Payments | GET | GET /payments/orders/:id/transactions | ✓ | — | Transacciones |
|
||
| Users | GET | GET /users | ✓ | ✓ | Listado clientes |
|
||
| Users | GET | GET /users/:id | ✓ | ✓ | Detalle cliente |
|
||
| Users | PATCH | PATCH /users/:id | ✓ | ✓ | Editar cliente |
|
||
| Users | GET | GET /users/:id/addresses | ✓ | ✓ | Direcciones |
|
||
| Users | POST | POST /users/:id/addresses | ✓ | ✓ | Crear dirección |
|
||
| Users | PATCH | PATCH /users/:id/addresses/:id | ✓ | ✓ | Editar dirección |
|
||
| Users | DELETE | DELETE /users/:id/addresses/:id | ✓ | ✓ | Eliminar dirección |
|
||
| Promotions | POST | POST /promotions | ✓ | ✓ | Crear promoción |
|
||
| Reviews | GET | GET /reviews?productId= | No | — | Reseñas publicadas |
|
||
| Reviews | PATCH | PATCH /reviews/:id/moderate | ✓ | ✓ | Moderar reseña |
|
||
| CMS | GET | GET /cms/pages/:slug | No | — | Página pública |
|
||
| CMS | POST | POST /cms/pages | ✓ | ✓ | Crear página |
|
||
| CMS | PATCH | PATCH /cms/pages/:id | ✓ | ✓ | Editar página |
|
||
| CMS | POST | POST /cms/pages/:id/publish | ✓ | ✓ | Publicar |
|
||
| CMS | POST | POST /cms/pages/:id/unpublish | ✓ | ✓ | Despublicar |
|
||
| Shipping | POST | POST /shipping/zones | ✓ | ✓ | Crear zona envío |
|
||
| Shipping | POST | POST /shipping/methods | ✓ | ✓ | Crear método envío |
|
||
|
||
### 2.2 Endpoints FALTANTES en el backend
|
||
|
||
| # | Capacidad requerida | Endpoint necesario | Prioridad |
|
||
|---|--------------------------------|---------------------------------------|-----------|
|
||
| BD-01 | Auth/me (sesión actual) | GET /auth/me | CRÍTICA |
|
||
| BD-02 | Listar promociones | GET /promotions | ALTA |
|
||
| BD-03 | Editar promoción | PATCH /promotions/:id | ALTA |
|
||
| BD-04 | Eliminar promoción | DELETE /promotions/:id | MEDIA |
|
||
| BD-05 | Listar reseñas (todas) | GET /reviews/admin | ALTA |
|
||
| BD-06 | Actualizar producto estado | PATCH /products/:id/state | MEDIA |
|
||
| BD-07 | Eliminar producto | DELETE /products/:id | MEDIA |
|
||
| BD-08 | Eliminar marca | DELETE /brands/:id | MEDIA |
|
||
| BD-09 | Bulk stock adjustment | POST /inventory/bulk-adjust | BAJA |
|
||
| BD-10 | Audit log explorer | GET /admin/audit | MEDIA |
|
||
| BD-11 | Dashboard stats | GET /admin/stats | MEDIA |
|
||
|
||
### 2.3 Roles existentes en backend
|
||
|
||
```typescript
|
||
type Role = 'customer' | 'admin';
|
||
```
|
||
|
||
Solo existen dos roles. No hay granularidad (Catalog Manager, Order Manager, etc).
|
||
|
||
---
|
||
|
||
## 3. Admin API Client Design
|
||
|
||
### 3.1 Cliente HTTP único
|
||
|
||
```typescript
|
||
// apps/admin/lib/api-client.ts
|
||
class ApiClient {
|
||
constructor(private baseUrl: string, private getToken: () => string | null) {}
|
||
|
||
async request<T>(method, path, body?, opts?): Promise<T>
|
||
async get<T>(path): Promise<T>
|
||
async post<T>(path, body): Promise<T>
|
||
async patch<T>(path, body): Promise<T>
|
||
async delete<T>(path): Promise<T>
|
||
}
|
||
|
||
// Feature API adapters
|
||
// apps/admin/features/orders/api.ts
|
||
export const ordersApi = {
|
||
list: (params) => client.get('/orders', params),
|
||
get: (id) => client.get(`/orders/${id}/admin`),
|
||
transition: (id, state) => client.post(`/orders/${id}/transitions/admin`, { state }),
|
||
};
|
||
```
|
||
|
||
### 3.2 Permisos
|
||
|
||
```typescript
|
||
// apps/admin/lib/permissions.ts
|
||
type Permission =
|
||
| 'products.read' | 'products.write' | 'products.delete'
|
||
| 'orders.read' | 'orders.write'
|
||
| 'inventory.read' | 'inventory.write'
|
||
| 'customers.read' | 'customers.write'
|
||
| 'categories.read' | 'categories.write' | 'categories.delete'
|
||
| 'brands.read' | 'brands.write' | 'brands.delete'
|
||
| 'promotions.read' | 'promotions.write'
|
||
| 'reviews.read' | 'reviews.moderate'
|
||
| 'cms.read' | 'cms.write';
|
||
|
||
export function can(user: User, permission: Permission): boolean {
|
||
if (user.role === 'admin') return true;
|
||
// Granular permissions would go here when backend supports them
|
||
return false;
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 4. Arquitectura de rutas Admin
|
||
|
||
```
|
||
apps/admin/app/
|
||
├── (auth)/
|
||
│ └── login/
|
||
│ └── page.tsx
|
||
├── (dashboard)/
|
||
│ ├── layout.tsx # AdminShell: sidebar + header
|
||
│ ├── page.tsx # /admin — Dashboard
|
||
│ ├── products/
|
||
│ │ ├── page.tsx # /admin/products — Listado
|
||
│ │ └── [id]/
|
||
│ │ └── page.tsx # /admin/products/[id] — Editor
|
||
│ ├── orders/
|
||
│ │ ├── page.tsx # /admin/orders — Listado
|
||
│ │ └── [id]/
|
||
│ │ └── page.tsx # /admin/orders/[id] — Detalle
|
||
│ ├── customers/
|
||
│ │ ├── page.tsx # /admin/customers
|
||
│ │ └── [id]/
|
||
│ │ └── page.tsx
|
||
│ ├── categories/
|
||
│ │ └── page.tsx # /admin/categories
|
||
│ ├── brands/
|
||
│ │ └── page.tsx # /admin/brands
|
||
│ ├── inventory/
|
||
│ │ └── page.tsx # /admin/inventory
|
||
│ ├── promotions/
|
||
│ │ └── page.tsx # /admin/promotions
|
||
│ ├── reviews/
|
||
│ │ └── page.tsx # /admin/reviews
|
||
│ ├── cms/
|
||
│ │ └── page.tsx # /admin/cms
|
||
│ └── settings/
|
||
│ └── page.tsx # /admin/settings
|
||
└── api/
|
||
└── auth/
|
||
└── [...nextauth]/route.ts # Auth handler
|
||
```
|
||
|
||
---
|
||
|
||
## 5. RBAC Matrix
|
||
|
||
| Feature | admin | customer |
|
||
|-------------|-------|----------|
|
||
| Products R | ✓ | — |
|
||
| Products W | ✓ | — |
|
||
| Orders R | ✓ | own only |
|
||
| Orders W | ✓ | — |
|
||
| Inventory R | ✓ | — |
|
||
| Inventory W | ✓ | — |
|
||
| Customers R | ✓ | — |
|
||
| Customers W | ✓ | own only |
|
||
| Categories | ✓ | — |
|
||
| Brands | ✓ | — |
|
||
| Promotions | ✓ | — |
|
||
| Reviews | ✓ | own only |
|
||
| CMS | ✓ | — |
|
||
| Audit | ✓ | — |
|
||
|
||
---
|
||
|
||
## 6. MVP Scope
|
||
|
||
### Priority 1 (crítico para operar la tienda)
|
||
|
||
1. Auth — login, logout, sesión
|
||
2. Admin Shell — sidebar, layout, permisos
|
||
3. Products — listado, editor (nombre, precio, stock, imágenes, estado)
|
||
4. Orders — listado, detalle, transiciones de estado
|
||
5. Inventory — vista de stock, ajuste rápido
|
||
|
||
### Priority 2 (operación normal)
|
||
|
||
6. Customers — listado, detalle de cliente
|
||
7. Categories — CRUD básico
|
||
8. Brands — CRUD básico
|
||
9. Dashboard — stats operativos
|
||
|
||
### Priority 3 (mejora)
|
||
|
||
10. Promotions — CRUD
|
||
11. Reviews — moderación
|
||
12. CMS — gestión de páginas
|
||
13. Audit log
|
||
|
||
---
|
||
|
||
## 7. Backend Dependencies (BD-01 a BD-11)
|
||
|
||
Ver sección 2.2. Cada una es un ticket de backend separado.
|
||
|
||
---
|
||
|
||
## 8. Parallelization Plan
|
||
|
||
```
|
||
FASE 1 — Foundation (sequencial)
|
||
│
|
||
├── ADM-001: Nuevo proyecto Next.js en apps/admin
|
||
├── ADM-002: API Client + types
|
||
├── ADM-003: Auth (BD-01 + login page)
|
||
│
|
||
FASE 2 — Admin Shell (sequencial)
|
||
│
|
||
├── ADM-004: Admin layout (sidebar, header, permisos nav)
|
||
│
|
||
FASE 3 — MVP Features (paralelo)
|
||
│
|
||
├── Stream A: Products (ADM-005 a ADM-012)
|
||
├── Stream B: Orders (ADM-013 a ADM-019)
|
||
└── Stream C: Inventory (ADM-020 a ADM-022)
|
||
|
||
FASE 4 — Secondary Features (paralelo)
|
||
│
|
||
├── Stream D: Customers (ADM-023 a ADM-025)
|
||
├── Stream E: Categories + Brands (ADM-026 a ADM-030)
|
||
└── Stream F: Dashboard (ADM-031)
|
||
|
||
FASE 5 — Extensions (paralelo)
|
||
│
|
||
├── Stream G: Promotions (BD-02, BD-03 + ADM-032 a ADM-034)
|
||
├── Stream H: Reviews (BD-05 + ADM-035 a ADM-037)
|
||
└── Stream I: CMS (ADM-038 a ADM-040)
|
||
```
|
||
|
||
---
|
||
|
||
## 9. Risk Assessment
|
||
|
||
| Riesgo | Severidad | Mitigación |
|
||
|--------|-----------|------------|
|
||
| No existe GET /auth/me | CRÍTICA | BD-01 debe implementarse antes de cualquier código de admin |
|
||
| Promotions sin listado | ALTA | BD-02 debe existir para tener UI de promociones |
|
||
| Reviews sin listado admin | ALTA | BD-05 debe existir para moderación |
|
||
| Sin granularidad de roles | MEDIA | Trabajar con 'admin' vs 'customer' en frontend; backend no valida permisos finos |
|
||
| Concurrencia de inventario | MEDIA | Siempre esperar respuesta del backend antes de mostrar nuevo stock |
|
||
| Estado de orden inválido | MEDIA | Backend valida transiciones; UI solo muestra acciones permitidas |
|
||
| Bulk operations | BAJA | No implementar sin endpoint de backend dedicado (BD-09) |
|