Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 31 additions & 18 deletions services/ngwmn_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@

from sqlalchemy import text


def _as_text(v):
return "" if v is None else str(v)

Comment on lines +21 to +23
Copy link

Copilot AI Mar 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These changes alter NGWMN XML serialization (explicit column ordering + _as_text(None) => empty string) but there are no tests exercising services/ngwmn_helper.py output. Adding a focused unit test that builds a representative row and asserts the generated XML (including None handling and correct PointID/column-to-element mapping) would help prevent regressions as the NGWMN view schemas evolve.

Copilot uses AI. Check for mistakes.

# NSMAP = dict(xsi="http://www.w3.org/2001/XMLSchema-instance", xsd="http://www.w3.org/2001/XMLSchema")


Expand All @@ -32,12 +37,19 @@ def make_xml_response(db, sql, point_id, func):


def make_lithology_response(point_id, db):
sql = 'select * from "NMA_view_NGWMN_Lithology" where "PointID"=:point_id'
sql = (
'select "PointID", "StratTop", "StratBottom", "TERM" '
'from "NMA_view_NGWMN_Lithology" where "PointID"=:point_id'
)
return make_xml_response(db, sql, point_id, lithology_xml)


def make_well_construction_response(point_id, db):
sql = 'select * from "NMA_view_NGWMN_WellConstruction" where "PointID"=:point_id'
sql = (
'select "PointID", "CasingTop", "CasingBottom", "CasingDepthUnits", '
'"ScreenTop", "ScreenBottom", "ScreenBottomUnit", "ScreenDescription", "CasingDescription" '
'from "NMA_view_NGWMN_WellConstruction" where "PointID"=:point_id'
)
Comment on lines +48 to +52
Copy link

Copilot AI Mar 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

make_well_construction_response now selects ScreenBottomUnit and CasingDescription, but make_well_construction() never writes those fields into the XML (it only uses indices 1-5 and 7). This makes the SQL harder to reason about and wastes work; either emit corresponding XML elements (e.g., include a unit element and casing description) or drop the unused columns from the SELECT so the tuple layout matches what is actually consumed.

Copilot uses AI. Check for mistakes.
return make_xml_response(db, sql, point_id, well_construction_xml)


Expand Down Expand Up @@ -184,7 +196,7 @@ def make_continuous_water_level(root, r):
("WaterLevelAccuracy", "0.02 ft"),
):
e = etree.SubElement(elem, attr)
e.text = str(val)
e.text = _as_text(val)


def make_water_level(root, r):
Expand All @@ -206,59 +218,60 @@ def make_water_level(root, r):
("WaterLevelAccuracy", r[5]),
):
e = etree.SubElement(elem, attr)
e.text = str(val)
e.text = _as_text(val)


def make_well_construction(root, r):
"""
0 1 2 3 4 5 6, 7, 8
pointid, castop, casbottom, cadepthunits, screentop, screenbotom, units,screen description, casing description
0 1 2 3 4 5 6 7 8
pointid, castop, casbottom, cadepthunits, screentop, screenbottom, screenbottomunit, screen description, casing description
:param root:
:param r:
:return:
"""
elem = etree.SubElement(root, "Casing")
make_point_id(elem, r)
make_point_id(elem, r, idx=0)

e = etree.SubElement(elem, "CasingTop")
e.text = str(r[1])
e.text = _as_text(r[1])

e = etree.SubElement(elem, "CasingBottom")
e.text = str(r[2])
e.text = _as_text(r[2])

e = etree.SubElement(elem, "CasingDepthUnits")
e.text = str(r[3])
e.text = _as_text(r[3])

e = etree.SubElement(elem, "ScreenTop")
e.text = str(r[4])
e.text = _as_text(r[4])

e = etree.SubElement(elem, "ScreenBottom")
e.text = str(r[5])
e.text = _as_text(r[5])

e = etree.SubElement(elem, "ScreenDescription")
e.text = str(r[7])
e.text = _as_text(r[7])

e = etree.SubElement(elem, "ScreenMaterial")
e.text = "steel"


def make_lithology(root, r):
elem = etree.SubElement(root, "Lithology")
make_point_id(elem, r)
make_point_id(elem, r, idx=0)

e = etree.SubElement(elem, "TopDepth")
e.text = str(r[1])
e.text = _as_text(r[1])

e = etree.SubElement(elem, "BottomDepth")
e.text = str(r[2])
e.text = _as_text(r[2])

e = etree.SubElement(elem, "Units")
e.text = "feet"

e = etree.SubElement(elem, "Description")
e.text = str(r[3])
e.text = _as_text(r[3])


def make_point_id(elem, r, idx=0):
e = etree.SubElement(elem, "PointID")
e.text = r[idx]
v = r[idx]
e.text = _as_text(v)