""" Pydantic Models and Schemas """ from pydantic import BaseModel, ConfigDict from typing import Optional, List from datetime import datetime class CustomerBase(BaseModel): """Base customer schema""" name: str email: Optional[str] = None phone: Optional[str] = None address: Optional[str] = None class CustomerCreate(CustomerBase): """Schema for creating a customer""" pass class CustomerUpdate(BaseModel): """Schema for updating a customer""" name: Optional[str] = None email: Optional[str] = None phone: Optional[str] = None address: Optional[str] = None cvr_number: Optional[str] = None city: Optional[str] = None postal_code: Optional[str] = None country: Optional[str] = None website: Optional[str] = None mobile_phone: Optional[str] = None invoice_email: Optional[str] = None is_active: Optional[bool] = None class Customer(CustomerBase): """Full customer schema""" id: int created_at: str # Changed from datetime to str for serialization updated_at: Optional[str] = None # Changed from datetime to str for serialization model_config = ConfigDict(from_attributes=True) class HardwareBase(BaseModel): """Base hardware schema""" serial_number: str model: str customer_id: int class HardwareCreate(HardwareBase): """Schema for creating hardware""" pass class Hardware(HardwareBase): """Full hardware schema""" id: int created_at: datetime class Config: from_attributes = True class VendorBase(BaseModel): """Base vendor schema""" name: str cvr_number: Optional[str] = None domain: Optional[str] = None email: Optional[str] = None phone: Optional[str] = None contact_person: Optional[str] = None category: Optional[str] = None notes: Optional[str] = None class VendorCreate(VendorBase): """Schema for creating a vendor""" pass class VendorUpdate(BaseModel): """Schema for updating a vendor""" name: Optional[str] = None cvr_number: Optional[str] = None domain: Optional[str] = None email: Optional[str] = None phone: Optional[str] = None contact_person: Optional[str] = None category: Optional[str] = None notes: Optional[str] = None is_active: Optional[bool] = None class Vendor(VendorBase): """Full vendor schema""" id: int is_active: bool = True created_at: datetime updated_at: Optional[datetime] = None class Config: from_attributes = True class ConversationBase(BaseModel): title: str transcript: Optional[str] = None summary: Optional[str] = None is_private: bool = False customer_id: Optional[int] = None ticket_id: Optional[int] = None category: str = "General" class ConversationCreate(ConversationBase): audio_file_path: str duration_seconds: int = 0 email_message_id: Optional[int] = None class ConversationUpdate(BaseModel): title: Optional[str] = None is_private: Optional[bool] = None ticket_id: Optional[int] = None customer_id: Optional[int] = None category: Optional[str] = None # For soft delete via update if needed, though usually strict API endpoint class Conversation(ConversationBase): id: int audio_file_path: str duration_seconds: int user_id: Optional[int] = None source: str created_at: datetime updated_at: Optional[datetime] = None deleted_at: Optional[datetime] = None model_config = ConfigDict(from_attributes=True) class SolutionBase(BaseModel): """Base schema for Case Solutions""" title: str description: Optional[str] = None solution_type: Optional[str] = None # Support, Drift, Konsulent, etc. result: Optional[str] = None # Løst, Delvist, Workaround, Ej løst class SolutionCreate(SolutionBase): """Schema for creating a solution""" sag_id: int created_by_user_id: Optional[int] = None class SolutionUpdate(BaseModel): """Schema for updating a solution""" title: Optional[str] = None description: Optional[str] = None solution_type: Optional[str] = None result: Optional[str] = None class Solution(SolutionBase): """Full solution schema""" id: int sag_id: int created_by_user_id: Optional[int] = None created_at: datetime updated_at: Optional[datetime] = None model_config = ConfigDict(from_attributes=True) class UserAdminCreate(BaseModel): username: str email: str password: str full_name: Optional[str] = None is_superadmin: bool = False is_active: bool = True group_ids: Optional[List[int]] = None class UserGroupsUpdate(BaseModel): group_ids: List[int] class GroupCreate(BaseModel): name: str description: Optional[str] = None class GroupPermissionsUpdate(BaseModel): permission_ids: List[int] # ===================================================== # AnyDesk Remote Support Integration Schemas # ===================================================== class AnyDeskSessionCreate(BaseModel): """Schema for creating a new AnyDesk session""" customer_id: int contact_id: Optional[int] = None sag_id: Optional[int] = None # Case/ticket ID description: Optional[str] = None created_by_user_id: Optional[int] = None class AnyDeskSession(BaseModel): """Full AnyDesk session schema""" id: int anydesk_session_id: str customer_id: int contact_id: Optional[int] = None sag_id: Optional[int] = None session_link: Optional[str] = None status: str # active, completed, failed, cancelled started_at: str ended_at: Optional[str] = None duration_minutes: Optional[int] = None created_by_user_id: Optional[int] = None created_at: str updated_at: Optional[str] = None model_config = ConfigDict(from_attributes=True) class AnyDeskSessionDetail(AnyDeskSession): """AnyDesk session with additional details""" contact_name: Optional[str] = None customer_name: Optional[str] = None sag_title: Optional[str] = None created_by_user_name: Optional[str] = None device_info: Optional[dict] = None metadata: Optional[dict] = None class AnyDeskWorklogSuggestion(BaseModel): """Suggested worklog entry from a completed session""" session_id: int duration_hours: float duration_minutes: int description: str start_time: str end_time: str billable: bool = True work_type: str = "remote_support" class AnyDeskSessionWithWorklog(BaseModel): """AnyDesk session with suggested worklog entry""" session: AnyDeskSession suggested_worklog: AnyDeskWorklogSuggestion class AnyDeskSessionHistory(BaseModel): """Session history response""" sessions: List[AnyDeskSessionDetail] total: int limit: int offset: int class AnyDeskSessionUpdate(BaseModel): """Schema for updating a session (mainly status updates)""" status: str ended_at: Optional[str] = None duration_minutes: Optional[int] = None