a
    Ueij                     @   s   d Z ddlmZmZmZ ddlmZmZ ddlZddlZej	
ej	ej	ej	ej	ej	e ddlmZ G dd dZdd	 ZdS )
u  
Módulo de Score de Producción.

Este módulo gestiona todo el flujo de visualización y análisis de órdenes:
1. Obtención de órdenes con filtros opcionales
2. Consulta de detalles individuales
3. Estadísticas y métricas generales
4. Exportación de datos

ARQUITECTURA:
=============
Este módulo sigue el patrón MVC:
- Model: ScoreProduccionSQL (consultas a BD - CM_Score)
- View: ScoreProduccion.html (template Jinja2)
- Controller: ScoreProduccionController (lógica de negocio)
    )jsonifyrender_templaterequest)datetimedateN)ScoreProduccionSQLc                   @   sR   e Zd ZdZdd ZdddZdd Zd	d
 ZeedddZ	dd Z
dd ZdS )ScoreProduccionControlleru   
    Controlador principal para el módulo de Score de Producción.
    
    Esta clase maneja toda la lógica de negocio para visualizar y analizar
    órdenes de producción desde la tabla CM_Score.
    c                 C   s   t  | _dS )zInicializa el controlador.N)r   sql)self r   A/var/www/html/src/App/Operaciones_Module/Lerma/ScoreProduccion.py__init__*   s    z"ScoreProduccionController.__init__Nc           	   
   C   s  zPt d t d t d t d | |}|rJt dt|   nt d t d | j|}|d st d	|d
   dd|d
 dW S |d }t dt|  t d | |}t d t d | |}t d t d t d t dt|  t d|	dddd t d|	dddd t d d|t|||dW S  t
y } z>t d t|  dd!l}|  dd"t|dW  Y d!}~S d!}~0 0 d!S )#u  
        🎯 FUNCIÓN ORQUESTADORA PRINCIPAL
        
        Esta función coordina todo el flujo de obtención de órdenes de producción.
        
        FLUJO DE EJECUCIÓN:
        1. Validar y procesar filtros (si existen)
        2. Ejecutar consulta SQL con filtros
        3. Procesar y enriquecer datos
        4. Calcular estadísticas adicionales
        5. Retornar respuesta estructurada
        
        Args:
            filtros_json (dict, optional): Diccionario con filtros opcionales
                - departamento (str): Filtrar por departamento
                - vendedor (str): Filtrar por vendedor
                - proyecto (str): Filtrar por proyecto ID
                - fechaDesde (str): Fecha desde (ISO format)
                - fechaHasta (str): Fecha hasta (ISO format)
                - partNum (str): Filtrar por número de parte
                - orderNum (int): Filtrar por número de orden
        
        Returns:
            dict: Respuesta estructurada con success, ordenes, estadísticas o errores
        Q
================================================================================u4   🎯 INICIANDO OBTENCIÓN DE ÓRDENES DE PRODUCCIÓNP================================================================================u#   
🔍 PASO 1: Procesando filtros...u   ✅ Filtros activos: u   ℹ️  Sin filtros aplicadosu*   
💾 PASO 2: Consultando base de datos...successu   ❌ Error al obtener órdenes: errorFu(   Error al obtener órdenes de producciónr   mensajer   ordenesu   ✅ Órdenes obtenidas: u$   
🔧 PASO 3: Enriqueciendo datos...u   ✅ Datos enriquecidosu)   
📊 PASO 4: Calculando estadísticas...u   ✅ Estadísticas calculadasu$   🎉 ÓRDENES OBTENIDAS EXITOSAMENTEu   📊 Total de registros: u"   📈 Promedio avance producción: promedioAvanceProduccionr   z.2f%u"   📦 Promedio avance surtimiento: promedioAvanceSurtimientozQ================================================================================
T)r   r   totalestadisticasZfiltros_aplicadosu   
❌ ERROR CRÍTICO: NError al procesar la solicitud)print_procesar_filtroslistkeysr	   Zobtener_todas_ordeneslen_enriquecer_ordenes_calcular_estadisticasget	Exceptionstr	traceback	print_exc)	r
   filtros_jsonfiltros_procesadosZresultado_ordenesr   ordenes_enriquecidasr   er%   r   r   r   obtener_ordenes_produccion2   sZ    


z4ScoreProduccionController.obtener_ordenes_produccionc              
   C   s   zt d|  | j|}|d r`|d r`|d }t d|d d|d  d	|d
W S t d|d   dd|d dW S W nF ty } z.t dt|  ddt|dW  Y d}~S d}~0 0 dS )u   
        Obtiene el detalle completo de una orden específica.
        
        Args:
            order_line_id (int): ID de OrderNum&Line (clave primaria)
        
        Returns:
            dict: Respuesta con los datos de la orden o error
        u&   
🔍 Obteniendo detalle de Orden ID: r   existeordenu   ✅ Orden obtenida: OrderNumz - PartNumT)r   r-   u   ❌ Orden no encontrada: r   FzOrden no encontradar      ❌ ERROR: $Error al obtener detalle de la ordenN)r   r	   Zobtener_orden_por_idr"   r#   r$   )r
   order_line_id	resultadoorden_enriquecidar*   r   r   r   obtener_detalle_orden   s(    
 z/ScoreProduccionController.obtener_detalle_ordenc                 C   s   |sdS i }dddddddd	}|  D ]\}}||v r(|| r(|| }d
| v rt|trzt|dd }W n   td|  Y q(Y n0 |dkrt|trzt	|}W n   td|  Y q(Y n0 |||< q(|r|S dS )a7  
        Procesa y valida los filtros recibidos del frontend.
        
        Convierte de camelCase (frontend) a snake_case (SQL).
        
        Args:
            filtros_json (dict): Filtros en formato camelCase
        
        Returns:
            dict: Filtros procesados en formato snake_case
        Ndepartamentovendedorproyectopart_num	order_numZfecha_desdeZfecha_hastar6   r7   r8   partNumorderNum
fechaDesde
fechaHastafechaZ u$   ⚠️  No se pudo convertir fecha: u/   ⚠️  No se pudo convertir número de orden: )
itemslower
isinstancer$   r   fromisoformatreplacer   r   int)r
   r'   r(   Zmapeo_filtrosZ	key_camelZ	key_snakevalorr   r   r   r      s8    



z+ScoreProduccionController._procesar_filtros)r-   returnc                 C   sR   dddd d dd d dddd d dd d d}|  D ]\}}||d u r.|||< q.|S )Nr   )IssuedQty_MPreasignado_MDemandado_M	PartNum_MAlternativa_MEn_PO_MPO_MNoPO_MIssuedQty_GPreasignado_GDemandado_G	PartNum_GAlternativa_GEn_PO_GPO_GNoPO_G)rC   r"   )r
   r-   defaultskvr   r   r   _normalizar_mg   s    
z(ScoreProduccionController._normalizar_mgc                 C   sn  g }|D ]^}|  }| |}|drpz0t|d dd}t | j}||d< W n   d|d< Y n0 |dr0zt|d dd}|t  j}||d< |dk rd	|d
< d|d< nD|dkrd|d
< d|d< n*|dkrd|d
< d|d< nd|d
< d|d< W n$   d|d< d|d
< d|d< Y n0 |d}	|	du rHd}	|	dkrdd|d< d|d< nd|	dkrd|d< d|d< nH|	d krd!|d< d|d< n,|	dkrd"|d< d|d< nd#|d< d|d< |d$}
|d%}|
du rd}
|du rd}|
dkrN||
 d }t|d&|d'< |d k r0d(|d)< n|d*k rDd#|d)< nd+|d)< nd|d'< d,|d)< |	| q|S )-u   
        Enriquece los datos de órdenes con información calculada adicional.
        
        Args:
            ordenes (list): Lista de órdenes originales
        
        Returns:
            list: Lista de órdenes enriquecidas
        	OrderDaterA   rB   ZDiasDesdOrdenN
NeedByDateZDiasHastaRequeridar   ZAtrasadaUrgenciaZdangerZColorUrgencia   ZUrgentewarning   u   PróximainfoZNormalr   DesconocidaZ	secondary   AvanceProducción        d   
CompletadoEstadoProduccionZColorEstadoK   ZAvanzadoZprimary2   z
En ProcesoZIniciadoZ	PendienteInsumosDemandadosInsumosEmitidos   ZPorcentajeEmisionu   CríticoZAlertaMaterialP   OKzN/A)
copyr^   r"   r   rF   rG   nowdaysroundappend)r
   r   r)   r-   r4   Zfecha_ordenZdias_desde_ordenZfecha_requeridaZdias_hasta_requeridaZavance_produccionZinsumos_demandadosZinsumos_emitidosZporcentaje_emisionr   r   r   r      s    


























z-ScoreProduccionController._enriquecer_ordenesc                 C   sr  |rt |dkr$ddddi i i dS d}d}d}d}|D ]H}|d}|dur^||7 }|d7 }|d}|dur8||7 }|d7 }q8|dkr|| nd}	|dkr|| nd}
t tdd	 |D }i }|D ]&}|d
pd}||dd ||< qi }|D ]$}|dd}||dd ||< qi }|D ]&}|dd}||dd ||< q&t|	dt|
dt |||||dS )u   
        Calcula estadísticas generales de las órdenes.
        
        Args:
            ordenes (list): Lista de órdenes
        
        Returns:
            dict: Diccionario con estadísticas calculadas
        r   rh   )r   r   ZtotalOrdenesZordenesUnicasZdistribucionDepartamentoZdistribucionUrgenciaZdistribucionEstadoProduccionrg   N   AvanceDeSurtimientoc                 s   s"   | ]}| d r| d V  qdS )r.   N)r"   ).0r-   r   r   r   	<genexpr>      zCScoreProduccionController._calcular_estadisticas.<locals>.<genexpr>DepartamentozSin Departamentora   rf   rk   ZDesconocidorp   )r   r"   setrv   )r
   r   Zsuma_avance_produccionZsuma_avance_surtimientoZcount_avance_produccionZcount_avance_surtimientor-   Zavance_prodZavance_surtZpromedio_avance_produccionZpromedio_avance_surtimientoZordenes_unicasZdistribucion_departamentoZdeptZdistribucion_urgenciaZurgenciaZdistribucion_estadoestador   r   r   r!     sf    





z0ScoreProduccionController._calcular_estadisticas)N)__name__
__module____qualname____doc__r   r+   r5   r   dictr^   r    r!   r   r   r   r   r   "   s   
j,6lr   c           	         s   t   | jddgddd }| jddgddd }| jd	dd
gd fdd}| jddgd fdd}| jddgd fdd}| jddgd fdd}| jddgd fdd}td dS )u   
    Registra las rutas de Flask para el módulo de Score de Producción.
    
    Args:
        app: Instancia de Flask
        mail: Instancia de Flask-Mail (no se usa en este módulo)
    z"/Operaciones/Lerma/ScoreProduccionGET)methodsc                   S   s   t dS )u   
        Renderiza la página HTML del módulo de Score de Producción.
        
        Returns:
            HTML renderizado
        z6Operaciones/Lerma/ScoreProduccion/ScoreProduccion.html)r   r   r   r   r   score_produccion_page  s    z8ejecutar_score_produccion.<locals>.score_produccion_pagez'/Operaciones/Lerma/ScoreProduccion/testc                   S   s    t ddt dddddS )u   
        Ruta de prueba para verificar que el backend funciona correctamente.
        
        Returns:
            JSON con mensaje de éxito
        Tu<   ¡Backend de Score de Producción funcionando correctamente!z%Y-%m-%d %H:%M:%Su#   Score de Producción - Planta Lermaz1.0)r   r   	timestampmoduloversionZaxios_ready)r   r   rt   strftimer   r   r   r   test_score_produccion  s    z8ejecutar_score_produccion.<locals>.test_score_produccionz2/Operaciones/Lerma/ScoreProduccion/obtener-ordenesPOSTc               
      s:  zt d t d t d d} tjdkr<t } t d|  nrtjdkrtjdtjd	tjd
tjdtjdtjdtjdd} dd |  D } t d|   | }|d rdnd}t||fW S  t	y4 } zFt dt
|  ddl}|  tddt
|ddfW  Y d}~S d}~0 0 dS )u   
        Endpoint para obtener todas las órdenes de producción.
        
        Acepta filtros opcionales vía query params (GET) o JSON (POST).
        
        Returns:
            JSON con lista de órdenes y estadísticas
        r   u*   📥 RECIBIENDO PETICIÓN /obtener-ordenesr   Nr   u   📊 Filtros recibidos (POST):r   r6   r7   r8   r<   r=   r>   r?   r;   c                 S   s   i | ]\}}|d ur||qS )Nr   )rz   r\   r]   r   r   r   
<dictcomp>(  r|   zOejecutar_score_produccion.<locals>.obtener_ordenes_endpoint.<locals>.<dictcomp>u   📊 Filtros recibidos (GET):r      i  u   
❌ ERROR EN ENDPOINT: r   Fr   r     )r   r   methodget_jsonargsr"   rC   r+   r   r#   r$   r%   r&   )Zfiltrosr3   status_coder*   r%   
controllerr   r   obtener_ordenes_endpoint  sB    












z;ejecutar_score_produccion.<locals>.obtener_ordenes_endpointz>/Operaciones/Lerma/ScoreProduccion/detalle/<int:order_line_id>c              
      s   z6t d|    | }|d r&dnd}t||fW S  ty } z6t dt|  tddt|dd	fW  Y d
}~S d
}~0 0 d
S )u   
        Endpoint para obtener el detalle de una orden específica.
        
        Args:
            order_line_id (int): ID de OrderNum&Line
        
        Returns:
            JSON con datos de la orden
        u   
📥 GET /detalle/r   r   i  r0   Fr1   r   r   N)r   r5   r   r#   r$   )r2   r3   r   r*   r   r   r   obtener_detalle_orden_endpointB  s    
zAejecutar_score_produccion.<locals>.obtener_detalle_orden_endpointz0/Operaciones/Lerma/ScoreProduccion/departamentosc               
      sZ   z j  } t| dfW S  tyT } z$tddt|ddfW  Y d}~S d}~0 0 dS )z
        Endpoint para obtener todos los departamentos disponibles.
        
        Returns:
            JSON con lista de departamentos
        r   FzError al obtener departamentosr   r   N)r	   Z!obtener_departamentos_disponiblesr   r#   r$   r3   r*   r   r   r   obtener_departamentos_endpointb  s    
zAejecutar_score_produccion.<locals>.obtener_departamentos_endpointz-/Operaciones/Lerma/ScoreProduccion/vendedoresc               
      sZ   z j  } t| dfW S  tyT } z$tddt|ddfW  Y d}~S d}~0 0 dS )z
        Endpoint para obtener todos los vendedores disponibles.
        
        Returns:
            JSON con lista de vendedores
        r   FzError al obtener vendedoresr   r   N)r	   Zobtener_vendedores_disponiblesr   r#   r$   r   r   r   r   obtener_vendedores_endpointz  s    
z>ejecutar_score_produccion.<locals>.obtener_vendedores_endpointz//Operaciones/Lerma/ScoreProduccion/estadisticasc               
      sZ   z j  } t| dfW S  tyT } z$tddt|ddfW  Y d}~S d}~0 0 dS )u   
        Endpoint para obtener estadísticas generales del sistema.
        
        Returns:
            JSON con estadísticas
        r   Fu   Error al obtener estadísticasr   r   N)r	   Zobtener_estadisticas_generalesr   r#   r$   r   r   r   r   obtener_estadisticas_endpoint  s    
z@ejecutar_score_produccion.<locals>.obtener_estadisticas_endpointu;   ✅ Rutas de Score de Producción registradas correctamenteN)r   router   )	appmailr   r   r   r   r   r   r   r   r   r   ejecutar_score_produccion  s     


:r   )r   flaskr   r   r   r   r   sysospathrw   dirnameabspath__file__Z2Consultas_SQL.Operaciones.Lerma.ScoreProduccionSQLr   r   r   r   r   r   r   <module>   s   4   5