generated from dopt-python/py311
prepare dialog for linking open consulting processes
This commit is contained in:
+101
-89
@@ -24,6 +24,8 @@ from wce_crm.types import (
|
|||||||
ConsultingType,
|
ConsultingType,
|
||||||
ContactPersonInfo,
|
ContactPersonInfo,
|
||||||
InitRecType,
|
InitRecType,
|
||||||
|
LinkingConsultationsEntryCompany,
|
||||||
|
LinkingConsultationsEntryPerson,
|
||||||
MainPageEntry,
|
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(
|
def initrec_company_get_initial_recording(
|
||||||
id_: RecId,
|
id_: RecId,
|
||||||
) -> dict[str, Any]:
|
) -> dict[str, Any]:
|
||||||
@@ -580,30 +517,6 @@ def page_consulting_delete(
|
|||||||
db.beratung_einzelberatung.c.geloescht.is_(None),
|
db.beratung_einzelberatung.c.geloescht.is_(None),
|
||||||
)
|
)
|
||||||
conn.execute(stmt, dump_data)
|
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)
|
@wrap_result(11)
|
||||||
@@ -682,6 +595,105 @@ def page_consulting_from_db(
|
|||||||
|
|
||||||
|
|
||||||
# // consulting page interaction
|
# // 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(
|
def companyprofile_page_get_consultations(
|
||||||
un_id: RecId,
|
un_id: RecId,
|
||||||
) -> CompanyProfileConsultations:
|
) -> CompanyProfileConsultations:
|
||||||
|
|||||||
@@ -266,6 +266,14 @@ class Page_Consulting_State(PageState[Module]):
|
|||||||
locked: bool
|
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)
|
@dc.dataclass(slots=True, kw_only=True)
|
||||||
class Page_Consulting_ConsultingSession_State(PageState[Module]):
|
class Page_Consulting_ConsultingSession_State(PageState[Module]):
|
||||||
session: Session
|
session: Session
|
||||||
|
|||||||
+40
-1
@@ -7,7 +7,7 @@ from pathlib import Path
|
|||||||
|
|
||||||
import polars as pl
|
import polars as pl
|
||||||
import sqlalchemy as sql
|
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 constants
|
||||||
from wce_crm import types as t
|
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}")
|
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(
|
ext_crm_master: sql.Table = Table(
|
||||||
"Master",
|
"Master",
|
||||||
MD_CRM,
|
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(None)
|
||||||
DF_CONTACT_PERSON = get_ext_crm_contact_person(constants.Config.DB_PATH_CRM)
|
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: sql.Table = Table(
|
||||||
"grunderfassung_unternehmen",
|
"grunderfassung_unternehmen",
|
||||||
MD_MAIN,
|
MD_MAIN,
|
||||||
|
|||||||
+332
-2
@@ -51,6 +51,8 @@ from PySide6.QtWidgets import (
|
|||||||
QComboBox,
|
QComboBox,
|
||||||
QCompleter,
|
QCompleter,
|
||||||
QDateEdit,
|
QDateEdit,
|
||||||
|
QDialog,
|
||||||
|
QDialogButtonBox,
|
||||||
QFormLayout,
|
QFormLayout,
|
||||||
QFrame,
|
QFrame,
|
||||||
QGridLayout,
|
QGridLayout,
|
||||||
@@ -60,6 +62,8 @@ from PySide6.QtWidgets import (
|
|||||||
QLabel,
|
QLabel,
|
||||||
QLayout,
|
QLayout,
|
||||||
QLineEdit,
|
QLineEdit,
|
||||||
|
QListWidget,
|
||||||
|
QListWidgetItem,
|
||||||
QMainWindow,
|
QMainWindow,
|
||||||
QMessageBox,
|
QMessageBox,
|
||||||
QPlainTextEdit,
|
QPlainTextEdit,
|
||||||
@@ -89,6 +93,7 @@ from wce_crm.data_models import (
|
|||||||
Initrec,
|
Initrec,
|
||||||
Page_CompanyProfile_State,
|
Page_CompanyProfile_State,
|
||||||
Page_Consulting_ConsultingSession_State,
|
Page_Consulting_ConsultingSession_State,
|
||||||
|
Page_Consulting_Linking_State,
|
||||||
Page_Consulting_State,
|
Page_Consulting_State,
|
||||||
Page_Consulting_Table_State,
|
Page_Consulting_Table_State,
|
||||||
Page_InitRecCompany_State,
|
Page_InitRecCompany_State,
|
||||||
@@ -115,8 +120,17 @@ from wce_crm.logging import (
|
|||||||
from wce_crm.types import CompanyProfileConsultationEntry, ConsultingType, RecId
|
from wce_crm.types import CompanyProfileConsultationEntry, ConsultingType, RecId
|
||||||
|
|
||||||
if TYPE_CHECKING:
|
if TYPE_CHECKING:
|
||||||
from wce_crm.data_models import AutoForm_State, Module, WrapperModule
|
from wce_crm.data_models import (
|
||||||
from wce_crm.types import ConsId, ExtMaId
|
AutoForm_State,
|
||||||
|
Module,
|
||||||
|
WrapperModule,
|
||||||
|
)
|
||||||
|
from wce_crm.types import (
|
||||||
|
ConsId,
|
||||||
|
ExtMaId,
|
||||||
|
LinkingConsultationsEntryCompany,
|
||||||
|
LinkingConsultationsEntryPerson,
|
||||||
|
)
|
||||||
|
|
||||||
K = TypeVar("K")
|
K = TypeVar("K")
|
||||||
V = TypeVar("V")
|
V = TypeVar("V")
|
||||||
@@ -2973,6 +2987,7 @@ class Page_InitRecCompany(QWidget):
|
|||||||
back_requested = Signal() # back button
|
back_requested = Signal() # back button
|
||||||
update_main_page = Signal() # form saved (data changed for front page)
|
update_main_page = Signal() # form saved (data changed for front page)
|
||||||
company_profile_requested = Signal(Page_CompanyProfile_State)
|
company_profile_requested = Signal(Page_CompanyProfile_State)
|
||||||
|
initrec_person_requested = Signal(Page_InitRecPerson_State) # TODO add corresponding call
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
@@ -3021,12 +3036,20 @@ class Page_InitRecCompany(QWidget):
|
|||||||
)
|
)
|
||||||
self.comp_profile_btn.setFixedHeight(50)
|
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.setSpacing(5)
|
||||||
header_layout.addWidget(back_btn_step)
|
header_layout.addWidget(back_btn_step)
|
||||||
header_layout.addWidget(back_btn_main)
|
header_layout.addWidget(back_btn_main)
|
||||||
header_layout.addWidget(title)
|
header_layout.addWidget(title)
|
||||||
header_layout.addSpacing(15)
|
header_layout.addSpacing(15)
|
||||||
header_layout.addWidget(self.comp_profile_btn)
|
header_layout.addWidget(self.comp_profile_btn)
|
||||||
|
header_layout.addWidget(self.initrec_person_btn)
|
||||||
vert_layout.addWidget(header_container)
|
vert_layout.addWidget(header_container)
|
||||||
|
|
||||||
# --- BANNER ---
|
# --- BANNER ---
|
||||||
@@ -3119,6 +3142,18 @@ class Page_InitRecCompany(QWidget):
|
|||||||
logger_gui.debug("[Page -- InitRec Company] State to call: %s", req_state)
|
logger_gui.debug("[Page -- InitRec Company] State to call: %s", req_state)
|
||||||
self.company_profile_requested.emit(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:
|
def reset(self) -> None:
|
||||||
self.auto_form.reset_form()
|
self.auto_form.reset_form()
|
||||||
|
|
||||||
@@ -4088,6 +4123,13 @@ class Page_Consulting(QWidget):
|
|||||||
db_index_layout.addWidget(db_index_set_button)
|
db_index_layout.addWidget(db_index_set_button)
|
||||||
container_layout.addLayout(db_index_layout)
|
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 = QFrame()
|
||||||
separator2.setFrameShape(QFrame.Shape.HLine)
|
separator2.setFrameShape(QFrame.Shape.HLine)
|
||||||
separator2.setFrameShadow(QFrame.Shadow.Sunken)
|
separator2.setFrameShadow(QFrame.Shadow.Sunken)
|
||||||
@@ -4264,6 +4306,34 @@ class Page_Consulting(QWidget):
|
|||||||
def _open_linking_dialogue(self) -> None:
|
def _open_linking_dialogue(self) -> None:
|
||||||
logger_page_consulting.info("[Consulting Page] Linking dialogue triggered")
|
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:
|
def _clear_info_banners(self) -> None:
|
||||||
while self.info_banners:
|
while self.info_banners:
|
||||||
banner = self.info_banners[0]
|
banner = self.info_banners[0]
|
||||||
@@ -4663,6 +4733,265 @@ class Page_Consulting(QWidget):
|
|||||||
self._sync_state_to_GUI("locking")
|
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("<b>Unternehmen wählen (Optional):</b>"))
|
||||||
|
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("<b>Person wählen (Optional):</b>"))
|
||||||
|
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):
|
class Page_Consulting_ConsultingSession(QWidget):
|
||||||
"""child of 'Page_Consulting_DynamicTable'"""
|
"""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_main_requested.connect(self.show_main_page)
|
||||||
self.initrec_company.back_requested.connect(self.show_new_entry_select)
|
self.initrec_company.back_requested.connect(self.show_new_entry_select)
|
||||||
self.initrec_company.update_main_page.connect(self.update_grid)
|
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.initrec_company.company_profile_requested.connect(self.show_page_company_profile)
|
||||||
self.stack.addWidget(self.initrec_company)
|
self.stack.addWidget(self.initrec_company)
|
||||||
# SITE: 'Grunderfassung Person'
|
# SITE: 'Grunderfassung Person'
|
||||||
|
|||||||
@@ -103,3 +103,15 @@ class CompanyProfileConsultationEntry:
|
|||||||
class CompanyProfileConsultations:
|
class CompanyProfileConsultations:
|
||||||
pauschal: list[CompanyProfileConsultationEntry]
|
pauschal: list[CompanyProfileConsultationEntry]
|
||||||
individual: 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
|
||||||
|
|||||||
Reference in New Issue
Block a user