diff --git a/app/migrations/env.py b/app/migrations/env.py index 9c8dad1..caa838d 100644 --- a/app/migrations/env.py +++ b/app/migrations/env.py @@ -1,7 +1,7 @@ # flake8: noqa -from pathlib import Path import importlib from logging.config import fileConfig +from pathlib import Path from alembic import context from sqlalchemy import engine_from_config, pool diff --git a/app/models/static.py b/app/models/static.py index 3a3c8d7..259167d 100644 --- a/app/models/static.py +++ b/app/models/static.py @@ -47,12 +47,12 @@ WebURL: str = Field( ..., - pattern=r"^https?://(?:[a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}(?::\d+)?" r"(?:/[^\s]*)?$", + pattern=r"^https?://(?:[a-zA-Z0-9-]+\.)+[a-zA-Z]{2,}(?::\d+)?" + r"(?:/[^\s]*)?$", description=( "A valid web URL, starting with 'http://' or 'https://'. It can " "include domain names, optional ports, and paths. Example: " - "'https://www.example.com' or 'http://example.com:8080/path'." - ), + "'https://www.example.com' or 'http://example.com:8080/path'."), examples=[ "https://www.helpwave.de", "https://www.example.com", diff --git a/app/models/voucher.py b/app/models/voucher.py index 67b71c6..1aba3f3 100644 --- a/app/models/voucher.py +++ b/app/models/voucher.py @@ -4,8 +4,8 @@ from pydantic import BaseModel from sqlalchemy import Column, DateTime, ForeignKey, Integer, Numeric, String, Text -from sqlalchemy.orm import relationship from sqlalchemy.dialects.postgresql import UUID +from sqlalchemy.orm import relationship from utils.database.connection import Base diff --git a/app/routers/customer_product.py b/app/routers/customer_product.py index 4c819c2..6d28e29 100644 --- a/app/routers/customer_product.py +++ b/app/routers/customer_product.py @@ -7,19 +7,22 @@ from models.customer_product import ( CustomerProduct, CustomerProductBase, - CustomerProductCreate, CustomerProductCalculation, CustomerProductCalculationRequest, + CustomerProductCreate, ExtendedCustomerProductBase, ) from models.customer_product_contract import CustomerProductContract from models.invoice import Invoice from models.product import Product -from models.product_plan import ProductPlan from models.product_contract import ProductContract +from models.product_plan import ProductPlan from models.static import PlanTypeEnum from models.voucher import Voucher -from utils.calculation.pricing import calculate_pricing_in_euro, calculate_full_pricing_in_euro +from utils.calculation.pricing import ( + calculate_full_pricing_in_euro, + calculate_pricing_in_euro, +) from utils.database.session import get_database from utils.security.token import get_user diff --git a/app/routers/product.py b/app/routers/product.py index 9536cbd..60d0dfc 100644 --- a/app/routers/product.py +++ b/app/routers/product.py @@ -1,8 +1,11 @@ from uuid import UUID from fastapi import APIRouter, Depends, HTTPException +from models.customer_product import CustomerProduct from models.product import Product, ProductBase +from models.user import User from utils.database.session import get_database +from utils.security.token import get_user router = APIRouter(prefix="/product", tags=["Product"]) @@ -20,3 +23,20 @@ async def read(uuid: UUID, session=Depends(get_database)): raise HTTPException(status_code=404, detail="Product not found.") return product + + +@router.get("/available/", response_model=list[ProductBase]) +async def available(user: User = Depends(get_user), + session=Depends(get_database)): + + if not user.customer: + raise HTTPException( + status_code=404, + detail="Customer not created yet.") + + booked_product_uuids = session.query(CustomerProduct.product_uuid).filter( + CustomerProduct.customer_uuid == user.customer_uuid).subquery() + available_products = session.query(Product).filter( + ~Product.uuid.in_(booked_product_uuids)).all() + + return available_products