feat: Implement Sales API with GET endpoint ✅ (auto-linted)
This commit is contained in:
parent
fb7c39f819
commit
dacdeb7945
34
alembic/versions/20250430_101955_cc017186_update_sale.py
Normal file
34
alembic/versions/20250430_101955_cc017186_update_sale.py
Normal 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')
|
@ -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
91
helpers/sale_helpers.py
Normal 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
21
models/sale.py
Normal 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")
|
@ -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
27
schemas/sale.py
Normal 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
|
Loading…
x
Reference in New Issue
Block a user