From ede8573a859579ba5ee0e163ef66576e9fc49a47 Mon Sep 17 00:00:00 2001 From: Rahul Gopathi Date: Sat, 16 Sep 2023 08:23:28 +0530 Subject: [PATCH] Add one more route in products Signed-off-by: Rahul Gopathi --- api/main.py | 12 +++++--- api/routers/prices.py | 6 ++-- api/routers/products.py | 48 +++++++++++++++++++++++++++++++- api/utils/__init__.py | 0 api/utils/customHTTPException.py | 6 ++++ load-data/main.py | 8 +++--- 6 files changed, 69 insertions(+), 11 deletions(-) create mode 100644 api/utils/__init__.py create mode 100644 api/utils/customHTTPException.py diff --git a/api/main.py b/api/main.py index afd023f..57ca217 100644 --- a/api/main.py +++ b/api/main.py @@ -1,6 +1,7 @@ -from fastapi import FastAPI, HTTPException +from fastapi import FastAPI from fastapi.responses import JSONResponse from api.routers import product_family, services, products, prices +from api.utils.customHTTPException import CustomHTTPException # Create a FastAPI instance api = FastAPI() @@ -13,6 +14,9 @@ # Custom exception handler to return a 404 response -@api.exception_handler(HTTPException) -async def not_found_exception_handler(request, exc): - return JSONResponse(content={"detail": "Not Found"}, status_code=404) +@api.exception_handler(CustomHTTPException) +async def custom_exception_handler(request, exc): + if exc.status_code and exc.detail: + return JSONResponse(content={"detail": exc.detail}, status_code=exc.status_code) + else: + return JSONResponse(content={"detail": "Not Found"}, status_code=404) diff --git a/api/routers/prices.py b/api/routers/prices.py index 065fa8e..b4684ca 100644 --- a/api/routers/prices.py +++ b/api/routers/prices.py @@ -12,7 +12,8 @@ async def get_prices_for_service(service_code: str, skip: int = Query(0, ge=0), # Query the Product table to retrieve prices for the specified service with SessionLocal() as db: query = db.query(Product.id.label("product_id"), Product.sku.label("sku"), Product.location.label("location"), - Product.region_code.label("region_code"), Price.pricePerUnit.label("price"), Price.unit.label("unit"))\ + Product.region_code.label("region_code"), Price.pricePerUnit.label("price"), + Price.unit.label("unit"), Price.description.label("description"))\ .join(Price, Price.product_id == Product.id)\ .filter(Product.service_code == service_code)\ .offset(skip)\ @@ -21,6 +22,7 @@ async def get_prices_for_service(service_code: str, skip: int = Query(0, ge=0), # Convert the query results to a list of dictionaries prices = [{"product_id": row.product_id, "sku": row.sku, "location": row.location, - "region_code": row.region_code, "price": row.price, "unit": row.unit} for row in query] + "region_code": row.region_code, "price": row.price, "unit": row.unit, + "price_description": row.description} for row in query] return prices diff --git a/api/routers/products.py b/api/routers/products.py index 3e98d20..90d4833 100644 --- a/api/routers/products.py +++ b/api/routers/products.py @@ -1,6 +1,7 @@ from fastapi import APIRouter, Query from api.database import SessionLocal -from api.models import Product +from api.models import Product, Price +from api.utils.customHTTPException import CustomHTTPException router = APIRouter() @@ -12,3 +13,48 @@ async def get_products(service_code: str, skip: int = Query(0, ge=0), limit: int with SessionLocal() as db: products = db.query(Product).filter(Product.service_code == service_code).offset(skip).limit(limit).all() return products + + +# Route to get all products of a particular product attribute value +@router.get("/products/") +def get_products_by_attribute( + attribute_name: str = Query(default="", description="Name of the product attribute"), + attribute_value: str = Query(default="", description="Value of the product attribute"), + include_prices: bool = Query(default=False, description="Include prices in the response"), +): + if not attribute_name or not attribute_value: + raise CustomHTTPException(status_code=400, detail="Missing query parameters") + else: + if include_prices: + with SessionLocal() as db: + + product_prices = db.query(Product.id.label("product_id"), Product.product_family_id.label("product_family_id"), + Product.service_code.label("service_code"), Product.sku.label("sku"), + Product.location.label("location"), Product.region_code.label("region_code"), + Price.pricePerUnit.label("price"), Price.unit.label("unit"), + Price.description.label("description")).\ + join(Price, Product.id == Price.product_id).\ + filter(Product.product_attributes[attribute_name] == attribute_value).all() + + # Check if any products match the condition + if not product_prices: + raise CustomHTTPException(status_code=404, detail="No products found with the specified condition") + + product_prices_result = [{"product_id": row.product_id, "product_family_id": row.product_family_id, + "sku": row.sku, "location": row.location, "service_code": row.service_code, + "region_code": row.region_code, "price": row.price, "unit": row.unit, + "price_description": row.description} for row in product_prices] + + return product_prices_result + else: + with SessionLocal() as db: + + products = db.query(Product).filter(Product.product_attributes[attribute_name] == attribute_value).all() + + # Check if any products match the condition + if not products: + raise CustomHTTPException(status_code=404, detail="No products found with the specified condition") + + product_list = [product.__dict__ for product in products] + + return product_list diff --git a/api/utils/__init__.py b/api/utils/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/api/utils/customHTTPException.py b/api/utils/customHTTPException.py new file mode 100644 index 0000000..145f422 --- /dev/null +++ b/api/utils/customHTTPException.py @@ -0,0 +1,6 @@ +from fastapi import HTTPException + + +class CustomHTTPException(HTTPException): + def __init__(self, status_code: int, detail: str): + super().__init__(status_code=status_code, detail=detail) diff --git a/load-data/main.py b/load-data/main.py index 2cb2d81..bfd0c09 100644 --- a/load-data/main.py +++ b/load-data/main.py @@ -25,7 +25,7 @@ # Function to create the database and tables def create_database_and_tables(cursor): - # Create the 'my_database' database if it doesn't exist + # Create the 'aws_database' database if it doesn't exist cursor.execute("CREATE DATABASE IF NOT EXISTS aws_database") cursor.execute("USE aws_database") @@ -98,12 +98,12 @@ def process_offer(offer_name, offer_details, cursor): product_family_id = cursor.lastrowid product_family_ids[product_family_name] = product_family_id - # Example: Insert data into the 'product' table + # Insert data into the 'product' table cursor.execute(""" INSERT INTO product (product_family_id, sku, service_code, location, region_code, product_attributes) VALUES (%s, %s, %s, %s, %s, %s) """, ( - product_family_id, # Use product family ID + product_family_id, product_details.get('sku', ''), product_details.get('attributes', {}).get('servicecode', ''), product_details.get('attributes', {}).get('location', product_details.get('attributes', {}).get('fromLocation', '')), @@ -113,7 +113,7 @@ def process_offer(offer_name, offer_details, cursor): last_added_product_id = cursor.lastrowid - # Example: Insert data into the 'price' table + # Insert data into the 'price' table term_details = offer_data.get('terms', {}).get('OnDemand', {}).get(product_sku, {}) price_dimensions = term_details.get(list(term_details.keys())[0], {}).get('priceDimensions', {}) price_info = price_dimensions.get(list(price_dimensions.keys())[0], {})