Commit 531afce6 by Javier

Initial commit

parents
CDR_HOSTNAME=sftp.xtratelecom.es
CDR_USERNAME=cF33028
CDR_PASSWORD=9BRW78sf
CDR_FIBRA_HOSTNAME=212.166.71.71
CDR_FIBRA_USERNAME=9624566
CDR_FIBRA_PASSWORD=3gWKHQBV3S
CDR_SFTP_PORT=22
SQLSERVER_SERVER=192.168.2.200
SQLSERVER_DATABASE=bdd_wifi
SQLSERVER_USERNAME=apicdr
SQLSERVER_PASSWORD=cdr5485
SQLSERVER_SERVER_TEST=192.168.2.200
SQLSERVER_DATABASE_TEST=cdr_test
SQLSERVER_USERNAME_TEST=apicdr
SQLSERVER_PASSWORD_TEST=cdr5485
\ No newline at end of file
venv
.vscode
__pycache__/
*.log
*.txt
*.pdf
*.rar
\ No newline at end of file
# Importación de CDRs y Facturas de MásMóvil
Descarga CDRs fijas desde el sFPT de MásMóvil para añadirlos a los sistemas de Rentel.
## Introducción
### Funcionalidad
Se ejecuta de forma periodica para conectarse a dos sFTP diferentes desde donde extrae el consumo de las líneas fijas (de clientes con fibra indirecta).
### Lenguajes de Programación
Le herramienta está desarrollada con Python. Se utilizan librerías de python para el acceso a los servidores SFTP.
### Credenciales
| Servicio | Descripción | Producción | Dirección | Base de datos | Usuario | Contraseña |
|-------------|---------------------------------------------------------------------------------------|------------|------------------------------------|---------------|---------|------------|
| CDR Fijos y móviles | Servidor FTP de CableMóvil con los CDR de los consumos de las líneas Fijos y móviles | Si | sftp.xtratelecom.es | | cF33028 | 9BRW78sf |
| SQL Server | Servidor Principal SQL Server | Si | 10.58.4.5 / 192.168.2.200 | bdd_wifi | apicdr | cdr5485 |
### Importador MásMóvil
Está compuesto de un script, `setup.py`, se encarga de conectarse al sFTP de MásMóvil, y descargar los archivos de CDRs nuevos.
Posteriormente procederemos al procesado de dichos ficheros, guardando cada línea de estos archivos previamente descargados en las tablas `TB_Cdr`, y `TB_Cdr_Fijos`.
En cada línea aparece la información de cada llamada, el teléfono que realiza la llamada, destino de llamada, duración, entre otros.
El script se encuentra alojado en la máquina `debian.utils` con la IP `192.168.2.63`.
Dicho script se ejecutará según la configuración de un crontab.
\ No newline at end of file
import os
from log import logging
import platform
import pyodbc
class ConectorDbWifi():
def __init__(self):
sql_server_hostname = os.getenv("SQLSERVER_SERVER")
sql_server_database = os.getenv("SQLSERVER_DATABASE")
sql_server_username = os.getenv("SQLSERVER_USERNAME")
sql_server_password = os.getenv("SQLSERVER_PASSWORD")
self.cursor = None
self.connection = None
try:
if platform.system() == "Windows":
self.connection = pyodbc.connect(
"DRIVER={{ODBC Driver 17 for SQL Server}};SERVER={server};\
DATABASE={database};UID={username};PWD={password}".format(
server=sql_server_hostname,
database=sql_server_database,
username=sql_server_username,
password=sql_server_password,
)
)
else:
self.connection = pyodbc.connect(
f"DRIVER=FreeTDS;server={sql_server_hostname};PORT=1433;DATABASE={sql_server_database};UID={sql_server_username};PWD={sql_server_password};TDS_Version=7.0", encoding="utf-8", ansi=True
)
except Exception as e:
print('Error al conectarse con la base de datos dbo.wifi')
logging.warning('Error al conectarse con la base de datos dbo.wifi')
def __enter__(self):
"""Se ejecuta cuando se entra en el bloque 'with'. Abre la conexión y el cursor."""
if not self.connection:
raise Exception("Conexión no establecida.")
self.cursor = self.connection.cursor() # Obtiene el cursor
return self.cursor # Devuelve el cursor para ser usado en el bloque 'with'
def __exit__(self, exc_type, exc_value, traceback):
"""Se ejecuta cuando se sale del bloque 'with'. Cierra el cursor y la conexión."""
if self.cursor:
self.cursor.close() # Cierra el cursor
if self.connection:
self.connection.close() # Cierra la conexión
# Si ocurre una excepción, la propagamos (devuelve False) o no (devuelve True)
return False # Devolver False permite que la excepción sea propagada
\ No newline at end of file
import paramiko
class SFTPConexion:
"""Crea una conexión SFTP"""
@staticmethod
def connection(hostname: str, username: str, password: str, port: int):
"""
Crea una conexión sFTP.
Args:
hostname (str): Nombre del host.
username (str): Nombre de usuario.
password (str): Constraseña de usuario.
port (_type_): Puerto de conexión.
Returns:
_type_: _description_
"""
transport = paramiko.Transport((hostname, port))
transport.connect(None, username, password)
return paramiko.SFTPClient.from_transport(transport)
\ No newline at end of file
from conector_sftp import SFTPConexion
import os, time
from datetime import datetime
from paramiko.ssh_exception import SSHException
from log import logging
from conector_db_wifi import ConectorDbWifi
class ManagerCdrFijos:
def __init__(self):
hostname_xtrtelecom = os.getenv('CDR_HOSTNAME')
username_xtrtelecom = os.getenv('CDR_USERNAME')
pwd_xtrtelecom = os.getenv('CDR_PASSWORD')
port_xtrtelecom = int(os.getenv("CDR_SFTP_PORT"))
# Guardo las rutas absolutas donde se almacena los ficheros que vamos a descargar
self.filename_fijo_download_sftp_path = []
# Guardo el nombre de los ficheros para descargarlos de sftp y agregarlos a la tabla tb_CDR_Ficheros
self.filename_fijo_download_sftp = []
# Diccionario donde se almacenara nombre fichero: fecha sftp de la creación del mismo en el sftp
self.filename_datetime_fijo = {}
try:
self.cnx_sftp_xtrtelecom = SFTPConexion.connection(
hostname_xtrtelecom, username_xtrtelecom, pwd_xtrtelecom, port_xtrtelecom
)
except SSHException as e:
message = "No se ha podido establecer la conexión con el servidor de los CDR de móviles y fijos.. Error: {e}".format(e=e)
logging.info(message)
print(message)
def get_cdr_filename_download_fijos(self):
"""
Obtengo los nombre de los ficheros, el path(ruta absoluta) y fecha_origen los almaceno para posteriormente descargarlos del sftp y
almacenar en la tabla TB_CDR_Ficheros
"""
try:
with ConectorDbWifi() as cursor:
#Consultamos en la tabla la fecha del último fichero subido
cursor.execute("SELECT TOP 1 created_at FROM bdd_wifi.dbo.TB_CDR_Ficheros WHERE tipo = 2 ORDER BY created_at DESC")
row = cursor.fetchone()
last_cdr_mvno_table_ficheros = row[0]
#Obtengo datos del sftp de cdr
item_list = self.cnx_sftp_xtrtelecom.listdir_attr('cdrs')
for item in item_list:
fecha = time.localtime(item.st_mtime) # Fecha creación fichero en el SFTP
file_date_time = datetime(fecha[0], fecha[1], fecha[2], fecha[3], fecha[4], fecha[5])
# Obtengo el nombre de los ficheros de fijos que la fecha sea posterior al último cdr ingresado en la tabla, y lo guardo en una lista, también guardo la ruta absoluta
# y un diccionario con la fecha de creación del fichero en el sftp asociada al nombre del fichero
""" #Obtener fichero de un dia concreto
if item.filename.__contains__('mvno_F33028-20230619'):
item_filename = item.filename
self.filename_datetime_mvno[item_filename]=str(file_date_time)
self.filename_mvno_download_sftp.append(item_filename)
self.filename_mvno_download_sftp_path.append('/home/rentel/FTP-upload-cdr-pcloud/cdrs/' + item_filename)
print(item.filename) """
if last_cdr_mvno_table_ficheros < file_date_time and 'mvno' not in item.filename:
item_filename = item.filename
self.filename_datetime_fijo[item_filename]=str(file_date_time)
self.filename_fijo_download_sftp.append(item_filename)
self.filename_fijo_download_sftp_path.append('/home/rentel/procesado-cdr-fijos/cdrs/' + item_filename)
message = f'Obtenidos nombre ficheros para su posterior descarga: {self.filename_fijo_download_sftp}'
logging.info(message)
except Exception as e:
logging.warning(f'Error al almacenar el nombre de los ficheros para su posterior descarga: {e}')
def download_cdr_fijos_xtratelecom(self):
"""
Descarga los archivos CDR del servidor SFTP almacenandolos en el directorio cdrs
"""
try:
with ConectorDbWifi() as cursor:
if self.filename_fijo_download_sftp:
for file in self.filename_fijo_download_sftp:
self.cnx_sftp_xtrtelecom.get("cdrs/" + file, "/home/rentel/procesado-cdr-fijos/cdrs/" + file)
filepath = "/home/rentel/procesado-cdr-fijos/cdrs/" + file
message = f'Fichero descargados correctamente en la carpeta cdrs {file}'
logging.info(message)
else:
message = "No hay fichero para descargar "
logging.info(message)
except Exception as e:
logging.warning(f'Error al descargar los archivos CDR del servidor SFTP: {e}')
def update_insert_date_fijo(self):
"""
Inserto o actualizo en la tabla TB_CDR_ficheros los ficheros de **fijos** , poniendo el campo procesado a null.
"""
# Recorro el nombre de los ficheros descargados y consulto en la tabla si ese fichero existe lo actualizo si no existe lo creo
for cdr_filename in self.filename_fijo_download_sftp:
filepath = '/home/rentel/procesado-cdr-fijos/cdrs/'+cdr_filename
lineas_fichero_txt = calcular_line_file(filepath)
message = f'Fichero para insertar o actualizar en la tabla TB_CDR_Ficheros {cdr_filename}'
logging.info(message)
with ConectorDbWifi() as cursor:
cursor.execute(
"SELECT count(*) FROM TB_CDR_Ficheros WHERE filename = ?",
cdr_filename
)
fetch = cursor.fetchone()
if "_mes" in str(cdr_filename):
mensual = 1
else:
mensual = 0
if "_deg" in str(cdr_filename):
degradado = 1
else:
degradado = 0
# Si existe un registro con ese nombre lo actualizo si no lo creo
if fetch[0] != 0:
fecha_creacion_fichero = self.filename_datetime_fijo.get(cdr_filename)
fecha_creacion_fichero_formateada = datetime.strptime(fecha_creacion_fichero, '%Y-%m-%d %H:%M:%S')
cursor.execute("UPDATE TB_CDR_Ficheros SET tipo = ?, fecha_origen = ?,Num_Reg_Txt = ?, Degradado=?, Mensual=? WHERE filename = ?", 2, fecha_creacion_fichero_formateada,lineas_fichero_txt, degradado, mensual, str(cdr_filename))
cursor.commit()
message = f'Fichero {cdr_filename} actualizado en la tabla TB_CDR_Ficheros'
logging.info(message)
else:
cursor.execute(
"INSERT INTO TB_CDR_Ficheros (filename, created_at, tipo, fecha_origen, Degradado, Num_Reg_Txt, Mensual) "
"VALUES ( ?, ?, ?, ?, ?, ?, ? )",
(
cdr_filename,
datetime.now(),
2,
self.filename_datetime_fijo.get(cdr_filename),
degradado,
lineas_fichero_txt,
mensual
),
)
cursor.commit()
message = f'Fichero {cdr_filename} insertado en la tabla TB_CDR_Ficheros'
logging.info(message)
def calcular_line_file(filepath):
with open(filepath, "rb") as myfile:
num_lines=myfile.readlines()
return len(num_lines)
import os
import logging
from datetime import date
APP_BASE_PATH: str = os.path.abspath(os.path.join(__file__, "../"))
LOG_PATH: str = os.path.join(APP_BASE_PATH, "logs/{date}-log.log".format(date=date.today()))
logger = logging.getLogger(__name__)
logging.basicConfig(
level=logging.INFO,
format="DATE:[%(asctime)s] LEVEL:[%(levelname)-s] FUNCTION:[%(funcName)s] Line:[%(lineno)d] MESSAGE:[%(message)s]",
datefmt="%a, %d %b %Y %H:%M:%S",
filename=LOG_PATH,
filemode="a",
)
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment