feat: Implement Sales API with GET endpoint (auto-linted)

This commit is contained in:
Backend IM Bot 2025-04-30 10:20:22 +00:00
parent fb7c39f819
commit dacdeb7945
6 changed files with 189 additions and 0 deletions

View File

@ -0,0 +1,34 @@
"""create table for sales
Revision ID: 2f9d3b7c8a4a
Revises: 0001
Create Date: 2023-05-25 12:34:56
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy.sql import func
import uuid
# revision identifiers, used by Alembic.
revision = '2f9d3b7c8a4a'
down_revision = '0001'
branch_labels = None
depends_on = None
def upgrade():
op.create_table(
'sales',
sa.Column('id', sa.String(36), primary_key=True, default=lambda: str(uuid.uuid4())),
sa.Column('customer_id', sa.String(36), nullable=False),
sa.Column('product_id', sa.String(36), nullable=False),
sa.Column('quantity', sa.Integer(), nullable=False),
sa.Column('price', sa.Float(), nullable=False),
sa.Column('total_amount', sa.Float(), nullable=False),
sa.Column('created_at', sa.DateTime(), server_default=func.now()),
sa.Column('updated_at', sa.DateTime(), server_default=func.now(), onupdate=func.now()),
sa.ForeignKeyConstraint(['customer_id'], ['customers.id']),
sa.ForeignKeyConstraint(['product_id'], ['products.id'])
)
def downgrade():
op.drop_table('sales')

View File

@ -0,0 +1,13 @@
from fastapi import APIRouter, Depends
from sqlalchemy.orm import Session
from typing import List
from core.database import get_db
from schemas.sale import SaleSchema
from helpers.sale_helpers import get_all_sales
router = APIRouter()
@router.get("/Sales", status_code=200, response_model=List[SaleSchema])
async def get_sales(db: Session = Depends(get_db)):
sales = get_all_sales(db)
return sales

91
helpers/sale_helpers.py Normal file
View File

@ -0,0 +1,91 @@
import uuid
from typing import List, Optional
from sqlalchemy.orm import Session
from models.sale import Sale
from schemas.sale import SaleCreate, SaleUpdate
def get_all_sales(db: Session) -> List[Sale]:
"""
Retrieves all sales from the database.
Args:
db (Session): The database session.
Returns:
List[Sale]: A list of all sale objects.
"""
return db.query(Sale).all()
def get_sale_by_id(db: Session, sale_id: uuid.UUID) -> Optional[Sale]:
"""
Retrieves a single sale by its ID.
Args:
db (Session): The database session.
sale_id (UUID): The ID of the sale to retrieve.
Returns:
Optional[Sale]: The sale object if found, otherwise None.
"""
return db.query(Sale).filter(Sale.id == sale_id).first()
def create_sale(db: Session, sale_data: SaleCreate) -> Sale:
"""
Creates a new sale in the database.
Args:
db (Session): The database session.
sale_data (SaleCreate): The data for the sale to create.
Returns:
Sale: The newly created sale object.
"""
db_sale = Sale(**sale_data.dict())
db.add(db_sale)
db.commit()
db.refresh(db_sale)
return db_sale
def update_sale(db: Session, sale_id: uuid.UUID, sale_data: SaleUpdate) -> Optional[Sale]:
"""
Updates an existing sale in the database.
Args:
db (Session): The database session.
sale_id (UUID): The ID of the sale to update.
sale_data (SaleUpdate): The updated data for the sale.
Returns:
Optional[Sale]: The updated sale object if found, otherwise None.
"""
db_sale = db.query(Sale).filter(Sale.id == sale_id).first()
if not db_sale:
return None
update_data = sale_data.dict(exclude_unset=True)
for key, value in update_data.items():
setattr(db_sale, key, value)
db.add(db_sale)
db.commit()
db.refresh(db_sale)
return db_sale
def delete_sale(db: Session, sale_id: uuid.UUID) -> bool:
"""
Deletes a sale from the database.
Args:
db (Session): The database session.
sale_id (UUID): The ID of the sale to delete.
Returns:
bool: True if the sale was deleted, False otherwise.
"""
db_sale = db.query(Sale).filter(Sale.id == sale_id).first()
if not db_sale:
return False
db.delete(db_sale)
db.commit()
return True

21
models/sale.py Normal file
View File

@ -0,0 +1,21 @@
from sqlalchemy import Column, Integer, Float, DateTime, ForeignKey
from sqlalchemy.dialects.postgresql import UUID
from sqlalchemy.orm import relationship
from sqlalchemy.sql import func
from core.database import Base
import uuid
class Sale(Base):
__tablename__ = "sales"
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
customer_id = Column(UUID(as_uuid=True), ForeignKey("customers.id"), nullable=False)
product_id = Column(UUID(as_uuid=True), ForeignKey("products.id"), nullable=False)
quantity = Column(Integer, nullable=False)
price = Column(Float, nullable=False)
total_amount = Column(Float, nullable=False)
created_at = Column(DateTime, default=func.now())
updated_at = Column(DateTime, default=func.now(), onupdate=func.now())
customer = relationship("Customer", back_populates="sales")
product = relationship("Product", back_populates="sales")

View File

@ -7,3 +7,6 @@ sqlalchemy>=1.4.0
python-dotenv>=0.19.0
bcrypt>=3.2.0
alembic>=1.13.1
jose
passlib
pydantic

27
schemas/sale.py Normal file
View File

@ -0,0 +1,27 @@
from pydantic import BaseModel, Field
from typing import Optional
from datetime import datetime
from uuid import UUID
class SaleBase(BaseModel):
customer_id: UUID = Field(..., description="The ID of the customer")
product_id: UUID = Field(..., description="The ID of the product")
quantity: int = Field(..., gt=0, description="The quantity of the product sold")
price: float = Field(..., gt=0, description="The price of the product")
total_amount: float = Field(..., gt=0, description="The total amount of the sale")
class SaleCreate(SaleBase):
pass
class SaleUpdate(SaleBase):
quantity: Optional[int] = Field(None, gt=0, description="The quantity of the product sold")
price: Optional[float] = Field(None, gt=0, description="The price of the product")
total_amount: Optional[float] = Field(None, gt=0, description="The total amount of the sale")
class SaleSchema(SaleBase):
id: UUID
created_at: datetime
updated_at: datetime
class Config:
orm_mode = True