Skip to content

Commit

Permalink
feat: add price.price_without_discount field (#130)
Browse files Browse the repository at this point in the history
  • Loading branch information
raphael0202 authored Jan 11, 2024
1 parent 73b32e6 commit 5e3be73
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 3 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
"""add price_price_without_discount field
Revision ID: fffca9fb2990
Revises: 6492fd03aab5
Create Date: 2024-01-11 10:31:00.992969
"""
from typing import Sequence, Union

import sqlalchemy as sa

from alembic import op

# revision identifiers, used by Alembic.
revision: str = "fffca9fb2990"
down_revision: Union[str, None] = "6492fd03aab5"
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_without_discount", sa.Numeric(precision=10, scale=2), nullable=True
),
)
# ### end Alembic commands ###


def downgrade() -> None:
# ### commands auto generated by Alembic - please adjust! ###
op.drop_column("prices", "price_without_discount")
# ### end Alembic commands ###
1 change: 1 addition & 0 deletions app/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ class Price(Base):
product: Mapped[Product] = relationship(back_populates="prices")

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

Expand Down
20 changes: 17 additions & 3 deletions app/schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -152,11 +152,15 @@ class PriceCreate(BaseModel):
)
price: float = Field(
gt=0,
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.",
description="price of the product, without its currency, taxes included.",
examples=["1.99"],
)
price_without_discount: float | None = Field(
default=None,
description="price of the product without discount, without its currency, taxes included. "
"If the product is not discounted, this field must be null. ",
examples=["2.99"],
)
price_per: PricePerEnum | None = Field(
default=PricePerEnum.KILOGRAM,
description="""if the price is about a barcode-less product
Expand Down Expand Up @@ -267,6 +271,16 @@ def set_price_per_to_null_if_barcode(self):
self.price_per = None
return self

@model_validator(mode="after")
def check_price_without_discout(self):
"""Check that `price_without_discount` is greater than `price`."""
if self.price_without_discount is not None:
if self.price_without_discount <= self.price:
raise ValueError(
"`price_without_discount` must be greater than `price`"
)
return self


class PriceBase(PriceCreate):
product_id: int | None
Expand Down
1 change: 1 addition & 0 deletions tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ def override_get_db():
product_name="PATE NOCCIOLATA BIO 700G",
# category="en:tomatoes",
price=3.5,
price_without_discount=4.5,
currency="EUR",
location_osm_id=123,
location_osm_type="NODE",
Expand Down
15 changes: 15 additions & 0 deletions tests/unit/test_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,3 +85,18 @@ def test_simple_price_with_product_code_and_labels_tags_raise(self):
currency="EUR",
date="2021-01-01",
)

def test_price_without_discount_raise(self):
with pytest.raises(
pydantic.ValidationError,
match="`price_without_discount` must be greater than `price`",
):
PriceCreateWithValidation(
product_code="5414661000456",
location_osm_id=123,
location_osm_type=LocationOSMEnum.NODE,
price=1.99,
price_without_discount=1.50,
currency="EUR",
date="2021-01-01",
)

0 comments on commit 5e3be73

Please sign in to comment.