draft for company profile

This commit is contained in:
2026-06-25 10:41:13 +02:00
parent b6087a5b21
commit b7f45066f0
3 changed files with 417 additions and 12 deletions
+14 -7
View File
@@ -221,6 +221,8 @@ def front_get_company_list() -> list[FrontpageCompany]:
stmt = sql.select( stmt = sql.select(
db.grunderfassung.c.erfassung_id, db.grunderfassung.c.erfassung_id,
db.grunderfassung.c.Partnersuche__un_suche, db.grunderfassung.c.Partnersuche__un_suche,
db.grunderfassung.c.Stammdaten__vorname,
db.grunderfassung.c.Stammdaten__name,
db.grunderfassung.c.Metadaten_aktualisierung, db.grunderfassung.c.Metadaten_aktualisierung,
).order_by(db.grunderfassung.c.Metadaten_aktualisierung.desc()) ).order_by(db.grunderfassung.c.Metadaten_aktualisierung.desc())
@@ -229,20 +231,25 @@ def front_get_company_list() -> list[FrontpageCompany]:
front_page_companies: list[FrontpageCompany] = [] front_page_companies: list[FrontpageCompany] = []
for entry in res: for entry in res.mappings():
erfassung_id = entry[0] erfassung_id = entry["erfassung_id"]
ma_id = entry[1] ma_id = entry["Partnersuche__un_suche"]
datetime_akt = cast(datetime.datetime, entry[2]) datetime_akt = cast(datetime.datetime, entry["Metadaten_aktualisierung"])
datetime_akt = datetime_akt.astimezone() datetime_akt = datetime_akt.astimezone()
name: str = "PLATZHALTER INDIVIDUAL" name: str
is_company: bool = False is_company: bool
if ma_id is not None: if ma_id is not None:
comp_info = initrec_comp_search_get_info(ma_id) comp_info = initrec_comp_search_get_info(ma_id)
name = comp_info["ma_unternehmensname"] name = comp_info["ma_unternehmensname"]
is_company = True is_company = True
else:
surname: str = entry["Stammdaten__name"]
first_name: str = entry["Stammdaten__vorname"]
names_to_join = [n for n in (first_name, surname) if n]
name = " ".join(names_to_join)
is_company = False
# front_page_companies.append(FrontpageCompany(erfassung_id, ma_id, name, datetime_akt))
front_page_companies.append( front_page_companies.append(
FrontpageCompany( FrontpageCompany(
erfassung_id=erfassung_id, erfassung_id=erfassung_id,
+2 -1
View File
@@ -323,12 +323,13 @@ INITREC_COMP_SEARCH_HEAD = [
] ]
INITREC_CONTACT_PERSON = [ INITREC_CONTACT_PERSON = [
# TODO check removal
FormField( FormField(
"Name Unternehmen/Netzwerkpartner (vorausgefüllt von Suche)", "Name Unternehmen/Netzwerkpartner (vorausgefüllt von Suche)",
FormFieldType.TEXT, FormFieldType.TEXT,
key="KP_name_partner", key="KP_name_partner",
required=False, required=False,
placeholder="Text wird nach gewähltem Unternehmen angezeigt", placeholder="[TODO: Logik in Verbindung mit Unternehmen unklar]",
readonly=True, readonly=True,
), ),
FormField( FormField(
+401 -4
View File
@@ -29,6 +29,7 @@ from PySide6.QtCore import (
) )
from PySide6.QtGui import QAction from PySide6.QtGui import QAction
from PySide6.QtWidgets import ( from PySide6.QtWidgets import (
QAbstractItemView,
QApplication, QApplication,
QComboBox, QComboBox,
QCompleter, QCompleter,
@@ -38,6 +39,7 @@ from PySide6.QtWidgets import (
QGridLayout, QGridLayout,
QGroupBox, QGroupBox,
QHBoxLayout, QHBoxLayout,
QHeaderView,
QLabel, QLabel,
QLayout, QLayout,
QLineEdit, QLineEdit,
@@ -48,6 +50,8 @@ from PySide6.QtWidgets import (
QScrollArea, QScrollArea,
QSizePolicy, QSizePolicy,
QStackedWidget, QStackedWidget,
QTableWidget,
QTableWidgetItem,
QVBoxLayout, QVBoxLayout,
QWidget, QWidget,
) )
@@ -2045,17 +2049,22 @@ class ClickableCell(QFrame):
class HeaderCell(QLabel): class HeaderCell(QLabel):
def __init__(self, text): def __init__(
self,
text: str,
font_size: int = 12,
):
super().__init__(text) super().__init__(text)
self.setAlignment(Qt.AlignmentFlag.AlignCenter) self.setAlignment(Qt.AlignmentFlag.AlignCenter)
self.setStyleSheet(""" self.setStyleSheet(f"""
HeaderCell { HeaderCell {{
background-color: #e2e8f0; background-color: #e2e8f0;
color: #475569; color: #475569;
font-weight: bold; font-weight: bold;
padding: 10px; padding: 10px;
border-radius: 6px; border-radius: 6px;
} font-size: {font_size}px;
}}
""") """)
@@ -2139,6 +2148,7 @@ class Page_InitRecCompany(QWidget):
back_main_requested = Signal() # back to main page back_main_requested = Signal() # back to main page
back_requested = Signal() # back button back_requested = Signal() # back button
update_triggered = Signal() # form saved (data changed for front page) update_triggered = Signal() # form saved (data changed for front page)
company_profile_requested = Signal()
def __init__(self): def __init__(self):
super().__init__() super().__init__()
@@ -2161,6 +2171,12 @@ class Page_InitRecCompany(QWidget):
header_layout = QVBoxLayout(header_container) header_layout = QVBoxLayout(header_container)
header_layout.setContentsMargins(0, 0, 0, 10) header_layout.setContentsMargins(0, 0, 0, 10)
comp_profile_btn = QPushButton("Unternehmensprofil")
comp_profile_btn.clicked.connect(lambda: self.company_profile_requested.emit())
comp_profile_btn.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed)
comp_profile_btn.setMinimumWidth(250)
# comp_profile_btn.setMaximumWidth(200)
back_btn_main = QPushButton("← Zurück zur Übersicht") back_btn_main = QPushButton("← Zurück zur Übersicht")
back_btn_main.clicked.connect(lambda: self.back_main_requested.emit()) back_btn_main.clicked.connect(lambda: self.back_main_requested.emit())
back_btn_main.setSizePolicy(QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Fixed) back_btn_main.setSizePolicy(QSizePolicy.Policy.Fixed, QSizePolicy.Policy.Fixed)
@@ -2176,6 +2192,8 @@ class Page_InitRecCompany(QWidget):
title.setStyleSheet("font-size: 20px; font-weight: bold;") title.setStyleSheet("font-size: 20px; font-weight: bold;")
header_layout.setSpacing(5) header_layout.setSpacing(5)
header_layout.addWidget(comp_profile_btn)
header_layout.addSpacing(15)
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)
@@ -2393,6 +2411,376 @@ class Page_InitRecPerson(QWidget):
self.auto_form.reset_form() self.auto_form.reset_form()
class Page_CompanyProfile(QWidget):
back_main_requested = Signal() # back to main page
back_requested = Signal() # back button
# TODO update should trigger something else
update_triggered = 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(1200)
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("Unternehmensprofil")
title.setStyleSheet("font-size: 20px; font-weight: bold;")
header_layout.setSpacing(5)
header_layout.addSpacing(15)
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(1200)
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)
# --- MAIN LAYOUT ---
if DEBUG:
separator1 = QFrame()
separator1.setFrameShape(QFrame.Shape.HLine)
separator1.setFrameShadow(QFrame.Shadow.Sunken)
container_layout.addWidget(separator1)
layout_change_title = QHBoxLayout()
self.change_title_text = QLineEdit(placeholderText="Unternehmensname eingeben...")
layout_change_title.addWidget(self.change_title_text)
change_title_btn = QPushButton("ändern")
layout_change_title.addWidget(change_title_btn)
change_title_btn.clicked.connect(self.set_company_name)
container_layout.addLayout(layout_change_title)
separator2 = QFrame()
separator2.setFrameShape(QFrame.Shape.HLine)
separator2.setFrameShadow(QFrame.Shadow.Sunken)
container_layout.addWidget(separator2)
container_layout.addSpacing(30)
self.title_company_name = HeaderCell("Unternehmen: n.v.", font_size=16)
container_layout.addWidget(self.title_company_name)
container_layout.addSpacing(20)
# separation in left and right
main_hor_layout = QHBoxLayout()
main_hor_layout.setSpacing(20)
# main_hor_layout.setContentsMargins(20, 20, 20, 20)
# left column
left_frame = QFrame()
left_frame.setObjectName("Segment")
left_frame.setSizePolicy(QSizePolicy.Policy.Preferred, QSizePolicy.Policy.Maximum)
left_layout = QVBoxLayout(left_frame)
main_hor_layout.addWidget(left_frame, stretch=1, alignment=Qt.AlignmentFlag.AlignTop)
master_data_label = HeaderCell("Stammdaten & Vermerke")
master_data_label.setSizePolicy(
QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed
)
left_layout.addWidget(master_data_label)
# self.table_master_data = MasterDataTable()
self.table_master_data = MasterDataFormWidget()
left_layout.addWidget(self.table_master_data)
left_layout.addWidget(QLabel("PLATZHALTER Vermerke: Welche Notizen?"))
# right column
right_column_layout = QVBoxLayout()
right_column_layout.setSpacing(20)
main_hor_layout.addLayout(right_column_layout, stretch=1)
# top right area
top_right_frame = QFrame()
top_right_frame.setObjectName("Segment")
top_right_frame.setSizePolicy(
QSizePolicy.Policy.Preferred, QSizePolicy.Policy.Maximum
)
top_right_layout = QVBoxLayout(top_right_frame)
common_consultancy_label = HeaderCell("Pauschalberatung")
common_consultancy_label.setSizePolicy(
QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed
)
top_right_layout.addWidget(common_consultancy_label)
top_right_new_btn = QPushButton("+ Hinzufügen")
top_right_new_btn.setSizePolicy(
QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed
)
top_right_new_btn.setMinimumHeight(30)
top_right_layout.addWidget(top_right_new_btn)
# bottom right area
bottom_right_frame = QFrame()
bottom_right_frame.setObjectName("Segment")
bottom_right_frame.setSizePolicy(
QSizePolicy.Policy.Preferred, QSizePolicy.Policy.Maximum
)
bottom_right_layout = QVBoxLayout(bottom_right_frame)
individual_consultancy_label = HeaderCell("Individualberatung")
individual_consultancy_label.setSizePolicy(
QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed
)
bottom_right_layout.addWidget(individual_consultancy_label)
bottom_right_new_btn = QPushButton("+ Hinzufügen")
bottom_right_new_btn.setSizePolicy(
QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Fixed
)
bottom_right_new_btn.setMinimumHeight(30)
bottom_right_layout.addWidget(bottom_right_new_btn)
right_column_layout.addWidget(top_right_frame)
right_column_layout.addWidget(bottom_right_frame)
right_column_layout.addStretch(1)
container_layout.addLayout(main_hor_layout)
container_layout.addStretch()
self.setStyleSheet("""
QFrame#Segment {
background-color: #ffffff;
border: 1px solid #e2e8f0;
border-radius: 12px;
padding: 3px;
}
""")
# self.setStyleSheet("""
# /* Hintergrund des Hauptfensters */
# QWidget {
# background-color: #f1f5f9;
# }
# /* Styling für unsere 3 Segmente */
# QFrame#Segment {
# background-color: #ffffff;
# border: 1px solid #e2e8f0;
# border-radius: 12px;
# padding: 15px;
# }
# /* Text-Styling */
# QLabel {
# color: #334155;
# font-size: 16px;
# font-weight: bold;
# }
# """)
def set_company_name(self, name: str = "") -> None:
if not name:
name = self.change_title_text.text()
if not name:
name = "n.v."
txt = f"Unternehmen: {name}"
self.title_company_name.setText(txt)
class MasterDataTable(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("Stammdaten Anzeige")
self.resize(450, 400)
layout = QVBoxLayout(self)
layout.setContentsMargins(15, 15, 15, 15)
# 1. Tabelle erstellen (0 Zeilen initial, 2 Spalten für Merkmal & Wert)
self.table = QTableWidget(0, 2)
# --- DER TRICK FÜR DEN CLEANEN LOOK ---
self.table.horizontalHeader().hide() # Spalten-Header ausblenden
self.table.verticalHeader().hide() # Zeilen-Header (Nummerierung) ausblenden
self.table.setShowGrid(False) # Gitternetzlinien deaktivieren
# Verhalten der Tabelle anpassen
self.table.setSelectionMode(
QAbstractItemView.SelectionMode.NoSelection
) # Nicht auswählbar
self.table.setEditTriggers(
QAbstractItemView.EditTrigger.NoEditTriggers
) # Schreibgeschützt
# Spaltenbreite steuern:
# Linke Spalte passt sich dem Text an, rechte Spalte füllt den Rest des Fensters
self.table.horizontalHeader().setSectionResizeMode(
0, QHeaderView.ResizeMode.ResizeToContents
)
self.table.horizontalHeader().setSectionResizeMode(1, QHeaderView.ResizeMode.Stretch)
layout.addWidget(self.table)
# Daten laden
self.load_data()
self.style_table()
def load_data(self):
daten = [
("Anwendungsname", "MyQtApp Pro"),
("Version", "2.4.1-beta"),
("Datenbank-Pfad", "/var/lib/sqlite/data.db"),
("Letzter Login", "2026-06-25 09:30"),
("Benutzer-ID", "USR-88291"),
("Verschlüsselung", "AES-256-GCM"),
]
# Tabelle befüllen
self.table.setRowCount(len(daten))
for zeile_index, (merkmal, wert) in enumerate(daten):
# Merkmal-Zelle (Links)
item_merkmal = QTableWidgetItem(merkmal)
item_merkmal.setTextAlignment(
Qt.AlignmentFlag.AlignLeft | Qt.AlignmentFlag.AlignVCenter
)
self.table.setItem(zeile_index, 0, item_merkmal)
# Wert-Zelle (Rechts)
item_wert = QTableWidgetItem(wert)
item_wert.setTextAlignment(
Qt.AlignmentFlag.AlignLeft | Qt.AlignmentFlag.AlignVCenter
)
self.table.setItem(zeile_index, 1, item_wert)
def style_table(self):
self.setStyleSheet("""
QWidget {
background-color: transparent;
}
QTableWidget {
border: none;
background-color: transparent;
}
QTableWidget::item {
padding: 8px;
color: #334155;
font-size: 14px;
}
QTableWidget::item:first-column {
font-weight: bold;
color: #64748b;
padding-right: 20px; /* Mehr Abstand zum Wert */
}
""")
class MasterDataFormWidget(QWidget):
def __init__(self):
super().__init__()
# main layout
main_layout = QVBoxLayout(self)
main_layout.setContentsMargins(0, 0, 0, 0)
# form in frame
segment_frame = QFrame()
segment_frame.setObjectName("Segment")
# form layout
form_layout = QFormLayout(segment_frame)
form_layout.setSpacing(15) # Vertikaler Abstand zwischen den Zeilen
form_layout.setLabelAlignment(Qt.AlignmentFlag.AlignLeft) # Merkmale linksbündig
# load data
self.load_data(form_layout)
main_layout.addWidget(segment_frame)n
self.style_ui()
def load_data(self, form_layout):
daten = [
("Anwendungsname", "MyQtApp Pro"),
("Version", "2.4.1-beta"),
("Datenbank-Pfad", "/var/lib/sqlite/data.db"),
("Letzter Login", "2026-06-25 09:30"),
("Benutzer-ID", "USR-88291"),
("Verschlüsselung", "AES-256-GCM"),
]
simulated_retrieved_data = {x[0]: x[1] for x in daten}
for merkmal, wert in simulated_retrieved_data.items():
lbl_merkmal = QLabel(f"{merkmal}")
lbl_merkmal.setObjectName("Merkmal")
lbl_wert = QLabel(str(wert))
lbl_wert.setObjectName("Wert")
lbl_wert.setTextInteractionFlags(Qt.TextInteractionFlag.TextSelectableByMouse)
form_layout.addRow(lbl_merkmal, lbl_wert)
def style_ui(self):
self.setStyleSheet("""
/* Hintergrund des Fensters */
QWidget {
background-color: transparent;
}
/* Unser optisch abgetrenntes Segment */
QFrame#Segment {
background-color: #ffffff;
border: 1px solid #e2e8f0;
border-radius: 12px;
padding: 5px;
}
/* Textgröße für alle Elemente im Formular hochsetzen */
QLabel {
font-size: 12px;
}
/* Linke Spalte (Merkmale): Grau und Fett */
QLabel#Merkmal {
font-weight: bold;
color: #64748b;
}
/* Rechte Spalte (Werte): Dunkel und gut lesbar */
QLabel#Wert {
color: #0f172a;
}
""")
def clear_layout( def clear_layout(
layout: QLayout | None, layout: QLayout | None,
) -> None: ) -> None:
@@ -2441,6 +2829,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_triggered.connect(self.update_grid) self.initrec_company.update_triggered.connect(self.update_grid)
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'
self.initrec_person = Page_InitRecPerson() self.initrec_person = Page_InitRecPerson()
@@ -2448,6 +2837,11 @@ class MainWindow(QMainWindow):
self.initrec_person.back_requested.connect(self.show_new_entry_select) self.initrec_person.back_requested.connect(self.show_new_entry_select)
self.initrec_person.update_triggered.connect(self.update_grid) self.initrec_person.update_triggered.connect(self.update_grid)
self.stack.addWidget(self.initrec_person) self.stack.addWidget(self.initrec_person)
# SITE: 'Unternehmensprofil'
self.company_profile = Page_CompanyProfile()
self.company_profile.back_main_requested.connect(self.show_main_page)
self.company_profile.back_requested.connect(self.show_page_initrec_company)
self.stack.addWidget(self.company_profile)
def setup_main_page(self): def setup_main_page(self):
# QMainWindow defines frame --> container widget needed for the middle # QMainWindow defines frame --> container widget needed for the middle
@@ -2613,6 +3007,9 @@ class MainWindow(QMainWindow):
self.initrec_person.reset_form() self.initrec_person.reset_form()
self.stack.setCurrentWidget(self.initrec_person) self.stack.setCurrentWidget(self.initrec_person)
def show_page_company_profile(self) -> None:
self.stack.setCurrentWidget(self.company_profile)
# --- MENÜ LOGIK --- # --- MENÜ LOGIK ---
def create_menu(self): def create_menu(self):
menu_bar = self.menuBar() menu_bar = self.menuBar()