424 lines
10 KiB
Markdown
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)
|