92 lines
3.2 KiB
Python
92 lines
3.2 KiB
Python
import pandas as pd
|
|
from sklearn.ensemble import IsolationForest
|
|
import joblib
|
|
import pyodbc
|
|
from datetime import datetime, timedelta
|
|
|
|
print("--- INICIANDO SCRIPT DE ENTRENAMIENTO (MONTOS CONTABLES) ---")
|
|
|
|
# --- 1. Configuración ---
|
|
DB_SERVER = 'TECNICA3'
|
|
DB_DATABASE = 'SistemaGestion'
|
|
CONNECTION_STRING = f'DRIVER={{ODBC Driver 18 for SQL Server}};SERVER={DB_SERVER};DATABASE={DB_DATABASE};Trusted_Connection=yes;TrustServerCertificate=yes;'
|
|
|
|
MODEL_FILE = 'modelo_montos.joblib'
|
|
CONTAMINATION_RATE = 0.002
|
|
|
|
# --- 2. Carga de Datos de Múltiples Tablas ---
|
|
try:
|
|
print(f"Conectando a la base de datos '{DB_DATABASE}' en '{DB_SERVER}'...")
|
|
cnxn = pyodbc.connect(CONNECTION_STRING)
|
|
|
|
fecha_limite = datetime.now() - timedelta(days=730) # Usamos 2 años de datos para tener más contexto financiero
|
|
|
|
# Query para Pagos a Distribuidores
|
|
query_pagos = f"""
|
|
SELECT
|
|
'Distribuidor' AS entidad,
|
|
Id_Distribuidor AS id_entidad,
|
|
Id_Empresa AS id_empresa,
|
|
Fecha AS fecha,
|
|
TipoMovimiento AS tipo_transaccion,
|
|
Monto AS monto
|
|
FROM
|
|
cue_PagosDistribuidor
|
|
WHERE
|
|
Fecha >= '{fecha_limite.strftime('%Y-%m-%d')}'
|
|
"""
|
|
|
|
# Query para Notas de Crédito/Débito
|
|
query_notas = f"""
|
|
SELECT
|
|
CASE
|
|
WHEN Destino = 'Distribuidores' THEN 'Distribuidor'
|
|
WHEN Destino = 'Canillas' THEN 'Canillita'
|
|
ELSE 'Desconocido'
|
|
END AS entidad,
|
|
Id_Destino AS id_entidad,
|
|
Id_Empresa AS id_empresa,
|
|
Fecha AS fecha,
|
|
Tipo AS tipo_transaccion,
|
|
Monto AS monto
|
|
FROM
|
|
cue_CreditosDebitos
|
|
WHERE
|
|
Fecha >= '{fecha_limite.strftime('%Y-%m-%d')}'
|
|
"""
|
|
|
|
print("Ejecutando consultas para obtener datos de pagos y notas...")
|
|
df_pagos = pd.read_sql(query_pagos, cnxn)
|
|
df_notas = pd.read_sql(query_notas, cnxn)
|
|
|
|
cnxn.close()
|
|
|
|
except Exception as e:
|
|
print(f"Error al conectar o consultar la base de datos: {e}")
|
|
exit()
|
|
|
|
# --- 3. Unificación y Preparación de Datos ---
|
|
if df_pagos.empty and df_notas.empty:
|
|
print("No se encontraron datos de entrenamiento en el período seleccionado. Saliendo.")
|
|
exit()
|
|
|
|
# Combinamos ambos dataframes
|
|
df = pd.concat([df_pagos, df_notas], ignore_index=True)
|
|
print(f"Preparando {len(df)} registros contables para el entrenamiento...")
|
|
|
|
# Feature Engineering: Convertir textos a números categóricos
|
|
# Esto ayuda al modelo a entender "Recibido", "Credito", etc., como categorías distintas.
|
|
df['tipo_transaccion_cat'] = pd.Categorical(df['tipo_transaccion']).codes
|
|
df['dia_semana'] = df['fecha'].dt.dayofweek
|
|
|
|
# Las características para el modelo serán el contexto de la transacción y su monto
|
|
features = ['id_entidad', 'id_empresa', 'tipo_transaccion_cat', 'dia_semana', 'monto']
|
|
X = df[features]
|
|
|
|
# --- 4. Entrenamiento y Guardado ---
|
|
print(f"Entrenando el modelo de montos contables con tasa de contaminación de {CONTAMINATION_RATE}...")
|
|
model = IsolationForest(n_estimators=100, contamination=CONTAMINATION_RATE, random_state=42)
|
|
model.fit(X)
|
|
joblib.dump(model, MODEL_FILE)
|
|
|
|
print(f"--- ENTRENAMIENTO DE MONTOS COMPLETADO. Modelo guardado en '{MODEL_FILE}' ---") |