Spaces:
Sleeping
Sleeping
File size: 4,652 Bytes
7687049 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 | 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
@dataclass
class GeneratedArtifact:
kind: str # "collaboratori" | "manager"
person: str
docx_path: Path
pdf_path: Optional[Path] = None
notes: str = ""
@dataclass
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)
|