Files
sufw-taetigkeitsnachweise/generate.py
T

155 lines
5.2 KiB
Python

from __future__ import annotations
import json
from pathlib import Path
import click
from src.taetigkeitsnachweis.errors import TaetigkeitsnachweisError
from src.taetigkeitsnachweis.logging_utils import configure_logging
from src.taetigkeitsnachweis.matcher import match_assignments
from src.taetigkeitsnachweis.parser import parse_allocation_records, parse_masterdata_records
from src.taetigkeitsnachweis.validator import validate_business_rules, validate_sources
from src.taetigkeitsnachweis.writer import (
build_employee_workbooks,
build_output_filename,
save_employee_workbooks,
)
def _load_config(project_root: Path) -> dict:
config_path = project_root / "config.json"
with config_path.open("r", encoding="utf-8") as config_file:
return json.load(config_file)
def _print_issues(issues: list, title: str) -> None:
if not issues:
return
click.echo(title)
for issue in issues:
click.echo(f"- [{issue.severity}] {issue.code}: {issue.message}")
def _print_preview(month: int, year: int, matched_assignments: list, planned_files: list[str]) -> None:
click.echo("=== Vorschau der ermittelten Werte ===")
click.echo(f"Berichtsmonat : {month:02d}/{year}")
click.echo(f"Aktive Faelle : {len(matched_assignments)}")
click.echo("--- Zu erzeugende Taetigkeitsnachweise ---")
for item in matched_assignments:
click.echo(
"- "
f"{item.allocation.employee_name} | "
f"{item.masterdata.funktion} | "
f"{item.foerderquote_percent:.2f}%"
)
click.echo("--- Geplante Ausgabedateien ---")
for file_name in planned_files:
click.echo(f"- {file_name}")
@click.command()
@click.option("--month", type=click.IntRange(1, 12), required=True)
@click.option("--year", type=click.IntRange(2000, 2100), required=True)
@click.option("--yes", is_flag=True, default=False, help="Skip interactive confirmation.")
def main(month: int, year: int, yes: bool) -> None:
configure_logging()
project_root = Path(__file__).resolve().parent
try:
config = _load_config(project_root)
source_issues = validate_sources(
config=config,
report_month=month,
report_year=year,
project_root=project_root,
)
_print_issues(source_issues, "=== Source validation ===")
if any(issue.severity == "error" for issue in source_issues):
raise click.ClickException("Source validation failed.")
allocation_records = parse_allocation_records(
config=config,
report_month=month,
report_year=year,
project_root=project_root,
)
masterdata_records = parse_masterdata_records(
config=config,
project_root=project_root,
)
matched_assignments, match_issues = match_assignments(
allocation_records=allocation_records,
masterdata_records=masterdata_records,
config=config,
)
_print_issues(match_issues, "=== Matching issues ===")
business_issues = validate_business_rules(
config=config,
report_month=month,
report_year=year,
allocation_records=allocation_records,
matched_assignments=matched_assignments,
project_root=project_root,
)
_print_issues(business_issues, "=== Business validation ===")
all_issues = [*match_issues, *business_issues]
if any(issue.severity == "error" for issue in all_issues):
raise click.ClickException("Validation failed after matching.")
filename_pattern = config["output"]["filename_pattern"]
unique_employees = sorted({item.allocation.employee_name for item in matched_assignments})
planned_files = [
build_output_filename(
filename_pattern=filename_pattern,
employee_name=employee_name,
report_year=year,
report_month=month,
)
for employee_name in unique_employees
]
_print_preview(
month=month,
year=year,
matched_assignments=matched_assignments,
planned_files=planned_files,
)
if not yes:
confirmed = click.confirm("Dateien jetzt schreiben?", default=False)
if not confirmed:
click.echo("Abbruch ohne Schreibzugriff.")
return
employee_workbooks = build_employee_workbooks(
config=config,
matched_assignments=matched_assignments,
report_month=month,
report_year=year,
project_root=project_root,
)
output_paths = save_employee_workbooks(
config=config,
employee_workbooks=employee_workbooks,
report_month=month,
report_year=year,
project_root=project_root,
)
click.echo("=== Generated files ===")
for output_path in output_paths:
click.echo(f"- {output_path}")
except TaetigkeitsnachweisError as exc:
raise click.ClickException(str(exc)) from exc
if __name__ == "__main__":
main()