feat: Generated endpoint endpoints/create-grocery.post.py via AI for Grocery

This commit is contained in:
Backend IM Bot 2025-04-13 22:18:24 +00:00
parent d6e27213e3
commit 77a788f8ec
5 changed files with 182 additions and 0 deletions

View File

@ -0,0 +1,27 @@
"""create groceries table
Revision ID: b8c2316d
Revises: a7b1205a
Create Date: 2024-01-23 10:30:00.000000
"""
from alembic import op
import sqlalchemy as sa
# revision identifiers, used by Alembic.
revision = 'b8c2316d'
down_revision = 'a7b1205a'
branch_labels = None
depends_on = None
def upgrade():
op.create_table(
'groceries',
sa.Column('id', sa.String(36), primary_key=True),
sa.Column('name', sa.String(), nullable=False),
sa.Column('created_at', sa.DateTime(), server_default=sa.func.now()),
sa.Column('updated_at', sa.DateTime(), server_default=sa.func.now()),
)
op.create_index(op.f('ix_groceries_name'), 'groceries', ['name'], unique=False)
def downgrade():
op.drop_index(op.f('ix_groceries_name'), table_name='groceries')
op.drop_table('groceries')

View File

@ -0,0 +1,38 @@
from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy.orm import Session
from core.database import get_db
from schemas.grocery import GroceryCreate, GrocerySchema
from helpers.grocery_helpers import create_grocery, get_grocery_by_name, validate_grocery_name, normalize_grocery_name
router = APIRouter()
@router.post("/create-grocery", response_model=GrocerySchema, status_code=status.HTTP_201_CREATED)
async def create_grocery_item(
grocery: GroceryCreate,
db: Session = Depends(get_db)
):
if not validate_grocery_name(grocery.name):
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Invalid grocery name"
)
normalized_name = normalize_grocery_name(grocery.name)
existing_grocery = get_grocery_by_name(db, normalized_name)
if existing_grocery:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Grocery with this name already exists"
)
grocery_data = GroceryCreate(name=normalized_name)
new_grocery = create_grocery(db, grocery_data)
if not new_grocery:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Failed to create grocery"
)
return new_grocery

View File

@ -0,0 +1,75 @@
from typing import Optional
from sqlalchemy.orm import Session
from sqlalchemy.exc import IntegrityError
from models.grocery import Grocery
from schemas.grocery import GroceryCreate
def create_grocery(db: Session, grocery_data: GroceryCreate) -> Optional[Grocery]:
"""
Creates a new grocery item in the database.
Args:
db (Session): The database session
grocery_data (GroceryCreate): The data for the grocery item to create
Returns:
Optional[Grocery]: The newly created grocery object, or None if creation failed
"""
try:
db_grocery = Grocery(**grocery_data.dict())
db.add(db_grocery)
db.commit()
db.refresh(db_grocery)
return db_grocery
except IntegrityError:
db.rollback()
return None
def get_grocery_by_name(db: Session, name: str) -> Optional[Grocery]:
"""
Retrieves a grocery item by its name.
Args:
db (Session): The database session
name (str): The name of the grocery item to retrieve
Returns:
Optional[Grocery]: The grocery object if found, otherwise None
"""
return db.query(Grocery).filter(Grocery.name == name).first()
def validate_grocery_name(name: str) -> bool:
"""
Validates the grocery name according to business rules.
Args:
name (str): The name to validate
Returns:
bool: True if the name is valid, False otherwise
"""
if not name or not isinstance(name, str):
return False
# Remove leading/trailing whitespace and check length
name = name.strip()
if len(name) < 1:
return False
# Additional validation rules could be added here
return True
def normalize_grocery_name(name: str) -> str:
"""
Normalizes a grocery name for consistency in storage.
Args:
name (str): The name to normalize
Returns:
str: The normalized name
"""
# Remove extra whitespace and capitalize first letter
normalized = " ".join(name.split())
return normalized.strip().capitalize()

13
models/grocery.py Normal file
View File

@ -0,0 +1,13 @@
from sqlalchemy import Column, String, DateTime
from sqlalchemy.dialects.postgresql import UUID
from sqlalchemy.sql import func
from core.database import Base
import uuid
class Grocery(Base):
__tablename__ = "groceries"
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
name = Column(String, nullable=False, index=True)
created_at = Column(DateTime, default=func.now())
updated_at = Column(DateTime, default=func.now(), onupdate=func.now())

29
schemas/grocery.py Normal file
View File

@ -0,0 +1,29 @@
from pydantic import BaseModel, Field
from typing import Optional
from datetime import datetime
from uuid import UUID
class GroceryBase(BaseModel):
name: str = Field(..., min_length=1, description="Name of the grocery item")
class GroceryCreate(GroceryBase):
pass
class GroceryUpdate(BaseModel):
name: Optional[str] = Field(None, min_length=1, description="Name of the grocery item")
class GrocerySchema(GroceryBase):
id: UUID
created_at: datetime
updated_at: datetime
class Config:
orm_mode = True
schema_extra = {
"example": {
"id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"name": "Milk",
"created_at": "2023-01-01T12:00:00",
"updated_at": "2023-01-01T12:00:00"
}
}