diff --git a/src/wce_crm/backend/backend.py b/src/wce_crm/backend/backend.py index a6e669e..8ad2161 100644 --- a/src/wce_crm/backend/backend.py +++ b/src/wce_crm/backend/backend.py @@ -82,7 +82,7 @@ def _transform_for_gui_output( return q.collect() -def comp_search_choices() -> tuple[tuple[str, int], ...]: +def initrec_comp_search_choices() -> tuple[tuple[str, int], ...]: # TODO no reload functionality logger.debug("[Call backend] comp_search_choices") q = db.DF_CRM_MASTER.lazy() @@ -97,7 +97,7 @@ def comp_search_choices() -> tuple[tuple[str, int], ...]: return tuple(zip(df["dedupl"], df["ma_id"])) -def comp_search_get_info( +def initrec_comp_search_get_info( ma_id: int, ) -> CompanyInfo: logger.debug("[Call backend] comp_search_get_info") @@ -109,7 +109,7 @@ def comp_search_get_info( return cast(CompanyInfo, df.row(0, named=True)) -def contact_person_search_choices( +def initrec_comp_contact_person_search_choices( ma_id: int | None, use_both_names: bool, ) -> tuple[tuple[str, int], ...]: @@ -137,7 +137,7 @@ def contact_person_search_choices( return tuple(zip(df["dedupl"], df["an_id"])) -def contact_person_search_get_info( +def initrec_comp_contact_person_search_get_info( an_id: int, ) -> ContactPersonInfo: logger.debug("[Call backend] contact_person_search_get_info") @@ -149,36 +149,32 @@ def contact_person_search_get_info( return cast(ContactPersonInfo, df.row(0, named=True)) -def insert_initial_recording( +def initrec_insert_initial_recording( data: dict[str, Any], ) -> None: logger.debug("[Call backend] insert_initial_recording") - stmt = db.grunderfassung_unternehmen.insert().values(data) + stmt = db.grunderfassung.insert().values(data) with db.ENGINE.begin() as conn: conn.execute(stmt) -def update_initial_recording( +def initrec_update_initial_recording( id_: int, data: dict[str, Any], ) -> None: logger.debug("[Call backend] update_initial_recording") stmt = ( - db.grunderfassung_unternehmen.update() - .where(db.grunderfassung_unternehmen.c.erfassung_id == id_) - .values(data) + db.grunderfassung.update().where(db.grunderfassung.c.erfassung_id == id_).values(data) ) with db.ENGINE.begin() as conn: conn.execute(stmt) -def get_initial_recording( +def initrec_get_initial_recording( id_: int, ) -> dict[str, Any]: logger.debug("[Call backend] get_initial_recording") - stmt = db.grunderfassung_unternehmen.select().where( - db.grunderfassung_unternehmen.c.erfassung_id == id_ - ) + stmt = db.grunderfassung.select().where(db.grunderfassung.c.erfassung_id == id_) with db.ENGINE.begin() as conn: ret = conn.execute(stmt) @@ -192,18 +188,19 @@ def get_initial_recording( @dc.dataclass(slots=True) class FrontpageCompany: erfassung_id: int - ma_id: int + # ma_id: int name: str Metadaten_aktualisierung: datetime.datetime + is_company: bool -def get_company_list() -> list[FrontpageCompany]: +def front_get_company_list() -> list[FrontpageCompany]: logger.debug("[Call backend] get_company_list") stmt = sql.select( - db.grunderfassung_unternehmen.c.erfassung_id, - db.grunderfassung_unternehmen.c.Partnersuche__un_suche, - db.grunderfassung_unternehmen.c.Metadaten_aktualisierung, - ).order_by(db.grunderfassung_unternehmen.c.Metadaten_aktualisierung.desc()) + db.grunderfassung.c.erfassung_id, + db.grunderfassung.c.Partnersuche__un_suche, + db.grunderfassung.c.Metadaten_aktualisierung, + ).order_by(db.grunderfassung.c.Metadaten_aktualisierung.desc()) with db.ENGINE.connect() as conn: res = conn.execute(stmt) @@ -216,9 +213,21 @@ def get_company_list() -> list[FrontpageCompany]: datetime_akt = cast(datetime.datetime, entry[2]) datetime_akt = datetime_akt.astimezone() - comp_info = comp_search_get_info(ma_id) - name = comp_info["ma_unternehmensname"] + name: str = "PLATZHALTER INDIVIDUAL" + is_company: bool = False + if ma_id is not None: + comp_info = initrec_comp_search_get_info(ma_id) + name = comp_info["ma_unternehmensname"] + is_company = True - front_page_companies.append(FrontpageCompany(erfassung_id, ma_id, name, datetime_akt)) + # front_page_companies.append(FrontpageCompany(erfassung_id, ma_id, name, datetime_akt)) + front_page_companies.append( + FrontpageCompany( + erfassung_id=erfassung_id, + name=name, + Metadaten_aktualisierung=datetime_akt, + is_company=is_company, + ) + ) return front_page_companies diff --git a/src/wce_crm/gui.py b/src/wce_crm/gui.py index f7f96a7..454f452 100644 --- a/src/wce_crm/gui.py +++ b/src/wce_crm/gui.py @@ -3,30 +3,19 @@ from __future__ import annotations import copy import dataclasses as dc import datetime -import enum -import json import pickle import re import sys import traceback -import uuid from collections import defaultdict from collections.abc import Container, Iterable, Sequence from pathlib import Path from pprint import pformat -from typing import Annotated, Any, Final, Protocol, TypeAlias, TypedDict, TypeVar, cast +from typing import Any, Final, Protocol, TypeAlias, TypedDict, TypeVar, cast from typing_extensions import override -import babel from pydantic import ( - AwareDatetime, - BaseModel, - ConfigDict, - EmailStr, - Field, ValidationError, - field_validator, - model_validator, ) from PySide6.QtCore import ( QDate, @@ -65,6 +54,13 @@ from PySide6.QtWidgets import ( import wce_crm.constants from wce_crm.backend import backend as be_init_rec +from wce_crm.data_models import COLUMN_SEP, FlatBaseModel, Grunderfassung +from wce_crm.form_defs import ( + INITREC_COMP, + INITREC_PERSON, + FormField, + FormFieldType, +) from wce_crm.logging import ( logger_auto_form, logger_get_data, @@ -103,12 +99,12 @@ QSS = """ """ DROPDOWN_DEFAULT: Final[str] = "--- Bitte wählen ---" DYNAMIC_LIST_KEY_PATTERN: Final[re.Pattern] = re.compile(r"-\[(\d+)\]") -COLUMN_SEP: Final[str] = "__" DATETIME_FMT: Final[str] = "%d.%m.%Y %H:%M:%S" DATE_FMT: Final[str] = "%d.%m.%Y" -def save_pydantic_model_dict_db( +# TODO check removal +def _save_pydantic_model_dict_db( model: FlatBaseModel, path: Path | None = None, ) -> None: @@ -123,7 +119,8 @@ def save_pydantic_model_dict_db( pickle.dump(export, f) -def load_pydantic_model_dict_db( +# TODO check removal +def _load_pydantic_model_dict_db( path: Path | None = None, ) -> dict[str, Any]: if path is None: @@ -164,197 +161,25 @@ def unmerge_dict_to_list( return [dict(zip(keys, row)) for row in zip(*value_lists)] -class FlatBaseModel(BaseModel): - """ - Optimised Pydantic base class, which parses JSON strings and column - separators recursively and correctly - """ - - @classmethod - def _recursive_parse_json(cls, data: Any) -> Any: - """look for JSON list strings and parse them""" - if isinstance(data, str) and data.startswith("[") and data.endswith("]"): - try: - parsed = json.loads(data) - # Falls die Liste selbst wieder konvertiert werden muss (z.B. Sub-Dicts) - return cls._recursive_parse_json(parsed) - except json.JSONDecodeError: - return data - elif isinstance(data, dict): - return {k: cls._recursive_parse_json(v) for k, v in data.items()} - elif isinstance(data, list): - return [cls._recursive_parse_json(item) for item in data] - return data - - @classmethod - def _recursive_unflatten(cls, data: Any) -> Any: - """building nested structure using column spearator sequence""" - if isinstance(data, dict): - unflattened_level = {} - for key, value in data.items(): - if COLUMN_SEP in key: - parts = key.split(COLUMN_SEP) - aktuell = unflattened_level - for part in parts[:-1]: - if part not in aktuell or not isinstance(aktuell[part], dict): - aktuell[part] = {} - aktuell = aktuell[part] - aktuell[parts[-1]] = value - else: - unflattened_level[key] = value - - return {k: cls._recursive_unflatten(v) for k, v in unflattened_level.items()} - - elif isinstance(data, list): - return [cls._recursive_unflatten(item) for item in data] - - return data - - @model_validator(mode="before") - @classmethod - def __unflatten_input(cls, data: Any) -> Any: # type: ignore - """entry control: prepare flat DB/GUI data for Pydantic""" - if not isinstance(data, dict): - return data - - # setp 1: convert all JSON-Strings to lists - json_parsed_data = cls._recursive_parse_json(data) - # step 2: build nested structure based on defined separator sequence - final_nested_data = cls._recursive_unflatten(json_parsed_data) - - return final_nested_data - - def to_db(self, *args, **kwargs) -> dict[str, Any]: - """output for DB: flat, lists as JSON-Strings""" - nested = super().model_dump(*args, **kwargs) - return self.__flatten_dict(nested, serialize_lists=True) - - def to_gui(self, *args, **kwargs) -> dict[str, Any]: - """output for GUI: flat, but lists remain Python lists""" - nested = super().model_dump(*args, **kwargs) - return self.__flatten_dict(nested, serialize_lists=False) - - @classmethod - def __flatten_dict( - cls, - nested_dict: dict, - parent_key: str = "", - serialize_lists: bool = True, - ) -> dict[str, Any]: - """recursive function to flatten the structure (for outputs)""" - items = [] - for k, v in nested_dict.items(): - new_key = f"{parent_key}{COLUMN_SEP}{k}" if parent_key else k - - if isinstance(v, dict): - items.extend(cls.__flatten_dict(v, new_key, serialize_lists).items()) - elif isinstance(v, list): - processed_list = [] - for item in v: - if isinstance(item, dict): - processed_list.append( - cls.__flatten_dict(item, serialize_lists=serialize_lists) - ) - else: - processed_list.append(item) - - if serialize_lists: - items.append((new_key, json.dumps(processed_list, default=_parse_json))) - else: - items.append((new_key, processed_list)) - else: - items.append((new_key, v)) - return dict(items) - - -def _parse_json(value: Any) -> str: - if isinstance(value, datetime.date): - return value.isoformat() - elif isinstance(value, datetime.datetime): - return value.isoformat() - else: - raise TypeError - - -@dc.dataclass(slots=True) -class CountryList: - iso_to_country: dict[str, str] - for_dropdown: Sequence[tuple[str, str]] - - -def get_country_list_german() -> CountryList: - locale = babel.Locale("de", "DE") - countries: list[tuple[str, str]] = [] - iso_to_country: dict[str, str] = {} - - for iso_code, country_name in locale.territories.items(): - if len(iso_code) == 2 and not iso_code.isdigit(): - countries.append((country_name, iso_code)) - iso_to_country[iso_code] = country_name - - countries.sort(key=lambda x: x[0]) - - return CountryList( - iso_to_country=iso_to_country, - for_dropdown=tuple(countries), - ) - - -def get_list_germany_states() -> CountryList: - states: list[tuple[str, str]] = [] - short_code_to_name: dict[str, str] = {} - - STATE_LIST: list[tuple[str, str]] = [ - ("Bayern", "BY"), - ("Niedersachen", "NI"), - ("Baden-Württemberg", "BW"), - ("Berlin", "BE"), - ("Brandenburg", "BB"), - ("Bremen", "HB"), - ("Hamburg", "HH"), - ("Hessen", "HE"), - ("Mecklenburg", "MV"), - ("Nordrhein-Westfalen", "NW"), - ("Rheinland-Pfalz", "RP"), - ("Saarland", "SL"), - ("Sachsen", "SN"), - ("Sachsen-Anhalt", "ST"), - ("Schleswig-Holstein", "SH"), - ("Thüringen", "TH"), - ] - STATE_LIST.sort(key=lambda x: x[1]) - - for country_name, code in STATE_LIST: - states.append((country_name, code)) - short_code_to_name[code] = country_name - - return CountryList( - iso_to_country=short_code_to_name, - for_dropdown=tuple(states), - ) - - -COUNTRY_LIST: Final[CountryList] = get_country_list_german() -GERMAN_STATE_LIST: Final[CountryList] = get_list_germany_states() - - -def get_leafs(data): +# TODO check removal +def _get_leafs(data): if isinstance(data, dict): for value in data.values(): - yield from get_leafs(value) + yield from _get_leafs(value) elif isinstance(data, (list, tuple, set)): for item in data: - yield from get_leafs(item) + yield from _get_leafs(item) else: yield data -def get_leaf_dicts(data): +# TODO check removal +def _get_leaf_dicts(data): if isinstance(data, dict): has_inner_dicts = False for value in data.values(): - for inner_dict in get_leaf_dicts(value): + for inner_dict in _get_leaf_dicts(value): has_inner_dicts = True yield inner_dict @@ -363,7 +188,7 @@ def get_leaf_dicts(data): elif isinstance(data, (list, tuple, set)): for item in data: - yield from get_leaf_dicts(item) + yield from _get_leaf_dicts(item) def pprint_registry(widget_registry: WidgetRegistry) -> None: @@ -387,110 +212,6 @@ def pformat_registry(widget_registry: WidgetRegistry) -> str: return "\n".join(lines) -class FormFieldType(enum.StrEnum): - GROUP = enum.auto() - TEXT = enum.auto() - LONGTEXT = enum.auto() - DATE = enum.auto() - DATETIME = enum.auto() - DROPDOWN = enum.auto() - EXTENDED_DROPDOWN = enum.auto() - DYNAMIC_LIST = enum.auto() - DYNAMIC_DROPDOWN_NUMERIC = enum.auto() - DYNAMIC_DROPDOWN_OPTION = enum.auto() - TEXT_SEARCH = enum.auto() - CUSTOM = enum.auto() - TEXT_DATE = enum.auto() - TEXT_DATETIME = enum.auto() - - -@dc.dataclass(slots=True) -class DropdownOption: - label: str - _data: dc.InitVar[Any | None] = None - data: Any = dc.field(init=False) - - def __post_init__( - self, - _data: Any | None, - ) -> None: - if _data is None: - self.data = self.label - else: - self.data = _data - - -@dc.dataclass(slots=True) -class FormField: - label: str - type: FormFieldType - children: Sequence[FormField] = dc.field(default_factory=list) - parent: FormField | None = None - required: bool = False - placeholder: str = "" - fill_value: str = "" - readonly: bool = False - options: dc.InitVar[Sequence[tuple[str, Any]]] = tuple() - dropdown_options: Sequence[DropdownOption] = dc.field(default=tuple(), init=False) - key: str = "" - tooltip: str = "" - info: str = "" - custom_widget: str = "" - init_label: str = dc.field(init=False) - ignore_get_data: bool = False - trigger_value: str = "" - enable_uuid_key: bool = False - - def __post_init__( - self, - options: Sequence[tuple[str, Any]], - ) -> None: - if not self.key and self.enable_uuid_key: - self.key = str(uuid.uuid4()) - - self.label = self.label.strip() - self.init_label = self.label.replace("*", "").replace(":", "") - if not self.label.endswith(":") and self.type is not FormFieldType.GROUP: - self.label += ":" - if self.required: - self.label += "*" - - if self.type is FormFieldType.CUSTOM and not self.custom_widget: - raise ValueError("Custom widget must be named using parameter >custom_widget<") - elif self.type is FormFieldType.CUSTOM and self.custom_widget not in CUSTOM_WIDGETS: - raise KeyError( - ( - f"Custom widget >{self.custom_widget}< is not a known member " - "of the custom widget registry" - ) - ) - - if self.type in (FormFieldType.DROPDOWN, FormFieldType.EXTENDED_DROPDOWN): - self.dropdown_options = tuple(DropdownOption(op[0], op[1]) for op in options) - - if self.type is FormFieldType.DYNAMIC_DROPDOWN_OPTION and not self.trigger_value: - raise ValueError( - "Dynamic Dropdown Option Widget must have a defined option or decision value" - ) - - if self.children: - self.required = self.required or any((child.required for child in self.children)) - for child in self.children: - child.parent = self - - def enhanced_label( - self, - add_text: str, - ) -> str: - enhanced_label = self.init_label + f" {add_text}" - if not enhanced_label.endswith(":") and self.type is not FormFieldType.GROUP: - enhanced_label += ":" - if self.required: - enhanced_label += "*" - - return enhanced_label - - class CustomForm(Protocol): def get_form_data(self) -> dict[str, Any]: ... @@ -1172,164 +893,6 @@ def validate_form_data( return errors -class Grunderfassung_Unternehmen(FlatBaseModel): - # default in SQLAlchemy with lambda and timezone-aware datetime) - Metadaten_erstellung: AwareDatetime | None = None - Metadaten_aktualisierung: AwareDatetime | None = None # see above - Metadaten_nutzer: str | None - Grunderfassung_fallnummer: str - Grunderfassung_notiz: str | None - - Partnersuche: Grunderfassung_PartnerSuche - Projektrelevanz: Grunderfassung_Projektrelevanz - Kontaktperson: Grunderfassung_Kontaktperson - Stammdaten: Grunderfassung_Stammdaten - WeitereInfos: Grunderfassung_WeitereInfos - Schulbildung: list[Grunderfassung_Schulbildung] - HoehereBildung: list[Grunderfassung_HoehereBildung] - Arbeitserfahrung: list[Grunderfassung_Arbeitserfahrung] - Sprachkenntnisse: list[Grunderfassung_Sprachen] - - -class Grunderfassung_PartnerSuche(BaseModel): - model_config = ConfigDict(str_strip_whitespace=True) - - un_suche: int - person_suche: int - kanal_aufmerksamkeit: str | None - - -class Grunderfassung_Projektrelevanz(BaseModel): - model_config = ConfigDict(str_strip_whitespace=True) - - relevanz: str - foerderperiode: str | None = None - - -class Grunderfassung_Kontaktperson(BaseModel): - model_config = ConfigDict(str_strip_whitespace=True) - - KP_name_partner: str | None - KP_titel: str | None - KP_anrede_anschrift: str | None - KP_name: str | None - KP_vorname: str | None - KP_festnetznummer: str | None - KP_mobilfunknummer: str | None - KP_email: EmailStr | None - KP_funktion_beziehung: str | None - KP_adresse: str | None - - -ValidAge = Annotated[int, Field(ge=0, le=99)] - - -class Grunderfassung_Stammdaten(BaseModel): - model_config = ConfigDict(str_strip_whitespace=True) - - titel: str | None - anrede_anschrift: str - name: str - vorname: str | None - geburtsdatum: datetime.date | None - herkunftsland: str - staatsangehoerigkeit: str | None - rueckkehrer: bool | None - aufenthaltsort: str | None - strasse: str | None - hausnummer: str | None - PLZ: str | None - ort: str | None - bundesland: str | None - land: str | None - festnetznummer: str | None - mobilfunknummer: str | None - email: EmailStr | None - familienstand: str | None - anzahl_kinder: Grunderfassung_Stammdaten_AnzahlKinder - - @field_validator("rueckkehrer", mode="before") - @classmethod - def str_to_bool(cls, value: Any) -> Any: - if isinstance(value, str): - value = value.strip().lower() - - if value == "ja": - return True - elif value == "nein": - return False - - raise ValueError("Wert muss 'ja', 'nein', True oder False sein.") - - return value - - -class Grunderfassung_Stammdaten_AnzahlKinder(BaseModel): - model_config = ConfigDict(str_strip_whitespace=True) - - anzahl: int | None - alter: list[ValidAge | None] | None = None - - -class Grunderfassung_WeitereInfos(BaseModel): - model_config = ConfigDict(str_strip_whitespace=True) - - WI_deutsch_sprache: str | None - WI_aufenthaltstitel: str | None - WI_gueltigkeit_aufenthaltstitel: datetime.date | None - WI_arbeitsstatus: str | None - WI_meldung_institution: str | None - - -class Grunderfassung_Schulbildung(BaseModel): - model_config = ConfigDict(str_strip_whitespace=True) - - SB_abschluss: str | None - SB_abschlussgrad: str | None - SB_schule: str | None - SB_ort: str | None - SB_land: str | None - SB_abschlussjahr: str | None - SB_bemerkungsfeld: str | None - - -class Grunderfassung_HoehereBildung(BaseModel): - model_config = ConfigDict(str_strip_whitespace=True) - - HB_anerkennung: str | None - HB_abschlussgrad: str | None - HB_abschlussgrad_dokument: str | None - HB_organisation: str | None - HB_beruf: str | None - HB_land: str | None - HB_ort: str | None - HB_abschlussjahr: str | None - HB_bemerkungsfeld: str | None - - -class Grunderfassung_Arbeitserfahrung(BaseModel): - model_config = ConfigDict(str_strip_whitespace=True) - - AE_branche: str | None - AE_bezeichnung: str | None - AE_funktion: str | None - AE_unternehmen: str | None - AE_land: str | None - AE_zeitspanne: str | None - AE_beschaeftigungsart: str | None - AE_bemerkungsfeld: str | None - - -class Grunderfassung_Sprachen(BaseModel): - model_config = ConfigDict(str_strip_whitespace=True) - - SP_sprache: str | None - SP_niveau: str | None - SP_nachweis: str | None - SP_art_nachweis: str | None = None - SP_datum_nachweis: datetime.date | None = None - - class Grunderfassung_SuchWidget(CustomWidget): def __init__( self, @@ -1479,7 +1042,7 @@ class Grunderfassung_SuchWidget(CustomWidget): def update_company_data(self) -> None: self.company_search_input.clear() self.company_search_input.addItem(DROPDOWN_DEFAULT, None) - search_choices = be_init_rec.comp_search_choices() + search_choices = be_init_rec.initrec_comp_search_choices() for item, db_index in search_choices: self.company_search_input.addItem(item, db_index) self.company_search_input.setCurrentIndex(-1) @@ -1490,7 +1053,7 @@ class Grunderfassung_SuchWidget(CustomWidget): ) -> None: self.person_search_input.clear() self.person_search_input.addItem(DROPDOWN_DEFAULT, None) - search_choices = be_init_rec.contact_person_search_choices(ma_id, True) + search_choices = be_init_rec.initrec_comp_contact_person_search_choices(ma_id, True) for item, db_index in search_choices: self.person_search_input.addItem(item, db_index) self.person_search_input.setCurrentIndex(0) @@ -1503,7 +1066,7 @@ class Grunderfassung_SuchWidget(CustomWidget): if ma_id is None or index == (-1): self._clear_company_fields() return - data = be_init_rec.comp_search_get_info( + data = be_init_rec.initrec_comp_search_get_info( ma_id=ma_id, ) self.fill_out_company(data) @@ -1518,7 +1081,7 @@ class Grunderfassung_SuchWidget(CustomWidget): self._clear_person_fields() return - data = be_init_rec.contact_person_search_get_info( + data = be_init_rec.initrec_comp_contact_person_search_get_info( an_id=an_id, ) self.fill_out_person(data) @@ -1783,7 +1346,7 @@ class AutoForm(QWidget): logger_auto_form.debug( "Loaded data dict:\n%s Passing to Pydantic...", pformat(loaded_data) ) - model = Grunderfassung_Unternehmen(**loaded_data) + model = Grunderfassung(**loaded_data) logger_auto_form.debug("Loaded to Pydantic.") logger_auto_form.debug("Convert to GUI structure...") form_data = model.to_gui() @@ -2492,9 +2055,9 @@ class NewEntrySelect_view(QWidget): btn_person.setFixedWidth(300) btn_person.setFixedHeight(40) btn_person.clicked.connect(lambda: self.person_requested.emit()) - btn_person.clicked.connect( - lambda: logger_gui.info("[Grunderfassung: Dummy Individualperson] Person gewählt") - ) + # btn_person.clicked.connect( + # lambda: logger_gui.info("[Grunderfassung: Dummy Individualperson] Person gewählt") + # ) layout.addWidget(back_btn) layout.addSpacing(15) @@ -2503,834 +2066,38 @@ class NewEntrySelect_view(QWidget): layout.addWidget(btn_person) +CONFIG_GRUNDERFASSUNG_UNTERNEHMEN: Final[AutoFormConfig] = AutoFormConfig( + model=Grunderfassung, + data_insert=be_init_rec.initrec_insert_initial_recording, + data_update=be_init_rec.initrec_update_initial_recording, + data_get=be_init_rec.initrec_get_initial_recording, + ignored_keys=( + "Metadaten_erstellung", + "Metadaten_aktualisierung", + "Metadaten_wiedereintrittsdatum", + ), + form_fields=INITREC_COMP, +) + +CONFIG_GRUNDERFASSUNG_PERSONEN: Final[AutoFormConfig] = AutoFormConfig( + model=Grunderfassung, + data_insert=be_init_rec.initrec_insert_initial_recording, + data_update=be_init_rec.initrec_update_initial_recording, + data_get=be_init_rec.initrec_get_initial_recording, + ignored_keys=( + "Metadaten_erstellung", + "Metadaten_aktualisierung", + "Partnersuche", + ), + form_fields=INITREC_PERSON, +) + CUSTOM_WIDGETS: Final[dict[str, type[CustomWidget]]] = { "grunderfassung_suche": Grunderfassung_SuchWidget, } -FORM_FIELDS_SEARCH_HEAD = [ - FormField( - "Suche", - FormFieldType.EXTENDED_DROPDOWN, - required=True, - key="un_suche", - placeholder="Suche...", - ), - FormField( - "Name Unternehmen/Netzwerkpartner", - FormFieldType.TEXT, - required=False, - key="un_name", - readonly=True, - info="ma_unternehmensname", - ), - FormField( - "Straße", - FormFieldType.TEXT, - required=False, - key="un_straße", - readonly=True, - info="ma_strasse", - ), - FormField( - "Hausnummer", - FormFieldType.TEXT, - required=False, - key="un_hausnummer", - readonly=True, - info="ma_hausnummer", - ), - FormField( - "PLZ", - FormFieldType.TEXT, - required=False, - key="un_PLZ", - readonly=True, - info="ma_plz", - ), - FormField( - "Ort", - FormFieldType.TEXT, - required=False, - key="un_ort", - readonly=True, - info="ma_ort", - ), - FormField( - "Suche Ansprechpartner", - FormFieldType.EXTENDED_DROPDOWN, - required=True, - key="person_suche", - placeholder="Suche...", - ), - FormField( - "Titel", - FormFieldType.TEXT, - required=False, - key="person_titel", - readonly=True, - info="an_titel", - ), - FormField( - "Anrede", - FormFieldType.TEXT, - required=False, - key="person_anrede", - readonly=True, - info="an_anrede", - ), - FormField( - "Name", - FormFieldType.TEXT, - required=False, - key="person_name", - readonly=True, - info="an_nachname", - ), - FormField( - "Vorname", - FormFieldType.TEXT, - required=False, - key="person_vorname", - readonly=True, - info="an_vorname", - ), - FormField( - "Telefon", - FormFieldType.TEXT, - required=False, - key="person_telefon", - readonly=True, - info="an_festnetz", - ), - FormField( - "Mobil", - FormFieldType.TEXT, - required=False, - key="person_mobilfunk", - readonly=True, - info="an_mobil", - ), - FormField( - "E-Mail", - FormFieldType.TEXT, - required=False, - key="person_email", - readonly=True, - info="an_mail", - ), - FormField( - "Funktion im Unternehmen", - FormFieldType.TEXT, - required=False, - key="person_funktion", - readonly=True, - info="an_position", - ), - FormField( - "Wie sind Sie auf uns aufmerksam geworden?", - FormFieldType.DROPDOWN, - required=False, - key="kanal_aufmerksamkeit", - options=[ - ("Agentur für Arbeit", None), - ("Ausländerbehörde", None), - ("Jobcenter", None), - ("Freunde/Familie", None), - ("Anerkennungsstelle", None), - ("Beratungsstelle", None), - ("Internet", None), - ("Arbeitgeber", None), - ("Bildungsdienstleister", None), - ("Welcome-Mappe", None), - ("Newsletter WFE", None), - ("Newsletter RM", None), - ("Sonstiges", None), - ], - ), -] - - -FORM_FIELDS_CONTACT_PERSON = [ - FormField( - "Name Unternehmen/Netzwerkpartner (vorausgefüllt von Suche)", - FormFieldType.TEXT, - key="KP_name_partner", - required=False, - placeholder="Text wird nach gewähltem Unternehmen angezeigt", - readonly=True, - ), - FormField( - "Titel", - FormFieldType.TEXT, - key="KP_titel", - required=False, - tooltip=( - "* nur wenn anrufende Person oder kontaktaufnehmende Person " - "nicht die zu beratende Person ist" - ), - ), - FormField( - "Anrede_Anschrift", - FormFieldType.TEXT, - key="KP_anrede_anschrift", - required=True, - ), - FormField( - "Name", - FormFieldType.TEXT, - key="KP_name", - required=True, - ), - FormField( - "Vorname", - FormFieldType.TEXT, - key="KP_vorname", - required=False, - ), - FormField( - "Festnetznummer", - FormFieldType.TEXT, - key="KP_festnetznummer", - required=False, - ), - FormField( - "Mobilfunknummer", - FormFieldType.TEXT, - key="KP_mobilfunknummer", - required=False, - ), - FormField( - "E-Mail", - FormFieldType.TEXT, - key="KP_email", - required=False, - ), - FormField( - "Funktion/Beziehung zur beratenden Person", - FormFieldType.TEXT, - key="KP_funktion_beziehung", - required=False, - ), - FormField( - "Adresse", - FormFieldType.LONGTEXT, - key="KP_adresse", - required=False, - ), -] - -FORM_FIELDS_MASTER_DATA = [ - FormField( - "Titel", - FormFieldType.TEXT, - key="titel", - required=False, - tooltip=( - "* nur wenn anrufende Person oder kontaktaufnehmende Person " - "nicht die zu beratende Person ist" - ), - ), - FormField( - "Anrede", - FormFieldType.TEXT, - key="anrede_anschrift", - required=True, - ), - FormField( - "Name", - FormFieldType.TEXT, - key="name", - required=True, - ), - FormField( - "Vorname", - FormFieldType.TEXT, - key="vorname", - required=False, - ), - FormField( - "Geburtsdatum", - FormFieldType.DATE, - key="geburtsdatum", - required=False, - tooltip=( - "* Wichtig zu erfragen, da u.a. Mindestgehaltsschwelle davon abhängt " - "(Regelung bei Ü45 Jahre)" - ), - ), - FormField( - "Herkunftsland", - FormFieldType.EXTENDED_DROPDOWN, - key="herkunftsland", - required=True, - placeholder="Suche...", - options=COUNTRY_LIST.for_dropdown, - tooltip=("* Wichtig zu erfragen aufgrund eventueller EU-Freizügigkeitsregelung"), - ), - FormField( - "Staatsangehörigkeit", - FormFieldType.EXTENDED_DROPDOWN, - key="staatsangehoerigkeit", - required=False, - placeholder="Suche...", - options=COUNTRY_LIST.for_dropdown, - tooltip=("* Wichtig zu erfragen aufgrund eventueller EU-Freizügigkeitsregelung"), - ), - FormField( - "Rückkehrer", - FormFieldType.DROPDOWN, - key="rueckkehrer", - required=False, - options=[("ja", None), ("nein", None)], - tooltip=("* Wichtig zu erfragen aufgrund eventueller EU-Freizügigkeitsregelung"), - ), - FormField( - "Wo befindet sich die Person?", - FormFieldType.DROPDOWN, - key="aufenthaltsort", - required=True, - options=[("Inland", None), ("Ausland EU/EWR", None), ("Ausland Drittstaat", None)], - ), - FormField( - "Straße", - FormFieldType.TEXT, - key="strasse", - required=False, - ), - FormField( - "Hausnummer", - FormFieldType.TEXT, - key="hausnummer", - required=False, - ), - FormField( - "PLZ", - FormFieldType.TEXT, - key="PLZ", - required=False, - ), - FormField( - "Ort", - FormFieldType.TEXT, - key="ort", - required=False, - ), - FormField( - "Bundesland", - FormFieldType.DROPDOWN, - key="bundesland", - required=False, - options=GERMAN_STATE_LIST.for_dropdown, - tooltip=("nur wenn Inland angegeben"), - ), - FormField( - "Land", - FormFieldType.EXTENDED_DROPDOWN, - key="land", - required=False, - placeholder="Suche...", - options=COUNTRY_LIST.for_dropdown, - ), - FormField( - "Festnetznummer", - FormFieldType.TEXT, - key="festnetznummer", - required=False, - ), - FormField( - "Mobilfunknummer", - FormFieldType.TEXT, - key="mobilfunknummer", - required=False, - ), - FormField( - "E-Mail", - FormFieldType.TEXT, - key="email", - required=False, - ), - FormField( - "Familienstand", - FormFieldType.TEXT, - key="familienstand", - required=False, - tooltip="* Wichtig zu erfragen aufgrund Lebensunterhaltssicherung", - ), - FormField( - "Anzahl Kinder", - FormFieldType.DYNAMIC_DROPDOWN_NUMERIC, - required=False, - tooltip="* Wichtig zu erfragen aufgrund Lebensunterhaltssicherung", - key="anzahl_kinder", - children=[ - FormField( - "Anzahl Kinder", - FormFieldType.DROPDOWN, - required=False, - options=[(str(x), None) for x in range(11)], - tooltip="* Wichtig zu erfragen aufgrund Lebensunterhaltssicherung", - key="anzahl", - children=[ - FormField("Alter Kind", FormFieldType.TEXT, key="alter"), - ], - ), - ], - ), -] - -FORM_FIELDS_ADDITIONAL_DATA = [ - FormField( - "Deutsch als Kommunikationssprache", - FormFieldType.DROPDOWN, - required=False, - key="WI_deutsch_sprache", - options=[ - ("nein", None), - ("ja, als Muttersprache", None), - ("ja, als Fremdsprache", None), - ], - ), - FormField( - "Aufenthaltstitel", - FormFieldType.DROPDOWN, - required=False, - key="WI_aufenthaltstitel", - options=[ - ("anerkannter Flüchtling §§ 22 - 26 AufenthG", None), - ("Aufenthaltsgestattung §55 AufenthG", None), - ("Blaue Karte EU § 18g AufenthG", None), - ("BüMA (Bescheinigung über Meldung als Asylsuchender)", None), - ("Duldung § 60 AufenthG", None), - ("bisher kein Aufenthaltstitel", None), - ("Deutscher", None), - ("familiäre Gründe §§ 27 - 36 AufenthG", None), - ("Niederlassungserlaubnis §9 AufenthG", None), - ("Staatsbürger EUR/EWR/CH", None), - ("Aufenthalt für Ausbildung §§ 16 - 17 AufenthG", None), - ("Aufenthalt für Erwerbstätigkeit §§ 18- 21 AufenthG", None), - ("Chancenaufenthaltsrecht §104c AufenthG", None), - ("Sonstiges", None), - ], - tooltip="sofern nicht bekannt, unbedingt einfordern", - ), - FormField( - "Gültigkeit Aufenthaltsstatus", - FormFieldType.DATE, - required=False, - key="WI_gueltigkeit_aufenthaltstitel", - ), - FormField( - "Arbeitsstatus aktuell", - FormFieldType.DROPDOWN, - required=False, - key="WI_arbeitsstatus", - options=[ - ("Arbeitslos", None), - ("Ausbildung/Qualifizierung Inland", None), - ("geringfügig beschäftigt", None), - ("in Anstellung Inland", None), - ("selbstständig Inland", None), - ("Ausbildung/Qualifizierung Ausland", None), - ("in Anstellung Ausland", None), - ("selbstständig Ausland", None), - ], - ), - FormField( - "Gemeldet bei Institutionen ", - FormFieldType.DROPDOWN, - required=False, - key="WI_meldung_institution", - options=[ - ("bei keiner", None), - ("Jobcenter mit Leistungsbezug", None), - ("Jobcenter ohne Leistungsbezug", None), - ("Sozialamt mit Leistungsbezug", None), - ("Sozialamt ohne Leistungsbezug", None), - ("Agentur für Arbeit mit Leistungsbezug", None), - ("Agentur für Arbeit ohne Leistungsbezug", None), - ], - ), -] - -FORM_FIELDS_SCHOOL = [ - FormField("Abschluss", FormFieldType.TEXT, required=False, key="SB_abschluss"), - FormField( - "Abschlussgrad laut Dokument", - FormFieldType.TEXT, - required=False, - key="SB_abschlussgrad", - ), - FormField( - "Schule", - FormFieldType.TEXT, - required=False, - key="SB_schule", - ), - FormField( - "Ort", - FormFieldType.TEXT, - required=False, - key="SB_ort", - ), - FormField( - "Land", - FormFieldType.EXTENDED_DROPDOWN, - key="SB_land", - required=False, - placeholder="Suche...", - options=COUNTRY_LIST.for_dropdown, - ), - FormField("Abschlussjahr", FormFieldType.TEXT, required=False, key="SB_abschlussjahr"), - FormField( - "Bemerkungsfeld", - FormFieldType.TEXT, - required=False, - key="SB_bemerkungsfeld", - ), -] - -FORM_FIELDS_HIGHER_EDUCATION = [ - FormField( - "Anerkennung", - FormFieldType.TEXT, - required=False, - key="HB_anerkennung", - ), - FormField( - "Abschlussgrad", - FormFieldType.TEXT, - required=False, - key="HB_abschlussgrad", - tooltip=( - "bitte den Titel eingeben z.B. Doktor, Diplom oder " - "Betriebswirt (Fachschulabschluss)" - ), - ), - FormField( - "Abschlussgrad laut Dokument", - FormFieldType.TEXT, - required=False, - key="HB_abschlussgrad_dokument", - ), - FormField( - "Hochschule / Ausbildungsbetrieb / Berufsschule", - FormFieldType.TEXT, - required=False, - key="HB_organisation", - ), - FormField( - "Beruf / Fachrichtung", - FormFieldType.TEXT, - required=False, - key="HB_beruf", - tooltip=( - "bitte spezifizieren z.B. Allgemeinmedizin, Ingenieur Maschinenbau, " - "technischer Betriebswirt Datenverarbeitung" - ), - ), - FormField( - "Land", - FormFieldType.EXTENDED_DROPDOWN, - key="HB_land", - required=False, - placeholder="Suche...", - options=COUNTRY_LIST.for_dropdown, - ), - FormField( - "Ort", - FormFieldType.TEXT, - required=False, - key="HB_ort", - ), - FormField( - "Abschlussjahr", - FormFieldType.TEXT, - required=False, - key="HB_abschlussjahr", - ), - FormField( - "Bemerkungsfeld", - FormFieldType.TEXT, - required=False, - key="HB_bemerkungsfeld", - tooltip="z.B. Promotionen oder den Studiengang angeben", - ), -] - -FORM_FIELDS_WORK_EXPERIENCE = [ - FormField( - "Branche", - FormFieldType.DROPDOWN, - required=False, - key="AE_branche", - options=[ - (part, None) - for part in ( - "Metallerzeugung & -bearbeitung", - "Elektro, Energie, Chemie", - "IT & Software", - "Kunststoff, Papier, Textil", - "Logistik, Verkehr, Transport", - "Handwerk, Bau, Grüne Berufe", - "Gesundheit & Pflege", - "Tourismus & Gastronomie", - "Handel", - "Bildung & Soziales", - "Entwicklung, Planung, Qualität", - "Administration, Finanzen, Verwaltung", - "Marketing, Design, Vertrieb", - "Einkauf, Lager, Wartung", - "Sonstige", - "Keine Schwerpunkte, branchenübergreifende Rekrutierung", - ) - ], - ), - FormField( - "Berufsbezeichnung/Tätigkeit", - FormFieldType.TEXT, - required=False, - key="AE_bezeichnung", - ), - FormField( - "Funktion", - FormFieldType.DROPDOWN, - required=False, - key="AE_funktion", - options=[ - ("Auszubildender", None), - ("Fachkraft", None), - ("Hilfskraft", None), - ("Akademiker", None), - ("Führungskraft", None), - ("Praktikant", None), - ("FSJ/BFD", None), - ("Elternzeit", None), - ("Sabbatical", None), - ("Sonstiges", None), - ], - ), - FormField( - "Unternehmen", - FormFieldType.TEXT, - required=False, - key="AE_unternehmen", - ), - FormField( - "Land", - FormFieldType.EXTENDED_DROPDOWN, - key="AE_land", - required=False, - placeholder="Suche...", - options=COUNTRY_LIST.for_dropdown, - ), - FormField( - "Zeitspanne (von ... bis ...)", - FormFieldType.TEXT, - required=False, - key="AE_zeitspanne", - ), - FormField( - "Beschäftsigungsart", - FormFieldType.DROPDOWN, - required=False, - key="AE_beschaeftigungsart", - options=[ - ("Vollzeit", None), - ("Teilzeit", None), - ("Sonstiges", None), - ], - tooltip="Minijob, Praktikum, Wehrdienst, soziale Dienste", - ), - FormField( - "Bemerkungsfeld", - FormFieldType.TEXT, - required=False, - key="AE_bemerkungsfeld", - ), -] - -FORM_FIELDS_LANGUAGES = [ - FormField( - "Sprache", - FormFieldType.TEXT, - required=False, - key="SP_sprache", - ), - FormField( - "Niveau", - FormFieldType.DROPDOWN, - required=False, - key="SP_niveau", - options=[ - ("A1", None), - ("A2", None), - ("B1", None), - ("B2", None), - ("C1", None), - ("C2", None), - ], - ), - FormField( - "Nachweis", - FormFieldType.DYNAMIC_DROPDOWN_OPTION, - key="", - trigger_value="vorhanden", - children=[ - FormField( - "Nachweis", - FormFieldType.DROPDOWN, - required=False, - options=[("vorhanden", None), ("nicht vorhanden", None)], - key="SP_nachweis", - children=[ - FormField( - "Art des Nachweises", - FormFieldType.TEXT, - required=False, - key="SP_art_nachweis", - ), - FormField( - "Datum des Nachweises", - FormFieldType.DATE, - required=False, - key="SP_datum_nachweis", - ), - ], - ), - ], - ), -] - - -FORM_FIELDS = [ - FormField( - "Ersteintrag Datum", - FormFieldType.TEXT_DATETIME, - required=False, - key="Metadaten_erstellung", - readonly=True, - ignore_get_data=True, - ), - FormField( - "Aktualisierung Datum", - FormFieldType.TEXT_DATETIME, - required=False, - key="Metadaten_aktualisierung", - readonly=True, - ignore_get_data=True, - ), - FormField( - "Aktualisierung Nutzer", - FormFieldType.TEXT, - required=False, - key="Metadaten_nutzer", - readonly=True, - ), - FormField( - "Fallnummer", - FormFieldType.TEXT, - required=True, - key="Grunderfassung_fallnummer", - ), - FormField( - "Notizen", - FormFieldType.LONGTEXT, - required=False, - key="Grunderfassung_notiz", - ), - FormField( - "Suche", - FormFieldType.CUSTOM, - custom_widget="grunderfassung_suche", - key="Partnersuche", - children=FORM_FIELDS_SEARCH_HEAD, - ), - FormField( - "Status && Projektrelevanz", - FormFieldType.GROUP, - key="Projektrelevanz", - children=[ - FormField( - "Projektrelevanz", - FormFieldType.DYNAMIC_DROPDOWN_OPTION, - key="", - trigger_value="ja", - children=[ - FormField( - "Relevanz", - FormFieldType.DROPDOWN, - required=True, - options=[("ja", None), ("nein", None)], - key="relevanz", - children=[ - FormField( - "Förderperiode", FormFieldType.TEXT, key="foerderperiode" - ), - ], - ), - ], - ), - ], - ), - FormField( - "Daten Kontaktperson", - FormFieldType.GROUP, - key="Kontaktperson", - children=FORM_FIELDS_CONTACT_PERSON, - ), - FormField( - "Stammdaten", - FormFieldType.GROUP, - key="Stammdaten", - children=FORM_FIELDS_MASTER_DATA, - ), - FormField( - "Weitere Informationen", - FormFieldType.GROUP, - key="WeitereInfos", - children=FORM_FIELDS_ADDITIONAL_DATA, - ), - FormField( - "Schulbildung", - FormFieldType.DYNAMIC_LIST, - children=FORM_FIELDS_SCHOOL, - key="Schulbildung", - ), - FormField( - "Studium/Ausbildung", - FormFieldType.DYNAMIC_LIST, - children=FORM_FIELDS_HIGHER_EDUCATION, - key="HoehereBildung", - ), - FormField( - "Arbeitserfahrung", - FormFieldType.DYNAMIC_LIST, - children=FORM_FIELDS_WORK_EXPERIENCE, - key="Arbeitserfahrung", - ), - FormField( - "Sprachkenntnisse", - FormFieldType.DYNAMIC_LIST, - children=FORM_FIELDS_LANGUAGES, - key="Sprachkenntnisse", - ), -] - -CONFIG_GRUNDERFASSUNG_UNTERNEHMEN: Final[AutoFormConfig] = AutoFormConfig( - model=Grunderfassung_Unternehmen, - data_insert=be_init_rec.insert_initial_recording, - data_update=be_init_rec.update_initial_recording, - data_get=be_init_rec.get_initial_recording, - ignored_keys=( - "Metadaten_erstellung", - "Metadaten_aktualisierung", - ), - form_fields=FORM_FIELDS, -) - - -class PageFormCompany(QWidget): +class Page_InitRecCompany(QWidget): back_main_requested = Signal() # back to main page back_requested = Signal() # back button save_clicked_form = Signal() # form saved (data changed for front page) @@ -3459,6 +2226,135 @@ class PageFormCompany(QWidget): self.auto_form.reset_form() +class Page_InitRecPerson(QWidget): + back_main_requested = Signal() # back to main page + back_requested = Signal() # back button + save_clicked_form = Signal() # form saved (data changed for front page) + + def __init__(self): + super().__init__() + # Hauptlayout der Seite + outer_layout = QHBoxLayout(self) + vert_layout = QVBoxLayout() + # main_layout.setContentsMargins(0, 0, 0, 0) + outer_layout.addStretch(1) + outer_layout.addLayout(vert_layout, stretch=100) + # outer_layout.addWidget(scroll_area, stretch=100) + outer_layout.addStretch(1) + # Optional: Damit der Container oben am Rand klebt + outer_layout.setAlignment(Qt.AlignmentFlag.AlignTop) + + # --- HEADER --- + header_container = QWidget() + header_container.setMinimumWidth(700) + header_container.setMaximumWidth(1000) + header_container.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed) + header_layout = QVBoxLayout(header_container) + header_layout.setContentsMargins(0, 0, 0, 10) + + back_btn_main = QPushButton("← Zurück zur Übersicht") + back_btn_main.clicked.connect(lambda: self.back_main_requested.emit()) + back_btn_main.setSizePolicy(QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Fixed) + back_btn_main.setMinimumWidth(200) + back_btn_main.setMaximumWidth(200) + back_btn_step = QPushButton("← Zurück") + back_btn_step.clicked.connect(lambda: self.back_requested.emit()) + back_btn_step.setSizePolicy(QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Fixed) + back_btn_step.setMinimumWidth(200) + back_btn_step.setMaximumWidth(200) + + title = QLabel("Grunderfassung Individualperson") + title.setStyleSheet("font-size: 20px; font-weight: bold;") + + header_layout.setSpacing(5) + header_layout.addWidget(back_btn_step) + header_layout.addWidget(back_btn_main) + header_layout.addWidget(title) + vert_layout.addWidget(header_container) + + # --- MAIN CONTENT --- + container = QWidget() + # SCROLL AREA + scroll_area = QScrollArea() + scroll_area.setWidgetResizable(True) + scroll_area.setMinimumWidth(700) + scroll_area.setMaximumWidth(1000) + scroll_area.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding) + # optional: remove frame to look more modern + scroll_area.setFrameShape(QFrame.Shape.NoFrame) + scroll_area.setWidget(container) + + vert_layout.addWidget(scroll_area) + + container_layout = QVBoxLayout(container) + container_layout.setContentsMargins(0, 0, 0, 0) + + # --- AUTO FORM LAYOUT --- + container_layout.addSpacing(20) + self.auto_form = AutoForm(cfg=CONFIG_GRUNDERFASSUNG_PERSONEN) + container_layout.addWidget(self.auto_form) + self.auto_form.save_clicked_form.connect(lambda: self.save_clicked_form.emit()) + + container_layout.addSpacing(15) + + # --- CUSTOM LOGIC --- + # ** fill 'Kontaktperson -> Namen Unternehmen' + # search_res = search_widgets_by_key(self.auto_form.widget_registry, "Partnersuche") + # assert len(search_res) == 1 + # search_widget = cast(Grunderfassung_SuchWidget, search_res[0]["widget"]) + # self.search_widget_trigger = cast( + # QLineEdit, search_widget.company_widgets["ma_unternehmensname"] + # ) + # text_widget_set = search_widgets_by_key( + # self.auto_form.widget_registry, f"Kontaktperson{COLUMN_SEP}KP_name_partner" + # ) + # assert len(text_widget_set) == 1 + # self.text_widget_set = cast(QLineEdit, text_widget_set[0]["widget"]) + # self.search_widget_trigger.textChanged.connect( + # self._custom_set_company_name_contact_person + # ) + + # ** 'Bundesland' only if 'Inland' selected in 'Stammdaten' + person_location = search_widgets_by_key( + self.auto_form.widget_registry, f"Stammdaten{COLUMN_SEP}aufenthaltsort" + ) + assert len(person_location) == 1 + self.person_location = cast(QComboBox, person_location[0]["widget"]) + assert isinstance(self.person_location, QComboBox) + self.person_location.currentIndexChanged.connect(self._custom_county_selection) + + selection_county = search_widgets_by_key( + self.auto_form.widget_registry, f"Stammdaten{COLUMN_SEP}bundesland" + ) + assert len(selection_county) == 1 + self.selection_county = cast(QComboBox, selection_county[0]["widget"]) + assert isinstance(self.selection_county, QComboBox) + self.selection_county.setProperty("styleClass", "stempel") + self.selection_county.setEnabled(False) + + # def _custom_set_company_name_contact_person(self, value: str) -> None: + # self.text_widget_set.setText(str(value)) + + def _custom_county_selection(self, idx: int) -> None: + value = self.person_location.itemData(idx) + if value == "Inland": + self.selection_county.setEnabled(True) + self.selection_county.setProperty("styleClass", "") + self.selection_county.style().unpolish(self.selection_county) + self.selection_county.style().polish(self.selection_county) + self.selection_county.update() + else: + self.selection_county.setCurrentIndex(0) + self.selection_county.setEnabled(False) + self.selection_county.setProperty("styleClass", "stempel") + self.selection_county.style().unpolish(self.selection_county) + self.selection_county.style().polish(self.selection_county) + self.selection_county.update() + + def reset_form(self) -> None: + self.auto_form.reset_form() + + def clear_layout( layout: QLayout | None, ) -> None: @@ -3499,14 +2395,21 @@ class MainWindow(QMainWindow): # SITE: add new entries for 'Grunderfassung' self.new_entry_select = NewEntrySelect_view() self.new_entry_select.back_requested.connect(self.show_main_page) - self.new_entry_select.company_requested.connect(self.show_company_page) + self.new_entry_select.company_requested.connect(self.show_page_initrec_company) + self.new_entry_select.person_requested.connect(self.show_page_initrec_person) self.stack.addWidget(self.new_entry_select) # SITE: 'Grunderfassung Unternehmen' - self.company_recording_page = PageFormCompany() - self.company_recording_page.back_main_requested.connect(self.show_main_page) - self.company_recording_page.back_requested.connect(self.show_new_entry_select) - self.company_recording_page.save_clicked_form.connect(self.update_grid) - self.stack.addWidget(self.company_recording_page) + self.initrec_company = Page_InitRecCompany() + self.initrec_company.back_main_requested.connect(self.show_main_page) + self.initrec_company.back_requested.connect(self.show_new_entry_select) + self.initrec_company.save_clicked_form.connect(self.update_grid) + self.stack.addWidget(self.initrec_company) + # SITE: 'Grunderfassung Person' + self.initrec_person = Page_InitRecPerson() + self.initrec_person.back_main_requested.connect(self.show_main_page) + self.initrec_person.back_requested.connect(self.show_new_entry_select) + self.initrec_person.save_clicked_form.connect(self.update_grid) + self.stack.addWidget(self.initrec_person) def setup_main_page(self): # QMainWindow defines frame --> container widget needed for the middle @@ -3602,12 +2505,15 @@ class MainWindow(QMainWindow): def update_grid(self) -> None: clear_layout(self.grid) - data = be_init_rec.get_company_list() + data = be_init_rec.front_get_company_list() for entry in data: self.add_row_to_grid(entry) - def add_row_to_grid(self, entry: be_init_rec.FrontpageCompany): + def add_row_to_grid( + self, + entry: be_init_rec.FrontpageCompany, + ): row = self.current_row # NAME @@ -3628,7 +2534,8 @@ class MainWindow(QMainWindow): # else: # empty_box = QFrame() # empty_box.setStyleSheet( - # "QFrame { background-color: #f8fafc; border: 2px dashed #e2e8f0; border-radius: 8px; }" + # "QFrame { background-color: #f8fafc; border: 2px + # dashed #e2e8f0; border-radius: 8px; }" # ) # self.grid.addWidget(empty_box, row, 2) @@ -3641,8 +2548,13 @@ class MainWindow(QMainWindow): self, data: be_init_rec.FrontpageCompany, ): - self.company_recording_page.auto_form.load_data(data.erfassung_id) - self.stack.setCurrentWidget(self.company_recording_page) + if data.is_company: + self.initrec_company.auto_form.load_data(data.erfassung_id) + self.stack.setCurrentWidget(self.initrec_company) + else: + self.initrec_person.auto_form.load_data(data.erfassung_id) + self.stack.setCurrentWidget(self.initrec_person) + # 1. Daten an die Detail-Seite übergeben # self.detail_page.update_content(data) # 2. Auf die Detail-Seite umblättern @@ -3655,9 +2567,13 @@ class MainWindow(QMainWindow): def show_new_entry_select(self): self.stack.setCurrentWidget(self.new_entry_select) - def show_company_page(self): - self.company_recording_page.reset_form() - self.stack.setCurrentWidget(self.company_recording_page) + def show_page_initrec_company(self): + self.initrec_company.reset_form() + self.stack.setCurrentWidget(self.initrec_company) + + def show_page_initrec_person(self): + self.initrec_person.reset_form() + self.stack.setCurrentWidget(self.initrec_person) # --- MENÜ LOGIK --- def create_menu(self):