fix: Stellenanteil in Prozentangabe und jeweiliges Monatsende als Datum eintragen
This commit is contained in:
1 parent
0d390f79b4
commit
b05849e673
4 files changed
+38
-19
No files matched your search
@@ -1,11 +1,12 @@
|
|||||||
[
|
[
|
||||||
{"source_field": "Antragsnummer", "target_cell": "B3", "format": null},
|
{"source_field": "Antragsnummer", "target_cell": "B3", "format": null},
|
||||||
{"source_field": "Name", "target_cell": "B17", "format": null},
|
{"source_field": "Name", "target_cell": "B17", "format": null},
|
||||||
{"source_field": "Stellenanteil in %", "target_cell": "R17", "format": "%.2f"},
|
{"source_field": "Stellenanteil in %", "target_cell": "R17", "format": null},
|
||||||
{"source_field": "Qualifikation", "target_cell": "B21", "format": null},
|
{"source_field": "Qualifikation", "target_cell": "B21", "format": null},
|
||||||
{"source_field": "Monat (MM.JJ)", "target_cell": "R21", "format": null},
|
{"source_field": "Monat (MM.JJ)", "target_cell": "R21", "format": null},
|
||||||
{"source_field": "Funktion", "target_cell": "B25", "format": null},
|
{"source_field": "Funktion", "target_cell": "B25", "format": null},
|
||||||
{"source_field": "Tätigkeit", "target_cell": "B31", "format": null},
|
{"source_field": "Tätigkeit", "target_cell": "B31", "format": null},
|
||||||
{"source_field": "Ort", "target_cell": "B95", "format": null},
|
{"source_field": "Ort", "target_cell": "B95", "format": null},
|
||||||
|
{"source_field": "Ort 2", "target_cell": "B103", "format": null},
|
||||||
{"source_field": "Datum", "target_cell": "J95", "format": null}
|
{"source_field": "Datum", "target_cell": "J95", "format": null}
|
||||||
]
|
]
|
||||||
+1
-1
@@ -11,7 +11,7 @@ class EmployeeRecord:
|
|||||||
antragsnummer: str
|
antragsnummer: str
|
||||||
qualifikation: str
|
qualifikation: str
|
||||||
funktion: str
|
funktion: str
|
||||||
stellenanteil: float
|
stellenanteil: str
|
||||||
monat: str # z. B. "01.2025"
|
monat: str # z. B. "01.2025"
|
||||||
taetigkeit: str
|
taetigkeit: str
|
||||||
id: Optional[int] = None
|
id: Optional[int] = None
|
||||||
|
|||||||
+25
-11
@@ -17,16 +17,6 @@ def _to_text(value: Any) -> str:
|
|||||||
return str(value).strip()
|
return str(value).strip()
|
||||||
|
|
||||||
|
|
||||||
def _to_float(value: Any, field_name: str) -> float:
|
|
||||||
if value is None or str(value).strip() == "":
|
|
||||||
return 0.0
|
|
||||||
text = str(value).strip().replace(",", ".")
|
|
||||||
try:
|
|
||||||
return float(text)
|
|
||||||
except ValueError:
|
|
||||||
return 0.0
|
|
||||||
|
|
||||||
|
|
||||||
def _to_int_or_none(value: Any) -> Optional[int]:
|
def _to_int_or_none(value: Any) -> Optional[int]:
|
||||||
if value is None or str(value).strip() == "":
|
if value is None or str(value).strip() == "":
|
||||||
return None
|
return None
|
||||||
@@ -36,6 +26,29 @@ def _to_int_or_none(value: Any) -> Optional[int]:
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def _to_percent_string(value: Any) -> str:
|
||||||
|
"""Wandelt einen Prozentwert in einen String ohne %-Zeichen um.
|
||||||
|
|
||||||
|
Excel speichert Prozentwerte als Dezimalbruch (50 % = 0.5).
|
||||||
|
Falls der Rohwert eine Zahl ≤ 1 ist, wird er als Excel-Prozentwert
|
||||||
|
interpretiert und mit 100 multipliziert.
|
||||||
|
"""
|
||||||
|
if value is None or str(value).strip() == "":
|
||||||
|
return ""
|
||||||
|
# Falls es bereits ein String mit %-Zeichen ist
|
||||||
|
if isinstance(value, str):
|
||||||
|
return value.strip().rstrip("% ")
|
||||||
|
# Numerischer Wert: Excel-Prozentwert (0.5 = 50 %) oder Ganzzahl (50 = 50 %)
|
||||||
|
if isinstance(value, (int, float)):
|
||||||
|
if 0 < value <= 1:
|
||||||
|
return str(int(value * 100))
|
||||||
|
if value == 0:
|
||||||
|
return "0"
|
||||||
|
# Wert > 1: bereits als Ganzzahl gemeint (z. B. 50)
|
||||||
|
return str(int(value))
|
||||||
|
return str(value).strip()
|
||||||
|
|
||||||
|
|
||||||
def _build_column_map(schema: list[FieldSchema]) -> dict[str, int]:
|
def _build_column_map(schema: list[FieldSchema]) -> dict[str, int]:
|
||||||
"""Baut ein Mapping von field_name → 0-basierter Spaltenindex."""
|
"""Baut ein Mapping von field_name → 0-basierter Spaltenindex."""
|
||||||
col_map: dict[str, int] = {}
|
col_map: dict[str, int] = {}
|
||||||
@@ -78,7 +91,8 @@ def parse_input_file(
|
|||||||
|
|
||||||
qualifikation = _to_text(row[col_map.get("Qualifikation", 0)]) if len(row) > col_map.get("Qualifikation", 0) else ""
|
qualifikation = _to_text(row[col_map.get("Qualifikation", 0)]) if len(row) > col_map.get("Qualifikation", 0) else ""
|
||||||
funktion = _to_text(row[col_map.get("Funktion", 0)]) if len(row) > col_map.get("Funktion", 0) else ""
|
funktion = _to_text(row[col_map.get("Funktion", 0)]) if len(row) > col_map.get("Funktion", 0) else ""
|
||||||
stellenanteil = _to_float(row[col_map.get("Stellenanteil in %", 0)], "Stellenanteil in %") if len(row) > col_map.get("Stellenanteil in %", 0) else 0.0
|
stellenanteil_raw = row[col_map.get("Stellenanteil in %", 0)] if len(row) > col_map.get("Stellenanteil in %", 0) else None
|
||||||
|
stellenanteil = _to_percent_string(stellenanteil_raw)
|
||||||
monat = _to_text(row[col_map.get("Monat (MM.JJ)", 0)]) if len(row) > col_map.get("Monat (MM.JJ)", 0) else ""
|
monat = _to_text(row[col_map.get("Monat (MM.JJ)", 0)]) if len(row) > col_map.get("Monat (MM.JJ)", 0) else ""
|
||||||
taetigkeit = _to_text(row[col_map.get("Tätigkeit", 0)]) if len(row) > col_map.get("Tätigkeit", 0) else ""
|
taetigkeit = _to_text(row[col_map.get("Tätigkeit", 0)]) if len(row) > col_map.get("Tätigkeit", 0) else ""
|
||||||
record_id = _to_int_or_none(row[col_map.get("ID", 0)]) if len(row) > col_map.get("ID", 0) else None
|
record_id = _to_int_or_none(row[col_map.get("ID", 0)]) if len(row) > col_map.get("ID", 0) else None
|
||||||
|
|||||||
+10
-6
@@ -5,7 +5,7 @@ Es werden KEINE Sheets programmatisch erzeugt oder kopiert –
|
|||||||
ausschließlich die vorhandenen Sheets mit Daten befüllt.
|
ausschließlich die vorhandenen Sheets mit Daten befüllt.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from datetime import date
|
import calendar
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
from openpyxl import load_workbook
|
from openpyxl import load_workbook
|
||||||
@@ -95,18 +95,22 @@ def _fill_sheet(ws, record: EmployeeRecord, employee_name: str, field_map: dict)
|
|||||||
value = record.funktion
|
value = record.funktion
|
||||||
elif source_field == "Tätigkeit":
|
elif source_field == "Tätigkeit":
|
||||||
value = record.taetigkeit
|
value = record.taetigkeit
|
||||||
elif source_field == "Ort":
|
elif source_field in ("Ort", "Ort 2"):
|
||||||
value = "Dresden"
|
value = "Dresden"
|
||||||
elif source_field == "Datum":
|
elif source_field == "Datum":
|
||||||
value = date.today().strftime("%d.%m.%Y")
|
parts = record.monat.split(".")
|
||||||
|
if len(parts) == 2:
|
||||||
|
month = int(parts[0])
|
||||||
|
year = int(parts[1])
|
||||||
|
last_day = calendar.monthrange(year, month)[1]
|
||||||
|
value = f"{last_day:02d}.{month:02d}.{year}"
|
||||||
|
else:
|
||||||
|
value = ""
|
||||||
else:
|
else:
|
||||||
continue
|
continue
|
||||||
formatted = _format_value(value, m.format)
|
formatted = _format_value(value, m.format)
|
||||||
_set_cell_value(ws, m.target_cell, formatted)
|
_set_cell_value(ws, m.target_cell, formatted)
|
||||||
|
|
||||||
# Datum zusätzlich ins Unterschriftsfeld
|
|
||||||
_set_cell_value(ws, "J95", date.today().strftime("%d.%m.%Y"))
|
|
||||||
|
|
||||||
|
|
||||||
def generate_activity_reports(
|
def generate_activity_reports(
|
||||||
employee_records: dict[str, list[EmployeeRecord]],
|
employee_records: dict[str, list[EmployeeRecord]],
|
||||||
|
|||||||
Reference in new issue
Block a user