Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 14 additions & 5 deletions database/models.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from __future__ import annotations

from datetime import datetime # Sqlalchemy uses this runtime
from datetime import date, datetime # Sqlalchemy uses this runtime
from typing import TYPE_CHECKING, Any
from uuid import UUID # Sqlalchemy uses this runtime

Expand Down Expand Up @@ -223,7 +223,14 @@ def lifecycle_dates(cls) -> Mapped[list[LifeCycleDate]]:
)


class Plan(PlanBase):
class PeriodOfValidityMixin:
"""Mixin for period of validity fields."""

period_of_validity_start: Mapped[date | None]
period_of_validity_end: Mapped[date | None]


class Plan(PlanBase, PeriodOfValidityMixin):
"""Maakuntakaava, compatible with Ryhti 2.0 specification"""

__tablename__ = "plan"
Expand All @@ -238,6 +245,8 @@ class Plan(PlanBase):
name: Mapped[language_str]
description: Mapped[language_str | None]
scale: Mapped[int | None]
official_use_only: Mapped[bool | None]
approval_date: Mapped[date | None]

geom: Mapped[WKBElement] = mapped_column(
type_=Geometry(geometry_type="MULTIPOLYGON", srid=PROJECT_SRID)
Expand Down Expand Up @@ -295,7 +304,7 @@ class Plan(PlanBase):
)


class PlanObjectBase(PlanBase):
class PlanObjectBase(PlanBase, PeriodOfValidityMixin):
"""All plan object tables have the same fields, apart from geometry."""

__abstract__ = True
Expand Down Expand Up @@ -549,7 +558,7 @@ class AdditionalInformation(VersionedBase, AttributeValueMixin):
)


class PlanRegulation(PlanBase, AttributeValueMixin):
class PlanRegulation(PlanBase, AttributeValueMixin, PeriodOfValidityMixin):
"""Kaavamääräys"""

__tablename__ = "plan_regulation"
Expand Down Expand Up @@ -612,7 +621,7 @@ class PlanRegulation(PlanBase, AttributeValueMixin):
subject_identifiers: Mapped[list[str] | None]


class PlanProposition(PlanBase):
class PlanProposition(PlanBase, PeriodOfValidityMixin):
"""Kaavasuositus"""

__tablename__ = "plan_proposition"
Expand Down
37 changes: 29 additions & 8 deletions database/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,34 @@

from alembic_utils.pg_view import PGView

plan_object_columns = (
"id",
"geom",
"name",
"source_data_object",
"height_unit",
"ordering",
"type_of_underground_id",
"plan_id",
"exported_at",
"lifecycle_status_id",
"created_at",
"modified_at",
"description",
"height_min",
"height_max",
"height_reference_point",
"period_of_validity_start",
"period_of_validity_end",
)

land_use_area_v = PGView(
schema="hame",
signature="land_use_area_v",
definition=dedent(
"""\
f"""\
select
*,
{",\n ".join(plan_object_columns)},
hame.short_names('land_use_area', id) short_names,
hame.primary_use_regulations(id) primary_use,
hame.regulation_values('land_use_area', id) regulation_values
Expand All @@ -22,9 +43,9 @@
schema="hame",
signature="other_area_v",
definition=dedent(
"""\
f"""\
select
*,
{",\n ".join(plan_object_columns)},
hame.short_names('other_area', id) short_names,
hame.sub_area_regulations(id) sub_area,
hame.regulation_values('other_area', id) regulation_values
Expand All @@ -38,9 +59,9 @@
schema="hame",
signature="line_v",
definition=dedent(
"""\
f"""\
select
*,
{",\n ".join(plan_object_columns)},
hame.short_names('line', id) short_names,
hame.type_regulations('line', id) type_regulations,
hame.regulation_values('line', id) regulation_values
Expand All @@ -54,9 +75,9 @@
schema="hame",
signature="point_v",
definition=dedent(
"""\
f"""\
select
*,
{",\n ".join(plan_object_columns)},
hame.short_names('point', id) short_names,
hame.type_regulations('point', id) type_regulations,
hame.regulation_values('point', id) regulation_values
Expand Down
60 changes: 32 additions & 28 deletions lambdas/ryhti_client/ryhti_client/database_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,14 @@ def get_last_period(self, periods: list[Period]) -> Period | None:
"""Returns the last period in the list, or None if the list is empty."""
return periods[-1] if periods else None

def serialize_date_period(
self, date_start: datetime.date, date_end: datetime.date | None
) -> Period:
return {
"begin": date_start.isoformat(),
"end": date_end.isoformat() if date_end else None,
}

def get_plan_recommendation(
self, plan_recommendation: models.PlanProposition
) -> dict:
Expand All @@ -272,12 +280,12 @@ def get_plan_recommendation(
plan_theme.uri for plan_theme in plan_recommendation.plan_themes
]
recommendation_dict["recommendationNumber"] = plan_recommendation.ordering
# we should only have one valid period. If there are several, pick last
recommendation_dict["periodOfValidity"] = self.get_last_period(
self.get_lifecycle_periods(
plan_recommendation, self.valid_status_value, datetimes=False

if plan_recommendation.period_of_validity_start:
recommendation_dict["periodOfValidity"] = self.serialize_date_period(
plan_recommendation.period_of_validity_start,
plan_recommendation.period_of_validity_end,
)
)
recommendation_dict["value"] = self.format_language_string_value(
plan_recommendation.text_value
)
Expand Down Expand Up @@ -384,12 +392,12 @@ def get_plan_regulation(self, plan_regulation: models.PlanRegulation) -> dict:
]
regulation_dict["subjectIdentifiers"] = plan_regulation.subject_identifiers
regulation_dict["regulationNumber"] = str(plan_regulation.ordering)
# we should only have one valid period. If there are several, pick last
regulation_dict["periodOfValidity"] = self.get_last_period(
self.get_lifecycle_periods(
plan_regulation, self.valid_status_value, datetimes=False

if plan_regulation.period_of_validity_start:
regulation_dict["periodOfValidity"] = self.serialize_date_period(
plan_regulation.period_of_validity_start,
plan_regulation.period_of_validity_end,
)
)

if plan_regulation.types_of_verbal_plan_regulations:
regulation_dict["verbalRegulations"] = [
Expand Down Expand Up @@ -453,12 +461,11 @@ def get_plan_object(self, plan_object: models.PlanObjectBase) -> dict:
plan_object.description
)
plan_object_dict["objectNumber"] = plan_object.ordering
# we should only have one valid period. If there are several, pick last
plan_object_dict["periodOfValidity"] = self.get_last_period(
self.get_lifecycle_periods(
plan_object, self.valid_status_value, datetimes=False

if plan_object.period_of_validity_start:
plan_object_dict["periodOfValidity"] = self.serialize_date_period(
plan_object.period_of_validity_start, plan_object.period_of_validity_end
)
)
if plan_object.height_min or plan_object.height_max:
plan_object_dict["verticalLimit"] = {
"dataType": "DecimalRange",
Expand Down Expand Up @@ -613,7 +620,10 @@ def get_plan_dictionary(self, plan: models.Plan) -> RyhtiPlan:
plan_description = (
plan.description.get("fin") if isinstance(plan.description, dict) else None
)
plan_dictionary["planDescription"] = plan_description
if plan_description:
plan_dictionary["planDescription"] = plan_description
if plan.official_use_only:
plan_dictionary["officialUseOnly"] = plan.official_use_only

# Here come the dependent objects. They are related to the plan directly or
# via the plan objects, so we better fetch the objects first and then move on.
Expand All @@ -640,19 +650,13 @@ def get_plan_dictionary(self, plan: models.Plan) -> RyhtiPlan:
self.get_plan_regulation_group_relations(plan_objects)
)

# we should only have one valid period. If there are several, pick last
plan_dictionary["periodOfValidity"] = self.get_last_period(
self.get_lifecycle_periods(plan, self.valid_status_value, datetimes=False)
)
# we should only have one approved period. If there are several, pick last
period_of_approval = self.get_last_period(
self.get_lifecycle_periods(
plan, self.approved_status_value, datetimes=False
if plan.approval_date:
plan_dictionary["approvalDate"] = plan.approval_date.isoformat()

if plan.period_of_validity_start:
plan_dictionary["periodOfValidity"] = self.serialize_date_period(
plan.period_of_validity_start, plan.period_of_validity_end
)
)
plan_dictionary["approvalDate"] = (
period_of_approval["begin"] if period_of_approval else None
)

# Documents are divided into different categories. They may only be added
# to plan *after* they have been uploaded.
Expand Down
Loading