Auswählbare Mitarbeitermonate in separater Multiselektliste hinzugefügt
This commit is contained in:
1 parent
eb1dd45e57
commit
d027bedcb8
2 files changed
+116
-10
No files matched your search
@@ -15,9 +15,10 @@ Um das Programm zu starten: Doppelklick auf `Tätigkeitsnachweis-Generator.exe`
|
|||||||
- Nach Auswahl wird das Template sofort validiert
|
- Nach Auswahl wird das Template sofort validiert
|
||||||
- Angezeigt wird: Anzahl gefundener Zielfelder
|
- Angezeigt wird: Anzahl gefundener Zielfelder
|
||||||
3. **Mitarbeiter auswählen** – Multiselect-Liste aller gefundenen Mitarbeiter
|
3. **Mitarbeiter auswählen** – Multiselect-Liste aller gefundenen Mitarbeiter
|
||||||
- Standardmäßig sind alle ausgewählt
|
- Standardmäßig ist keiner ausgewählt
|
||||||
- Nicht selektierte Mitarbeiter werden bei der Generierung übersprungen
|
- Nicht selektierte Mitarbeiter werden bei der Generierung übersprungen
|
||||||
4. **"Tätigkeitsnachweise generieren"** klicken
|
4. **Mitarbeitermonate auswählen** – Multiselect-Liste aller verfügbaren Monate im Dokument. Vorselektiert sind die aktuell letzten beiden Monate.
|
||||||
|
5. **"Tätigkeitsnachweise generieren"** klicken
|
||||||
- Die generierten Dateien werden im `output/`-Ordner abgelegt
|
- Die generierten Dateien werden im `output/`-Ordner abgelegt
|
||||||
|
|
||||||
## Konfiguration
|
## Konfiguration
|
||||||
|
|||||||
+113
-8
@@ -30,6 +30,26 @@ from src.parser import parse_input_file, group_by_employee, get_unique_antragsnu
|
|||||||
from src.validator import validate_input_file, validate_template
|
from src.validator import validate_input_file, validate_template
|
||||||
from src.writer import generate_activity_reports
|
from src.writer import generate_activity_reports
|
||||||
|
|
||||||
|
|
||||||
|
def set_active_employee(employee_name: str):
|
||||||
|
"""Merkt die zuletzt angeklickte Person für die Monatsliste."""
|
||||||
|
st.session_state.active_month_employee = employee_name
|
||||||
|
|
||||||
|
|
||||||
|
def sync_employee_months(employee_name: str, months: list[str]):
|
||||||
|
"""Übernimmt Monats-Checkboxen vor dem nächsten UI-Rendern."""
|
||||||
|
st.session_state.employee_months[employee_name] = {
|
||||||
|
month for month in months
|
||||||
|
if st.session_state.get(f"month_{employee_name}_{month}", False)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def set_all_employee_months(employee_name: str, months: list[str], selected: bool):
|
||||||
|
"""Setzt alle Monats-Checkboxen einer Person gesammelt."""
|
||||||
|
st.session_state.employee_months[employee_name] = set(months) if selected else set()
|
||||||
|
for month in months:
|
||||||
|
st.session_state[f"month_{employee_name}_{month}"] = selected
|
||||||
|
|
||||||
# --- Seite konfigurieren ---
|
# --- Seite konfigurieren ---
|
||||||
st.set_page_config(
|
st.set_page_config(
|
||||||
page_title="Tätigkeitsnachweis-Generator",
|
page_title="Tätigkeitsnachweis-Generator",
|
||||||
@@ -72,6 +92,8 @@ if "cached_val_result" not in st.session_state:
|
|||||||
st.session_state.cached_val_result = None
|
st.session_state.cached_val_result = None
|
||||||
if "cached_tpl_result" not in st.session_state:
|
if "cached_tpl_result" not in st.session_state:
|
||||||
st.session_state.cached_tpl_result = None
|
st.session_state.cached_tpl_result = None
|
||||||
|
if "employee_months" not in st.session_state:
|
||||||
|
st.session_state.employee_months = {}
|
||||||
|
|
||||||
# --- Layout: zwei Spalten ---
|
# --- Layout: zwei Spalten ---
|
||||||
col1, col2 = st.columns(2)
|
col1, col2 = st.columns(2)
|
||||||
@@ -230,25 +252,95 @@ if st.session_state.input_validated and st.session_state.parsed_records:
|
|||||||
employees = get_unique_employees(st.session_state.parsed_records)
|
employees = get_unique_employees(st.session_state.parsed_records)
|
||||||
st.caption(f"{len(employees)} Mitarbeiter gefunden – wähle aus, für wen Tätigkeitsnachweise erstellt werden sollen:")
|
st.caption(f"{len(employees)} Mitarbeiter gefunden – wähle aus, für wen Tätigkeitsnachweise erstellt werden sollen:")
|
||||||
|
|
||||||
# "Alle" / "Keine" Buttons
|
# Monatsbezeichnungen für die kompakte Anzeige hinter dem Namen
|
||||||
btn_col1, btn_col2 = st.columns(2)
|
month_labels = {
|
||||||
if btn_col1.button("☑ Alle auswählen", use_container_width=True):
|
"01": "Jan", "02": "Feb", "03": "Mär", "04": "Apr",
|
||||||
|
"05": "Mai", "06": "Jun", "07": "Jul", "08": "Aug",
|
||||||
|
"09": "Sep", "10": "Okt", "11": "Nov", "12": "Dez",
|
||||||
|
}
|
||||||
|
|
||||||
|
all_groups = group_by_employee(st.session_state.parsed_records)
|
||||||
|
available_months = {}
|
||||||
|
for emp in employees:
|
||||||
|
months = sorted({
|
||||||
|
record.monat.split(".", 1)[0].zfill(2)
|
||||||
|
for record in all_groups.get(emp, [])
|
||||||
|
if record.monat and record.monat.split(".", 1)[0].isdigit()
|
||||||
|
}, key=lambda value: int(value))
|
||||||
|
available_months[emp] = months
|
||||||
|
if emp not in st.session_state.employee_months:
|
||||||
|
st.session_state.employee_months[emp] = set(months[-2:])
|
||||||
|
|
||||||
|
# Mitarbeiter- und Monatsliste teilen sich die verfügbare Breite.
|
||||||
|
employee_col, month_col = st.columns(2)
|
||||||
|
with employee_col:
|
||||||
|
employee_btn_col1, employee_btn_col2 = st.columns(2)
|
||||||
|
if employee_btn_col1.button("☑ Alle auswählen", use_container_width=True):
|
||||||
for emp in employees:
|
for emp in employees:
|
||||||
st.session_state[f"sel_{emp}"] = True
|
st.session_state[f"sel_{emp}"] = True
|
||||||
if btn_col2.button("☐ Keine auswählen", use_container_width=True):
|
if employee_btn_col2.button("☐ Keine auswählen", use_container_width=True):
|
||||||
for emp in employees:
|
for emp in employees:
|
||||||
st.session_state[f"sel_{emp}"] = False
|
st.session_state[f"sel_{emp}"] = False
|
||||||
|
|
||||||
# Mitarbeiter-Liste mit Rahmen
|
|
||||||
with st.container(border=True):
|
with st.container(border=True):
|
||||||
selected_employees = []
|
selected_employees = []
|
||||||
for emp in employees:
|
for emp in employees:
|
||||||
key = f"sel_{emp}"
|
key = f"sel_{emp}"
|
||||||
if key not in st.session_state:
|
if key not in st.session_state:
|
||||||
st.session_state[key] = True
|
st.session_state[key] = False
|
||||||
if st.checkbox(emp, key=key):
|
selected_months = st.session_state.employee_months.get(emp, set())
|
||||||
|
short_months = ", ".join(month_labels[m] for m in available_months[emp] if m in selected_months)
|
||||||
|
label = f"{emp} ({short_months})" if short_months else f"{emp} (**keine Monate**)"
|
||||||
|
if st.checkbox(
|
||||||
|
label,
|
||||||
|
key=key,
|
||||||
|
on_change=set_active_employee,
|
||||||
|
args=(emp,),
|
||||||
|
):
|
||||||
selected_employees.append(emp)
|
selected_employees.append(emp)
|
||||||
|
|
||||||
|
with month_col:
|
||||||
|
selected_for_months = st.session_state.get("active_month_employee")
|
||||||
|
if selected_for_months not in employees:
|
||||||
|
selected_for_months = None
|
||||||
|
|
||||||
|
month_btn_col1, month_btn_col2 = st.columns(2)
|
||||||
|
month_btn_col1.button(
|
||||||
|
"☑ Alle Monate",
|
||||||
|
use_container_width=True,
|
||||||
|
disabled=not selected_for_months,
|
||||||
|
on_click=set_all_employee_months,
|
||||||
|
args=(selected_for_months, available_months[selected_for_months], True) if selected_for_months else ("", [], True),
|
||||||
|
)
|
||||||
|
month_btn_col2.button(
|
||||||
|
"☐ Keine Monate",
|
||||||
|
use_container_width=True,
|
||||||
|
disabled=not selected_for_months,
|
||||||
|
on_click=set_all_employee_months,
|
||||||
|
args=(selected_for_months, available_months[selected_for_months], False) if selected_for_months else ("", [], False),
|
||||||
|
)
|
||||||
|
|
||||||
|
with st.container(border=True):
|
||||||
|
st.caption("Monate für den angeklickten Mitarbeiter")
|
||||||
|
if selected_for_months:
|
||||||
|
st.write(selected_for_months)
|
||||||
|
month_values = {}
|
||||||
|
for month in available_months[selected_for_months]:
|
||||||
|
month_key = f"month_{selected_for_months}_{month}"
|
||||||
|
if month_key not in st.session_state:
|
||||||
|
st.session_state[month_key] = month in st.session_state.employee_months[selected_for_months]
|
||||||
|
month_values[month] = st.checkbox(
|
||||||
|
f"{month_labels[month]} ({month})",
|
||||||
|
key=month_key,
|
||||||
|
on_change=sync_employee_months,
|
||||||
|
args=(selected_for_months, available_months[selected_for_months]),
|
||||||
|
)
|
||||||
|
st.session_state.employee_months[selected_for_months] = {
|
||||||
|
month for month, checked in month_values.items() if checked
|
||||||
|
}
|
||||||
|
else:
|
||||||
|
st.info("Einen Mitarbeiter links auswählen, um seine Monate festzulegen.")
|
||||||
|
|
||||||
st.caption(f"{len(selected_employees)} von {len(employees)} Mitarbeitern ausgewählt")
|
st.caption(f"{len(selected_employees)} von {len(employees)} Mitarbeitern ausgewählt")
|
||||||
else:
|
else:
|
||||||
selected_employees = []
|
selected_employees = []
|
||||||
@@ -283,7 +375,20 @@ if generate_clicked:
|
|||||||
else:
|
else:
|
||||||
# Filtere Records auf selektierte Mitarbeiter
|
# Filtere Records auf selektierte Mitarbeiter
|
||||||
all_groups = group_by_employee(st.session_state.parsed_records)
|
all_groups = group_by_employee(st.session_state.parsed_records)
|
||||||
selected_groups = {name: all_groups[name] for name in selected_employees if name in all_groups}
|
selected_groups = {
|
||||||
|
name: [
|
||||||
|
record for record in all_groups[name]
|
||||||
|
if record.monat.split(".", 1)[0].zfill(2)
|
||||||
|
in st.session_state.employee_months.get(name, set())
|
||||||
|
]
|
||||||
|
for name in selected_employees
|
||||||
|
if name in all_groups
|
||||||
|
}
|
||||||
|
selected_groups = {name: records for name, records in selected_groups.items() if records}
|
||||||
|
|
||||||
|
if not selected_groups:
|
||||||
|
st.error("Für die ausgewählten Mitarbeiter sind keine Monate ausgewählt.")
|
||||||
|
st.stop()
|
||||||
|
|
||||||
template_path = Path(app_config.template_dir) / selected_template
|
template_path = Path(app_config.template_dir) / selected_template
|
||||||
output_dir = Path(app_config.output_dir)
|
output_dir = Path(app_config.output_dir)
|
||||||
|
|||||||
Reference in new issue
Block a user