Skip to content

BDMS-139: Create Parameter table#152

Merged
jirhiker merged 27 commits into
stagingfrom
parameter_model
Oct 8, 2025
Merged

BDMS-139: Create Parameter table#152
jirhiker merged 27 commits into
stagingfrom
parameter_model

Conversation

@ksmuczynski

@ksmuczynski ksmuczynski commented Sep 26, 2025

Copy link
Copy Markdown
Contributor

Why

This PR addresses the following problem / context:

  • Need a new Parameter table to store centralized metadata about each parameter, such as its category (e.g., 'Metals', 'Field Parameter') and its unique chemical identifier (CAS Number).
  • The primary purpose of the Parameter table is is to ensure that every observation in the database is linked to a single, authoritative definition of what was measured.
  • Need a new Regulatory_Limit table to store all the specific, citable standards and limits, regulatory and health-based, associated with a given parameter.
  • The Regulatory_Limit table allows a single Parameter to have multiple different limits set by various agencies (e.g., a federal EPA limit and a state-level NMED limit).

How

Implementation summary - the following was changed / added / removed:

  • Created a new Parameter table and populated with appropriate fields and relationships.
  • Created a new Regulatory_Limit table and populated with appropriate fields and relationships.
  • Updated the lexicon.json file to include valid values for the limit_type field.
  • Added Parameter and RegulatoryLimit tables to the __init__.py file

Notes

Any special considerations, workarounds, or follow-up work to note?

  • Related validation schema files and test files still need to be created or updated.
  • Transfer script(s) needs to be created.

@codecov-commenter

codecov-commenter commented Sep 26, 2025

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 93.40102% with 13 lines in your changes missing coverage. Please review.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
tests/conftest.py 93.51% 7 Missing ⚠️
core/initializers.py 81.25% 3 Missing ⚠️
tests/test_collabnet.py 0.00% 2 Missing ⚠️
core/app.py 50.00% 1 Missing ⚠️
Files with missing lines Coverage Δ
api/search.py 97.77% <100.00%> (ø)
db/__init__.py 97.61% <100.00%> (ø)
db/lexicon.py 88.23% <100.00%> (ø)
db/observation.py 100.00% <100.00%> (ø)
db/parameter.py 100.00% <100.00%> (ø)
db/regulatory_limit.py 100.00% <100.00%> (ø)
schemas/observation.py 98.43% <100.00%> (ø)
schemas/parameter.py 100.00% <100.00%> (ø)
tests/__init__.py 100.00% <100.00%> (ø)
tests/test_observation.py 95.65% <100.00%> (ø)
... and 4 more

Comment thread db/regulatory_limit.py
Comment thread db/parameter.py Outdated
Comment thread db/parameter.py
Comment thread db/regulatory_limit.py
Comment thread db/parameter.py Outdated
Comment thread db/parameter.py
Comment thread db/parameter.py
@jirhiker

jirhiker commented Oct 1, 2025

Copy link
Copy Markdown
Member

@ksmuczynski please update the lexicon.json file to use the new normalized structure. Then I will merge this PR

@jirhiker

jirhiker commented Oct 3, 2025

Copy link
Copy Markdown
Member

@ksmuczynski tests are failing. once they are fixed i will merge PR

ksmuczynski and others added 3 commits October 6, 2025 16:15
Create parameter fixtures, update test files, update schema files, update lexicon
@jacob-a-brown

Copy link
Copy Markdown
Contributor

@jirhiker three updates needed to be made to ensure the tests past and that the API is working as expected:

  • The scope of all test fixtures needed to be changed to function (the default), otherwise too many database connections occurred and we'd receive the error sqlalchemy.exc.TimeoutError: QueuePool limit of size 5 overflow 10 reached, connection timed out, timeout 30.00. Because the fixtures are now scoped to functions they are torn down after the test is complete. This is to keep the tests independent.
  • After changing all of the fixtures the only test that was failing was tests/test_search.py::test_search_api. It would find the well and the spring, but not the contact. This happened because the concatenation of
vector = (
    Contact.search_vector
    | Email.search_vector
    | Phone.search_vector
    | Address.search_vector)

meant that if Contact, Email, Phone, or Address were NULL then the whole vector would be NULL. With the help of AI it was fixed by using

vector = (
        func.coalesce(Contact.search_vector, text("''::tsvector"))
        .op("||")(func.coalesce(Email.search_vector, text("''::tsvector")))
        .op("||")(func.coalesce(Phone.search_vector, text("''::tsvector")))
        .op("||")(func.coalesce(Address.search_vector, text("''::tsvector")))
    )

This error didn't occur previously because after the contact, email, phone, and address fixtures were invoked elsewhere they would persist. Now that invoking the contact fixture only creates a contact its related email, phone, and address attributes are NULL unless those fixtures are also invoked.

  • For similar reasons, the search results for contacts should use outerjoin incase one of the attributes does not exist.

@jirhiker jirhiker merged commit b54a05a into staging Oct 8, 2025
3 checks passed
@ksmuczynski ksmuczynski deleted the parameter_model branch October 8, 2025 19:22
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.

4 participants