Skip to content

Commit

Permalink
feat: add labels_tags field
Browse files Browse the repository at this point in the history
This field is used to store labels of products without barcode
  • Loading branch information
raphael0202 committed Nov 23, 2023
1 parent bcbcc2a commit 3a368a5
Show file tree
Hide file tree
Showing 4 changed files with 76 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
"""add prices.labels_tags field
Revision ID: 012466c0013e
Revises: 5acb37b190cc
Create Date: 2023-11-23 14:00:14.162599
"""
from typing import Sequence, Union

import sqlalchemy as sa
from sqlalchemy.dialects import postgresql

from alembic import op

# revision identifiers, used by Alembic.
revision: str = "012466c0013e"
down_revision: Union[str, None] = "5acb37b190cc"
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(
"prices",
sa.Column(
"labels_tags", postgresql.JSONB(astext_type=sa.Text()), nullable=True
),
)
op.create_index(
op.f("ix_prices_labels_tags"), "prices", ["labels_tags"], unique=False
)
# ### end Alembic commands ###


def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.drop_index(op.f("ix_prices_labels_tags"), table_name="prices")
op.drop_column("prices", "labels_tags")
# ### end Alembic commands ###
11 changes: 11 additions & 0 deletions app/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,17 @@ def create_price(
detail=f"Invalid category tag: category '{price.category_tag}' does not exist in the taxonomy",
)

if price.labels_tags is not None:
# lowercase the labels tags to perform the match
price.labels_tags = [label_tag.lower() for label_tag in price.labels_tags]
labels_taxonomy = get_taxonomy("label")
for label_tag in price.labels_tags:
if label_tag not in labels_taxonomy:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=f"Invalid label tag: label '{label_tag}' does not exist in the taxonomy",
)

db_price = crud.create_price(db, price=price, user=current_user)
background_tasks.add_task(tasks.create_price_product, db, db_price)
background_tasks.add_task(tasks.create_price_location, db, db_price)
Expand Down
2 changes: 2 additions & 0 deletions app/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
Numeric,
String,
)
from sqlalchemy.dialects.postgresql import JSONB
from sqlalchemy.orm import Mapped, mapped_column, relationship
from sqlalchemy.sql import func
from sqlalchemy_utils import force_auto_coercion
Expand Down Expand Up @@ -91,6 +92,7 @@ class Price(Base):

product_code = Column(String, nullable=True, index=True)
category_tag = Column(String, nullable=True, index=True)
labels_tags = Column(JSONB, nullable=True, index=True)
product_id: Mapped[int] = mapped_column(ForeignKey("products.id"), nullable=True)
product: Mapped[Product] = relationship(back_populates="prices")

Expand Down
24 changes: 23 additions & 1 deletion app/schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,25 @@ class PriceCreate(BaseModel):
This ID must be a canonical category ID in the Open Food Facts taxonomy.
If the ID is not valid, the price will be rejected.""",
)
labels_tags: list[str] | None = Field(
default=None,
description="""labels of the product, only for products without barcode.
The labels must be valid labels in the Open Food Facts taxonomy.
If one of the labels is not valid, the price will be rejected.
The most common labels are:
- `en:organic`: the product is organic
- `en:fair-trade`: the product is fair-trade
Other labels can be provided if relevant.
""",
)
price: float = Field(
gt=0,
description="price of the product, without its currency, taxes included.",
description="price of the product, without its currency, taxes included. "
"If the price is about a barcode-less product, it must be the price per "
"kilogram or per liter.",
examples=["1.99"],
)
currency: str | Currency = Field(
Expand Down Expand Up @@ -143,6 +159,12 @@ def currency_is_valid(cls, v):
except ValueError:
raise ValueError("not a valid currency code")

@field_validator("labels_tags")
def labels_tags_is_valid(cls, v):
if v is not None:
if len(v) == 0:
raise ValueError("`labels_tags` cannot be empty")

@field_serializer("currency")
def serialize_currency(self, currency: Currency, _info):
if type(currency) is Currency:
Expand Down

0 comments on commit 3a368a5

Please sign in to comment.