# Flujo de Trabajo para Procesamiento de Precios en Cotizador

## Índice
1. [Proceso General](#proceso-general)
2. [Flujo de Trabajo Detallado](#flujo-de-trabajo-detallado)
3. [Ejemplos Implementados](#ejemplos-implementados)
4. [Mejores Prácticas y Errores Comunes](#mejores-prácticas-y-errores-comunes)

## Proceso General

El procesamiento de precios en el cotizador sigue estos pasos principales:
1. Identificación de componentes en CZE_Quotes
2. Implementación de funciones en CotizadorSQL.py
3. Actualización de lógica en Cotizador.py
4. Validación y pruebas

## Flujo de Trabajo Detallado

### 1. Identificación

Antes de comenzar la implementación, identificar:
- Columnas relevantes en CZE_Quotes
- Consulta SQL asociada (#Consulta = X)
- Si el componente usa cantidad (QtyGenset)
- Condiciones de validación

### 2. Implementación en CotizadorSQL.py

#### 2.1 Función get_X_data
```python
def get_X_data(item, qty_genset):
    """Obtiene datos del componente."""
    query = """
    SELECT 
        Item_X,
        ISNULL(price, 0) AS price,
        TechnicalSheet,
        ? * ISNULL(price, 0) AS price_tot  # Solo si usa QtyGenset
    FROM Table_X
    WHERE Item_X = ?
    """
    
    try:
        with get_connection() as conn:
            cursor = conn.cursor()
            cursor.execute(query, (qty_genset, item))
            result = cursor.fetchone()
            
            if result:
                return {
                    'item': result[0],
                    'price': result[1],
                    'tech_sheet': result[2],
                    'price_tot': result[3]
                }
            return None
    except Exception as e:
        print(f"Error obteniendo datos: {e}")
        raise
```

#### 2.2 Función update_X_pricing
```python
def update_X_pricing(quote_id, component_num, data):
    """Actualiza precios en CZE_Quotes."""
    query = f"""
    UPDATE CZE_Quotes
    SET 
        Component{component_num}_Price = ?,
        Component{component_num}_TSheet = ?,
        Component{component_num}_PriceTot = ?
    WHERE QuoteID = ?
    """
    
    try:
        with get_connection() as conn:
            cursor = conn.cursor()
            cursor.execute(query, (
                data['price'],
                data['tech_sheet'],
                data['price_tot'],
                quote_id
            ))
            conn.commit()
    except Exception as e:
        print(f"Error actualizando precios: {e}")
        raise
```

### 3. Implementación en Cotizador.py

#### 3.1 Actualizar get_quote_data
```python
def get_quote_data(quote_id):
    """Obtiene datos necesarios de la cotización."""
    query = """
    SELECT 
        -- IMPORTANTE: Documentar índices
        FuelTypeIDBack,          -- 0
        KWOutput,                -- 1
        QtyGenset,              -- 2
        Component1_Item,         -- 3
        Component1_Description,  -- 4
        -- etc...
    FROM CZE_Quotes
    WHERE QuoteID = ?
    """
```

#### 3.2 Configurar Estructura de Índices
```python
# Definir mapeo de índices (NO usar strings como índices)
component_indices = {
    'type1': [(3, 4), (5, 6), (7, 8)],  # [índice_item, índice_descripción]
    'type2': [(9, 10), (11, 12), (13, 14)]
}
```

#### 3.3 Implementar Lógica en pricing_quote
```python
def pricing_quote(quote_id):
    try:
        quote_data = get_quote_data(quote_id)
        if not quote_data:
            raise Exception("Cotización no encontrada")
        
        qty_genset = quote_data[2]  # Usar índice numérico
        
        for component_idx in range(3):
            for comp_type, indices_list in component_indices.items():
                item_idx, desc_idx = indices_list[component_idx]
                
                if quote_data[desc_idx] != "No":
                    component_data = get_X_data(quote_data[item_idx], qty_genset)
                    if component_data:
                        update_X_pricing(quote_id, component_idx + 1, component_data)
        
        return True
    except Exception as e:
        print(f"Error procesando precios: {e}")
        raise
```

## Ejemplos Implementados

### 1. Generador Principal (GEN)
```python
# En CotizadorSQL.py
def get_genset_data(fuel_type, kw_output, engine_brand, alternator_brand, 
                    voltage_id, certification_id, controller_brand, qty_genset):
    query = """
    SELECT DISTINCT
        CZE_GensetCost.CostID,
        ISNULL(CZE_GensetCost.Cost, 0) AS price,
        CZE_GensetCost.TechnicalSheet,
        ? * ISNULL(CZE_GensetCost.Cost, 0) AS Genset_PriceTot
    FROM CZE_Genset
    -- [JOINs aquí]
    WHERE
        CZE_Genset.Active = 1
        -- [Condiciones WHERE aquí]
    """
```

### 2. Breakers Principales (INT)
```python
# En CotizadorSQL.py
def get_breaker_data(item_breaker, qty_genset):
    query = """
    SELECT 
        CZE_BreakersCatalog.Item_breaker,
        ISNULL(CZE_BreakersCatalog.price, 0) AS price,
        CZE_BreakersCatalog.TechnicalSheet,
        ? * ISNULL(CZE_BreakersCatalog.price, 0) AS price_tot
    FROM CZE_BreakersCatalog
    WHERE CZE_BreakersCatalog.Item_breaker = ?
    """
```

### 3. Opciones de Breakers (BRK_OPT)
```python
# En CotizadorSQL.py
def get_breaker_option_data(item_option, qty_genset):
    query = """
    SELECT 
        CZE_BreakersOptions.Item_breaker_options,
        ISNULL(CZE_BreakersOptions.price, 0) AS price,
        CZE_BreakersOptions.TechnicalSheet,
        ? * ISNULL(CZE_BreakersOptions.price, 0) AS price_tot
    FROM CZE_BreakersOptions
    WHERE CZE_BreakersOptions.Item_breaker_options = ?
    """
```

## Mejores Prácticas y Errores Comunes

### Puntos Críticos
1. **NO usar strings como índices** para quote_data
   - Incorrecto: `quote_data['ComponentName']`
   - Correcto: `quote_data[3]`

2. **Documentar índices** en get_quote_data
   ```python
   # Bien documentado
   SELECT 
       Field1,    -- 0
       Field2,    -- 1
       Field3     -- 2
   ```

3. **Orden de parámetros en cursor.execute**
   - El orden debe coincidir con los '?' en la consulta SQL
   - Primer '?' = primer parámetro en la tupla

4. **Cálculos con QtyGenset**
   - Incluir siempre que el componente use cantidad
   - Multiplicar precio unitario por QtyGenset

5. **Validaciones**
   - Verificar valores nulos
   - Validar opciones de selección
   - Manejar errores apropiadamente

6. **Convenciones de Nombres**
   - _Price: precio unitario
   - _TSheet: ficha técnica
   - _PriceTot: precio total

### Errores Comunes
1. Error "row indices must be integers, not str"
   - Causa: Usar strings como índices en quote_data
   - Solución: Usar índices numéricos

2. Valores incorrectos en precios totales
   - Causa: Orden incorrecto de parámetros en cursor.execute
   - Solución: Asegurar que QtyGenset sea el primer parámetro

3. Datos no actualizados
   - Causa: Olvidar commit() después de UPDATE
   - Solución: Siempre usar commit() en funciones de actualización

