
    tz0it&                       S SK JrJrJrJrJrJrJr  S SKJ	r	  S SK
r
S SKrS SKJr  S SKJrJr  S SKJr  S SKrS SKJr  S SKJr  S S	KJrJr  S S
KJr  S SKJr  S SKJrJrJ r J!r!J"r"J#r#J$r$J%r%J&r&J'r'J(r(J)r)J*r*Jr  \
RV                  " S5      r,S r-S r.S r/S\0S\1S\2S\04S jr3S\0S\1S\2S\04S jr4S\\   S\1S\\1   S\2S\4
S jr5S\04S jr6S\1S\1S\7S\2S\1S\04S jr8S r9S  r:S! r;g)"    )apprender_templaterequestsessionjsonifyredirecturl_for)wrapsNdatetime)ListDict)Path)&consultar_docs_por_oportunidad_y_tarea)IS_PRODUCTION)verificar_configuracion upload_document_to_existing_docs)upload_document)
CRMManager)buscar_oportunidad_crminsert_CRM_CONTACTverificar_oportunidad_existentecrear_actualizar_oportunidadobtener_quotation_type_idcrear_formulario_headcrear_formulario_detailsobtener_seller_user_idobtener_nombre_usuariocrear_tarea_cotizaciondebe_crear_tareaactualizar_formulario_con_docsget_FormID_by_TaskIDr   cotizaciones_especialesc                 4  ^  T R                   " S5      U 4S j5       n T R                   " S5      S 5       nT R                   " SS/S9S 5       nT R                   " SS/S9U 4S	 j5       nT R                   " S
S/S9S 5       nT R                   " SS/S9S 5       ng)u   
Función principal que registra todas las rutas del módulo de cotizaciones especiales

Args:
    app: Instancia de Flask
    mail: Instancia del sistema de mail
z)/Ventas/Cotiz/EspecialSolicitud/GetConfigc                  ^  >  [        STR                  R                  S5      TR                  R                  S5      TR                  R                  S5      S.5      $ ! [         aD  n [        R                  S[        U 5       35        [        S[        U 5      S.5      S	4s S
n A $ S
n A ff = f)uR   
Endpoint para que el frontend consulte el modo de operación (Prototipo o Real).
T	PROTOTIPOPROTOTIPO_INTERFAZEMAIL_PROTOTYPE_MODE)successPROTOTIPO_MODEr'   r(   u$   ❌ Error al obtener configuracion: Fr)   error  N)r   configget	Exceptionloggerr,   str)er   s    hC:\Users\victor.barrera\Documents\proyectos\elepV3\Elep\src\App\Ventas_Module\Cotiz\CotizEspSolicitud.pyget_cotiz_config-cotiz_esp_solicitud.<locals>.get_cotiz_config4   s    

	E"%**.."='*zz~~6J'K(+

7M(N	    	ELL?AxHIus1v>?DD	Es   AA 
B,(9B'!B,'B,c            	      p    SSK Jn    [        S[        U R                  R                  SS5      5      05      $ )Nr   current_app	prototipor&   F)flaskr9   r   boolr.   r/   r8   s    r4   is_prototipo)cotiz_esp_solicitud.<locals>.is_prototipo   s;    %	 k0044[%HI
  	    z-/Ventas/Cotiz/EspecialSolicitud/InsertContactPOST)methodsc                     [         R                  " SS9n U (       d  [        SSS.5      S4$ U R                  S5      nU R                  S5      nU R                  S	5      nU(       a  U(       a  U(       d  [        SS
S.5      S4$  [	        UUU5      nUc  [        SSS.5      S4$ [        SUS.5      S4$ ! [
         aD  n[        R                  S[        U5       35        [        S[        U5      S.5      S4s SnA$ SnAff = f)zH
Inserta un contacto en Q_CRM y devuelve el OpportunityNumber generado.
T)silentFu   Se esperaba JSON válido.r+     contactNamecontactNumbercontactEmailzFaltan campos obligatorios.Nz No se pudo crear la oportunidad.r-   )r)   opportunityNumber   zError en InsertContact: )	r   get_jsonr   r/   r   r0   r1   r,   r2   )datarE   rF   rG   new_opportunityr3   s         r4   insert_contact_endpoint4cotiz_esp_solicitud.<locals>.insert_contact_endpoint   sF    t, 4   
 hh}-1xx/ -| 6   
	0O &$?     %4   
  	LL3CF8<= Q   	s$   B5 %B5 5
D?9C>8D>Dz1/Ventas/Cotiz/EspecialSolicitud/BuscarOportunidadc                  
  >  [         R                  " 5       n U S   nTR                  R                  S5      (       a^  [        R                  SU 35        [        U5      n[        U5      nU(       a  [        SUSS.5      S4$ [        SS	U S
3SSS.S.5      S4$ [        R                  SU 35        [        R                  S5        [        R                  STR                  R                  S5       35        [        R                  STR                  R                  S5       35        [        R                  STR                  R                  S5       35        [        R                  S5        [        R                  S5        [        TR                  S9n[        R                  S5        UR                  U5      nUR                  S5      UR                  S5      UR                  S5      UR                  S5      UR                  S5      UR                  S 5      UR                  S!5      UR                  S"5      UR                  S#5      S$UR                  S%5      UR                  S&5      S'S'S(.n[        R                  S)U S*35        [        SUS+S.5      S4$ ! [         aH  n[        R                  S,[        U5       35        [        S[        U5      S-SS.S.5      S4s S.nA$ S.nAf[         a[  n[        R                  S/[        U5       35        [        SS0S1S2S3[        U5      R!                  S4S'5      0S5.S.5      S64s S.nA$ S.nAf["         a?  n[        R                  S7[        U5       35        [        SS8S9S:S.S.5      S;4s S.nA$ S.nAf[$         a`  n[        R                  S<[        U5       3SS=9  [        SS>S?S:[&        R(                  " 5       R+                  5       S@.S.5      S;4s S.nA$ S.nAff = f)Azf
Busca una oportunidad. Usa la BD local si PROTOTIPO=True.
Se conecta al CRM real si PROTOTIPO=False.
opportunity_numberr&   u7   ⚠️ MODO PROTOTIPO: Buscando oportunidad local SQL: Tz/Oportunidad (prototipo) encontrada en BD local.)r)   rK   messagerI   FzLa oportunidad z" no existe en la BD de prototipos.PROTOTYPE_NOT_FOUNDinforQ   code
alert_typer+   i  u,   ✅ MODO REAL: Buscando oportunidad en CRM: zB--- DEBUG: Verificando app.config ANTES de llamar a CRMManager ---zDEBUG: Valor de PROTOTIPO: zDEBUG: Valor de BC_TENANT_ID: BC_TENANT_IDzDEBUG: Valor de BC_ENV_NAME: BC_ENV_NAMEu&   --- DEBUG: Fin de la verificación ---zIntentando crear CRMManager...)r.   zCRMManager creado exitosamente.NoContactNameContactTypeSalespersonNameContactEMailAddressColonyCityCountyMXPostCodePhone )CRM_OpportunityNumberCRM_ContactNameCRM_ContactTypeCRM_AssignedSalespersonCRM_ContactEmailCRM_ContactAdressCRM_ContactColoniaCRM_ContactCityCRM_ContactStateCRM_ContactCountryCRM_ContactZipCRM_ContactNumberCRM_ContactIDCRM_ContactLegalIdentifierzOportunidad z  encontrada y mapeada desde CRM.z-Oportunidad encontrada exitosamente en el CRMz"Oportunidad no encontrada en CRM: CRM_OPPORTUNITY_NOT_FOUNDNu    Campo faltante en la petición: u!   Datos incompletos en la peticiónMISSING_FIELDwarningmissing_field')rQ   rU   rV   detailsrD   u0   Error de conexión en búsqueda de oportunidad: uM   Error de conexión con la base de datos. Intente nuevamente en unos momentos.DATABASE_CONNECTION_ERRORr,   r-   u.   Error inesperado en búsqueda de oportunidad: exc_infoOError interno del servidor. Si el problema persiste, contacte al administrador.INTERNAL_SERVER_ERRORrQ   rU   rV   	timestamp)r   rJ   r.   r/   r1   rS   floatr   r   r   get_opportunity_context
ValueErrorrv   r2   KeyErrorr,   replaceConnectionErrorr0   r   now	isoformat)	rK   opportunity_number_rawnumero_oportunidad_floatoportunidadcrm_managercontexto_crmoportunidad_mapeadar3   r   s	           r4   buscar_oportunidad/cotiz_esp_solicitud.<locals>.buscar_oportunidad   s   I	##%D%)*>%?" zz~~k** UVlUmno ,11G+H(45MN"#' +#T$  	  ##()89O8PPr's$9*0"$    JKaJbcd `a 9#**..:U9VWX <SZZ^^N=[<\]^ ;CJJNN=<Y;Z[\DE <=(

;=>  +BBCYZ .:-=-=d-C'3'7'7'F'3'7'7'F/;/?/?@Q/R(4(8(8(H)5)9)9))D*6*:*:8*D'3'7'7'?(4(8(8(B*.&2&6&6z&B)5)9)9')B%'24'#$ l+A*BBbcd#/N   	   		NN?AxHI "1v7"(     	LL;CF8DE B+"+'QR)@ 	
 
 
 
  		LLKCPQF8TU n7")     	LLI#a&R]aLb p3")!)!9!9!;	   	sc   A?J J HJ 
P(=K+%P+P8AMPP4NPP"AO=7P=Pz&/Ventas/Cotiz/EspecialSolicitud/Enviarc                  n    [         R                  (       a$  S[         R                  ;   a  [        [         5      n O[         R                  " 5       n U (       d)  [        R                  S5        [        SSSSS.S.5      S	4$ [        R                  " S
5      nU(       d)  [        R                  S5        [        SSSSS.S.5      S4$ [        R                  SU 35        [        U 5      nUS   (       d  [        SUS   SSS.S.5      S	4$ [        X5      nUS   (       a  [        R                  SU 35        SnUR                  SS5      S:  a  UR                  SS5      nUSU S3-  n[        SUUS   US   US   UR                  S/ 5      UR                  SS5      S.S .5      S!4$ [        SUS   US"   US#   S.S.5      US$   4$ ! [         a`  n[        R                  S%[        U5       3SS&9  [        SS'S(S)[        R                   " 5       R#                  5       S*.S.5      S+4s S,nA$ S,nAff = f)-u   
Procesa el envío de solicitud de cotización especial
ACTUALIZADO: Manejo mejorado de FormData con archivos

Returns:
    JSON con resultado del procesamiento
zmultipart/form-datau*   Petición sin datos en envío de solicitudFu,   Petición inválida - no se recibieron datosINVALID_REQUESTrv   rT   r+   rD   user_idz2Usuario no autenticado intentando enviar solicitudzUsuario no autenticadoNOT_AUTHENTICATEDi  u:   Procesando solicitud de cotización especial para UserID: validrQ   VALIDATION_ERRORr)   z.Solicitud procesada exitosamente para UserID: u-   Solicitud de cotización enviada exitosamentearchivos_subidosr    con z documento(s)Topportunity_idforms_createdtasks_generateddocs_ids)r   r   r   r   r   )r)   rQ   rK   rI   rU   rV   status_codeu)   Error inesperado en envío de solicitud: r{   r}   r~   r,   r   r-   N)r   content_type"procesar_form_data_con_archivos_v3rJ   r1   rv   r   r   r/   rS   validar_estructura_solicitudprocesar_solicitud_cotizacionr0   r,   r2   r   r   r   )rK   r   validation_resultresultado_procesamientorQ   archivos_countr3   s          r4   enviar_solicitud-cotiz_esp_solicitud.<locals>.enviar_solicitud  s   [	##(=AUAU(U9'B '')KL$#Q 1&/     kk),GST$#; 3&/     KKTU\T]^_ !=T B$W-$#4Y#? 2&/     'DD&R#&y1LWIVW J*../A1EI%<%@%@ASUV%WN~&6mDDG#&*ABR*S)@)Q+BCT+U$;$?$?
B$O,C,G,GHZ\],^
  
 
 
 $#:9#E 7 ?&=l&K   ,M:; ;  
	LLDSVHMX\L] p3")!)!9!9!;	   
	s:   A=G
  AG
 AG
 
BG
 *G
 

H4AH/)H4/H4z3/Ventas/Cotiz/EspecialSolicitud/DiagnosticoArchivosGETc                      [        5       n [        SU [        R                  " 5       R	                  5       S.5      S4$ ! [
         aD  n[        R                  S[        U5       35        [        S[        U5      S.5      S4s SnA$ SnAff = f)	u`   
Endpoint para verificar la configuración del sistema de archivos
Solo para desarrollo/testing
T)r)   diagnosticor   rI   u   Error en diagnóstico: Fr+   r-   N)	r   r   r   r   r   r0   r1   r,   r2   )config_resultr3   s     r4   diagnostico_archivos1cotiz_esp_solicitud.<locals>.diagnostico_archivos  s    	35M,%\\^557  	   	LL23q6(;< Q   	s   ;> 
B9BBBN)route)r   mailr5   r=   rM   r   r   r   s   `       r4   cotiz_esp_solicitudr   +   s     	YY:;E <E"hT 	YY:; < 	YY>Q2 R2j 	YYBVHUN VN` 	YY7&Jc KcL 	YYDugV Wr?   c                     SU ;  a  SSS.$ SU ;  a  SSS.$ SU ;  a  SSS.$ U S   n/ S	QnU H3  nUR                  US
5      R                  5       (       a  M*  SSU S3S.s  $    U S   (       a  [        U S   5      S:X  a  SSS.$ SSS.$ ! [         a0  n[        R                  S[        U5       35        SSS.s SnA$ SnAff = f)u   
Valida la estructura de los datos recibidos

Args:
    data (dict): Datos de la solicitud

Returns:
    dict: Resultado de validación
r   FzFaltan datos de la oportunidad)r   rQ   formularioGeneralz#Faltan datos del formulario generalformulariosEspecificosu(   Faltan datos de formularios específicos)rf   rg   rj   re   z	El campo z es obligatorior   u@   Debe seleccionar al menos un tipo de formulario para cotizaciónTu   Validación exitosau$   Error en validación de estructura: u%   Error interno en validación de datosN)r/   striplenr0   r1   r,   r2   )rK   r   campos_obligatorioscampor3   s        r4   r   r     s    T$"/OPPd*"/TUU#4/"/YZZ =)^(E??5"-3355!&Yug_3UVV )
 ,-T:R5S1TXY1Y"/qrr*?@@ T;CF8DE+RSSTs>   
B 
B 
B 1B 
B #"B B 
C%C :C Cc                     U S   S   n [        U5      nU(       a+  US   S-   nU SU 3n[
        R                  SU SU 35        O$SnU SU 3n[
        R                  SU SU 35        [        U S   UU5      n	U	S   (       d  U	$ / n
/ n[        U S   UU5      nUS   (       a(  U
R                  US   5        UR                  US   5        [
        R                  SU 35        U S     HD  n[        UUU5      nUS   (       d  M  U
R                  US   5        UR                  US   5        MF     S!n/ nS"U ;   a|  U S"   (       ar  [        U S"   5      S!:  a`  [        U S"   UU
U5      nUS   (       a'  US#   nUS$   n[
        R                  S%U S&U S'35        O[
        R                  S(U S&US)    35         [        U UUUU
UUUS*9nUS   (       d  [
        R                  S+U S&US,    35        O[
        R                  S-U S&US,    35         [
        R                  S/U S0[        U
5       S1[        U5       S2U 35        S3UU
UUUS4.$ ! [         a  n[        U5      nUR                  S5      (       a<  UR	                  S5      S   n[
        R                  SU SU 35        SS	S
SSS.s SnA$ UR                  S5      (       a<  UR	                  S5      S   n[
        R                  SU SU 35        SSSSSS.s SnA$ UeSnAff = f! [          a/  n[
        R#                  S.U S&[        U5       35         SnAGN3SnAff = f! [          a3  n[
        R#                  S5[        U5       35        SS6S7S8S9S.s SnA$ SnAff = f):u  
Procesa la solicitud siguiendo el flujo del diagrama
ACTUALIZADO: Gestión de documentos DESPUÉS de crear formularios + ENVÍO DE CORREO

Args:
    data (dict): Datos de la solicitud
    user_id (int): ID del usuario

Returns:
    dict: Resultado del procesamiento
r   rf   zOPPORTUNITY_CLOSED::   z(Intento de procesar oportunidad cerrada z con status Ful   El número de oportunidad ingresado ya terminó su proceso, por favor ingresar un no. de oportunidad válidoOPPORTUNITY_CLOSEDrv   rD   )r)   rQ   rU   rV   r   NzOPPORTUNITY_IN_PROCESS:z+Intento de procesar oportunidad en proceso u   Hay una solicitud previa de ingeniería por lo que no se puede generar una nueva. Comuníquese con ingeniería para que cancelen las tareas y puedan volver a asignar nuevas tareasOPPORTUNITY_IN_PROCESSrS   i  Version-u   Creando nueva versión z para oportunidad zCreando nueva oportunidad u
    versión r)   r   form_idtasksz*Tareas generadas tras formulario general: r   r   archivostotal_archivos_subidosr   zDocumentos procesados para : 	 archivosz!Error procesando documentos para rQ   )rK   r   rP   nueva_versionr   r   r   r   u,   Error enviando correo de notificación para mensajeu2   Correo de notificación enviado exitosamente para z&Error inesperado enviando correo para z"Solicitud procesada exitosamente: z	, Forms: z	, Tasks: z, Archivos: T)r)   r   r   r   r   r   z%Error en procesamiento de solicitud: z&Error interno al procesar la solicitudPROCESSING_ERRORr,   r-   )r   r   r2   
startswithsplitr1   rv   rS   r   procesar_formulario_generalappendextendprocesar_formulario_especificor   "procesar_documentos_con_formids_v2*enviar_notificacion_cotizacion_especial_v2r0   r,   )rK   r   rP   oportunidad_existenter3   	error_msgstatusr   r   resultado_oportunidadr   r   resultado_general
formularioresultado_formr   docs_ids_generadosresultado_docsresultado_correos                      r4   r   r   (  s   T
!-01HI	$CDV$W!< !1)<q@M 231]ODNKK1-@RSeRfghM 231]ODNKK45G4H
S`Rabc !=!
 %Y/((  8$%
 Y'  !29!=>""#4W#=> 	@@QRS 78J;N i(($$^I%>?&&~g'>? 9 "#$z"2s4
;K7Lq7P?Z 	N i()78P)Q&%3J%?"9.9ILbKcclmn!B>BRRTUcdmUnTopq	^I-#5++ /'=	  $I.!MnM]]_`pqz`{_|}~PQ_P``bcst}c~b  A  B 	88H	RUVcRdQeenor  tC  pD  oE  EQ  Rh  Qi  j  	k ,*. 6*
 	
{  	AI##$9::"-a0!IJ\I]]ijpiqrs$  N0"+#&  %%&?@@"-a0!LM_L``lmsltuv$  U4"(#&  7	h  	^LLA.AQQSTWXYTZS[\]]	^$  
<SVHEF?&!
 	

s   M I A1M A;M B2M :8L 2M 3L <M 
LAL	/L0M 5AL	LM L		LM 
M
$M?M M

M 
N
(N?N
N
formulario_datar   r   returnc                 (    [        S5      n[        XU5      nUS   (       d  U$ US   nSU ;   a$  U S   (       a  [        XPS   5      nUS   (       d  U$ [        U5      n/ nU(       aO  [	        U5      n	[        U5      n
[        U	UUU
5      nUS   (       d  U$ US   /n[        R                  SU 35        O[        R                  SU 35        SUUS	.$ ! [         a2  n[        R                  S
[        U5       35        SSSSS.s SnA$ SnAff = f)z
Procesa el formulario general (siempre presente)

Args:
    formulario_data (Dict): Datos del formulario general
    opportunity_id (str): ID de la oportunidad
    user_id (int): ID del usuario

Returns:
    Dict: Resultado del procesamiento
Generalr)   r   	preguntastask_idz(Formulario general procesado con tarea: z(Formulario general procesado SIN tarea: Tr)   r   r   z&Error al procesar formulario general: Fz$Error al procesar formulario generalr   r,   r)   rQ   rU   rV   N)r   r   r   r    r   r   r   r1   rS   r0   r,   r2   )r   r   r   quotation_type_idresultado_headr   resultado_details
debe_crearr   seller_user_id	user_nameresultado_taskr3   s                r4   r   r     sB   8
5i@ /~RYZi(!! + /)ok.J 8R]B^ _$Y/(( &&78
3G<N.w7I3	N "),%%#I./EKKB7)LMKKB7)LM 
 	
  
=c!fXFG=&!	
 	

s/   "C .C AC <C 
D'DDDc                     U R                  SS5      n[        U5      n[        XU5      nUS   (       d  U$ US   nSU ;   a$  U S   (       a  [        X`S   5      nUS   (       d  U$ [	        U5      n/ n	U(       aS  [        U5      n
[        U5      n[        U
UUU5      nUS   (       d  U$ US   /n	[        R                  SU SU S	35        O[        R                  S
U SU S	35        SUU	S.$ ! [         aE  n[        R                  S[        U5       35        SSU R                  SS5       3SSS.s SnA$ SnAff = f)u   
Procesa un formulario específico (plantas, UPS, etc.)

Args:
    formulario_data (Dict): Datos del formulario específico
    opportunity_id (str): ID de la oportunidad
    user_id (int): ID del usuario

Returns:
    Dict: Resultado del procesamiento
tipor   r)   r   r   r   u,   Formulario específico procesado con tarea: z (tipo: )u,   Formulario específico procesado SIN tarea: Tr   u*   Error al procesar formulario específico: FzError al procesar formulario nombreu   específicor   r,   r   N)r/   r   r   r   r    r   r   r   r1   rS   r0   r,   r2   )r   r   r   tipo_formularior   r   r   r   r   r   r   r   r   r3   s                 r4   r   r     s   9
)--fi@5oF /~RYZi(!! + /)ok.J 8R]B^ _$Y/(( &&78
3G<N.w7I3	N "),%%#I./EKKFwixXgWhhijkKKFwixXgWhhijk 
 	
  
A#a&JK67J7J8Ub7c6de&!	
 	

s0   4C/ .C/ &AC/ *AC/ /
D>9:D93D>9D>archivos_formulariosr   c                 V    [        U5      nSSSSSSS[        R                  " 5       / / 0 S.n/ n/ n/ nSSSSSSS	S
SSSS.n	[        R	                  S[        U 5       S35        [        R	                  SU 35        U  GHp  n
US==   S-  ss'    U
R                  SS5      nU
R                  SS5      nU
R                  S/ 5      nU
R                  SS5      n[        R	                  SU S[        U5       S35        U(       a  [        U5      S:X  a  [        R	                  SU S35        M  US==   [        U5      -  ss'   SnU	R                  X5      nUb$  U H  nUR                  U5      (       d  M  Un  O   O[        R                  S U S!35        U(       d\  S"U S#U S$3n[        R                  S%U 35        UR                  UUS&S'.5        US(==   S-  ss'   US)==   [        U5      -  ss'   GM|  [        R	                  S*U 35        [        UUUUUS+9nUS,   (       Gah  [        US-   5      n[        US.   5      nUS/   nUS0==   U-  ss'   US)==   U-  ss'   US1==   US2   S1   -  ss'   U(       aU  [        UU5      nUS,   (       a$  [        R	                  S3U S4U 35        UUS5   U'   O[        R                  S6U S7U 35        U(       a+  UU;  a%  UR                  U5        US8   R                  U5        UR                  UUUUUUR                  S9/ 5      UR                  S20 5      S:.5        US;==   S-  ss'   [        R	                  S<U S=U S>U 35        US:  a  UR                  UU S?3S@US.   SA.5        GM  GM  SBU S=USC    3n[        R                  S%U 35        UR                  UUSDUSE.5        US(==   S-  ss'   US)==   [        U5      -  ss'   GMs     [        R                  " 5       USK'   USK   USL   -
  R                  5       USM'   XuSN'   US0   S:X  a$  [        U5      S:  a  SOSP[        U5       SQ3SRUUSS.$ STUS0    SU3nUS;   S:  a  USVUS;    S3-  n[        U5      S:  a  USW[        U5       SX3-  n[        R	                  SY5        [        R	                  SZUS    35        [        R	                  S[US;    35        [        R	                  S\US(    35        [        R	                  S]US    35        [        R	                  S^US0    35        [        R	                  S_US)    35        [        R	                  S`US1   Sa Sb35        [        R	                  ScUSM   Sa Sd35        [        R	                  SeU 35        SHUUS0   UUUUSf.$ ! [         a  nSFU
R                  SSG5       S=[        U5       3n[        R                  USHSI9  UR                  U
R                  SSG5      USJS'.5        US(==   S-  ss'   US)==   [        U
R                  S/ 5      5      -  ss'    SnAGM  SnAff = f! [         aK  nSg[        U5       3n[        R                  USHSI9  SOShSiUUSSU (       a  [        U 5      OSSj.Sk.s SnA$ SnAff = f)lu}  
Versión mejorada para procesar documentos asociándolos con FormIDs específicos

Args:
    archivos_formularios (List[Dict]): Lista de formularios con sus archivos
    opportunity_id (str): ID de la oportunidad
    forms_created (list[str]): Lista de FormIDs creados
    user_id (int): ID del usuario

Returns:
    dict: Resultado del procesamiento con estadísticas detalladas
r   )formularios_procesadosformularios_exitososformularios_fallidostotal_archivos_intentadostotal_archivos_exitosostotal_archivos_fallidos   tamaño_total_mbtiempo_inicioerrores_por_formularior   mapeo_formid_docsFormSolicVisFormPTTransNacFormPTTransULFormAireFormSistCritUPSFormGralFormBess	FormSolar
FormEneCog	FormImessFormProyecEsp)SolicVis
PTTransNac	PTTransULAireSistCritUPSr   BessSolarEnergyCogenerationImess	ProyecEspu    🚀 Procesando documentos para z formulario(s)u   📋 FormIDs disponibles: r   r   formularioTipore   formularioNombrer   	totalSizeu   📝 Procesando formulario:  (z
 archivos)u   ⏭️ z: sin archivos, omitiendor   Nz'El sufijo esperado para el formulario 'z
' es None.u!   No se encontró FormID para tipo z (sufijo esperado: r   u   ❌ form_id_no_encontrado)r   r,   
tipo_errorr   r   u   🎯 FormID encontrado: )r   r   filesr   
created_byr)   r   archivos_fallidosdocs_idr   r   estadisticasu   🔗 FormID z vinculado con DocsID r   u"   ⚠️ No se pudo vincular FormID z con DocsID r   download_urls)r   r   r  archivos_exitososr  r  r  r   u   ✅ r   z archivos subidos, DocsID: z archivos fallaronarchivos_parciales_fallidos)r   r,   r  r  zError subiendo archivos para rQ   upload_completo_fallido)r   r,   r  detalleszError procesando formulario desconocidoTr{   excepcion_procesamiento
tiempo_finr   duracion_total_segundosr   F"   No se pudo subir ningún archivo. z errores en formulariosUPLOAD_FAILED)r)   rQ   rU   r  erroreszProcesados r    en r   z advertencia(s)u,   📊 === RESUMEN GLOBAL DE PROCESAMIENTO ===u       📋 Formularios procesados: u      ✅ Formularios exitosos: u      ❌ Formularios fallidos: u      📄 Archivos intentados: u      ✅ Archivos exitosos: u      ❌ Archivos fallidos:       📏 Tamaño total: .2f MBu      ⏱️ Duración total: 	 segundosu      🆔 DocsIDs generados: )r)   rQ   r   r   r$  r   r  z%Error general procesando documentos: z#Error interno procesando documentosr   )error_generalr   r   r   )r)   rQ   rU   technical_errorr  )r   r   r   r1   rS   r   r/   endswithrv   r,   r   upload_form_files_v2r!   r0   r2   total_seconds)r   r   r   r   r  estadisticas_globalesr   errores_procesamientor   mapeo_formulariosr   r   nombre_modulor   
total_sizeform_id_buscadosufijo_esperador   r   resultado_uploadr  r  r  actualizar_resultador3   success_messages                             r4   r   r   W  s   a
+G4
 '($%$%)*'('( !%\\^&("$!#!
   "!# '*(,! ". (
 	6s;O7P6QQ_`a0@A3O!":;q@;um"1"5"56F"K / 3 34F K*..z2>,00a@
:?:K2cRZm_\fgh3x=A#5KK'/)::S TU%&ABc(mSB #'"3"7"7"W".#0"++O<<.5O! $1
 NN%L_L]]g#hi&"COCTTghwgxxy zILL4	{!34)00&5!*&=2 
 **@AQFA)*CDHUD66GHI $8+#1"#)$  $I..(+,<=O,P(Q%(+,<=P,Q(R%.y9G)*CDHYYD)*CDHYYD)*<=AQR`AabtAuu= /Mo_f/g,/	:"KK,6GG]^e]f(ghZa12EFW"NN-OP_O``lmtlu+vw 72D#D*11':-.BCJJ7S +11#2+:#*->->)9)=)=or)R(8(<(<^R(P3  **@AQFAKK$&7r:K9LLghogp qr )1,-44*9(9'::L%M*G1ABU1V	6  - #@?PPRScdmSnRo pILL4	{!34)00&5!*&?$4	2  **@AQFA)*CDHUD[  4v /7llnl+!,/2G2XX
-/ 	78 ;P67 !!:;q@SI^E_bcEc ?DY@Z?[[rs' 50  ((=>W(X'YYbc !781<&;<R&S%TTbccO$%)s+@'A&B/RRO 	BD67LMe7f6ghi34IJ`4a3bcd34IJ`4a3bcd34IJe4f3ghi01FG`1a0bcd01FG`1a0bcd-.CDV.WX[-\\_`a12GHa2bcf1ggpqr12D1EFG &&;<U&V*,&<1
 	
c  	m:?;N;NO_an;o:pprsvwxsyrz{	Y6%,,"1"5"56F"V&";. 
 &&<=B=%&?@CH[H[\fhjHkDll@@	mv  
;CF8D	Y.<&(!**++,H\3/C+Dbc	
 	

s   BY BV-,Y .AV-7B V-7Y :FV-Y AV-.A)Y EY -
Y7BYY YY 
Z(A Z#Z(#Z(c                     U R                   R                  S5      nU(       a  [        R                  " U5      nO0 n/ nSSSSSSSS	S
SS.
n[        R                  S5        UR                  5        GH$  u  pVSU S3nU R                  R                  U5      n[        R                  SU 35        [        R                  S[        U5       35        / n	/ n
[        U5       GH  u  pU(       d9  [        R                  SUS-    SU S35        U
R                  SUS-    S35        MF  UR                  (       a  UR                  R                  5       S:X  a9  [        R                  SUS-    SU S35        U
R                  SUS-    S35        M  UR!                  S["        R$                  5        UR'                  5       nUR!                  S5        US:X  aG  [        R                  SUR                   SU S35        U
R                  UR                   S35        GM<  US:  aT  US-  n[        R                  SUR                   SU SUS  S!35        U
R                  UR                   SUS  S!35        GM  [)        UR                  5      R*                  R-                  5       n1 S"knUU;  aM  [        R                  SUR                   SU S#U S$35        U
R                  UR                   S#U S$35        GM   UR!                  S5        UR/                  S%5      nUR!                  S5        [        U5      S:X  aG  [        R                  SUR                   SU S&35        U
R                  UR                   S&35        GM   U	R                  U5        [        R                  S+UR                   S,US%-  S- S.35        GM     U
(       aF  [        R                  S/U S([        U
5       S035        U
 H  n[        R                  S1U 35        M     U	(       d  GM  [7        S2 U	 5       5      nU	 H  nUR!                  S5        M     UR                  UUU	[        U	5      UU
S3.5        [        R                  S4U S([        U	5       S5US%-  S- S635        GM'     U(       aM  X2S7'   [7        S8 U 5       5      n[7        S9 U 5       5      n[        R                  S:U S5US%-  S%-  S  S;35        U$ [        R                  S<5        U$ ! [0         aX  n[        R3                  S'UR                   S([5        U5       35        U
R                  UR                   S)35         S*nAGM  S*nAff = f! [        R8                   a-  n[        R3                  S=[5        U5       35        0 s S*nA$ S*nAf[0         a,  n[        R3                  S>[5        U5       3S?S@9  0 s S*nA$ S*nAff = f)Au   
Versión mejorada para procesar FormData con mejor manejo de archivos

Args:
    request: Objeto request de Flask

Returns:
    Dict: Datos estructurados incluyendo archivos organizados por formulario
rK   r   r   r   r   r   r   r   r  r  r  )
r  r  r  r  r  r	  r
  r  r  r  u'   🔍 Procesando archivos de FormData...files_z[]u!   🔍 Buscando archivos en campo: u   🔍 Archivos encontrados: u   ❌ Archivo r   r%  u   : objeto archivo vacíoArchivo u   : objeto vacíore   z: sin nombre de archivoz: sin nombrer   u   : archivo vacíoi       z: muy grande (r'  zMB)>   .doc.jpg.pdf.png.xls.docx.jpeg.xlsxu   : extensión no permitida (r      u   : contenido vacíou   ❌ Error leyendo archivo r   z: error de lecturaNu   ✅ Archivo válido: r  .1f KB)   ⚠️ u    archivos inválidos:z   - c              3      #    U  HY  nUR                  S 5      b  M  UR                  S [        R                  5      =(       d    UR                  5       =(       d    S v   M[     g7f)r   N)seekosSEEK_ENDtell).0archivos     r4   	<genexpr>5procesar_form_data_con_archivos_v3.<locals>.<genexpr>  sG      !#3||A HGLLBKK0GGLLNGaG#3s   A#AA#)r  r  r   cantidadr  archivosInvalidosu   📎 u    archivos válidos (z
 KB total)r   c              3   *   #    U  H	  oS    v   M     g7f)rR  N rN  forms     r4   rP  rQ    s      S>Rdj!1>R   c              3   *   #    U  H	  oS    v   M     g7f)r  NrU  rV  s     r4   rP  rQ    s     P;O4+.;OrX  u   📁 Total procesado: z MB)u7   📄 No se encontraron archivos válidos en el FormDatau+   ❌ Error decodificando JSON del FormData: u,   ❌ Error procesando FormData con archivos: Tr{   )rW  r/   jsonloadsr1   rS   itemsr  getlistdebugr   	enumeraterv   r   filenamer   rJ  rK  rL  rM  r   suffixlowerreadr0   r,   r2   sumJSONDecodeError)r   	json_datarK   r   form_modules	tipo_formmodulo
field_namearchivos_tipoarchivos_validosarchivos_invalidosirO  	file_sizesize_mb	extensionextensiones_permitidasheaderr3   r,   r3  total_archivoss                         r4   r   r   H  s   OLL$$V,	::i(DD  " '*(, ". (
 	=>!-!3!3!5I!)B/J#MM11*=MLL<ZLIJLL6s=7I6JKL  "!#'6
NN\!A#d9+E\#]^&--1_.MN''7+;+;+A+A+Cr+INN\!A#d9+E\#]^&--1\.JK Q,#LLN	Q>NN\'2B2B1C4	{Rb#cd&--1A1A0BBR.ST.';7GNN\'2B2B1C4	{R`ahil`mmp#qr&--1A1A0B.QXY\P]]`.ab !!1!1299??A	)l&$::NN\'2B2B1C4	{Rmnwmxxy#z{&--1A1A0BB]^g]hhi.jkLLO$\\$/FLLO 6{a'g6F6F5GtI;Vh'ij*11W5E5E4FFX2YZ  ( !''03G4D4D3ER	RVWZG[[_`as 7x "2c:L6M5NNcde/ENNU5'?3 0    !#3! 
  0GLLO  0 %++&/(. 0 #$4 5!+);-  eI;b5E1F0GG[\fgk\klo[ppz{|C "6H  3  S>R SSNP;OPPJKK00@@TU_`dUdeiUijmTnnrst  KKQR_ ! LL#=g>N>N=OrRUVWRXQY!Z[&--1A1A0BBT.UVb  B3q6(KL	 CCF8LW[\	sj   K8U* ;BTBU* CU* .U* 
U'AU"U* "U''U* *W>"V& W&W3!WWWr   r  r  c                 
    U(       a  [        U5      S:X  a  SS/ / SSSSSS.S.$ [        R                  S[        U5       SU  35        S	U S
U  3nSnSSKJn  U" X6U5      nUS   (       d  SSUS    3SS.$ US   n	[        R                  SU	 SU  35        [        U5      SSS[
        R                  " 5       0 0 S.n
/ n/ n[        US5       GHO  u  p U(       a  UR                  (       dV  SU S3n[        R                  SU 35        UR                  SU 3USS.5        U
S   R                  SS5      S-   U
S   S'   Mu  UR                  S[        R                  5        UR                  5       nUR                  S5        [!        UR                  5      R"                  R%                  5       nU
S   R                  US5      S-   U
S   U'   [        R                  S U S
[        U5       S!UR                   S"US#-  S$ S%3	5        S&U  S'U 3n['        UU	UR                  UUS(9nUS   (       a  UR                  UR                  US)   S*   US)   S+   U	US)   S,   UUUS-.5        U
S.==   S-  ss'   U
S/==   U-  ss'   [        R                  S0U S1UR                   S2US)   S+    35        GM  UR                  SS35      nUR                  UR                  US4US5.5        U
S   R                  S4S5      S-   U
S   S4'   [        R)                  S6U S!U 35        GMR     [        U5      U
S<'   [
        R                  " 5       U
S='   U
S=   U
S>   -
  R1                  5       U
S?'   U
S/   S@-  U
SA'   U
S.   S:  nU
S<   S:X  a
  SBU
S.    SC3nO#U
S.   S:X  a  SDU
S<    SE3nSnOU
S.    SFU
S<    SG3n[        R                  SHU  SI35        [        R                  SJU
S.    35        [        R                  SKU
S<    35        [        R                  SLU
SA   SM SN35        [        R                  SOU
S?   SM SP35        U
S   (       aN  [        R                  SQ5        U
S   R3                  5        H"  u  nn[        R                  SRU S!U SS35        M$     U
S   (       aN  [        R                  ST5        U
S   R3                  5        H"  u  nn[        R                  SRU S!U SU35        M$     UUUUU
SV   UU	U Vs/ s H  nUS+   PM
     snU
SW.	$ ! [*         a|  nS7U S![-        U5       3n[        R)                  USS89  UR                  [/        US9SU 35      US:[-        U5      S;.5        U
S   R                  S:S5      S-   U
S   S:'    SnAGM  SnAff = fs  snf ! [*         a`  nSX[-        U5       3n[        R)                  USS89  SSYSZU/ / SU(       a  [        U5      OSSU(       a  [        U5      OSUS[.S\.s SnA$ SnAff = f)]uf  
Versión mejorada para subir múltiples archivos de un formulario

Args:
    form_id (str): ID del formulario
    opportunity_id (str): ID de la oportunidad
    files (list): Lista de archivos FileStorage
    user_id (int): ID del usuario
    created_by (str): Nombre del usuario

Returns:
    dict: Resultado del procesamiento con estadísticas detalladas
r   TzNo hay archivos para procesarN)total_intentadostotal_exitosostotal_fallidos   tamaño_total)r)   rQ   r   r  r  r  u   🚀 Iniciando upload de z archivos para FormID zVentas/Formularios//Q_SpQ_FormsHead)crear_docs_headr)   Fz#Error creando grupo de documentos: rQ   DOCS_HEAD_ERROR)r)   rQ   rU   r  u   📋 DocsHead z creado para FormID )rv  rw  rx  ry  r   archivos_por_tipoerrores_por_tipor   r;  u    está vacío o sin nombrerH  archivo_archivo_vacio)archivo_originalr,   r  r  r~  u   📄 Procesando archivo r   r  rE  rF  rG  zArchivo de z - Oportunidad )file_objr  titledescriptionruta_completarK   doc_line_iddownload_urlremote_path)r  r  r  r  r  ro  	file_typeupload_orderrw  ry  u   ✅ Archivo z	 subido: z -> zError desconocido en uploadupload_failed)r  r,   r  ro  u   ❌ Error subiendo archivo zError procesando archivo r{   r`  	excepcion)r  r,   r  r  rx  r   r   duracion_segundosr<  r   zTodos los archivos (z) fueron subidos exitosamenter"  z erroresz archivos subidos, z	 fallaronu#   📊 Resumen de upload para FormID r   u      ✅ Exitosos: u      ❌ Fallidos: r&  r'  r(  u      ⏱️ Duración: r)  u      📁 Tipos de archivo:z      z archivo(s)u      ⚠️ Tipos de error:z
 error(es)rv  )	r)   rQ   r   r  total_procesadosr  r  r  r  z'Error general en upload_form_files_v2: z1Error interno al procesar archivos del formularioFORM_FILES_ERROR)rv  rw  rx  r*  )r)   rQ   rU   r+  r   r  r  r  )r   r1   rS   )Consultas_SQL.Utilities.DocsManagementSQLr|  r   r   r_  r`  rv   r   r/   rJ  rK  rL  rM  r   ra  rb  r   r,   r0   r2   getattrr.  r\  )r   r   r  r   r  r  origenr|  docs_head_resultr  r  r   r  indexr  r   ro  rq  r  	resultador3   r)   rQ   extcount
error_typerO  s                              r4   r-  r-    sO   ~
E
a:$&%'()&'&'%&	!  	/E
|;QRYQZ[\ .n-=QwiH" 	N*7JG	* @AQR[A\@]^)  #9-nWI-A'KL !$E
%\\^!# "
 (2OEJyx'8'8"*5'1K LINNWYK#89%,,.6ug,>!*&5. 
 IUUgHhHlHlm|~  IA  DE  IEL!34_E a-$MMO	a  !2!23::@@B	?KL_?`?d?denpq?ruv?v01)<6ugQs5zl"XM^M^L__abklpbpqtauuyz{ !,G9ONCST =%#"++ +"/	 Y'$++,4,=,='0'8'G(1&(9.(I#*'0'8'G%.%.(-	- 	 !!12a72 1Y>1KK,ugYx?P?P>QQUV_`fVghvVwUx yz )i9V WI%,,,4,=,=!*&5%.	.  IUUgHhHlHlm|~  IA  DE  IEL!34_ELL#>ugR	{!ST}  3\ *-->)?%&%-\\^\"-9,-G,WfJg-g,v,v,x()+7+HK+X'( /014()Q.,\:J-K,LLijG*+q0:<HX;Y:ZZbcGG%&6788KLYiLjKkktuG 	9'!DE'5E(F'GHI'5E(F'GHI-l;M.Ns-SSVWX+L9L,Mc+RR[\]+,KK35*+>?EEG
UfSEE7+>? H *+KK35%12D%E%K%K%M!
EfZL5'DE &N  0!2 ,-? @*EUVEU'gn5EUV(

 
	
_  y7wbQI	Y6!(((/*QVPWFX(Y&"-!$Q	*  AMM_@`@d@deprs@twx@x/0==yn W  
=c!fXF	Y.J&( "!#27CJQ"#05#e*1!*	
 	

s~   #V AV 9AV A,T
V E,T
0V 3A+T
GV 5VV 

VA0VV VV 
X"AW=7X=Xc                     U R                  S/ 5      nSSSSSS.nU H  nUR                  SS5      R                  5       nUR                  SS5      nSU;   a  SU;   a  UR                  5       S	;   US
'   MY  SU;   a  XRS'   Me  SU;   a  XRS'   Mq  SU;   d  SU;   a  XRS'   M  SU;   d  M  SU;   d  M  XRS'   M     U$ ! [         a3  n[        R	                  S[        U5       35        SSSSSS.s SnA$ SnAff = f)u   
Extrae datos específicos del formulario general para el correo

Args:
    formulario_general (dict): Datos del formulario general

Returns:
    dict: Datos extraídos y formateados
r   Fre   )requiere_visitaestadociudad	direcciondescripcion_proyectopregunta	respuestavisitaespecialista)u   sísiyesr  r  r  u
   direcciónr  u   informaciónproyector  z/Error extrayendo datos del formulario general: N)r/   rb  r0   r1   rv   r2   )formulario_generalr   datos_extraidosr  pregunta_textor  r3   s          r4    extraer_datos_formulario_generalr    s%   %
&**;;	  %$&
 "H%\\*b9??AN ["5I>)n.N5>__5FJ^5^ 12^+,5)^+,5)/;.3P/8,>1jN6R:C 67 "  
HQQR$$&
 	

s*   B#B; )B; 1	B; ;
C8(C3-C83C8c                 |   [        X5      n/ nU H  nUS   nUS   nU(       a'  UR                  5       R                  S5      (       a  SnOSnU(       a&  UR                  5       (       a  UR                  5       nO)U(       a   [        R
                  R                  U5      nOSnUR                  UUUS.5        M     U$ )zh
Construye el arreglo archivos_adjuntos a partir de la info en BD
para la oportunidad y task indicados.
      )zhttp://zhttps://urllocalre   )r   rutar   )r   rb  r   r   rK  pathbasenamer   )	oportunity_idr   rowsarchivos_adjuntosrowr  r  r   r   s	            r4   obtener_archivos_adjuntosr    s    
 2-ID A1vDJJL++,CDDDDU[[]][[]FWW%%d+FF  "
 	- 6 r?   c           
          SSK Jn  SSKJn	  SSKJn
  [        U5      n/ nU H  nSU;   a  UR                  S5        M  SU;   a  UR                  S5        M5  S	U;   a  UR                  S
5        MN  SU;   a  UR                  S5        Mg  SU;   a  UR                  S5        M  SU;   a  UR                  S5        M  SU;   a  UR                  S5        M  SU;   a  UR                  S5        M  SU;   a  UR                  S5        M  SU;   d  M  UR                  S5        M     [        U R                  S0 5      5      n0 SU_SU S   R                  SS5      _SU S   R                  S S!5      _S"U_S#U	R                  " 5       R                  S$5      _S%U	R                  " 5       R                  S&5      _S'U_S([        U5      _S)[        U5      _S*U_S+U_S,US-   _S.US/   _S0US1   _S2US3   _S4US4   _S5S6_S7S8U 30EnS9U 3nUS::  a	  US;U S<3-  nUS4   (       a  S=U S>3nS?S@SAS0SB.nU H  n[        U5      USC'   SDnU  [        [        U5      5      n[        UU5      n[        SE:X  a  SFnOYSU;   a  SGnOPSU;   a  SHnOGS	U;   a  SInO>SU;   a  SJnO5SU;   a  SJnO,SU;   a  SKnO#SU;   a  SKnOSU;   a  SLnOSU;   a  SKnOSU;   a  SMnU
R                   R                  SN5      (       a  U
R                   R                  SO5      nU" SPUSQU/0SRUUSS9nM     UR                  STSE5      (       a?  UR                  SU0 5      R                  SAS5      n["        R%                  SVU SWU 35        U$ ["        R'                  SXU SYUR                  SZS[5       35        U$ ! [(         aF  n["        R'                  S\[+        U5       3S?S]9  SES^[+        U5       3[+        U5      /S_.s S`nA$ S`nAff = f)au   
Versión mejorada del envío de correo de notificación.
Corregida para:
1. Evitar KeyError si no hay tareas.
2. Usar current_app para acceder a la configuración (evita AttributeError).
r   )enviar_correo_universalr   r8   r   u   Solicitud de Visita Técnicar   z.Plantas, Tableros y Transformadores Nacionalesr   z&Plantas, Tableros y Transformadores ULr   zAires Acondicionadosr   u   Sistemas Críticos (UPS)r   BESSr   zSistemas Solaresr  u   Energía y Cogeneraciónr  iMessr  zProyectos Especialesr   numero_oportunidadcliente_nombrer   rg   zNo especificadovendedor_asignadori   zNo asignadosolicitante_nombrefecha_solicitudz%d/%m/%Yhora_solicitudz%H:%Mformularios_solicitadostotal_formulariostotal_tareasform_idsversionproyecto_estador  proyecto_ciudadr  proyecto_direccionr  proyecto_descripcionr  r  url_sistemazhttps://sycelephant.comurl_oportunidadz+https://sycelephant.com/ventas/oportunidad/u;   🔔 Nueva Solicitud de Cotización Especial - Oportunidad r   u    (Versión r   u   🚨 URGENTE - u    - REQUIERE VISITA TÉCNICATu9   No se generaron tareas para envío de correo específico.total_destinatarios)r)   r   destinatariosTaskIdre   Fzvictor.barrera@igsa.com.mxzmarco.escobar@igsa.com.mxzcarlos.huitron@igsa.com.mxzjose.lopez@igsa.com.mxzrogelio.robles@igsa.com.mxzcarlos.anguiano@igsa.com.mxzdiego.rivas@igsa.com.mxzarturo.martinez@igsa.com.mxr(   EMAIL_PROTOTYPE_TOADRESSz.Emails/Ventas/Cotiz/CotizEspSolicitudMail.htmlTOi  )template_pathasuntodestinatarios_adicionalesmail_list_idtemplate_datar  r)   r  u&   ✅ Proceso de correo finalizado para z. Enviados: u   ❌ Error enviando correo para r   r   zError desconocidoz5Error en enviar_notificacion_cotizacion_especial_v2: r{   u'   Error interno al enviar notificación: )r)   r   r$  N)#App.Utilities_module.MailManagementr  r   r;   r9   r   r   r  r/   r   strftimer   intr"   r  r   r.   r1   rS   r,   r0   r2   )rK   r   rP   r   r   r   r   r   r  r   r9   r   formularios_nombresr   datos_proyector  r  r  taskIDdestinatarioformID_taskarchivosAdjuntosr  r3   s                           r4   r   r     s   N
O%% +73	 !$G(#**+IJ!W,#**+[\ G+#**+STw&#**+AB"g-#**+EFw&#**62'#**+=>(#**+EF'#**73 G+#**+AB) %. :$((CVXZ:[\
 "4
 d=1556GIZ[
  m!4!8!89RTa!b	
 !)
 x||~66zB
 hlln55g>
 &':
  ]!3
 C0
 
  }!
& ~h7'
( ~h7)
* !."=+
, #N3I$J-
. ~.?@/
4 45
6 !L^L\]7
> OOaNbc1M?!44F +,&vh.IJF R3Q7
	 &F&)&kM(#L.s6{;K8T%;![0#>L%4#?L$3#;L;.#?L&+5#?L;.#@L K/#@L![0#<L K/#@L$3#@L !!%%&<==*11556PQ/N<.+ "+"2	IE &\ ==E**"+--"D"H"HI^`a"bKK@@PP\]p\qrs  LL:>:J"Y]][dfyMzL{|} 
LSQRVHU`de@QIAx
 	

s+   D	N IN *,N 
O'!;O"O'"O')<r;   r   r   r   r   r   r   r	   	functoolsr
   loggingrZ  r   typingr   r   pathlibr   rK  =Consultas_SQL.Operaciones.Ingenieria.Cotiz.CotizCreatedIngSQLr   r.   r   #App.Utilities_module.DocsManagementr   r   r   "App.Utilities_module.CRMManagementr   /Consultas_SQL.Ventas.Cotiz.CotizEspSolicitudSQLr   r   r   r   r   r   r   r   r   r   r    r!   r"   	getLoggerr1   r   r   r   dictr2   r  r   r   r   r   listr-  r  r  r   rU  r?   r4   <module>r     sV   U T T      	 p   i ? 9   ( 
		4	5Sl%TN`
DD
 D
s D
UX D
]a D
LE
D E
# E
X[ E
`d E
No
T$Z o
Y\ o
379o
GJo
OSo
bY4 YvM
# M
s M
4 M
!$M
25M
:>M
^/
b"HV
r?   