template-saas/docs/01-modulos/SAAS-019-portfolio.md
Adrian Flores Cortes 7d05081b4d
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
[SAAS-018-022] docs: Add specifications for advanced modules
Add complete specifications for 5 advanced modules:
- SAAS-018 Sales Foundation (21 SP) - Leads, opportunities, pipeline
- SAAS-019 Portfolio (13 SP) - Product/service catalog
- SAAS-020 Commissions (13 SP) - Commission system for salespeople
- SAAS-021 MLM (21 SP) - Multi-level marketing networks
- SAAS-022 Goals (13 SP) - Goals and objectives tracking

Each specification includes:
- Complete DDL with RLS policies
- Full API endpoint documentation
- Frontend pages and components
- Dependencies and integration points
- Story point estimates

Total new SP: 81 (bringing total to 260 SP)
Core modules: 14 (100% complete)
Advanced modules: 5 (specified, ready for implementation)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-24 20:12:07 -06:00

297 lines
7.9 KiB
Markdown

---
id: "SAAS-019"
title: "Portfolio"
type: "Module"
status: "Specified"
priority: "P2"
module: "portfolio"
version: "1.0.0"
created_date: "2026-01-24"
updated_date: "2026-01-24"
estimated_sp: 13
---
# SAAS-019: Portfolio
## Metadata
- **Codigo:** SAAS-019
- **Modulo:** Portfolio
- **Prioridad:** P2
- **Estado:** Especificado
- **Fase:** 6 - Advanced Features
- **Story Points:** 13
## Descripcion
Catalogo de productos y servicios para plataformas SaaS. Permite definir ofertas, precios, categorias y variantes. Se integra con Sales para cotizaciones y con Billing para suscripciones basadas en productos.
## Objetivos
1. Catalogo de productos/servicios configurable
2. Categorias y subcategorias jerarquicas
3. Precios con multiples monedas
4. Variantes de productos (tallas, colores, etc.)
5. Integracion con Sales y Billing
## Alcance
### Incluido
- CRUD de productos/servicios
- Categorias jerarquicas
- Precios por moneda
- Variantes basicas
- Imagenes de productos
- Productos activos/inactivos
- Busqueda y filtros
- Exportacion catalogo
### Excluido
- Inventario (erp-core)
- Ordenes de compra (erp-core)
- Proveedores (erp-core)
- Configurador de productos complejo
## Modelo de Datos
### Schema: portfolio
```sql
-- Categorias
CREATE TABLE portfolio.categories (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL REFERENCES tenants.tenants(id),
name VARCHAR(100) NOT NULL,
slug VARCHAR(100) NOT NULL,
description TEXT,
parent_id UUID REFERENCES portfolio.categories(id),
image_url VARCHAR(500),
position INTEGER DEFAULT 0,
is_active BOOLEAN DEFAULT true,
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW(),
CONSTRAINT unique_category_slug UNIQUE (tenant_id, slug)
);
-- Productos
CREATE TABLE portfolio.products (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
tenant_id UUID NOT NULL REFERENCES tenants.tenants(id),
-- Info basica
name VARCHAR(200) NOT NULL,
slug VARCHAR(200) NOT NULL,
description TEXT,
short_description VARCHAR(500),
-- Clasificacion
type portfolio.product_type NOT NULL DEFAULT 'product',
category_id UUID REFERENCES portfolio.categories(id),
-- Codigo
sku VARCHAR(100),
barcode VARCHAR(100),
-- Precios
base_price DECIMAL(15,2) NOT NULL DEFAULT 0,
currency VARCHAR(3) DEFAULT 'USD',
tax_rate DECIMAL(5,2) DEFAULT 0,
-- Estado
status portfolio.product_status NOT NULL DEFAULT 'draft',
is_featured BOOLEAN DEFAULT false,
-- Media
images JSONB DEFAULT '[]',
thumbnail_url VARCHAR(500),
-- Metadata
tags JSONB DEFAULT '[]',
attributes JSONB DEFAULT '{}',
meta_title VARCHAR(200),
meta_description VARCHAR(500),
-- Audit
created_at TIMESTAMPTZ DEFAULT NOW(),
updated_at TIMESTAMPTZ DEFAULT NOW(),
CONSTRAINT unique_product_slug UNIQUE (tenant_id, slug),
CONSTRAINT unique_product_sku UNIQUE (tenant_id, sku)
);
-- Variantes
CREATE TABLE portfolio.variants (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
product_id UUID NOT NULL REFERENCES portfolio.products(id) ON DELETE CASCADE,
tenant_id UUID NOT NULL REFERENCES tenants.tenants(id),
name VARCHAR(200) NOT NULL,
sku VARCHAR(100),
-- Precio diferencial
price_adjustment DECIMAL(15,2) DEFAULT 0,
price_type portfolio.price_type DEFAULT 'adjustment', -- 'adjustment' | 'fixed'
-- Atributos (color, talla, etc.)
attributes JSONB NOT NULL DEFAULT '{}',
-- Estado
is_active BOOLEAN DEFAULT true,
created_at TIMESTAMPTZ DEFAULT NOW()
);
-- Precios por moneda
CREATE TABLE portfolio.prices (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
product_id UUID NOT NULL REFERENCES portfolio.products(id) ON DELETE CASCADE,
variant_id UUID REFERENCES portfolio.variants(id) ON DELETE CASCADE,
currency VARCHAR(3) NOT NULL,
amount DECIMAL(15,2) NOT NULL,
-- Precios especiales
compare_at_price DECIMAL(15,2), -- Precio tachado
cost_price DECIMAL(15,2), -- Costo
-- Vigencia
starts_at TIMESTAMPTZ,
ends_at TIMESTAMPTZ,
created_at TIMESTAMPTZ DEFAULT NOW(),
CONSTRAINT unique_price UNIQUE (product_id, variant_id, currency)
);
-- Enums
CREATE TYPE portfolio.product_type AS ENUM (
'product', 'service', 'digital', 'subscription'
);
CREATE TYPE portfolio.product_status AS ENUM (
'draft', 'active', 'inactive', 'archived'
);
CREATE TYPE portfolio.price_type AS ENUM (
'adjustment', 'fixed'
);
```
### RLS Policies
```sql
ALTER TABLE portfolio.categories ENABLE ROW LEVEL SECURITY;
ALTER TABLE portfolio.products ENABLE ROW LEVEL SECURITY;
ALTER TABLE portfolio.variants ENABLE ROW LEVEL SECURITY;
ALTER TABLE portfolio.prices ENABLE ROW LEVEL SECURITY;
CREATE POLICY tenant_isolation ON portfolio.products
USING (tenant_id = current_setting('app.current_tenant_id')::UUID);
```
## Endpoints API
### Categories
| Metodo | Endpoint | Descripcion |
|--------|----------|-------------|
| GET | /portfolio/categories | Listar categorias |
| POST | /portfolio/categories | Crear categoria |
| GET | /portfolio/categories/:id | Obtener categoria |
| PATCH | /portfolio/categories/:id | Actualizar categoria |
| DELETE | /portfolio/categories/:id | Eliminar categoria |
| GET | /portfolio/categories/tree | Arbol jerarquico |
### Products
| Metodo | Endpoint | Descripcion |
|--------|----------|-------------|
| GET | /portfolio/products | Listar productos |
| POST | /portfolio/products | Crear producto |
| GET | /portfolio/products/:id | Obtener producto |
| PATCH | /portfolio/products/:id | Actualizar producto |
| DELETE | /portfolio/products/:id | Eliminar producto |
| POST | /portfolio/products/:id/duplicate | Duplicar producto |
| PATCH | /portfolio/products/:id/status | Cambiar estado |
### Variants
| Metodo | Endpoint | Descripcion |
|--------|----------|-------------|
| GET | /portfolio/products/:id/variants | Listar variantes |
| POST | /portfolio/products/:id/variants | Crear variante |
| PATCH | /portfolio/variants/:id | Actualizar variante |
| DELETE | /portfolio/variants/:id | Eliminar variante |
### Prices
| Metodo | Endpoint | Descripcion |
|--------|----------|-------------|
| GET | /portfolio/products/:id/prices | Listar precios |
| POST | /portfolio/products/:id/prices | Agregar precio |
| PATCH | /portfolio/prices/:id | Actualizar precio |
| DELETE | /portfolio/prices/:id | Eliminar precio |
## Frontend
### Paginas
- `/portfolio` - Dashboard catalogo
- `/portfolio/products` - Lista de productos
- `/portfolio/products/new` - Crear producto
- `/portfolio/products/:id` - Editar producto
- `/portfolio/categories` - Gestion categorias
### Componentes
- `ProductsList` - Tabla/grid de productos
- `ProductForm` - Formulario producto completo
- `ProductCard` - Tarjeta preview
- `VariantsManager` - Gestion variantes
- `PricesManager` - Gestion precios multi-moneda
- `CategoryTree` - Arbol de categorias
- `CategoryForm` - Formulario categoria
- `ImageUploader` - Subida de imagenes
- `ProductSearch` - Busqueda avanzada
### Hooks
- `useProducts` - CRUD productos
- `useCategories` - CRUD categorias
- `useVariants` - CRUD variantes
- `usePrices` - CRUD precios
## Dependencias
### Modulos Requeridos
- SAAS-001 Auth
- SAAS-002 Tenants
- SAAS-011 Storage (imagenes)
### Modulos Opcionales
- SAAS-018 Sales (productos en oportunidades)
- SAAS-004 Billing (suscripciones)
## Criterios de Aceptacion
1. [ ] CRUD productos con validaciones
2. [ ] Categorias jerarquicas funcionales
3. [ ] Variantes con atributos dinamicos
4. [ ] Precios multi-moneda
5. [ ] Subida de imagenes integrada
6. [ ] Busqueda y filtros avanzados
7. [ ] Tests unitarios (>70% coverage)
## Estimacion
| Componente | SP |
|------------|-----|
| DDL + Entities | 2 |
| Backend Services | 3 |
| Controllers + DTOs | 2 |
| Frontend Pages | 3 |
| Frontend Components | 2 |
| Tests | 1 |
| **Total** | **13** |
---
**Ultima actualizacion:** 2026-01-24
**Autor:** Claude Opus 4.5