Spaces:
Paused
Paused
File size: 5,538 Bytes
b79b0dc 8730c05 b79b0dc 21ab478 b79b0dc 21ab478 b79b0dc 5fa5dc7 b79b0dc b40f73e b79b0dc 5fa5dc7 8730c05 b79b0dc 8730c05 5fa5dc7 02a6b87 5fa5dc7 1326afb 4f4cfa4 1326afb 9d20b05 1326afb 9d20b05 1326afb 4f4cfa4 1326afb 5fa5dc7 4bd3006 5fa5dc7 4bd3006 5fa5dc7 b79b0dc ea1b45f 5fa5dc7 ea1b45f 5fa5dc7 b79b0dc 5fa5dc7 b79b0dc 5fa5dc7 f8eac62 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 | 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"])
@router.get("/", response_model=PaginatedResponse[ProjectOut])
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
)
@router.get("/{project_no}", response_model=ProjectDetailNoCustomersOut)
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)
@router.get(
"/{project_no}/customers",
response_model=List[ProjectCustomerOut],
response_model_exclude={"barrier_sizes", "contacts", "bidder_notes"}
)
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)
@router.get(
"/{project_no}/customers/{customer_id}",
response_model=ProjectCustomerOut,
response_model_exclude={"barrier_sizes", "contacts", "bidder_notes"}
)
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)
@router.post("/", response_model=ProjectOut, status_code=status.HTTP_201_CREATED)
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())
@router.put("/{project_no}", response_model=ProjectOut)
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())
@router.delete("/{project_no}", status_code=status.HTTP_204_NO_CONTENT)
def delete_project(project_no: int, db: Session = Depends(get_db)):
"""Delete a project"""
service = ProjectService(db)
service.delete(project_no)
return None
|