generated from dopt-python/py311
document selection: add Pydantic models and tests for saving/loading
This commit is contained in:
@@ -87,6 +87,7 @@ Grunderfassung_Dokumente
|
||||
speicher_pfad text
|
||||
dateiname_original text
|
||||
dateigroesse_bytes int nullable
|
||||
datum_hinzugefuegt "timestamp with time zone"
|
||||
mime_type text
|
||||
anmerkung text
|
||||
|
||||
|
||||
@@ -282,7 +282,7 @@ class Page_InitRec_DocumentSection_Doc_State(PageState[Module]):
|
||||
session: Session
|
||||
id: int | None
|
||||
pers_id: int | None
|
||||
datum_erstellt_utc: datetime.datetime = dc.field(
|
||||
datum_hinzugefuegt: datetime.datetime = dc.field(
|
||||
default_factory=lambda: datetime.datetime.now(datetime.UTC)
|
||||
)
|
||||
speicher_pfad: Path
|
||||
@@ -294,6 +294,28 @@ class Page_InitRec_DocumentSection_Doc_State(PageState[Module]):
|
||||
geloescht: bool = False
|
||||
|
||||
|
||||
class Grunderfassung_Dokumente(BaseModel):
|
||||
docs: list[Grunderfassung_Dokument]
|
||||
|
||||
|
||||
class Grunderfassung_Dokument(BaseModel):
|
||||
model_config = ConfigDict(str_strip_whitespace=True)
|
||||
|
||||
id: int | None
|
||||
pers_id: int | None
|
||||
speicher_pfad: Path
|
||||
dateiname_original: str = ""
|
||||
datum_hinzugefuegt: AwareDatetime
|
||||
dateigroesse_bytes: int | None = None
|
||||
mime_type: str = ""
|
||||
anmerkung: str = ""
|
||||
|
||||
# default in SQLAlchemy with lambda and timezone-aware datetime
|
||||
erstellt: AwareDatetime | None = Field(default=None, exclude=True)
|
||||
aktualisiert: AwareDatetime | None = Field(default=None, exclude=True) # see above
|
||||
geloescht: AwareDatetime | None = None
|
||||
|
||||
|
||||
@dc.dataclass(slots=True, kw_only=True)
|
||||
class Page_Consulting_State(PageState[Module]):
|
||||
session: Session
|
||||
@@ -332,7 +354,7 @@ class Page_Consulting_ConsultingSession_State(PageState[Module]):
|
||||
)
|
||||
anmerkungen: str | None = None
|
||||
rueckmeldung: str | None = None
|
||||
ist_geloescht: bool = False
|
||||
geloescht: bool = False
|
||||
locked: bool
|
||||
|
||||
|
||||
@@ -667,6 +689,9 @@ class Grunderfassung_Sprachen(BaseModel):
|
||||
SP_datum_nachweis: datetime.date | None = None
|
||||
|
||||
|
||||
# TODO placeholer docuemnt
|
||||
|
||||
|
||||
# ** Consulting
|
||||
class Beratungsgespraech_Vorgang(BaseModel):
|
||||
model_config = ConfigDict(str_strip_whitespace=True)
|
||||
|
||||
+15
-82
@@ -100,12 +100,17 @@ from wce_crm.data_models import (
|
||||
Page_NewEntry_State,
|
||||
Session,
|
||||
set_page_state,
|
||||
translate_pydantic_errors,
|
||||
)
|
||||
from wce_crm.form_defs import (
|
||||
FormField,
|
||||
FormFieldType,
|
||||
)
|
||||
from wce_crm.gui_components.dialogs import (
|
||||
GUI_validation_error_handling,
|
||||
get_message_box,
|
||||
get_user_confirmation,
|
||||
pydantic_validation_error_handling,
|
||||
)
|
||||
from wce_crm.logging import (
|
||||
logger_custom_fields,
|
||||
logger_get_data,
|
||||
@@ -4984,7 +4989,7 @@ class Page_Consulting(QWidget):
|
||||
self.STATE.locked = True
|
||||
|
||||
if update_only:
|
||||
relevant_gui_states = [s for s in self.STATE.cons_sessions if not s.ist_geloescht]
|
||||
relevant_gui_states = [s for s in self.STATE.cons_sessions if not s.geloescht]
|
||||
rel_cons_session_states = [s for s in data.beratungen if s.geloescht is None]
|
||||
assert len(relevant_gui_states) == len(rel_cons_session_states)
|
||||
for gui_state, pydantic_state in zip(
|
||||
@@ -5097,7 +5102,7 @@ class Page_Consulting(QWidget):
|
||||
|
||||
for row in self.STATE.cons_sessions:
|
||||
logger_page_consulting.debug("[Consulting Page] Row state:\n%s", row)
|
||||
if row.beratung_id is None and row.ist_geloescht:
|
||||
if row.beratung_id is None and row.geloescht:
|
||||
logger_page_consulting.debug(
|
||||
(
|
||||
"[Consulting Page] Session which was never saved in the database "
|
||||
@@ -5110,7 +5115,7 @@ class Page_Consulting(QWidget):
|
||||
if timestamp_deleted is not None:
|
||||
# if process is deleted, all sessions must be marked as deleted
|
||||
timestamp_deleted_session = timestamp_deleted
|
||||
elif row.ist_geloescht:
|
||||
elif row.geloescht:
|
||||
timestamp_deleted_session = datetime.datetime.now(datetime.UTC)
|
||||
|
||||
cons_session_dict = dc.asdict(row)
|
||||
@@ -5596,9 +5601,11 @@ class Page_Consulting_ConsultingSession(QWidget):
|
||||
"Löschen bestätigen",
|
||||
"Soll der Eintrag wirklich gelöscht werden?",
|
||||
)
|
||||
if confirm:
|
||||
self.STATE.ist_geloescht = True
|
||||
self.delete_request.emit(self)
|
||||
if not confirm:
|
||||
return
|
||||
|
||||
self.STATE.geloescht = True
|
||||
self.delete_request.emit(self)
|
||||
|
||||
def _sync_state_to_GUI(
|
||||
self,
|
||||
@@ -5863,7 +5870,7 @@ class Page_Consulting_Table(QWidget):
|
||||
# states_to_show = [s for s in self.STATE.row_states if not s.ist_geloescht]
|
||||
# for row_state in states_to_show:
|
||||
for row_state in self.STATE.row_states:
|
||||
if not row_state.ist_geloescht:
|
||||
if not row_state.geloescht:
|
||||
self.add_row(row_state, True)
|
||||
|
||||
if section is None or section == "locking":
|
||||
@@ -6009,80 +6016,6 @@ def clear_layout(
|
||||
clear_layout(child.layout())
|
||||
|
||||
|
||||
def get_message_box(
|
||||
msg_type: QMessageBox.Icon,
|
||||
title: str,
|
||||
message: str,
|
||||
detailed_text: str | None = None,
|
||||
) -> QMessageBox:
|
||||
msg_box = QMessageBox()
|
||||
msg_box.setIcon(msg_type)
|
||||
msg_box.setWindowTitle(title)
|
||||
msg_box.setText(message)
|
||||
if detailed_text is not None:
|
||||
msg_box.setDetailedText(detailed_text)
|
||||
|
||||
return msg_box
|
||||
|
||||
|
||||
def get_user_confirmation(
|
||||
parent_widget: QWidget,
|
||||
title: str,
|
||||
message: str,
|
||||
) -> bool:
|
||||
response = QMessageBox.question(
|
||||
parent_widget,
|
||||
title,
|
||||
message,
|
||||
buttons=(QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No),
|
||||
defaultButton=QMessageBox.StandardButton.No,
|
||||
)
|
||||
|
||||
if response == QMessageBox.StandardButton.Yes:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
def pydantic_validation_error_handling(
|
||||
val_error: ValidationError,
|
||||
) -> None:
|
||||
error_texts: list[str] = []
|
||||
translated_errors = translate_pydantic_errors(val_error.errors())
|
||||
|
||||
for error in translated_errors:
|
||||
error_field = str(error["loc"][0])
|
||||
reason = error["msg"]
|
||||
path = " → ".join(error["loc"][:-1]) # type: ignore
|
||||
|
||||
error_texts.append(f"- {error_field}: {reason}, (Pfad: {path})")
|
||||
|
||||
msg_box = get_message_box(
|
||||
QMessageBox.Icon.Warning,
|
||||
"Fehler bei der Validierung der Eingabedaten",
|
||||
(
|
||||
"Bei der Validierung der Eingaben ist ein Fehler aufgetreten. Details "
|
||||
"sind unten angefügt."
|
||||
),
|
||||
"\n".join(error_texts),
|
||||
)
|
||||
msg_box.exec()
|
||||
|
||||
|
||||
def GUI_validation_error_handling(
|
||||
errors: list[str],
|
||||
) -> None:
|
||||
error_text = "Bitte füllen Sie die folgenden Pflichtfelder aus:\n\n▸ " + "\n▸ ".join(
|
||||
errors
|
||||
)
|
||||
msg_box = get_message_box(
|
||||
QMessageBox.Icon.Warning,
|
||||
"Fehlende oder fehlerhafte Angaben",
|
||||
error_text,
|
||||
)
|
||||
msg_box.exec()
|
||||
|
||||
|
||||
class _ModifyButton(QPushButton):
|
||||
modify_activated = Signal()
|
||||
modify_deactivated = Signal()
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
from pydantic import ValidationError
|
||||
from PySide6.QtWidgets import QMessageBox, QWidget
|
||||
|
||||
from wce_crm.data_models import translate_pydantic_errors
|
||||
|
||||
|
||||
def get_user_confirmation(
|
||||
parent_widget: QWidget,
|
||||
title: str,
|
||||
message: str,
|
||||
) -> bool:
|
||||
response = QMessageBox.question(
|
||||
parent_widget,
|
||||
title,
|
||||
message,
|
||||
buttons=(QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No),
|
||||
defaultButton=QMessageBox.StandardButton.No,
|
||||
)
|
||||
|
||||
if response == QMessageBox.StandardButton.Yes:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
def get_message_box(
|
||||
msg_type: QMessageBox.Icon,
|
||||
title: str,
|
||||
message: str,
|
||||
detailed_text: str | None = None,
|
||||
) -> QMessageBox:
|
||||
msg_box = QMessageBox()
|
||||
msg_box.setIcon(msg_type)
|
||||
msg_box.setWindowTitle(title)
|
||||
msg_box.setText(message)
|
||||
if detailed_text is not None:
|
||||
msg_box.setDetailedText(detailed_text)
|
||||
|
||||
return msg_box
|
||||
|
||||
|
||||
def pydantic_validation_error_handling(
|
||||
val_error: ValidationError,
|
||||
) -> None:
|
||||
error_texts: list[str] = []
|
||||
translated_errors = translate_pydantic_errors(val_error.errors())
|
||||
|
||||
for error in translated_errors:
|
||||
error_field = str(error["loc"][0])
|
||||
reason = error["msg"]
|
||||
path = " → ".join(error["loc"][:-1]) # type: ignore
|
||||
|
||||
error_texts.append(f"- {error_field}: {reason}, (Pfad: {path})")
|
||||
|
||||
msg_box = get_message_box(
|
||||
QMessageBox.Icon.Warning,
|
||||
"Fehler bei der Validierung der Eingabedaten",
|
||||
(
|
||||
"Bei der Validierung der Eingaben ist ein Fehler aufgetreten. Details "
|
||||
"sind unten angefügt."
|
||||
),
|
||||
"\n".join(error_texts),
|
||||
)
|
||||
msg_box.exec()
|
||||
|
||||
|
||||
def GUI_validation_error_handling(
|
||||
errors: list[str],
|
||||
) -> None:
|
||||
error_text = "Bitte füllen Sie die folgenden Pflichtfelder aus:\n\n▸ " + "\n▸ ".join(
|
||||
errors
|
||||
)
|
||||
msg_box = get_message_box(
|
||||
QMessageBox.Icon.Warning,
|
||||
"Fehlende oder fehlerhafte Angaben",
|
||||
error_text,
|
||||
)
|
||||
msg_box.exec()
|
||||
@@ -1,5 +1,6 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import dataclasses as dc
|
||||
import datetime
|
||||
import os
|
||||
import sys
|
||||
@@ -36,11 +37,14 @@ from PySide6.QtWidgets import (
|
||||
import wce_crm.constants
|
||||
from wce_crm.constants import TIMEZONE_CEST
|
||||
from wce_crm.data_models import (
|
||||
Grunderfassung_Dokument,
|
||||
Grunderfassung_Dokumente,
|
||||
Page_InitRec_DocumentSection_Doc_State,
|
||||
Page_InitRec_DocumentSection_State,
|
||||
Session,
|
||||
set_page_state,
|
||||
)
|
||||
from wce_crm.gui_components.dialogs import get_user_confirmation
|
||||
from wce_crm.logging import logger_gui as logger
|
||||
|
||||
if TYPE_CHECKING:
|
||||
@@ -246,7 +250,7 @@ class FileItemWidget(QFrame):
|
||||
self.btn_delete.setToolTip("Datei entfernen")
|
||||
self.btn_delete.setCursor(Qt.CursorShape.PointingHandCursor)
|
||||
self.btn_delete.setFixedWidth(36)
|
||||
self.btn_delete.clicked.connect(lambda: self.request_remove.emit(self))
|
||||
self.btn_delete.clicked.connect(self._on_delete_btn_clicked)
|
||||
|
||||
layout.addWidget(self.btn_preview)
|
||||
layout.addWidget(self.btn_delete)
|
||||
@@ -260,13 +264,26 @@ class FileItemWidget(QFrame):
|
||||
|
||||
self._sync_state_to_GUI(None)
|
||||
|
||||
def _on_delete_btn_clicked(self) -> None:
|
||||
confirm = get_user_confirmation(
|
||||
self,
|
||||
"Löschen bestätigen",
|
||||
"Soll der Eintrag wirklich gelöscht werden?",
|
||||
)
|
||||
|
||||
if not confirm:
|
||||
return
|
||||
|
||||
self.STATE.geloescht = True
|
||||
self.request_remove.emit(self)
|
||||
|
||||
def _sync_state_to_GUI(
|
||||
self,
|
||||
section: Literal["locking", "content"] | None,
|
||||
) -> None:
|
||||
|
||||
if section is None or section == "content":
|
||||
created_at_string = self.STATE.datum_erstellt_utc.astimezone(
|
||||
created_at_string = self.STATE.datum_hinzugefuegt.astimezone(
|
||||
TIMEZONE_CEST
|
||||
).strftime("%d.%m.%Y %H:%M")
|
||||
|
||||
@@ -356,7 +373,7 @@ class DocumentSectionWidget(QWidget):
|
||||
|
||||
# Dropzone at the top
|
||||
self.drop_zone = _DropZoneWidget()
|
||||
self.drop_zone.files_dropped.connect(self._add_files)
|
||||
self.drop_zone.files_dropped.connect(self.add_new_rows)
|
||||
main_layout.addWidget(self.drop_zone)
|
||||
|
||||
# list containing the file items
|
||||
@@ -383,7 +400,7 @@ class DocumentSectionWidget(QWidget):
|
||||
self.remove_all_rows()
|
||||
for doc in self.STATE.docs:
|
||||
if not doc.geloescht:
|
||||
self.add_row(doc, True)
|
||||
self._add_row(doc, True)
|
||||
|
||||
self.count_changed.emit(self.STATE.doc_count)
|
||||
|
||||
@@ -450,21 +467,12 @@ class DocumentSectionWidget(QWidget):
|
||||
|
||||
# !! the row is never None, there are no 'empty' rows
|
||||
# TODO
|
||||
def add_row(
|
||||
def _add_row(
|
||||
self,
|
||||
row_state: Page_InitRec_DocumentSection_Doc_State | None,
|
||||
row_state: Page_InitRec_DocumentSection_Doc_State,
|
||||
state_exists: bool,
|
||||
) -> None:
|
||||
if row_state is None:
|
||||
new_state = Page_InitRec_DocumentSection_Doc_State(
|
||||
session=self.STATE.session,
|
||||
id=None,
|
||||
pers_id=self.STATE.pers_id,
|
||||
speicher_pfad=None,
|
||||
locked=self.STATE.locked,
|
||||
)
|
||||
|
||||
item_widget = FileItemWidget(new_state)
|
||||
item_widget = FileItemWidget(row_state)
|
||||
item_widget.request_remove.connect(self._remove_row)
|
||||
# embed in QListWidget
|
||||
list_item = QListWidgetItem(self.file_list_widget)
|
||||
@@ -478,55 +486,29 @@ class DocumentSectionWidget(QWidget):
|
||||
|
||||
self.STATE.child_modules.append(item_widget)
|
||||
if not state_exists:
|
||||
self.STATE.docs.append(new_state)
|
||||
self.STATE.docs.append(row_state)
|
||||
|
||||
# TODO change trigger
|
||||
self.STATE.doc_count = self.file_list_widget.count()
|
||||
|
||||
def _add_files(
|
||||
self,
|
||||
filepaths: Iterable[Path],
|
||||
):
|
||||
for path in filepaths:
|
||||
# create custom row widget
|
||||
new_state = Page_InitRec_DocumentSection_Doc_State(
|
||||
session=self.STATE.session,
|
||||
id=None,
|
||||
pers_id=self.STATE.pers_id,
|
||||
speicher_pfad=path,
|
||||
locked=self.STATE.locked,
|
||||
)
|
||||
self.STATE.docs.append(new_state)
|
||||
item_widget = FileItemWidget(new_state)
|
||||
item_widget.request_remove.connect(self._remove_row)
|
||||
self.STATE.child_modules.append(item_widget)
|
||||
|
||||
# embed in QListWidget
|
||||
list_item = QListWidgetItem(self.file_list_widget)
|
||||
# min size to avoid cropping of text
|
||||
size_hint = item_widget.sizeHint()
|
||||
size_hint.setHeight(size_hint.height() + 4)
|
||||
list_item.setSizeHint(size_hint)
|
||||
|
||||
self.file_list_widget.addItem(list_item)
|
||||
self.file_list_widget.setItemWidget(list_item, item_widget)
|
||||
|
||||
self.STATE.doc_count = self.file_list_widget.count()
|
||||
self.count_changed.emit(self.STATE.doc_count)
|
||||
|
||||
def _remove_row(
|
||||
self,
|
||||
widget: QWidget,
|
||||
):
|
||||
# TODO set list item directly when the row is created and reference it back
|
||||
# search and delete row
|
||||
for i in range(self.file_list_widget.count()):
|
||||
item = self.file_list_widget.item(i)
|
||||
if self.file_list_widget.itemWidget(item) == widget:
|
||||
assert isinstance(widget, FileItemWidget)
|
||||
self.file_list_widget.takeItem(i)
|
||||
taken_item = self.file_list_widget.takeItem(i)
|
||||
self.STATE.child_modules.remove(widget)
|
||||
del taken_item
|
||||
widget.deleteLater()
|
||||
break
|
||||
# do not remove the corresponding state since it is tracked
|
||||
# to be post-processed when the database saving operation is triggered
|
||||
# TODO change trigger
|
||||
self.STATE.doc_count = self.file_list_widget.count()
|
||||
self.count_changed.emit(self.STATE.doc_count)
|
||||
|
||||
@@ -539,16 +521,35 @@ class DocumentSectionWidget(QWidget):
|
||||
|
||||
return self.STATE
|
||||
|
||||
def add_new_rows(
|
||||
self,
|
||||
filepaths: Iterable[Path],
|
||||
):
|
||||
for path in filepaths:
|
||||
# create custom row widget
|
||||
new_state = Page_InitRec_DocumentSection_Doc_State(
|
||||
session=self.STATE.session,
|
||||
id=None,
|
||||
pers_id=self.STATE.pers_id,
|
||||
speicher_pfad=path,
|
||||
locked=self.STATE.locked,
|
||||
)
|
||||
self._add_row(new_state, state_exists=False)
|
||||
|
||||
# TODO change trigger
|
||||
self.STATE.doc_count = self.file_list_widget.count()
|
||||
self.count_changed.emit(self.STATE.doc_count)
|
||||
|
||||
# TODO change to protocol/interface with state
|
||||
def get_all_documents_data(self):
|
||||
"""Methode zum Auslesen aller angehängten Dateien inkl. Metadaten für das Speichern."""
|
||||
documents = []
|
||||
for i in range(self.file_list_widget.count()):
|
||||
item = self.file_list_widget.item(i)
|
||||
widget = self.file_list_widget.itemWidget(item)
|
||||
if isinstance(widget, FileItemWidget):
|
||||
documents.append(widget.get_state())
|
||||
return documents
|
||||
# def get_all_documents_data(self):
|
||||
# """Methode zum Auslesen aller angehängten Dateien inkl. Metadaten für das Speichern."""
|
||||
# documents = []
|
||||
# for i in range(self.file_list_widget.count()):
|
||||
# item = self.file_list_widget.item(i)
|
||||
# widget = self.file_list_widget.itemWidget(item)
|
||||
# if isinstance(widget, FileItemWidget):
|
||||
# documents.append(widget.get_state())
|
||||
# return documents
|
||||
|
||||
|
||||
class _MainWindow(QMainWindow):
|
||||
@@ -576,14 +577,49 @@ class _MainWindow(QMainWindow):
|
||||
self.doc_section.count_changed.connect(self.update_header)
|
||||
layout.addWidget(self.doc_section)
|
||||
|
||||
# --- TEST BUTTONS ---
|
||||
# test button to trigger data gathering (simulation for saving procedure and
|
||||
# backend interaction)
|
||||
layout_save_load_btn = QHBoxLayout()
|
||||
layout_save_load_btn.setContentsMargins(0, 0, 0, 0)
|
||||
self.btn_save = QPushButton("Erfassung speichern (Daten auslesen)")
|
||||
self.btn_save.setStyleSheet(
|
||||
"background-color: #0078D4; color: white; padding: 8px; font-weight: bold;"
|
||||
)
|
||||
self.btn_save.clicked.connect(self.print_backend_data)
|
||||
layout.addWidget(self.btn_save)
|
||||
self.btn_save.clicked.connect(self.get_current_widget_state)
|
||||
self.btn_load = QPushButton("Zustand initialisieren (Daten laden)")
|
||||
self.btn_load.setStyleSheet(
|
||||
"background-color: #0078D4; color: white; padding: 8px; font-weight: bold;"
|
||||
)
|
||||
self.btn_load.clicked.connect(self.load_given_state)
|
||||
|
||||
layout_save_load_btn.addWidget(self.btn_save)
|
||||
layout_save_load_btn.addWidget(self.btn_load)
|
||||
layout.addLayout(layout_save_load_btn)
|
||||
|
||||
layout_lock_btn = QHBoxLayout()
|
||||
layout_lock_btn.setContentsMargins(0, 0, 0, 0)
|
||||
btn_lock = QPushButton("Form sperren")
|
||||
btn_lock.setStyleSheet(
|
||||
"background-color: #0078D4; color: white; padding: 8px; font-weight: bold;"
|
||||
)
|
||||
btn_lock.clicked.connect(lambda: self.locking_form(True))
|
||||
btn_unlock = QPushButton("Form entsperren")
|
||||
btn_unlock.setStyleSheet(
|
||||
"background-color: #0078D4; color: white; padding: 8px; font-weight: bold;"
|
||||
)
|
||||
btn_unlock.clicked.connect(lambda: self.locking_form(False))
|
||||
|
||||
layout_lock_btn.addWidget(btn_lock)
|
||||
layout_lock_btn.addWidget(btn_unlock)
|
||||
layout.addLayout(layout_lock_btn)
|
||||
|
||||
btn_pyd_val = QPushButton("Pydantic Validierung")
|
||||
btn_pyd_val.setStyleSheet(
|
||||
"background-color: #0078D4; color: white; padding: 8px; font-weight: bold;"
|
||||
)
|
||||
btn_pyd_val.clicked.connect(self.pydantic_validate_state)
|
||||
layout.addWidget(btn_pyd_val)
|
||||
|
||||
self.setCentralWidget(central_widget)
|
||||
|
||||
@@ -591,15 +627,103 @@ class _MainWindow(QMainWindow):
|
||||
"""update counter in corresponding label, must be mapped to section heading in form"""
|
||||
self.header_label.setText(f"<b>📎 Dokumente & Anhänge ({count})</b>")
|
||||
|
||||
def print_backend_data(self):
|
||||
data = self.doc_section.get_all_documents_data()
|
||||
print("\n--- DATEN FÜR SPEICHERVORGANG BEREIT ---")
|
||||
for i, doc in enumerate(data, 1):
|
||||
print(f"Datei {i}:")
|
||||
print(f" Pfad: {doc['file_path']}")
|
||||
print(f" Datum: {doc['created_at']}")
|
||||
print(f" Kategorie: {doc['category']}")
|
||||
print(f" Anmerkung: {doc['note']}")
|
||||
def locking_form(
|
||||
self,
|
||||
lock: bool,
|
||||
) -> None:
|
||||
if lock:
|
||||
self.doc_section.lock()
|
||||
else:
|
||||
self.doc_section.unlock()
|
||||
|
||||
def get_current_widget_state(self):
|
||||
_ = self.doc_section.get_state()
|
||||
|
||||
def pydantic_validate_state(self):
|
||||
# data = self.doc_section.get_all_documents_data()
|
||||
state = self.doc_section.get_state()
|
||||
docs: list[Grunderfassung_Dokument] = []
|
||||
for doc in state.docs:
|
||||
geloescht_dt: datetime.datetime | None = None
|
||||
if doc.geloescht:
|
||||
geloescht_dt = datetime.datetime.now(datetime.UTC)
|
||||
|
||||
dump_data = dc.asdict(doc)
|
||||
dump_data["geloescht"] = geloescht_dt
|
||||
|
||||
validated = Grunderfassung_Dokument(**dump_data)
|
||||
docs.append(validated)
|
||||
|
||||
validated_section = Grunderfassung_Dokumente(docs=docs)
|
||||
|
||||
logger.debug(
|
||||
("[Module -- DocumentSelection] Pydantic validation. Model:\n%s"),
|
||||
pformat(validated_section.model_dump()),
|
||||
)
|
||||
|
||||
def load_given_state(self) -> None:
|
||||
new_state = Page_InitRec_DocumentSection_State(
|
||||
session=self.SESSION,
|
||||
pers_id=None,
|
||||
docs=[
|
||||
Page_InitRec_DocumentSection_Doc_State(
|
||||
child_modules=[],
|
||||
session=Session(user_id=42, user_name="TEST-USER"),
|
||||
id=None,
|
||||
pers_id=None,
|
||||
datum_hinzugefuegt=datetime.datetime(
|
||||
2026, 7, 31, 6, 38, 7, 120949, tzinfo=datetime.timezone.utc
|
||||
),
|
||||
speicher_pfad=Path("A:/Organisation/Zeiterfassung/Gesamt.xlsx"),
|
||||
dateiname_original="Gesamt.xlsx",
|
||||
dateigroesse_bytes=182564,
|
||||
mime_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
||||
anmerkung="",
|
||||
locked=False,
|
||||
geloescht=True,
|
||||
),
|
||||
Page_InitRec_DocumentSection_Doc_State(
|
||||
child_modules=[],
|
||||
session=Session(user_id=42, user_name="TEST-USER"),
|
||||
id=None,
|
||||
pers_id=None,
|
||||
datum_hinzugefuegt=datetime.datetime(
|
||||
2026, 7, 31, 6, 39, 46, 903040, tzinfo=datetime.timezone.utc
|
||||
),
|
||||
speicher_pfad=Path(
|
||||
"B:/projects/WCE-NAFKA/01 Anforderungen/Detaillierte-Übersicht-Inhalte-Unterkategorien.xlsx"
|
||||
),
|
||||
dateiname_original="Detaillierte-Übersicht-Inhalte-Unterkategorien.xlsx",
|
||||
dateigroesse_bytes=121528,
|
||||
mime_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
||||
anmerkung="",
|
||||
locked=False,
|
||||
geloescht=False,
|
||||
),
|
||||
Page_InitRec_DocumentSection_Doc_State(
|
||||
child_modules=[],
|
||||
session=Session(user_id=42, user_name="TEST-USER"),
|
||||
id=None,
|
||||
pers_id=None,
|
||||
datum_hinzugefuegt=datetime.datetime(
|
||||
2026, 7, 31, 6, 39, 46, 909045, tzinfo=datetime.timezone.utc
|
||||
),
|
||||
speicher_pfad=Path(
|
||||
"B:/projects/WCE-NAFKA/01 Anforderungen/Mockup-CRM.pptx"
|
||||
),
|
||||
dateiname_original="Mockup-CRM.pptx",
|
||||
dateigroesse_bytes=613242,
|
||||
mime_type="application/vnd.openxmlformats-officedocument.presentationml.presentation",
|
||||
anmerkung="",
|
||||
locked=False,
|
||||
geloescht=False,
|
||||
),
|
||||
],
|
||||
locked=False,
|
||||
geloescht=False,
|
||||
)
|
||||
|
||||
self.doc_section.load_state(new_state)
|
||||
|
||||
|
||||
def main() -> None:
|
||||
|
||||
Reference in New Issue
Block a user