# 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)
