"""Pydantic schemas for Project, SubProject, ProjectFunctionGroup, ProjectFunction.""" from datetime import datetime from pydantic import BaseModel, Field # ===== Project Schemas ===== class ProjectCreateRequest(BaseModel): """Request body for creating a new project.""" name: str = Field(..., max_length=255) description: str | None = None status: str = Field("draft", max_length=20) start_date: datetime | None = None end_date: datetime | None = None budget: float | None = None total_costs: float = 0.0 notes: str | None = None custom_fields: str | None = None custom_field_defs: str | None = None class ProjectUpdateRequest(BaseModel): """Request body for updating an existing project.""" name: str | None = Field(None, max_length=255) description: str | None = None status: str | None = Field(None, max_length=20) start_date: datetime | None = None end_date: datetime | None = None budget: float | None = None total_costs: float | None = None notes: str | None = None custom_fields: str | None = None custom_field_defs: str | None = None class ProjectResponse(BaseModel): """Public project representation.""" id: str account_id: str name: str description: str | None = None status: str start_date: datetime | None = None end_date: datetime | None = None budget: float | None = None total_costs: float = 0.0 notes: str | None = None custom_fields: str | None = None custom_field_defs: str | None = None created_at: datetime updated_at: datetime model_config = {"from_attributes": True} class ProjectListResponse(BaseModel): """Paginated list of projects.""" items: list[ProjectResponse] total: int page: int size: int # ===== SubProject Schemas ===== class SubProjectCreateRequest(BaseModel): """Request body for creating a subproject.""" name: str = Field(..., max_length=255) parent_id: str | None = None sort_order: int = 0 class SubProjectUpdateRequest(BaseModel): """Request body for updating a subproject.""" name: str | None = Field(None, max_length=255) parent_id: str | None = None sort_order: int | None = None class SubProjectResponse(BaseModel): """Public subproject representation.""" id: str name: str project_id: str parent_id: str | None = None sort_order: int = 0 model_config = {"from_attributes": True} class SubProjectListResponse(BaseModel): """Paginated list of subprojects.""" items: list[SubProjectResponse] total: int page: int size: int # ===== ProjectFunctionGroup Schemas ===== class ProjectFunctionGroupCreateRequest(BaseModel): """Request body for creating a function group.""" name: str = Field(..., max_length=255) sort_order: int = 0 start_date: datetime | None = None end_date: datetime | None = None class ProjectFunctionGroupUpdateRequest(BaseModel): """Request body for updating a function group.""" name: str | None = Field(None, max_length=255) sort_order: int | None = None start_date: datetime | None = None end_date: datetime | None = None class ProjectFunctionGroupResponse(BaseModel): """Public function group representation.""" id: str name: str project_id: str sort_order: int = 0 start_date: datetime | None = None end_date: datetime | None = None model_config = {"from_attributes": True} class ProjectFunctionGroupListResponse(BaseModel): """Paginated list of function groups.""" items: list[ProjectFunctionGroupResponse] total: int page: int size: int # ===== ProjectFunction Schemas ===== class ProjectFunctionCreateRequest(BaseModel): """Request body for creating a project function.""" name: str = Field(..., max_length=255) function_type: str = "crew" quantity: float = 1.0 daily_costs: float = 0.0 total_costs: float = 0.0 sort_order: int = 0 class ProjectFunctionUpdateRequest(BaseModel): """Request body for updating a project function.""" name: str | None = Field(None, max_length=255) function_type: str | None = None quantity: float | None = None daily_costs: float | None = None total_costs: float | None = None sort_order: int | None = None class ProjectFunctionResponse(BaseModel): """Public project function representation.""" id: str name: str function_group_id: str function_type: str = "crew" quantity: float = 1.0 daily_costs: float = 0.0 total_costs: float = 0.0 sort_order: int = 0 model_config = {"from_attributes": True} class ProjectFunctionListResponse(BaseModel): """Paginated list of project functions.""" items: list[ProjectFunctionResponse] total: int page: int size: int # ===== ProjectEquipmentGroup Schemas ===== class ProjectEquipmentGroupCreateRequest(BaseModel): """Request body for creating an equipment group.""" name: str = Field(..., max_length=255) sort_order: int = 0 start_date: datetime | None = None end_date: datetime | None = None class ProjectEquipmentGroupUpdateRequest(BaseModel): """Request body for updating an equipment group.""" name: str | None = Field(None, max_length=255) sort_order: int | None = None start_date: datetime | None = None end_date: datetime | None = None class ProjectEquipmentGroupResponse(BaseModel): """Public equipment group representation.""" id: str name: str project_id: str sort_order: int = 0 start_date: datetime | None = None end_date: datetime | None = None model_config = {"from_attributes": True} class ProjectEquipmentGroupListResponse(BaseModel): """Paginated list of equipment groups.""" items: list[ProjectEquipmentGroupResponse] total: int page: int size: int class ProjectEquipmentGroupDetailResponse(BaseModel): """Equipment group with nested items.""" id: str name: str project_id: str sort_order: int = 0 start_date: datetime | None = None end_date: datetime | None = None items: list["ProjectEquipmentResponse"] = [] model_config = {"from_attributes": True} # ===== ProjectEquipment Schemas ===== class ProjectEquipmentCreateRequest(BaseModel): """Request body for adding equipment to a project group.""" equipment_id: str | None = None name: str = Field(..., max_length=255) quantity: float = 1.0 price: float = 0.0 discount: float = 0.0 sort_order: int = 0 class ProjectEquipmentUpdateRequest(BaseModel): """Request body for updating project equipment.""" equipment_id: str | None = None name: str | None = Field(None, max_length=255) quantity: float | None = None price: float | None = None discount: float | None = None sort_order: int | None = None class ProjectEquipmentResponse(BaseModel): """Public project equipment representation.""" id: str project_equipment_group_id: str equipment_id: str | None = None name: str quantity: float = 1.0 price: float = 0.0 discount: float = 0.0 sort_order: int = 0 model_config = {"from_attributes": True} class ProjectEquipmentListResponse(BaseModel): """Paginated list of project equipment.""" items: list[ProjectEquipmentResponse] total: int page: int size: int