diff --git a/endpoints/create-fruit.post.py b/endpoints/create-fruit.post.py index e69de29..191a70a 100644 --- a/endpoints/create-fruit.post.py +++ b/endpoints/create-fruit.post.py @@ -0,0 +1,30 @@ +from fastapi import APIRouter, HTTPException, status +from typing import Dict +from pydantic import BaseModel + +from helpers.fruit_helpers import add_fruit, validate_fruit_data + +router = APIRouter() + +class FruitCreate(BaseModel): + name: str + quantity: int + +@router.post("/create-fruit", status_code=status.HTTP_201_CREATED, response_model=Dict[str, any]) +async def create_fruit(fruit: FruitCreate): + """Create a new fruit entry""" + try: + if not validate_fruit_data(fruit.name, fruit.quantity): + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail="Invalid fruit data provided" + ) + + new_fruit = add_fruit(fruit.name, fruit.quantity) + return new_fruit + + except ValueError as e: + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail=str(e) + ) \ No newline at end of file diff --git a/helpers/generic_helpers.py b/helpers/generic_helpers.py new file mode 100644 index 0000000..8ada0d9 --- /dev/null +++ b/helpers/generic_helpers.py @@ -0,0 +1,115 @@ +from typing import Dict, List, Optional +from datetime import datetime + +# In-memory store for fruits since no model was provided +_fruits_store: List[Dict[str, any]] = [] + +def add_fruit(fruit_name: str, quantity: int) -> Dict[str, any]: + """ + Adds a fruit to the in-memory store with the given quantity. + + Args: + fruit_name (str): Name of the fruit to add + quantity (int): Quantity of the fruit + + Returns: + Dict[str, any]: The newly added fruit entry + """ + if not validate_fruit_data(fruit_name, quantity): + raise ValueError("Invalid fruit data provided") + + new_fruit = { + "name": fruit_name.lower(), + "quantity": quantity, + "added_at": datetime.now() + } + + # Check if fruit already exists + existing_fruit = get_fruit_by_name(fruit_name) + if existing_fruit: + existing_fruit["quantity"] += quantity + existing_fruit["updated_at"] = datetime.now() + return existing_fruit + + _fruits_store.append(new_fruit) + return new_fruit + +def get_fruit_by_name(fruit_name: str) -> Optional[Dict[str, any]]: + """ + Retrieves a fruit by its name from the in-memory store. + + Args: + fruit_name (str): Name of the fruit to retrieve + + Returns: + Optional[Dict[str, any]]: The fruit entry if found, None otherwise + """ + fruit_name = fruit_name.lower() + for fruit in _fruits_store: + if fruit["name"] == fruit_name: + return fruit + return None + +def get_all_fruits() -> List[Dict[str, any]]: + """ + Retrieves all fruits from the in-memory store. + + Returns: + List[Dict[str, any]]: List of all fruit entries + """ + return _fruits_store + +def update_fruit_quantity(fruit_name: str, new_quantity: int) -> Optional[Dict[str, any]]: + """ + Updates the quantity of a specific fruit. + + Args: + fruit_name (str): Name of the fruit to update + new_quantity (int): New quantity value + + Returns: + Optional[Dict[str, any]]: Updated fruit entry if found, None otherwise + """ + if not validate_fruit_data(fruit_name, new_quantity): + raise ValueError("Invalid fruit data provided") + + fruit = get_fruit_by_name(fruit_name) + if fruit: + fruit["quantity"] = new_quantity + fruit["updated_at"] = datetime.now() + return fruit + return None + +def delete_fruit(fruit_name: str) -> bool: + """ + Deletes a fruit from the in-memory store. + + Args: + fruit_name (str): Name of the fruit to delete + + Returns: + bool: True if fruit was deleted, False if not found + """ + fruit_name = fruit_name.lower() + for i, fruit in enumerate(_fruits_store): + if fruit["name"] == fruit_name: + _fruits_store.pop(i) + return True + return False + +def validate_fruit_data(fruit_name: str, quantity: int) -> bool: + """ + Validates fruit data before processing. + + Args: + fruit_name (str): Name of the fruit to validate + quantity (int): Quantity to validate + + Returns: + bool: True if data is valid, False otherwise + """ + if not fruit_name or not isinstance(fruit_name, str) or len(fruit_name.strip()) == 0: + return False + if not isinstance(quantity, int) or quantity < 0: + return False + return True \ No newline at end of file diff --git a/models/fruit.py b/models/fruit.py new file mode 100644 index 0000000..31eeaaa --- /dev/null +++ b/models/fruit.py @@ -0,0 +1,14 @@ +from sqlalchemy import Column, String, Integer, DateTime +from sqlalchemy.dialects.postgresql import UUID +from sqlalchemy.sql import func +from core.database import Base +import uuid + +class Fruit(Base): + __tablename__ = "fruits" + + id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) + name = Column(String, nullable=False, index=True) + quantity = Column(Integer, nullable=False, default=0) + created_at = Column(DateTime, default=func.now()) + updated_at = Column(DateTime, default=func.now(), onupdate=func.now()) \ No newline at end of file