diff --git a/frappe/integrations/doctype/geolocation_settings/geolocation_settings.json b/frappe/integrations/doctype/geolocation_settings/geolocation_settings.json index 52fa6691b3..ed69716cd8 100644 --- a/frappe/integrations/doctype/geolocation_settings/geolocation_settings.json +++ b/frappe/integrations/doctype/geolocation_settings/geolocation_settings.json @@ -6,6 +6,7 @@ "field_order": [ "enable_address_autocompletion", "provider", + "base_url", "api_key" ], "fields": [ @@ -14,24 +15,33 @@ "fieldtype": "Select", "label": "Provider", "mandatory_depends_on": "enable_address_autocompletion", - "options": "Geoapify" + "options": "Geoapify\nNomatim" }, { + "depends_on": "eval: doc.provider === \"Geoapify\"", "fieldname": "api_key", "fieldtype": "Password", "label": "API Key", - "mandatory_depends_on": "enable_address_autocompletion" + "mandatory_depends_on": "eval: doc.enable_address_autocompletion && doc.provider === \"Geoapify\"" }, { "default": "0", "fieldname": "enable_address_autocompletion", "fieldtype": "Check", "label": "Enable Address Autocompletion" + }, + { + "depends_on": "eval: doc.provider === \"Nomatim\"", + "fieldname": "base_url", + "fieldtype": "Data", + "label": "Base URL", + "mandatory_depends_on": "eval: doc.provider === \"Nomatim\" && doc.enable_address_autocompletion", + "options": "URL" } ], "issingle": 1, "links": [], - "modified": "2024-05-19 20:43:49.711209", + "modified": "2024-05-19 22:00:01.118978", "modified_by": "Administrator", "module": "Integrations", "name": "Geolocation Settings", diff --git a/frappe/integrations/doctype/geolocation_settings/geolocation_settings.py b/frappe/integrations/doctype/geolocation_settings/geolocation_settings.py index 62fa0dd276..287ce23398 100644 --- a/frappe/integrations/doctype/geolocation_settings/geolocation_settings.py +++ b/frappe/integrations/doctype/geolocation_settings/geolocation_settings.py @@ -4,8 +4,10 @@ import frappe from frappe import _ from frappe.model.document import Document +from frappe.utils import get_url from .providers.geoapify import Geoapify +from .providers.nomatim import Nomatim class GeolocationSettings(Document): @@ -18,8 +20,9 @@ class GeolocationSettings(Document): from frappe.types import DF api_key: DF.Password | None + base_url: DF.Data | None enable_address_autocompletion: DF.Check - provider: DF.Literal["Geoapify"] + provider: DF.Literal["Geoapify", "Nomatim"] # end: auto-generated types pass @@ -36,6 +39,12 @@ def autocomplete(txt: str) -> list[dict]: if settings.provider == "Geoapify": provider = Geoapify(settings.get_password("api_key"), frappe.local.lang) + elif settings.provider == "Nomatim": + provider = Nomatim( + base_url=settings.base_url, + referer=get_url(), + lang=frappe.local.lang, + ) else: frappe.throw(_("This geolocation provider is not supported yet.")) diff --git a/frappe/integrations/doctype/geolocation_settings/providers/nomatim.py b/frappe/integrations/doctype/geolocation_settings/providers/nomatim.py new file mode 100644 index 0000000000..c02e14ad68 --- /dev/null +++ b/frappe/integrations/doctype/geolocation_settings/providers/nomatim.py @@ -0,0 +1,47 @@ +import json + +import requests + +import frappe + + +class Nomatim: + def __init__(self, base_url: str, referer: str, lang: str | None = None): + self.lang = lang + self.referer = referer + self.base_url = base_url + + def autocomplete(self, query: str): + params = { + "q": query, + "format": "json", + "limit": 5, + "addressdetails": 1, + "accept-language": self.lang, + "layer": "address", + } + response = requests.get( + f"{self.base_url}/search", + params=params, + headers={"Referer": self.referer}, + ) + response.raise_for_status() + + results = response.json() + for result in results: + if "address" not in result: + continue + + address = result["address"] + yield { + "label": result["display_name"], + "value": json.dumps( + { + "address_line1": f'{address.get("road")} {address.get("house_number", "")}'.strip(), + "city": address.get("city") or address.get("town") or address.get("village"), + "state": address.get("state"), + "pincode": address.get("postcode"), + "country": frappe.db.get_value("Country", {"code": address.get("country_code")}), + } + ), + }