Spaces:
Sleeping
Sleeping
| from __future__ import annotations | |
| import re | |
| from dataclasses import dataclass | |
| from pathlib import Path | |
| from typing import Iterable, List, Optional, Tuple, Dict | |
| import pandas as pd | |
| from .docx_fill import fill_template | |
| from .io import load_pair | |
| class GeneratedArtifact: | |
| kind: str # "collaboratori" | "manager" | |
| person: str | |
| docx_path: Path | |
| pdf_path: Optional[Path] = None | |
| notes: str = "" | |
| class GenerateResult: | |
| produced: List[GeneratedArtifact] | |
| warnings: List[str] | |
| def _safe_filename(name: str) -> str: | |
| name = str(name).strip() | |
| name = re.sub(r"\s+", " ", name) | |
| name = re.sub(r"[^A-Za-z0-9 _-]+", "", name) | |
| return name.replace(" ", "_") | |
| def list_people(auto_path: Path, valut_path: Path) -> List[str]: | |
| """Return UNION of names found in AUTO and VALUT (dedup).""" | |
| df_auto, df_val = load_pair(auto_path, valut_path) | |
| a = set(df_auto.get("Nome e cognome", [])) | |
| b = set(df_val.get("Nome e cognome", [])) | |
| names = sorted({x for x in a.union(b) if isinstance(x, str) and x.strip()}) | |
| return names | |
| def _generate_one( | |
| *, | |
| kind: str, | |
| person_name: str, | |
| df_auto: pd.DataFrame, | |
| df_val: pd.DataFrame, | |
| template_path: Path, | |
| output_dir: Path, | |
| workdir: Path, | |
| make_pdf: bool, | |
| ) -> GeneratedArtifact: | |
| base = f"REPORT_{kind}_{_safe_filename(person_name)}" | |
| out_docx = output_dir / f"{base}.docx" | |
| out_pdf = output_dir / f"{base}.pdf" | |
| notes = "" | |
| # Fill template | |
| fill_template( | |
| template_path=template_path, | |
| out_docx=out_docx, | |
| df_auto=df_auto, | |
| df_valut=df_val, | |
| person_name=person_name, | |
| kind=kind, | |
| workdir=workdir, | |
| ) | |
| pdf_path: Optional[Path] = None | |
| if make_pdf: | |
| from .pdf_convert import docx_to_pdf | |
| try: | |
| docx_to_pdf(out_docx, out_pdf) | |
| pdf_path = out_pdf | |
| except Exception as e: | |
| notes = f"PDF non generato: {e}" | |
| pdf_path = None | |
| return GeneratedArtifact(kind=kind, person=person_name, docx_path=out_docx, pdf_path=pdf_path, notes=notes) | |
| def generate_selected( | |
| *, | |
| collab_auto: Optional[Path], | |
| collab_valut: Optional[Path], | |
| collab_template: Optional[Path], | |
| manager_auto: Optional[Path], | |
| manager_valut: Optional[Path], | |
| manager_template: Optional[Path], | |
| selected_collaboratori: Iterable[str], | |
| selected_manager: Iterable[str], | |
| output_dir: Path, | |
| make_pdf: bool, | |
| ) -> GenerateResult: | |
| produced: List[GeneratedArtifact] = [] | |
| warnings: List[str] = [] | |
| output_dir.mkdir(parents=True, exist_ok=True) | |
| workdir = output_dir / "_work" | |
| workdir.mkdir(parents=True, exist_ok=True) | |
| if collab_auto and collab_valut and collab_template: | |
| df_auto, df_val = load_pair(collab_auto, collab_valut) | |
| for person in selected_collaboratori: | |
| try: | |
| produced.append( | |
| _generate_one( | |
| kind="collaboratori", | |
| person_name=person, | |
| df_auto=df_auto, | |
| df_val=df_val, | |
| template_path=collab_template, | |
| output_dir=output_dir, | |
| workdir=workdir / "collaboratori", | |
| make_pdf=make_pdf, | |
| ) | |
| ) | |
| except Exception as e: | |
| warnings.append(f"[Collaboratori] {person}: errore generazione ({e})") | |
| else: | |
| if any([collab_auto, collab_valut, collab_template]): | |
| warnings.append("Collaboratori: mancano uno o più file (AUTO/VALUT/TEMPLATE).") | |
| if manager_auto and manager_valut and manager_template: | |
| df_auto, df_val = load_pair(manager_auto, manager_valut) | |
| for person in selected_manager: | |
| try: | |
| produced.append( | |
| _generate_one( | |
| kind="manager", | |
| person_name=person, | |
| df_auto=df_auto, | |
| df_val=df_val, | |
| template_path=manager_template, | |
| output_dir=output_dir, | |
| workdir=workdir / "manager", | |
| make_pdf=make_pdf, | |
| ) | |
| ) | |
| except Exception as e: | |
| warnings.append(f"[Manager] {person}: errore generazione ({e})") | |
| else: | |
| if any([manager_auto, manager_valut, manager_template]): | |
| warnings.append("Manager: mancano uno o più file (AUTO/VALUT/TEMPLATE).") | |
| return GenerateResult(produced=produced, warnings=warnings) | |