Files
pointeuse-optimisator/app/ods_import.py
toto 6f6c7f154e Initial commit — décompte horaire
App web de suivi des heures de travail (FastAPI + HTMX + JSON plats).
- Saisie inline par semaine avec bouton ✓ par ligne
- Congés MA/AM/J avec coloration cellule et mise à jour live via OOB HTMX
- Import fichier ODS badgeuse
- Solde semaine et solde global recalculés à la volée
- Design "ledger" écru, DM Mono, zéro border-radius
- Déploiement Docker sur port 8000

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-24 15:08:32 +02:00

70 lines
2.0 KiB
Python

"""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