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>
297 lines
7.9 KiB
Markdown
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
|