U
    `i"                     @   s   d dl mZmZmZmZ ddlmZ ddlmZ d dl	Z	ede
Zejddgd	ed
ddZejddgd	dd Zejddgd	ed
ddZejddgd	dd Zejdddgd	dd Zejddgd	dd ZdS )    )	Blueprintjsonifyrequestsession   )quote_reception_services)OpportunityAndCostingDTONZquote_receptionz/costing/<int:costing_num>GET)methods)costing_numc              
   C   sx   z<t j| }|r t| W S tdd|  didfW S W n6 tk
rr } ztddidf W Y S d}~X Y nX dS )u   
    Controlador para obtener datos unificados de la cotización (Costeo y CRM).
    Ruta final: /api/reception/costing/<int:costing_num>
    erroru   Cotización con número z no encontradai  (   Ocurrió un error interno en el servidor  N)r   Quote_Reception_Serviceget_unified_data_by_costing_numr   to_dict	Exception)r   data_dtoe r   lC:\Users\victor.barrera\Documents\proyectos\elepV3\Elep\src\App\api\controller\quote_reception_controller.py get_reception_costing_controller	   s    r   z/taxesc               
   C   sP   zt j } t| W S  tk
rJ } ztddidf W Y S d}~X Y nX dS )z^
    Controlador para obtener la lista de impuestos.
    Ruta final: /api/reception/taxes
    r   r   r   N)r   r   	get_taxesr   r   )taxesr   r   r   r   get_taxes_controller   s
    

r   z"/costing-details/<int:costing_num>c              
   C   s`   zt j| }t|W S  tk
rZ } z&td|  tddidf W Y S d}~X Y nX dS )uz   
    Controlador para obtener las líneas de costeo.
    Ruta final: /api/reception/costing-details/<int:costing_num>
    z9Error en el controlador quote_reception/costing-details: r   r   r   N)r   r   get_costing_detailsr   r   print)r   detailsr   r   r   r   get_costing_details_controller+   s    
r   z/create-quotationPOSTc               
   C   s   z>t  } tj| }|dr.t|dfW S t|dfW S W nF tk
r } z(td|  tddddf W Y S d	}~X Y nX d	S )
ug   
    Controlador para crear una nueva cotización.
    Ruta final: /api/reception/create-quotation
    success     z*Error en el controlador create-quotation: Fr   r    r   r   N)	r   get_jsonr   r   create_quotationgetr   r   r   )dataresultr   r   r   r   create_quotation_controller8   s    
r)   z/preview-quotationOPTIONSc               
   C   s  t jdkrHtddi} | jdd | jdd | jdd	 | d
fS z8t  }|rft|dkrtd d}|r|dpt jd}nt jd}|rddl	}ddl
}ddlm} |j|jdddd}|j|d| d}td|  |j|rt|ddd}||}W 5 Q R X td tdt|   z|| td W n2 tk
r }	 ztd|	  W 5 d}	~	X Y nX n0td |  d!| d"| d#}
|
d$d%d&ifW S nd'}
|
d$d%d&ifW S |sd(}
|
d$d%d&ifW S |dpt jd}td) td*|  td+t|   tj|}|rltd,t| d- |d
d%d&ifW S d.}
|
d/d%d&ifW S W nn tk
r }	 zNtd0|	  ddl}|  d1t|	 d2|  d3}
|
d/d%d&if W Y S d}	~	X Y nX dS )4u   
    Controlador para generar vista previa de la cotización antes de crearla.
    Ruta final: /api/reception/preview-quotation
    r*   statusokzAccess-Control-Allow-Origin*zAccess-Control-Allow-HeaderszContent-Type,X-Auth-TokenzAccess-Control-Allow-Methodsr         uO   ⚠️ Datos incompletos recibidos, intentando cargar desde archivo temporal...NtokenzX-Auth-Tokenr   )current_appstaticpdfVentasCotiz
temp_data_.jsonu   🔍 Buscando archivo: rutf-8encodingu)   ✅ Datos cargados desde archivo temporalu   📦 Datos cargados: u"   🗑️ Archivo temporal eliminadou-   ⚠️ No se pudo eliminar archivo temporal: u$   ❌ Archivo temporal no encontrado: u   
                    <!DOCTYPE html>
                    <html>
                    <body>
                        <h1>❌ Error: No se encontraron datos de cotización</h1>
                        <p>Token: z1</p>
                        <p>Archivo buscado: zQ</p>
                    </body>
                    </html>
                    r"   zContent-Typeztext/html; charset=utf-8u   
                <!DOCTYPE html>
                <html>
                <body>
                    <h1>❌ Error: No se recibió token</h1>
                </body>
                </html>
                u   
            <!DOCTYPE html>
            <html>
            <body>
                <h1>❌ Error: No se pudieron cargar los datos</h1>
            </body>
            </html>
            u,   📋 Generando vista previa para cotizaciónu   🎫 Token recibido: u   📦 Datos recibidos: u   ✅ HTML generado: z caracteresu   
            <!DOCTYPE html>
            <html>
            <body>
                <h1>❌ No se pudo generar la vista previa</h1>
                <p>El servicio no retornó contenido HTML</p>
            </body>
            </html>
            r   u    ❌ Error en preview-quotation: u  
        <!DOCTYPE html>
        <html>
        <head>
            <title>Error</title>
            <style>
                body {
                    font-family: Arial, sans-serif;
                    padding: 40px;
                    background-color: #f5f5f5;
                }
                .error {
                    background-color: #fee;
                    border: 2px solid #f00;
                    padding: 20px;
                    border-radius: 8px;
                    max-width: 800px;
                    margin: 0 auto;
                }
                pre {
                    background-color: #333;
                    color: #fff;
                    padding: 15px;
                    overflow-x: auto;
                    border-radius: 4px;
                }
            </style>
        </head>
        <body>
            <div class="error">
                <h1>❌ Error al generar vista previa</h1>
                <p><strong>Mensaje:</strong> z</p>
                <pre>zB</pre>
            </div>
        </body>
        </html>
        )r   methodr   headersaddr$   lenr   r&   osjsonflaskr1   pathjoin	root_pathexistsopenloadlistkeysremover   r   r   generate_quotation_preview	traceback	print_excstr
format_exc)responser'   r0   r@   rA   r1   
output_dirtemp_data_filefr   
error_htmlpreview_htmlrM   r   r   r   preview_quotation_controllerM   s~    

"
	 %rW   z/generate-pdf/<quote_id>c           W      C   s  z~ddl }ddl}ddl}ddl}ddl}ddl}ddlm}m} ddl	m
}	 ddlm}
 ddlm} ddlm} ddlm} td	 td
 td	 | }td t|j|ddd d}ztd}td}|r^ddlm} | R}| >}|d| | }|r|d s2|d| | }W 5 Q R X W 5 Q R X |r^|d r^|d }|sn|rn|}td|pzd  W n2 tk
r } ztd|  W 5 d}~X Y nX t| }|jd}| d}t| }|jd}| d}|j}|j !|dddd}|j"|dd ddl}|j !|d| d}t#|d d!d"}|j$||ddd# W 5 Q R X td$|  |d%| %d&d }td'|  zf| H}| 4}|d(| | }|d sd)n
|d d) }W 5 Q R X W 5 Q R X td*|  W n: tk
r@ } ztd+t|  d)}W 5 d}~X Y nX | d&| } td,|   t|}!| }"td-|!  td.|"  d/| d0| d1| d2}#|j !||#}$td3| d0| d2 |j !|d4ddd5}%td6|  td7|%  td8|j &|%  |j &|%sBd9|% }&td:|&  t'd|&d;d<fW S td=|%  td> |(d?}'|'std@ dAdB|j )dCg}(|(D ],})|j &|)r|)}'tdD|)   qq|'r|j &|'sdE}&td:|&  t'd|&d;d<fW S tdF|'  tdG|  tdH|$  tdI|  tdJ |j*|'|%||$|g|j+|j+dd!dK|j ,|%dL}*z|*j-dMdN\}+},|*j.}-|+rtdO|+  |,rtdP|,  |-dkr|,r|,ndQ}&tdR|-  t'ddS|& d;d<fW W S |j &|$stdT|$  t'ddUd;d<fW W S tdV|$  tdW|j /|$ dX W n< |j0k
rt   |*1  tdY t'ddZd;d<f Y W S X td[ td\|! d|" d |2d]}.|2d^}/|2d_}0d`dda|!|"g}1tdbdc!|1  z|3|.}2|24|/|0 tdd de}3|25|3 tdf|3  d}4|1D ]H}5z,|25|5 tdg|5  |5dkrHd}4W q |j6k
r`   |4sdh|5 di|27  d|5 }&tdj|&  |28  t'd|&|5dkd<f Y   W W S tdl|5  z&|29|5 |25|5 tdm|5  W np tk
rZ } zPdn|5 dot| }&tdj|&  |28  t'd|&d;d<f W Y  Y   W W S d}~X Y nX Y nX q|27 }6tdp tdq|6  |28  W nX tk
r } z8drt| }&td:|&  t'd|&d;d<f W Y W S d}~X Y nX tds dt|! d|" d}7du|! d|" d}8t#|$dv}|	|d/| d1| d2dwdx}9d/| d0| }:|
|9|:|7|8};|;dy 
s tdz|;d{   td| d}}<d~}=t#|$dvj}>|	|>d/| d1| d2dwdx}?|
|?|:|<|=};|;dy 	st'd|;d{ d;dfW  5 Q R  W  5 Q R  W S W 5 Q R X |;d }@td|@  W 5 Q R X td z:t:|dd}At:|dd}Bt:|dd}Ct:|dd}D|A|B }E|C|B }Fi }Gz| x}| d}|d|d | }H|H
r|Hd |Hd) t:|Hd d d}Gn|dd|dddd}GW 5 Q R X W 5 Q R X W nN tk
rV } z.td|  |dd|dddd}GW 5 d}~X Y nX td |dd}I|I}Jzj| F}| 2}|d|I | }K|Kr|Kd r|Kd }JW 5 Q R X W 5 Q R X td|I dc|J  W n2 tk
r } ztd|  W 5 d}~X Y nX t;j<=|d%}L|Ld}M|Ld}N|Ld}Otd|N  td|M  td|O  | ||d%|dd|dd|dd|dd|dd|dd|dd|dd|dd|Ld|A|B|C|D|E|F|Gd |Gd |Gd |J|I|dd)t>|dg |@|? @dd}Pd|$d| d0| d2ddg}Qdg}R|rh|RA| td|  ntd |Mr|M|Rkr|RA|M td|M  n|Mrtd|M  ntd td|R  |dd| d| d|dd d|P|Q|Rdgdd}S|Sd |Sd{ |Sd d d}T|Sd rPtd td|Sd d   td|  ntd|Sd{   W n\ tk
r } z<tdt|  ddlB}U|UC  ddt| dd}TW 5 d}~X Y nX ddlD}V|VEd) z|j &|$rDtd|$  td|j &|$  tdtF|G|$jHdd   |I|$ td|$  ntd|$  W n~ tJk
r } ztd|  td˃ W 5 d}~X Y nF tk
r } z&tdt|  ddlB}U|UC  W 5 d}~X Y nX z@|j !|d| d}|j &|r|I| td|  W n6 tk
rJ } ztdt|  W 5 d}~X Y nX td	 tdσ td	 t'd|@|8|ddќ|TdfW S  tk
r } z<td|  ddlB}U|UC  t'dt|d;d<f W Y S d}~X Y nX dS )u   
    Genera el PDF de la cotización, lo sube a FTP en estructura de carpetas y envía por email
    Ruta final: /api/reception/generate-pdf/<quote_id>
    r   N)r1   r   )FileStorage)subir_archivo_ftp_desde_request)enviar_correo_universal)datetime)get_connectionzP================================================================================u+   🚀 INICIANDO GENERACIÓN DE PDF CON EMAILu$   🧠 Datos recibidos para genera PDFr   F)indentensure_asciiuser_idemailz+SELECT Email FROM Profiles WHERE UserID = ?z
                                SELECT P.Email
                                FROM Users U
                                JOIN Profiles P ON P.ProfileID = U.ProfileID
                                WHERE U.UserID = ?
                            u"   📧 Email del creador detectado: zNo disponibleu1   ⚠️ No se pudo resolver el email del creador: /z /api/reception/preview-quotationr2   r3   r4   r5   T)exist_okr6   r7   wr9   r:   )r^   r]   u!   💾 Datos temporales guardados: 	CostingID-u/   
📊 Obteniendo versión de cotización para: zm
                        SELECT MAX(Version) FROM Q_QuotationHead WHERE QuotationNum = ?
                    r/   u"   📊 Versión calculada desde BD: u5   ⚠️ Error al obtener versión, usando versión 1: u   ✅ QuoteID construido: u   📁 Carpeta base: u   📁 Carpeta versión: cotizacion__V_z.pdfu    📄 Nombre del PDF: cotizacion_puppeteer_pdfzPreviewCotizacion.jsu   📂 Base dir: u   📄 Script path: u   📄 Script exists: z&Script de Puppeteer no encontrado en: u   ❌ r#   r   u   ✅ Script encontrado: u   
🔍 Buscando Node.js...nodeuF   ⚠️ Node.js no encontrado con shutil.which, buscando manualmente...z C:\Program Files\nodejs\node.exez&C:\Program Files (x86)\nodejs\node.exez~\AppData\Roaming\npm\node.exeu     ✅ Encontrado: z?Node.js no encontrado. Instala Node.js desde https://nodejs.orgu   
✅ Usando Node.js desde: u   
🌐 URL de vista previa: u   💾 Ruta de salida: u   🎫 Token: u   
🚀 Ejecutando Puppeteer...ignore)stdoutstderrtextr;   errorscwdZ   )timeoutu   
📋 Puppeteer stdout:
u   
⚠️ Puppeteer stderr:
z Error desconocido al generar PDFu"   
❌ Puppeteer falló con código zError al generar PDF: u   ❌ PDF no generado en: z$El PDF no fue generado correctamenteu   ✅ PDF generado exitosamente: u   📦 Tamaño del archivo: z bytesu1   ❌ Timeout: Puppeteer tardó más de 90 segundosu0   Timeout: La generación del PDF tardó demasiadou=   
🗂️ Verificando/Creando estructura de carpetas en FTP...u1   📊 Estructura a crear: /Cotizaciones_Generales/FTP_HOSTFTP_USERFTP_PASSfileCotizaciones_Generalesu!   📁 Carpetas a crear/verificar: z -> u   ✅ Conectado a FTPz$/domains/sycelephant.com/public_htmlu   📂 Ruta inicial: u     ✅ Carpeta existente: zError: La carpeta requerida 'z&' no existe en el servidor FTP. Ruta: u     ❌ )r    r   carpeta_faltanteu     📁 Creando carpeta: u     ✅ Carpeta creada: zError al crear carpeta 'z': u=   ✅ Estructura de carpetas FTP verificada/creada exitosamenteu   📂 Ruta final en FTP: zError al trabajar con FTP: u   
📤 Subiendo PDF a FTP...zH/domains/sycelephant.com/public_html/file/Ventas/Cotizaciones_Generales/z/Ventas/Cotizaciones_Generales/rbQuotationPDF)streamfilenamenameexitou   ❌ Error al subir a FTP: mensajeuC   ⚠️ Intentando método alternativo sin estructura de carpetas...z1/domains/sycelephant.com/public_html/file/Ventas/z/Ventas/r"   url_webu   ✅ PDF subido exitosamente: u#   
📧 Preparando envío de email...	SalePriceAmountTotalAmountDiscountPercentz
                            SELECT TaxCode, FrontES, TaxAmount 
                            FROM Q_TaxRate 
                            WHERE TaxCode = ?
                        TaxCoded   )codigonombre
porcentajezN/Au+   ⚠️ Error al obtener info del impuesto: u-   
👤 Obteniendo información del vendedor...CurrencyCodeUSDzk
                            SELECT FrontES FROM Q_Currency WHERE CurrencyCode = ?
                        u   💱 Moneda para email: u,   ⚠️ No se pudo obtener nombre de moneda: r   telefonou   ✅ Vendedor encontrado: u   ✅ Email vendedor: u   ✅ Teléfono vendedor: CaseCostCRM_ContactNameClienteCRM_ContactTypeCRM_OpportunityNumberCRM_ContactEmailCRM_ContactNumberCRM_ContactCityCRM_ContactStateCRM_ContactCountryr   r   OvercostFactorQuotationLinesz%d/%m/%Y %H:%M)quotation_idversion
costing_idcaso_costeocliente_nombretipo_contactooportunidad_crmcliente_emailcliente_telefonocliente_ciudadcliente_estadocliente_paisvendedor_asignadoprecio_listaprecio_ofertaprecio_totaldescuento_porcentajemonto_descuentomonto_impuestoimpuesto_codigoimpuesto_nombreimpuesto_porcentajemonedamoneda_codigofactor_sobrecostototal_lineaspdf_urlfecha_generacionlocalCotizacion_zapplication/pdf)tiporutar   mimetypezjesuscadena27@hotmail.comu0   ✅ Email del creador agregado a destinatarios: u6   ⚠️ No se agregó email del creador (no disponible)u1   ✅ Email del vendedor agregado a destinatarios: u0   ℹ️ Email del vendedor ya está en la lista: u7   ⚠️ No se agregó email del vendedor (no disponible)u   📧 Destinatarios TO finales: z0Emails/Ventas/Cotiz/RecepcionCotizacionMail.htmlu   📋 Nueva Cotización z - Vz - i  zjescad27@gmail.com)TOCC)template_pathasuntomail_list_idtemplate_dataarchivos_adjuntosdestinatarios_adicionalesr    destinatariostotal_destinatarios)email_enviadoemail_mensajeemail_destinatariosu   ✅ Email enviado correctamentez   Destinatarios: u.   ⚠️ Advertencia: No se pudo enviar email - u   ❌ Error al enviar email: zError al enviar email: u   🔍 Intentando eliminar: u   🔍 Archivo existe: u   🔍 Permisos: u    ✅ Archivo temporal eliminado: u   ⚠️ Archivo no existe: u#   ❌ Error de permisos al eliminar: u;   💡 El archivo podría estar siendo usado por otro procesou(   ❌ Error al eliminar archivo temporal: u)   🗑️ Archivo temporal JSON eliminado: u2   ⚠️ No se pudo eliminar archivo temporal JSON: u#   ✅ PROCESO COMPLETADO EXITOSAMENTEz5PDF generado, subido y enviado por email exitosamente)r    r   pdf_ruta_ftpr   messager.   u   
❌ ERROR CRÍTICO: )Kr@   
subprocessuuidshutilftplibrA   rB   r1   r   werkzeug.datastructuresrX   App.Subir_ArchivorY   #App.Utilities_module.MailManagementrZ   r[   Consultas_SQL.conexionr\   r   r$   dumpsr   r&   cursorexecutefetchoner   rO   uuid4host_urlrstriprE   rC   rD   makedirsrG   dumpsplitrF   r   which
expanduserPopenPIPEdirnamecommunicate
returncodegetsizeTimeoutExpiredkillgetenvFTPloginrp   
error_permpwdquitmkdfloatr   r   get_seller_infor?   nowstrftimeappendrM   rN   timesleepoctstatst_moderK   PermissionError)Wquote_idr@   r   r   r   r   rA   r1   r   rX   rY   rZ   r[   r\   r'   
user_emailr_   session_emailconnr   rowr   r0   base_urlpreview_urlbase_dirrR   rS   rT   r   version_resultr   quote_id_correctocosting_num_basequote_id_folderoutput_filenameoutput_pathscript_path	error_msg	node_pathpossible_pathsrC   processrl   rm   return_codehost_ftpusuario_ftp   contraseña_ftpcarpetas_estructuraftpcurrent_pathpuede_crearcarpetaruta_final_ftpruta_ftp_completacarpeta_relativapdf_fileitemresultado_ftpruta_ftp_simplecarpeta_simplef2	pdf_file2r   r   r   r   r   r   r   impuesto_infotax_rowr   moneda_nombremoneda_resultvendedor_infovendedor_emailvendedor_nombrevendedor_telefonor   r   destinatarios_toresultado_email
email_inforM   r   r   r   r   !generate_quotation_pdf_controller   s$   


 


.    

















>*

:





 












&	




"

$	r)  )rB   r   r   r   r   servicesr   Z!services.quote_reception_servicesr   rA   __name__routerrouteintr   r   r   r)   rW   r)  r   r   r   r   <module>   s"   



 