From a01e0915c25df36a8e046707531f6436499b1d04 Mon Sep 17 00:00:00 2001 From: jacob-a-brown Date: Fri, 20 Mar 2026 16:31:03 -0600 Subject: [PATCH 1/3] fix(well inventory): allow null mp heights --- services/well_inventory_csv.py | 5 ----- tests/test_well_inventory.py | 32 ++++---------------------------- 2 files changed, 4 insertions(+), 33 deletions(-) diff --git a/services/well_inventory_csv.py b/services/well_inventory_csv.py index 89ece733..1cd8b2e2 100644 --- a/services/well_inventory_csv.py +++ b/services/well_inventory_csv.py @@ -837,11 +837,6 @@ def _add_csv_row(session: Session, group: Group, model: WellInventoryRow, user) session.add(sample) session.flush() - if model.depth_to_water_ft is not None and universal_mp_height is None: - raise ValueError( - "measuring_point_height_ft or mp_height is required when depth_to_water_ft is provided for a non-null observation" - ) - # create Observation # TODO: groundwater_level_reason may be conditionally required for null depth_to_water_ft - handle accordingly observation = Observation( diff --git a/tests/test_well_inventory.py b/tests/test_well_inventory.py index fd27e395..fdb17f6e 100644 --- a/tests/test_well_inventory.py +++ b/tests/test_well_inventory.py @@ -598,14 +598,14 @@ def test_mp_height_used_for_thing_and_observation_when_measuring_point_height_ft assert observations[0].measuring_point_height == 4.0 -def test_null_observation_allows_blank_mp_height(tmp_path): - """When depth to water is not provided (ie null), blank measuring_point_height_ft and mp_height fields should be allowed and result in a null measuring_point_height for the observation and no associated measuring point height (MeasuringPointHistory) for the well.""" +def test_null_mp_height_allowed(tmp_path): + """A null measuring_point_height_ft and mp_height area allowed when depth to water is provided, and results in null measuring_point_height for the thing and observation.""" row = _minimal_valid_well_inventory_row() row.update( { "measuring_point_height_ft": "", "water_level_date_time": "2025-02-15T10:30:00", - "depth_to_water_ft": "", + "depth_to_water_ft": 8, "sample_method": "Steel-tape measurement", "data_quality": "Water level accurate to within two hundreths of a foot", "water_level_notes": "Attempted measurement", @@ -628,6 +628,7 @@ def test_null_observation_allows_blank_mp_height(tmp_path): assert len(things) == 1 assert things[0].measuring_point_height is None assert len(observations) == 1 + assert observations[0].value == 8 assert observations[0].measuring_point_height is None @@ -658,31 +659,6 @@ def test_conflicting_mp_heights_raises_error(tmp_path): ) -def test_no_mp_height_raises_error_when_depth_to_water_provided(tmp_path): - row = _minimal_valid_well_inventory_row() - row.update( - { - "water_level_date_time": "2025-02-15T10:30:00", - "measuring_point_height_ft": "", - "mp_height": "", - "depth_to_water_ft": "8", - } - ) - - file_path = tmp_path / "well-inventory-no-mp-height.csv" - with file_path.open("w", encoding="utf-8", newline="") as f: - writer = csv.DictWriter(f, fieldnames=list(row.keys())) - writer.writeheader() - writer.writerow(row) - - result = well_inventory_csv(file_path) - assert result.exit_code == 1, result.stderr - assert ( - result.payload["validation_errors"][0]["error"] - == "measuring_point_height_ft or mp_height is required when depth_to_water_ft is provided for a non-null observation" - ) - - def test_blank_depth_to_water_still_creates_water_level_records(tmp_path): """Blank depth-to-water is treated as missing while preserving the attempted measurement.""" row = _minimal_valid_well_inventory_row() From 6d03bf42452ff72edc02314d1366245e20664cb9 Mon Sep 17 00:00:00 2001 From: jacob-a-brown Date: Fri, 20 Mar 2026 16:39:43 -0600 Subject: [PATCH 2/3] fix(well inventory): use one mp height for thing and gwl --- services/well_inventory_csv.py | 20 ++++++++++++++++++-- tests/test_well_inventory.py | 6 +++--- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/services/well_inventory_csv.py b/services/well_inventory_csv.py index 217fd736..a2c21c50 100644 --- a/services/well_inventory_csv.py +++ b/services/well_inventory_csv.py @@ -687,6 +687,22 @@ def _add_csv_row(session: Session, group: Group, model: WellInventoryRow, user) } ) + if ( + model.mp_height is not None + and model.measuring_point_height_ft is not None + and model.mp_height != model.measuring_point_height_ft + ): + raise ValueError( + "Conflicting values for measuring point height: mp_height and measuring_point_height_ft" + ) + + if model.measuring_point_height_ft is not None: + universal_mp_height = model.measuring_point_height_ft + elif model.mp_height is not None: + universal_mp_height = model.mp_height + else: + universal_mp_height = None + data = CreateWell( location_id=loc.id, group_id=group.id, @@ -695,7 +711,7 @@ def _add_csv_row(session: Session, group: Group, model: WellInventoryRow, user) well_depth=model.total_well_depth_ft, well_depth_source=model.depth_source, well_casing_diameter=model.casing_diameter_ft, - measuring_point_height=model.measuring_point_height_ft, + measuring_point_height=universal_mp_height, measuring_point_description=model.measuring_point_description, well_completion_date=model.date_drilled, well_completion_date_source=model.completion_source, @@ -839,7 +855,7 @@ def _add_csv_row(session: Session, group: Group, model: WellInventoryRow, user) value=model.depth_to_water_ft, unit="ft", observation_datetime=model.measurement_date_time, - measuring_point_height=model.mp_height, + measuring_point_height=universal_mp_height, groundwater_level_reason=( model.level_status.value if hasattr(model.level_status, "value") diff --git a/tests/test_well_inventory.py b/tests/test_well_inventory.py index 23dfa537..9b4fe0df 100644 --- a/tests/test_well_inventory.py +++ b/tests/test_well_inventory.py @@ -482,7 +482,7 @@ def test_well_inventory_db_contents_with_waterlevels(tmp_path): "sample_method": "Steel-tape measurement", "data_quality": "Water level accurate to within two hundreths of a foot", "water_level_notes": "Attempted measurement", - "mp_height_ft": 2.5, + "mp_height_ft": 3.5, "level_status": "Water level not affected", } ) @@ -670,7 +670,7 @@ def test_blank_depth_to_water_still_creates_water_level_records(tmp_path): "sample_method": "Steel-tape measurement", "data_quality": "Water level accurate to within two hundreths of a foot", "water_level_notes": "Attempted measurement", - "mp_height_ft": 2.5, + "mp_height_ft": 3.5, } ) @@ -694,7 +694,7 @@ def test_blank_depth_to_water_still_creates_water_level_records(tmp_path): "2025-02-15T10:30:00Z" ) assert observations[0].value is None - assert observations[0].measuring_point_height == 2.5 + assert observations[0].measuring_point_height == 3.5 def test_rerunning_same_well_inventory_csv_is_idempotent(): From cf7ca5a27c5018f781452abe1ab66b25469e8038 Mon Sep 17 00:00:00 2001 From: jacob-a-brown Date: Fri, 20 Mar 2026 16:41:29 -0600 Subject: [PATCH 3/3] fix(test): fix typo in doc string --- tests/test_well_inventory.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_well_inventory.py b/tests/test_well_inventory.py index 9b4fe0df..95a950db 100644 --- a/tests/test_well_inventory.py +++ b/tests/test_well_inventory.py @@ -600,7 +600,7 @@ def test_mp_height_used_for_thing_and_observation_when_measuring_point_height_ft def test_null_mp_height_allowed(tmp_path): - """A null measuring_point_height_ft and mp_height area allowed when depth to water is provided, and results in null measuring_point_height for the thing and observation.""" + """A null measuring_point_height_ft and mp_height are allowed when depth to water is provided, and results in null measuring_point_height for the thing and observation.""" row = _minimal_valid_well_inventory_row() row.update( {