Skip to content

Commit 00f0d27

Browse files
committed
add plan documents
1 parent 0333034 commit 00f0d27

9 files changed

+612
-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,169 @@
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+
(self.document_date_label, self.document_date),
86+
]
87+
self.arrival_date_widget: QgsDateTimeEdit | None = None
88+
self.confirmation_date_widget: QgsDateTimeEdit | None = None
89+
90+
add_field_menu = QMenu(self)
91+
add_field_menu.addAction("Saapumispäivämäärä").triggered.connect(self._add_arrival_date)
92+
add_field_menu.addAction("Vahvistuspäivämäärä").triggered.connect(self._add_confirmation_date)
93+
self.add_field_btn.setMenu(add_field_menu)
94+
self.add_field_btn.setIcon(QgsApplication.getThemeIcon("mActionAdd.svg"))
95+
self.del_btn.setIcon(QgsApplication.getThemeIcon("mActionDeleteSelected.svg"))
96+
self.del_btn.clicked.connect(lambda: self.delete_signal.emit(self))
97+
98+
self.expanded = True
99+
self.expand_hide_btn.clicked.connect(self._on_expand_hide_btn_clicked)
100+
101+
# Set values from input Document model
102+
self.name.setText(document.name)
103+
self.url.setText(document.url)
104+
self.document_type.set_value(document.type_of_document_id)
105+
self.publicity.set_value(document.category_of_publicity_id)
106+
self.decision.setChecked(document.decision is True)
107+
if document.language_id:
108+
self.language.set_value(document.language_id)
109+
self.retention_time.set_value(document.retention_time_id)
110+
self.personal_data_content.set_value(document.personal_data_content_id)
111+
if document.arrival_date:
112+
self._add_arrival_date(document.arrival_date)
113+
if document.confirmation_date:
114+
self._add_confirmation_date(document.confirmation_date)
115+
116+
def _add_widgets(self, label: QLabel, widget: QWidget):
117+
self.form_layout.addRow(label, widget)
118+
self.widgets.append((label, widget))
119+
if not self.expanded:
120+
self._on_expand_hide_btn_clicked()
121+
122+
def _add_arrival_date(self, default_value: datetime | None = None):
123+
if not self.arrival_date_widget:
124+
self.arrival_date_widget = QgsDateTimeEdit()
125+
self.arrival_date_widget.setDisplayFormat("d.M.yyyy")
126+
if default_value:
127+
self.arrival_date_widget.setDateTime(default_value)
128+
self._add_widgets(QLabel("Saapumispäivämäärä"), self.arrival_date_widget)
129+
130+
def _add_confirmation_date(self, default_value: datetime | None = None):
131+
if not self.confirmation_date_widget:
132+
self.confirmation_date_widget = QgsDateTimeEdit()
133+
self.confirmation_date_widget.setDisplayFormat("d.M.yyyy")
134+
if default_value:
135+
self.confirmation_date_widget.setDateTime(default_value)
136+
self._add_widgets(QLabel("Vahvistuspäivämäärä"), self.confirmation_date_widget)
137+
138+
def _on_expand_hide_btn_clicked(self):
139+
if self.expanded:
140+
for label, value_widget in self.widgets:
141+
self.form_layout.removeWidget(label)
142+
label.hide()
143+
self.form_layout.removeWidget(value_widget)
144+
value_widget.hide()
145+
self.expand_hide_btn.setArrowType(Qt.ArrowType.DownArrow)
146+
self.expanded = False
147+
else:
148+
for label, value_widget in self.widgets:
149+
self.form_layout.addRow(label, value_widget)
150+
label.show()
151+
value_widget.show()
152+
self.expand_hide_btn.setArrowType(Qt.ArrowType.UpArrow)
153+
self.expanded = True
154+
155+
def into_model(self) -> Document:
156+
return Document(
157+
name=self.name.text(),
158+
url=self.url.text(),
159+
type_of_document_id=self.document_type.value(),
160+
decision=self.decision.isChecked(),
161+
category_of_publicity_id=self.publicity.value(),
162+
personal_data_content_id=self.personal_data_content.value(),
163+
retention_time_id=self.retention_time.value(),
164+
language_id=self.language.value(),
165+
document_date=self.document_date.date(),
166+
# exported_at=self.document.exported_at,
167+
plan_id=self.document.plan_id,
168+
id_=self.document.id_,
169+
)

0 commit comments

Comments
 (0)