|
14 | 14 | # limitations under the License. |
15 | 15 | # =============================================================================== |
16 | 16 | import importlib |
| 17 | +from datetime import datetime, timedelta, timezone |
17 | 18 |
|
18 | | -from sqlalchemy import select |
| 19 | +from sqlalchemy import delete, select |
19 | 20 |
|
20 | 21 | move_notes = importlib.import_module( |
21 | 22 | "data_migrations.migrations.20260205_0001_move_nma_location_notes" |
22 | 23 | ) |
23 | 24 | publish_project_areas = importlib.import_module( |
24 | 25 | "data_migrations.migrations.20260714_0001_publish_project_areas" |
25 | 26 | ) |
| 27 | +backfill_acoustic_maturity = importlib.import_module( |
| 28 | + "data_migrations.migrations.20260820_0001_backfill_acoustic_data_maturity" |
| 29 | +) |
26 | 30 | from db.location import Location |
27 | 31 | from db.notes import Notes |
28 | 32 | from db.group import Group |
29 | 33 | from db.engine import session_ctx |
| 34 | +from db.transducer import TransducerObservation |
| 35 | +from tests import get_parameter_id |
30 | 36 |
|
31 | 37 |
|
32 | 38 | def test_move_nma_location_notes_creates_notes_and_clears_field(): |
@@ -139,3 +145,91 @@ def test_publish_project_areas_marks_project_area_groups_public(): |
139 | 145 | session.delete(draft_with_area) |
140 | 146 | session.delete(draft_without_area) |
141 | 147 | session.commit() |
| 148 | + |
| 149 | + |
| 150 | +def test_backfill_acoustic_data_maturity_only_touches_null_acoustic_rows( |
| 151 | + sensor_to_water_well_thing_deployment, |
| 152 | +): |
| 153 | + deployment_id = sensor_to_water_well_thing_deployment.id |
| 154 | + parameter_id = get_parameter_id("groundwater level", "Field Parameter") |
| 155 | + observed = datetime(2019, 7, 23, 12, 0, tzinfo=timezone.utc) |
| 156 | + |
| 157 | + with session_ctx() as session: |
| 158 | + # An acoustic row with no maturity -- the case this migration exists for. |
| 159 | + acoustic = TransducerObservation( |
| 160 | + parameter_id=parameter_id, |
| 161 | + deployment_id=deployment_id, |
| 162 | + observation_datetime=observed, |
| 163 | + value=42.0, |
| 164 | + nma_waterlevelscontinuous_acoustic_global_id="ACOUSTIC-NULL", |
| 165 | + ) |
| 166 | + # An acoustic row whose maturity was already set deliberately. The |
| 167 | + # blanket value must not overwrite a decision someone made. |
| 168 | + acoustic_already_set = TransducerObservation( |
| 169 | + parameter_id=parameter_id, |
| 170 | + deployment_id=deployment_id, |
| 171 | + observation_datetime=observed + timedelta(hours=1), |
| 172 | + value=43.0, |
| 173 | + nma_waterlevelscontinuous_acoustic_global_id="ACOUSTIC-SET", |
| 174 | + data_maturity="provisional", |
| 175 | + ) |
| 176 | + # A pressure row with no maturity. NULL here means the pressure QC flag |
| 177 | + # was NULL, which is a different question -- leave it alone. |
| 178 | + pressure = TransducerObservation( |
| 179 | + parameter_id=parameter_id, |
| 180 | + deployment_id=deployment_id, |
| 181 | + observation_datetime=observed + timedelta(hours=2), |
| 182 | + value=44.0, |
| 183 | + nma_waterlevelscontinuous_pressure_global_id="PRESSURE-NULL", |
| 184 | + ) |
| 185 | + session.add_all([acoustic, acoustic_already_set, pressure]) |
| 186 | + session.commit() |
| 187 | + ids = (acoustic.id, acoustic_already_set.id, pressure.id) |
| 188 | + |
| 189 | + try: |
| 190 | + backfill_acoustic_maturity.run(session) |
| 191 | + |
| 192 | + session.refresh(acoustic) |
| 193 | + session.refresh(acoustic_already_set) |
| 194 | + session.refresh(pressure) |
| 195 | + assert acoustic.data_maturity == backfill_acoustic_maturity.MATURITY |
| 196 | + assert acoustic_already_set.data_maturity == "provisional" |
| 197 | + assert pressure.data_maturity is None |
| 198 | + finally: |
| 199 | + session.execute( |
| 200 | + delete(TransducerObservation).where(TransducerObservation.id.in_(ids)) |
| 201 | + ) |
| 202 | + session.commit() |
| 203 | + |
| 204 | + |
| 205 | +def test_backfill_acoustic_data_maturity_is_idempotent( |
| 206 | + sensor_to_water_well_thing_deployment, |
| 207 | +): |
| 208 | + deployment_id = sensor_to_water_well_thing_deployment.id |
| 209 | + parameter_id = get_parameter_id("groundwater level", "Field Parameter") |
| 210 | + |
| 211 | + with session_ctx() as session: |
| 212 | + observation = TransducerObservation( |
| 213 | + parameter_id=parameter_id, |
| 214 | + deployment_id=deployment_id, |
| 215 | + observation_datetime=datetime(2020, 1, 1, tzinfo=timezone.utc), |
| 216 | + value=45.0, |
| 217 | + nma_waterlevelscontinuous_acoustic_global_id="ACOUSTIC-REPEAT", |
| 218 | + ) |
| 219 | + session.add(observation) |
| 220 | + session.commit() |
| 221 | + observation_id = observation.id |
| 222 | + |
| 223 | + try: |
| 224 | + backfill_acoustic_maturity.run(session) |
| 225 | + backfill_acoustic_maturity.run(session) |
| 226 | + |
| 227 | + session.refresh(observation) |
| 228 | + assert observation.data_maturity == backfill_acoustic_maturity.MATURITY |
| 229 | + finally: |
| 230 | + session.execute( |
| 231 | + delete(TransducerObservation).where( |
| 232 | + TransducerObservation.id == observation_id |
| 233 | + ) |
| 234 | + ) |
| 235 | + session.commit() |
0 commit comments