diff --git a/.github/workflows/django_tests.yaml b/.github/workflows/django_tests.yaml index 4e8628cc2..f7a9373d2 100644 --- a/.github/workflows/django_tests.yaml +++ b/.github/workflows/django_tests.yaml @@ -27,6 +27,10 @@ jobs: --health-timeout 5s --health-retries 5 steps: + - name: Install GDAL + run: | + sudo apt-get update + sudo apt-get install -y gdal-bin libgdal-dev python3-gdal - uses: actions/checkout@v5 - uses: actions/setup-python@v6 with: diff --git a/api-rework/.gitignore b/api-rework/.gitignore index e18b65190..3d94139b4 100644 --- a/api-rework/.gitignore +++ b/api-rework/.gitignore @@ -1 +1,2 @@ +protobuf devops diff --git a/api-rework/client/src/activities/form-viewer/FormViewer.tsx b/api-rework/client/src/activities/form-viewer/FormViewer.tsx index 8efd028a9..bbe0adbd4 100644 --- a/api-rework/client/src/activities/form-viewer/FormViewer.tsx +++ b/api-rework/client/src/activities/form-viewer/FormViewer.tsx @@ -35,7 +35,7 @@ const FormViewer = ({ formData }) => { @@ -49,22 +49,22 @@ const FormViewer = ({ formData }) => {
{formData?.projects.map(({ description }) => ( - + ))}
{formData?.employer.map(({ employer }) => ( - + ))}
{formData?.funding_agencies.map(({ invasive_species_agency_code }) => ( - + ))}
{formData?.jurisdictions.map(({ jurisdiction, percent_covered }) => ( -
+
@@ -72,7 +72,7 @@ const FormViewer = ({ formData }) => {
{formData?.participants.map(({ name, pac_number }) => ( -
+
{pac_number && }
@@ -80,7 +80,7 @@ const FormViewer = ({ formData }) => {
{formData?.linked_activities?.map(({ full, short_id }) => ( -
+
diff --git a/api-rework/client/src/activities/json_viewer.tsx b/api-rework/client/src/activities/json_viewer.tsx index a34c75099..8a4f0c5c4 100644 --- a/api-rework/client/src/activities/json_viewer.tsx +++ b/api-rework/client/src/activities/json_viewer.tsx @@ -41,7 +41,7 @@ const JSONViewer: React.FC = ({ data, helpText, diffCandidates toggleDiff(candidate.title)} + onChange={() => toggleDiff(candidate.title)} /> Show Diff with {candidate.title} diff --git a/api-rework/client/src/common-components/form-map/FormMap.tsx b/api-rework/client/src/common-components/form-map/FormMap.tsx index 623025ebd..6b8326f0d 100644 --- a/api-rework/client/src/common-components/form-map/FormMap.tsx +++ b/api-rework/client/src/common-components/form-map/FormMap.tsx @@ -1,4 +1,4 @@ -import { useEffect, useRef, useState } from 'react'; +import { useEffect, useRef } from 'react'; import maplibregl, { LngLatBoundsLike, LngLatLike } from 'maplibre-gl'; import { centroid } from '@turf/centroid'; import { bbox } from '@turf/bbox'; @@ -6,12 +6,13 @@ import { bbox } from '@turf/bbox'; import './formMap.css'; type PropTypes = { - geojson?: GeoJSON.Polygon | GeoJSON.Feature; + geojson: GeoJSON.Polygon | GeoJSON.Feature; }; + const FormMap = ({ geojson }: PropTypes) => { const SRC = 'https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}'; const mapRef = useRef(null); - const [map, setMap] = useState(); + const map= useRef(undefined); const mapCenter: LngLatLike = (() => { if (!geojson) return [-121, 54] as LngLatLike; @@ -20,7 +21,7 @@ const FormMap = ({ geojson }: PropTypes) => { useEffect(() => { // Init Map after load - setMap( + map.current = new maplibregl.Map({ container: 'map', center: mapCenter, @@ -30,7 +31,8 @@ const FormMap = ({ geojson }: PropTypes) => { 'raster-tiles': { type: 'raster', tiles: [SRC], - tileSize: 256 + tileSize: 256, + maxzoom: 18 } }, layers: [ @@ -42,20 +44,21 @@ const FormMap = ({ geojson }: PropTypes) => { ], version: 8 } - }) + } ); - }, []); + }, [geojson]); useEffect(() => { // Apply Geometry + Layer - if (!map || !geojson) return; - map?.on('load', () => { + if (!map.current || !geojson) return; + + map.current.on('load', () => { if (geojson) { - map?.addSource('form-feature', { + map.current?.addSource('form-feature', { type: 'geojson', data: geojson }); - map?.addLayer({ + map.current?.addLayer({ id: 'form-feature', type: 'fill', source: 'form-feature', @@ -66,12 +69,13 @@ const FormMap = ({ geojson }: PropTypes) => { } }); const bounds = bbox(geojson) as LngLatBoundsLike; - map.fitBounds(bounds, { + map.current?.fitBounds(bounds, { padding: 10, minZoom: 8 }); } }); + }, [map]); return (
diff --git a/api-rework/client/src/common-components/header/header.css b/api-rework/client/src/common-components/header/header.css index e65f0da65..c68e2d95b 100644 --- a/api-rework/client/src/common-components/header/header.css +++ b/api-rework/client/src/common-components/header/header.css @@ -12,6 +12,7 @@ header { border-bottom: 1pt solid black; font-family: Calibri, sans-serif; color: white; + z-index: 100; h1, p { diff --git a/api-rework/invasives/api/fixtures/test/common/test_activities.json b/api-rework/invasives/api/fixtures/test/common/test_activities.json index 7b07a9144..45a441d13 100644 --- a/api-rework/invasives/api/fixtures/test/common/test_activities.json +++ b/api-rework/invasives/api/fixtures/test/common/test_activities.json @@ -7,7 +7,8 @@ "created_timestamp": "2026-01-01 12:01:00-08:00", "received_timestamp": "2026-01-01 12:02:00-08:00", "subtype": "Observation_Plant_Terrestrial", - "comment": "The test looks for this comment" + "comment": "The test looks for this comment", + "shape": "SRID=4326;POLYGON ((-122.177141614583 52.1532521915262, -122.177829032404 52.1531151489405, -122.178253871019 52.1527563687912, -122.178253859939 52.1523128961334, -122.177829014477 52.1519541224493, -122.177141614583 52.1518170838594, -122.176454214689 52.1519541224493, -122.176029369227 52.1523128961334, -122.176029358147 52.1527563687912, -122.176454196762 52.1531151489405, -122.177141614583 52.1532521915262))" } }, { @@ -18,7 +19,8 @@ "created_timestamp": "2026-01-01 12:01:00-08:00", "received_timestamp": "2026-01-01 12:02:00-08:00", "subtype": "Observation_Plant_Terrestrial", - "comment": "Nothing here" + "comment": "Nothing here", + "shape": "SRID=4326;POLYGON ((-122.177141614583 52.1532521915262, -122.177829032404 52.1531151489405, -122.178253871019 52.1527563687912, -122.178253859939 52.1523128961334, -122.177829014477 52.1519541224493, -122.177141614583 52.1518170838594, -122.176454214689 52.1519541224493, -122.176029369227 52.1523128961334, -122.176029358147 52.1527563687912, -122.176454196762 52.1531151489405, -122.177141614583 52.1532521915262))" } } ] diff --git a/api-rework/invasives/api/fixtures/test/subtypes/biocontrol/test_biocontrol_collection.json b/api-rework/invasives/api/fixtures/test/subtypes/biocontrol/test_biocontrol_collection.json index b081cfcfd..6209c2cfc 100644 --- a/api-rework/invasives/api/fixtures/test/subtypes/biocontrol/test_biocontrol_collection.json +++ b/api-rework/invasives/api/fixtures/test/subtypes/biocontrol/test_biocontrol_collection.json @@ -17,7 +17,8 @@ "batch_row_id": 34, "linked_activities": [ "CD542709-F767-402F-818E-117B3FBC797D" - ] + ], + "shape": "SRID=4326;POLYGON ((-122.177141614583 52.1532521915262, -122.177829032404 52.1531151489405, -122.178253871019 52.1527563687912, -122.178253859939 52.1523128961334, -122.177829014477 52.1519541224493, -122.177141614583 52.1518170838594, -122.176454214689 52.1519541224493, -122.176029369227 52.1523128961334, -122.176029358147 52.1527563687912, -122.176454196762 52.1531151489405, -122.177141614583 52.1532521915262))" } }, { @@ -35,7 +36,8 @@ "received_timestamp": "2026-01-07T23:44:38.919Z", "subtype": "Biocontrol_Collection", "batch_id": 56, - "batch_row_id": 78 + "batch_row_id": 78, + "shape": "SRID=4326;POLYGON ((-122.177141614583 52.1532521915262, -122.177829032404 52.1531151489405, -122.178253871019 52.1527563687912, -122.178253859939 52.1523128961334, -122.177829014477 52.1519541224493, -122.177141614583 52.1518170838594, -122.176454214689 52.1519541224493, -122.176029369227 52.1523128961334, -122.176029358147 52.1527563687912, -122.176454196762 52.1531151489405, -122.177141614583 52.1532521915262))" } }, { diff --git a/api-rework/invasives/api/fixtures/test/subtypes/biocontrol/test_biocontrol_dispersal_monitoring.json b/api-rework/invasives/api/fixtures/test/subtypes/biocontrol/test_biocontrol_dispersal_monitoring.json index e1efd0b9e..55f2fa1c9 100644 --- a/api-rework/invasives/api/fixtures/test/subtypes/biocontrol/test_biocontrol_dispersal_monitoring.json +++ b/api-rework/invasives/api/fixtures/test/subtypes/biocontrol/test_biocontrol_dispersal_monitoring.json @@ -17,7 +17,8 @@ "batch_row_id": 34, "linked_activities": [ "CD542709-F767-402F-818E-117B3FBC797D" - ] + ], + "shape": "SRID=4326;POLYGON ((-122.177141614583 52.1532521915262, -122.177829032404 52.1531151489405, -122.178253871019 52.1527563687912, -122.178253859939 52.1523128961334, -122.177829014477 52.1519541224493, -122.177141614583 52.1518170838594, -122.176454214689 52.1519541224493, -122.176029369227 52.1523128961334, -122.176029358147 52.1527563687912, -122.176454196762 52.1531151489405, -122.177141614583 52.1532521915262))" } }, { @@ -35,7 +36,8 @@ "received_timestamp": "2026-01-07T23:44:38.919Z", "subtype": "Monitoring_Biocontrol_Dispersal_Plant_Terrestrial", "batch_id": 56, - "batch_row_id": 78 + "batch_row_id": 78, + "shape": "SRID=4326;POLYGON ((-122.177141614583 52.1532521915262, -122.177829032404 52.1531151489405, -122.178253871019 52.1527563687912, -122.178253859939 52.1523128961334, -122.177829014477 52.1519541224493, -122.177141614583 52.1518170838594, -122.176454214689 52.1519541224493, -122.176029369227 52.1523128961334, -122.176029358147 52.1527563687912, -122.176454196762 52.1531151489405, -122.177141614583 52.1532521915262))" } }, { diff --git a/api-rework/invasives/api/fixtures/test/subtypes/monitoring/test_biocontrol_release_monitoring.json b/api-rework/invasives/api/fixtures/test/subtypes/monitoring/test_biocontrol_release_monitoring.json index 2e28693de..f6bfcc783 100644 --- a/api-rework/invasives/api/fixtures/test/subtypes/monitoring/test_biocontrol_release_monitoring.json +++ b/api-rework/invasives/api/fixtures/test/subtypes/monitoring/test_biocontrol_release_monitoring.json @@ -17,7 +17,8 @@ "batch_row_id": 34, "linked_activities": [ "CD542709-F767-402F-818E-117B3FBC797D" - ] + ], + "shape": "SRID=4326;POLYGON ((-122.177141614583 52.1532521915262, -122.177829032404 52.1531151489405, -122.178253871019 52.1527563687912, -122.178253859939 52.1523128961334, -122.177829014477 52.1519541224493, -122.177141614583 52.1518170838594, -122.176454214689 52.1519541224493, -122.176029369227 52.1523128961334, -122.176029358147 52.1527563687912, -122.176454196762 52.1531151489405, -122.177141614583 52.1532521915262))" } }, { @@ -34,7 +35,8 @@ "received_timestamp": "2026-01-07T23:44:38.919Z", "subtype": "Monitoring_Biocontrol_Release_Plant_Terrestrial", "batch_id": 56, - "batch_row_id": 78 + "batch_row_id": 78, + "shape": "SRID=4326;POLYGON ((-122.177141614583 52.1532521915262, -122.177829032404 52.1531151489405, -122.178253871019 52.1527563687912, -122.178253859939 52.1523128961334, -122.177829014477 52.1519541224493, -122.177141614583 52.1518170838594, -122.176454214689 52.1519541224493, -122.176029369227 52.1523128961334, -122.176029358147 52.1527563687912, -122.176454196762 52.1531151489405, -122.177141614583 52.1532521915262))" } }, { diff --git a/api-rework/invasives/api/fixtures/test/subtypes/monitoring/test_chemical_treatment_monitoring.json b/api-rework/invasives/api/fixtures/test/subtypes/monitoring/test_chemical_treatment_monitoring.json index ba663b83c..13ac66a08 100644 --- a/api-rework/invasives/api/fixtures/test/subtypes/monitoring/test_chemical_treatment_monitoring.json +++ b/api-rework/invasives/api/fixtures/test/subtypes/monitoring/test_chemical_treatment_monitoring.json @@ -17,7 +17,8 @@ "batch_row_id": 34, "linked_activities": [ "CD542709-F767-402F-818E-117B3FBC797D" - ] + ], + "shape": "SRID=4326;POLYGON ((-122.177141614583 52.1532521915262, -122.177829032404 52.1531151489405, -122.178253871019 52.1527563687912, -122.178253859939 52.1523128961334, -122.177829014477 52.1519541224493, -122.177141614583 52.1518170838594, -122.176454214689 52.1519541224493, -122.176029369227 52.1523128961334, -122.176029358147 52.1527563687912, -122.176454196762 52.1531151489405, -122.177141614583 52.1532521915262))" } }, { @@ -35,7 +36,8 @@ "received_timestamp": "2026-01-07T23:44:38.919Z", "subtype": "Monitoring_Chemical_Plant_Terrestrial_Aquatic", "batch_id": 56, - "batch_row_id": 78 + "batch_row_id": 78, + "shape": "SRID=4326;POLYGON ((-122.177141614583 52.1532521915262, -122.177829032404 52.1531151489405, -122.178253871019 52.1527563687912, -122.178253859939 52.1523128961334, -122.177829014477 52.1519541224493, -122.177141614583 52.1518170838594, -122.176454214689 52.1519541224493, -122.176029369227 52.1523128961334, -122.176029358147 52.1527563687912, -122.176454196762 52.1531151489405, -122.177141614583 52.1532521915262))" } }, { diff --git a/api-rework/invasives/api/fixtures/test/subtypes/monitoring/test_mechanical_treatment_monitoring.json b/api-rework/invasives/api/fixtures/test/subtypes/monitoring/test_mechanical_treatment_monitoring.json index 9050398b2..cf128dc35 100644 --- a/api-rework/invasives/api/fixtures/test/subtypes/monitoring/test_mechanical_treatment_monitoring.json +++ b/api-rework/invasives/api/fixtures/test/subtypes/monitoring/test_mechanical_treatment_monitoring.json @@ -17,7 +17,8 @@ "batch_row_id": 34, "linked_activities": [ "CD542709-F767-402F-818E-117B3FBC797D" - ] + ], + "shape": "SRID=4326;POLYGON ((-122.177141614583 52.1532521915262, -122.177829032404 52.1531151489405, -122.178253871019 52.1527563687912, -122.178253859939 52.1523128961334, -122.177829014477 52.1519541224493, -122.177141614583 52.1518170838594, -122.176454214689 52.1519541224493, -122.176029369227 52.1523128961334, -122.176029358147 52.1527563687912, -122.176454196762 52.1531151489405, -122.177141614583 52.1532521915262))" } }, { @@ -34,7 +35,8 @@ "received_timestamp": "2026-01-07T23:44:38.919Z", "subtype": "Monitoring_Mechanical_Plant_Terrestrial_Aquatic", "batch_id": 56, - "batch_row_id": 78 + "batch_row_id": 78, + "shape": "SRID=4326;POLYGON ((-122.177141614583 52.1532521915262, -122.177829032404 52.1531151489405, -122.178253871019 52.1527563687912, -122.178253859939 52.1523128961334, -122.177829014477 52.1519541224493, -122.177141614583 52.1518170838594, -122.176454214689 52.1519541224493, -122.176029369227 52.1523128961334, -122.176029358147 52.1527563687912, -122.176454196762 52.1531151489405, -122.177141614583 52.1532521915262))" } }, { diff --git a/api-rework/invasives/api/fixtures/test/subtypes/observations/test_aquatic_observation.json b/api-rework/invasives/api/fixtures/test/subtypes/observations/test_aquatic_observation.json index 08e9f4f0e..6608d5f6f 100644 --- a/api-rework/invasives/api/fixtures/test/subtypes/observations/test_aquatic_observation.json +++ b/api-rework/invasives/api/fixtures/test/subtypes/observations/test_aquatic_observation.json @@ -17,7 +17,8 @@ "batch_row_id": 34, "linked_activities": [ "CD542709-F767-402F-818E-117B3FBC797D" - ] + ], + "shape": "SRID=4326;POLYGON ((-122.177141614583 52.1532521915262, -122.177829032404 52.1531151489405, -122.178253871019 52.1527563687912, -122.178253859939 52.1523128961334, -122.177829014477 52.1519541224493, -122.177141614583 52.1518170838594, -122.176454214689 52.1519541224493, -122.176029369227 52.1523128961334, -122.176029358147 52.1527563687912, -122.176454196762 52.1531151489405, -122.177141614583 52.1532521915262))" } }, { @@ -34,7 +35,8 @@ "received_timestamp": "2026-01-07T23:44:38.919Z", "subtype": "Observation_Plant_Aquatic", "batch_id": 56, - "batch_row_id": 78 + "batch_row_id": 78, + "shape": "SRID=4326;POLYGON ((-122.177141614583 52.1532521915262, -122.177829032404 52.1531151489405, -122.178253871019 52.1527563687912, -122.178253859939 52.1523128961334, -122.177829014477 52.1519541224493, -122.177141614583 52.1518170838594, -122.176454214689 52.1519541224493, -122.176029369227 52.1523128961334, -122.176029358147 52.1527563687912, -122.176454196762 52.1531151489405, -122.177141614583 52.1532521915262))" } }, { diff --git a/api-rework/invasives/api/fixtures/test/subtypes/observations/test_terrestrial_observation.json b/api-rework/invasives/api/fixtures/test/subtypes/observations/test_terrestrial_observation.json index 0d0cfdad1..13e2cc240 100644 --- a/api-rework/invasives/api/fixtures/test/subtypes/observations/test_terrestrial_observation.json +++ b/api-rework/invasives/api/fixtures/test/subtypes/observations/test_terrestrial_observation.json @@ -17,7 +17,8 @@ "batch_row_id": 34, "linked_activities": [ "CD542709-F767-402F-818E-117B3FBC797D" - ] + ], + "shape": "SRID=4326;POLYGON ((-122.177141614583 52.1532521915262, -122.177829032404 52.1531151489405, -122.178253871019 52.1527563687912, -122.178253859939 52.1523128961334, -122.177829014477 52.1519541224493, -122.177141614583 52.1518170838594, -122.176454214689 52.1519541224493, -122.176029369227 52.1523128961334, -122.176029358147 52.1527563687912, -122.176454196762 52.1531151489405, -122.177141614583 52.1532521915262))" } }, { @@ -35,7 +36,8 @@ "received_timestamp": "2026-01-07T23:44:38.919Z", "subtype": "Observation_Plant_Terrestrial", "batch_id": 56, - "batch_row_id": 78 + "batch_row_id": 78, + "shape": "SRID=4326;POLYGON ((-122.177141614583 52.1532521915262, -122.177829032404 52.1531151489405, -122.178253871019 52.1527563687912, -122.178253859939 52.1523128961334, -122.177829014477 52.1519541224493, -122.177141614583 52.1518170838594, -122.176454214689 52.1519541224493, -122.176029369227 52.1523128961334, -122.176029358147 52.1527563687912, -122.176454196762 52.1531151489405, -122.177141614583 52.1532521915262))" } }, { diff --git a/api-rework/invasives/api/fixtures/test/subtypes/treatments/test_aquatic_chemical_treatment.json b/api-rework/invasives/api/fixtures/test/subtypes/treatments/test_aquatic_chemical_treatment.json index 3b4451306..49bbae420 100644 --- a/api-rework/invasives/api/fixtures/test/subtypes/treatments/test_aquatic_chemical_treatment.json +++ b/api-rework/invasives/api/fixtures/test/subtypes/treatments/test_aquatic_chemical_treatment.json @@ -17,7 +17,8 @@ "batch_row_id": 34, "linked_activities": [ "CD542709-F767-402F-818E-117B3FBC797D" - ] + ], + "shape": "SRID=4326;POLYGON ((-122.177141614583 52.1532521915262, -122.177829032404 52.1531151489405, -122.178253871019 52.1527563687912, -122.178253859939 52.1523128961334, -122.177829014477 52.1519541224493, -122.177141614583 52.1518170838594, -122.176454214689 52.1519541224493, -122.176029369227 52.1523128961334, -122.176029358147 52.1527563687912, -122.176454196762 52.1531151489405, -122.177141614583 52.1532521915262))" } }, { @@ -35,7 +36,8 @@ "received_timestamp": "2026-01-07T23:44:38.919Z", "subtype": "Treatment_Chemical_Plant_Aquatic", "batch_id": 56, - "batch_row_id": 78 + "batch_row_id": 78, + "shape": "SRID=4326;POLYGON ((-122.177141614583 52.1532521915262, -122.177829032404 52.1531151489405, -122.178253871019 52.1527563687912, -122.178253859939 52.1523128961334, -122.177829014477 52.1519541224493, -122.177141614583 52.1518170838594, -122.176454214689 52.1519541224493, -122.176029369227 52.1523128961334, -122.176029358147 52.1527563687912, -122.176454196762 52.1531151489405, -122.177141614583 52.1532521915262))" } }, { diff --git a/api-rework/invasives/api/fixtures/test/subtypes/treatments/test_aquatic_mechanical_treatment.json b/api-rework/invasives/api/fixtures/test/subtypes/treatments/test_aquatic_mechanical_treatment.json index ccb48f078..09addf749 100644 --- a/api-rework/invasives/api/fixtures/test/subtypes/treatments/test_aquatic_mechanical_treatment.json +++ b/api-rework/invasives/api/fixtures/test/subtypes/treatments/test_aquatic_mechanical_treatment.json @@ -17,7 +17,8 @@ "batch_row_id": 34, "linked_activities": [ "CD542709-F767-402F-818E-117B3FBC797D" - ] + ], + "shape": "SRID=4326;POLYGON ((-122.177141614583 52.1532521915262, -122.177829032404 52.1531151489405, -122.178253871019 52.1527563687912, -122.178253859939 52.1523128961334, -122.177829014477 52.1519541224493, -122.177141614583 52.1518170838594, -122.176454214689 52.1519541224493, -122.176029369227 52.1523128961334, -122.176029358147 52.1527563687912, -122.176454196762 52.1531151489405, -122.177141614583 52.1532521915262))" } }, { @@ -35,7 +36,8 @@ "received_timestamp": "2026-01-07T23:44:38.919Z", "subtype": "Treatment_Mechanical_Plant_Aquatic", "batch_id": 56, - "batch_row_id": 78 + "batch_row_id": 78, + "shape": "SRID=4326;POLYGON ((-122.177141614583 52.1532521915262, -122.177829032404 52.1531151489405, -122.178253871019 52.1527563687912, -122.178253859939 52.1523128961334, -122.177829014477 52.1519541224493, -122.177141614583 52.1518170838594, -122.176454214689 52.1519541224493, -122.176029369227 52.1523128961334, -122.176029358147 52.1527563687912, -122.176454196762 52.1531151489405, -122.177141614583 52.1532521915262))" } }, { diff --git a/api-rework/invasives/api/fixtures/test/subtypes/treatments/test_biocontrol_release.json b/api-rework/invasives/api/fixtures/test/subtypes/treatments/test_biocontrol_release.json index 07522cce9..9a1621244 100644 --- a/api-rework/invasives/api/fixtures/test/subtypes/treatments/test_biocontrol_release.json +++ b/api-rework/invasives/api/fixtures/test/subtypes/treatments/test_biocontrol_release.json @@ -17,7 +17,8 @@ "batch_row_id": 34, "linked_activities": [ "CD542709-F767-402F-818E-117B3FBC797D" - ] + ], + "shape": "SRID=4326;POLYGON ((-122.177141614583 52.1532521915262, -122.177829032404 52.1531151489405, -122.178253871019 52.1527563687912, -122.178253859939 52.1523128961334, -122.177829014477 52.1519541224493, -122.177141614583 52.1518170838594, -122.176454214689 52.1519541224493, -122.176029369227 52.1523128961334, -122.176029358147 52.1527563687912, -122.176454196762 52.1531151489405, -122.177141614583 52.1532521915262))" } }, { @@ -35,7 +36,8 @@ "received_timestamp": "2026-01-07T23:44:38.919Z", "subtype": "Biocontrol_Release", "batch_id": 56, - "batch_row_id": 78 + "batch_row_id": 78, + "shape": "SRID=4326;POLYGON ((-122.177141614583 52.1532521915262, -122.177829032404 52.1531151489405, -122.178253871019 52.1527563687912, -122.178253859939 52.1523128961334, -122.177829014477 52.1519541224493, -122.177141614583 52.1518170838594, -122.176454214689 52.1519541224493, -122.176029369227 52.1523128961334, -122.176029358147 52.1527563687912, -122.176454196762 52.1531151489405, -122.177141614583 52.1532521915262))" } }, { diff --git a/api-rework/invasives/api/fixtures/test/subtypes/treatments/test_terrestrial_chemical_treatment.json b/api-rework/invasives/api/fixtures/test/subtypes/treatments/test_terrestrial_chemical_treatment.json index d36dc023e..99619aeb5 100644 --- a/api-rework/invasives/api/fixtures/test/subtypes/treatments/test_terrestrial_chemical_treatment.json +++ b/api-rework/invasives/api/fixtures/test/subtypes/treatments/test_terrestrial_chemical_treatment.json @@ -17,7 +17,8 @@ "batch_row_id": 34, "linked_activities": [ "CD542709-F767-402F-818E-117B3FBC797D" - ] + ], + "shape": "SRID=4326;POLYGON ((-122.177141614583 52.1532521915262, -122.177829032404 52.1531151489405, -122.178253871019 52.1527563687912, -122.178253859939 52.1523128961334, -122.177829014477 52.1519541224493, -122.177141614583 52.1518170838594, -122.176454214689 52.1519541224493, -122.176029369227 52.1523128961334, -122.176029358147 52.1527563687912, -122.176454196762 52.1531151489405, -122.177141614583 52.1532521915262))" } }, { @@ -35,7 +36,8 @@ "received_timestamp": "2026-01-07T23:44:38.919Z", "subtype": "Treatment_Chemical_Plant_Terrestrial", "batch_id": 56, - "batch_row_id": 78 + "batch_row_id": 78, + "shape": "SRID=4326;POLYGON ((-122.177141614583 52.1532521915262, -122.177829032404 52.1531151489405, -122.178253871019 52.1527563687912, -122.178253859939 52.1523128961334, -122.177829014477 52.1519541224493, -122.177141614583 52.1518170838594, -122.176454214689 52.1519541224493, -122.176029369227 52.1523128961334, -122.176029358147 52.1527563687912, -122.176454196762 52.1531151489405, -122.177141614583 52.1532521915262))" } }, { diff --git a/api-rework/invasives/api/fixtures/test/subtypes/treatments/test_terrestrial_mechanical_treatment.json b/api-rework/invasives/api/fixtures/test/subtypes/treatments/test_terrestrial_mechanical_treatment.json index 45ee151e6..94e0e7a72 100644 --- a/api-rework/invasives/api/fixtures/test/subtypes/treatments/test_terrestrial_mechanical_treatment.json +++ b/api-rework/invasives/api/fixtures/test/subtypes/treatments/test_terrestrial_mechanical_treatment.json @@ -17,7 +17,8 @@ "batch_row_id": 34, "linked_activities": [ "CD542709-F767-402F-818E-117B3FBC797D" - ] + ], + "shape": "SRID=4326;POLYGON ((-122.177141614583 52.1532521915262, -122.177829032404 52.1531151489405, -122.178253871019 52.1527563687912, -122.178253859939 52.1523128961334, -122.177829014477 52.1519541224493, -122.177141614583 52.1518170838594, -122.176454214689 52.1519541224493, -122.176029369227 52.1523128961334, -122.176029358147 52.1527563687912, -122.176454196762 52.1531151489405, -122.177141614583 52.1532521915262))" } }, { @@ -35,7 +36,8 @@ "received_timestamp": "2026-01-07T23:44:38.919Z", "subtype": "Treatment_Mechanical_Plant_Terrestrial", "batch_id": 56, - "batch_row_id": 78 + "batch_row_id": 78, + "shape": "SRID=4326;POLYGON ((-122.177141614583 52.1532521915262, -122.177829032404 52.1531151489405, -122.178253871019 52.1527563687912, -122.178253859939 52.1523128961334, -122.177829014477 52.1519541224493, -122.177141614583 52.1518170838594, -122.176454214689 52.1519541224493, -122.176029369227 52.1523128961334, -122.176029358147 52.1527563687912, -122.176454196762 52.1531151489405, -122.177141614583 52.1532521915262))" } }, { diff --git a/api-rework/invasives/api/legacy_db/migrate.py b/api-rework/invasives/api/legacy_db/migrate.py index 27fce6549..a30e02ae6 100644 --- a/api-rework/invasives/api/legacy_db/migrate.py +++ b/api-rework/invasives/api/legacy_db/migrate.py @@ -1,4 +1,5 @@ -import decimal +from decimal import Decimal, ROUND_DOWN +import json import logging from pprint import pformat @@ -48,6 +49,23 @@ def migrate(old: LegacyActivity): new.form_status = old.activity_payload.form_status new.comment = old.activity_payload.form_data.activity_data.general_comment + if old.activity_payload.geometry is None or len(old.activity_payload.geometry) > 1: + logging.error( + "geometry cannot be understood: " + pformat(old.activity_payload.geometry) + ) + else: + new.shape = json.dumps((old.activity_payload.geometry[0]["geometry"])) + properties = ( + old.activity_payload.geometry[0]["properties"] + if "properties" in old.activity_payload.geometry[0] + else None + ) + if properties and "radius" in properties: + logging.debug(f"Mapping radius: {properties['radius']}") + new.shape_radius = Decimal(properties["radius"]).quantize( + Decimal("0.0000000000000001"), rounding=ROUND_DOWN + ) + new.created_by = old.activity_payload.created_by src_map = { "web": PlatformSource.Web.value, @@ -62,10 +80,10 @@ def migrate(old: LegacyActivity): new.area_m = old.activity_payload.form_data.activity_data.reported_area new.latitude = round( - decimal.Decimal(old.activity_payload.form_data.activity_data.latitude), 7 + Decimal(old.activity_payload.form_data.activity_data.latitude), 7 ) new.longitude = round( - decimal.Decimal(old.activity_payload.form_data.activity_data.longitude), 7 + Decimal(old.activity_payload.form_data.activity_data.longitude), 7 ) new.utm_zone = old.activity_payload.form_data.activity_data.utm_zone new.utm_easting = old.activity_payload.form_data.activity_data.utm_easting diff --git a/api-rework/invasives/api/migrations/0002_initial.py b/api-rework/invasives/api/migrations/0002_initial.py index 66e2e141f..1ba6c086e 100644 --- a/api-rework/invasives/api/migrations/0002_initial.py +++ b/api-rework/invasives/api/migrations/0002_initial.py @@ -1,6 +1,7 @@ -# Generated by Django 6.0 on 2026-02-05 19:42 +# Generated by Django 6.0 on 2026-02-09 06:02 import api.models.enums.water_level_management +import django.contrib.gis.db.models.fields import django.core.validators import django.db.models.deletion import uuid @@ -64,6 +65,9 @@ class Migration(migrations.Migration): ("actioned", models.BooleanField(default=False)), ("success", models.BooleanField(default=None, null=True)), ], + options={ + "db_table": '"etl"."pending_link"', + }, ), migrations.CreateModel( name="AdjacentLandUseCode", @@ -738,6 +742,17 @@ class Migration(migrations.Migration): models.DecimalField(decimal_places=7, max_digits=10, null=True), ), ("location_description", models.CharField(max_length=512, null=True)), + ("shape", django.contrib.gis.db.models.fields.GeometryField(srid=4326)), + ( + "shape_radius", + models.DecimalField( + blank=True, + decimal_places=16, + max_digits=17, + null=True, + validators=[django.core.validators.MinValueValidator(0)], + ), + ), ( "creating_platform", models.CharField( diff --git a/api-rework/invasives/api/models/migrator/activity_pending_link.py b/api-rework/invasives/api/models/migrator/activity_pending_link.py index 3adb15171..cedbc81c3 100644 --- a/api-rework/invasives/api/models/migrator/activity_pending_link.py +++ b/api-rework/invasives/api/models/migrator/activity_pending_link.py @@ -13,6 +13,5 @@ class ActivityPendingLink(models.Model): actioned = models.BooleanField(blank=False, null=False, default=False) success = models.BooleanField(blank=False, null=True, default=None) - -class Meta: - db_table = '"etl"."pending_link"' + class Meta: + db_table = '"etl"."pending_link"' diff --git a/api-rework/invasives/api/models/mixins/geometry.py b/api-rework/invasives/api/models/mixins/geometry.py index 964abff2b..ec78d47d6 100644 --- a/api-rework/invasives/api/models/mixins/geometry.py +++ b/api-rework/invasives/api/models/mixins/geometry.py @@ -1,3 +1,4 @@ +from django.contrib.gis.db import models as geomodels from django.core.validators import MaxValueValidator, MinValueValidator from django.db import models @@ -9,11 +10,9 @@ class Geometry(models.Model): Geometry details for an activity Record consumed by: - All Activity Types - @TODO: Update with PostGIS support for shapes | Constrain to BC Geometry + @TODO: Constrain to BC Geometry """ - # centroid = models. # SUPPORT CENTROID - # geom = models. # SUPPORT GEOMETRY. This should also support Multi-polygons. area_m = models.PositiveBigIntegerField( validators=[MaxValueValidator(MAX_AREA)], null=True ) @@ -26,9 +25,21 @@ class Geometry(models.Model): longitude = models.DecimalField(max_digits=10, decimal_places=7, null=True) location_description = models.CharField(max_length=512, null=True) + shape = geomodels.GeometryField( + srid=4326, geography=False, spatial_index=True, null=False + ) + shape_radius = models.DecimalField( + max_digits=17, + decimal_places=16, + null=True, + blank=True, + validators=[MinValueValidator(0)], + ) + class Meta: abstract = True def clean(self): super().save() # Check Geometry/Lat/Long are in BC. + # Check radius is shape is point. No radius is shape is not point. diff --git a/api-rework/invasives/api/serializers/activity.py b/api-rework/invasives/api/serializers/activity.py index 7c1b37e90..f2327ecea 100644 --- a/api-rework/invasives/api/serializers/activity.py +++ b/api-rework/invasives/api/serializers/activity.py @@ -1,5 +1,9 @@ +import json import logging +from django.contrib.gis.db.models.functions import AsGeoJSON +from django.contrib.gis.serializers.geojson import JSONSerializer as GeoJSONSerializer + from rest_framework import serializers from api.models.activity import ( @@ -11,6 +15,7 @@ ProjectCode, ) from api.models.activity.activity import Activity +from api.models.mixins.geometry import Geometry from api.serializers.type.subtype import ( AquaticChemicalTreatmentSerializer, AquaticObservationSerializer, @@ -101,6 +106,9 @@ class ActivitySerializer(serializers.ModelSerializer): participants = ParticipantSerializer(source="participant_set", many=True) linked_activities = serializers.SerializerMethodField() + shape = serializers.SerializerMethodField() + centroid = serializers.SerializerMethodField() + class Meta: model = Activity fields = ( @@ -131,15 +139,38 @@ class Meta: "utm_easting", "utm_northing", "location_description", + "shape", + "centroid", ) def get_linked_activities(self, obj): - print(obj) arr = [] for linked_id in obj.linked_activities.all(): arr.append({"short_id": linked_id.short_id, "full": linked_id.id}) return arr + def get_shape(self, obj: Activity): + geojson_py_object = json.loads(obj.shape.json) + + if geojson_py_object["type"] == "Feature": + # Shouldn't be any + logging.warning("Unexpected geometry with type Feature") + return geojson_py_object + + feature_object = { + "type": "Feature", + "geometry": geojson_py_object, + "properties": {"id": obj.short_id}, + } + + if obj.shape_radius is not None: + feature_object["properties"]["radius"] = obj.shape_radius + + return feature_object + + def get_centroid(self, obj: Geometry): + return json.loads(obj.centroid) + def get_subtype_data(self, obj: Activity): """Maps the Activity to the proper Subtype Serializer, populating the form specific information""" SUBTYPE_SERIALIZER_MAP = { diff --git a/api-rework/invasives/api/tests/subtypes/base.py b/api-rework/invasives/api/tests/subtypes/base.py index 0a7a12913..58375c863 100644 --- a/api-rework/invasives/api/tests/subtypes/base.py +++ b/api-rework/invasives/api/tests/subtypes/base.py @@ -39,68 +39,3 @@ def fetch_a(self): def fetch_b(self): return self.fetch(self.ID_B) - - ####### - # Cross-Subtype tests - ####### - - def expect_two_activities(self): - """ - Test that there are are two activities in a record result (imported by fixtures) - """ - result = self.client.get( - "/activities", headers={"Authorization": "Bearer act_as_user=test_user"} - ) - self.assertEqual(result.status_code, 200) - - response_object = result.json() - self.assertEqual(len(response_object), 2) - - def no_pac_number_present(self): - """ - Tests that the records do not contain a pesticide application number under participants - """ - try: - record = Activity.objects.get(id=self.ID_A) - self.assertIsNotNone(record) - serial = ActivitySerializer(record) - participants = serial.data["participants"] - self.assertGreaterEqual(len(participants), 1) - for person in participants: - self.assertIsNotNone(person.get("name")) - self.assertIsNone(person.get("pac_number")) - - except Activity.DoesNotExist: - self.fail("Activity does not exist") - - def pac_number_is_present(self): - """Tests that the records contain pesticide application numbers under participants (Chemical Treatments)""" - try: - record = Activity.objects.get(id=self.ID_A) - self.assertIsNotNone(record) - serial = ActivitySerializer(record) - serial.data["participants"] - - for person in serial.data["participants"]: - self.assertIsNotNone(person.get("name")) - self.assertIsNotNone(person.get("pac_number")) - - except Activity.DoesNotExist: - self.fail("Activity does not exist") - - def casting_fixture_into_serializer(self, expected_subtype_key): - """ - Test casting the record data into an ActivitySerializer. - - :param expected_subtype_key: An anticipated key for the subtype being casted. e.g.: 'well_information' - """ - try: - record = Activity.objects.get(id=self.ID_A) - self.assertIsNotNone(record) - - serial = ActivitySerializer(record) - # Check a subtype specific field - self.assertIsNotNone(serial.data["subtype_data"][expected_subtype_key]) - - except Activity.DoesNotExist: - self.fail("Activity does not exist") diff --git a/api-rework/invasives/api/tests/subtypes/test_aquatic_chemical_treatment.py b/api-rework/invasives/api/tests/subtypes/test_aquatic_chemical_treatment.py index 54fea52a2..e4180d111 100644 --- a/api-rework/invasives/api/tests/subtypes/test_aquatic_chemical_treatment.py +++ b/api-rework/invasives/api/tests/subtypes/test_aquatic_chemical_treatment.py @@ -11,15 +11,6 @@ class AquaticChemicalTreatmentTest(BaseActivitySubtypeTest): "test/common/test_participants", ] - def test_expect_two_activities(self): - self.expect_two_activities() - - def test_pac_number_is_present(self): - self.pac_number_is_present() - - def test_casting_fixture_into_serializer(self): - self.casting_fixture_into_serializer(expected_subtype_key="entries") - def test_subtype_values(self): record = self.fetch_a().json() sd = record["subtype_data"] diff --git a/api-rework/invasives/api/tests/subtypes/test_aquatic_mechanical_treatment.py b/api-rework/invasives/api/tests/subtypes/test_aquatic_mechanical_treatment.py index b044d3cc6..0046ac2e7 100644 --- a/api-rework/invasives/api/tests/subtypes/test_aquatic_mechanical_treatment.py +++ b/api-rework/invasives/api/tests/subtypes/test_aquatic_mechanical_treatment.py @@ -10,15 +10,6 @@ class AquaticMechanicalTreatmentTest(BaseActivitySubtypeTest): "test/common/test_participants", ] - def test_expect_two_activities(self): - self.expect_two_activities() - - def test_no_pac_number_present(self): - self.no_pac_number_present() - - def test_casting_fixture_into_serializer(self): - self.casting_fixture_into_serializer(expected_subtype_key="entries") - def test_subtype_details_full(self): """Subtype keys match the information from fixtures.""" response_object = self.fetch_a().json() diff --git a/api-rework/invasives/api/tests/subtypes/test_aquatic_observation.py b/api-rework/invasives/api/tests/subtypes/test_aquatic_observation.py index 90b2c7cec..bbde9bed6 100644 --- a/api-rework/invasives/api/tests/subtypes/test_aquatic_observation.py +++ b/api-rework/invasives/api/tests/subtypes/test_aquatic_observation.py @@ -9,15 +9,6 @@ class AquaticObservationTest(BaseActivitySubtypeTest): "test/common/test_participants", ] - def test_expect_two_activities(self): - self.expect_two_activities() - - def test_no_pac_number_present(self): - self.no_pac_number_present() - - def test_casting_fixture_into_serializer(self): - self.casting_fixture_into_serializer(expected_subtype_key="secchi_depth") - def test_subtype_details_full(self): """Subtype keys match the information from fixtures.""" response_object = self.fetch_a().json() diff --git a/api-rework/invasives/api/tests/subtypes/test_biocontrol_collection.py b/api-rework/invasives/api/tests/subtypes/test_biocontrol_collection.py index bcf19e85d..c134cd0f7 100644 --- a/api-rework/invasives/api/tests/subtypes/test_biocontrol_collection.py +++ b/api-rework/invasives/api/tests/subtypes/test_biocontrol_collection.py @@ -10,15 +10,6 @@ class BiocontrolReleaseTest(BaseActivitySubtypeTest): "test/common/test_participants", ] - def test_expect_two_activities(self): - self.expect_two_activities() - - def test_no_pac_number_present(self): - self.no_pac_number_present() - - def test_casting_fixture_into_serializer(self): - self.casting_fixture_into_serializer(expected_subtype_key="entries") - def test_subtype_details_full(self): """Subtype keys match the information from fixtures.""" response_object = self.fetch_a().json() diff --git a/api-rework/invasives/api/tests/subtypes/test_biocontrol_dispersal_monitoring.py b/api-rework/invasives/api/tests/subtypes/test_biocontrol_dispersal_monitoring.py index 7667a062a..01e6318df 100644 --- a/api-rework/invasives/api/tests/subtypes/test_biocontrol_dispersal_monitoring.py +++ b/api-rework/invasives/api/tests/subtypes/test_biocontrol_dispersal_monitoring.py @@ -10,15 +10,6 @@ class BiocontrolReleaseTest(BaseActivitySubtypeTest): "test/common/test_participants", ] - def test_expect_two_activities(self): - self.expect_two_activities() - - def test_no_pac_number_present(self): - self.no_pac_number_present() - - def test_casting_fixture_into_serializer(self): - self.casting_fixture_into_serializer(expected_subtype_key="entries") - def test_subtype_details_full(self): response_object = self.fetch_a().json() diff --git a/api-rework/invasives/api/tests/subtypes/test_biocontrol_release.py b/api-rework/invasives/api/tests/subtypes/test_biocontrol_release.py index f18d9ba2a..ac98b011f 100644 --- a/api-rework/invasives/api/tests/subtypes/test_biocontrol_release.py +++ b/api-rework/invasives/api/tests/subtypes/test_biocontrol_release.py @@ -10,15 +10,6 @@ class BiocontrolReleaseTest(BaseActivitySubtypeTest): "test/common/test_participants", ] - def test_expect_two_activities(self): - self.expect_two_activities() - - def test_no_pac_number_present(self): - self.no_pac_number_present() - - def test_casting_fixture_into_serializer(self): - self.casting_fixture_into_serializer(expected_subtype_key="entries") - def test_subtype_details_full(self): """Subtype keys match the information from fixtures.""" response_object = self.fetch_a().json() diff --git a/api-rework/invasives/api/tests/subtypes/test_biocontrol_release_monitoring.py b/api-rework/invasives/api/tests/subtypes/test_biocontrol_release_monitoring.py index 2626be5d1..b17737c23 100644 --- a/api-rework/invasives/api/tests/subtypes/test_biocontrol_release_monitoring.py +++ b/api-rework/invasives/api/tests/subtypes/test_biocontrol_release_monitoring.py @@ -10,15 +10,6 @@ class BiocontrolReleaseTest(BaseActivitySubtypeTest): "test/common/test_participants", ] - def test_expect_two_activities(self): - self.expect_two_activities() - - def test_no_pac_number_present(self): - self.no_pac_number_present() - - def test_casting_fixture_into_serializer(self): - self.casting_fixture_into_serializer(expected_subtype_key="entries") - def test_subtype_details_full(self): response_object = self.fetch_a().json() diff --git a/api-rework/invasives/api/tests/subtypes/test_chemical_treatment_monitoring.py b/api-rework/invasives/api/tests/subtypes/test_chemical_treatment_monitoring.py index 5023d1776..3553d95cf 100644 --- a/api-rework/invasives/api/tests/subtypes/test_chemical_treatment_monitoring.py +++ b/api-rework/invasives/api/tests/subtypes/test_chemical_treatment_monitoring.py @@ -11,15 +11,6 @@ class ChemicalTreatmentMonitoringTest(BaseActivitySubtypeTest): "test/common/test_participants", ] - def test_expect_two_activities(self): - self.expect_two_activities() - - def test_no_pac_number_present(self): - self.no_pac_number_present() - - def test_casting_fixture_into_serializer(self): - self.casting_fixture_into_serializer(expected_subtype_key="entries") - def test_subtype_details_full(self): """Subtype keys match the information from fixtures.""" diff --git a/api-rework/invasives/api/tests/subtypes/test_mechanical_treatment_monitoring.py b/api-rework/invasives/api/tests/subtypes/test_mechanical_treatment_monitoring.py index 5f7c00f21..7adbf3aa6 100644 --- a/api-rework/invasives/api/tests/subtypes/test_mechanical_treatment_monitoring.py +++ b/api-rework/invasives/api/tests/subtypes/test_mechanical_treatment_monitoring.py @@ -10,15 +10,6 @@ class MechanicalTreatmentMonitoringTest(BaseActivitySubtypeTest): "test/common/test_participants", ] - def test_expect_two_activities(self): - self.expect_two_activities() - - def test_no_pac_number_present(self): - self.no_pac_number_present() - - def test_casting_fixture_into_serializer(self): - self.casting_fixture_into_serializer(expected_subtype_key="entries") - def test_subtype_details_full(self): """Subtype keys match the information from fixtures.""" response_object = self.fetch_a().json() diff --git a/api-rework/invasives/api/tests/subtypes/test_terrestrial_chemical_treatment.py b/api-rework/invasives/api/tests/subtypes/test_terrestrial_chemical_treatment.py index 98bd39910..4d9a64498 100644 --- a/api-rework/invasives/api/tests/subtypes/test_terrestrial_chemical_treatment.py +++ b/api-rework/invasives/api/tests/subtypes/test_terrestrial_chemical_treatment.py @@ -11,15 +11,6 @@ class TerrestrialChemicalTreatmentTest(BaseActivitySubtypeTest): "test/common/test_participants", ] - def test_expect_two_activities(self): - self.expect_two_activities() - - def test_pac_number_is_present(self): - self.pac_number_is_present() - - def test_casting_fixture_into_serializer(self): - self.casting_fixture_into_serializer(expected_subtype_key="well_entries") - def test_subtype_values(self): record = self.fetch_a().json() sd = record["subtype_data"] diff --git a/api-rework/invasives/api/tests/subtypes/test_terrestrial_mechanical_treatment.py b/api-rework/invasives/api/tests/subtypes/test_terrestrial_mechanical_treatment.py index 2d4b50df8..0911edad8 100644 --- a/api-rework/invasives/api/tests/subtypes/test_terrestrial_mechanical_treatment.py +++ b/api-rework/invasives/api/tests/subtypes/test_terrestrial_mechanical_treatment.py @@ -10,15 +10,6 @@ class TerrestrialMechanicalTreatmentTest(BaseActivitySubtypeTest): "test/common/test_participants", ] - def test_expect_two_activities(self): - self.expect_two_activities() - - def test_no_pac_number_present(self): - self.no_pac_number_present() - - def test_casting_fixture_into_serializer(self): - self.casting_fixture_into_serializer(expected_subtype_key="entries") - def test_subtype_details_full(self): """Subtype keys match the information from fixtures.""" response_object = self.fetch_a().json() diff --git a/api-rework/invasives/api/tests/subtypes/test_terrestrial_observation.py b/api-rework/invasives/api/tests/subtypes/test_terrestrial_observation.py index edac845e9..9b5420819 100644 --- a/api-rework/invasives/api/tests/subtypes/test_terrestrial_observation.py +++ b/api-rework/invasives/api/tests/subtypes/test_terrestrial_observation.py @@ -10,15 +10,6 @@ class TerrestrialObservationTest(BaseActivitySubtypeTest): "test/common/test_participants", ] - def test_expect_two_activities(self): - self.expect_two_activities() - - def test_no_pac_number_present(self): - self.no_pac_number_present() - - def test_casting_fixture_into_serializer(self): - self.casting_fixture_into_serializer(expected_subtype_key="slope_percent") - def test_subtype_details_full(self): """Subtype keys match the information from fixtures.""" response_object = self.fetch_a().json() diff --git a/api-rework/invasives/api/viewsets/activity.py b/api-rework/invasives/api/viewsets/activity.py index 1d7d7d3dd..7a8136781 100644 --- a/api-rework/invasives/api/viewsets/activity.py +++ b/api-rework/invasives/api/viewsets/activity.py @@ -1,6 +1,7 @@ import json import logging +from django.contrib.gis.db.models.functions import Centroid, AsGeoJSON from django.http.response import HttpResponse import psycopg from psycopg.rows import dict_row @@ -20,9 +21,20 @@ class ActivityViewSet(ReadOnlyModelViewSet): - queryset = Activity.objects.all() + querysets = { + "list": Activity.objects.values("id", "type", "subtype", "date"), + "default": Activity.objects.annotate(centroid=AsGeoJSON(Centroid("shape"))) + .prefetch_related() + .all(), + } permission_classes = [AllowAny] + def get_queryset(self): + if self.action in self.querysets.keys(): + return self.querysets[self.action] + + return self.querysets["default"] + def get_serializer_class(self): if self.action == "list": return ActivityListSerializer diff --git a/api-rework/invasives/invasivesbc/settings.py b/api-rework/invasives/invasivesbc/settings.py index ee477f552..748236c4e 100644 --- a/api-rework/invasives/invasivesbc/settings.py +++ b/api-rework/invasives/invasivesbc/settings.py @@ -13,6 +13,7 @@ INSTALLED_APPS = [ "django.contrib.auth", "django.contrib.contenttypes", + "django.contrib.gis", "api", "corsheaders", ] @@ -44,7 +45,7 @@ DATABASES = { "default": { - "ENGINE": "django.db.backends.postgresql", + "ENGINE": "django.contrib.gis.db.backends.postgis", "NAME": os.getenv("DB_NAME"), "USER": os.getenv("DB_USER"), "PASSWORD": os.getenv("DB_PASSWORD"),