Skip to content

Commit

Permalink
feat: add a new /products endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
raphael0202 committed Jan 5, 2024
1 parent 135e33b commit b42ff8e
Show file tree
Hide file tree
Showing 6 changed files with 901 additions and 861 deletions.
22 changes: 19 additions & 3 deletions app/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,20 @@
from fastapi.middleware.cors import CORSMiddleware
from fastapi.security import OAuth2PasswordRequestForm
from fastapi.templating import Jinja2Templates
from fastapi_filter import FilterDepends
from fastapi_filters import FilterValues, SortingValues, create_filters, create_sorting
from fastapi_filters.ext.sqlalchemy import apply_filters_and_sorting, apply_sorting
from fastapi_pagination import Page, add_pagination
from fastapi_pagination.ext.sqlalchemy import paginate
from openfoodfacts.utils import get_logger
from sqlalchemy import select
from sqlalchemy.orm import Session

from app import crud, schemas, tasks
from app.auth import OAuth2PasswordBearerOrAuthCookie
from app.config import settings
from app.db import session
from app.enums import ProofTypeEnum
from app.models import Product
from app.utils import init_sentry

logger = get_logger(level=settings.log_level.to_int())
Expand Down Expand Up @@ -167,10 +170,13 @@ def authentication(

@app.get("/api/v1/prices", response_model=Page[schemas.PriceFull], tags=["Prices"])
def get_price(
filters: schemas.PriceFilter = FilterDepends(schemas.PriceFilter),
db: Session = Depends(get_db),
filters: FilterValues = Depends(create_filters(**schemas.PRICE_FILTERS)),
sorting: SortingValues = Depends(create_sorting("date", "price")),
):
return paginate(db, crud.get_prices_query(filters=filters))
return paginate(
db, apply_filters_and_sorting(crud.get_prices_query(), filters, sorting)
)


@app.post(
Expand Down Expand Up @@ -267,6 +273,16 @@ def get_product_by_code(product_code: str, db: Session = Depends(get_db)):
return db_product


@app.get(
"/api/v1/products", response_model=Page[schemas.ProductBase], tags=["Products"]
)
def get_products(
db: Session = Depends(get_db),
sorting: SortingValues = Depends(create_sorting(("unique_scans_n", "smaller"))),
):
return paginate(db, apply_sorting(select(Product), sorting))


@app.get(
"/api/v1/products/{product_id}",
response_model=schemas.ProductBase,
Expand Down
12 changes: 3 additions & 9 deletions app/crud.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
LocationCreate,
PriceBase,
PriceCreate,
PriceFilter,
ProductBase,
ProductCreate,
UserBase,
Expand Down Expand Up @@ -105,23 +104,18 @@ def update_product(db: Session, product: ProductBase, update_dict: dict):

# Prices
# ------------------------------------------------------------------------------
def get_prices_query(
with_join_product=True, with_join_location=True, filters: PriceFilter | None = None
):
def get_prices_query(with_join_product=True, with_join_location=True):
"""Useful for pagination."""
query = select(Price)
if with_join_product:
query = query.options(joinedload(Price.product))
if with_join_location:
query = query.options(joinedload(Price.location))
if filters:
query = filters.filter(query)
query = filters.sort(query)
return query


def get_prices(db: Session, filters: PriceFilter | None = None):
return db.execute(get_prices_query(filters=filters)).all()
def get_prices(db: Session):
return db.execute(get_prices_query()).all()


def create_price(db: Session, price: PriceCreate, user: UserBase):
Expand Down
62 changes: 33 additions & 29 deletions app/schemas.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import datetime
from typing import Optional

from fastapi_filter.contrib.sqlalchemy import Filter
from fastapi_filters import FilterField, FilterOperator
from openfoodfacts import Flavor
from openfoodfacts.taxonomy import get_taxonomy
from pydantic import (
Expand All @@ -14,7 +13,6 @@
)

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


class UserBase(BaseModel):
Expand Down Expand Up @@ -277,29 +275,35 @@ class ProofBase(BaseModel):
created: datetime.datetime


class PriceFilter(Filter):
product_code: Optional[str] | None = None
product_id: Optional[int] | None = None
category_tag: Optional[str] | None = None
labels_tags__like: Optional[str] | None = None
origins_tags__like: Optional[str] | None = None
location_osm_id: Optional[int] | None = None
location_osm_type: Optional[LocationOSMEnum] | None = None
location_id: Optional[int] | None = None
price: Optional[int] | None = None
price__gt: Optional[int] | None = None
price__gte: Optional[int] | None = None
price__lt: Optional[int] | None = None
price__lte: Optional[int] | None = None
currency: Optional[str] | None = None
date: Optional[str] | None = None
date__gt: Optional[str] | None = None
date__gte: Optional[str] | None = None
date__lt: Optional[str] | None = None
date__lte: Optional[str] | None = None
owner: Optional[str] | None = None

order_by: Optional[list[str]] | None = None

class Constants(Filter.Constants):
model = Price
PRICE_FILTERS = {
"product_code": FilterField(str, operators={FilterOperator.eq}),
"product_id": FilterField(int, operators={FilterOperator.eq}),
"category_tag": FilterField(str, operators={FilterOperator.eq}),
"labels_tags": FilterField(list[str], operators={FilterOperator.like}),
"origins_tags": FilterField(list[str], operators={FilterOperator.like}),
"location_osm_id": FilterField(int, operators={FilterOperator.eq}),
"location_osm_type": FilterField(LocationOSMEnum, operators={FilterOperator.eq}),
"location_id": FilterField(int, operators={FilterOperator.eq}),
"price": FilterField(
float,
operators={
FilterOperator.eq,
FilterOperator.gt,
FilterOperator.lt,
FilterOperator.ge,
FilterOperator.le,
},
),
"currency": FilterField(str, operators={FilterOperator.eq}),
"date": FilterField(
datetime.date,
operators={
FilterOperator.eq,
FilterOperator.gt,
FilterOperator.lt,
FilterOperator.ge,
FilterOperator.le,
},
),
"owner": FilterField(str, operators={FilterOperator.eq}),
}
Loading

0 comments on commit b42ff8e

Please sign in to comment.