Spaces:
Paused
Paused
feat(project): remove heavy nested collections from project customer response for performance improvement
4f4cfa4 | from fastapi import APIRouter, Depends, status, Query | |
| from sqlalchemy.orm import Session | |
| from app.db.session import get_db | |
| from app.services.project_service import ProjectService | |
| from app.schemas.project import ProjectCreate, ProjectOut | |
| from app.schemas.project_detail import ProjectDetailOut, ProjectCustomerOut, ProjectDetailNoCustomersOut | |
| from app.schemas.paginated_response import PaginatedResponse | |
| from typing import List, Optional | |
| router = APIRouter(prefix="/api/v1/projects", tags=["projects"]) | |
| def list_projects( | |
| customer_type: Optional[int] = Query(0, description="Customer type filter (0 for all types)", ge=0), | |
| status: Optional[int] = Query(None, description="Status filter (None excludes status=3, pass specific value to include all)"), | |
| order_by: Optional[str] = Query("project_no", description="Field to order by"), | |
| order_direction: Optional[str] = Query("asc", description="Order direction: asc or desc", regex="^(asc|desc)$"), | |
| page: Optional[int] = Query(1, description="Page number (1-indexed)", ge=1), | |
| page_size: Optional[int] = Query(10, description="Number of records per page", ge=1, le=100), | |
| db: Session = Depends(get_db) | |
| ): | |
| """ | |
| Get paginated list of projects with filtering and sorting. | |
| - **customer_type**: Filter by customer type (0 = all types) | |
| - **status**: Filter by status (None = exclude status 3, pass specific value to include all) | |
| - **order_by**: Field name to sort by (project_no, project_name, etc.) | |
| - **order_direction**: Sort direction (asc or desc) | |
| - **page**: Page number starting from 1 | |
| - **page_size**: Number of records per page (max 100) | |
| """ | |
| service = ProjectService(db) | |
| return service.list_projects( | |
| customer_type=customer_type, | |
| status=status, | |
| order_by=order_by, | |
| order_direction=order_direction, | |
| page=page, | |
| page_size=page_size | |
| ) | |
| def get_project(project_no: int, db: Session = Depends(get_db)): | |
| """Get a specific project by ProjectNo without customers collection | |
| For customer data, use `/api/v1/projects/{project_no}/customers` instead. | |
| """ | |
| service = ProjectService(db) | |
| # Use lean method that does not fetch customers or notes for performance | |
| return service.get_detail_no_customers(project_no) | |
| def get_project_customers( | |
| project_no: int, | |
| page: Optional[int] = Query(1, description="Page number (1-indexed)", ge=1), | |
| page_size: Optional[int] = Query(25, description="Number of records per page", ge=1, le=1000), | |
| last_id: Optional[int] = Query(None, description="Keyset pagination anchor: last seen bidder Id"), | |
| db: Session = Depends(get_db) | |
| ): | |
| """Get customers associated with a specific project (by ProjectNo) | |
| Returns a paginated list of customers for the project. Pagination defaults | |
| to page=1 and page_size=100 to avoid very large responses. | |
| """ | |
| service = ProjectService(db) | |
| # Use the dedicated service method to fetch only customers for the project | |
| return service.get_customers(project_no, page=page, page_size=page_size, last_id=last_id) | |
| def get_project_customer_detail( | |
| project_no: int, | |
| customer_id: str, | |
| db: Session = Depends(get_db) | |
| ): | |
| """Get detailed bidder information for a specific customer on a project | |
| Returns the complete bidder details including barrier sizes, contacts, and notes | |
| for the specified project number and customer ID combination. | |
| - **project_no**: The project number | |
| - **customer_id**: The customer ID (CustId from Bidders table) | |
| """ | |
| service = ProjectService(db) | |
| return service.get_project_customer_detail(project_no, customer_id) | |
| def create_project(project_in: ProjectCreate, db: Session = Depends(get_db)): | |
| """ | |
| Create a new project using stored procedure | |
| Creates a new project record using the spProjectsInsert stored procedure. | |
| All project fields including billing, shipping, payment, and project details | |
| can be provided in the request body. | |
| Returns the created project with the generated ProjectNo. | |
| """ | |
| service = ProjectService(db) | |
| return service.create(project_in.model_dump()) | |
| def update_project(project_no: int, project_in: ProjectCreate, db: Session = Depends(get_db)): | |
| """ | |
| Update an existing project using stored procedure | |
| Updates an existing project record using the spProjectsUpdate stored procedure. | |
| All project fields including billing, shipping, payment, and project details | |
| can be updated in the request body. | |
| Returns the updated project data. | |
| """ | |
| service = ProjectService(db) | |
| return service.update(project_no, project_in.model_dump()) | |
| def delete_project(project_no: int, db: Session = Depends(get_db)): | |
| """Delete a project""" | |
| service = ProjectService(db) | |
| service.delete(project_no) | |
| return None | |