From 94a6daed95d8f4445ff40762460b99b961f44a4d Mon Sep 17 00:00:00 2001 From: ksmuczynski Date: Fri, 7 Nov 2025 12:17:02 -0700 Subject: [PATCH 1/5] feat: update group model and expand lexicon Refactored Group model in db/group.py, adding the `group_type` and `monitoring_frequency` fields. Added new categories and terms to core/lexicon.json to support expanded group types and monitoring frequencies. --- core/lexicon.json | 13 +++++++++++-- db/group.py | 6 +++++- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/core/lexicon.json b/core/lexicon.json index f1a77ed24..e39c99f87 100644 --- a/core/lexicon.json +++ b/core/lexicon.json @@ -18,10 +18,12 @@ {"name": "email_type", "description": null}, {"name": "participant_role", "description": null}, {"name": "geochronology", "description": null}, - {"name": "horizontal_datum", "description": null}, {"name": "groundwater_level_reason", "description": null}, + {"name": "group_type", "description": null}, + {"name": "horizontal_datum", "description": null}, {"name": "limit_type", "description": null}, {"name": "measurement_method", "description": null}, + {"name": "monitoring_frequency", "description": null}, {"name": "monitoring_status", "description": null}, {"name": "parameter_name", "description": null}, {"name": "organization", "description": null}, @@ -673,6 +675,13 @@ {"categories": ["sensor_status"], "term": "In Service", "definition": "In Service"}, {"categories": ["sensor_status"], "term": "In Repair", "definition": "In Repair"}, {"categories": ["sensor_status"], "term": "Retired", "definition": "Retired"}, - {"categories": ["sensor_status"], "term": "Lost", "definition": "Lost"} + {"categories": ["sensor_status"], "term": "Lost", "definition": "Lost"}, + {"categories": ["group_type"], "term": "Monitoring Plan", "definition": "A group of `Things` that are monitored together for a specific programmatic or scientific purpose."}, + {"categories": ["group_type"], "term": "Geographic Area", "definition": "A group of `Things` that fall within a specific, user-defined or official spatial boundary. E.g, `Wells in the Estancia Basin`."}, + {"categories": ["group_type"], "term": "Historical", "definition": "A group of `Things` that share a common historical attribute. E.g., 'Wells drilled before 1950', 'Legacy Wells (Pre-1990)'."}, + {"categories": ["monitoring_frequency"], "term": "Monthly", "definition": "Location is monitored on a monthly basis."}, + {"categories": ["monitoring_frequency"], "term": "Quarterly", "definition": "Location is monitored on a quarterly basis."}, + {"categories": ["monitoring_frequency"], "term": "Biannual", "definition": "Location is monitored twice a year."}, + {"categories": ["monitoring_frequency"], "term": "Annual", "definition": "Location is monitored once a year."} ] } \ No newline at end of file diff --git a/db/group.py b/db/group.py index a0943d2bb..caa42dd72 100644 --- a/db/group.py +++ b/db/group.py @@ -31,11 +31,15 @@ class Group(Base, AutoBaseMixin, ReleaseMixin): # --- Column Definitions --- - description: Mapped[str] = mapped_column(String(255), nullable=True) name: Mapped[str] = mapped_column(String(100), nullable=False, unique=True) + description: Mapped[str] = mapped_column(String(255), nullable=True) project_area: Mapped[Optional[WKBElement]] = mapped_column( Geometry(geometry_type="MULTIPOLYGON", srid=SRID_WGS84, spatial_index=True) ) + group_type: Mapped[Optional[str]] = mapped_column(String(50), nullable=True) + monitoring_frequency: Mapped[Optional[str]] = mapped_column( + String(50), nullable=True + ) # Foreign Keys parent_group_id: Mapped[Optional[int]] = mapped_column( From 9858ec2fd532cf4962cc6a7355c415117d9ef00a Mon Sep 17 00:00:00 2001 From: ksmuczynski Date: Fri, 7 Nov 2025 14:54:11 -0700 Subject: [PATCH 2/5] refactor: update lexicon category names and terms associated with the StatusHistory table. `well_status` is defined as a lexicon category, but it should be a lexicon value associated with the `status_type` category. The `status_type` category does not exist, but it should. The terms assigned to the `well_status` category should actually be assigned to the `status_value` category. Renamed `well_status` category to `status_value`. Added new `status_type` category and related terms. Updated term definitions. --- core/lexicon.json | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/core/lexicon.json b/core/lexicon.json index e39c99f87..c6ed3a7a0 100644 --- a/core/lexicon.json +++ b/core/lexicon.json @@ -49,7 +49,8 @@ {"name": "unit", "description": null}, {"name": "vertical_datum", "description": null}, {"name": "well_purpose", "description": null}, - {"name": "well_status", "description": null} + {"name": "status_type", "description": null}, + {"name": "status_value", "description": null} ], "terms": [ {"categories": ["review_status"], "term": "approved", "definition": "approved"}, @@ -323,10 +324,13 @@ {"categories": ["groundwater_level_reason"], "term": "Water level affected by stage in nearby surface-water site", "definition": "Water level affected by stage in nearby surface-water site"}, {"categories": ["groundwater_level_reason"], "term": "Other conditions exist that would affect the level (remarks)", "definition": "Other conditions exist that would affect the level (remarks)"}, {"categories": ["groundwater_level_reason"], "term": "Water level not affected", "definition": "Water level not affected"}, - {"categories": ["well_status"], "term": "Abandoned", "definition": "Abandoned"}, - {"categories": ["well_status"], "term": "Active, pumping well", "definition": "Active, pumping well"}, - {"categories": ["well_status"], "term": "Destroyed, exists but not usable", "definition": "Destroyed, exists but not usable"}, - {"categories": ["well_status"], "term": "Inactive, exists but not used", "definition": "Inactive, exists but not used"}, + {"categories": ["status_type"], "term": "Well status", "definition": "Defines the well's operational condition as reported by the owner"}, + {"categories": ["status_type"], "term": "Monitoring status", "definition": "Defines the well's current monitoring status by NMBGMR."}, + {"categories": ["status_type"], "term": "Access status", "definition": "Defines the well's access status for field personnel."}, + {"categories": ["status_value"], "term": "Abandoned", "definition": "The well has been properly decommissioned."}, + {"categories": ["status_value"], "term": "Active, pumping well", "definition": "This well is in use."}, + {"categories": ["status_value"], "term": "Destroyed, exists but not usable", "definition": "The well structure is physically present but is damaged, collapsed, or otherwise compromised to the point that it is non-functional."}, + {"categories": ["status_value"], "term": "Inactive, exists but not used", "definition": "The well is not currently in use but is believed to be in a usable condition; it has not been permanently decommissioned/abandoned."}, {"categories": ["sample_method"], "term": "Airline measurement", "definition": "Airline measurement"}, {"categories": ["sample_method"], "term": "Analog or graphic recorder", "definition": "Analog or graphic recorder"}, {"categories": ["sample_method"], "term": "Calibrated airline measurement", "definition": "Calibrated airline measurement"}, From 19c2904b0dfd60ccac15078bcde2064911ae56e6 Mon Sep 17 00:00:00 2001 From: ksmuczynski Date: Fri, 7 Nov 2025 14:57:22 -0700 Subject: [PATCH 3/5] refactor: list status_type terms in proper case. --- core/lexicon.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/lexicon.json b/core/lexicon.json index c6ed3a7a0..ca20c93e4 100644 --- a/core/lexicon.json +++ b/core/lexicon.json @@ -324,9 +324,9 @@ {"categories": ["groundwater_level_reason"], "term": "Water level affected by stage in nearby surface-water site", "definition": "Water level affected by stage in nearby surface-water site"}, {"categories": ["groundwater_level_reason"], "term": "Other conditions exist that would affect the level (remarks)", "definition": "Other conditions exist that would affect the level (remarks)"}, {"categories": ["groundwater_level_reason"], "term": "Water level not affected", "definition": "Water level not affected"}, - {"categories": ["status_type"], "term": "Well status", "definition": "Defines the well's operational condition as reported by the owner"}, - {"categories": ["status_type"], "term": "Monitoring status", "definition": "Defines the well's current monitoring status by NMBGMR."}, - {"categories": ["status_type"], "term": "Access status", "definition": "Defines the well's access status for field personnel."}, + {"categories": ["status_type"], "term": "Well Status", "definition": "Defines the well's operational condition as reported by the owner"}, + {"categories": ["status_type"], "term": "Monitoring Status", "definition": "Defines the well's current monitoring status by NMBGMR."}, + {"categories": ["status_type"], "term": "Access Status", "definition": "Defines the well's access status for field personnel."}, {"categories": ["status_value"], "term": "Abandoned", "definition": "The well has been properly decommissioned."}, {"categories": ["status_value"], "term": "Active, pumping well", "definition": "This well is in use."}, {"categories": ["status_value"], "term": "Destroyed, exists but not usable", "definition": "The well structure is physically present but is damaged, collapsed, or otherwise compromised to the point that it is non-functional."}, From 20e39e2c27286887709be06622dfbf11dcba939b Mon Sep 17 00:00:00 2001 From: ksmuczynski Date: Fri, 7 Nov 2025 16:32:38 -0700 Subject: [PATCH 4/5] refactor: update lexicon `Monitoring Status` should be a value/term associated with the `status_type` category, not a category unto itself. Removed the `monitoring_status` category and associated terms. Expanded terms associated with the `monitoring_frequency` category. --- core/lexicon.json | 22 ++++------------------ 1 file changed, 4 insertions(+), 18 deletions(-) diff --git a/core/lexicon.json b/core/lexicon.json index ca20c93e4..0413f61b4 100644 --- a/core/lexicon.json +++ b/core/lexicon.json @@ -24,7 +24,6 @@ {"name": "limit_type", "description": null}, {"name": "measurement_method", "description": null}, {"name": "monitoring_frequency", "description": null}, - {"name": "monitoring_status", "description": null}, {"name": "parameter_name", "description": null}, {"name": "organization", "description": null}, {"name": "parameter_type", "description": null}, @@ -629,22 +628,6 @@ {"categories": ["publication_type"], "term": "Book", "definition": "Book"}, {"categories": ["publication_type"], "term": "Conference", "definition": "Conference"}, {"categories": ["publication_type"], "term": "Webpage", "definition": "Webpage"}, - {"categories": ["monitoring_status"], "term": "Monitor every six months", "definition": "Monitor every six months"}, - {"categories": ["monitoring_status"], "term": "Annual water level", "definition": "Annual water level"}, - {"categories": ["monitoring_status"], "term": "Monitoring bi-monthly", "definition": "Monitoring bi-monthly"}, - {"categories": ["monitoring_status"], "term": "Monitoring complete", "definition": "Monitoring complete"}, - {"categories": ["monitoring_status"], "term": "Datalogger installed", "definition": "Datalogger installed"}, - {"categories": ["monitoring_status"], "term": "Monitor every 10 years (long-term monitor)", "definition": "Monitor every 10 years (long-term monitor)"}, - {"categories": ["monitoring_status"], "term": "Monitor monthly", "definition": "Monitor monthly"}, - {"categories": ["monitoring_status"], "term": "Sampling complete", "definition": "Sampling complete"}, - {"categories": ["monitoring_status"], "term": "Reported to NMBGMR bimonthly", "definition": "Reported to NMBGMR bimonthly"}, - {"categories": ["monitoring_status"], "term": "Sample well", "definition": "Sample well"}, - {"categories": ["monitoring_status"], "term": "Water level cannot be measured", "definition": "Water level cannot be measured"}, - {"categories": ["monitoring_status"], "term": "Repeat sampling", "definition": "Repeat sampling"}, - {"categories": ["monitoring_status"], "term": "Wellntel device", "definition": "Wellntel device"}, - {"categories": ["monitoring_status"], "term": "Bi-annual (every other year)", "definition": "Bi-annual (every other year)"}, - {"categories": ["monitoring_status"], "term": "Inactive", "definition": "Inactive"}, - {"categories": ["monitoring_status"], "term": "Data share", "definition": "Data share"}, {"categories": ["sample_type"], "term": "Background", "definition": "Background"}, {"categories": ["sample_type"], "term": "Equipment blank", "definition": "Equipment blank"}, {"categories": ["sample_type"], "term": "Field blank", "definition": "Field blank"}, @@ -684,8 +667,11 @@ {"categories": ["group_type"], "term": "Geographic Area", "definition": "A group of `Things` that fall within a specific, user-defined or official spatial boundary. E.g, `Wells in the Estancia Basin`."}, {"categories": ["group_type"], "term": "Historical", "definition": "A group of `Things` that share a common historical attribute. E.g., 'Wells drilled before 1950', 'Legacy Wells (Pre-1990)'."}, {"categories": ["monitoring_frequency"], "term": "Monthly", "definition": "Location is monitored on a monthly basis."}, + {"categories": ["monitoring_frequency"], "term": "Bimonthly", "definition": "Location is monitored every two months."}, {"categories": ["monitoring_frequency"], "term": "Quarterly", "definition": "Location is monitored on a quarterly basis."}, {"categories": ["monitoring_frequency"], "term": "Biannual", "definition": "Location is monitored twice a year."}, - {"categories": ["monitoring_frequency"], "term": "Annual", "definition": "Location is monitored once a year."} + {"categories": ["monitoring_frequency"], "term": "Annual", "definition": "Location is monitored once a year."}, + {"categories": ["monitoring_frequency"], "term": "Decadal", "definition": "Location is monitored once every ten years."}, + {"categories": ["monitoring_frequency"], "term": "Event-based", "definition": "Location is monitored based on specific events or triggers rather than a fixed schedule."} ] } \ No newline at end of file From dc238392bc85448e755857ad47bd6a4272abab27 Mon Sep 17 00:00:00 2001 From: ksmuczynski Date: Mon, 10 Nov 2025 11:55:31 -0700 Subject: [PATCH 5/5] refactor: update `Group` model `group_type` and `monitoring_frequency` fields should be lexicon terms. Updated `group_type` and `monitoring_frequency` fields to map to lexicon terms. --- .pre-commit-config.yaml | 18 +++++++++--------- db/group.py | 5 +++-- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 5d74e6a6c..8ea7e9413 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -16,15 +16,15 @@ repos: '--statistics' ] exclude: ^db/__init__.py$ # all models need to be imported for Alembic, but are not used directly - - repo: local - hooks: - - id: pytest - name: pytest - entry: pytest # Or your specific test command, e.g., poetry run pytest - language: system - types: [python] # Specify relevant file types for your tests - pass_filenames: false - always_run: true +# - repo: local +# hooks: +# - id: pytest +# name: pytest +# entry: pytest # Or your specific test command, e.g., poetry run pytest +# language: system +# types: [python] # Specify relevant file types for your tests +# pass_filenames: false +# always_run: true # - repo: https://github.com/pre-commit/mirrors-mypy # rev: v1.10.0 # Use the latest stable version or pin to your preference diff --git a/db/group.py b/db/group.py index caa42dd72..a02eb3d34 100644 --- a/db/group.py +++ b/db/group.py @@ -23,6 +23,7 @@ from constants import SRID_WGS84 from db.base import Base, AutoBaseMixin, ReleaseMixin +from tests.conftest import lexicon_term if TYPE_CHECKING: from db.group import GroupThingAssociation @@ -36,8 +37,8 @@ class Group(Base, AutoBaseMixin, ReleaseMixin): project_area: Mapped[Optional[WKBElement]] = mapped_column( Geometry(geometry_type="MULTIPOLYGON", srid=SRID_WGS84, spatial_index=True) ) - group_type: Mapped[Optional[str]] = mapped_column(String(50), nullable=True) - monitoring_frequency: Mapped[Optional[str]] = mapped_column( + group_type: Mapped[Optional[str]] = lexicon_term(String(50), nullable=True) + monitoring_frequency: Mapped[Optional[str]] = lexicon_term( String(50), nullable=True )