a
    giP                     @   sF   d Z ddlmZ ddlZddlmZmZ ddlmZ G dd dZdS )u2  
Módulo de consultas SQL para Score de Producción.

Este módulo maneja todas las consultas relacionadas con:
- Obtención de órdenes de producción de la tabla CM_Score
- Filtros por departamento, vendedor, fechas, proyecto
- Detalles individuales de órdenes
- Estadísticas y métricas de órdenes

ESTRUCTURA DE TABLA CM_Score:
==============================
Campos principales que usaremos:
- OrderNum (int) - Número de orden
- OrderLine (int) - Línea de orden
- PartNum (nvarchar) - Número de parte
- LineDesc (nvarchar) - Descripción de línea
- OrderDate (date) - Fecha de orden
- NeedByDate (date) - Fecha requerida
- Departamento (nvarchar) - Departamento
- Vendedor (nvarchar) - Vendedor
- Name (nvarchar) - Nombre cliente
- ProjectID (nvarchar) - ID de proyecto
- JobNum2 (nvarchar) - Número de trabajo
- FechaProducción (date) - Fecha de producción
- AvanceProducción (numeric) - Avance de producción
- AvanceDeSurtimiento (numeric) - Avance de surtimiento
- EstadoFecha (nvarchar) - Estado de fecha
- ComentarioProducción (nvarchar) - Comentarios
    )get_connectionN)datetimedate)Decimalc                   @   sN   e Zd ZdZedddZedd Zedd Zed	d
 Zedd Z	dS )ScoreProduccionSQLu   
    Clase que contiene todas las consultas SQL para el módulo de Score de Producción.
    Todos los métodos son estáticos para facilitar su uso sin necesidad de instanciar la clase.
    Nc                 C   s  d}zrzft  }| }d}g }| rF| drF|d7 }|| d  | rj| drj|d7 }|| d  | r| dr|d7 }|d	| d  d	 | r| d
r|d7 }|d	| d
  d	 | r| dr|d7 }|| d  | r| dr|d7 }|| d  | r6| dr6|d7 }|| d  |d7 }tdt| d |rf||| n
|| dd |jD }| }|	  |	  g }|D ]}i }	t
|D ]h\}
}||
 }t|tr| |	|< n<t|tr| |	|< n"t|trt||	|< n||	|< q||	 qtdt| d d|t|ddW W |rpz|	  W S    Y S 0 S  tjy } zXdt| }td|  dg d|dW  Y d}~W |rz|	  W S    Y S 0 S d}~0  tyT } zXdt| }td|  dg d|dW  Y d}~W |rJz|	  W S    Y S 0 S d}~0 0 W |rz|	  W n   Y n0 n"|rz|	  W n   Y n0 0 dS ) u  
        Obtiene todas las órdenes de producción con filtros opcionales.
        
        Esta es la consulta principal que alimenta la tabla del frontend.
        
        Args:
            filtros (dict, optional): Diccionario con filtros opcionales
                - departamento (str): Filtrar por departamento
                - vendedor (str): Filtrar por vendedor
                - proyecto (str): Filtrar por proyecto ID
                - fecha_desde (date): Filtrar desde fecha
                - fecha_hasta (date): Filtrar hasta fecha
                - part_num (str): Filtrar por número de parte
                - order_num (int): Filtrar por número de orden
        
        Returns:
            dict: {
                'success': bool,
                'ordenes': list de diccionarios con los datos,
                'total': int (cantidad de registros),
                'error': str (si falla)
            }
        Nur
  
                SELECT 
                    [OrderNum&Line],
                    OrderNum,
                    OrderLine,
                    PartNum,
                    LineDesc,
                    OrderDate,
                    NeedByDate,
                    Departamento,
                    Vendedor,
                    Name,
                    ProjectID,
                    JobNum2,
                    Capacidad,
                    Voltaje,
                    Tipo,
                    RevisionNum,
                    Revision_Job,
                    ProdCode,
                    DecriptionProd,
                    FechaProducción,
                    ComentarioProducción,
                    AvanceProducción,
                    FechaPlaneación,
                    EstadoFecha,
                    ComentarioPlaneación,
                    AvanceDeSurtimiento,
                    AvisoDeTerminacion,
                    FechaDeTermino,
                    FechaDeCierre,
                    InsumosDemandados,
                    InsumosEmitidos,
                    AvaceDeEmisiones,
                    ComentarioCalidad,
                    FechaActualización,
                    ClienteEEUU,
                    FechaActualización,
                    MaterialFaltante,
                    FechaMat,
                    Caseta,
                    -- Motor
                    IssuedQty_M,
                    OnhandQty_M,
                    Preasignado_M,
                    Demandado_M,
                    Faltante_M,
                    Comment_M,
                    PartNum_M,
                    Alternativa_M,
                    En_PO_M,
                    PO_M,
                    NoPO_M,
                    NoSerie_M,
                    Estatus_M,
                    Fecha_Llegada_M,
                    RefCategory_M,
                    Description_M,

                    -- Generador
                    IssuedQty_G,
                    OnhandQty_G,
                    Preasignado_G,
                    Demandado_G,
                    Faltante_G,
                    PartNum_G,
                    Alternativa_G,
                    En_PO_G,
                    PO_G,
                    NoPO_G,
                    NoSerie_G,
                    Estatus_G,
                    Fecha_Llegada_G,
                    Description_G,
                    Comment_G,
                    EnRequisicion_G,
                    NoRequisicion_G,
                    En_PO_Altern_G,
                    En_PO_Altern_M
                FROM CM_Score
                WHERE 1=1
                AND PartNum LIKE 'EP%'
            departamentoz AND Departamento = ?vendedorz AND Vendedor = ?proyectoz AND ProjectID LIKE ?%part_numz AND PartNum LIKE ?	order_numz AND OrderNum = ?fecha_desdez AND OrderDate >= ?fecha_hastaz AND OrderDate <= ?z6 ORDER BY OrderDate DESC, OrderNum DESC, OrderLine ASCu   🔍 Ejecutando query con z filtrosc                 S   s   g | ]}|d  qS r    .0columnr   r   I/var/www/html/src/Consultas_SQL/SupYCtrol/IngDeControl/ScoreControlSQL.py
<listcomp>       z<ScoreProduccionSQL.obtener_todas_ordenes.<locals>.<listcomp>u   ✅ Se obtuvieron u	    órdenesT)successordenestotalerroru,   Error de base de datos al obtener órdenes:    ❌ Fr   u&   Error inesperado al obtener órdenes: )r   cursorgetappendprintlenexecutedescriptionfetchallclose	enumerate
isinstancer   	isoformatr   r   floatpyodbcErrorstr	Exception)filtrosconnr   queryZ
parametroscolumnas
resultadosr   	resultado
orden_dictidxcolumnavalore	error_msgr   r   r   obtener_todas_ordenes4   s    U

z(ScoreProduccionSQL.obtener_todas_ordenesc                 C   sb  d}z4z(t  }| }d}||| f dd |jD }| }|  |  |ri }t|D ]`\}}|| }	t|	tr|		 ||< qdt|	t
r|		 ||< qdt|	trt|	||< qd|	||< qdd|dddW W |rz|  W S    Y S 0 S dddd|  d	dW W |r.z|  W S    Y S 0 S W n tjy }
 zXd
t|
 }td|  ddd|dW  Y d}
~
W |rz|  W S    Y S 0 S d}
~
0  ty }
 zXdt|
 }td|  ddd|dW  Y d}
~
W |rz|  W S    Y S 0 S d}
~
0 0 W |r^z|  W n   Y n0 n"|r\z|  W n   Y n0 0 dS )u  
        Obtiene una orden específica por su OrderNum&Line (clave primaria).
        
        Args:
            order_line_id (int): ID de OrderNum&Line
        
        Returns:
            dict: {
                'success': bool,
                'orden': dict con todos los datos de la orden,
                'existe': bool,
                'error': str (si falla)
            }
        Nzn
                SELECT *
                FROM CM_Score
                WHERE [OrderNum&Line] = ?
            c                 S   s   g | ]}|d  qS r   r   r   r   r   r   r   M  r   z;ScoreProduccionSQL.obtener_orden_por_id.<locals>.<listcomp>T)r   ordenexister   FzOrden con ID z no encontradaz)Error de base de datos al obtener orden: r   z#Error inesperado al obtener orden: )r   r   r!   r"   fetchoner$   r%   r&   r   r'   r   r   r(   r)   r*   r+   r   r,   )order_line_idr.   r   r/   r0   r2   r3   r4   r5   r6   r7   r8   r   r   r   obtener_orden_por_id.  s    



%

z'ScoreProduccionSQL.obtener_orden_por_idc                  C   s0  d} zzpt  } |  }d}|| | }|  |   dd |D }d|ddW W | rxz|   W S    Y S 0 S  ty } zTdt| }td|  d	g |dW  Y d}~W | rz|   W S    Y S 0 S d}~0 0 W | r,z|   W n   Y n0 n"| r*z|   W n   Y n0 0 dS )
u   
        Obtiene todos los departamentos únicos.
        
        Returns:
            dict: {
                'success': bool,
                'departamentos': list de strings,
                'error': str (si falla)
            }
        Nz
                SELECT DISTINCT Departamento
                FROM CM_Score
                WHERE Departamento IS NOT NULL
                ORDER BY Departamento ASC
            c                 S   s   g | ]}|d  r|d  qS r   r   r   r2   r   r   r   r     r   zHScoreProduccionSQL.obtener_departamentos_disponibles.<locals>.<listcomp>T)r   departamentosr   z Error al obtener departamentos: r   Fr   r   r!   r#   r$   r,   r+   r   )r.   r   r/   r1   r@   r7   r8   r   r   r   !obtener_departamentos_disponibles  sV    
z4ScoreProduccionSQL.obtener_departamentos_disponiblesc                  C   s0  d} zzpt  } |  }d}|| | }|  |   dd |D }d|ddW W | rxz|   W S    Y S 0 S  ty } zTdt| }td|  d	g |dW  Y d}~W | rz|   W S    Y S 0 S d}~0 0 W | r,z|   W n   Y n0 n"| r*z|   W n   Y n0 0 dS )
u   
        Obtiene todos los vendedores únicos.
        
        Returns:
            dict: {
                'success': bool,
                'vendedores': list de strings,
                'error': str (si falla)
            }
        Nz
                SELECT DISTINCT Vendedor
                FROM CM_Score
                WHERE Vendedor IS NOT NULL
                ORDER BY Vendedor ASC
            c                 S   s   g | ]}|d  r|d  qS r   r   r?   r   r   r   r     r   zEScoreProduccionSQL.obtener_vendedores_disponibles.<locals>.<listcomp>T)r   
vendedoresr   zError al obtener vendedores: r   FrA   )r.   r   r/   r1   rC   r7   r8   r   r   r   obtener_vendedores_disponibles  sV    
z1ScoreProduccionSQL.obtener_vendedores_disponiblesc                  C   s  d} zzt  } |  }d}|| | }|  |   |r|d pNd|d pXd|d pbd|d pld|d pvd|d rt|d nd	|d
 rt|d
 nd	|d pd|d pdd	}d|ddW W | rz|   W S    Y S 0 S ddddW W | rz|   W S    Y S 0 S W np ty } zVdt| }td|  dd|dW  Y d}~W | rz|   W S    Y S 0 S d}~0 0 W | rz|   W n   Y n0 n"| rz|   W n   Y n0 0 dS )u  
        Obtiene estadísticas generales de las órdenes.
        
        Returns:
            dict: {
                'success': bool,
                'estadisticas': dict con métricas generales,
                'error': str (si falla)
            }
        Nu  
                SELECT 
                    COUNT(*) as TotalOrdenes,
                    COUNT(DISTINCT OrderNum) as OrdenesUnicas,
                    COUNT(DISTINCT Departamento) as TotalDepartamentos,
                    COUNT(DISTINCT Vendedor) as TotalVendedores,
                    COUNT(DISTINCT ProjectID) as TotalProyectos,
                    AVG(CAST(AvanceProducción AS FLOAT)) as PromedioAvanceProduccion,
                    AVG(CAST(AvanceDeSurtimiento AS FLOAT)) as PromedioAvanceSurtimiento,
                    SUM(CASE WHEN AvisoDeTerminacion IS NOT NULL THEN 1 ELSE 0 END) as OrdenesTerminadas,
                    SUM(CASE WHEN FechaDeCierre IS NOT NULL THEN 1 ELSE 0 END) as OrdenesCerradas
                FROM CM_Score
            r                  g                 )	ZTotalOrdenesZOrdenesUnicasZTotalDepartamentosZTotalVendedoresZTotalProyectosZPromedioAvanceProduccionZPromedioAvanceSurtimientoZOrdenesTerminadasZOrdenesCerradasT)r   estadisticasr   Fu$   No se pudieron obtener estadísticasu    Error al obtener estadísticas: r   )	r   r   r!   r<   r$   r(   r,   r+   r   )r.   r   r/   r2   rM   r7   r8   r   r   r   obtener_estadisticas_generales  s~    







z1ScoreProduccionSQL.obtener_estadisticas_generales)N)
__name__
__module____qualname____doc__staticmethodr9   r>   rB   rD   rN   r   r   r   r   r   *   s   	 z
e
6
:r   )	rR   Consultas_SQL.conexionr   r)   r   r   decimalr   r   r   r   r   r   <module>   s
   