Skip to content

feat(ogc): publish a well water-column layer - #885

Merged
jirhiker merged 1 commit into
feat/BDMS-976-group-a-last-observation-datefrom
feat/ogc-well-water-column-layer
Aug 24, 2026
Merged

feat(ogc): publish a well water-column layer#885
jirhiker merged 1 commit into
feat/BDMS-976-group-a-last-observation-datefrom
feat/ogc-well-water-column-layer

Conversation

@jirhiker

Copy link
Copy Markdown
Member

Stacked on #884 — base is feat/BDMS-976-group-a-last-observation-date, and this migration chains after that PR's b8c9d0e1f2a3. The diff here is the single commit on top; #884 (and the chain under it) merges first.

What

A well's construction record says how deep the hole goes and its water-level record says how far down the water sits, but nothing in the catalogue published the difference — the standing column of water in the well, which is the number that says whether a well still holds usable water.

ogc_well_water_column and its unfiltered ogc_internal_ twin carry one row per water well: the same well and location fields the water_wells layer publishes, plus four derived depths in feet.

column value
water_column_latest well depth − latest depth to water
water_column_average well depth − mean depth to water
water_column_maximum well depth − shallowest depth to water
water_column_minimum well depth − deepest depth to water

Max/min name the column, not the reading: the shallowest water level leaves the most water in the well.

Decisions

  • Manual readings only. Depth to water is value - measuring_point_height with a missing height treated as ground level — the same convention water_well_summary and latest_depth_to_water_wells already use, so the three layers cannot disagree about what a depth to water is. Continuous transducer readings are not counted.
  • Negative results are clamped to zero. A reading deeper than the recorded well depth is a contradiction between two records, not a well holding negative water. Worth knowing: a well whose readings all exceed its recorded depth publishes four zeros, which reads the same as a genuinely dry well. The contradiction stays visible in water_well_summary, which publishes the raw shallowest and deepest readings beside the well depth.
  • Materialized, because every column but the latest aggregates a well's whole reading history. The nightly pg_cron job refreshes every matview in the public schema by name, so both are picked up with no change to the schedule, and both carry a unique index on id so a manual refresh can run CONCURRENTLY.
  • Rows are restricted to wells with both a recorded depth and at least one usable reading — without either, all four columns would be NULL and the row would say nothing.

Also in the diff

Collection entries in both pygeoapi configs (public and internal) and field descriptions for the four calculated columns, so they are documented on /schema and /queryables.

Tests

Two new tests in tests/test_ogc.py: the arithmetic including the clamp (a 10 ft well with readings at 5, 2 and 14 ft below ground surface), and public-vs-internal release filtering (a well whose only reading is private drops out of the public layer and reports on the internal one). The collection is added to the catalogue and items-endpoint assertions.

Local runs: pytest --ignore=tests/transfers → 1151 passed, 84 skipped, 6 xpassed. behave --tags="@backend and @production and not @skip" → 88 scenarios passed.

Deploy note

Schema migration only — no data migration pending. The new matviews are empty until first refreshed; the nightly job covers that, or run oco refresh-matview --concurrently to populate them at deploy time.

🤖 Generated with Claude Code

A well's construction record says how deep the hole goes and its water-level
record says how far down the water sits, but nothing in the catalogue
published the difference -- the standing column of water in the well, which is
the number that says whether a well still holds usable water.

ogc_well_water_column (and its unfiltered ogc_internal_ twin) carries one row
per water well with the same well and location fields the water_wells layer
publishes, plus four derived depths in feet: the well depth less the latest
depth to water, less the mean depth to water, less the shallowest reading on
record, and less the deepest. Shallowest water leaves the most in the well and
deepest the least, hence maximum/minimum naming the column rather than the
reading.

Readings are manual groundwater-level observations taken below ground surface
as value minus measuring-point height, the same convention water_well_summary
and latest_depth_to_water_wells already use, so the three layers cannot
disagree about what a depth to water is. Continuous transducer readings are
not counted.

Negative results are clamped to zero: a reading deeper than the recorded well
depth is a contradiction between two records rather than a well holding
negative water. The contradiction itself stays visible in water_well_summary,
which publishes the raw shallowest and deepest readings beside the well depth.
Wells with no recorded depth, or no usable reading, are left out -- all four
columns would be NULL and the row would say nothing.

Materialized, because every column but the latest aggregates a well's whole
reading history. The nightly pg_cron job refreshes every matview in the public
schema by name, so the two are picked up with no change to the schedule, and
both carry a unique index on id so a manual refresh can run CONCURRENTLY.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@likithabommasani21
likithabommasani21 force-pushed the feat/ogc-well-water-column-layer branch from f321d7e to 8a0c3ce Compare August 24, 2026 19:38
@github-actions

Copy link
Copy Markdown
Contributor

Coverage

79.49% total — gate is 75%.

No measured coverage for the Python files changed here.

@jirhiker
jirhiker merged commit 1a9361a into staging Aug 24, 2026
13 checks passed
@jirhiker
jirhiker deleted the feat/ogc-well-water-column-layer branch August 24, 2026 21:48
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