diff --git a/alembic/versions/20231218_1553_1e60d73e79cd_add_product_brands_field.py b/alembic/versions/20231218_1553_1e60d73e79cd_add_product_brands_field.py new file mode 100644 index 00000000..18acc71c --- /dev/null +++ b/alembic/versions/20231218_1553_1e60d73e79cd_add_product_brands_field.py @@ -0,0 +1,30 @@ +"""Add product brands field + +Revision ID: 1e60d73e79cd +Revises: 727cb6912bd5 +Create Date: 2023-12-18 15:53:40.553628 + +""" +from typing import Sequence, Union + +import sqlalchemy as sa + +from alembic import op + +# revision identifiers, used by Alembic. +revision: str = "1e60d73e79cd" +down_revision: Union[str, None] = "727cb6912bd5" +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("products", sa.Column("brands", sa.String(), nullable=True)) + # ### end Alembic commands ### + + +def downgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + op.drop_column("products", "brands") + # ### end Alembic commands ### diff --git a/app/models.py b/app/models.py index 8d07b450..0ed51417 100644 --- a/app/models.py +++ b/app/models.py @@ -42,6 +42,7 @@ class Product(Base): source = Column(ChoiceType(Flavor)) product_name = Column(String) product_quantity = Column(Integer) + brands = Column(String) image_url = Column(String) prices: Mapped[list["Price"]] = relationship(back_populates="product") diff --git a/app/schemas.py b/app/schemas.py index e6c217ed..ab0afc35 100644 --- a/app/schemas.py +++ b/app/schemas.py @@ -47,6 +47,10 @@ class ProductBase(ProductCreate): description="quantity of the product, normalized in g or mL (depending on the product).", examples=[700], ) + brands: int | None = Field( + description="brand(s) of the product.", + examples=["Rigoni di Asiago", "Lindt"], + ) image_url: AnyHttpUrl | None = Field( description="URL of the product image.", examples=[ diff --git a/app/utils.py b/app/utils.py index e77ffde7..6e08dfa5 100644 --- a/app/utils.py +++ b/app/utils.py @@ -31,6 +31,9 @@ def init_sentry(sentry_dsn: str | None, integrations: list[Integration] | None = # OpenFoodFacts # ------------------------------------------------------------------------------ +OFF_FIELDS = ["product_name", "product_quantity", "brands", "image_url"] + + def openfoodfacts_product_search(code: str): client = API( username=None, @@ -49,7 +52,7 @@ def fetch_product_openfoodfacts_details(product: ProductBase): response = openfoodfacts_product_search(code=product.code) if response["status"]: product_openfoodfacts_details["source"] = Flavor.off - for off_field in ["product_name", "product_quantity", "image_url"]: + for off_field in OFF_FIELDS: if off_field in response["product"]: product_openfoodfacts_details[off_field] = response["product"][ off_field @@ -62,6 +65,10 @@ def fetch_product_openfoodfacts_details(product: ProductBase): # OpenStreetMap # ------------------------------------------------------------------------------ +OSM_FIELDS = ["name", "display_name", "lat", "lon"] +OSM_ADDRESS_FIELDS = ["postcode", "city", "country"] + + def openstreetmap_nominatim_search(osm_id: int, osm_type: str): client = Nominatim() search_query = f"{osm_type}/{osm_id}" @@ -75,13 +82,13 @@ def fetch_location_openstreetmap_details(location: LocationBase): osm_id=location.osm_id, osm_type=location.osm_type.value.lower() ) if len(response): - for osm_field in ["name", "display_name", "lat", "lon"]: + for osm_field in OSM_FIELDS: if osm_field in response[0]: location_openstreetmap_details[f"osm_{osm_field}"] = response[0][ osm_field ] if "address" in response[0]: - for osm_address_field in ["postcode", "city", "country"]: + 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}"