diff --git a/alembic/versions/20240520_1604_dd4776351212_add_location_osm_tag_key_osm_tag_value_.py b/alembic/versions/20240520_1604_dd4776351212_add_location_osm_tag_key_osm_tag_value_fields.py similarity index 100% rename from alembic/versions/20240520_1604_dd4776351212_add_location_osm_tag_key_osm_tag_value_.py rename to alembic/versions/20240520_1604_dd4776351212_add_location_osm_tag_key_osm_tag_value_fields.py diff --git a/alembic/versions/20240520_1704_2737db183adb_add_location_osm_address_country_code_field.py b/alembic/versions/20240520_1704_2737db183adb_add_location_osm_address_country_code_field.py new file mode 100644 index 00000000..2708e172 --- /dev/null +++ b/alembic/versions/20240520_1704_2737db183adb_add_location_osm_address_country_code_field.py @@ -0,0 +1,32 @@ +"""Add Location osm_address_country_code field + +Revision ID: 2737db183adb +Revises: dd4776351212 +Create Date: 2024-05-20 17:04:40.347002 + +""" +from typing import Sequence, Union + +import sqlalchemy as sa + +from alembic import op + +# revision identifiers, used by Alembic. +revision: str = "2737db183adb" +down_revision: Union[str, None] = "dd4776351212" +branch_labels: Union[str, Sequence[str], None] = None +depends_on: Union[str, Sequence[str], None] = None + + +def upgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + op.add_column( + "locations", sa.Column("osm_address_country_code", sa.String(), nullable=True) + ) + # ### end Alembic commands ### + + +def downgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + op.drop_column("locations", "osm_address_country_code") + # ### end Alembic commands ### diff --git a/app/models.py b/app/models.py index bc5d7d19..b454f7d2 100644 --- a/app/models.py +++ b/app/models.py @@ -97,6 +97,7 @@ class Location(Base): osm_address_postcode = mapped_column(String) osm_address_city = mapped_column(String) osm_address_country = mapped_column(String) + osm_address_country_code = mapped_column(String) osm_lat = mapped_column(Numeric(precision=11, scale=7)) osm_lon = mapped_column(Numeric(precision=11, scale=7)) diff --git a/app/schemas.py b/app/schemas.py index 60ebaf40..5e0b1912 100644 --- a/app/schemas.py +++ b/app/schemas.py @@ -155,6 +155,14 @@ class LocationFull(LocationCreate): osm_address_postcode: str | None = None osm_address_city: str | None = None osm_address_country: str | None = None + osm_address_country_code: str | None = Field( + default=None, + min_length=2, + max_length=2, + pattern=r"^[A-Z]{2}$", + description="OSM country code (ISO 3166-1 alpha-2)", + examples=["FR", "US"], + ) osm_lat: float | None = None osm_lon: float | None = None created: datetime.datetime = Field(description="datetime of the creation.") diff --git a/app/utils.py b/app/utils.py index 3d404e30..defe48cb 100644 --- a/app/utils.py +++ b/app/utils.py @@ -148,7 +148,11 @@ def fetch_product_openfoodfacts_details( # ------------------------------------------------------------------------------ OSM_FIELDS = ["name", "display_name", "lat", "lon"] OSM_TAG_FIELDS_MAPPING = {"class": "tag_key", "type": "tag_value"} -OSM_ADDRESS_FIELDS = ["postcode", "country"] # 'city" is managed seperately +OSM_ADDRESS_FIELDS = [ + "postcode", + "country", + "country_code", +] # 'city" is managed seperately # https://wiki.openstreetmap.org/wiki/Key:place OSM_ADDRESS_PLACE_FIELDS = ["village", "town", "city", "municipality"] @@ -170,28 +174,30 @@ def fetch_location_openstreetmap_details( if len(response): for osm_field in OSM_FIELDS: if osm_field in response[0]: - location_openstreetmap_details[f"osm_{osm_field}"] = response[0][ - osm_field - ] + key = f"osm_{osm_field}" + value = response[0][osm_field] + location_openstreetmap_details[key] = value for osm_field in list(OSM_TAG_FIELDS_MAPPING.keys()): if osm_field in response[0]: - location_openstreetmap_details[ - f"osm_{OSM_TAG_FIELDS_MAPPING[osm_field]}" - ] = response[0][osm_field] + key = f"osm_{OSM_TAG_FIELDS_MAPPING[osm_field]}" + value = response[0][osm_field] + location_openstreetmap_details[key] = value if "address" in response[0]: for osm_address_field in OSM_ADDRESS_FIELDS: if osm_address_field in response[0]["address"]: - location_openstreetmap_details[ - f"osm_address_{osm_address_field}" - ] = response[0]["address"][osm_address_field] + key = f"osm_address_{osm_address_field}" + value = response[0]["address"][osm_address_field] + if osm_address_field == "country_code": # "fr" -> "FR" + value = value.upper() + location_openstreetmap_details[key] = value # manage city location_openstreetmap_details["osm_address_city"] = None for osm_address_place_field in OSM_ADDRESS_PLACE_FIELDS: if osm_address_place_field in response[0]["address"]: if not location_openstreetmap_details["osm_address_city"]: - location_openstreetmap_details[ - "osm_address_city" - ] = response[0]["address"][osm_address_place_field] + key = "osm_address_city" + value = response[0]["address"][osm_address_place_field] + location_openstreetmap_details[key] = value return location_openstreetmap_details except Exception: diff --git a/tests/integration/test_api.py b/tests/integration/test_api.py index 5839adcc..63de5203 100644 --- a/tests/integration/test_api.py +++ b/tests/integration/test_api.py @@ -102,6 +102,7 @@ def override_get_db(): osm_address_postcode="38000", osm_address_city="Grenoble", osm_address_country="France", + osm_address_country_code="FR", osm_lat=45.1805534, osm_lon=5.7153387, created=datetime.datetime.now(), @@ -118,6 +119,7 @@ def override_get_db(): osm_address_postcode="1000", osm_address_city="Bruxelles - Brussel", osm_address_country="Belgiƫ / Belgique / Belgien", + osm_address_country_code="BE", osm_lat=1, osm_lon=2, created=datetime.datetime.now(),