Skip to content

Commit 282cbbb

Browse files
committed
add plan documents
1 parent 0333034 commit 282cbbb

9 files changed

+611
-4
lines changed

arho_feature_template/core/models.py

+24-1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
from arho_feature_template.utils.misc_utils import LANGUAGE, get_layer_by_name, iface
1616

1717
if TYPE_CHECKING:
18+
from datetime import datetime
19+
1820
from qgis.core import QgsFeature, QgsGeometry
1921

2022

@@ -255,7 +257,7 @@ def from_feature(cls, feature: QgsFeature) -> RegulationConfig:
255257
id=feature["id"],
256258
regulation_code=feature["value"],
257259
name=feature["name"][LANGUAGE],
258-
description=feature["description"][LANGUAGE],
260+
description=feature["description"][LANGUAGE] if feature["description"] else "",
259261
status=feature["status"],
260262
level=feature["level"],
261263
parent_id=feature["parent_id"],
@@ -370,5 +372,26 @@ class Plan:
370372
producers_plan_identifier: str | None = None
371373
organisation_id: str | None = None
372374
general_regulations: list[RegulationGroup] = field(default_factory=list)
375+
documents: list[Document] = field(default_factory=list)
373376
geom: QgsGeometry | None = None
374377
id_: int | None = None
378+
379+
380+
@dataclass
381+
class Document:
382+
name: str | None = None
383+
url: str | None = None
384+
type_of_document_id: str | None = None
385+
decision: bool | None = None
386+
# permanent_document_identifier: str | None = None
387+
category_of_publicity_id: str | None = None
388+
personal_data_content_id: str | None = None
389+
retention_time_id: str | None = None
390+
language_id: str | None = None
391+
document_date: datetime | None = None
392+
# exported_at: str | None = None
393+
# exported_file_key:
394+
confirmation_date: datetime | None = None
395+
arrival_date: datetime | None = None
396+
plan_id: int | None = None
397+
id_: int | None = None

arho_feature_template/core/plan_manager.py

+21
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
from arho_feature_template.core.lambda_service import LambdaService
1212
from arho_feature_template.core.models import (
13+
Document,
1314
FeatureTemplateLibrary,
1415
Plan,
1516
PlanFeature,
@@ -26,6 +27,7 @@
2627
from arho_feature_template.gui.tools.inspect_plan_features_tool import InspectPlanFeatures
2728
from arho_feature_template.project.layers.code_layers import PlanRegulationGroupTypeLayer, code_layers
2829
from arho_feature_template.project.layers.plan_layers import (
30+
DocumentLayer,
2931
LandUseAreaLayer,
3032
LandUsePointLayer,
3133
LineLayer,
@@ -479,6 +481,11 @@ def save_plan(plan: Plan) -> QgsFeature:
479481
regulation_group_feature = save_regulation_group(regulation_group, plan_id)
480482
save_regulation_group_association(regulation_group_feature["id"], PlanLayer.name, plan_id)
481483

484+
# Save documents
485+
for document in plan.documents:
486+
document.plan_id = feature["id"]
487+
save_document(document)
488+
482489
return feature
483490

484491

@@ -587,3 +594,17 @@ def save_proposition(proposition: Proposition) -> QgsFeature:
587594
)
588595

589596
return feature
597+
598+
599+
def save_document(document: Document) -> QgsFeature:
600+
feature = DocumentLayer.feature_from_model(document)
601+
layer = DocumentLayer.get_from_project()
602+
603+
_save_feature(
604+
feature=feature,
605+
layer=layer,
606+
id_=document.id_,
607+
edit_text="Asiakirjan lisäys" if document.id_ is None else "Asiakirjan muokkaus",
608+
)
609+
610+
return feature

arho_feature_template/gui/components/code_combobox.py

+6-1
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,12 @@ def populate_from_code_layer(self, layer_type: type[AbstractCodeLayer]) -> None:
8383
items[code_feature["id"]] = item
8484

8585
item.setText(0, code_feature["name"][LANGUAGE])
86-
item.setToolTip(0, code_feature["description"][LANGUAGE])
86+
item.setToolTip(
87+
0,
88+
code_feature["description"][LANGUAGE]
89+
if code_feature["description"]
90+
else code_feature["name"][LANGUAGE],
91+
)
8792
item.setData(0, Qt.UserRole, code_feature["id"])
8893

8994
if code_feature["value"] in layer_type.category_only_codes:
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
from __future__ import annotations
2+
3+
from importlib import resources
4+
from typing import TYPE_CHECKING
5+
6+
from qgis.core import QgsApplication
7+
from qgis.gui import QgsDateTimeEdit
8+
from qgis.PyQt import uic
9+
from qgis.PyQt.QtCore import Qt, pyqtSignal
10+
from qgis.PyQt.QtWidgets import QCheckBox, QFormLayout, QLabel, QMenu, QToolButton, QWidget
11+
12+
from arho_feature_template.core.models import Document
13+
from arho_feature_template.project.layers.code_layers import (
14+
CategoryOfPublicityLayer,
15+
LanguageLayer,
16+
PersonalDataContentLayer,
17+
RetentionTimeLayer,
18+
TypeOfDocumentLayer,
19+
)
20+
21+
if TYPE_CHECKING:
22+
from datetime import datetime
23+
24+
from qgis.PyQt.QtWidgets import QLineEdit, QPushButton
25+
26+
from arho_feature_template.gui.components.code_combobox import CodeComboBox, HierarchicalCodeComboBox
27+
28+
29+
ui_path = resources.files(__package__) / "plan_document_widget.ui"
30+
FormClass, _ = uic.loadUiType(ui_path)
31+
32+
33+
class DocumentWidget(QWidget, FormClass): # type: ignore
34+
"""A widget representation of a plan document."""
35+
36+
delete_signal = pyqtSignal(QWidget)
37+
38+
def __init__(self, document: Document, parent=None):
39+
super().__init__(parent)
40+
self.setupUi(self)
41+
42+
# TYPES
43+
self.name: QLineEdit
44+
self.url: QLineEdit
45+
self.url_label: QLabel
46+
self.document_type: CodeComboBox
47+
self.document_type_label: QLabel
48+
self.publicity: CodeComboBox
49+
self.publicity_label: QLabel
50+
self.decision: QCheckBox
51+
self.decision_label: QLabel
52+
self.language: CodeComboBox
53+
self.language_label: QLabel
54+
self.retention_time: HierarchicalCodeComboBox
55+
self.retention_time_label: QLabel
56+
self.personal_data_content: CodeComboBox
57+
self.personal_data_content_label: QLabel
58+
self.document_date: QgsDateTimeEdit
59+
self.document_date_label: QLabel
60+
61+
self.add_field_btn: QPushButton
62+
self.del_btn: QPushButton
63+
self.form_layout: QFormLayout
64+
self.expand_hide_btn: QToolButton
65+
66+
# INIT
67+
self.document = document
68+
69+
self.document_type.populate_from_code_layer(TypeOfDocumentLayer)
70+
self.publicity.populate_from_code_layer(CategoryOfPublicityLayer)
71+
self.language.populate_from_code_layer(LanguageLayer)
72+
self.language.setCurrentIndex(1)
73+
self.retention_time.populate_from_code_layer(RetentionTimeLayer)
74+
self.personal_data_content.populate_from_code_layer(PersonalDataContentLayer)
75+
76+
# List of widgets for hiding / showing
77+
self.widgets: list[tuple[QLabel, QWidget]] = [
78+
(self.url_label, self.url),
79+
(self.document_type_label, self.document_type),
80+
(self.publicity_label, self.publicity),
81+
(self.decision_label, self.decision),
82+
(self.language_label, self.language),
83+
(self.retention_time_label, self.retention_time),
84+
(self.personal_data_content_label, self.personal_data_content),
85+
]
86+
self.arrival_date_widget: QgsDateTimeEdit | None = None
87+
self.confirmation_date_widget: QgsDateTimeEdit | None = None
88+
89+
add_field_menu = QMenu(self)
90+
add_field_menu.addAction("Saapumispäivämäärä").triggered.connect(self._add_arrival_date)
91+
add_field_menu.addAction("Vahvistuspäivämäärä").triggered.connect(self._add_confirmation_date)
92+
self.add_field_btn.setMenu(add_field_menu)
93+
self.add_field_btn.setIcon(QgsApplication.getThemeIcon("mActionAdd.svg"))
94+
self.del_btn.setIcon(QgsApplication.getThemeIcon("mActionDeleteSelected.svg"))
95+
self.del_btn.clicked.connect(lambda: self.delete_signal.emit(self))
96+
97+
self.expanded = True
98+
self.expand_hide_btn.clicked.connect(self._on_expand_hide_btn_clicked)
99+
100+
# Set values from input Document model
101+
self.name.setText(document.name)
102+
self.url.setText(document.url)
103+
self.document_type.set_value(document.type_of_document_id)
104+
self.publicity.set_value(document.category_of_publicity_id)
105+
self.decision.setChecked(document.decision is True)
106+
if document.language_id:
107+
self.language.set_value(document.language_id)
108+
self.retention_time.set_value(document.retention_time_id)
109+
self.personal_data_content.set_value(document.personal_data_content_id)
110+
if document.arrival_date:
111+
self._add_arrival_date(document.arrival_date)
112+
if document.confirmation_date:
113+
self._add_confirmation_date(document.confirmation_date)
114+
115+
def _add_widgets(self, label: QLabel, widget: QWidget):
116+
self.form_layout.addRow(label, widget)
117+
self.widgets.append((label, widget))
118+
if not self.expanded:
119+
self._on_expand_hide_btn_clicked()
120+
121+
def _add_arrival_date(self, default_value: datetime | None = None):
122+
if not self.arrival_date_widget:
123+
self.arrival_date_widget = QgsDateTimeEdit()
124+
self.arrival_date_widget.setDisplayFormat("d.M.yyyy")
125+
if default_value:
126+
self.arrival_date_widget.setDateTime(default_value)
127+
self._add_widgets(QLabel("Saapumispäivämäärä"), self.arrival_date_widget)
128+
129+
def _add_confirmation_date(self, default_value: datetime | None = None):
130+
if not self.confirmation_date_widget:
131+
self.confirmation_date_widget = QgsDateTimeEdit()
132+
self.confirmation_date_widget.setDisplayFormat("d.M.yyyy")
133+
if default_value:
134+
self.confirmation_date_widget.setDateTime(default_value)
135+
self._add_widgets(QLabel("Vahvistuspäivämäärä"), self.confirmation_date_widget)
136+
137+
def _on_expand_hide_btn_clicked(self):
138+
if self.expanded:
139+
for label, value_widget in self.widgets:
140+
self.form_layout.removeWidget(label)
141+
label.hide()
142+
self.form_layout.removeWidget(value_widget)
143+
value_widget.hide()
144+
self.expand_hide_btn.setArrowType(Qt.ArrowType.DownArrow)
145+
self.expanded = False
146+
else:
147+
for label, value_widget in self.widgets:
148+
self.form_layout.addRow(label, value_widget)
149+
label.show()
150+
value_widget.show()
151+
self.expand_hide_btn.setArrowType(Qt.ArrowType.UpArrow)
152+
self.expanded = True
153+
154+
def into_model(self) -> Document:
155+
return Document(
156+
name=self.name.text(),
157+
url=self.url.text(),
158+
type_of_document_id=self.document_type.value(),
159+
decision=self.decision.isChecked(),
160+
category_of_publicity_id=self.publicity.value(),
161+
personal_data_content_id=self.personal_data_content.value(),
162+
retention_time_id=self.retention_time.value(),
163+
language_id=self.language.value(),
164+
document_date=self.document_date.date(),
165+
# exported_at=self.document.exported_at,
166+
plan_id=self.document.plan_id,
167+
id_=self.document.id_,
168+
)

0 commit comments

Comments
 (0)