diff --git a/alembic/versions/20250430_101955_cc017186_update_sale.py b/alembic/versions/20250430_101955_cc017186_update_sale.py new file mode 100644 index 0000000..7779687 --- /dev/null +++ b/alembic/versions/20250430_101955_cc017186_update_sale.py @@ -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') \ No newline at end of file diff --git a/endpoints/Sales.get.py b/endpoints/Sales.get.py index e69de29..00c6c30 100644 --- a/endpoints/Sales.get.py +++ b/endpoints/Sales.get.py @@ -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 \ No newline at end of file diff --git a/helpers/sale_helpers.py b/helpers/sale_helpers.py new file mode 100644 index 0000000..dc73d06 --- /dev/null +++ b/helpers/sale_helpers.py @@ -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 \ No newline at end of file diff --git a/models/sale.py b/models/sale.py new file mode 100644 index 0000000..c8826a6 --- /dev/null +++ b/models/sale.py @@ -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") \ No newline at end of file diff --git a/requirements.txt b/requirements.txt index 596e6f3..db12c92 100644 --- a/requirements.txt +++ b/requirements.txt @@ -7,3 +7,6 @@ sqlalchemy>=1.4.0 python-dotenv>=0.19.0 bcrypt>=3.2.0 alembic>=1.13.1 +jose +passlib +pydantic diff --git a/schemas/sale.py b/schemas/sale.py new file mode 100644 index 0000000..862675e --- /dev/null +++ b/schemas/sale.py @@ -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 \ No newline at end of file