mirror of
https://github.com/marcogll/telegram_new_socias.git
synced 2026-01-13 21:25:16 +00:00
175 lines
6.1 KiB
Python
175 lines
6.1 KiB
Python
import os
|
|
import json
|
|
import logging
|
|
import requests
|
|
from datetime import datetime, time as time_cls
|
|
|
|
from modules.database import SessionVanityHr
|
|
from models.vanity_hr_models import HorarioEmpleadas, DataEmpleadas
|
|
|
|
def _send_webhook(url: str, payload: dict):
|
|
"""Sends a POST request to a webhook."""
|
|
if not url:
|
|
logging.warning("No webhook URL provided.")
|
|
return False
|
|
try:
|
|
headers = {"Content-Type": "application/json"}
|
|
res = requests.post(url, json=payload, headers=headers, timeout=20)
|
|
res.raise_for_status()
|
|
logging.info(f"Webhook sent successfully to: {url}")
|
|
return True
|
|
except Exception as e:
|
|
logging.error(f"Error sending webhook to {url}: {e}")
|
|
return False
|
|
|
|
def _convert_to_time(time_str: str):
|
|
"""Converts a string like '10:00 AM' to a datetime.time object."""
|
|
if not time_str or not isinstance(time_str, str):
|
|
return None
|
|
try:
|
|
# Handle 'Todo el día' or other non-time strings
|
|
if ":" not in time_str:
|
|
return None
|
|
return datetime.strptime(time_str, '%I:%M %p').time()
|
|
except ValueError:
|
|
logging.warning(f"Could not parse time string: {time_str}")
|
|
return None
|
|
|
|
def _finalize_horario(telegram_id: int, data: dict):
|
|
"""Finalizes the 'horario' flow."""
|
|
logging.info(f"Finalizing 'horario' flow for telegram_id: {telegram_id}")
|
|
|
|
# 1. Prepare data for webhook and DB
|
|
day_pairs = [
|
|
("monday", "MONDAY_IN", "MONDAY_OUT"),
|
|
("tuesday", "TUESDAY_IN", "TUESDAY_OUT"),
|
|
("wednesday", "WEDNESDAY_IN", "WEDNESDAY_OUT"),
|
|
("thursday", "THURSDAY_IN", "THURSDAY_OUT"),
|
|
("friday", "FRIDAY_IN", "FRIDAY_OUT"),
|
|
("saturday", "SATURDAY_IN", None),
|
|
]
|
|
|
|
schedule_data = {
|
|
"telegram_id": telegram_id,
|
|
"short_name": data.get("SHORT_NAME"),
|
|
}
|
|
|
|
rows_for_db = []
|
|
for day_key, in_key, out_key in day_pairs:
|
|
entrada = _convert_to_time(data.get(in_key))
|
|
salida_raw = data.get(out_key) if out_key else "6:00 PM"
|
|
salida = _convert_to_time(salida_raw)
|
|
|
|
schedule_data[f"{day_key}_in"] = entrada
|
|
schedule_data[f"{day_key}_out"] = salida
|
|
|
|
if not entrada or not salida:
|
|
logging.warning(f"Missing schedule data for {day_key}. Entrada: {entrada}, Salida: {salida}")
|
|
continue
|
|
|
|
rows_for_db.append(
|
|
{
|
|
"dia_semana": day_key,
|
|
"hora_entrada": entrada,
|
|
"hora_salida": salida,
|
|
}
|
|
)
|
|
|
|
# 2. Send to webhook
|
|
webhook_url = os.getenv("WEBHOOK_SCHEDULE")
|
|
if webhook_url:
|
|
json_payload = {
|
|
k: (v.isoformat() if isinstance(v, time_cls) else v) for k, v in schedule_data.items()
|
|
}
|
|
json_payload["timestamp"] = datetime.now().isoformat()
|
|
_send_webhook(webhook_url, json_payload)
|
|
|
|
# 3. Save to database (vanity_hr.horario_empleadas)
|
|
if not SessionVanityHr:
|
|
logging.error("SessionVanityHr is not initialized. Cannot persist horarios.")
|
|
return False
|
|
|
|
session = SessionVanityHr()
|
|
try:
|
|
empleada = session.query(DataEmpleadas).filter(DataEmpleadas.telegram_chat_id == telegram_id).first()
|
|
numero_empleado = empleada.numero_empleado if empleada else None
|
|
if not numero_empleado:
|
|
logging.warning(f"No se encontró numero_empleado para telegram_id={telegram_id}. Se guardará NULL.")
|
|
|
|
existing_rows = {
|
|
row.dia_semana: row
|
|
for row in session.query(HorarioEmpleadas).filter_by(telegram_id=telegram_id).all()
|
|
}
|
|
|
|
for row in rows_for_db:
|
|
dia = row["dia_semana"]
|
|
entrada = row["hora_entrada"]
|
|
salida = row["hora_salida"]
|
|
existing = existing_rows.get(dia)
|
|
if existing:
|
|
existing.numero_empleado = numero_empleado or existing.numero_empleado
|
|
existing.hora_entrada_teorica = entrada
|
|
existing.hora_salida_teorica = salida
|
|
else:
|
|
session.add(
|
|
HorarioEmpleadas(
|
|
numero_empleado=numero_empleado,
|
|
telegram_id=telegram_id,
|
|
dia_semana=dia,
|
|
hora_entrada_teorica=entrada,
|
|
hora_salida_teorica=salida,
|
|
)
|
|
)
|
|
|
|
session.commit()
|
|
return True
|
|
except Exception as e:
|
|
logging.error(f"Database error in _finalize_horario: {e}")
|
|
session.rollback()
|
|
return False
|
|
finally:
|
|
session.close()
|
|
|
|
|
|
# Mapping of flow names to finalization functions
|
|
FINALIZATION_MAP = {
|
|
"horario": _finalize_horario,
|
|
# Add other flows here, e.g., "onboarding": _finalize_onboarding
|
|
}
|
|
|
|
|
|
async def finalize_flow(update, context):
|
|
"""Generic function to finalize a conversation flow."""
|
|
flow_name = context.user_data.get("flow_name")
|
|
telegram_id = update.effective_user.id
|
|
|
|
if not flow_name:
|
|
logging.error("finalize_flow called without a flow_name in user_data.")
|
|
return
|
|
|
|
finalizer_func = FINALIZATION_MAP.get(flow_name)
|
|
if not finalizer_func:
|
|
logging.warning(f"No finalizer function found for flow: {flow_name}")
|
|
await update.message.reply_text("Flujo completado (sin acción final definida).")
|
|
return
|
|
|
|
# The final answer needs to be saved first
|
|
current_state_key = context.user_data.get("current_state")
|
|
if current_state_key:
|
|
flow_definition_path = os.path.join("conv-flows", f"{flow_name}.json")
|
|
with open(flow_definition_path, 'r') as f:
|
|
flow = json.load(f)
|
|
current_step = next((step for step in flow["steps"] if step["state"] == current_state_key), None)
|
|
if current_step:
|
|
variable_name = current_step.get("variable")
|
|
if variable_name:
|
|
context.user_data[variable_name] = update.message.text
|
|
|
|
|
|
success = finalizer_func(telegram_id, context.user_data)
|
|
|
|
if success:
|
|
await update.message.reply_text("¡Horario guardado con éxito! 👍")
|
|
else:
|
|
await update.message.reply_text("Ocurrió un error al guardar tu horario. Por favor, contacta a un administrador.")
|