erp-retail/orchestration/planes/fase-2-analisis-modulos/ANALISIS-RT-004-compras.md

424 lines
10 KiB
Markdown

# ANALISIS MODULO RT-004: COMPRAS Y REABASTECIMIENTO
**Fecha:** 2025-12-18
**Fase:** 2 - Analisis por Modulo
**Modulo:** RT-004 Compras
**Herencia:** 80%
**Story Points:** 38
**Prioridad:** P0
---
## 1. DESCRIPCION GENERAL
### 1.1 Proposito
Gestion centralizada de compras con sugerencias automaticas de reabastecimiento, ordenes de compra y recepcion de mercancia.
### 1.2 Funcionalidades Principales
| Funcionalidad | Descripcion | Criticidad |
|---------------|-------------|------------|
| Sugerencias compra | Automaticas por stock | Alta |
| Ordenes de compra | CRUD completo | Critica |
| Recepcion | Validacion contra OC | Critica |
| Proveedores | Catalogo y evaluacion | Media |
| Distribucion | A sucursales | Media |
---
## 2. HERENCIA DEL CORE
### 2.1 Componentes Heredados (80%)
| Componente Core | % Uso | Accion |
|-----------------|-------|--------|
| purchase.purchase_orders | 100% | HEREDAR |
| purchase.purchase_order_lines | 100% | HEREDAR |
| purchase.rfqs | 100% | HEREDAR |
| core.partners (proveedores) | 100% | HEREDAR |
| inventory.pickings | 80% | EXTENDER para recepcion |
### 2.2 Servicios a Heredar
```typescript
import { PurchaseOrdersService } from '@erp-core/purchases';
import { RFQsService } from '@erp-core/purchases';
import { PartnersService } from '@erp-core/core'; // proveedores
```
### 2.3 Servicios a Extender
```typescript
class RetailPurchaseService extends PurchaseOrdersService {
// Sugerencias automaticas
async generateSuggestions(): Promise<PurchaseSuggestion[]>;
// Distribucion a sucursales
async distributeToBranches(poId: string, distribution: DistributionDto): Promise<void>;
}
```
---
## 3. COMPONENTES NUEVOS
### 3.1 Entidades Adicionales
```typescript
// 1. PurchaseSuggestion - Sugerencia de compra
@Entity('purchase_suggestions', { schema: 'retail' })
export class PurchaseSuggestion {
@PrimaryGeneratedColumn('uuid')
id: string;
@Column('uuid')
tenantId: string;
@ManyToOne(() => Product)
product: Product;
@ManyToOne(() => Branch, { nullable: true })
branch: Branch;
@ManyToOne(() => Partner)
supplier: Partner;
@Column({ type: 'decimal', precision: 12, scale: 4 })
currentStock: number;
@Column({ type: 'decimal', precision: 12, scale: 4 })
reorderPoint: number;
@Column({ type: 'decimal', precision: 12, scale: 4 })
suggestedQuantity: number;
@Column({ type: 'decimal', precision: 12, scale: 2 })
estimatedCost: number;
@Column({ type: 'boolean', default: false })
isProcessed: boolean;
@Column({ type: 'timestamptz' })
generatedAt: Date;
}
// 2. PurchaseDistribution - Distribucion a sucursales
@Entity('purchase_distributions', { schema: 'retail' })
export class PurchaseDistribution {
@PrimaryGeneratedColumn('uuid')
id: string;
@ManyToOne(() => PurchaseOrder)
purchaseOrder: PurchaseOrder;
@ManyToOne(() => PurchaseOrderLine)
purchaseOrderLine: PurchaseOrderLine;
@ManyToOne(() => Branch)
branch: Branch;
@Column({ type: 'decimal', precision: 12, scale: 4 })
quantity: number;
@Column({ type: 'boolean', default: false })
isReceived: boolean;
}
```
### 3.2 Servicios Backend
| Servicio | Metodos Principales |
|----------|-------------------|
| PurchaseSuggestionService | generate(), getAll(), approve(), reject() |
| RetailPurchaseService | createFromSuggestions(), distribute() |
| ReceiptService | create(), validate(), confirm() |
| SupplierEvaluationService | evaluate(), getMetrics() |
### 3.3 Controladores
```typescript
@Controller('purchases')
export class RetailPurchaseController {
// Sugerencias
@Get('suggestions')
getSuggestions(): Promise<PurchaseSuggestion[]>;
@Post('suggestions/generate')
generateSuggestions(): Promise<PurchaseSuggestion[]>;
@Post('suggestions/approve')
approveSuggestions(@Body() ids: string[]): Promise<PurchaseOrder>;
// Ordenes de compra (heredado + extendido)
@Post()
create(@Body() dto: CreatePurchaseOrderDto): Promise<PurchaseOrder>;
@Post(':id/distribute')
distribute(@Param('id') id: string, @Body() dto: DistributionDto): Promise<void>;
@Post(':id/send')
sendToSupplier(@Param('id') id: string): Promise<void>;
// Recepcion
@Post(':id/receive')
receiveOrder(@Param('id') id: string, @Body() dto: ReceiveDto): Promise<Receipt>;
// Proveedores
@Get('suppliers/:id/metrics')
getSupplierMetrics(@Param('id') id: string): Promise<SupplierMetrics>;
}
```
---
## 4. ALGORITMO DE SUGERENCIAS
### 4.1 Logica de Reorden
```typescript
interface ReorderAlgorithm {
// Parametros
stockActual: number;
stockMinimo: number;
stockMaximo: number;
ventasDiarias: number; // promedio ultimos 30 dias
leadTime: number; // dias de entrega proveedor
// Calculo
puntoReorden = stockMinimo + (ventasDiarias * leadTime);
// Condicion
if (stockActual <= puntoReorden) {
cantidadSugerida = stockMaximo - stockActual;
return { producto, cantidadSugerida, proveedor };
}
}
```
### 4.2 Pseudocodigo
```sql
-- Query para generar sugerencias
WITH ventas_promedio AS (
SELECT
product_id,
AVG(quantity) as avg_daily_sales
FROM retail.pos_order_lines pol
JOIN retail.pos_orders po ON pol.order_id = po.id
WHERE po.order_date >= NOW() - INTERVAL '30 days'
GROUP BY product_id
),
stock_actual AS (
SELECT
product_id,
SUM(quantity_on_hand) as total_stock
FROM retail.branch_stock
GROUP BY product_id
)
SELECT
p.id as product_id,
sa.total_stock,
p.reorder_point,
p.max_stock,
COALESCE(vp.avg_daily_sales, 0) as avg_sales,
s.lead_time_days,
(p.reorder_point + (COALESCE(vp.avg_daily_sales, 0) * s.lead_time_days)) as calculated_reorder,
(p.max_stock - sa.total_stock) as suggested_quantity
FROM inventory.products p
JOIN stock_actual sa ON p.id = sa.product_id
LEFT JOIN ventas_promedio vp ON p.id = vp.product_id
LEFT JOIN core.partners s ON p.default_supplier_id = s.id
WHERE sa.total_stock <= (p.reorder_point + (COALESCE(vp.avg_daily_sales, 0) * s.lead_time_days));
```
---
## 5. FLUJOS DE NEGOCIO
### 5.1 Flujo de Compra
```
1. Sistema genera sugerencias (cron)
2. Comprador revisa sugerencias
3. Aprobar sugerencias
4. Crear orden de compra
5. Asignar distribucion por sucursal
6. Enviar OC al proveedor
7. Estado: DRAFT → CONFIRMED → SENT
8. Recepcion de mercancia
9. Validar vs OC (diferencias)
10. Estado: SENT → RECEIVED
11. Actualizar stock por sucursal
12. Generar factura proveedor (opcional)
```
### 5.2 Flujo de Recepcion
```
1. Proveedor entrega mercancia
2. Buscar OC correspondiente
3. Contar productos recibidos
4. Registrar cantidades por linea
5. Validar vs ordenado
6. Si diferencia:
a. Faltante: registrar, notificar
b. Sobrante: rechazar o aceptar
7. Confirmar recepcion
8. Distribuir a sucursales
9. Actualizar stock
```
---
## 6. TABLAS DDL
### 6.1 Tablas Heredadas
```sql
-- Del core (schema purchase)
purchase.purchase_orders
purchase.purchase_order_lines
purchase.rfqs
purchase.rfq_lines
```
### 6.2 Tablas Nuevas Retail
```sql
-- Sugerencias
CREATE TABLE retail.purchase_suggestions (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
tenant_id UUID NOT NULL REFERENCES auth.tenants(id),
product_id UUID NOT NULL REFERENCES inventory.products(id),
branch_id UUID REFERENCES retail.branches(id),
supplier_id UUID REFERENCES core.partners(id),
current_stock DECIMAL(12,4) NOT NULL,
reorder_point DECIMAL(12,4) NOT NULL,
suggested_quantity DECIMAL(12,4) NOT NULL,
estimated_cost DECIMAL(12,2),
is_processed BOOLEAN DEFAULT FALSE,
generated_at TIMESTAMPTZ DEFAULT NOW(),
created_at TIMESTAMPTZ DEFAULT NOW()
);
-- Distribucion
CREATE TABLE retail.purchase_distributions (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
tenant_id UUID NOT NULL REFERENCES auth.tenants(id),
purchase_order_id UUID NOT NULL REFERENCES purchase.purchase_orders(id),
purchase_order_line_id UUID NOT NULL REFERENCES purchase.purchase_order_lines(id),
branch_id UUID NOT NULL REFERENCES retail.branches(id),
quantity DECIMAL(12,4) NOT NULL,
is_received BOOLEAN DEFAULT FALSE,
created_at TIMESTAMPTZ DEFAULT NOW()
);
```
---
## 7. DEPENDENCIAS
### 7.1 Dependencias de Core
| Modulo | Estado | Requerido Para |
|--------|--------|---------------|
| MGN-012 Purchasing | 0% | Ordenes de compra |
| MGN-011 Inventory | 60% | Productos |
| MGN-005 Catalogs | 0% | Proveedores |
### 7.2 Dependencias de Retail
| Modulo | Tipo |
|--------|------|
| RT-001 Fundamentos | Prerequisito |
| RT-003 Inventario | Stock y recepciones |
### 7.3 Bloquea a
| Modulo | Razon |
|--------|-------|
| RT-003 Inventario | Recepciones actualizan stock |
---
## 8. CRITERIOS DE ACEPTACION
### 8.1 Funcionales
- [ ] Generar sugerencias automaticas
- [ ] Ver sugerencias pendientes
- [ ] Aprobar/rechazar sugerencias
- [ ] Crear OC desde sugerencias
- [ ] Crear OC manual
- [ ] Asignar distribucion por sucursal
- [ ] Enviar OC a proveedor (email)
- [ ] Registrar recepcion
- [ ] Validar cantidades vs OC
- [ ] Registrar diferencias
- [ ] Actualizar stock al recibir
- [ ] Ver historial de compras por proveedor
### 8.2 Performance
- [ ] Generacion sugerencias < 30s
- [ ] Listado OC < 1s
---
## 9. RIESGOS
| Riesgo | Probabilidad | Impacto | Mitigacion |
|--------|--------------|---------|------------|
| Core purchase incompleto | Alta | Bloqueante | Implementar primero en core |
| Algoritmo ineficiente | Media | Medio | Indices y optimizacion query |
---
## 10. ESTIMACION DETALLADA
| Componente | SP Backend | SP Frontend | Total |
|------------|-----------|-------------|-------|
| Entities + Migrations | 3 | - | 3 |
| SuggestionService | 5 | - | 5 |
| RetailPurchaseService | 5 | - | 5 |
| ReceiptService | 5 | - | 5 |
| SupplierEvaluationService | 2 | - | 2 |
| Controllers | 3 | - | 3 |
| Suggestions UI | - | 5 | 5 |
| PO Pages | - | 5 | 5 |
| Receipt Pages | - | 5 | 5 |
| **TOTAL** | **23** | **15** | **38** |
---
## 11. REFERENCIAS
| Documento | Ubicacion |
|-----------|-----------|
| Epica RT-004 | docs/08-epicas/EPIC-RT-004-compras.md |
| Modulo Core Purchase | erp-core/backend/src/modules/purchases/ |
---
**Estado:** ANALISIS COMPLETO
**Bloqueado por:** RT-001, RT-003, MGN-012 (core)