220 lines
10 KiB
Python
220 lines
10 KiB
Python
import random
|
|
from datetime import date, timedelta
|
|
from werkzeug.security import generate_password_hash
|
|
from database import get_db_connection, init_db
|
|
|
|
def generar_historico_definitivo(dias_atras=180):
|
|
init_db()
|
|
conn = get_db_connection()
|
|
c = conn.cursor()
|
|
|
|
# 1. LIMPIEZA TOTAL (Evita el choque con los datos por defecto de database.py)
|
|
print("Limpiando datos de prueba anteriores...")
|
|
c.execute("DELETE FROM rendicion_items")
|
|
c.execute("DELETE FROM rendiciones")
|
|
c.execute("DELETE FROM workers WHERE is_admin = 0")
|
|
conn.commit()
|
|
|
|
c.execute("SELECT id, name FROM modulos")
|
|
modulos = c.fetchall()
|
|
|
|
if not modulos:
|
|
print("Error: No hay módulos creados.")
|
|
return
|
|
|
|
# 2. RECLUTAMIENTO FORZADO PARA TODOS LOS MÓDULOS
|
|
print(f"Reclutando personal para {len(modulos)} módulos...")
|
|
default_pass = generate_password_hash("123456")
|
|
workers_data = []
|
|
|
|
for mod_id, mod_name in modulos:
|
|
tipos = ["Full Time", "Full Time", "Part Time", "Part Time"]
|
|
for i in range(4):
|
|
# Usamos un RUT fijo basado en la iteración para no inflar la DB si lo corres sin limpiar
|
|
rut_falso = f"{10 + i}.{mod_id:03d}.100-{i}"
|
|
nombre_falso = f"Trabajador {i+1} ({mod_name})"
|
|
phone_falso = f"+56 9 8888 {mod_id:02d}{i:02d}"
|
|
|
|
banco = random.choice(["Banco Estado", "Banco de Chile", "Banco Falabella", "Santander", "BCI", "Scotiabank"])
|
|
workers_data.append((
|
|
rut_falso, nombre_falso, phone_falso,
|
|
default_pass, 0, mod_id, tipos[i],
|
|
banco, f"{random.randint(10000000, 99999999)}", random.choice(["Cuenta Corriente", "Cuenta Vista", "Cuenta Rut"]),
|
|
f"{random.randint(10000000, 99999999)}-{random.choice('0123456789K')}",
|
|
))
|
|
|
|
c.executemany('''INSERT OR IGNORE INTO workers
|
|
(rut, name, phone, password_hash, is_admin, modulo_id, tipo,
|
|
nombre_banco, numero_cuenta, tipo_cuenta, rut_banco)
|
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)''', workers_data)
|
|
conn.commit()
|
|
|
|
# 3. PREPARACIÓN DE DATOS
|
|
c.execute("SELECT id, modulo_id, tipo FROM workers WHERE is_admin = 0")
|
|
all_workers_data = c.fetchall()
|
|
todos_los_trabajadores = [w[0] for w in all_workers_data]
|
|
workers_tipo = {w[0]: w[2] for w in all_workers_data}
|
|
|
|
trabajadores_por_modulo = {}
|
|
for w_id, m_id, _ in all_workers_data:
|
|
if m_id not in trabajadores_por_modulo:
|
|
trabajadores_por_modulo[m_id] = []
|
|
trabajadores_por_modulo[m_id].append(w_id)
|
|
|
|
c.execute("""
|
|
SELECT p.id, ph.price, ph.commission
|
|
FROM productos p
|
|
JOIN precios_historicos ph ON p.id = ph.producto_id
|
|
GROUP BY p.id
|
|
""")
|
|
productos = c.fetchall()
|
|
|
|
# 4. VIAJE EN EL TIEMPO
|
|
hoy = date.today()
|
|
fecha_inicio = hoy - timedelta(days=dias_atras)
|
|
rendiciones_creadas = 0
|
|
|
|
# Textos de ejemplo para los gastos
|
|
motivos_gastos = [
|
|
"Compra bidón de agua",
|
|
"Artículos de aseo",
|
|
"Lápices y cuaderno",
|
|
"Reparación menor del módulo",
|
|
"Bolsas para entregar productos",
|
|
"Cinta adhesiva",
|
|
"Pilas para escáner"
|
|
]
|
|
|
|
print(f"Generando turnos con gastos aleatorios desde {fecha_inicio} hasta {hoy}...")
|
|
|
|
for i in range(dias_atras + 1):
|
|
fecha_actual = fecha_inicio + timedelta(days=i)
|
|
fecha_str = fecha_actual.strftime('%Y-%m-%d')
|
|
|
|
for modulo_id, mod_name in modulos:
|
|
workers_modulo = trabajadores_por_modulo.get(modulo_id, [])
|
|
if not workers_modulo:
|
|
continue
|
|
|
|
num_turnos = random.randint(1, 2)
|
|
turnos_a_hacer = [True, False] if num_turnos == 2 else [random.choice([True, False])]
|
|
|
|
for es_manana in turnos_a_hacer:
|
|
# Reemplazos (15%)
|
|
es_reemplazo = random.random() < 0.15
|
|
if es_reemplazo and len(todos_los_trabajadores) > len(workers_modulo):
|
|
posibles_reemplazos = [w for w in todos_los_trabajadores if w not in workers_modulo]
|
|
worker_id = random.choice(posibles_reemplazos)
|
|
else:
|
|
worker_id = random.choice(workers_modulo)
|
|
|
|
if es_manana:
|
|
hora_entrada = f"{random.randint(8, 10):02d}:{random.choice(['00', '30'])}"
|
|
hora_salida = f"{random.randint(14, 16):02d}:{random.choice(['00', '30'])}"
|
|
else:
|
|
hora_entrada = f"{random.randint(13, 15):02d}:{random.choice(['00', '30'])}"
|
|
hora_salida = f"{random.randint(19, 21):02d}:{random.choice(['00', '30'])}"
|
|
|
|
worker_tipo = workers_tipo.get(worker_id, "Part Time")
|
|
worker_comision = 1 if worker_tipo == "Full Time" else random.choice([0, 1])
|
|
|
|
# Acompañante (70%)
|
|
companion_id = None
|
|
comp_in, comp_out = None, None
|
|
companion_comision = 0
|
|
companion2_id = None
|
|
companion2_comision = 0
|
|
if random.random() < 0.70:
|
|
posibles_comp = [w for w in workers_modulo if w != worker_id]
|
|
if posibles_comp:
|
|
companion_id = random.choice(posibles_comp)
|
|
comp_in, comp_out = hora_entrada, hora_salida
|
|
comp_tipo = workers_tipo.get(companion_id, "Part Time")
|
|
companion_comision = 1 if comp_tipo == "Full Time" else random.choice([0, 1])
|
|
|
|
# Acompañante 2 (25% probability if companion 1 is present)
|
|
if random.random() < 0.25:
|
|
posibles_comp2 = [w for w in posibles_comp if w != companion_id]
|
|
if posibles_comp2:
|
|
companion2_id = random.choice(posibles_comp2)
|
|
comp2_tipo = workers_tipo.get(companion2_id, "Part Time")
|
|
companion2_comision = 1 if comp2_tipo == "Full Time" else random.choice([0, 1])
|
|
|
|
# If there is no companion, comision should be disabled (0)
|
|
if companion_id is None:
|
|
companion_comision = 0
|
|
if companion2_id is None:
|
|
companion2_comision = 0
|
|
|
|
num_prods = random.randint(1, 5)
|
|
prods_elegidos = random.sample(productos, min(num_prods, len(productos)))
|
|
items_a_insertar = []
|
|
total_calculado = 0
|
|
|
|
for prod in prods_elegidos:
|
|
p_id, p_price, p_comm = prod
|
|
cantidad = random.randint(1, 6)
|
|
items_a_insertar.append((p_id, cantidad, p_price, p_comm))
|
|
total_calculado += (p_price * cantidad)
|
|
|
|
debito, credito, mp, efectivo = 0, 0, 0, 0
|
|
b_debito, b_credito, b_mp, b_efectivo = 0, 0, 0, 0
|
|
|
|
divisiones = random.randint(1, 3)
|
|
monto_restante = int(total_calculado)
|
|
metodos = ["debito", "credito", "mp", "efectivo"]
|
|
random.shuffle(metodos)
|
|
|
|
for idx, metodo in enumerate(metodos[:divisiones]):
|
|
monto = monto_restante if idx == divisiones - 1 else random.randint(0, monto_restante // 2)
|
|
monto_restante -= monto
|
|
|
|
if monto > 0:
|
|
boletas = random.randint(1, 4)
|
|
if metodo == "debito": debito, b_debito = monto, boletas
|
|
elif metodo == "credito": credito, b_credito = monto, boletas
|
|
elif metodo == "mp": mp, b_mp = monto, boletas
|
|
elif metodo == "efectivo": efectivo, b_efectivo = monto, boletas
|
|
|
|
tipo_registro = "Reemplazo histórico" if es_reemplazo else "Turno histórico"
|
|
|
|
# === LÓGICA DE GASTOS RANDOM ===
|
|
# 15% de probabilidad de tener un gasto en el turno (entre $2.000 y $15.000)
|
|
gastos = 0
|
|
if random.random() < 0.15:
|
|
gastos = random.randint(2, 15) * 1000
|
|
tipo_registro += f" | {random.choice(motivos_gastos)}"
|
|
|
|
c.execute('''
|
|
INSERT INTO rendiciones
|
|
(worker_id, worker_comision, companion_id, companion2_id, modulo_id, fecha,
|
|
hora_entrada, hora_salida, companion_hora_entrada, companion_hora_salida,
|
|
companion_comision, companion2_comision,
|
|
venta_debito, venta_credito, venta_mp, venta_efectivo,
|
|
boletas_debito, boletas_credito, boletas_mp, boletas_efectivo,
|
|
gastos, observaciones)
|
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
''', (worker_id, worker_comision, companion_id, companion2_id, modulo_id, fecha_str,
|
|
hora_entrada, hora_salida, comp_in, comp_out,
|
|
companion_comision, companion2_comision,
|
|
debito, credito, mp, efectivo,
|
|
b_debito, b_credito, b_mp, b_efectivo,
|
|
gastos, tipo_registro))
|
|
|
|
r_id = c.lastrowid
|
|
|
|
for item in items_a_insertar:
|
|
p_id, cant, p_price, p_comm = item
|
|
c.execute('''
|
|
INSERT INTO rendicion_items (rendicion_id, producto_id, cantidad, precio_historico, comision_historica)
|
|
VALUES (?, ?, ?, ?, ?)
|
|
''', (r_id, p_id, cant, p_price, p_comm))
|
|
|
|
rendiciones_creadas += 1
|
|
|
|
conn.commit()
|
|
conn.close()
|
|
print(f"Éxito: Se inyectaron {rendiciones_creadas} rendiciones para TODOS los módulos.")
|
|
|
|
if __name__ == '__main__':
|
|
generar_historico_definitivo(180) |