From ef424196f9d08ccaa80d7171ccd173ccd9bd2c5c Mon Sep 17 00:00:00 2001 From: Backend IM Bot Date: Mon, 5 May 2025 18:00:53 +0000 Subject: [PATCH] feat: add logistics api endpoint and related models, schemas, and migrations --- ...250505_180024_37ad2850_update_logistics.py | 33 +++++ endpoints/Logisticsapp.get.py | 13 ++ helpers/logistics_helpers.py | 136 ++++++++++++++++++ models/logistics.py | 15 ++ schemas/logistics.py | 25 ++++ 5 files changed, 222 insertions(+) create mode 100644 alembic/versions/20250505_180024_37ad2850_update_logistics.py create mode 100644 helpers/logistics_helpers.py create mode 100644 models/logistics.py create mode 100644 schemas/logistics.py diff --git a/alembic/versions/20250505_180024_37ad2850_update_logistics.py b/alembic/versions/20250505_180024_37ad2850_update_logistics.py new file mode 100644 index 0000000..bb3a779 --- /dev/null +++ b/alembic/versions/20250505_180024_37ad2850_update_logistics.py @@ -0,0 +1,33 @@ +"""create table for logistics +Revision ID: 1d4f21e8c5f9 +Revises: 2f9d3b7c8a4a +Create Date: 2023-05-23 12:34:56 + +""" +from alembic import op +import sqlalchemy as sa +from sqlalchemy.sql import func +import uuid + +# revision identifiers, used by Alembic. +revision = '1d4f21e8c5f9' +down_revision = '2f9d3b7c8a4a' +branch_labels = None +depends_on = None + +def upgrade(): + table_name = "logistics" + + op.create_table( + table_name, + sa.Column('id', sa.String(36), primary_key=True, default=lambda: str(uuid.uuid4())), + sa.Column('name', sa.String(), nullable=False), + sa.Column('description', sa.String(), nullable=True), + sa.Column('details', sa.Text(), nullable=True), + sa.Column('created_at', sa.DateTime(), server_default=func.now()), + sa.Column('updated_at', sa.DateTime(), server_default=func.now(), onupdate=func.now()) + ) + +def downgrade(): + table_name = "logistics" + op.drop_table(table_name) \ No newline at end of file diff --git a/endpoints/Logisticsapp.get.py b/endpoints/Logisticsapp.get.py index e69de29..03485bc 100644 --- a/endpoints/Logisticsapp.get.py +++ b/endpoints/Logisticsapp.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.logistics import LogisticsSchema +from helpers.logistics_helpers import get_all_logistics + +router = APIRouter() + +@router.get("/Logisticsapp", status_code=200, response_model=List[LogisticsSchema]) +async def get_logistics(db: Session = Depends(get_db)): + logistics_list = get_all_logistics(db) + return logistics_list \ No newline at end of file diff --git a/helpers/logistics_helpers.py b/helpers/logistics_helpers.py new file mode 100644 index 0000000..f9029c2 --- /dev/null +++ b/helpers/logistics_helpers.py @@ -0,0 +1,136 @@ +from typing import List, Optional, Dict, Any +from uuid import UUID +from sqlalchemy.orm import Session +from models.logistics import Logistics +from schemas.logistics import LogisticsCreate, LogisticsUpdate, LogisticsSchema + +def get_all_logistics(db: Session) -> List[LogisticsSchema]: + """ + Retrieves all logistics from the database. + + Args: + db (Session): The database session. + + Returns: + List[LogisticsSchema]: A list of all logistics schemas. + """ + logistics = db.query(Logistics).all() + return [LogisticsSchema.from_orm(logistics_obj) for logistics_obj in logistics] + +def get_logistics_by_id(db: Session, logistics_id: UUID) -> Optional[LogisticsSchema]: + """ + Retrieves a single logistics by its ID. + + Args: + db (Session): The database session. + logistics_id (UUID): The ID of the logistics to retrieve. + + Returns: + Optional[LogisticsSchema]: The logistics schema if found, otherwise None. + """ + logistics = db.query(Logistics).filter(Logistics.id == logistics_id).first() + if logistics: + return LogisticsSchema.from_orm(logistics) + else: + return None + +def create_logistics(db: Session, logistics_data: LogisticsCreate) -> LogisticsSchema: + """ + Creates a new logistics in the database. + + Args: + db (Session): The database session. + logistics_data (LogisticsCreate): The data for the logistics to create. + + Returns: + LogisticsSchema: The newly created logistics schema. + """ + db_logistics = Logistics(**logistics_data.dict()) + db.add(db_logistics) + db.commit() + db.refresh(db_logistics) + return LogisticsSchema.from_orm(db_logistics) + +def update_logistics(db: Session, logistics_id: UUID, logistics_data: LogisticsUpdate) -> Optional[LogisticsSchema]: + """ + Updates an existing logistics in the database. + + Args: + db (Session): The database session. + logistics_id (UUID): The ID of the logistics to update. + logistics_data (LogisticsUpdate): The updated data for the logistics. + + Returns: + Optional[LogisticsSchema]: The updated logistics schema if found, otherwise None. + """ + logistics = db.query(Logistics).filter(Logistics.id == logistics_id).first() + if logistics: + update_data = logistics_data.dict(exclude_unset=True) + for key, value in update_data.items(): + setattr(logistics, key, value) + db.commit() + db.refresh(logistics) + return LogisticsSchema.from_orm(logistics) + else: + return None + +def delete_logistics(db: Session, logistics_id: UUID) -> bool: + """ + Deletes a logistics from the database. + + Args: + db (Session): The database session. + logistics_id (UUID): The ID of the logistics to delete. + + Returns: + bool: True if the logistics was deleted, False otherwise. + """ + logistics = db.query(Logistics).filter(Logistics.id == logistics_id).first() + if logistics: + db.delete(logistics) + db.commit() + return True + else: + return False + +def validate_logistics_data(logistics_data: Dict[str, Any]) -> bool: + """ + Validates input logistics data dictionary. + + Args: + logistics_data (Dict[str, Any]): The input logistics data to validate. + + Returns: + bool: True if the data is valid, False otherwise. + """ + if not logistics_data: + return False + if "name" not in logistics_data or not isinstance(logistics_data["name"], str) or len(logistics_data["name"]) < 3: + return False + # Add more validation rules as needed + return True + +def generate_logistics_report(logistics_data: List[LogisticsSchema]) -> Dict[str, Any]: + """ + Generates a report based on the provided logistics data. + + Args: + logistics_data (List[LogisticsSchema]): The logistics data to generate the report from. + + Returns: + Dict[str, Any]: The generated logistics report. + """ + report = { + "total_logistics": len(logistics_data), + "logistics_by_creation_date": {} + } + for logistics in logistics_data: + creation_date = logistics.created_at.date() + if creation_date not in report["logistics_by_creation_date"]: + report["logistics_by_creation_date"][creation_date] = [] + report["logistics_by_creation_date"][creation_date].append({ + "id": logistics.id, + "name": logistics.name, + "description": logistics.description + }) + return report \ No newline at end of file diff --git a/models/logistics.py b/models/logistics.py new file mode 100644 index 0000000..31b8da8 --- /dev/null +++ b/models/logistics.py @@ -0,0 +1,15 @@ +from sqlalchemy import Column, String, DateTime, JSON +from sqlalchemy.dialects.postgresql import UUID +from sqlalchemy.sql import func +from core.database import Base +import uuid + +class Logistics(Base): + __tablename__ = "logistics" + + id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4) + name = Column(String, nullable=False) + description = Column(String, nullable=True) + details = Column(JSON, nullable=True) + created_at = Column(DateTime, default=func.now()) + updated_at = Column(DateTime, default=func.now(), onupdate=func.now()) \ No newline at end of file diff --git a/schemas/logistics.py b/schemas/logistics.py new file mode 100644 index 0000000..042e28b --- /dev/null +++ b/schemas/logistics.py @@ -0,0 +1,25 @@ +from pydantic import BaseModel, Field +from typing import Optional +from datetime import datetime +from uuid import UUID + +class LogisticsBase(BaseModel): + name: str = Field(..., description="Name of the logistics") + description: Optional[str] = Field(None, description="Description of the logistics") + details: Optional[dict] = Field(None, description="Details of the logistics") + +class LogisticsCreate(LogisticsBase): + pass + +class LogisticsUpdate(LogisticsBase): + name: Optional[str] = Field(None, description="Name of the logistics") + description: Optional[str] = Field(None, description="Description of the logistics") + details: Optional[dict] = Field(None, description="Details of the logistics") + +class LogisticsSchema(LogisticsBase): + id: UUID + created_at: datetime + updated_at: datetime + + class Config: + orm_mode = True \ No newline at end of file