# ANALISIS MODULO RT-003: INVENTARIO MULTI-SUCURSAL

**Fecha:** 2025-12-18
**Fase:** 2 - Analisis por Modulo
**Modulo:** RT-003 Inventario
**Herencia:** 60%
**Story Points:** 42
**Prioridad:** P0

---

## 1. DESCRIPCION GENERAL

### 1.1 Proposito
Gestion de inventario distribuido entre multiples sucursales con transferencias, conteos ciclicos y alertas de reorden.

### 1.2 Funcionalidades Principales

| Funcionalidad | Descripcion | Criticidad |
|---------------|-------------|------------|
| Stock por sucursal | Inventario independiente | Critica |
| Transferencias | Entre sucursales | Alta |
| Alertas reorden | Stock minimo | Alta |
| Conteos ciclicos | ABC | Media |
| Kardex | Historial movimientos | Media |
| Reservas | Stock apartado | Media |

---

## 2. HERENCIA DEL CORE

### 2.1 Componentes Heredados (60%)

| Componente Core | % Uso | Accion |
|-----------------|-------|--------|
| inventory.products | 100% | HEREDAR |
| inventory.product_variants | 100% | HEREDAR |
| inventory.warehouses | 100% | HEREDAR |
| inventory.locations | 100% | HEREDAR |
| inventory.lots | 100% | HEREDAR |
| inventory.stock_moves | 80% | EXTENDER |
| inventory.pickings | 60% | EXTENDER |

### 2.2 Servicios a Heredar

```typescript
import { ProductsService } from '@erp-core/inventory';
import { WarehousesService } from '@erp-core/inventory';
import { LocationsService } from '@erp-core/inventory';
import { LotsService } from '@erp-core/inventory';
```

### 2.3 Servicios a Extender

```typescript
// Extender para multi-sucursal
class RetailInventoryService extends InventoryService {
  // Stock por sucursal
  async getStockByBranch(branchId: string, productId: string): Promise<BranchStock>;

  // Transferencias
  async createTransfer(dto: CreateTransferDto): Promise<StockTransfer>;
  async confirmTransfer(id: string): Promise<StockTransfer>;
  async receiveTransfer(id: string, dto: ReceiveDto): Promise<StockTransfer>;
}
```

---

## 3. COMPONENTES NUEVOS

### 3.1 Entidades (TypeORM)

```typescript
// 1. BranchStock - Stock por sucursal
@Entity('branch_stock', { schema: 'retail' })
export class BranchStock {
  @PrimaryGeneratedColumn('uuid')
  id: string;

  @Column('uuid')
  tenantId: string;

  @ManyToOne(() => Branch)
  branch: Branch;

  @ManyToOne(() => Product)
  product: Product;

  @Column({ type: 'decimal', precision: 12, scale: 4 })
  quantityOnHand: number;

  @Column({ type: 'decimal', precision: 12, scale: 4, default: 0 })
  quantityReserved: number;

  @Column({ type: 'decimal', precision: 12, scale: 4 })
  @Generated('quantityOnHand - quantityReserved')
  quantityAvailable: number;

  @Column({ type: 'decimal', precision: 12, scale: 4, nullable: true })
  reorderPoint: number;

  @Column({ type: 'decimal', precision: 12, scale: 4, nullable: true })
  maxStock: number;

  @Column({ type: 'date', nullable: true })
  lastCountDate: Date;
}

// 2. StockTransfer - Transferencia
@Entity('stock_transfers', { schema: 'retail' })
export class StockTransfer {
  @PrimaryGeneratedColumn('uuid')
  id: string;

  @Column('uuid')
  tenantId: string;

  @Column()
  transferNumber: string;

  @ManyToOne(() => Branch)
  sourceBranch: Branch;

  @ManyToOne(() => Branch)
  destinationBranch: Branch;

  @Column({ type: 'enum', enum: TransferStatus })
  status: TransferStatus;

  @Column({ type: 'timestamptz' })
  requestDate: Date;

  @Column({ type: 'timestamptz', nullable: true })
  shipDate: Date;

  @Column({ type: 'timestamptz', nullable: true })
  receiveDate: Date;

  @ManyToOne(() => User)
  requestedBy: User;

  @ManyToOne(() => User, { nullable: true })
  shippedBy: User;

  @ManyToOne(() => User, { nullable: true })
  receivedBy: User;

  @OneToMany(() => StockTransferLine, line => line.transfer)
  lines: StockTransferLine[];
}

// 3. StockTransferLine
@Entity('stock_transfer_lines', { schema: 'retail' })
export class StockTransferLine {
  @PrimaryGeneratedColumn('uuid')
  id: string;

  @ManyToOne(() => StockTransfer)
  transfer: StockTransfer;

  @ManyToOne(() => Product)
  product: Product;

  @Column({ type: 'decimal', precision: 12, scale: 4 })
  quantityRequested: number;

  @Column({ type: 'decimal', precision: 12, scale: 4, nullable: true })
  quantityShipped: number;

  @Column({ type: 'decimal', precision: 12, scale: 4, nullable: true })
  quantityReceived: number;
}
```

### 3.2 Servicios Backend

| Servicio | Metodos Principales |
|----------|-------------------|
| BranchStockService | getStock(), updateStock(), reserveStock(), releaseStock() |
| TransferService | create(), confirm(), ship(), receive(), cancel() |
| ReorderService | checkReorderPoints(), generateSuggestions() |
| CycleCountService | createCount(), recordCount(), approveAdjustment() |
| KardexService | getMovements(), getProductHistory() |

### 3.3 Controladores

```typescript
@Controller('inventory')
export class RetailInventoryController {
  // Stock por sucursal
  @Get('branches/:branchId/stock')
  getBranchStock(@Param('branchId') branchId: string): Promise<BranchStock[]>;

  @Get('branches/:branchId/stock/:productId')
  getProductStock(@Param('branchId') branchId: string,
                  @Param('productId') productId: string): Promise<BranchStock>;

  @Get('stock/all/:productId')
  getStockAllBranches(@Param('productId') productId: string): Promise<BranchStock[]>;

  // Transferencias
  @Post('transfers')
  createTransfer(@Body() dto: CreateTransferDto): Promise<StockTransfer>;

  @Post('transfers/:id/confirm')
  confirmTransfer(@Param('id') id: string): Promise<StockTransfer>;

  @Post('transfers/:id/ship')
  shipTransfer(@Param('id') id: string, @Body() dto: ShipDto): Promise<StockTransfer>;

  @Post('transfers/:id/receive')
  receiveTransfer(@Param('id') id: string, @Body() dto: ReceiveDto): Promise<StockTransfer>;

  // Alertas
  @Get('alerts/reorder')
  getReorderAlerts(): Promise<ReorderAlert[]>;

  // Kardex
  @Get('kardex/:productId')
  getKardex(@Param('productId') productId: string,
            @Query() filters: KardexFilters): Promise<KardexEntry[]>;
}
```

---

## 4. FLUJOS DE NEGOCIO

### 4.1 Flujo de Transferencia

```
1. Sucursal destino solicita transferencia
      ↓
2. Estado: DRAFT → PENDING (pendiente aprobacion)
      ↓
3. Sucursal origen aprueba
      ↓
4. Estado: PENDING → APPROVED
      ↓
5. Sucursal origen prepara y envia
      ↓
6. Estado: APPROVED → IN_TRANSIT
      ↓
7. Stock origen: - cantidad_enviada
      ↓
8. Sucursal destino recibe
      ↓
9. Validar cantidades (diferencias)
      ↓
10. Estado: IN_TRANSIT → RECEIVED
      ↓
11. Stock destino: + cantidad_recibida
```

### 4.2 Flujo de Conteo Ciclico

```
1. Generar conteo (clasificacion ABC)
      ↓
2. Asignar a contador
      ↓
3. Conteo ciego (sin ver stock sistema)
      ↓
4. Registrar cantidades
      ↓
5. Comparar vs sistema
      ↓
6. Si diferencia:
   a. Registrar motivo
   b. Aprobar ajuste (supervisor)
   c. Aplicar ajuste
      ↓
7. Actualizar fecha ultimo conteo
```

---

## 5. TABLAS DDL

### 5.1 Tablas Nuevas

```sql
-- Definidas en 03-retail-tables.sql
CREATE TABLE retail.branch_stock (...);
CREATE TABLE retail.stock_transfers (...);
CREATE TABLE retail.stock_transfer_lines (...);
```

### 5.2 Indices

```sql
-- Stock por sucursal
CREATE UNIQUE INDEX idx_branch_stock_branch_product
  ON retail.branch_stock(branch_id, product_id);

-- Transferencias
CREATE INDEX idx_transfers_source ON retail.stock_transfers(source_branch_id);
CREATE INDEX idx_transfers_dest ON retail.stock_transfers(destination_branch_id);
CREATE INDEX idx_transfers_status ON retail.stock_transfers(status);
```

### 5.3 Triggers

```sql
-- Actualizar stock al confirmar venta
CREATE OR REPLACE FUNCTION retail.update_stock_on_sale()
RETURNS TRIGGER AS $$
BEGIN
  UPDATE retail.branch_stock
  SET quantity_on_hand = quantity_on_hand - NEW.quantity
  WHERE branch_id = (SELECT branch_id FROM retail.pos_sessions WHERE id =
    (SELECT session_id FROM retail.pos_orders WHERE id = NEW.order_id))
  AND product_id = NEW.product_id;
  RETURN NEW;
END;
$$ LANGUAGE plpgsql;
```

---

## 6. DEPENDENCIAS

### 6.1 Dependencias de Core

| Modulo | Estado | Requerido Para |
|--------|--------|---------------|
| MGN-011 Inventory | 60% | Base de productos y stock |
| MGN-005 Catalogs | 0% | Productos base |

### 6.2 Dependencias de Retail

| Modulo | Tipo |
|--------|------|
| RT-001 Fundamentos | Prerequisito |
| RT-004 Compras | Recepciones |

### 6.3 Bloquea a

| Modulo | Razon |
|--------|-------|
| RT-002 POS | Stock disponible |
| RT-009 E-commerce | Stock online |

---

## 7. ESPECIFICACIONES APLICABLES

### 7.1 Del Core

| SPEC | Aplicacion |
|------|------------|
| SPEC-INVENTARIOS-CICLICOS | Conteos |
| SPEC-TRAZABILIDAD-LOTES-SERIES | Productos con lote |
| SPEC-VALORACION-INVENTARIO | Costeo |

### 7.2 Configuracion

```yaml
inventory_config:
  reorder:
    check_interval: "1h"
    notification: ["email", "push"]

  cycle_count:
    classification:
      A: { frequency: "weekly", threshold: 0.8 }  # 80% del valor
      B: { frequency: "monthly", threshold: 0.15 }
      C: { frequency: "quarterly", threshold: 0.05 }

  transfers:
    require_approval: true
    auto_reserve_on_request: true
```

---

## 8. CRITERIOS DE ACEPTACION

### 8.1 Funcionales

- [ ] Consultar stock por sucursal
- [ ] Ver stock en todas las sucursales
- [ ] Crear solicitud de transferencia
- [ ] Aprobar transferencia
- [ ] Enviar transferencia (actualiza stock origen)
- [ ] Recibir transferencia (actualiza stock destino)
- [ ] Registrar diferencias en recepcion
- [ ] Alertas de stock bajo automaticas
- [ ] Conteo ciclico con clasificacion ABC
- [ ] Ver kardex de movimientos

### 8.2 Performance

- [ ] Consulta stock < 500ms
- [ ] Listado sucursales < 1s

---

## 9. RIESGOS

| Riesgo | Probabilidad | Impacto | Mitigacion |
|--------|--------------|---------|------------|
| Inconsistencia stock | Media | Critico | Transacciones atomicas |
| Performance en listados | Media | Medio | Indices + paginacion |

---

## 10. ESTIMACION DETALLADA

| Componente | SP Backend | SP Frontend | Total |
|------------|-----------|-------------|-------|
| Entities + Migrations | 3 | - | 3 |
| BranchStockService | 5 | - | 5 |
| TransferService | 8 | - | 8 |
| ReorderService | 3 | - | 3 |
| CycleCountService | 5 | - | 5 |
| Controllers | 3 | - | 3 |
| Stock Pages | - | 8 | 8 |
| Transfer Pages | - | 5 | 5 |
| Alerts UI | - | 2 | 2 |
| **TOTAL** | **27** | **15** | **42** |

---

## 11. REFERENCIAS

| Documento | Ubicacion |
|-----------|-----------|
| Epica RT-003 | docs/08-epicas/EPIC-RT-003-inventario.md |
| Modulo Core Inventory | erp-core/backend/src/modules/inventory/ |
| SPEC Conteos | erp-core/docs/04-modelado/especificaciones-tecnicas/ |

---

**Estado:** ANALISIS COMPLETO
**Bloqueado por:** RT-001 Fundamentos, MGN-011 Inventory (core)
