diff --git a/arho_feature_template/core/models.py b/arho_feature_template/core/models.py
index ad49087..416fb40 100644
--- a/arho_feature_template/core/models.py
+++ b/arho_feature_template/core/models.py
@@ -15,6 +15,8 @@
from arho_feature_template.utils.misc_utils import LANGUAGE, get_layer_by_name, iface
if TYPE_CHECKING:
+ from datetime import datetime
+
from qgis.core import QgsFeature, QgsGeometry
@@ -255,7 +257,7 @@ def from_feature(cls, feature: QgsFeature) -> RegulationConfig:
id=feature["id"],
regulation_code=feature["value"],
name=feature["name"][LANGUAGE],
- description=feature["description"][LANGUAGE],
+ description=feature["description"][LANGUAGE] if feature["description"] else "",
status=feature["status"],
level=feature["level"],
parent_id=feature["parent_id"],
@@ -284,7 +286,6 @@ class Regulation:
@dataclass
class Proposition:
- name: str
value: str
theme_id: str | None = None
proposition_number: int | None = None
@@ -370,5 +371,26 @@ class Plan:
producers_plan_identifier: str | None = None
organisation_id: str | None = None
general_regulations: list[RegulationGroup] = field(default_factory=list)
+ documents: list[Document] = field(default_factory=list)
geom: QgsGeometry | None = None
id_: int | None = None
+
+
+@dataclass
+class Document:
+ name: str | None = None
+ url: str | None = None
+ type_of_document_id: str | None = None
+ decision: bool | None = None
+ # permanent_document_identifier: str | None = None
+ category_of_publicity_id: str | None = None
+ personal_data_content_id: str | None = None
+ retention_time_id: str | None = None
+ language_id: str | None = None
+ document_date: datetime | None = None
+ # exported_at: str | None = None
+ # exported_file_key:
+ confirmation_date: datetime | None = None
+ arrival_date: datetime | None = None
+ plan_id: int | None = None
+ id_: int | None = None
diff --git a/arho_feature_template/core/plan_manager.py b/arho_feature_template/core/plan_manager.py
index fc5cf4e..11596ed 100644
--- a/arho_feature_template/core/plan_manager.py
+++ b/arho_feature_template/core/plan_manager.py
@@ -10,6 +10,7 @@
from arho_feature_template.core.lambda_service import LambdaService
from arho_feature_template.core.models import (
+ Document,
FeatureTemplateLibrary,
Plan,
PlanFeature,
@@ -28,6 +29,7 @@
from arho_feature_template.gui.tools.inspect_plan_features_tool import InspectPlanFeatures
from arho_feature_template.project.layers.code_layers import PlanRegulationGroupTypeLayer, code_layers
from arho_feature_template.project.layers.plan_layers import (
+ DocumentLayer,
LandUseAreaLayer,
LandUsePointLayer,
LineLayer,
@@ -496,10 +498,11 @@ def save_plan(plan: Plan) -> QgsFeature:
edit_text="Kaavan muokkaus" if editing else "Kaavan luominen",
)
- # Check for deleted general regulations
+ plan_id = feature["id"]
if editing:
+ # Check for deleted general regulations
for association in RegulationGroupAssociationLayer.get_dangling_associations(
- plan.general_regulations, feature["id"], PlanLayer.name
+ plan.general_regulations, plan_id, PlanLayer.name
):
_delete_feature(
association,
@@ -507,13 +510,22 @@ def save_plan(plan: Plan) -> QgsFeature:
"Kaavamääräysryhmän assosiaation poisto",
)
+ # Check for documents to be deleted
+ doc_layer = DocumentLayer.get_from_project()
+ for doc_feature in DocumentLayer.get_documents_to_delete(plan.documents, plan):
+ _delete_feature(doc_feature, doc_layer, "Asiakirjan poisto")
+
# Save general regulations
if plan.general_regulations:
for regulation_group in plan.general_regulations:
- plan_id = feature["id"]
regulation_group_feature = save_regulation_group(regulation_group, plan_id)
save_regulation_group_association(regulation_group_feature["id"], PlanLayer.name, plan_id)
+ # Save documents
+ for document in plan.documents:
+ document.plan_id = plan_id
+ save_document(document)
+
return feature
@@ -660,3 +672,17 @@ def delete_proposition(proposition: Proposition):
layer = PlanPropositionLayer.get_from_project()
_delete_feature(feature, layer, "Kaavasuosituksen poisto")
+
+
+def save_document(document: Document) -> QgsFeature:
+ feature = DocumentLayer.feature_from_model(document)
+ layer = DocumentLayer.get_from_project()
+
+ _save_feature(
+ feature=feature,
+ layer=layer,
+ id_=document.id_,
+ edit_text="Asiakirjan lisäys" if document.id_ is None else "Asiakirjan muokkaus",
+ )
+
+ return feature
diff --git a/arho_feature_template/gui/components/code_combobox.py b/arho_feature_template/gui/components/code_combobox.py
index fc7b1a4..5368aad 100644
--- a/arho_feature_template/gui/components/code_combobox.py
+++ b/arho_feature_template/gui/components/code_combobox.py
@@ -83,7 +83,12 @@ def populate_from_code_layer(self, layer_type: type[AbstractCodeLayer]) -> None:
items[code_feature["id"]] = item
item.setText(0, code_feature["name"][LANGUAGE])
- item.setToolTip(0, code_feature["description"][LANGUAGE])
+ item.setToolTip(
+ 0,
+ code_feature["description"][LANGUAGE]
+ if code_feature["description"]
+ else code_feature["name"][LANGUAGE],
+ )
item.setData(0, Qt.UserRole, code_feature["id"])
if code_feature["value"] in layer_type.category_only_codes:
diff --git a/arho_feature_template/gui/components/plan_document_widget.py b/arho_feature_template/gui/components/plan_document_widget.py
new file mode 100644
index 0000000..a9d4941
--- /dev/null
+++ b/arho_feature_template/gui/components/plan_document_widget.py
@@ -0,0 +1,187 @@
+from __future__ import annotations
+
+from importlib import resources
+from typing import TYPE_CHECKING
+
+from qgis.core import QgsApplication
+from qgis.gui import QgsDateTimeEdit
+from qgis.PyQt import uic
+from qgis.PyQt.QtCore import Qt, pyqtSignal
+from qgis.PyQt.QtWidgets import QCheckBox, QFormLayout, QLabel, QMenu, QToolButton, QWidget
+
+from arho_feature_template.core.models import Document
+from arho_feature_template.project.layers.code_layers import (
+ CategoryOfPublicityLayer,
+ LanguageLayer,
+ PersonalDataContentLayer,
+ RetentionTimeLayer,
+ TypeOfDocumentLayer,
+)
+
+if TYPE_CHECKING:
+ from datetime import datetime
+
+ from qgis.PyQt.QtWidgets import QLineEdit, QPushButton
+
+ from arho_feature_template.gui.components.code_combobox import CodeComboBox, HierarchicalCodeComboBox
+
+
+ui_path = resources.files(__package__) / "plan_document_widget.ui"
+FormClass, _ = uic.loadUiType(ui_path)
+
+
+class DocumentWidget(QWidget, FormClass): # type: ignore
+ """A widget representation of a plan document."""
+
+ document_edited = pyqtSignal()
+ delete_signal = pyqtSignal(QWidget)
+
+ def __init__(self, document: Document, parent=None):
+ super().__init__(parent)
+ self.setupUi(self)
+
+ # TYPES
+ self.name: QLineEdit
+ self.url: QLineEdit
+ self.url_label: QLabel
+ self.document_type: CodeComboBox
+ self.document_type_label: QLabel
+ self.publicity: CodeComboBox
+ self.publicity_label: QLabel
+ self.decision: QCheckBox
+ self.decision_label: QLabel
+ self.language: CodeComboBox
+ self.language_label: QLabel
+ self.retention_time: HierarchicalCodeComboBox
+ self.retention_time_label: QLabel
+ self.personal_data_content: CodeComboBox
+ self.personal_data_content_label: QLabel
+ self.document_date: QgsDateTimeEdit
+ self.document_date_label: QLabel
+
+ self.add_field_btn: QPushButton
+ self.del_btn: QPushButton
+ self.form_layout: QFormLayout
+ self.expand_hide_btn: QToolButton
+
+ # INIT
+ self.document = document
+
+ self.document_type.populate_from_code_layer(TypeOfDocumentLayer)
+ self.publicity.populate_from_code_layer(CategoryOfPublicityLayer)
+ self.language.populate_from_code_layer(LanguageLayer)
+ self.language.setCurrentIndex(1)
+ self.retention_time.populate_from_code_layer(RetentionTimeLayer)
+ self.personal_data_content.populate_from_code_layer(PersonalDataContentLayer)
+
+ self.name.textChanged.connect(self.document_edited.emit)
+ self.document_type.currentIndexChanged.connect(self.document_edited.emit)
+ self.publicity.currentIndexChanged.connect(self.document_edited.emit)
+ self.language.currentIndexChanged.connect(self.document_edited.emit)
+ self.retention_time.currentIndexChanged.connect(self.document_edited.emit)
+ self.personal_data_content.currentIndexChanged.connect(self.document_edited.emit)
+
+ # List of widgets for hiding / showing
+ self.widgets: list[tuple[QLabel, QWidget]] = [
+ (self.url_label, self.url),
+ (self.document_type_label, self.document_type),
+ (self.publicity_label, self.publicity),
+ (self.decision_label, self.decision),
+ (self.language_label, self.language),
+ (self.retention_time_label, self.retention_time),
+ (self.personal_data_content_label, self.personal_data_content),
+ (self.document_date_label, self.document_date),
+ ]
+ self.arrival_date_widget: QgsDateTimeEdit | None = None
+ self.confirmation_date_widget: QgsDateTimeEdit | None = None
+
+ add_field_menu = QMenu(self)
+ add_field_menu.addAction("Saapumispäivämäärä").triggered.connect(self._add_arrival_date)
+ add_field_menu.addAction("Vahvistuspäivämäärä").triggered.connect(self._add_confirmation_date)
+ self.add_field_btn.setMenu(add_field_menu)
+ self.add_field_btn.setIcon(QgsApplication.getThemeIcon("mActionAdd.svg"))
+ self.del_btn.setIcon(QgsApplication.getThemeIcon("mActionDeleteSelected.svg"))
+ self.del_btn.clicked.connect(lambda: self.delete_signal.emit(self))
+
+ self.expanded = True
+ self.expand_hide_btn.clicked.connect(self._on_expand_hide_btn_clicked)
+
+ # Set values from input Document model
+ self.name.setText(document.name)
+ self.url.setText(document.url)
+ self.document_type.set_value(document.type_of_document_id)
+ self.publicity.set_value(document.category_of_publicity_id)
+ self.decision.setChecked(document.decision is True)
+ if document.language_id:
+ self.language.set_value(document.language_id)
+ self.retention_time.set_value(document.retention_time_id)
+ self.personal_data_content.set_value(document.personal_data_content_id)
+ if document.arrival_date:
+ self._add_arrival_date(document.arrival_date)
+ if document.confirmation_date:
+ self._add_confirmation_date(document.confirmation_date)
+
+ def is_ok(self) -> bool:
+ return (
+ self.name.text() != ""
+ and self.document_type.value() is not None
+ and self.publicity.value() is not None
+ and self.language.value() is not None
+ and self.retention_time.value() is not None
+ and self.personal_data_content.value() is not None
+ )
+
+ def _add_widgets(self, label: QLabel, widget: QWidget):
+ self.form_layout.addRow(label, widget)
+ self.widgets.append((label, widget))
+ if not self.expanded:
+ self._on_expand_hide_btn_clicked()
+
+ def _add_arrival_date(self, default_value: datetime | None = None):
+ if not self.arrival_date_widget:
+ self.arrival_date_widget = QgsDateTimeEdit()
+ self.arrival_date_widget.setDisplayFormat("d.M.yyyy")
+ if default_value:
+ self.arrival_date_widget.setDateTime(default_value)
+ self._add_widgets(QLabel("Saapumispäivämäärä"), self.arrival_date_widget)
+
+ def _add_confirmation_date(self, default_value: datetime | None = None):
+ if not self.confirmation_date_widget:
+ self.confirmation_date_widget = QgsDateTimeEdit()
+ self.confirmation_date_widget.setDisplayFormat("d.M.yyyy")
+ if default_value:
+ self.confirmation_date_widget.setDateTime(default_value)
+ self._add_widgets(QLabel("Vahvistuspäivämäärä"), self.confirmation_date_widget)
+
+ def _on_expand_hide_btn_clicked(self):
+ if self.expanded:
+ for label, value_widget in self.widgets:
+ self.form_layout.removeWidget(label)
+ label.hide()
+ self.form_layout.removeWidget(value_widget)
+ value_widget.hide()
+ self.expand_hide_btn.setArrowType(Qt.ArrowType.DownArrow)
+ self.expanded = False
+ else:
+ for label, value_widget in self.widgets:
+ self.form_layout.addRow(label, value_widget)
+ label.show()
+ value_widget.show()
+ self.expand_hide_btn.setArrowType(Qt.ArrowType.UpArrow)
+ self.expanded = True
+
+ def into_model(self) -> Document:
+ return Document(
+ name=self.name.text(),
+ url=self.url.text(),
+ type_of_document_id=self.document_type.value(),
+ decision=self.decision.isChecked(),
+ category_of_publicity_id=self.publicity.value(),
+ personal_data_content_id=self.personal_data_content.value(),
+ retention_time_id=self.retention_time.value(),
+ language_id=self.language.value(),
+ document_date=self.document_date.date(),
+ # exported_at=self.document.exported_at,
+ plan_id=self.document.plan_id,
+ id_=self.document.id_,
+ )
diff --git a/arho_feature_template/gui/components/plan_document_widget.ui b/arho_feature_template/gui/components/plan_document_widget.ui
new file mode 100644
index 0000000..9b26f0e
--- /dev/null
+++ b/arho_feature_template/gui/components/plan_document_widget.ui
@@ -0,0 +1,233 @@
+
+
+ plan_document
+
+
+
+ 0
+ 0
+ 488
+ 327
+
+
+
+ Form
+
+
+ -
+
+
-
+
+
+
+ 11
+ 75
+ true
+
+
+
+ Asiakirja
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 40
+ 20
+
+
+
+
+ -
+
+
+ Muu tieto
+
+
+
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+ 30
+ 16777215
+
+
+
+
+
+
+
+
+
+ -
+
+
-
+
+
+ Nimi
+
+
+
+ -
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+ false
+
+
+
+ -
+
+
+ Laajenna
+
+
+ false
+
+
+ Qt::UpArrow
+
+
+
+
+
+ -
+
+
+ URL
+
+
+
+ -
+
+
+ -
+
+
+ Tyyppi
+
+
+
+ -
+
+
+ -
+
+
+ Julkisuusluokka
+
+
+
+ -
+
+
+ -
+
+
+ Kieli
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+ Päätös
+
+
+
+ -
+
+
+
+ 0
+ 0
+
+
+
+
+
+
+
+ -
+
+
+ Henkilötietosisältö
+
+
+
+ -
+
+
+ Säilytysaika
+
+
+
+ -
+
+
+ d.M.yyyy
+
+
+
+ -
+
+
+ Asiakirjan päivämäärä
+
+
+
+
+
+
+
+
+
+ QgsDateTimeEdit
+ QDateTimeEdit
+
+
+
+ CodeComboBox
+ QComboBox
+ arho_feature_template.gui.components.code_combobox
+
+
+ HierarchicalCodeComboBox
+ QComboBox
+ arho_feature_template.gui.components.code_combobox
+
+
+
+
+
diff --git a/arho_feature_template/gui/components/plan_proposition_widget.py b/arho_feature_template/gui/components/plan_proposition_widget.py
index dbff0ad..986df25 100644
--- a/arho_feature_template/gui/components/plan_proposition_widget.py
+++ b/arho_feature_template/gui/components/plan_proposition_widget.py
@@ -14,7 +14,7 @@
from arho_feature_template.project.layers.code_layers import PlanThemeLayer
if TYPE_CHECKING:
- from qgis.PyQt.QtWidgets import QLineEdit, QPushButton
+ from qgis.PyQt.QtWidgets import QPushButton
ui_path = resources.files(__package__) / "plan_proposition_widget.ui"
FormClass, _ = uic.loadUiType(ui_path)
@@ -30,7 +30,6 @@ def __init__(self, proposition: Proposition, parent=None):
self.setupUi(self)
# TYPES
- self.name: QLineEdit
self.value_label: QLabel
self.text_input: QTextEdit
self.add_field_btn: QPushButton
@@ -58,7 +57,7 @@ def __init__(self, proposition: Proposition, parent=None):
self.expanded = True
self.expand_hide_btn.clicked.connect(self._on_expand_hide_btn_clicked)
- self.name.setText(proposition.name)
+ # self.name.setText(proposition.name)
self.text_input.setText(proposition.value)
if proposition.theme_id:
self._add_theme(proposition.theme_id)
@@ -103,7 +102,6 @@ def _on_expand_hide_btn_clicked(self):
def into_model(self) -> Proposition:
return Proposition(
- name=self.name.text(),
value=self.text_input.toPlainText(),
theme_id=self.theme_widget.value() if self.theme_widget else None,
proposition_number=self.proposition_number_widget.get_value() if self.proposition_number_widget else None,
diff --git a/arho_feature_template/gui/components/plan_proposition_widget.ui b/arho_feature_template/gui/components/plan_proposition_widget.ui
index 73bbcb1..c1b9049 100644
--- a/arho_feature_template/gui/components/plan_proposition_widget.ui
+++ b/arho_feature_template/gui/components/plan_proposition_widget.ui
@@ -7,7 +7,7 @@
0
0
441
- 207
+ 125
@@ -87,49 +87,31 @@
+ -
+
+
+ Laajenna
+
+
+ false
+
+
+ Qt::UpArrow
+
+
+
-
-
-
-
- Otsikko
-
-
-
- -
-
-
-
-
-
- false
-
-
-
- -
-
-
- Laajenna
-
-
- false
-
-
- Qt::UpArrow
-
-
-
-
-
- -
Sisältö
- -
+
-
diff --git a/arho_feature_template/gui/dialogs/plan_attribute_form.py b/arho_feature_template/gui/dialogs/plan_attribute_form.py
index 2cae050..e746ccd 100644
--- a/arho_feature_template/gui/dialogs/plan_attribute_form.py
+++ b/arho_feature_template/gui/dialogs/plan_attribute_form.py
@@ -3,6 +3,7 @@
from importlib import resources
from typing import TYPE_CHECKING
+from qgis.core import QgsApplication
from qgis.PyQt import uic
from qgis.PyQt.QtCore import Qt
from qgis.PyQt.QtWidgets import (
@@ -16,7 +17,8 @@
QTreeWidgetItem,
)
-from arho_feature_template.core.models import Plan, RegulationGroup, RegulationGroupLibrary
+from arho_feature_template.core.models import Document, Plan, RegulationGroup, RegulationGroupLibrary
+from arho_feature_template.gui.components.plan_document_widget import DocumentWidget
from arho_feature_template.gui.components.plan_regulation_group_widget import RegulationGroupWidget
from arho_feature_template.gui.components.tree_with_search_widget import TreeWithSearchWidget
from arho_feature_template.gui.dialogs.plan_regulation_group_form import PlanRegulationGroupForm
@@ -28,7 +30,7 @@
from arho_feature_template.utils.misc_utils import disconnect_signal
if TYPE_CHECKING:
- from qgis.PyQt.QtWidgets import QComboBox, QLineEdit, QTextEdit, QVBoxLayout, QWidget
+ from qgis.PyQt.QtWidgets import QComboBox, QLineEdit, QPushButton, QTextEdit, QVBoxLayout, QWidget
from arho_feature_template.gui.components.code_combobox import CodeComboBox, HierarchicalCodeComboBox
@@ -51,6 +53,10 @@ class PlanAttributeForm(QDialog, FormClass): # type: ignore
plan_regulation_group_libraries_combobox: QComboBox
regulation_groups_tree_layout: QVBoxLayout
+ documents_scroll_contents: QWidget
+ documents_layout: QVBoxLayout
+ add_document_btn: QPushButton
+
button_box: QDialogButtonBox
def __init__(self, plan: Plan, regulation_group_libraries: list[RegulationGroupLibrary], parent=None):
@@ -97,6 +103,13 @@ def __init__(self, plan: Plan, regulation_group_libraries: list[RegulationGroupL
for regulation_group in plan.general_regulations:
self.add_plan_regulation_group(regulation_group)
+ self.document_widgets: list[DocumentWidget] = []
+ for document in plan.documents:
+ self.add_document(document)
+
+ self.add_document_btn.clicked.connect(self.add_new_document)
+ self.add_document_btn.setIcon(QgsApplication.getThemeIcon("mActionAdd.svg"))
+
self.button_box.button(QDialogButtonBox.Ok).setEnabled(False)
self.button_box.accepted.connect(self._on_ok_clicked)
@@ -109,6 +122,7 @@ def _check_required_fields(self) -> None:
and self.plan_type_combo_box.value() is not None
and self.organisation_combo_box.value() is not None
and self.lifecycle_status_combo_box.value() is not None
+ and all(document_widget.is_ok() for document_widget in self.document_widgets)
):
ok_button.setEnabled(True)
else:
@@ -161,6 +175,25 @@ def init_plan_regulation_group_library(self, library: RegulationGroupLibrary):
group_definition.name, group_definition, category_item
)
+ def add_new_document(self):
+ self.add_document(Document())
+ self._check_required_fields()
+
+ def add_document(self, document: Document):
+ widget = DocumentWidget(document, parent=self.documents_scroll_contents)
+ widget.delete_signal.connect(self.delete_document)
+ widget.document_edited.connect(self._check_required_fields)
+ self.documents_layout.insertWidget(1, widget)
+ self.document_widgets.append(widget)
+
+ def delete_document(self, document_widget: DocumentWidget):
+ document_widget.delete_signal.disconnect()
+ document_widget.document_edited.disconnect()
+ self.documents_layout.removeWidget(document_widget)
+ self.document_widgets.remove(document_widget)
+ document_widget.deleteLater()
+ self._check_required_fields()
+
# ---
def into_model(self) -> Plan:
@@ -176,6 +209,7 @@ def into_model(self) -> Plan:
matter_management_identifier=self.matter_management_identifier_line_edit.text() or None,
lifecycle_status_id=self.lifecycle_status_combo_box.value(),
general_regulations=[reg_group_widget.into_model() for reg_group_widget in self.regulation_group_widgets],
+ documents=[document_widget.into_model() for document_widget in self.document_widgets],
geom=self.plan.geom,
)
diff --git a/arho_feature_template/gui/dialogs/plan_attribute_form.ui b/arho_feature_template/gui/dialogs/plan_attribute_form.ui
index 106411a..c31b0eb 100644
--- a/arho_feature_template/gui/dialogs/plan_attribute_form.ui
+++ b/arho_feature_template/gui/dialogs/plan_attribute_form.ui
@@ -290,6 +290,61 @@
+
+
+ Asiakirjat
+
+
+ -
+
+
+ Qt::ScrollBarAsNeeded
+
+
+ true
+
+
+
+
+ 0
+ 0
+ 831
+ 562
+
+
+
+
-
+
+
+
+ 0
+ 0
+
+
+
+ Lisää asiakirja
+
+
+
+ -
+
+
+ Qt::Vertical
+
+
+
+ 20
+ 20
+
+
+
+
+
+
+
+
+
+
-
diff --git a/arho_feature_template/gui/dialogs/plan_regulation_group_form.py b/arho_feature_template/gui/dialogs/plan_regulation_group_form.py
index db0c100..cf43229 100644
--- a/arho_feature_template/gui/dialogs/plan_regulation_group_form.py
+++ b/arho_feature_template/gui/dialogs/plan_regulation_group_form.py
@@ -122,7 +122,7 @@ def delete_regulation(self, regulation_widget: RegulationWidget):
regulation_widget.deleteLater()
def add_new_proposition(self):
- proposition = Proposition(name="", value="")
+ proposition = Proposition(value="")
self.add_proposition(proposition)
def add_proposition(self, proposition: Proposition):
diff --git a/arho_feature_template/project/layers/code_layers.py b/arho_feature_template/project/layers/code_layers.py
index e96c706..cd6bce8 100644
--- a/arho_feature_template/project/layers/code_layers.py
+++ b/arho_feature_template/project/layers/code_layers.py
@@ -91,4 +91,34 @@ class VerbalRegulationType(AbstractCodeLayer):
category_only_codes: ClassVar[list[str]] = ["maarayksenTyyppi"]
+class CategoryOfPublicityLayer(AbstractCodeLayer):
+ name = "Julkisuusluokka"
+
+ category_only_codes: ClassVar[list[str]] = []
+
+
+class TypeOfDocumentLayer(AbstractCodeLayer):
+ name = "Asiakirjatyyppi"
+
+ category_only_codes: ClassVar[list[str]] = []
+
+
+class LanguageLayer(AbstractCodeLayer):
+ name = "Kieli"
+
+ category_only_codes: ClassVar[list[str]] = []
+
+
+class PersonalDataContentLayer(AbstractCodeLayer):
+ name = "Henkilötietosisältö"
+
+ category_only_codes: ClassVar[list[str]] = []
+
+
+class RetentionTimeLayer(AbstractCodeLayer):
+ name = "Säilytysaika"
+
+ category_only_codes: ClassVar[list[str]] = []
+
+
code_layers = AbstractCodeLayer.__subclasses__()
diff --git a/arho_feature_template/project/layers/plan_layers.py b/arho_feature_template/project/layers/plan_layers.py
index 9437718..96a3a42 100644
--- a/arho_feature_template/project/layers/plan_layers.py
+++ b/arho_feature_template/project/layers/plan_layers.py
@@ -11,6 +11,7 @@
from qgis.utils import iface
from arho_feature_template.core.models import (
+ Document,
Plan,
PlanFeature,
Proposition,
@@ -110,6 +111,10 @@ def model_from_feature(cls, feature: QgsFeature) -> Plan:
for feat in general_regulation_features
if feat is not None
],
+ documents=[
+ DocumentLayer.model_from_feature(feat)
+ for feat in DocumentLayer.get_features_by_attribute_value("plan_id", feature["id"])
+ ],
id_=feature["id"],
)
@@ -376,7 +381,6 @@ class PlanPropositionLayer(AbstractPlanLayer):
def feature_from_model(cls, model: Proposition) -> QgsFeature:
feature = cls.initialize_feature_from_model(model)
- feature["name"] = {LANGUAGE: model.name}
feature["text_value"] = {LANGUAGE: model.value}
feature["plan_regulation_group_id"] = model.regulation_group_id_
feature["ordering"] = model.proposition_number
@@ -388,7 +392,6 @@ def feature_from_model(cls, model: Proposition) -> QgsFeature:
@classmethod
def model_from_feature(cls, feature: QgsFeature) -> Proposition:
return Proposition(
- name=feature["name"][LANGUAGE],
value=feature["text_value"][LANGUAGE],
regulation_group_id_=feature["plan_regulation_group_id"],
proposition_number=feature["ordering"],
@@ -405,6 +408,53 @@ class DocumentLayer(AbstractPlanLayer):
name = "Asiakirjat"
filter_template = Template("plan_id = '$plan_id'")
+ @classmethod
+ def feature_from_model(cls, model: Document) -> QgsFeature:
+ feature = cls.initialize_feature_from_model(model)
+
+ feature["name"] = {LANGUAGE: model.name}
+ feature["url"] = model.url
+ feature["type_of_document_id"] = model.type_of_document_id
+ feature["decision"] = model.decision
+ feature["category_of_publicity_id"] = model.category_of_publicity_id
+ feature["personal_data_content_id"] = model.personal_data_content_id
+ feature["retention_time_id"] = model.retention_time_id
+ feature["language_id"] = model.language_id
+ feature["document_date"] = model.document_date
+ feature["arrival_date"] = model.arrival_date
+ feature["confirmation_date"] = model.confirmation_date
+ feature["plan_id"] = model.plan_id
+ feature["id"] = model.id_ if model.id_ else feature["id"]
+
+ return feature
+
+ @classmethod
+ def model_from_feature(cls, feature: QgsFeature) -> Document:
+ return Document(
+ name=feature["name"][LANGUAGE],
+ url=feature["url"],
+ type_of_document_id=feature["type_of_document_id"],
+ decision=feature["decision"],
+ category_of_publicity_id=feature["category_of_publicity_id"],
+ personal_data_content_id=feature["personal_data_content_id"],
+ retention_time_id=feature["retention_time_id"],
+ language_id=feature["language_id"],
+ document_date=feature["document_date"],
+ arrival_date=feature["arrival_date"],
+ confirmation_date=feature["confirmation_date"],
+ plan_id=feature["plan_id"],
+ id_=feature["id"],
+ )
+
+ @classmethod
+ def get_documents_to_delete(cls, documents: list[Document], plan: Plan) -> list[QgsFeature]:
+ updated_document_ids = [doc.id_ for doc in documents]
+ return [
+ doc
+ for doc in cls.get_features_by_attribute_value("plan_id", str(plan.id_))
+ if doc["id"] not in updated_document_ids
+ ]
+
class SourceDataLayer(AbstractPlanLayer):
name = "Lähtötietoaineistot"