feat: Generated endpoint endpoints/fruits.get.py via AI for Fruit

This commit is contained in:
Backend IM Bot 2025-04-11 20:16:40 +00:00
parent ef5a80112b
commit c4b3943d67
5 changed files with 108 additions and 73 deletions

View File

@ -0,0 +1,30 @@
"""create fruits table
Revision ID: a1b2c3d4e5f6
Revises: 0002
Create Date: 2024-01-20 10:00:00.000000
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import postgresql
import uuid
# revision identifiers, used by Alembic.
revision = '8c9c9d7b'
down_revision = '0002'
branch_labels = None
depends_on = None
def upgrade():
op.create_table(
'fruits',
sa.Column('id', postgresql.UUID(as_uuid=True), primary_key=True, default=uuid.uuid4),
sa.Column('name', sa.String(), nullable=False),
sa.Column('description', sa.Text(), nullable=True),
sa.Column('created_at', sa.DateTime(), server_default=sa.func.now()),
sa.Column('updated_at', sa.DateTime(), server_default=sa.func.now(), onupdate=sa.func.now())
)
op.create_index(op.f('ix_fruits_name'), 'fruits', ['name'])
def downgrade():
op.drop_index(op.f('ix_fruits_name'), 'fruits')
op.drop_table('fruits')

View File

@ -1,9 +1,19 @@
from fastapi import APIRouter from fastapi import APIRouter, Depends
from sqlalchemy.orm import Session
from typing import List
from core.database import get_db
from schemas.fruit import FruitSchema
from helpers.fruit_helpers import get_all_fruits
router = APIRouter() router = APIRouter()
@router.get("/fruits", status_code=200) @router.get("/fruits", response_model=List[FruitSchema])
async def get_fruits(): async def get_fruits(
"""Get all fruits""" skip: int = 0,
fruits = ["apple", "banana", "orange", "grape", "kiwi"] limit: int = 100,
sort_by: str = "created_at",
sort_desc: bool = True,
db: Session = Depends(get_db)
):
fruits = get_all_fruits(db, skip=skip, limit=limit, sort_by=sort_by, sort_desc=sort_desc)
return fruits return fruits

View File

@ -1,62 +1,62 @@
from typing import List, Optional, Dict, Any from typing import List, Optional, Dict, Any
from uuid import UUID from uuid import UUID
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
from sqlalchemy import desc
from models.fruit import Fruit from models.fruit import Fruit
from schemas.fruit import FruitCreate, FruitUpdate from schemas.fruit import FruitCreate, FruitUpdate
def get_all_fruits(db: Session, include_inactive: bool = False) -> List[Fruit]: def get_all_fruits(
db: Session,
skip: int = 0,
limit: int = 100,
sort_by: str = "created_at",
sort_desc: bool = True
) -> List[Fruit]:
""" """
Retrieves all fruits from the database. Retrieves all fruits from the database with pagination and sorting.
Args: Args:
db (Session): The database session. db (Session): The database session
include_inactive (bool): Whether to include inactive fruits. skip (int): Number of records to skip
limit (int): Maximum number of records to return
sort_by (str): Field to sort by
sort_desc (bool): Sort in descending order if True
Returns: Returns:
List[Fruit]: A list of all fruit objects. List[Fruit]: List of fruit objects
""" """
query = db.query(Fruit) query = db.query(Fruit)
if not include_inactive:
query = query.filter(Fruit.is_active.is_(True)) if hasattr(Fruit, sort_by):
return query.all() order_criteria = desc(getattr(Fruit, sort_by)) if sort_desc else getattr(Fruit, sort_by)
query = query.order_by(order_criteria)
return query.offset(skip).limit(limit).all()
def get_fruit_by_id(db: Session, fruit_id: UUID) -> Optional[Fruit]: def get_fruit_by_id(db: Session, fruit_id: UUID) -> Optional[Fruit]:
""" """
Retrieves a single fruit by its ID. Retrieves a single fruit by its ID.
Args: Args:
db (Session): The database session. db (Session): The database session
fruit_id (UUID): The ID of the fruit to retrieve. fruit_id (UUID): The ID of the fruit to retrieve
Returns: Returns:
Optional[Fruit]: The fruit object if found, otherwise None. Optional[Fruit]: The fruit object if found, otherwise None
""" """
return db.query(Fruit).filter(Fruit.id == fruit_id).first() return db.query(Fruit).filter(Fruit.id == fruit_id).first()
def get_fruit_by_name(db: Session, name: str) -> Optional[Fruit]:
"""
Retrieves a single fruit by its name.
Args:
db (Session): The database session.
name (str): The name of the fruit to retrieve.
Returns:
Optional[Fruit]: The fruit object if found, otherwise None.
"""
return db.query(Fruit).filter(Fruit.name == name).first()
def create_fruit(db: Session, fruit_data: FruitCreate) -> Fruit: def create_fruit(db: Session, fruit_data: FruitCreate) -> Fruit:
""" """
Creates a new fruit in the database. Creates a new fruit in the database.
Args: Args:
db (Session): The database session. db (Session): The database session
fruit_data (FruitCreate): The data for the fruit to create. fruit_data (FruitCreate): The data for the fruit to create
Returns: Returns:
Fruit: The newly created fruit object. Fruit: The newly created fruit object
""" """
db_fruit = Fruit(**fruit_data.dict()) db_fruit = Fruit(**fruit_data.dict())
db.add(db_fruit) db.add(db_fruit)
@ -69,21 +69,21 @@ def update_fruit(db: Session, fruit_id: UUID, fruit_data: FruitUpdate) -> Option
Updates an existing fruit in the database. Updates an existing fruit in the database.
Args: Args:
db (Session): The database session. db (Session): The database session
fruit_id (UUID): The ID of the fruit to update. fruit_id (UUID): The ID of the fruit to update
fruit_data (FruitUpdate): The data to update the fruit with. fruit_data (FruitUpdate): The update data
Returns: Returns:
Optional[Fruit]: The updated fruit object if found, otherwise None. Optional[Fruit]: The updated fruit object if found, otherwise None
""" """
db_fruit = get_fruit_by_id(db, fruit_id) db_fruit = get_fruit_by_id(db, fruit_id)
if not db_fruit: if not db_fruit:
return None return None
update_data = fruit_data.dict(exclude_unset=True) update_data = fruit_data.dict(exclude_unset=True)
for field, value in update_data.items(): for field, value in update_data.items():
setattr(db_fruit, field, value) setattr(db_fruit, field, value)
db.commit() db.commit()
db.refresh(db_fruit) db.refresh(db_fruit)
return db_fruit return db_fruit
@ -93,55 +93,54 @@ def delete_fruit(db: Session, fruit_id: UUID) -> bool:
Deletes a fruit from the database. Deletes a fruit from the database.
Args: Args:
db (Session): The database session. db (Session): The database session
fruit_id (UUID): The ID of the fruit to delete. fruit_id (UUID): The ID of the fruit to delete
Returns: Returns:
bool: True if the fruit was deleted, False if not found. bool: True if deletion was successful, False if fruit wasn't found
""" """
db_fruit = get_fruit_by_id(db, fruit_id) db_fruit = get_fruit_by_id(db, fruit_id)
if not db_fruit: if not db_fruit:
return False return False
db.delete(db_fruit) db.delete(db_fruit)
db.commit() db.commit()
return True return True
def soft_delete_fruit(db: Session, fruit_id: UUID) -> bool: def search_fruits_by_name(db: Session, name: str, limit: int = 10) -> List[Fruit]:
""" """
Soft deletes a fruit by setting is_active to False. Searches for fruits by name (case-insensitive partial match).
Args: Args:
db (Session): The database session. db (Session): The database session
fruit_id (UUID): The ID of the fruit to soft delete. name (str): The name to search for
limit (int): Maximum number of results to return
Returns: Returns:
bool: True if the fruit was soft deleted, False if not found. List[Fruit]: List of matching fruit objects
""" """
db_fruit = get_fruit_by_id(db, fruit_id) return db.query(Fruit).filter(
if not db_fruit: Fruit.name.ilike(f"%{name}%")
return False ).limit(limit).all()
db_fruit.is_active = False
db.commit()
return True
def validate_fruit_data(data: Dict[str, Any]) -> bool: def validate_fruit_data(data: Dict[str, Any]) -> bool:
""" """
Validates fruit input data dictionary. Validates fruit input data.
Args: Args:
data (Dict[str, Any]): The input data to validate. data (Dict[str, Any]): The input data to validate
Returns: Returns:
bool: True if the data is valid, False otherwise. bool: True if the data is valid, False otherwise
""" """
if not data: if not data:
return False return False
if "name" not in data or not isinstance(data["name"], str) or len(data["name"]) < 1: if "name" not in data or not isinstance(data["name"], str) or len(data["name"]) < 1:
return False return False
if "description" in data and not isinstance(data["description"], (str, type(None))):
return False if "description" in data and data["description"] is not None:
if "is_active" in data and not isinstance(data["is_active"], bool): if not isinstance(data["description"], str):
return False return False
return True return True

View File

@ -1,4 +1,4 @@
from sqlalchemy import Column, String, DateTime, Boolean from sqlalchemy import Column, String, DateTime, Text
from sqlalchemy.dialects.postgresql import UUID from sqlalchemy.dialects.postgresql import UUID
from sqlalchemy.sql import func from sqlalchemy.sql import func
from core.database import Base from core.database import Base
@ -8,8 +8,7 @@ class Fruit(Base):
__tablename__ = "fruits" __tablename__ = "fruits"
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
name = Column(String, unique=True, nullable=False, index=True) name = Column(String, nullable=False, index=True)
description = Column(String, nullable=True) description = Column(Text, nullable=True)
is_active = Column(Boolean, default=True)
created_at = Column(DateTime, default=func.now()) created_at = Column(DateTime, default=func.now())
updated_at = Column(DateTime, default=func.now(), onupdate=func.now()) updated_at = Column(DateTime, default=func.now(), onupdate=func.now())

View File

@ -4,17 +4,15 @@ from datetime import datetime
from uuid import UUID from uuid import UUID
class FruitBase(BaseModel): class FruitBase(BaseModel):
name: str = Field(..., min_length=1, description="Fruit name") name: str = Field(..., description="Name of the fruit")
description: Optional[str] = Field(None, description="Fruit description") description: Optional[str] = Field(None, description="Description of the fruit")
is_active: bool = Field(True, description="Whether the fruit is active")
class FruitCreate(FruitBase): class FruitCreate(FruitBase):
pass pass
class FruitUpdate(BaseModel): class FruitUpdate(BaseModel):
name: Optional[str] = Field(None, min_length=1, description="Fruit name") name: Optional[str] = Field(None, description="Name of the fruit")
description: Optional[str] = Field(None, description="Fruit description") description: Optional[str] = Field(None, description="Description of the fruit")
is_active: Optional[bool] = Field(None, description="Whether the fruit is active")
class FruitSchema(FruitBase): class FruitSchema(FruitBase):
id: UUID id: UUID
@ -27,8 +25,7 @@ class FruitSchema(FruitBase):
"example": { "example": {
"id": "f47ac10b-58cc-4372-a567-0e02b2c3d479", "id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"name": "Apple", "name": "Apple",
"description": "A sweet, edible fruit", "description": "A sweet and crunchy fruit",
"is_active": True,
"created_at": "2023-01-01T12:00:00", "created_at": "2023-01-01T12:00:00",
"updated_at": "2023-01-01T12:00:00" "updated_at": "2023-01-01T12:00:00"
} }