Skip to content

Commit

Permalink
feat: add price.price_per field (#127)
Browse files Browse the repository at this point in the history
  • Loading branch information
raphael0202 authored Jan 11, 2024
1 parent 27b7f0f commit 5740271
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
"""add product.price_per field
Revision ID: a8ad2f078f3f
Revises: 007443669adc
Create Date: 2024-01-11 09:14:25.778905
"""
from typing import Sequence, Union

import sqlalchemy as sa

from alembic import op

# revision identifiers, used by Alembic.
revision: str = "a8ad2f078f3f"
down_revision: Union[str, None] = "007443669adc"
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(
"price_per",
sa.String(length=255),
nullable=True,
),
)
op.execute(
"UPDATE prices SET price_per = 'KILOGRAM' WHERE price_per IS NULL AND category_tag IS NOT NULL;"
)
# ### end Alembic commands ###


def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column("prices", "price_per")
# ### end Alembic commands ###
12 changes: 11 additions & 1 deletion app/enums.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from enum import Enum
from enum import Enum, unique

from babel.numbers import list_currencies

Expand All @@ -17,3 +17,13 @@ class ProofTypeEnum(Enum):
PRICE_TAG = "PRICE_TAG"
RECEIPT = "RECEIPT"
GDPR_REQUEST = "GDPR_REQUEST"


@unique
class PricePerEnum(Enum):
"""For raw products (fruits, vegetables, etc.), the price is either
per unit or per kilogram. This enum is used to store this information.
"""

UNIT = "UNIT"
KILOGRAM = "KILOGRAM"
3 changes: 2 additions & 1 deletion app/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
from sqlalchemy_utils.types.choice import ChoiceType

from app.db import Base
from app.enums import CurrencyEnum, LocationOSMEnum, ProofTypeEnum
from app.enums import CurrencyEnum, LocationOSMEnum, PricePerEnum, ProofTypeEnum

force_auto_coercion()
JSONVariant = JSON().with_variant(JSONB(), "postgresql")
Expand Down Expand Up @@ -108,6 +108,7 @@ class Price(Base):

price = Column(Numeric(precision=10, scale=2))
currency = Column(ChoiceType(CurrencyEnum))
price_per = Column(ChoiceType(PricePerEnum))

location_osm_id = Column(BigInteger, index=True)
location_osm_type = Column(ChoiceType(LocationOSMEnum))
Expand Down
17 changes: 16 additions & 1 deletion app/schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
model_validator,
)

from app.enums import CurrencyEnum, LocationOSMEnum, ProofTypeEnum
from app.enums import CurrencyEnum, LocationOSMEnum, PricePerEnum, ProofTypeEnum
from app.models import Price, Product


Expand Down Expand Up @@ -154,6 +154,14 @@ class PriceCreate(BaseModel):
"kilogram or per liter.",
examples=["1.99"],
)
price_per: PricePerEnum | None = Field(
default=PricePerEnum.KILOGRAM,
description="""if the price is about a barcode-less product
(if `category_tag` is provided), this field must be set to `KILOGRAM`
or `UNIT` (KILOGRAM by default).
This field is set to null and ignored if `product_code` is provided.
""",
)
currency: CurrencyEnum = Field(
description="currency of the price, as a string. "
"The currency must be a valid currency code. "
Expand Down Expand Up @@ -249,6 +257,13 @@ def product_code_and_category_tag_are_exclusive(self):
raise ValueError("either `product_code` or `category_tag` must be set")
return self

@model_validator(mode="after")
def set_price_per_to_null_if_barcode(self):
"""Validator that sets `price_per` to null if `product_code` is set."""
if self.product_code is not None:
self.price_per = None
return self


class PriceBase(PriceCreate):
product_id: int | None
Expand Down
2 changes: 2 additions & 0 deletions tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ def test_create_price_with_category_tag(db_session, user, clean_prices):
"labels_tags": ["en:Organic"],
"origins_tags": ["en:France"],
"date": "2023-12-01",
"price_per": "UNIT",
}
)
response = client.post(
Expand All @@ -155,6 +156,7 @@ def test_create_price_with_category_tag(db_session, user, clean_prices):
assert json_response.get("labels_tags") == ["en:organic"]
assert json_response.get("origins_tags") == ["en:france"]
assert json_response.get("date") == "2023-12-01"
assert json_response.get("price_per") == "UNIT"
assert "id" not in response.json()
db_prices = crud.get_prices(db_session)
assert len(db_prices) == 1
Expand Down

0 comments on commit 5740271

Please sign in to comment.