o
    Xh                    @   s  d dl mZmZmZmZmZmZ d dlmZ d dl	m
Z
 d dlmZ d dlmZmZ d dlZd dlZd dlZd dlmZ d dlZd dlZd dlmZmZmZmZ d dlZd	Zejed
d ejej de!ej"#ede$ gd e%e&Z'ee&Z(dZ)dZ*dZ+dZ,dZ-dZ.de, de- de) de* de+ de./dd de(j0d< de(j0d< d e(j0d!< de(j0d"< ee( e
e(Z1G d#d$ d$e1j2Z3G d%d& d&e1j2Z4e(j5d'd(gd)d*d+ Z6G d,d- d-Z7d.d/ Z8e7 Z9e(5dd0d1 Z:e(5d2d3d4 Z;e(5d5d6d7 Z<e(5d8d9d: Z=e(5d;d<d= Z>e(j5d>d(gd)d?d@ Z?e(j5d>dAgd)dBdC Z@e(j5dDdEgd)dFdG ZAe(j5dDdHgd)dIdJ ZBe(j5dKd(gd)dLdM ZCe(j5dNd(gd)dOdP ZDe(j5dQdAgd)dRdS ZEdTdU ZFdVdW ZGdXdY ZHe(j5dZd(gd)d[d\ ZIe(j5d]d(gd)d^d_ ZJe(j5d`d(gd)dadb ZKe(j5dcdAgd)ddde ZLe(j5dfdAgd)dgdh ZMe(j5didAgd)djdk ZNe(j5dld(gd)dmdn ZOe(j5dod(gd)dpdq ZPe(j5drdAgd)dsdt ZQe(j5dud(gd)dvdw ZRe(j5dxd(gd)dydz ZSe(j5d{d(gd)d|d} ZTe(Ud~dd ZVe(Uddd ZWe(UeXdd ZYdd ZZe&dkr?e([  eZ  W d   n	1 s:w   Y  e&dkre\d e\d e\d e\d e']d z'e([  e1j^_ed e']d e8  W d   n	1 szw   Y  W n eXy Z` ze'adebe`  W Y dZ`[`ndZ`[`ww e\d e\d e\d e\d e\d e\d e\d e\d e(jcddd
d
d e(ZddS )    )Flaskrequestjsonify	send_filerender_templatesend_from_directory)CORS)
SQLAlchemy)text)datetime	timedeltaN)Path)DictListOptionalAnyz#/var/www/html/TransmisionesMig/logsT)exist_okz4%(asctime)s - %(name)s - %(levelname)s - %(message)szreporte_mensual.log)levelformathandlers	localhost1433TRANSMISIONESMIGsazSistemas123*/zODBC Driver 17 for SQL Serverzmssql+pyodbc://:@/z?driver= +z'&TrustServerCertificate=yes&Encrypt=yesSQLALCHEMY_DATABASE_URIFSQLALCHEMY_TRACK_MODIFICATIONSz8K8m2#D9v$L4x@R7n*W5q&F1s!P6j%T3y^B8e@N7k$H4m*V9r&L2x#Q5w
SECRET_KEYDEBUGc                   @   s   e Zd ZdZejejddZejedddZ	ejedddZ
ejeddddZeedZeed	Zeed
ZejejddZejejejdZejejejejdZejddddZdd ZdS )EmpresaClienteEmpresas_ClientesTprimary_key   Fnullable   )uniquer)   2     default)r/   onupdateControlReportesempresa_clientedynamic)backreflazyc                 C   sN   | j | j| j| j| j| j| j| j| jr| j	 nd | j
r#| j
	 d
S d d
S )N)
idrazon_socialnombre_comercialnitemailtelefono	direccionactivofecha_creacionfecha_modificacion)IDRazonSocialNombreComercialNITEmailTelefono	DireccionActivoFechaCreacion	isoformatFechaModificacionself rM   %/var/www/html/TransmisionesMig/app.pyto_dictJ   s   
zEmpresaCliente.to_dictN)__name__
__module____qualname____tablename__dbColumnIntegerr@   StringrA   rB   rC   rD   rE   rF   BooleanrG   DateTimer   utcnowrH   rJ   relationshipreportesrO   rM   rM   rM   rN   r#   9   s    r#   c                   @   s>  e Zd ZdZejejddZejedddZ	ejeje
dddZejejdejdZejejdd	Zeed
Zejejdd	Zejejdd	Zejedddd	Zejedddd	ZeejZeejZeejZejejdd	ZejejddZejedddZejddddfZ dd Z!dS )r1   Control_ReportesTr%      Fr(   zEmpresas_Clientes.ID)r)   r/   r.   r-   r            r,   Periodo	ClienteID_periodo_cliente_uc)namec              	   C   s  d }| j r | j j| j j| j j| j j| j j| j j| j j| j jd}i d| jd| j	d| j
d|d| jr9| j nd dt| jpAdd	t| jpIdd
t| jpQddt| jpYdd| jd| jredndd| jd| jrut| jnd d| jrt| jnd dt| jd| jr| j nd d| j| jrdnd|r|d  d|d  dnd|r|d nd |r|d nd |r|d dS d dS )N)r6   r7   r8   r9   r:   r;   r<   r=   r6   periodo
cliente_idclientefecha_enviototal_documentosr   documentos_exitososvalor_total
tasa_exitoobservacionesstatus	completedpendingcontenido_completodetalle_facturasdetalle_gastos	facturadofecha_facturacionnumero_factura	Facturado	Pendienter8    (r9   )Cliente no encontrador7   )estado_facturacioncliente_info_resumidacliente_razon_socialcliente_nombre_comercialcliente_nit)r2   r@   rA   rB   rC   rD   rE   rF   rG   rb   rc   
FechaEnviorI   intTotalDocumentosDocumentosExitososfloat
ValorTotal	TasaExitoObservacionesEnviadoContenidoCompletoDetalleFacturasjsonloadsDetalleGastosboolrx   FechaFacturacionNumeroFactura)rL   cliente_inforM   rM   rN   rO   r   sl   	


zControlReportes.to_dictN)"rP   rQ   rR   rS   rT   rU   rV   r@   rW   rb   
ForeignKeyrc   rY   r   rZ   r   rX   r   r   r   r   Numericr   r   Textr   r   r   rx   r   r   UniqueConstraint__table_args__rO   rM   rM   rM   rN   r1   Y   s(    r1   z/api/facturacion-por-clienteGET)methodsc               
   C   sj  zt jdt j} t jd}g }| r9|r-|  dt|d }|t	j
|k n|t	j
|  d tjt	ttt	jtjkt	jdk}|rZ|D ]}||}qR|t	j
  }i }|D ]p\}}	|	j}
|
|vr|	j|	j|	j|	j|	j|	j|	jdg dd	dd	d
||
< ||
 d |j
|j|jt |j!pdt |j"pd|j#r|j#$ ndd ||
 d  |jpd7  < ||
 d  t |j!pd7  < ||
 d  d7  < qh|% D ]}|d dkrt&dd |d D }t'||d  d|d< qt(d| |t)|t*|% dW S  t+y4 } zt,-dt|  t(dt|ddfW  Y d}~S d}~ww )uI   Obtiene resumen de facturación agrupado por cliente - útil para carterayearmonth-r`   -%T)r6   r7   r8   r9   r:   r;   r=   r           )rh   r\   rj   total_valorperiodos_reportadostasa_exito_promedior\   N)rf   rj   rk   rl   rm   ri   rj   r   r      c                 s   s    | ]}|d  V  qdS )rm   NrM   ).0rrM   rM   rN   	<genexpr>   s    z.get_facturacion_por_cliente.<locals>.<genexpr>r   )successr   r   total_clientesclientes_facturacionu+   Error obteniendo facturación por cliente: Fr   errorr-   ).r   argsgetr   nowr   strzfillappendr1   rb   likerT   sessionqueryr#   joinrc   r@   filterr   order_bydescallrA   rB   rC   rD   rE   rG   r   r   r   r   r   r   rI   valuessumroundr   lenlist	Exceptionloggerr   )r   r   filtersperiod_filterr   filter_conditionr\   r   reporterh   cliente_keycliente_data
tasa_totalerM   rM   rN   get_facturacion_por_cliente   s   	



r   c                   @   sR  e Zd ZdZdd Zd!dededeee	f fdd	Z
deee	f fd
dZdeee	f deee	f deee	f fddZdededededeee	f deee	f deee	f defddZdededeee	f dedeee	f deee	f defddZdeeee	f  fddZdedeeee	f  fddZdedeeee	f  fdd ZdS )"ReportManageruB   Maneja la generación y gestión de reportes mensuales por clientec                 C   s   d S NrM   rK   rM   rM   rN   __init__   s   zReportManager.__init__Nrg   target_datereturnc                 C   s  |du rt  }t |j|jdtdd }|d}t |j|jd}t |j|jt|j|jd ddd}tj	
|}|sGdd| d	|d
S td|j d| d| d| d	 zctj	j||dd }|rvdd|j d| |d
W S | |||}	| |||}
| |	|
}| ||||||	|
}| |||||	|
}td|j d|  dd|j d| || ||dW S  ty } ztd| dt|  ddt| |d
W  Y d}~S d}~ww )u5   Genera el reporte mensual para un cliente específicoNr   )daysz%Y-%m   ;   FzCliente con ID  no encontrado)r   messageperiodzGenerando reporte para cliente u    - período rz    - r{   Trb   rc   r   z%Ya existe un reporte para el cliente u    en el período z+Reporte generado exitosamente para cliente z#Reporte generado exitosamente para )r   r   r   rh   	report_id
statisticsz-Error generando reporte mensual para cliente : Error generando reporte: )r   r   r   r   r   strftimecalendar
monthranger#   r   r   r   inforA   r1   	filter_byfirst!_get_invoice_statistics_by_client!_get_expense_statistics_by_client_combine_statistics_generate_report_content_save_reportrO   r   r   r   )rL   rg   r   todayr   
start_dateend_daterh   existing_reportinvoice_statsexpense_statscombined_statsreport_contentr   r   rM   rM   rN   generate_monthly_report   sX   
&
&	z%ReportManager.generate_monthly_reportc              
   C   s   dddddddddd	S )u   Retorna estadísticas vacíasr   r   )	rj   rk   documentos_recibidosdocumentos_aceptadosdocumentos_rechazadostotal_subtotal	total_ivar   rm   rM   rK   rM   rM   rN   _empty_stats>  s   zReportManager._empty_statsr   r   c                 C   s\   i }|  D ]}|| ||  ||< q|d }|d }t|dkr&|| d ndd|d< |S )u.   Combina las estadísticas de facturas y gastosrj   rk   r   d   r`   rm   )keysr   )rL   r   r   combinedkeytotalexitososrM   rM   rN   r   L  s   "z!ReportManager._combine_statisticsr   r   r   rh   r   c                 C   sT  g d}||j d  }	|j}
g }|d |d |dt d  |d|	 d|
  |d	 |d
 |d |d |d |d |d	 |d |d |d|j  |d|j  |d|j  |j	r|d|j	  |j
r|d|j
  |jr|d|j  |d	 |d |d	 |d |d |d|j  |d|d d|d  |d dkr|d|d d |d |d! d |d"|d# d$d% |d&|d' d( n
|d)|j d* |d	 |d dkrx|d+ |d, |d	 |d- |d.|d d |d/|d! d |d0|d |d!  d |d	 |d1 |d2|d# d$d% |d3d4|d#  d$d% |d	 |d5 |d6|d7 d( |d8|d9 d( |d:|d' d( |d	 |d; |d< |d	 |d dkr|d dkr|d! |d  d4 nd}|d= |d.|d d |d>|d! dd?|d$d@ |dA|d |d!  dd?d4| d$d@ |dB|d' d( |d	 |d dkrx|d dkr0|d! |d  d4 nd}|dC |d.|d d |d>|d! dd?|d$d@ |dA|d |d!  dd?d4| d$d@ |dB|d' d( |d	 |d |dD |dE |dF |dG |d	 |dH |dI |d dJ|S )KuC   Genera el contenido textual del reporte para un cliente específico)EneroFebreroMarzoAbrilMayoJunioJulioAgosto
SeptiembreOctubre	Noviembre	Diciembrer   u8   REPORTE MENSUAL CONSOLIDADO DE FACTURACIÓN ELECTRÓNICAzA=================================================================u   Fecha de generación: z%d/%m/%Y %H:%M:%Su   Período analizado: r    u   INFORMACIÓN DEL PROVEEDOR:z------------------------------u#   Razón Social: TransmisionesMig SASz"Nombre Comercial: TransmisionesMigu#   Servicio: Facturación Electrónicau   INFORMACIÓN DEL CLIENTE:u   Razón Social: zNombre Comercial: zNIT: zEmail: u   Teléfono: u   Dirección: zRESUMEN EJECUTIVOz--------------------z	Cliente: u   Período de facturación: z%d/%m/%Yr   rj   r   zTotal documentos procesados: ,z&Documentos transmitidos exitosamente: rk   u   Tasa de éxito: rm   z.2f%zValor total facturado: $r   z,.2fz"No se encontraron documentos para u    en este período.u$   DETALLE DE FACTURACIÓN ELECTRÓNICAz(========================================u0   Estadísticas de Documentos (Facturas y Gastos):z- Total Documentos: z(- Documentos Transmitidos Exitosamente: z- Documentos NO Transmitidos: zIndicadores de Efectividad:u    - Tasa de Transmisión Exitosa: u"   - Tasa de Fallos en Transmisión: r   zResumen Financiero:z- Subtotal: $r   z- IVA: $r   z
- Total: $zDETALLE POR TIPO DE DOCUMENTOz#===================================u   Facturas Electrónicas:z- Transmitidos Exitosamente: rz   z%)z- NO Transmitidos: z- Valor Total: $zDocumentos de Gastos:zNOTA IMPORTANTE:zEEste reporte incluye documentos de las tablas fe_documentos y Gastos1u(   procesados durante el período indicado.uY   Solo se evalúa el estado de transmisión (transmitido/no transmitido) para ambas tablas.z7Para cualquier consulta sobre este reporte, contacte a:u=   TransmisionesMig SAS - Servicios de Facturación Electrónica
)r   r   r   r   r   r   rA   rB   rC   rD   rE   rF   r   )rL   r   r   r   rh   r   r   r   month_names
month_namer   contenttasa_exito_facturastasa_exito_gastosrM   rM   rN   r   Y  s   















"












&
 ,
&
 ,










z&ReportManager._generate_report_contentr  c           	      C   s   z/t ||t dd|d |d |d |d |t|t|d}tj| tj  |j	W S  t
yK } ztj  tdt|   d	}~ww )
uB   Guarda el reporte en la base de datos con información del clienteTu!   Reporte generado automáticamenterj   rk   r   rm   rb   rc   r   r   r   r   r   r   r   r   r   r   zError guardando reporte: N)r1   r   rZ   r   dumpsrT   r   addcommitr@   r   rollbackr   r   r   )	rL   r   rg   r   r  r   r   reportr   rM   rM   rN   r     s0   

zReportManager._save_reportc              
   C   sd   zt jt j  }dd |D W S  ty1 } ztdt	|  g W  Y d}~S d}~ww )u7   Obtiene todos los reportes con información del clientec                 S      g | ]}|  qS rM   rO   r   r  rM   rM   rN   
<listcomp>      z1ReportManager.get_all_reports.<locals>.<listcomp>Error obteniendo reportes: N)
r1   r   r   rb   r   r   r   r   r   r   )rL   reportsr   rM   rM   rN   get_all_reports  s   zReportManager.get_all_reportsr   c              
   C   sb   zt j|}|r| W S dW S  ty0 } ztd| dt|  W Y d}~dS d}~ww )z)Obtiene el detalle completo de un reporteN%Error obteniendo detalle del reporte r   )r1   r   r   rO   r   r   r   r   )rL   r   r  r   rM   rM   rN   get_report_detail  s   zReportManager.get_report_detailc              
   C   sr   zt jj|dt j  }dd |D W S  ty8 } zt	d| dt
|  g W  Y d}~S d}~ww )4   Obtiene todos los reportes de un cliente específicorc   c                 S   r  rM   r  r  rM   rM   rN   r     r  z7ReportManager.get_reports_by_client.<locals>.<listcomp>&Error obteniendo reportes del cliente r   N)r1   r   r   r   rb   r   r   r   r   r   r   )rL   rg   r  r   rM   rM   rN   get_reports_by_client  s   z#ReportManager.get_reports_by_clientr   )rP   rQ   rR   __doc__r   r   r   r   r   r   r   r   r   r#   r   r   r   r  r   r  r#  rM   rM   rM   rN   r      s6     D.



t


	"	r   c               
   C   sn   zt   td t j  td W dS  ty6 }  ztd|   t j  W Y d} ~ dS d} ~ ww )u'   Crear todas las tablas automáticamenteu+   ✓ Tablas creadas/verificadas exitosamenteu   ✓ Clientes de ejemplo creadosu   ✗ Error creando tablas: NF)	rT   
create_allr   r   r   r  r   r   r  r   rM   rM   rN   crear_tablas  s   


r'  c               
   C   sV   zt dW S  ty* }  ztdt|   dt|  dfW  Y d} ~ S d} ~ ww )u   Página principalz
index.htmlu"   Error cargando página principal: u   Error cargando la aplicación: r-   N)r   r   r   r   r   r&  rM   rM   rN   index  s   
r(  z/static/<path:filename>c              
   C   sN   zt d| W S  ty& } ztd|  dt|  W Y d}~dS d}~ww )u   Servir archivos estáticosz%/var/www/html/TransmisionesMig/staticu"   Error sirviendo archivo estático r   NzArchivo no encontrado  )r   r   r   r   r   )filenamer   rM   rM   rN   static_files#  s   r,  z/testc                   C   s   t ddt  dS )zEndpoint de pruebaokz"Servidor funcionando correctamente)ro   r   	timestamp)r   r   r   rI   rM   rM   rM   rN   test,  s
   
r/  z/test-dbc               
   C   s   z%t jtd tj } tj }tdd| |t	j
d dd dW S  tyL } ztdt|  td	t|d
dfW  Y d}~S d}~ww )u    Probar conexión a base de datosSELECT 1r-  zBase de datos conectadar   r   r   )ro   r   clientes_countreportes_countdb_urizError en test-db: r   ro   r   r-   N)rT   r   executer
   r#   r   countr1   r   appconfigsplitr   r   r   r   )r1  r2  r   rM   rM   rN   test_db5  s*   


r:  z/init-dbc               
   C   s~   zt  } | rtdddW S tddddfW S  ty> } ztdt|  tdt|ddfW  Y d	}~S d	}~ww )
zInicializar base de datosTz(Base de datos inicializada correctamenter   r   Fz%Error al inicializar la base de datosr-   zError en init-db: r   N)r'  r   r   r   r   r   )	resultador   rM   rM   rN   init_databaseJ  s.   
r=  z/api/clientesc               
   C   s|   zt jjddt j } tdd | D W S  ty= } zt	dt
|  tdt
|idfW  Y d}~S d}~ww )	zObtiene la lista de clientesTrG   c                 S   r  rM   r  )r   rh   rM   rM   rN   r  g  r  z get_clientes.<locals>.<listcomp>zError obteniendo clientes: r   r-   N)r#   r   r   r   rA   r   r   r   r   r   r   )clientesr   rM   rM   rN   get_clientesb  s    r@  POSTc                  C   sd  zt  } g d}|D ]}| |s"tdd| dddf  W S qtjj| d d }|r?tdd	| d  ddfW S t| d
 | d | d | dd| dd| dd| ddd}tj	
| tj	  td|j d|j d tdd| ddfW S  ty } z tdt|  tj	  tdt|ddfW  Y d}~S d}~ww )zCrea un nuevo cliente)r7   r8   r9   Fz	El campo z es obligatorior     r9   rC   zYa existe un cliente con NIT r7   r8   r:   r  r;   r<   r=   TrA   rB   rC   rD   rE   rF   rG   zCliente creado:  (NIT: r{   zCliente creado exitosamenter   r   rh      zError creando cliente: r-   N)r   get_jsonr   r   r#   r   r   r   rT   r   r  r  r   r   rA   rC   rO   r   r   r   r  )datarequired_fieldsfieldexistingrh   r   rM   rM   rN   create_clientel  sd   









rM  z/api/clientes/<int:cliente_id>PUTc              
   C   s>  zot j| }|stddddfW S t }d|v r |d |_d|v r)|d |_d|v r2|d |_d|v r;|d |_	d	|v rD|d	 |_
d
|v rM|d
 |_t |_tj  td|j d|j d tdd| dW S  ty } z#td|  dt|  tj  tdt|ddfW  Y d}~S d}~ww )zActualiza un clienteFr|   r   r*  r7   r8   r:   r;   r<   r=   Cliente actualizado:  (ID: r{   Tz Cliente actualizado exitosamenterF  zError actualizando cliente r   r-   N)r#   r   r   r   r   rH  rA   rB   rD   rE   rF   rG   r   rZ   rJ   rT   r   r  r   r   r@   rO   r   r   r   r  )rg   rh   rI  r   rM   rM   rN   update_cliente  sR   









rQ  DELETEc              
   C   s   z`t j| }|stddddfW S tjj| d }|dkr8d|_t	 |_
tj  d|j d| d	}n|j}tj| tj  d| d
}td|j d|  d td|dW S  ty } z#td|  dt|  tj  tdt|ddfW  Y d}~S d}~ww )z"Desactiva un cliente (soft delete)Fr|   r   r*  r!  r   zCliente z desactivado (tiene z reportes asociados)z eliminado completamentezCliente eliminado/desactivado: rP  r{   Tr;  zError eliminando cliente r   r-   N)r#   r   r   r   r1   r   r6  rG   r   rZ   rJ   rT   r   r  rA   deleter   r   r   r   r   r  )rg   rh   r2  r   r7   r   rM   rM   rN   delete_cliente  sF   




rT  z'/api/clientes/<int:cliente_id>/reportesc              
   C   s   z"t j| }|stddddfW S t| }td| |dW S  tyL } zt	d|  dt
|  tdt
|dd	fW  Y d
}~S d
}~ww )r   Fr|   r   r*  T)r   rh   r\   r"  r   r-   N)r#   r   r   r   report_managerr#  rO   r   r   r   r   )rg   rh   r\   r   rM   rM   rN   get_reportes_by_cliente  s2   

rV  z/api/test-pos-connectionc               
   C   sp   zt ddt  ddddW S  ty7 }  ztdt|   t dt| d	d
fW  Y d} ~ S d} ~ ww )z/Endpoint para que el POS pruebe la conectividadr-  u   Conexión desde POS exitosazReportes Web MIGz1.0zTransmisionesMig POS)ro   r   r.  serverversioncliente_sistemazError en test-pos-connection: r   r4  r-   N)r   r   r   rI   r   r   r   r   r&  rM   rM   rN   test_pos_connection  s&   

rZ  z/api/reportes-desde-posc            
   
   C   sl  zt  } td| d  g d}|D ]}| |s,tdd| ddf  W S q| d }t|}|sAtdd	ddfW S | d }tjj	||j
d
d }|rbt||  d| d|j }nt|j
| }d| d|j }td|  td
||j
|j|j|jd|dW S  ty }	 ztdt|	  tddt|	 ddfW  Y d}	~	S d}	~	ww )z-Recibe reportes enviados desde el sistema POSu.   📥 Recibiendo reporte desde POS - Período: rf   )rf   ri   empresaFCampo requerido faltante: r   rB  r[  z%No se pudo crear/verificar el clienteTr   zReporte z actualizado para z creado para u   ✅ r6   r7   r8   r9   )r   r   rh   rf   u(   ❌ Error recibiendo reporte desde POS: Error interno: r-   N)r   rH  r   r   r   r   #verificar_o_crear_cliente_desde_posr1   r   r   r@   r   actualizar_reporte_existenterA   crear_reporte_desde_posrB   rC   r   r   r   )
rI  rJ  rK  empresa_datarh   r   r   mensajer   r   rM   rM   rN   recibir_reporte_desde_pos)  sp   



rd  c              
   C   s  z|  dd }|std W dS tjj|d }|rd}|  dr3|j| d kr3| d |_d}|  d	rF|j	| d	 krF| d	 |_	d}|  d
rY|j
| d
 krY| d
 |_
d}|  drl|j| d krl| d |_d}|rt |_tj  td|j  |W S t|  dd|  d	d||  d
d|  ddddd}tj| tj  td|j d| d |W S  ty } ztdt|  tj  W Y d}~dS d}~ww )z?Verifica si existe un cliente o lo crea basado en datos del POSr9   r  u$   ⚠️ NIT vacío en datos desde POSNrC  Fr7   Tr8   r:   r;   rO  zSin DefinirrD  z Nuevo cliente creado desde POS: rE  r{   z-Error verificando/creando cliente desde POS: )r   stripr   warningr#   r   r   r   rA   rB   rD   rE   r   rZ   rJ   rT   r   r  r   r  r   r   r   r  )rb  r9   rh   cliente_actualizadonuevo_clienter   rM   rM   rN   r_  j  sX   













r_  c              
   C   s   zJ| dr|d | _| dr|d | _| dr|d | _| dr)|d | _| dr3|d | _dt d | _	t
 | _tj  W d	S  tyl } ztdt|  tj  W Y d	}~d	S d	}~ww )
z0Actualiza un reporte existente con datos del POSrj   rk   rl   rm   rr   zActualizado desde POS - %Y-%m-%d %H:%M:%Sz&Error actualizando reporte existente: N)r   r   r   r   r   r   r   r   r   r   rZ   r   rT   r   r  r   r   r   r   r  )r   rI  r   rM   rM   rN   r`    s&   










r`  c                 C   s   zMt |d | t ddt d |dd|dd|dd|d	d|d
dt|di t|di d}tj	
| tj	  |jW S  tyo } ztdt|  tj	  W Y d}~dS d}~ww )z)Crea un nuevo reporte desde datos del POSrf   TzCreado desde POS - ri  rj   r   rk   rl   rm   rr   r  rs   rt   r  z!Error creando reporte desde POS: N)r1   r   rZ   r   r   r   r   r  rT   r   r  r  r@   r   r   r   r   r  )rg   rI  nuevo_reporter   rM   rM   rN   ra    s0   






ra  z/api/statusc            	   
   C   s  zzt jtd d} W n   d} Y d}| rVz!tjtj 	 }|r8|j
|j |jr4|j ndd}W n tyU } ztdt|  W Y d}~nd}~ww | ratjjdd nd}| rjtj nd}t }|jd	k rt|j|jd
 d
nt|jd
 d
d
}t|j|jd}t| || t  ||dW S  ty } z tdt|  tdt|t  ddfW  Y d}~S d}~ww )u:   Obtiene el estado del sistema con información de clientesr0  TFN)rf   ri   rh   u"   Error obteniendo último reporte: r>  r      r   ra   )db_connectedlast_reportnext_report_datecurrent_timeclientes_activostotal_reporteszError obteniendo estado: )rl  r   ro  r-   )rT   r   r5  r
   r1   r   r   r   r   r   rb   rI   r2   rO   r   r   rf  r   r#   r   r6  r   r   r   r   r   r   )	rl  rm  ultimor   rp  rq  r   
next_monthrn  rM   rM   rN   
get_status  sX    0

	
rt  z/api/reportsc               
   C   s   zt jd} | rtt| }nt }t|W S  ty? } zt	
dt|  tdt|idfW  Y d}~S d}~ww )u9   Obtiene la lista de reportes con información de clientesrg   r  r   r-   N)r   r   r   rU  r#  r   r  r   r   r   r   r   )rg   r  r   rM   rM   rN   get_reports  s   
 ru  z/api/reports/<int:report_id>c              
   C   s~   zt | }|rt|W S tddidfW S  ty> } ztd|  dt|  tdt|idfW  Y d}~S d}~ww )u,   Obtiene el detalle de un reporte específicor   Reporte no encontrador*  r  r   r-   N)rU  r  r   r   r   r   r   )r   r  r   rM   rM   rN   r  "  s   

 r  z/api/generate-reportc               
   C   s   zEt  pi } | d}|stddddfW S d}d| v r0d| v r0tt| d t| d d	}t||}|d
 r?t|W S t|dfW S  tyo } zt	
dt|  tddt| ddfW  Y d}~S d}~ww )u;   Genera un nuevo reporte mensual para un cliente específicorg   FzEl cliente_id es obligatorior;  rB  Nr   r   r   r   r   Error interno del servidor: r-   )r   rH  r   r   r   r   rU  r   r   r   r   r   )rI  rg   r   resultr   rM   rM   rN   generate_report/  s6   

ry  z/api/generate-all-reportsc               
   C   s  z_t  pi } d}d| v rd| v rtt| d t| d d}tjjdd }g }d}|D ]}t	|j
|}|| |d |d	 rI|d7 }q.tdd
| dt| d|t||dW S  ty } ztdt|  tddt| ddfW  Y d}~S d}~ww )z/Genera reportes para todos los clientes activosNr   r   r   Tr>  r   )rh   rx  r   Se generaron z reportes de 	 clientes)r   r   generated_counttotal_clientsresultsz2Error generando reportes para todos los clientes: Frw  r;  r-   )r   rH  r   r   r#   r   r   r   rU  r   r@   r   rO   r   r   r   r   r   r   )rI  r   r?  r~  r|  rh   rx  r   rM   rM   rN   generate_all_reportsO  sD   
r  z/api/verify-missingc               
   C   s  zt jjdd } t }|j}|j}|d }d}g }| D ]}d}g }	tddD ]8}
| d|
d}t	jj||j
dd }|sat||
t||
d }t|j
|}|d	 ra|d7 }|	| q)td|D ]8}
| d|
d}t	jj||j
dd }|st||
t||
d }t|j
|}|d	 r|d7 }|	| qg||7 }|| ||	d
 qtd| dt|  d td|t| d| dt|  d|dW S  ty } ztdt|  tdddt| ddfW  Y d}~S d}~ww )z<Verifica y genera reportes faltantes para todos los clientesTr>  r   r      r   02dr   r   )rh   r|  generated_periodsu'   Verificación completada. Se generaron z reportes faltantes para z
 clientes.rz  r{  )r   r|  r}  r   results_by_clientz&Error verificando reportes faltantes: Frw  )r   r|  r   r-   N)r#   r   r   r   r   r   r   r   ranger1   r@   r   r   r   rU  r   r   rO   r   r   r   r   r   r   r   )r?  current_datecurrent_yearcurrent_monthprevious_yeartotal_generatedr  rh   r|  r  r   r   rL  r   rx  r   rM   rM   rN   verify_missingx  sp   



r  z%/api/reports/<int:report_id>/downloadc              
   C   s   zVt | }|stddidfW S |dd}|s"tddidfW S t }||d |d |d	i }|d
d	dd}d| d|d  d}t
|d|ddW S  ty } ztd|  dt|  tdt|idfW  Y d}~S d}~ww )z$Descarga un reporte en formato textor   rv  r*  rr   r  z#Contenido del reporte no disponiblezutf-8r   rh   r8   Clienter   _Reporte_rf   z.txtTz
text/plainas_attachmentdownload_namemimetypezError descargando reporte r   r-   N)rU  r  r   r   ioBytesIOwriteencodeseekreplacer   r   r   r   r   )r   r  r  bytes_bufferr   cliente_namer+  r   rM   rM   rN   download_report  s0   

 r  z/api/reports/exportc                  C   sf  z|t  } | stddidfW S g }| D ]}z^|dpi }||dd|dd|dd|d	d|d
d|dd|dd|dd|dd|ddkrWdnd|dd|dd|dridnd|dppdd W q ty } ztd|d dt|  W Y d}~qd}~ww |stdd id!fW S t	
|}|jd"d#d$d%}d&|jv rzt	j|d& d'd(jd)|d&< W n ty } ztd*t|  W Y d}~nd}~ww t }zRt	j|d+d,@}|j|d-d.d/ |jd- }t|jD ]%\}	}
t||
 tt t|
d0 }t|d1|jtd2|	  _qW d   n	1 s3w   Y  W n+ tyd } ztd3t|  tdd4t| id!fW  Y d}~W S d}~ww |d d5t ! d6 d7}t"|d#|d8d9W S  ty } z(td:t|  ddl#}t|$  tdd;t| id!fW  Y d}~S d}~ww )<u[   Exporta todos los reportes a Excel con información de clientes - ORDENADO ALFABÉTICAMENTEr   zNo hay reportes para exportarr*  rh   r7   zN/Ar8   r9   rf   rj   r   rk   rm   rl   ri   ro   rp   
Completadory   r:   r  r;   r=   u   SíNorn   )   Razón SocialzNombre ComercialrC   u   PeríodozTotal DocumentoszDocumentos Exitososu   Tasa de Éxito (%)zValor Total   Fecha GeneraciónEstadorD   u	   TeléfonorG   r   zError procesando reporte r6   r   Nz$No se pudieron procesar los reportesr-   r  Tlast)by	ascendingna_positionr  coerce)errorsri  zError formateando fechas: openpyxl)enginezReportes por ClienteF)
sheet_namer(  r`   r,   A   zError creando Excel: zError al crear archivo Excel: Reportes_Clientes_z%Y%m%d_%H%M%Sz.xlsxzAapplication/vnd.openxmlformats-officedocument.spreadsheetml.sheetr  zError exportando reportes: zError interno al exportar: )%rU  r  r   r   r   r   r   r   r   pd	DataFramesort_valuescolumnsto_datetimedtr   rf  r  r  ExcelWriterto_excelsheets	enumeratemaxastypeapplyr   mincolumn_dimensionschrwidthr  r   r   r   	traceback
format_exc)r  
excel_datar  rh   r   dfexcel_bufferwriter	worksheetidxcol
max_lengthr+  r  rM   rM   rN   export_reports  s   










 

" 
(
&r  z"/api/actualizar-estado-facturacionc               
   C   s4  zt  } td| d  g d}|D ]}| |s,tdd| ddf  W S q| d }| d }| d	 }| d
 }zt|dd}W n   t	 }Y t
jj|d }|sjtdd| dddfW S tjj||jdd }	|	stdd| d|j dddfW S d|	_||	_||	_d| dt	 d }
|	jr|	 jd|
 7  _n|
|	_tj  td|j d| d|  tdd|j|j|j|jd|	j|	j|	j|	j|	jr|	j nddd W S  ty } z#td!t|  tj   tdd"t| dd#fW  Y d}~S d}~ww )$u>   Actualiza el estado de facturación de un reporte desde el POSu5   📋 Actualizando estado de facturación - Período: rf   )rf   rw   r   rv   Fr\  r   rB  rw   r   rv   Tr   rC  zCliente con NIT r   r*  Tr   u   Reporte para período z y cliente zFacturado desde POS - Factura #r   ri  z | u2   ✅ Estado de facturación actualizado - Cliente: u   , Período: z, Factura: u/   Estado de facturación actualizado exitosamenter]  N)r6   rf   ru   rw   rv   )r   r   rh   r   u/   ❌ Error actualizando estado de facturación: r^  r-   )!r   rH  r   r   r   r   r   fromisoformatr  r   r#   r   r   r   r1   r@   rA   rx   r   r   r   r   rT   r   r  rB   rC   rb   rI   r   r   r   r  )rI  rJ  rK  rf   rw   r   fecha_facturacion_strrv   rh   r   observaciones_facturacionr   rM   rM   rN   actualizar_estado_facturacion3  s   






r  z$/api/reportes-pendientes-facturacionc            
      C   s  zt jd} t jd}t jd}tjttttj	tj
ktjdktjdk}| rQ|rE|  dt|d }|tj|k}n|tj|  d}|r[|tj	|k}|tj  }g }|D ]/\}}||j
|j|j|j|jt|jp~d	|jpd	|jpd	|jr|j nd
|jpdd
 qit dt!| d t"|W S  t#y }	 zt$dt|	  t"dt|	ddfW  Y d
}	~	S d
}	~	ww )u6   Obtiene reportes que están pendientes de facturaciónr   r   rg   TFr   r`   r   r   N)

reporte_idrf   r   r   r   rl   rj   rk   ri   ru   u   📋 Obtenidos u$    reportes pendientes de facturaciónu*   ❌ Error obteniendo reportes pendientes: r   r-   )%r   r   r   rT   r   r   r1   r#   r   rc   r@   r   r   rx   r   r   rb   r   r   r   r   r   rC   rA   rB   r   r   r   r   r   rI   r   r   r   r   r   r   )
r   r   rg   r   r   reportes_pendientesr<  r   rh   r   rM   rM   rN   #get_reportes_pendientes_facturacion  s\   

r  z/api/reportes-facturadosc            
      C   s  zt jd} t jd}t jd}tjttttj	tj
ktjdktjdk}| rQ|rE|  dt|d }|tj|k}n|tj|  d}|r[|tj	|k}|tj  }g }|D ]8\}}||j
|j|j|j|jt|jp~d|jpd|jpd|jr|j nd	|j|j |jr|j nd	d
 qit!"dt#| d t$|W S  t%y }	 zt!&dt|	  t$dt|	ddfW  Y d	}	~	S d	}	~	ww )z+Obtiene reportes que ya han sido facturadosr   r   rg   Tr   r`   r   r   N)r  rf   r   r   r   rl   rj   rk   ri   ru   rw   rv   u   💰 Obtenidos z reportes facturadosu*   ❌ Error obteniendo reportes facturados: Fr   r-   )'r   r   r   rT   r   r   r1   r#   r   rc   r@   r   r   rx   r   r   rb   r   r   r   r   r   r   rC   rA   rB   r   r   r   r   r   rI   r   r   r   r   r   r   r   )
r   r   rg   r   r   reportes_facturadosr<  r   rh   r   rM   rM   rN   get_reportes_facturados  s`   

r  z/api/estadisticas-facturacionc            
      C   s  zt jdt j} tjtj	
|  dtjdk}| }|tjdk }|| }tjtjtjtj	
|  dtjdktjdk pNd}tjtjtjtj	
|  dtjdktjdk pod}t|dkr{|| d ndd}t|dkr|| d ndd}t| |||||t|t|t|| d	W S  ty }	 ztd	t|	  tdt|	d
dfW  Y d}	~	S d}	~	ww )u/   Obtiene estadísticas generales de facturaciónr   r   Tr   Fr   r`   )	r   rq  r  r  porcentaje_facturadoporcentaje_pendientevalor_total_facturadovalor_total_pendientevalor_total_generalu$   ❌ Error obteniendo estadísticas: r   r-   N)r   r   r   r   r   r   r1   r   r   rb   r   r   r6  rx   rT   r   funcr   r   scalarr   r   r   r   r   r   r   )
r   reportes_queryrq  r  r  r  r  r  r  r   rM   rM   rN   get_estadisticas_facturacion  sp   	

r  r*  c                 C   sT   t dtj  tjdrtddidfS dtjv rdS tjdr(t	d	S d
S )Nz404 error: /api/r   zEndpoint no encontrador*  z/static/r)  z1/var/www/html/TransmisionesMig/templates/404.htmlz404.html)u   Página no encontradar*  )
r   rf  r   urlpath
startswithr   osexistsr   r   rM   rM   rN   	not_found;  s   
r  r-   c                 C   sZ   t dt|  dtj  tj  tj	dr!t
ddidfS tjdr+tdS d	S )
Nz500 error:  - URL: r  r   Error interno del servidorr-   z1/var/www/html/TransmisionesMig/templates/500.htmlz500.html)r  r-   )r   r   r   r   r  rT   r   r  r  r  r   r  r  r   r  rM   rM   rN   internal_errorD  s
   
r  c                 C   s6   t dt|  dtj  tj  tddidfS )z Maneja excepciones no capturadasu   Excepción no capturada: r  r   r  r-   )	r   r   r   r   r  rT   r   r  r   r&  rM   rM   rN   handle_exceptionL  s   
r  c               
   C   s   t d z)t  tjtd t d t  W d   W dS 1 s'w   Y  W dS  t	yK }  zt 
dt|   W Y d} ~ dS d} ~ ww )u2   Inicialización de la aplicación para producciónuG   Aplicación cargada para producción con Apache - Versión con Clientesr0  u4   ✅ Conexión a base de datos exitosa en producciónNu7   ❌ Error de conexión a base de datos en producción: )r   r   r7  app_contextrT   r   r5  r
   r'  r   r   r   r&  rM   rM   rN   initialize_appT  s   


&"r  __main__z2==================================================u+   🚨 MODO DESARROLLO - SISTEMA CON CLIENTESu8   🚨 Esta aplicación maneja múltiples empresas clienteu1   Iniciando aplicación con gestión de clientes...r0  u%   ✅ Conexión a base de datos exitosau,   ❌ No se pudo conectar a la base de datos: z3
==================================================zURLs de prueba:z- http://localhost:8000/testz- http://localhost:8000/test-dbz- http://localhost:8000/init-dbz"- http://localhost:8000/api/statusz$- http://localhost:8000/api/clientesz3==================================================
z0.0.0.0i@  )hostportdebugthreaded)eflaskr   r   r   r   r   r   
flask_corsr   flask_sqlalchemyr	   
sqlalchemyr
   r   r   r   loggingr  pathlibr   r  pandasr  typingr   r   r   r   r   log_dirmakedirsbasicConfigINFOFileHandlerr  r   StreamHandler	getLoggerrP   r   r7  	DB_SERVERDB_PORTDB_DATABASEDB_USERNAMEDB_PASSWORD	DB_DRIVERr  r8  rT   Modelr#   r1   router   r   r'  rU  r(  r,  r/  r:  r=  r@  rM  rQ  rT  rV  rZ  rd  r_  r`  ra  rt  ru  r  ry  r  r  r  r  r  r  r  r  errorhandlerr  r  r   r  r  r  printr   r   r5  r   rf  r   runapplicationrM   rM   rM   rN   <module>   s    
 



 D
V  





	
4
.
+


@=
2



(
B
 
V
Z
8
:
8








 