Skip to content

Commit 2a518e9

Browse files
authored
Merge branch 'main' into 156-kaavamaarayksen-otsikointi-dynaamisesti
2 parents de502f7 + c760651 commit 2a518e9

34 files changed

+750
-251
lines changed

arho_feature_template/core/lambda_service.py

+28-10
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import json
44
import re
55
from http import HTTPStatus
6-
from typing import cast
6+
from typing import Callable, cast
77

88
from qgis.PyQt.QtCore import QByteArray, QObject, QUrl, pyqtSignal
99
from qgis.PyQt.QtNetwork import QNetworkAccessManager, QNetworkProxy, QNetworkReply, QNetworkRequest
@@ -15,6 +15,7 @@
1515
class LambdaService(QObject):
1616
jsons_received = pyqtSignal(dict, dict)
1717
validation_received = pyqtSignal(dict)
18+
validation_failed = pyqtSignal()
1819
ActionAttribute = cast(QNetworkRequest.Attribute, QNetworkRequest.User + 1)
1920
ACTION_VALIDATE_PLANS = "validate_plans"
2021
ACTION_GET_PLANS = "get_plans"
@@ -57,10 +58,28 @@ def _is_api_gateway_request(self) -> bool:
5758
match = re.match(r"^https://.*execute-api.*amazonaws\.com.*$", self.lambda_url)
5859
return bool(match)
5960

61+
def _get_response_handler(self, action: str) -> Callable[[dict], None]:
62+
handlers = {
63+
self.ACTION_GET_PLANS: self._process_json_reply,
64+
self.ACTION_VALIDATE_PLANS: self._process_validation_reply,
65+
}
66+
return handlers[action]
67+
68+
def _get_error_handler(self, action: str) -> Callable[[], None]:
69+
handlers = {
70+
self.ACTION_GET_PLANS: lambda: None,
71+
self.ACTION_VALIDATE_PLANS: self._handle_validation_error,
72+
}
73+
return handlers[action]
74+
6075
def _handle_reply(self, reply: QNetworkReply):
76+
action = reply.request().attribute(LambdaService.ActionAttribute)
77+
response_handler = self._get_response_handler(action)
78+
error_handler = self._get_error_handler(action)
6179
if reply.error() != QNetworkReply.NoError:
6280
error = reply.errorString()
63-
QMessageBox.critical(None, "API Error", f"Lambda call failed: {error}")
81+
QMessageBox.critical(None, "API Virhe", f"Lambda kutsu epäonnistui: {error}")
82+
error_handler()
6483
reply.deleteLater()
6584
return
6685

@@ -72,30 +91,29 @@ def _handle_reply(self, reply: QNetworkReply):
7291
# If calling the lambda directly, the response includes status code and body
7392
if int(response_json.get("statusCode", 0)) != HTTPStatus.OK:
7493
error = response_json["body"] if "body" in response_json else response_json["errorMessage"]
75-
QMessageBox.critical(None, "API Error", f"Lambda call failed: {error}")
94+
QMessageBox.critical(None, "API Virhe", f"Lambda kutsu epäonnistui: {error}")
95+
error_handler()
7696
reply.deleteLater()
7797
return
7898
body = response_json["body"]
7999
else:
80100
body = response_json
81101

82102
except (json.JSONDecodeError, KeyError) as e:
83-
QMessageBox.critical(None, "JSON Error", f"Failed to parse response JSON: {e}")
103+
QMessageBox.critical(None, "JSON Virhe", f"Vastauksen JSON-tiedoston jäsennys epäonnistui: {e}")
104+
error_handler()
84105
return
85106
finally:
86107
reply.deleteLater()
108+
response_handler(body)
87109

88-
action = reply.request().attribute(LambdaService.ActionAttribute)
89-
if action == self.ACTION_GET_PLANS:
90-
self._process_json_reply(body)
91-
elif action == self.ACTION_VALIDATE_PLANS:
92-
self._process_validation_reply(body)
110+
def _handle_validation_error(self):
111+
self.validation_failed.emit()
93112

94113
def _process_validation_reply(self, response_json: dict):
95114
"""Processes the validation reply from the lambda and emits a signal."""
96115

97116
validation_errors = response_json.get("ryhti_responses")
98-
99117
self.validation_received.emit(validation_errors)
100118

101119
def _process_json_reply(self, response_json: dict):

arho_feature_template/core/models.py

+42-9
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,13 @@
1212
from arho_feature_template.exceptions import ConfigSyntaxError
1313
from arho_feature_template.project.layers.code_layers import AdditionalInformationTypeLayer, UndergroundTypeLayer
1414
from arho_feature_template.qgis_plugin_tools.tools.resources import resources_path
15-
from arho_feature_template.utils.misc_utils import LANGUAGE, get_layer_by_name, iface
15+
from arho_feature_template.utils.misc_utils import deserialize_localized_text, get_layer_by_name, iface
1616

1717
if TYPE_CHECKING:
1818
from datetime import datetime
1919

2020
from qgis.core import QgsFeature, QgsGeometry
21+
from qgis.PyQt.QtCore import QDate
2122

2223

2324
logger = logging.getLogger(__name__)
@@ -96,6 +97,7 @@ def from_config_file(
9697
for group_name in feature_data.get("regulation_groups", [])
9798
if (group := cls.find_matching_group_config(group_name, regulation_group_libraries))
9899
],
100+
lifecycles=[],
99101
plan_id=None,
100102
id_=None,
101103
)
@@ -144,6 +146,15 @@ def from_config_file(cls, config_fp: Path) -> RegulationGroupLibrary:
144146
],
145147
)
146148

149+
def get_short_names(self) -> set[str]:
150+
"""Returns set of non-empty short names (letter codes) of regulation groups part of the library."""
151+
return {
152+
regulation_group.short_name
153+
for category in self.regulation_group_categories
154+
for regulation_group in category.regulation_groups
155+
if regulation_group.short_name
156+
}
157+
147158

148159
@dataclass
149160
class RegulationLibrary:
@@ -246,8 +257,8 @@ class RegulationConfig:
246257

247258
id: str
248259
regulation_code: str
249-
name: str
250-
description: str
260+
name: str | None
261+
description: str | None
251262
status: str
252263
level: int
253264
parent_id: str | None
@@ -268,8 +279,8 @@ def from_feature(cls, feature: QgsFeature) -> RegulationConfig:
268279
return cls(
269280
id=feature["id"],
270281
regulation_code=feature["value"],
271-
name=feature["name"].get(LANGUAGE) if feature["name"] else None,
272-
description=feature["description"].get(LANGUAGE) if feature["description"] else None,
282+
name=deserialize_localized_text(feature["name"]),
283+
description=deserialize_localized_text(feature["description"]),
273284
status=feature["status"],
274285
level=feature["level"],
275286
parent_id=feature["parent_id"],
@@ -287,8 +298,8 @@ class AdditionalInformationConfig:
287298
# From layer
288299
id: str
289300
additional_information_type: str
290-
name: str
291-
description: str
301+
name: str | None
302+
description: str | None
292303
status: str
293304
level: int
294305
parent_id: str | None
@@ -344,8 +355,8 @@ def initialize(cls, config_fp: Path = ADDITIONAL_INFORMATION_CONFIG_PATH) -> Add
344355
ai_config = AdditionalInformationConfig(
345356
id=feature["id"],
346357
additional_information_type=ai_code,
347-
name=feature["name"].get(LANGUAGE) if feature["name"] else None,
348-
description=feature["description"].get(LANGUAGE) if feature["description"] else None,
358+
name=deserialize_localized_text(feature["name"]),
359+
description=deserialize_localized_text(feature["description"]),
349360
status=feature["status"],
350361
level=feature["level"],
351362
parent_id=feature["parent_id"],
@@ -513,6 +524,26 @@ def from_config_data(cls, data: dict) -> RegulationGroup:
513524
id_=None,
514525
)
515526

527+
def __str__(self):
528+
return " - ".join(part for part in (self.short_name, self.name) if part)
529+
530+
531+
@dataclass
532+
class LifeCycle:
533+
status_id: str | None = None
534+
id_: str | None = None
535+
plan_id: str | None = None
536+
plan_regulation_id: str | None = None
537+
plan_proposition_id: str | None = None
538+
starting_at: QDate | None = None
539+
ending_at: QDate | None = None
540+
# might not need the following
541+
land_use_are_id: str | None = None
542+
other_area_id: str | None = None
543+
line_id: str | None = None
544+
land_use_point_id: str | None = None
545+
other_point_id: str | None = None
546+
516547

517548
@dataclass
518549
class PlanFeature:
@@ -522,6 +553,7 @@ class PlanFeature:
522553
name: str | None = None
523554
description: str | None = None
524555
regulation_groups: list[RegulationGroup] = field(default_factory=list)
556+
lifecycles: list[LifeCycle] = field(default_factory=list)
525557
plan_id: int | None = None
526558
id_: str | None = None
527559

@@ -537,6 +569,7 @@ class Plan:
537569
description: str | None = None
538570
plan_type_id: str | None = None
539571
lifecycle_status_id: str | None = None
572+
lifecycles: list[LifeCycle] = field(default_factory=list)
540573
record_number: str | None = None
541574
matter_management_identifier: str | None = None
542575
permanent_plan_identifier: str | None = None

0 commit comments

Comments
 (0)