From 2bfa8f682148b97299be2c7e483e16e93d743d0c Mon Sep 17 00:00:00 2001 From: Raphael Odini Date: Wed, 22 Nov 2023 11:37:06 +0100 Subject: [PATCH] feat: simple Product model (#44) * Add Product model * Add schema. Fix migration name * Replace ProductOFFSource with openfoodfacts.Flavor --- ..._1856_df15f7cacf48_create_product_table.py | 50 +++++++++++++++++++ app/models.py | 18 ++++++- app/schemas.py | 26 +++++++++- 3 files changed, 92 insertions(+), 2 deletions(-) create mode 100644 alembic/versions/20231121_1856_df15f7cacf48_create_product_table.py diff --git a/alembic/versions/20231121_1856_df15f7cacf48_create_product_table.py b/alembic/versions/20231121_1856_df15f7cacf48_create_product_table.py new file mode 100644 index 00000000..bf8b57e9 --- /dev/null +++ b/alembic/versions/20231121_1856_df15f7cacf48_create_product_table.py @@ -0,0 +1,50 @@ +"""Create Product table + +Revision ID: aead2a83cfa8 +Revises: 1c8431a64d3a +Create Date: 2023-11-21 18:56:39.786743 + +""" +from typing import Sequence, Union + +import sqlalchemy as sa + +from alembic import op + +# revision identifiers, used by Alembic. +revision: str = "df15f7cacf48" +down_revision: Union[str, None] = "1c8431a64d3a" +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.create_table( + "products", + sa.Column("id", sa.Integer(), nullable=False), + sa.Column("code", sa.String(), nullable=True), + sa.Column("source", sa.String(length=255), nullable=True), + sa.Column("product_name", sa.String(), nullable=True), + sa.Column("product_quantity", sa.Integer(), nullable=True), + sa.Column("image_url", sa.String(), nullable=True), + sa.Column( + "created", + sa.DateTime(timezone=True), + server_default=sa.text("now()"), + nullable=True, + ), + sa.Column("updated", sa.DateTime(timezone=True), nullable=True), + sa.PrimaryKeyConstraint("id"), + ) + op.create_index(op.f("ix_products_id"), "products", ["id"], unique=False) + op.create_index(op.f("ix_products_code"), "products", ["code"], unique=True) + # ### end Alembic commands ### + + +def downgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + op.drop_index(op.f("ix_products_code"), table_name="products") + op.drop_index(op.f("ix_products_id"), table_name="products") + op.drop_table("products") + # ### end Alembic commands ### diff --git a/app/models.py b/app/models.py index 762c6645..8064d43d 100644 --- a/app/models.py +++ b/app/models.py @@ -1,3 +1,4 @@ +from openfoodfacts import Flavor from sqlalchemy import ( BigInteger, Column, @@ -31,12 +32,27 @@ class User(Base): __tablename__ = "users" +class Product(Base): + id = Column(Integer, primary_key=True, index=True) + + code = Column(String, unique=True, index=True) + + source = Column(ChoiceType(Flavor)) + product_name = Column(String) + product_quantity = Column(Integer) + image_url = Column(String) + + created = Column(DateTime(timezone=True), server_default=func.now()) + updated = Column(DateTime(timezone=True), onupdate=func.now()) + + __tablename__ = "products" + + class Location(Base): id = Column(Integer, primary_key=True, index=True) osm_id = Column(BigInteger) osm_type = Column(ChoiceType(LocationOSMType)) - osm_name = Column(String) osm_display_name = Column(String) osm_address_postcode = Column(String) diff --git a/app/schemas.py b/app/schemas.py index edb22846..6c8e0448 100644 --- a/app/schemas.py +++ b/app/schemas.py @@ -2,7 +2,15 @@ from typing import Optional from fastapi_filter.contrib.sqlalchemy import Filter -from pydantic import BaseModel, ConfigDict, Field, field_serializer, field_validator +from openfoodfacts import Flavor +from pydantic import ( + AnyHttpUrl, + BaseModel, + ConfigDict, + Field, + field_serializer, + field_validator, +) from sqlalchemy_utils import Currency from app.enums import LocationOSMType @@ -16,6 +24,22 @@ class UserBase(BaseModel): token: str +class ProductCreate(BaseModel): + model_config = ConfigDict(from_attributes=True, arbitrary_types_allowed=True) + + code: str + + +class ProductBase(BaseModel): + id: int + source: Flavor | None + product_name: str | None + product_quantity: int | None + image_url: AnyHttpUrl | None + created: datetime + updated: datetime | None + + class LocationCreate(BaseModel): model_config = ConfigDict(from_attributes=True, arbitrary_types_allowed=True)