"""Parse badge-reader ODS files and return structured data.""" from datetime import datetime, time from odf.opendocument import load from odf.table import Table, TableRow, TableCell from odf.text import P def _cell_text(cell) -> str: parts = [] for p in cell.getElementsByType(P): for node in p.childNodes: if hasattr(node, "data"): parts.append(node.data) return "".join(parts).strip() def _parse_time(val: str) -> str | None: """Return HH:MM or None. Ignores zero-times (formula placeholders).""" val = val.strip() if not val: return None for fmt in ("%H:%M:%S", "%H:%M"): try: t = datetime.strptime(val, fmt) hhmm = t.strftime("%H:%M") if hhmm == "00:00": return None return hhmm except ValueError: pass return None def _parse_date(val: str) -> str | None: """Return YYYY-MM-DD or None.""" val = val.strip() for fmt in ("%d/%m/%Y", "%Y-%m-%d"): try: return datetime.strptime(val, fmt).strftime("%Y-%m-%d") except ValueError: pass return None def parse_ods(path: str) -> list[dict]: """Return list of pointage dicts from all sheets in the ODS file.""" doc = load(path) sheets = doc.spreadsheet.getElementsByType(Table) records = [] for sheet in sheets: rows = sheet.getElementsByType(TableRow) for row in rows: cells = row.getElementsByType(TableCell) if len(cells) < 5: continue date_val = _cell_text(cells[0]) date = _parse_date(date_val) if not date: continue records.append({ "date": date, "matin_entree": _parse_time(_cell_text(cells[1])), "matin_sortie": _parse_time(_cell_text(cells[2])), "aprem_entree": _parse_time(_cell_text(cells[3])), "aprem_sortie": _parse_time(_cell_text(cells[4])), }) return records