"""Business logic: compute worked hours and expected hours per day/week.""" from datetime import datetime, timedelta def hhmm_to_minutes(val: str | None) -> int: if not val: return 0 h, m = val.split(":") return int(h) * 60 + int(m) def minutes_to_hhmm(minutes: int) -> str: sign = "-" if minutes < 0 else "" minutes = abs(minutes) return f"{sign}{minutes // 60}h{minutes % 60:02d}" def heures_travaillees(p: dict) -> int: """Return worked minutes for a pointage row.""" matin = max(0, hhmm_to_minutes(p["matin_sortie"]) - hhmm_to_minutes(p["matin_entree"])) aprem = max(0, hhmm_to_minutes(p["aprem_sortie"]) - hhmm_to_minutes(p["aprem_entree"])) # only count if entry AND exit are present if not (p["matin_entree"] and p["matin_sortie"]): matin = 0 if not (p["aprem_entree"] and p["aprem_sortie"]): aprem = 0 return matin + aprem def heures_dues(date_str: str, conges: list[dict], heures_jour_min: int) -> int: """Return expected minutes for a date, accounting for vacations.""" d = datetime.strptime(date_str, "%Y-%m-%d").date() # Weekend = no hours due if d.weekday() >= 5: return 0 conges_date = {c["type"] for c in conges if c["date"] == date_str} if "jour" in conges_date: return 0 if "matin" in conges_date and "aprem" in conges_date: return 0 half = heures_jour_min // 2 if "matin" in conges_date or "aprem" in conges_date: return half return heures_jour_min def compute_week(pointages: list[dict], conges: list[dict], heures_jour_min: int) -> dict: """Compute totals for a list of pointages (one week).""" total_travaille = 0 total_du = 0 jours = [] for p in pointages: travaille = heures_travaillees(p) du = heures_dues(p["date"], conges, heures_jour_min) delta = travaille - du total_travaille += travaille total_du += du jours.append({ **p, "travaille_min": travaille, "du_min": du, "delta_min": delta, "travaille": minutes_to_hhmm(travaille), "du": minutes_to_hhmm(du), "delta": minutes_to_hhmm(delta), "conge": {c["type"] for c in conges if c["date"] == p["date"]}, }) return { "jours": jours, "total_travaille": minutes_to_hhmm(total_travaille), "total_du": minutes_to_hhmm(total_du), "solde": minutes_to_hhmm(total_travaille - total_du), "solde_min": total_travaille - total_du, }