diff --git a/spp_registrant_gis/models/res_partner.py b/spp_registrant_gis/models/res_partner.py
index 1ba8b3ad1..60d20d31d 100644
--- a/spp_registrant_gis/models/res_partner.py
+++ b/spp_registrant_gis/models/res_partner.py
@@ -1,5 +1,7 @@
# Part of OpenSPP. See LICENSE file for full copyright and licensing details.
-from odoo import fields, models
+import json
+
+from odoo import api, fields, models
class ResPartner(models.Model):
@@ -12,3 +14,47 @@ class ResPartner(models.Model):
help="Geographic coordinates (latitude/longitude) for spatial queries and mapping. "
"Used for proximity-based targeting and geographic analysis of registrants.",
)
+ # OP#1143: plain latitude/longitude inputs kept in sync with `coordinates`
+ # so the values can be entered (registry create, change requests) and
+ # imported without needing the MapTiler map widget configured. Editing the
+ # map updates these; editing these rebuilds the point.
+ gis_latitude = fields.Float(
+ string="Latitude",
+ digits=(9, 6),
+ compute="_compute_gis_lat_long",
+ inverse="_inverse_gis_lat_long",
+ store=True,
+ help="Latitude in decimal degrees (WGS84). Kept in sync with GPS Coordinates.",
+ )
+ gis_longitude = fields.Float(
+ string="Longitude",
+ digits=(9, 6),
+ compute="_compute_gis_lat_long",
+ inverse="_inverse_gis_lat_long",
+ store=True,
+ help="Longitude in decimal degrees (WGS84). Kept in sync with GPS Coordinates.",
+ )
+
+ @api.depends("coordinates")
+ def _compute_gis_lat_long(self):
+ """Derive latitude/longitude from the point geometry (x=lon, y=lat)."""
+ for rec in self:
+ geom = rec.coordinates
+ if geom and not geom.is_empty and getattr(geom, "geom_type", None) == "Point":
+ rec.gis_longitude = geom.x
+ rec.gis_latitude = geom.y
+ else:
+ rec.gis_longitude = 0.0
+ rec.gis_latitude = 0.0
+
+ def _inverse_gis_lat_long(self):
+ """Rebuild the point geometry when latitude/longitude are entered.
+
+ Both values are taken from the record, so filling either field commits
+ the current pair. (0, 0) is treated as "unset" and clears the point.
+ """
+ for rec in self:
+ if rec.gis_latitude or rec.gis_longitude:
+ rec.coordinates = json.dumps({"type": "Point", "coordinates": [rec.gis_longitude, rec.gis_latitude]})
+ else:
+ rec.coordinates = False
diff --git a/spp_registrant_gis/tests/test_registrant_gis.py b/spp_registrant_gis/tests/test_registrant_gis.py
index c815820e2..64c2fe2d2 100644
--- a/spp_registrant_gis/tests/test_registrant_gis.py
+++ b/spp_registrant_gis/tests/test_registrant_gis.py
@@ -79,3 +79,25 @@ def test_coordinates_empty_by_default(self):
# Coordinates should be False/empty by default
self.assertFalse(registrant.coordinates)
+
+ # ── OP#1143: visible latitude/longitude inputs synced with coordinates ──
+ def test_lat_long_computed_from_coordinates(self):
+ """Setting coordinates populates the latitude/longitude inputs."""
+ registrant = self.partner_model.create({"name": "LatLong From Point", "is_registrant": True})
+ registrant.write({"coordinates": json.dumps({"type": "Point", "coordinates": [121.5, 14.25]})})
+ self.assertAlmostEqual(registrant.gis_longitude, 121.5, places=5)
+ self.assertAlmostEqual(registrant.gis_latitude, 14.25, places=5)
+
+ def test_coordinates_built_from_lat_long(self):
+ """Typing latitude/longitude rebuilds the coordinates point."""
+ group = self.partner_model.create({"name": "LatLong Group", "is_registrant": True, "is_group": True})
+ group.write({"gis_latitude": 8.5, "gis_longitude": 124.75})
+ self.assertTrue(group.coordinates)
+ self.assertAlmostEqual(group.coordinates.x, 124.75, places=5) # x = longitude
+ self.assertAlmostEqual(group.coordinates.y, 8.5, places=5) # y = latitude
+
+ def test_lat_long_empty_when_no_coordinates(self):
+ """With no point set, the latitude/longitude inputs read as 0."""
+ registrant = self.partner_model.create({"name": "No Coords", "is_registrant": True})
+ self.assertEqual(registrant.gis_latitude, 0.0)
+ self.assertEqual(registrant.gis_longitude, 0.0)
diff --git a/spp_registrant_gis/views/res_partner_views.xml b/spp_registrant_gis/views/res_partner_views.xml
index 5a258a565..3bed3464e 100644
--- a/spp_registrant_gis/views/res_partner_views.xml
+++ b/spp_registrant_gis/views/res_partner_views.xml
@@ -14,6 +14,11 @@
>
+
+
+
@@ -33,6 +38,11 @@
>
+
+
+