diff --git a/src/wce_crm/backend/backend.py b/src/wce_crm/backend/backend.py
index 2b0c0b4..d23b884 100644
--- a/src/wce_crm/backend/backend.py
+++ b/src/wce_crm/backend/backend.py
@@ -24,6 +24,8 @@ from wce_crm.types import (
ConsultingType,
ContactPersonInfo,
InitRecType,
+ LinkingConsultationsEntryCompany,
+ LinkingConsultationsEntryPerson,
MainPageEntry,
)
@@ -315,71 +317,6 @@ def initrec_person_from_db(
)
-# def initrec_person_to_db(
-# auto_form_data: Initrec,
-# ) -> Initrec_FromDb:
-# logger.debug("[AutoForm -- backend] Call database saving routine...")
-
-# dump_data = copy.deepcopy(auto_form_data.form_data)
-# dump_data["geloescht"] = auto_form_data.geloescht
-
-# return_from_db: Initrec_FromDb
-
-# with db.ENGINE.begin() as conn:
-# if auto_form_data.rec_id is None:
-# # insert new "Vorgang"
-# logger.debug("[AutoForm -- backend] Insert...")
-
-# stmt = db.grunderfassung_personen.insert().returning(
-# db.grunderfassung_personen.c.pers_id,
-# db.grunderfassung_personen.c.Metadaten_aktualisierung,
-# db.grunderfassung_personen.c.geloescht,
-# )
-# ret = conn.execute(stmt, dump_data)
-# if ret.rowcount == 0:
-# raise IOError("Entry was not inserted correctly")
-
-# from_db = ret.mappings().fetchall()
-# assert len(from_db) == 1, "expected excactly one returned row"
-# data_from_db = from_db[0]
-# return_from_db = Initrec_FromDb(
-# rec_id=data_from_db["un_id"],
-# geloescht=data_from_db["geloescht"],
-# Metadaten_aktualisierung=data_from_db["Metadaten_aktualisierung"],
-# )
-
-# logger.debug("[AutoForm -- backend] Inserted InitRec successfully")
-
-# else:
-# logger.debug("[AutoForm -- backend] Update...")
-# stmt = (
-# db.beratung_vorgang.update()
-# .where(db.grunderfassung_personen.c.pers_id == auto_form_data.rec_id)
-# .returning(
-# db.grunderfassung_personen.c.Metadaten_aktualisierung,
-# db.grunderfassung_personen.c.geloescht,
-# )
-# )
-# ret = conn.execute(stmt, dump_data)
-
-# from_db = ret.mappings().fetchall()
-# assert len(from_db) == 1, "expected excatly one returned row"
-# data_from_db = from_db[0]
-
-# return_from_db = Initrec_FromDb(
-# rec_id=auto_form_data.rec_id,
-# geloescht=data_from_db["geloescht"],
-# Metadaten_aktualisierung=data_from_db["Metadaten_aktualisierung"],
-# )
-
-# logger.debug(
-# "[AutoForm -- backend] Updated InitRec with ID %d successfully",
-# auto_form_data.rec_id,
-# )
-
-# return return_from_db
-
-
def initrec_company_get_initial_recording(
id_: RecId,
) -> dict[str, Any]:
@@ -580,30 +517,6 @@ def page_consulting_delete(
db.beratung_einzelberatung.c.geloescht.is_(None),
)
conn.execute(stmt, dump_data)
- return
-
- stmt = db.beratung_einzelberatung.select().where(
- db.beratung_einzelberatung.c.vorgang_id == cons_id,
- db.beratung_einzelberatung.c.geloescht.is_(None),
- )
- ret = conn.execute(stmt)
- cons_sessions = ret.mappings().all()
- # empty results possible
- if not cons_sessions:
- logger.debug("[Consulting Page] No sessions, return directly...")
- return
-
- rows_for_db_update: list[dict[str, Any]] = []
- for row_data in cons_sessions:
- row_data_dump = copy.deepcopy(dump_data)
- row_data_dump["b_beratung_id"] = row_data["beratung_id"]
- rows_for_db_update.append(row_data_dump)
-
- if rows_for_db_update:
- stmt = db.beratung_einzelberatung.update().where(
- db.beratung_einzelberatung.c.beratung_id == sql.bindparam("b_beratung_id")
- )
- conn.execute(stmt, rows_for_db_update)
@wrap_result(11)
@@ -682,6 +595,105 @@ def page_consulting_from_db(
# // consulting page interaction
+def page_consulting_linking_companies(
+ un_id: RecId | None,
+) -> list[LinkingConsultationsEntryCompany]:
+ with db.ENGINE.connect() as conn:
+ q_relevant_companies = sql.select(
+ db.grunderfassung_unternehmen.c.un_id,
+ db.grunderfassung_unternehmen.c.Partnersuche__un_suche,
+ ).where(
+ db.grunderfassung_unternehmen.c.geloescht.is_(None),
+ db.grunderfassung_unternehmen.c.Partnersuche__un_suche.is_not(None),
+ )
+ if un_id is not None:
+ q_relevant_companies = q_relevant_companies.where(
+ db.grunderfassung_unternehmen.c.un_id == un_id
+ )
+
+ q_relevant_companies = q_relevant_companies.subquery("relevant_companies")
+
+ stmt = sql.select(
+ q_relevant_companies.c.un_id,
+ db.ext_crm_master_attach.c.ma_unternehmensname,
+ ).select_from(
+ q_relevant_companies.join(
+ db.ext_crm_master_attach,
+ q_relevant_companies.c.Partnersuche__un_suche
+ == db.ext_crm_master_attach.c.ma_id,
+ )
+ )
+
+ ret = conn.execute(stmt)
+ company_names = ret.mappings().all()
+ if not company_names:
+ raise ValueError(f"No companies found for 'un_id': {un_id}")
+
+ logger.debug("[Page Consulting -- Linking] Retrieved company names:\n%s", company_names)
+
+ linking_entries: list[LinkingConsultationsEntryCompany] = []
+ for entry in company_names:
+ linking_entries.append(
+ LinkingConsultationsEntryCompany(
+ un_id=entry["un_id"],
+ display_name=entry["ma_unternehmensname"],
+ )
+ )
+
+ return linking_entries
+
+
+def page_consulting_linking_persons(
+ un_id: RecId | None,
+) -> list[LinkingConsultationsEntryPerson]:
+ with db.ENGINE.connect() as conn:
+ # if un_id None: list all persons
+ # else: list just the persons associated with the company
+
+ person_select = sql.select(
+ db.grunderfassung_personen.c.pers_id,
+ db.grunderfassung_personen.c.Stammdaten__name,
+ db.grunderfassung_personen.c.Stammdaten__vorname,
+ db.grunderfassung_personen.c.Stammdaten__ort,
+ )
+
+ if un_id is not None:
+ person_select = person_select.select_from(
+ db.grunderfassung_personen.join(
+ db.zuordnung_personen_unternehmen,
+ db.grunderfassung_personen.c.pers_id
+ == db.zuordnung_personen_unternehmen.c.pers_id,
+ )
+ ).where(db.zuordnung_personen_unternehmen.c.un_id == un_id)
+
+ ret = conn.execute(person_select)
+ person_names = ret.mappings().all()
+ if not person_names:
+ logger.warning(f"No persons found for 'un_id': {un_id}")
+ return []
+
+ logger.debug("[Page Consulting -- Linking] Retrieved person names:\n%s", person_names)
+
+ linking_entries: list[LinkingConsultationsEntryPerson] = []
+ for entry in person_names:
+ first_name = entry["Stammdaten__vorname"]
+ last_name = entry["Stammdaten__name"]
+ location_city = entry["Stammdaten__ort"]
+
+ display_name = f"{first_name} {last_name}"
+ if location_city:
+ display_name += f" (Ort: {location_city})"
+
+ linking_entries.append(
+ LinkingConsultationsEntryPerson(
+ pers_id=entry["pers_id"],
+ display_name=display_name,
+ )
+ )
+
+ return linking_entries
+
+
def companyprofile_page_get_consultations(
un_id: RecId,
) -> CompanyProfileConsultations:
diff --git a/src/wce_crm/data_models.py b/src/wce_crm/data_models.py
index 94d30e0..b444340 100644
--- a/src/wce_crm/data_models.py
+++ b/src/wce_crm/data_models.py
@@ -266,6 +266,14 @@ class Page_Consulting_State(PageState[Module]):
locked: bool
+@dc.dataclass(slots=True, kw_only=True)
+class Page_Consulting_Linking_State(PageState[Module]):
+ session: Session
+ un_id: RecId | None = None
+ pers_id: RecId | None = None
+ beratungs_typ: ConsultingType
+
+
@dc.dataclass(slots=True, kw_only=True)
class Page_Consulting_ConsultingSession_State(PageState[Module]):
session: Session
diff --git a/src/wce_crm/db.py b/src/wce_crm/db.py
index c990f04..737ed5f 100644
--- a/src/wce_crm/db.py
+++ b/src/wce_crm/db.py
@@ -7,7 +7,7 @@ from pathlib import Path
import polars as pl
import sqlalchemy as sql
-from sqlalchemy import Column, String, Table, TypeDecorator
+from sqlalchemy import Column, String, Table, TypeDecorator, event
from wce_crm import constants
from wce_crm import types as t
@@ -63,6 +63,14 @@ MD_MAIN = sql.MetaData()
ENGINE = sql.create_engine(f"sqlite:///{constants.Config.DB_PATH_MAIN}")
+@event.listens_for(ENGINE, "connect")
+def attach_second_db(dbapi_connection, connection_record):
+ cursor = dbapi_connection.cursor()
+ # 'kontaktliste' is the alias for the second DB
+ cursor.execute(f"ATTACH DATABASE '{constants.Config.DB_PATH_CRM}' AS kontaktliste")
+ cursor.close()
+
+
ext_crm_master: sql.Table = Table(
"Master",
MD_CRM,
@@ -247,6 +255,37 @@ def get_ext_crm_contact_person(
# df_contact_person = get_ext_crm_contact_person(None)
DF_CONTACT_PERSON = get_ext_crm_contact_person(constants.Config.DB_PATH_CRM)
+ext_crm_master_attach: sql.Table = Table(
+ "Master",
+ MD_CRM,
+ Column("ma_id", sql.Integer, nullable=False, unique=True),
+ Column("wce_id", sql.ForeignKey("Nutzer.wce_id")),
+ Column("ma_unternehmensname", sql.Text, nullable=True),
+ Column("ma_branche", sql.Text, nullable=True),
+ Column("ma_strasse", sql.Text, nullable=True),
+ Column("ma_hausnummer", sql.Text, nullable=True),
+ Column("ma_plz", sql.Text, nullable=True),
+ Column("ma_ort", sql.Text, nullable=True),
+ Column("ma_plz_postfach", sql.Text, nullable=True),
+ Column("ma_postfach", sql.Text, nullable=True),
+ Column("ma_website", sql.Text, nullable=True),
+ Column("ma_mail", sql.Text, nullable=True),
+ Column("ma_telefonnummer", sql.Text, nullable=True),
+ Column("ma_faxnummer", sql.Text, nullable=True),
+ Column("ma_ersteintrag_datum", SafeDateTime, nullable=True),
+ Column("ma_aktualisierung_datum", SafeDateTime, nullable=True),
+ Column("ma_aktualisierung_nutzer", sql.Text, nullable=True),
+ Column("ma_sollprozess", sql.Text, nullable=True),
+ Column("ma_auslaendische_mitarbeiter", sql.Text, nullable=True),
+ Column("ma_quelle_information", sql.Text, nullable=True),
+ Column("ma_bemerkung", sql.Text, nullable=True),
+ Column("ma_kontakt", sql.Boolean, nullable=True),
+ Column("ma_schlagworte", sql.Text, nullable=True),
+ Column("ma_archiviert", sql.Boolean, nullable=True, default=False),
+ schema="kontaktliste",
+)
+
+
grunderfassung_unternehmen: sql.Table = Table(
"grunderfassung_unternehmen",
MD_MAIN,
diff --git a/src/wce_crm/gui.py b/src/wce_crm/gui.py
index 08b2b60..f0fa05e 100644
--- a/src/wce_crm/gui.py
+++ b/src/wce_crm/gui.py
@@ -51,6 +51,8 @@ from PySide6.QtWidgets import (
QComboBox,
QCompleter,
QDateEdit,
+ QDialog,
+ QDialogButtonBox,
QFormLayout,
QFrame,
QGridLayout,
@@ -60,6 +62,8 @@ from PySide6.QtWidgets import (
QLabel,
QLayout,
QLineEdit,
+ QListWidget,
+ QListWidgetItem,
QMainWindow,
QMessageBox,
QPlainTextEdit,
@@ -89,6 +93,7 @@ from wce_crm.data_models import (
Initrec,
Page_CompanyProfile_State,
Page_Consulting_ConsultingSession_State,
+ Page_Consulting_Linking_State,
Page_Consulting_State,
Page_Consulting_Table_State,
Page_InitRecCompany_State,
@@ -115,8 +120,17 @@ from wce_crm.logging import (
from wce_crm.types import CompanyProfileConsultationEntry, ConsultingType, RecId
if TYPE_CHECKING:
- from wce_crm.data_models import AutoForm_State, Module, WrapperModule
- from wce_crm.types import ConsId, ExtMaId
+ from wce_crm.data_models import (
+ AutoForm_State,
+ Module,
+ WrapperModule,
+ )
+ from wce_crm.types import (
+ ConsId,
+ ExtMaId,
+ LinkingConsultationsEntryCompany,
+ LinkingConsultationsEntryPerson,
+ )
K = TypeVar("K")
V = TypeVar("V")
@@ -2973,6 +2987,7 @@ class Page_InitRecCompany(QWidget):
back_requested = Signal() # back button
update_main_page = Signal() # form saved (data changed for front page)
company_profile_requested = Signal(Page_CompanyProfile_State)
+ initrec_person_requested = Signal(Page_InitRecPerson_State) # TODO add corresponding call
def __init__(
self,
@@ -3021,12 +3036,20 @@ class Page_InitRecCompany(QWidget):
)
self.comp_profile_btn.setFixedHeight(50)
+ self.initrec_person_btn = QPushButton("Individualperson erfassen")
+ self.initrec_person_btn.clicked.connect(self._request_inirec_person)
+ self.initrec_person_btn.setSizePolicy(
+ QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed
+ )
+ self.initrec_person_btn.setFixedHeight(50)
+
header_layout.setSpacing(5)
header_layout.addWidget(back_btn_step)
header_layout.addWidget(back_btn_main)
header_layout.addWidget(title)
header_layout.addSpacing(15)
header_layout.addWidget(self.comp_profile_btn)
+ header_layout.addWidget(self.initrec_person_btn)
vert_layout.addWidget(header_container)
# --- BANNER ---
@@ -3119,6 +3142,18 @@ class Page_InitRecCompany(QWidget):
logger_gui.debug("[Page -- InitRec Company] State to call: %s", req_state)
self.company_profile_requested.emit(req_state)
+ def _request_inirec_person(self) -> None:
+ assert self.STATE.un_id is not None, (
+ "requested initrec of person for a company which is not known (no ID)"
+ )
+ req_state = Page_InitRecPerson_State(
+ session=self.STATE.session,
+ pers_id=None,
+ locked=False,
+ )
+ logger_gui.debug("[Page -- InitRec Company] State to call: %s", req_state)
+ self.initrec_person_requested.emit(req_state)
+
def reset(self) -> None:
self.auto_form.reset_form()
@@ -4088,6 +4123,13 @@ class Page_Consulting(QWidget):
db_index_layout.addWidget(db_index_set_button)
container_layout.addLayout(db_index_layout)
+ linking_button = QPushButton("Verlinkungsdialog öffnen")
+ linking_button.setSizePolicy(
+ QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Preferred
+ )
+ linking_button.clicked.connect(self._open_linking_dialogue)
+ container_layout.addWidget(linking_button)
+
separator2 = QFrame()
separator2.setFrameShape(QFrame.Shape.HLine)
separator2.setFrameShadow(QFrame.Shadow.Sunken)
@@ -4264,6 +4306,34 @@ class Page_Consulting(QWidget):
def _open_linking_dialogue(self) -> None:
logger_page_consulting.info("[Consulting Page] Linking dialogue triggered")
+ # Dialog erstellen und anzeigen
+ dialog_state = Page_Consulting_Linking_State(
+ session=self.STATE.session,
+ un_id=self.STATE.un_id,
+ pers_id=self.STATE.pers_id,
+ beratungs_typ=self.STATE.beratungs_typ,
+ )
+ dialog = Page_Consulting_LinkingDialog(dialog_state, parent=self)
+
+ # .exec() öffnet das Fenster modal (blockiert das Hauptfenster)
+ if dialog.exec() == QDialog.DialogCode.Accepted:
+ # Hier hast du am Ende beide (oder nur eine) Entitäten auswertbar vorliegen:
+ firma = dialog.gewaehltes_unternehmen
+ person = dialog.gewaehlte_person
+
+ comp_name = firma["name"] if firma else "Keine"
+ person_name = person["name"] if person else "Keine"
+ logger_page_consulting.info(
+ "[Consulting Page] Firme gewählt: %s, Person gewählt: %s",
+ comp_name,
+ person_name,
+ )
+
+ # 1. TODO: Datenbank-Update ausführen (Fremdschlüssel setzen)
+ # 2. Banner ausblenden: self.banner.hide()
+ else:
+ logger_page_consulting.info("[Consulting Page] Verknüpfung abgebrochen.")
+
def _clear_info_banners(self) -> None:
while self.info_banners:
banner = self.info_banners[0]
@@ -4663,6 +4733,265 @@ class Page_Consulting(QWidget):
self._sync_state_to_GUI("locking")
+class Page_Consulting_LinkingDialog(QDialog):
+ def __init__(
+ self,
+ state: Page_Consulting_Linking_State,
+ parent: QWidget | None = None,
+ ):
+ super().__init__(parent)
+ self.STATE = state
+
+ self.setWindowTitle("Beziehung verknüpfen")
+ self.resize(700, 450)
+
+ # firmen_aus_db = [{"id": 1, "name": "Siemens AG"}, {"id": 2, "name": "Bosch GmbH"}]
+ # personen_aus_db = [
+ # {
+ # "id": 50,
+ # "name": "Max Mustermann",
+ # "unternehmen_id": 1,
+ # "firma_name": "Siemens AG",
+ # },
+ # {
+ # "id": 51,
+ # "name": "Erika Muster",
+ # "unternehmen_id": 1,
+ # "firma_name": "Siemens AG",
+ # },
+ # {
+ # "id": 52,
+ # "name": "Peter Müller",
+ # "unternehmen_id": 2,
+ # "firma_name": "Bosch GmbH",
+ # },
+ # {
+ # "id": 53,
+ # "name": "Freiberufler Frank",
+ # "unternehmen_id": None,
+ # "firma_name": None,
+ # },
+ # ]
+
+ # self.all_unternehmen = firmen_aus_db
+ # self.all_personen = personen_aus_db
+
+ # # Rückgabewerte
+ # self.gewaehltes_unternehmen = None
+ # self.gewaehlte_person = None
+
+ # --- UI LAYOUT ---
+ main_layout = QVBoxLayout(self)
+ column_layout = QHBoxLayout()
+
+ # left column: companies
+ self.vbox_companies = QVBoxLayout()
+ self.vbox_companies.addWidget(QLabel("Unternehmen wählen (Optional):"))
+ self.btn_clear_company = QPushButton("Auswahl aufheben")
+ self.list_companies = QListWidget()
+ self.vbox_companies.addWidget(self.list_companies)
+ self.vbox_companies.addWidget(self.btn_clear_company)
+
+ # right column: persons
+ self.vbox_persons = QVBoxLayout()
+ self.vbox_persons.addWidget(QLabel("Person wählen (Optional):"))
+ self.btn_clear_person = QPushButton("Auswahl aufheben")
+ self.list_persons = QListWidget()
+ self.vbox_persons.addWidget(self.list_persons)
+ self.vbox_persons.addWidget(self.btn_clear_person)
+
+ column_layout.addLayout(self.vbox_companies)
+ column_layout.addLayout(self.vbox_persons)
+ main_layout.addLayout(column_layout)
+
+ # Unten: OK / Abbrechen Buttons
+ self.button_box = QDialogButtonBox(
+ QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel
+ )
+ self.ok_btn = self.button_box.button(QDialogButtonBox.StandardButton.Ok)
+ self.ok_btn.setText("Verknüpfung speichern")
+ self.ok_btn.setEnabled(False)
+ self.button_box.button(QDialogButtonBox.StandardButton.Cancel).setText("Abbrechen")
+ main_layout.addWidget(self.button_box)
+
+ # initial loading
+ # self._load_companies()
+ # self._load_persons()
+
+ # list_style = """
+ # QListWidget::item:selected {
+ # background-color: #0078D4; /* Blau, wenn die Liste aktiv fokussiert ist */
+ # color: white;
+ # }
+ # QListWidget::item:selected:!active {
+ # background-color: #CCE4F7; /* Gut sichtbares Hellblau, wenn die Liste den Fokus verliert */
+ # color: black;
+ # }
+ # QListWidget::item:hover {
+ # background-color: #F0F0F0; /* Dezentes Grau beim Drüberfahren */
+ # }
+ # """
+ # self.list_companies.setStyleSheet(list_style)
+ # self.list_persons.setStyleSheet(list_style)
+
+ # signals
+ self.list_companies.itemSelectionChanged.connect(self._company_selected)
+ self.list_persons.itemSelectionChanged.connect(self._person_selected)
+
+ self.btn_clear_company.clicked.connect(self._clear_company_selection)
+ self.btn_clear_person.clicked.connect(self._clear_person_selection)
+
+ self.button_box.accepted.connect(self.accept)
+ self.button_box.rejected.connect(self.reject)
+
+ self._sync_state_to_GUI(reset=True)
+
+ def _enable_person_selection(
+ self,
+ enable: bool,
+ ) -> None:
+ logger_page_consulting.debug(">>>>>>> CALL ENABLE: %s", enable)
+ for i in range(self.vbox_persons.count()):
+ item = self.vbox_persons.itemAt(i)
+ if not item:
+ continue
+ widget = item.widget()
+ logger_page_consulting.debug(">>>>>>> Type widget: %s", type(widget))
+ if isinstance(widget, QWidget):
+ logger_page_consulting.debug(">>>>>>> Widget (enable=%s): %s", enable, widget)
+ widget.setEnabled(enable)
+
+ def _reset(self) -> None:
+ self._clear_company_selection()
+ self._clear_person_selection()
+
+ def _sync_state_to_GUI(
+ self,
+ reset: bool,
+ section: Literal["person_selection", "validation"] | None = None,
+ ) -> None:
+ if reset:
+ self._reset()
+ self._load_companies()
+
+ if section is None or section == "person_selection":
+ if self.STATE.beratungs_typ is ConsultingType.PAUSCHAL:
+ self._enable_person_selection(False)
+ elif self.STATE.beratungs_typ is ConsultingType.INDIVIDUAL:
+ self._enable_person_selection(True)
+ self.list_persons.blockSignals(True)
+ self._load_persons(self.STATE.un_id)
+ self.list_persons.blockSignals(False)
+
+ if section is None or section == "validation":
+ self._validate()
+
+ def _validate(self) -> None:
+ valid: bool = False
+
+ if self.STATE.beratungs_typ is ConsultingType.PAUSCHAL:
+ assert self.STATE.pers_id is None
+ if self.STATE.un_id is not None:
+ valid = True
+ elif self.STATE.beratungs_typ is ConsultingType.INDIVIDUAL:
+ if self.STATE.pers_id is not None:
+ valid = True
+ else:
+ RuntimeError("Undefined consulting type")
+
+ if valid:
+ self.ok_btn.setEnabled(True)
+ else:
+ self.ok_btn.setEnabled(False)
+
+ def _load_companies(self) -> None:
+ self.list_companies.clear()
+ companies = backend.page_consulting_linking_companies(un_id=self.STATE.un_id)
+ logger_page_consulting.debug(
+ "[Page Consulting -- Linking] Retrieved company entries:\n%s", companies
+ )
+
+ for company in companies:
+ item = QListWidgetItem(company.display_name)
+ item.setData(Qt.ItemDataRole.UserRole, company)
+ self.list_companies.addItem(item)
+
+ def _load_persons(
+ self,
+ un_id: RecId | None,
+ ) -> None:
+ """Lädt Personen. Wenn firma_id übergeben wird, wird gefiltert."""
+ self.list_persons.clear()
+
+ persons = backend.page_consulting_linking_persons(un_id)
+ logger_page_consulting.debug(
+ "[Page Consulting -- Linking] Retrieved person entries:\n%s", persons
+ )
+
+ for person in persons:
+ item = QListWidgetItem(person.display_name)
+ item.setData(Qt.ItemDataRole.UserRole, person)
+ self.list_persons.addItem(item)
+
+ # --- LOGIK ---
+ def _company_selected(self) -> None:
+ items = self.list_companies.selectedItems()
+ if not items:
+ return
+
+ company = cast(
+ "LinkingConsultationsEntryCompany", items[0].data(Qt.ItemDataRole.UserRole)
+ )
+ self.STATE.un_id = company.un_id
+
+ logger_page_consulting.debug(
+ "[Page Consulting -- Linking] Company selected. State is:\n%s",
+ pformat(self.STATE),
+ )
+ self._sync_state_to_GUI(reset=False)
+ # if self.STATE.beratungs_typ is ConsultingType.INDIVIDUAL:
+ # self.list_persons.blockSignals(True)
+ # self._load_persons(un_id=self.STATE.un_id)
+ # self.list_persons.blockSignals(False)
+
+ def _person_selected(self) -> None:
+ items = self.list_persons.selectedItems()
+ if not items:
+ return
+
+ person = cast(
+ "LinkingConsultationsEntryPerson", items[0].data(Qt.ItemDataRole.UserRole)
+ )
+ self.STATE.pers_id = person.pers_id
+ self._sync_state_to_GUI(reset=False, section="validation")
+
+ # TODO this backlink is a really good idea and should be implemented
+ # if person["unternehmen_id"]:
+ # self.list_companies.blockSignals(True)
+ #
+ # for i in range(self.list_companies.count()):
+ # item = self.list_companies.item(i)
+ # firma_data = item.data(Qt.ItemDataRole.UserRole)
+ # if firma_data["id"] == person["unternehmen_id"]:
+ # item.setSelected(True)
+ # self.gewaehltes_unternehmen = firma_data
+ # break
+ # self.list_companies.blockSignals(False)
+
+ def _clear_company_selection(self) -> None:
+ self.list_companies.clearSelection()
+ self.STATE.un_id = None
+ self._sync_state_to_GUI(reset=False)
+
+ def _clear_person_selection(self) -> None:
+ self.list_persons.clearSelection()
+ self.STATE.pers_id = None
+ self._sync_state_to_GUI(reset=False)
+
+ def get_state(self) -> Page_Consulting_Linking_State:
+ return self.STATE
+
+
class Page_Consulting_ConsultingSession(QWidget):
"""child of 'Page_Consulting_DynamicTable'"""
@@ -5461,6 +5790,7 @@ class MainWindow(QMainWindow):
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.update_main_page.connect(self.update_grid)
+ self.initrec_company.initrec_person_requested.connect(self.show_page_initrec_person)
self.initrec_company.company_profile_requested.connect(self.show_page_company_profile)
self.stack.addWidget(self.initrec_company)
# SITE: 'Grunderfassung Person'
diff --git a/src/wce_crm/types.py b/src/wce_crm/types.py
index a4c0715..9f9f943 100644
--- a/src/wce_crm/types.py
+++ b/src/wce_crm/types.py
@@ -103,3 +103,15 @@ class CompanyProfileConsultationEntry:
class CompanyProfileConsultations:
pauschal: list[CompanyProfileConsultationEntry]
individual: list[CompanyProfileConsultationEntry]
+
+
+@dc.dataclass(slots=True)
+class LinkingConsultationsEntryCompany:
+ un_id: RecId
+ display_name: str
+
+
+@dc.dataclass(slots=True)
+class LinkingConsultationsEntryPerson:
+ pers_id: RecId
+ display_name: str