
    iWZ                     r   S SK r S SKrS SKrS SKrS SKrS SKJr  S SKJr  S SK	J
r
  S SKJr  S SKJr  S SKJr  S SKJrJrJr  \" 5         \R(                  " S	5      rS
r1 SkrSr\ R2                  " S5      \ R2                  " S5      \ R2                  " S5      SS.rS\
S\S\S\S\S\S\S\4S jrS\
S\4S jrS\S\4S jr S\S\4S jr!S\S\4S  jr"S\
S\\   4S! jr#S\S\S\S\4S" jr$S#\RJ                  S$\SS4S% jr&S\S\S\S\4S& jr'S'\S\S\S(\S)\S\4S* jr(S\4S+ jr)S\
S'\S\S\S\S\4S, jr*g)-    N)Path)secure_filename)FileStorage)load_dotenv)Optional)datetime)crear_docs_headcrear_docs_detailobtener_siguiente_doc_linedocs_managementi    >   .doc.jpg.pdf.png.xls.docx.jpeg.xlsxzhttps://file.sycelephant.comFTP_HOSTFTP_USERFTP_PASSz/public_html/file/)hostuserpassword	base_pathfile_objorigenuser_id
created_bytitledescriptionruta_completareturnc                 F   Sn [         R                  SU SU 35        [        U 5      nUS   (       de  SUS   SS.U(       aU  [        R                  R                  U5      (       a0   [        R                  " U5        [         R                  S	U 35        $ $ $ [        U 5      nU(       db  SSSS.U(       aU  [        R                  R                  U5      (       a0   [        R                  " U5        [         R                  S	U 35        $ $ $ [        U5      n
U
S   (       de  SU
S   SS.U(       aU  [        R                  R                  U5      (       a0   [        R                  " U5        [         R                  S	U 35        $ $ $ [        XtU5      nUS   (       d^  UU(       aU  [        R                  R                  U5      (       a0   [        R                  " U5        [         R                  S	U 35        $ $ $ [        XU5      nUS   (       d^  UU(       aU  [        R                  R                  U5      (       a0   [        R                  " U5        [         R                  S	U 35        $ $ $ US   n[        XX[S   US   5      nUS   (       d^  UU(       aU  [        R                  R                  U5      (       a0   [        R                  " U5        [         R                  S	U 35        $ $ $ SSU S3UUS   US   US   US   US   U R                   S.S.n[         R                  SUS    35        UU(       aU  [        R                  R                  U5      (       a0   [        R                  " U5        [         R                  S	U 35        $ $ $ ! [         a.  n	[         R                  S
U S[        U	5       35         Sn	A	$ Sn	A	ff = f! [         a.  n	[         R                  S
U S[        U	5       35         Sn	A	$ Sn	A	ff = f! [         a.  n	[         R                  S
U S[        U	5       35         Sn	A	$ Sn	A	ff = f! [         a.  n	[         R                  S
U S[        U	5       35         Sn	A	$ Sn	A	ff = f! [         a.  n	[         R                  S
U S[        U	5       35         Sn	A	$ Sn	A	ff = f! [         a.  n	[         R                  S
U S[        U	5       35         Sn	A	$ Sn	A	ff = f! [         a.  n	[         R                  S
U S[        U	5       35         Sn	A	$ Sn	A	ff = f! [         a  n	S[        U	5       3n[         R#                  USS9  SSSUS .s Sn	A	U(       a  [        R                  R                  U5      (       ak   [        R                  " U5        [         R                  S	U 35        $ ! [         a.  n	[         R                  S
U S[        U	5       35         Sn	A	$ Sn	A	ff = f$ $ Sn	A	ff = f! U(       a  [        R                  R                  U5      (       ak   [        R                  " U5        [         R                  S	U 35        f ! [         a.  n	[         R                  S
U S[        U	5       35         Sn	A	f Sn	A	ff = ff f = f)!u<  
Función REUTILIZABLE para subir UN documento con validación completa
Puede usarse para: Formularios, Cotizaciones, Oportunidades, etc.

Args:
    file_obj (FileStorage): Objeto archivo de Flask
    origen (str): Módulo origen (ej: "Q_SpQ_FormsHead", "Q_SpQ_Quotations")
    user_id (int): ID del usuario
    created_by (str): Nombre completo del usuario
    title (str): Título del archivo
    description (str): Descripción del archivo
    ruta_completa (str): Ruta completa (ej: "Ventas/Formularios/1001-2/FormPEmx")

Returns:
    dict: Resultado de la operación
NzIniciando upload de documento: z para validFmessageVALIDATION_ERRORsuccessr&   codeArchivo temporal eliminado: %No se pudo eliminar archivo temporal : Error al crear archivo temporalTEMP_FILE_ERRORSECURITY_ERRORr)   docs_idremote_path	extensionTDocumento "" subido exitosamentedoc_line_iddownload_url	file_sizer1   r6   r7   r2   r8   	file_typeoriginal_namer)   r&   datazDocumento subido exitosamente: z%Error inesperado en upload_document: exc_info&Error interno al procesar el documentoINTERNAL_ERRORr)   r&   r*   technical_error)loggerinfovalidar_archivo_basicoospathexistsremovedebug	Exceptionwarningstrcrear_archivo_temporalvalidar_seguridad_archivosubir_archivo_ftpgestionar_docs_headcrear_registro_documentofilenameerror)r   r   r   r   r    r!   r"   	temp_pathvalidacion_resulteseguridad_resultupload_resultdocs_head_resultr1   docs_detail_resultresultado_final	error_msgs                    bC:\Users\victor.barrera\Documents\proyectos\elepV3\Elep\src\App\Utilities_module\DocsManagement.pyupload_documentr`   8   s   & IU^5eWF:,OP 38< ) ,Y7*T 	22^		)$;I;GH 39G +84	 <)B 	22^		)$;I;GH 39u 5Y?( +I6(p 	22^		)$;I;GH 39c *)MJY' ^ 	22^		)$;I;GH 39Y /v
K	*#T 	22^		)$;I;GH 39Q #9- 6K})Ek*
 "),%@ 	22^		)$;I;GH 399 $UG+@A"1-@ -n =,];.{;.{;!)!2!2
 	56H6W5XYZ 	22^		)$;I;GH 39  ^!FykQSTWXYTZS[\]]^9 ^!FykQSTWXYTZS[\]]^9 ^!FykQSTWXYTZS[\]]^9 ^!FykQSTWXYTZS[\]]^9 ^!FykQSTWXYTZS[\]]^9 ^!FykQSTWXYTZS[\]]^9 ^!FykQSTWXYTZS[\]]^!  
;CF8D	Y.?$(	
 	
 	22^		)$;I;GH ^!FykQSTWXYTZS[\]]^	 39
 	22^		)$;I;GH ^!FykQSTWXYTZS[\]]^	 39s>  8T0 (.NT0 .OT0 .P	T0 
.Q;T0 >.Q?/#T0 >.R:/AT0 ".S5
O$OO
P$PP	
Q$P<<Q
Q<$Q77Q<?
R7	$R22R7:
S2$S--S25
T-?$T((T-0
X:(W?"X#X .W
W:$W55W:?XX ,Z 4.Y#"Z #
Z-$ZZ ZZ c                 R    U (       a  U R                   (       d  SSS.$ [        U R                   5      n[        U5      R                  R	                  5       nU[
        ;  a  SSSR                  [
        5       3S.$ U R                  S[        R                  5        U R                  5       nU R                  S5        U[        :  a  [        S-  nSSUS	 S
3S.$ US:X  a  SSS.$ SUUUS.$ ! [         a0  n[        R                  S[        U5       35        SSS.s SnA$ SnAff = f)uc   
Validaciones básicas del archivo (tamaño, extensión, etc.)
REUTILIZABLE para cualquier módulo
Fu*   No se proporcionó ningún archivo válidor%   r&   u4   Tipo de archivo no permitido. Extensiones válidas: z, r      u2   El archivo excede el tamaño máximo permitido de z.1fMBu   El archivo está vacíoT)r%   rT   r3   r8   u   Error en validación básica: zError al validar el archivoN)rT   r   r   suffixlowerEXTENSIONES_PERMITIDASjoinseekrG   SEEK_ENDtell   TAMAÑO_MAXIMOrL   rD   rU   rN   )r   rT   r3   r8   
   tamaño_mbrX   s         r_   rF   rF      sC   
1
x00G  #8#4#45N))//1	 22QRVR[R[\rRsQtu  	a%MMO	a~%';7JOPZ[^O__ab 
 >4   ""	
 	
  
5c!fX>?4
 	

s6   C, AC, <AC, 
C, %C, ,
D&6%D!D&!D&rV   c                      [        U 5      nUS   (       d  U$ [        U 5      nUS   (       d  SSUS    3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)uL   
Validación de seguridad usando ClamAV
REUTILIZABLE para cualquier módulo
r%   cleanFz Archivo infectado o sospechoso: threatrb   TzArchivo segurou#   Error en validación de seguridad: z)Error al validar la seguridad del archivoN)validar_headers_archivoescanear_con_clamavrL   rD   rU   rN   )rV   header_resultclamav_resultrX   s       r_   rP   rP      s    

/	:W%   ,I6W%=mH>U=VW  '
 	

  
:3q6(CDB
 	

s#   > > > 
A8%A3-A83A8	file_pathc                 F    [        U S5       nUR                  S5      nSSS5        / SQnU H  nUWR                  5       ;   d  M  SSS.s  $    SS	S.$ ! , (       d  f       N;= f! [         a0  n[        R                  S
[        U5       35        SSS.s SnA$ SnAff = f)uO   
Validación básica de headers de archivo para detección rápida de amenazas
rbi   N)s!   X5O!P%@AP[4\PZX54(P^)7CC)7}$EICARs   <scripts   javascript:s	   vbscript:Fz%Archivo contiene patrones sospechososrb   Tu   Headers válidoszError al validar headers: z'Error al validar estructura del archivo)openreadrf   rL   rD   rU   rN   )ru   fheaderpatrones_sospechosospatronrX   s         r_   rq   rq      s    
)T"aVVD\F # 
 +F'"F  + )
 	
% #".  
1#a&:;@
 	

s?   A& A#A& A& A& 
A#A& &
B 0%BB B c                 f    [         R                  " SSU /SSSS9nUR                  S:X  a  [        R	                  SU  35        SSS	.$ UR
                  (       a  UR
                  R                  5       OS
n[        R                  SU 35        SUS	.$ ! [         R                   a     [        R                  SU  35        SSS	.s $ [         a    [        R                  S5        SSS	.s $ [         a<  n[        R                  S[        U5       35        SS[        U5       3S	.s SnA$ SnAff = f)z
Escanea archivo con ClamAV
clamscanz--no-summaryTd   )capture_outputtexttimeoutr   zClamAV: Archivo limpio - N)ro   rp   zAmenaza desconocidazClamAV: Amenaza detectada - FzClamAV timeout para archivo: zTimeout en escaneo de virusu3   ClamAV no está instalado o no se encuentra en PATHzSistema antivirus no disponiblezError ejecutando ClamAV: zError en escaneo: )
subprocessrun
returncoderD   rK   stdoutstriprM   TimeoutExpiredrU   FileNotFoundErrorrL   rN   )ru   resultthreat_inforX   s       r_   rr   rr   "  s=   (
3	
 !LL4YK@A 
 4:==&----/F[KNN9+GH% 
 $$ 
4YK@A3
 	
  
JK7
 	
  
0Q9:*3q6(3
 	

s1   AB 	A	B 1D0#D0+	D041D+%D0+D0c                     [        U R                  5      n[        U5      R                  n[        R
                  " US9u  p4[        R                  " US5       nU R                  S5        UR                  U R                  5       5        SSS5        [        R                  SU 35        U$ ! , (       d  f       N(= f! [         a+  n[        R                  S[        U5       35         SnAgSnAff = f)z,
Crea un archivo temporal desde FileStorage
)re   wbr   NzArchivo temporal creado: z Error creando archivo temporal: )r   rT   r   re   tempfilemkstemprG   fdopenri   writery   rD   rK   rL   rU   rN   )r   rT   r3   temp_fdrV   	temp_filerX   s          r_   rO   rO   T  s    "8#4#45N))	%--Y?YYw%MM!OOHMMO, & 	0<= &%  7Ax@As0   AB= 1B,
!B= ,
B:6B= =
C2!C--C2c                 z   Sn [        U5      nU(       d/  S[        [        R                  " 5       R	                  5       5       3n[
        S   UR                  SS5      -   nU SU 3n[         SU SU 3n[        R                  " [
        S   5      nUR                  [
        S   [
        S   5        [        X55        [        U S	5       nUR                  S
U 3U5        SSS5        [        R                  SU 35        [        R                  SU 35        SUUUUS.U(       a   UR!                  5         $ $ ! , (       d  f       N_= f!    $ = f! [        R"                   aT  n	S[%        U	5       3n
[        R'                  U
5        SSSU
S.s Sn	A	U(       a   UR!                  5         $ !    $ = f$ Sn	A	f[(         aT  n	S[%        U	5       3n
[        R'                  U
5        SSSU
S.s Sn	A	U(       a   UR!                  5         $ !    $ = f$ Sn	A	ff = f! U(       a   UR!                  5         f !    f = ff = f)uV   
Sube archivo al servidor FTP
🆕 CORREGIDA: URL de descarga correcta para navegador
Narchivo_r   \/r   r   r   rw   zSTOR z#Archivo subido exitosamente a FTP: u   URL pública accesible: T)r)   r2   r7   rT   ftp_pathzError de permisos FTP: Fz"Error de permisos al subir archivoFTP_PERMISSION_ERRORrB   zError subiendo archivo a FTP: z"Error al subir archivo al servidor	FTP_ERROR)r   intr   now	timestamp
FTP_CONFIGreplaceBASE_URLftplibFTPlogincrear_directorios_ftprx   
storbinaryrD   rE   quit
error_permrN   rU   rL   )rV   r    r"   conn_ftpnombre_archivoftp_directoryremote_file_path
public_urlarchivorX   r^   s              r_   rQ   rQ   j  sC   
 H=(/'HLLN,D,D,F(G'HIN #;/-2G2Gc2RR+_An-=> !z=/>2BC
 ::j01z&):j+AB 	h6 )T"g%(8'9 :GD # 	9:J9KLM.zl;< %&&(
:  G #"L3  
-c!fX6	Y;*(	
 	
$ 	   
4SVH=	Y;(	
 	
 	 
 	 s   CE 
D9 ?E 'E
9
EE 
EH%)F4HH F,,F04H)H*H+H 7HHHH H:!H21H:2H64H:ftp_conndirectory_pathc                      U R                  U5        [        R                  SU 35        g! [        R                   a     Of = fUR                  S5      R                  S5      nSnU H  nU(       d  M  USU-   -  n U R                  U5        M(  ! [        R                   ap     U R                  U5        [        R                  SU 35         Mi  ! [        R                   a+  nS[        U5      R                  5       ;  a  Ue SnA M  SnAff = ff = f   [        R                  SU 35        g! [         a(  n[        R                  S[        U5       35        UeSnAff = f)	z,
Crea directorios en FTP de forma recursiva
zDirectorio FTP existe: Nr    zDirectorio FTP creado: rI   z*Estructura de directorios FTP verificada: zError creando directorios FTP: )cwdrD   rK   r   r   r   splitmkdrN   rf   rE   rL   rU   )r   r   
path_partscurrent_pathpartrX   s         r_   r   r     sI   #	LL(LL2>2BCD   		
 $))#.44S9
DC$J&L	 \*$$   LL.LL#:<.!IJ((  s1v||~5 6   " 	@@PQR 6s1vh?@su   )- AD5 A;D5  BD5 D()CD5 D(DDD5 DDD5 5
E'?#E""E'c                      [        XU5      $ ! [         a1  n[        R                  S[	        U5       35        SSSS.s SnA$ SnAff = f)ul   
Crea un nuevo DocsHead (cada upload individual genera su propio grupo)
REUTILIZABLE para cualquier módulo
zError gestionando DocsHead: Fz1Error interno al gestionar registro de documentosDOCS_HEAD_ERRORr(   N)r	   rL   rD   rU   rN   )r   r   r   rX   s       r_   rR   rR     sO    
	
w
;; 
3CF8<=J%
 	

s    
A	&AA	A	r1   rutar:   c                      [        U 5      n[        XXX45      $ ! [         a1  n[        R	                  S[        U5       35        SSSS.s SnA$ SnAff = f)uA   
Crea registro en DocsDetail
REUTILIZABLE para cualquier módulo
z%Error creando registro de documento: Fz$Error interno al registrar documentoDOCS_DETAIL_ERRORr(   N)r   r
   rL   rD   rU   rN   )r1   r    r!   r   r:   doc_linerX   s          r_   rS   rS     s]    
-g6 !EXX 
<SVHEF='
 	

s    
A&A
AAc                     / n [         S   (       d  U R                  S5        [         S   (       d  U R                  S5        [         S   (       d  U R                  S5         [        R                  " SS/S	S
S9nUR                  S:w  a  U R                  S5         [        R                  " 5       n[        US5       nUR                  S5        SSS5        [        R                  " U5        [        U 5      S:H  U [        S-  [!        ["        5      [$        S.$ ! [
        [        R                  4 a    U R                  S5         Nf = f! , (       d  f       N= f! [         a    U R                  S5         Nf = f)u]   
Verifica que la configuración del módulo sea correcta
REUTILIZABLE para cualquier módulo
r   zFTP_HOST no configurador   zFTP_USER no configurador   zFTP_PASS no configurador   z	--versionT   )r   r   r   z ClamAV no responde correctamenteu(   ClamAV no está instalado o no accesiblewtestNz&No se pueden crear archivos temporalesrc   )configuracion_validaerroresu   tamaño_maximo_mbextensiones_permitidasbase_url)r   appendr   r   r   r   r   r   mktemprx   r   rG   rJ   rL   lenrl   listrg   r   )r   r   	temp_testrz   s       r_   verificar_configuracionr     s?   
 G f01f01j!01C[ 9$XYZ!NN=>
AOO%	)S!QGGFO "
		)
 !$G 1+{;"&'=">  z889 CABC "!  A?@As<   !9D !E <E	E +EE	
EE E87E8c                    Sn [         R                  SU SU 35        [        U 5      nUS   (       de  SUS   SS.U(       aU  [        R                  R                  U5      (       a0   [        R                  " U5        [         R                  S	U 35        $ $ $ [        U 5      nU(       db  SSSS.U(       aU  [        R                  R                  U5      (       a0   [        R                  " U5        [         R                  S	U 35        $ $ $ [        U5      nUS   (       de  SUS   SS.U(       aU  [        R                  R                  U5      (       a0   [        R                  " U5        [         R                  S	U 35        $ $ $ [        XRU5      n	U	S   (       d^  U	U(       aU  [        R                  R                  U5      (       a0   [        R                  " U5        [         R                  S	U 35        $ $ $ [        XX9S   US   5      n
U
S   (       d^  U
U(       aU  [        R                  R                  U5      (       a0   [        R                  " U5        [         R                  S	U 35        $ $ $ SSU S3UU
S   U	S   U	S   US   US   U R                  S.S.n[         R                  SU SU
S    35        UU(       aU  [        R                  R                  U5      (       a0   [        R                  " U5        [         R                  S	U 35        $ $ $ ! [         a.  n[         R                  S
U S[        U5       35         SnA$ SnAff = f! [         a.  n[         R                  S
U S[        U5       35         SnA$ SnAff = f! [         a.  n[         R                  S
U S[        U5       35         SnA$ SnAff = f! [         a.  n[         R                  S
U S[        U5       35         SnA$ SnAff = f! [         a.  n[         R                  S
U S[        U5       35         SnA$ SnAff = f! [         a.  n[         R                  S
U S[        U5       35         SnA$ SnAff = f! [         a  nS[        U5       3n[         R!                  USS9  SSSUS.s SnAU(       a  [        R                  R                  U5      (       ak   [        R                  " U5        [         R                  S	U 35        $ ! [         a.  n[         R                  S
U S[        U5       35         SnA$ SnAff = f$ $ SnAff = f! U(       a  [        R                  R                  U5      (       ak   [        R                  " U5        [         R                  S	U 35        f ! [         a.  n[         R                  S
U S[        U5       35         SnAf SnAff = ff f = f)u  
Sube un documento a un DocsHead existente (no crea nuevo DocsHead)

Args:
    file_obj (FileStorage): Objeto archivo de Flask
    docs_id (int): DocsID existente donde agregar el archivo
    title (str): Título del archivo
    description (str): Descripción del archivo
    ruta_completa (str): Ruta completa (ej: "Ventas/Formularios/1001-2/FormPEmx")

Returns:
    dict: Resultado de la operación
Nz&Subiendo documento a DocsID existente r-   r%   Fr&   r'   r(   r+   r,   r.   r/   r0   r)   r2   r3   Tr4   r5   r6   r7   r8   r9   r<   zDocumento subido a DocsID z6Error inesperado en upload_document_to_existing_docs: r>   r@   rA   rB   )rD   rE   rF   rG   rH   rI   rJ   rK   rL   rM   rN   rO   rP   rQ   rS   rT   rU   )r   r1   r    r!   r"   rV   rW   rX   rY   rZ   r\   r]   r^   s                r_    upload_document_to_existing_docsr   .  s~     IN^<WIRwOP 38< ) ,Y7*F 	22^		)$;I;GH 39y +84	 <)t 	22^		)$;I;GH 39g 5Y?( +I6(b 	22^		)$;I;GH 39U *)MJY' P 	22^		)$;I;GH 39K 6K})Ek*
 "),%@ 	22^		)$;I;GH 399 $UG+@A"1-@ -n =,];.{;.{;!)!2!2
 	0	<N}<];^_` 	22^		)$;I;GH 39  ^!FykQSTWXYTZS[\]]^9 ^!FykQSTWXYTZS[\]]^9 ^!FykQSTWXYTZS[\]]^9 ^!FykQSTWXYTZS[\]]^9 ^!FykQSTWXYTZS[\]]^9 ^!FykQSTWXYTZS[\]]^!  
LSQRVHU	Y.?$(	
 	
 	22^		)$;I;GH ^!FykQSTWXYTZS[\]]^	 39
 	22^		)$;I;GH ^!FykQSTWXYTZS[\]]^	 39s   8Q? (.LQ? .MQ? .NQ? 
.O;Q? .P	6A
Q? ,.Q
M'$MM
N"$NN
O$OO
P$PP	
Q$P<<Q
Q<$Q77Q<?
U	(U1U2U ".T
U	$UU	UU ,W/.V21W/2
W*<$W% W/%W**W/)+rG   r   r   r   loggingpathlibr   werkzeug.utilsr   werkzeug.datastructuresr   dotenvr   typingr   r   )Consultas_SQL.Utilities.DocsManagementSQLr	   r
   r   	getLoggerrD   rl   rg   r   getenvr   rN   r   dictr`   rF   rP   rq   rr   rO   rQ   r   r   rR   rS   r   r        r_   <module>r      s5   
      * /      
		,	- ! ]  * IIj!IIj!		*%%	
j^k j^3 j^ j^RU j^j^,/j^@Cj^HLj^`6
[ 6
T 6
p
 
 
>!
s !
t !
F,
3 ,
4 ,
d[ Xc] ,D DS D D DL'FJJ ' ' 'Z
 
c 
s 
t 
 
c 
# 
C 
!
.1
6:
2& &P`^{ `^S `^QT `^14`^EH`^MQ`^r   