Skip to content

Add plan cancellation info and up-to-date plan views - #598

Merged
LKajan merged 15 commits into
mainfrom
plan-cancellation-info
Sep 15, 2026
Merged

LKajan merged 15 commits into
mainfrom
plan-cancellation-info

Conversation

@LKajan

@LKajan LKajan commented Sep 15, 2026

Copy link
Copy Markdown
Collaborator

No description provided.

LKajan and others added 15 commits September 7, 2026 15:26
Import valid plans from the Ryhti WFS service with OWSLib, bounded by a
municipality or region geometry. Creates a plan matter and a plan per
feature. Also stop alembic from disabling application loggers.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
A plan can be valid and still be work in progress in this database. The
new hame.plan.final flag says that the plan content is complete and may
be published to read-only consumers. plan_valid requires it on top of the
lifecycle status and validity period checks, and the other valid views
inherit the check through plan_valid.

The final column is left out of the plan_valid column list, since every
row of the view is final. That keeps the column list unchanged, so the
migration can use CREATE OR REPLACE VIEW instead of dropping every
dependent view and re-granting them.

WFS imported plans are marked final, because the service only publishes
complete valid plans.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JKnFNyyjs8AD9jXw6ij7CF
The stored kaavalaji code is usually a lower level code such as 11
Kokonaismaakuntakaava, so the view now also resolves it to its level 1
ancestor: 1 maakuntakaava, 2 yleiskaava or 3 asemakaava.

The migration re-grants select, because the downgrade removes a column
and alembic_utils then drops and recreates the view instead of replacing
it, which loses the grants.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Serialization to Ryhti is a separate step, so this only adds the tables.

test_db geom_columns only found columns named geom, so it now selects
geometry columns by their type. The plan_instance fixture used a UUID
object as its id while every other row uses a string, which broke a
flush that contained two plans.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
A plan matter marked repealing repeals every valid plan of the same level 1
plan type that its plans overlap, and the triggers keep the rows in step with
the plan geometry.

hame.repealed_plans and hame.repealed_plan_objects say what the rows should be
and can be selected on their own; hame.refresh_plan_cancellation_info only
writes what they return. The plan rows are upserted so that a plan that stays
repealed keeps its row id, and with it the cancelled group relations added by
hand.

The repealing column lands among the existing columns of plan_matter_valid, so
CREATE OR REPLACE VIEW cannot make the change and the view is dropped and
created again. That drops its grants, which the migration grants back.

Not covered: editing a repealed plan does not refresh the rows of the plans
that repeal it, cancelled group relations are still filled by hand, nothing
sets a repealed plan to lifecycle status 14, and the serializer does not yet
send planCancellationInfos to Ryhti.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JKnFNyyjs8AD9jXw6ij7CF
The action publishes a plan through the read-only valid views. The plan must
have lifecycle status 13 and be valid today, and it must pass Ryhti validation,
which the action runs and saves like validate_plan does. It then refreshes the
cancellation info, repeals the plans and plan objects that are cancelled whole,
and sets final.

The cancellation info has to be refreshed before anything is repealed, because
hame.repealed_plans reads hame.plan_valid, which a repealed plan leaves as soon
as it gets lifecycle status 14. A plan that is already final is refused, so a
second run cannot wipe the rows. Editing the geometry of a plan that is final
already has the same effect through the existing trigger, which this does not
address.

PostgreSQL cannot revoke a single column from a table wide update grant, so
arho_read_write now gets update on the plan columns one by one, with final left
out. The lambda owns the tables and is not bound by the grants.

The plan cancellation fixtures move from test_cancellation_triggers to conftest,
because two test modules use them now.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
A repealed plan now ends on the day the repealing plan begins, as Ryhti
does. The new trigger hame.trg_plan_repealed gives the plan objects,
regulations and propositions of a repealed plan the same status and
end date. docs/known-issues.md lists the Ryhti rule 248 mismatch that
is left open.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The serializer writes planCancellationInfos in the valid and repealed
lifecycle statuses, the import writes the rows of the file as they are
and marks the plan matter repealing, and the copier clones the rows. The
validate and finalize actions refresh the rows before serializing.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
A plan or plan object that a repealing plan repeals only in part stays
valid on the part the repealing plan does not cover. The valid views now
derive that geometry: the plan geometry minus the repealing plans, and the
intersection of the remaining valid geometries of a plan object. A row
with nothing left is dropped. See docs/adr/0002.

hame.repealed_plans tests the overlap against the stored plan geometry,
so a final repealing plan does not clip its own target away and keep
rewriting its cancellation info row.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This is because this can be tested without the cancelled plans existing in Ryhti.
MinIO no longer publishes images on Docker Hub, so CI could not start
the test containers.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@LKajan
LKajan merged commit 38b3e3b into main Sep 15, 2026
2 checks passed
@LKajan
LKajan deleted the plan-cancellation-info branch September 15, 2026 20:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant