diff --git a/.env.example b/.env.example index 4be3e048f..aebc40609 100644 --- a/.env.example +++ b/.env.example @@ -1,7 +1,7 @@ DB_DRIVER=postgres -POSTGRES_USER= -POSTGRES_PASSWORD= +POSTGRES_USER=admin +POSTGRES_PASSWORD=password POSTGRES_DB= # asset storage diff --git a/db/location.py b/db/location.py index 397fba62c..f54d7a1f7 100644 --- a/db/location.py +++ b/db/location.py @@ -53,6 +53,11 @@ class Location(Base, AutoBaseMixin, ReleaseMixin): quad_name: Mapped[str] = mapped_column(String(100), nullable=True) notes: Mapped[str] = mapped_column(Text, nullable=True) nma_notes_location: Mapped[str] = mapped_column(Text, nullable=True) + nma_coordinate_notes: Mapped[str] = mapped_column(Text, nullable=True) + elevation_accuracy: Mapped[float] = mapped_column(nullable=True) + elevation_method: Mapped[str] = lexicon_term(nullable=True) + coordinate_accuracy: Mapped[float] = mapped_column(nullable=True) + coordinate_method: Mapped[str] = lexicon_term(nullable=True) # --- Relationship Definitions --- thing_associations: Mapped[list["LocationThingAssociation"]] = relationship( diff --git a/db/thing.py b/db/thing.py index cbeed6c59..b6117b9d0 100644 --- a/db/thing.py +++ b/db/thing.py @@ -18,11 +18,14 @@ from sqlalchemy.orm import relationship, mapped_column, Mapped from sqlalchemy_utils import TSVectorType +from uuid import UUID + from db import lexicon_term from db.base import AutoBaseMixin, Base, ReleaseMixin class Thing(Base, AutoBaseMixin, ReleaseMixin): + name = mapped_column(String(255), nullable=False) description = mapped_column(String(500)) thing_type = lexicon_term(nullable=True) diff --git a/schemas/location.py b/schemas/location.py index aa8074e8c..d98235108 100644 --- a/schemas/location.py +++ b/schemas/location.py @@ -38,6 +38,10 @@ class CreateLocation(BaseCreateModel): notes: str | None = None point: str # point is required and should be in WKT format release_status: str | None = "draft" + elevation_accuracy: float | None = None + elevation_method: str | None = None + coordinate_accuracy: float | None = None + coordinate_method: str | None = None @classmethod @field_validator("point") @@ -60,9 +64,17 @@ class LocationResponse(BaseResponseModel): Response schema for sample location details. """ - name: str | None = None + name: str | None + notes: str | None point: str - release_status: str + release_status: str | None + elevation_accuracy: float | None + elevation_method: str | None + coordinate_accuracy: float | None + coordinate_method: str | None + state: str | None + county: str | None + quad_name: str | None @field_validator("point", mode="before") def point_to_wkt(cls, value): @@ -94,6 +106,11 @@ class UpdateLocation(BaseUpdateModel): name: str | None = None notes: str | None = None point: str | None = None + release_status: str | None = None + elevation_accuracy: float | None = None + elevation_method: str | None = None + coordinate_accuracy: float | None = None + coordinate_method: str | None = None # ============= EOF ============================================= diff --git a/tests/conftest.py b/tests/conftest.py index 215023674..85092920e 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -9,7 +9,17 @@ def location(): with session_ctx() as session: loc = Location( - name="first location", release_status="draft", point="POINT(0 0 0)" + name="first location", + notes="these are some test notes", + point="POINT(0 0 0)", + release_status="draft", + elevation_accuracy=100, + elevation_method="Survey-grade GPS", + coordinate_accuracy=50, + coordinate_method="GPS, uncorrected", + state="New Mexico", + county="Socorro", + quad_name="some NM quad", ) session.add(loc) session.commit() diff --git a/tests/test_location.py b/tests/test_location.py index 6d4945949..a27ddf775 100644 --- a/tests/test_location.py +++ b/tests/test_location.py @@ -43,8 +43,13 @@ def override_dependencies_fixture(): def test_add_location(): payload = { "name": "test location", + "notes": "these are some test notes", "point": "POINT Z (10.1 10.1 0)", "release_status": "draft", + "elevation_accuracy": 1.0, + "elevation_method": "Survey-grade GPS", + "coordinate_accuracy": 5.0, + "coordinate_method": "GPS, uncorrected", } response = client.post("/location", json=payload) @@ -53,8 +58,13 @@ def test_add_location(): assert "id" in data assert "created_at" in data assert data["name"] == payload["name"] + assert data["notes"] == payload["notes"] assert data["point"] == payload["point"] assert data["release_status"] == payload["release_status"] + assert data["elevation_accuracy"] == payload["elevation_accuracy"] + assert data["elevation_method"] == payload["elevation_method"] + assert data["coordinate_accuracy"] == payload["coordinate_accuracy"] + assert data["coordinate_method"] == payload["coordinate_method"] # cleanup after test cleanup_post_test(Location, data["id"]) @@ -65,17 +75,27 @@ def test_add_location(): def test_update_location(location): payload = { + "name": "patched name", + "notes": "these are some patched notes", "point": "POINT Z (10.1 20.2 0)", "release_status": "draft", - "name": "patched name", + "elevation_accuracy": 2.0, + "elevation_method": "Survey-grade GPS", + "coordinate_accuracy": 10.0, + "coordinate_method": "GPS, uncorrected", } response = client.patch(f"/location/{location.id}", json=payload) assert response.status_code == 200 data = response.json() assert data["id"] == location.id + assert data["name"] == payload["name"] + assert data["notes"] == payload["notes"] assert data["point"] == payload["point"] assert data["release_status"] == payload["release_status"] - assert data["name"] == payload["name"] + assert data["elevation_accuracy"] == payload["elevation_accuracy"] + assert data["elevation_method"] == payload["elevation_method"] + assert data["coordinate_accuracy"] == payload["coordinate_accuracy"] + assert data["coordinate_method"] == payload["coordinate_method"] # cleanup after test cleanup_patch_test(Location, payload, location) @@ -111,8 +131,16 @@ def test_get_locations(location): "+00:00", "Z" ) assert data["items"][0]["name"] == location.name + assert data["items"][0]["notes"] == location.notes assert data["items"][0]["point"] == to_shape(location.point).wkt assert data["items"][0]["release_status"] == location.release_status + assert data["items"][0]["elevation_accuracy"] == location.elevation_accuracy + assert data["items"][0]["elevation_method"] == location.elevation_method + assert data["items"][0]["coordinate_accuracy"] == location.coordinate_accuracy + assert data["items"][0]["coordinate_method"] == location.coordinate_method + assert data["items"][0]["state"] == location.state + assert data["items"][0]["county"] == location.county + assert data["items"][0]["quad_name"] == location.quad_name def test_get_location_by_id(location): @@ -124,6 +152,13 @@ def test_get_location_by_id(location): assert data["name"] == location.name assert data["point"] == to_shape(location.point).wkt assert data["release_status"] == location.release_status + assert data["elevation_accuracy"] == location.elevation_accuracy + assert data["elevation_method"] == location.elevation_method + assert data["coordinate_accuracy"] == location.coordinate_accuracy + assert data["coordinate_method"] == location.coordinate_method + assert data["state"] == location.state + assert data["county"] == location.county + assert data["quad_name"] == location.quad_name def test_get_sample_by_id_404_not_found(location): diff --git a/transfers/util.py b/transfers/util.py index 4b4cec3bb..44980a212 100644 --- a/transfers/util.py +++ b/transfers/util.py @@ -207,15 +207,18 @@ def make_location(row: pd.Series) -> Location: # created_at = row.DateCreated location = Location( - # nma_pk_location=row.LocationId, + nma_pk_location=row.LocationId, + # TODO: determine if PointID should map to location.name or thing.name or if the Location table needs a name field at all. name=row.PointID, point=transformed_point.wkt, release_status="public" if row.PublicRelease else "private", - # elevation_accuracy=row.AltitudeAccuracy, - # elevation_method=row.AltitudeMethod, + elevation_accuracy=row.AltitudeAccuracy, + elevation_method=row.AltitudeMethod, # created_at=created_at, - # point_accuracy=row.CoordinateAccuracy, - # point_method=row.CoordinateMethod, + coordinate_accuracy=row.CoordinateAccuracy, + coordinate_method=row.CoordinateMethod, + nma_coordinate_notes=row.CoordinateNotes, + nma_notes_location=row.LocationNotes, ) return location