template-saas/docs/02-especificaciones/ET-SAAS-019-portfolio.md
Adrian Flores Cortes 2825b3d5fd
Some checks are pending
CI / Backend CI (push) Waiting to run
CI / Frontend CI (push) Waiting to run
CI / Security Scan (push) Waiting to run
CI / CI Summary (push) Blocked by required conditions
docs: Add ET-SAAS-018 to ET-SAAS-022 technical specifications
- ET-SAAS-018-sales.md: Sales pipeline/CRM module
- ET-SAAS-019-portfolio.md: Product catalog module
- ET-SAAS-020-commissions.md: Commissions system
- ET-SAAS-021-mlm.md: Multi-Level Marketing module
- ET-SAAS-022-goals.md: Goals and objectives system
- Update _MAP.md with all 9 specifications

All specs document:
- Data model (DDL, enums, tables)
- Backend architecture (endpoints, services)
- Security (RLS, RBAC permissions)
- Frontend status and hooks
- Module integrations

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-03 13:14:48 -06:00

319 lines
9.6 KiB
Markdown

---
id: "ET-SAAS-019"
title: "Especificacion Tecnica Portfolio (Product Catalog)"
type: "TechnicalSpec"
status: "Implemented"
priority: "P1"
module: "portfolio"
version: "1.0.0"
created_date: "2026-02-03"
updated_date: "2026-02-03"
story_points: 8
---
# ET-SAAS-019: Especificacion Tecnica - Portfolio (Catalogo de Productos)
## Metadata
- **Codigo:** ET-SAAS-019
- **Modulo:** Portfolio
- **Version:** 1.0.0
- **Estado:** Implementado
- **Fecha:** 2026-02-03
- **Basado en:** SAAS-019
---
## 1. Resumen Ejecutivo
### 1.1 Estado Actual
Sistema de catalogo de productos completamente implementado.
| Capacidad | Estado | Notas |
|-----------|--------|-------|
| Categories | SI | Jerarquicas con arbol |
| Products | SI | Multi-tipo, inventario |
| Variants | SI | Atributos configurables |
| Prices | SI | Multi-moneda, tiered |
| RLS | SI | Row Level Security |
### 1.2 Funcionalidades v1.0
Catalogo completo con:
- **4 Entidades**: Categories, Products, Variants, Prices
- **Categorias jerarquicas**: Arbol ilimitado con parent_id
- **5 Tipos de producto**: physical, digital, service, subscription, bundle
- **Variantes**: Atributos dinamicos (color, size, etc.)
- **Precios flexibles**: one_time, recurring, usage_based, tiered
---
## 2. Modelo de Datos
### 2.1 Schema: portfolio
#### Tabla: categories
| Campo | Tipo | Descripcion |
|-------|------|-------------|
| id | UUID | PK |
| tenant_id | UUID | FK tenants |
| parent_id | UUID | FK categories (jerarquia) |
| name | VARCHAR(100) | Nombre categoria |
| slug | VARCHAR(120) | URL-friendly (unique per tenant) |
| description | TEXT | Descripcion |
| position | INT | Orden dentro del padre |
| image_url | VARCHAR(500) | Imagen |
| color | VARCHAR(7) | Color hex |
| icon | VARCHAR(50) | Icono |
| is_active | BOOLEAN | Estado |
| meta_title, meta_description | VARCHAR/TEXT | SEO |
| custom_fields | JSONB | Campos personalizados |
#### Tabla: products
| Campo | Tipo | Descripcion |
|-------|------|-------------|
| id | UUID | PK |
| tenant_id | UUID | FK tenants |
| category_id | UUID | FK categories |
| name | VARCHAR(255) | Nombre producto |
| slug | VARCHAR(280) | URL-friendly |
| sku | VARCHAR(100) | Stock Keeping Unit |
| barcode | VARCHAR(100) | Codigo de barras |
| description | TEXT | Descripcion larga |
| short_description | VARCHAR(500) | Descripcion corta |
| product_type | ENUM | physical, digital, service, subscription, bundle |
| status | ENUM | draft, active, inactive, discontinued, out_of_stock |
| base_price | DECIMAL(15,2) | Precio base |
| cost_price | DECIMAL(15,2) | Costo |
| compare_at_price | DECIMAL(15,2) | Precio tachado |
| currency | VARCHAR(3) | Moneda (default USD) |
| track_inventory | BOOLEAN | Trackear inventario |
| stock_quantity | INT | Cantidad en stock |
| low_stock_threshold | INT | Umbral de stock bajo |
| allow_backorder | BOOLEAN | Permitir backorder |
| weight, length, width, height | DECIMAL | Dimensiones |
| images | JSONB | Array de URLs |
| featured_image_url | VARCHAR(500) | Imagen principal |
| tags | JSONB | Array de tags |
| is_visible | BOOLEAN | Visible en frontend |
| is_featured | BOOLEAN | Producto destacado |
| has_variants | BOOLEAN | Tiene variantes |
| variant_attributes | JSONB | Atributos para variantes |
#### Tabla: variants
| Campo | Tipo | Descripcion |
|-------|------|-------------|
| id | UUID | PK |
| tenant_id | UUID | FK tenants |
| product_id | UUID | FK products |
| sku | VARCHAR(100) | SKU de variante |
| barcode | VARCHAR(100) | Codigo de barras |
| name | VARCHAR(255) | Nombre (e.g., "Rojo - XL") |
| attributes | JSONB | {"color": "red", "size": "XL"} |
| price | DECIMAL(15,2) | Override de precio |
| cost_price | DECIMAL(15,2) | Costo variante |
| stock_quantity | INT | Stock de variante |
| weight | DECIMAL(10,3) | Peso (override) |
| image_url | VARCHAR(500) | Imagen de variante |
| is_active | BOOLEAN | Estado |
| position | INT | Orden |
#### Tabla: prices
| Campo | Tipo | Descripcion |
|-------|------|-------------|
| id | UUID | PK |
| tenant_id | UUID | FK tenants |
| product_id | UUID | FK products (o variant_id) |
| variant_id | UUID | FK variants (o product_id) |
| price_type | ENUM | one_time, recurring, usage_based, tiered |
| currency | VARCHAR(3) | Moneda |
| amount | DECIMAL(15,2) | Precio |
| compare_at_amount | DECIMAL(15,2) | Precio comparativo |
| billing_period | VARCHAR(20) | day, week, month, year |
| billing_interval | INT | Intervalo (e.g., 1 = mensual) |
| min_quantity, max_quantity | INT | Rango para tiered |
| valid_from, valid_until | TIMESTAMPTZ | Validez |
| priority | INT | Prioridad (0 = default) |
| is_active | BOOLEAN | Estado |
### 2.2 Enums
```sql
portfolio.product_type: physical, digital, service, subscription, bundle
portfolio.product_status: draft, active, inactive, discontinued, out_of_stock
portfolio.price_type: one_time, recurring, usage_based, tiered
portfolio.attribute_type: color, size, material, style, capacity, custom
```
---
## 3. Arquitectura Backend
### 3.1 Estructura de Archivos
```
backend/src/modules/portfolio/
├── portfolio.module.ts
├── controllers/
│ ├── categories.controller.ts
│ └── products.controller.ts
├── services/
│ ├── categories.service.ts
│ └── products.service.ts
├── entities/
│ ├── category.entity.ts
│ ├── product.entity.ts
│ ├── variant.entity.ts
│ └── price.entity.ts
├── dto/
│ ├── create-category.dto.ts
│ ├── create-product.dto.ts
│ └── ...
└── __tests__/
```
### 3.2 Endpoints API
#### Categories
| Metodo | Endpoint | Descripcion |
|--------|----------|-------------|
| GET | /portfolio/categories | Listar (paginado) |
| GET | /portfolio/categories/tree | Arbol jerarquico |
| GET | /portfolio/categories/:id | Obtener |
| POST | /portfolio/categories | Crear |
| PUT | /portfolio/categories/:id | Actualizar |
| DELETE | /portfolio/categories/:id | Eliminar |
#### Products
| Metodo | Endpoint | Descripcion |
|--------|----------|-------------|
| GET | /portfolio/products | Listar (paginado, filtros) |
| GET | /portfolio/products/:id | Obtener con variantes |
| POST | /portfolio/products | Crear |
| PUT | /portfolio/products/:id | Actualizar |
| PATCH | /portfolio/products/:id/status | Cambiar status |
| POST | /portfolio/products/:id/duplicate | Duplicar |
| DELETE | /portfolio/products/:id | Eliminar |
#### Variants
| Metodo | Endpoint | Descripcion |
|--------|----------|-------------|
| GET | /portfolio/products/:id/variants | Listar variantes |
| POST | /portfolio/products/:id/variants | Crear variante |
| PATCH | /portfolio/products/:id/variants/:vid | Actualizar |
| DELETE | /portfolio/products/:id/variants/:vid | Eliminar |
#### Prices
| Metodo | Endpoint | Descripcion |
|--------|----------|-------------|
| GET | /portfolio/products/:id/prices | Listar precios |
| POST | /portfolio/products/:id/prices | Crear precio |
| PATCH | /portfolio/products/:id/prices/:pid | Actualizar |
| DELETE | /portfolio/products/:id/prices/:pid | Eliminar |
---
## 4. Seguridad
### 4.1 Row Level Security (RLS)
```sql
-- Aislamiento por tenant
CREATE POLICY categories_tenant_isolation ON portfolio.categories
USING (tenant_id = current_setting('app.tenant_id')::uuid);
CREATE POLICY products_tenant_isolation ON portfolio.products
USING (tenant_id = current_setting('app.tenant_id')::uuid);
```
### 4.2 Permisos RBAC
| Permiso | Descripcion |
|---------|-------------|
| portfolio:read | Ver catalogo |
| portfolio:write | Crear/editar productos |
| portfolio:delete | Eliminar productos |
| portfolio:publish | Publicar/despublicar |
| portfolio:manage | Configuracion avanzada |
---
## 5. Frontend
### 5.1 Paginas Implementadas
| Ruta | Componente | Estado |
|------|------------|--------|
| /dashboard/portfolio | PortfolioPage | Implementado |
| /dashboard/portfolio/products | ProductsPage | Implementado |
| /dashboard/portfolio/categories | CategoriesPage | Implementado |
| /dashboard/portfolio/products/:id | ProductDetailPage | Pendiente |
| /dashboard/portfolio/products/new | ProductFormPage | Pendiente |
### 5.2 Hooks
```typescript
// frontend/src/hooks/usePortfolio.ts
useCategories, useCategory, useCategoryTree
useCreateCategory, useUpdateCategory, useDeleteCategory
useProducts, useProduct
useCreateProduct, useUpdateProduct, useDeleteProduct, useDuplicateProduct
useProductVariants, useCreateVariant, useUpdateVariant, useDeleteVariant
useProductPrices, useCreatePrice, useUpdatePrice, useDeletePrice
```
---
## 6. Integraciones
### 6.1 Modulos Relacionados
| Modulo | Integracion |
|--------|-------------|
| sales | Productos en oportunidades |
| commissions | Comisiones por producto/categoria |
| storage | Imagenes de productos |
| audit | Log de cambios |
### 6.2 Eventos Emitidos
```typescript
ProductCreated, ProductUpdated, ProductStatusChanged
CategoryCreated, CategoryUpdated
VariantCreated, PriceUpdated
LowStockAlert // Cuando stock < threshold
```
---
## 7. Filtros y Busqueda
### 7.1 Filtros Disponibles
```typescript
interface ProductFilters {
category_id?: string;
product_type?: ProductType;
status?: ProductStatus;
is_visible?: boolean;
is_featured?: boolean;
min_price?: number;
max_price?: number;
search?: string; // Busca en name, sku, description
tags?: string[];
sort_by?: 'name' | 'price' | 'created_at' | 'stock';
sort_order?: 'ASC' | 'DESC';
}
```
---
## 8. Referencias
- DDL: `database/ddl/schemas/portfolio/`
- Backend: `backend/src/modules/portfolio/`
- Frontend Services: `frontend/src/services/portfolio/`
- Frontend Hooks: `frontend/src/hooks/usePortfolio.ts`
- Frontend Pages: `frontend/src/pages/dashboard/portfolio/`