Skip to content

Commit 6d2d810

Browse files
committed
fix(well-inventory): preserve attempted water-level records when depth-to-water is blank
- Treat blank depth_to_water_ft values as missing instead of invalid numeric input - Create water-level sample and observation records when water_level_date_time is present even if no depth value was obtained - Preserve attempted measurements for dry, obstructed, or otherwise unreadable wells without dropping the observation record
1 parent a7bad53 commit 6d2d810

3 files changed

Lines changed: 60 additions & 7 deletions

File tree

schemas/well_inventory.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -326,7 +326,7 @@ class WellInventoryRow(BaseModel):
326326
validation_alias=AliasChoices("mp_height", "mp_height_ft"),
327327
)
328328
level_status: Optional[str] = None
329-
depth_to_water_ft: Optional[float] = None
329+
depth_to_water_ft: OptionalFloat = None
330330
data_quality: DataQualityField = None
331331
water_level_notes: Optional[str] = None
332332

services/well_inventory_csv.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -739,12 +739,7 @@ def _add_csv_row(session: Session, group: Group, model: WellInventoryRow, user)
739739
)
740740
session.add(fa)
741741

742-
if model.depth_to_water_ft is not None:
743-
if model.measurement_date_time is None:
744-
raise ValueError(
745-
"water_level_date_time is required when depth_to_water_ft is provided"
746-
)
747-
742+
if model.measurement_date_time is not None:
748743
# get groundwater level parameter
749744
parameter = (
750745
session.query(Parameter)
@@ -790,6 +785,7 @@ def _add_csv_row(session: Session, group: Group, model: WellInventoryRow, user)
790785
value=model.depth_to_water_ft,
791786
unit="ft",
792787
observation_datetime=model.measurement_date_time,
788+
measuring_point_height=model.mp_height,
793789
nma_data_quality=(
794790
model.data_quality.value
795791
if hasattr(model.data_quality, "value")

tests/test_well_inventory.py

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@
1919
Location,
2020
LocationThingAssociation,
2121
Thing,
22+
Sample,
23+
Observation,
2224
Contact,
2325
ThingContactAssociation,
2426
FieldEvent,
@@ -455,6 +457,43 @@ def test_well_inventory_db_contents():
455457
assert participant.participant.name == file_content["field_staff_2"]
456458

457459

460+
def test_blank_depth_to_water_still_creates_water_level_records(tmp_path):
461+
"""Blank depth-to-water is treated as missing while preserving the attempted measurement."""
462+
row = _minimal_valid_well_inventory_row()
463+
row.update(
464+
{
465+
"water_level_date_time": "2025-02-15T10:30:00",
466+
"depth_to_water_ft": "",
467+
"sample_method": "Steel-tape measurement",
468+
"data_quality": "Water level accurate to within two hundreths of a foot",
469+
"water_level_notes": "Attempted measurement",
470+
"mp_height_ft": 2.5,
471+
}
472+
)
473+
474+
file_path = tmp_path / "well-inventory-blank-depth.csv"
475+
with file_path.open("w", encoding="utf-8", newline="") as f:
476+
writer = csv.DictWriter(f, fieldnames=list(row.keys()))
477+
writer.writeheader()
478+
writer.writerow(row)
479+
480+
result = well_inventory_csv(file_path)
481+
assert result.exit_code == 0, result.stderr
482+
483+
with session_ctx() as session:
484+
samples = session.query(Sample).all()
485+
observations = session.query(Observation).all()
486+
487+
assert len(samples) == 1
488+
assert len(observations) == 1
489+
assert samples[0].sample_date == datetime.fromisoformat("2025-02-15T10:30:00")
490+
assert observations[0].observation_datetime == datetime.fromisoformat(
491+
"2025-02-15T10:30:00"
492+
)
493+
assert observations[0].value is None
494+
assert observations[0].measuring_point_height == 2.5
495+
496+
458497
# =============================================================================
459498
# Error Handling Tests - Cover API error paths
460499
# =============================================================================
@@ -1037,6 +1076,24 @@ def test_water_level_aliases_are_mapped(self):
10371076
"2025-02-15T10:30:00"
10381077
)
10391078
assert model.mp_height == 2.5
1079+
assert model.depth_to_water_ft == 11.2
1080+
assert model.water_level_notes == "Initial reading"
1081+
1082+
def test_blank_depth_to_water_is_treated_as_none(self):
1083+
row = _minimal_valid_well_inventory_row()
1084+
row.update(
1085+
{
1086+
"water_level_date_time": "2025-02-15T10:30:00",
1087+
"depth_to_water_ft": "",
1088+
}
1089+
)
1090+
1091+
model = WellInventoryRow(**row)
1092+
1093+
assert model.measurement_date_time == datetime.fromisoformat(
1094+
"2025-02-15T10:30:00"
1095+
)
1096+
assert model.depth_to_water_ft is None
10401097

10411098
def test_canonical_name_wins_when_alias_and_canonical_present(self):
10421099
row = _minimal_valid_well_inventory_row()

0 commit comments

Comments
 (0)