"""Phase 6.3 collaboration DTOs.""" from __future__ import annotations from datetime import datetime from uuid import UUID from pydantic import BaseModel, Field from app.models.types import ( ActivityPriority, ActivityRelatedType, ActivityStatus, ActivityType, CallDirection, CollaborationEntityType, EmailDeliveryStatus, RecurrenceRule, TeamRoleCode, TimelineEventType, ) from app.schemas.common import ORMBase class SalesActivityCreate(BaseModel): subject: str = Field(max_length=255) activity_type: ActivityType related_type: ActivityRelatedType | None = None related_id: UUID | None = None lead_id: UUID | None = None contact_id: UUID | None = None organization_id: UUID | None = None opportunity_id: UUID | None = None due_at: datetime | None = None owner_user_id: str | None = Field(default=None, max_length=100) description: str | None = None status: ActivityStatus = ActivityStatus.PLANNED priority: ActivityPriority = ActivityPriority.MEDIUM custom_type_label: str | None = Field(default=None, max_length=100) class SalesActivityUpdate(BaseModel): subject: str | None = Field(default=None, max_length=255) activity_type: ActivityType | None = None related_type: ActivityRelatedType | None = None related_id: UUID | None = None lead_id: UUID | None = None contact_id: UUID | None = None organization_id: UUID | None = None opportunity_id: UUID | None = None due_at: datetime | None = None owner_user_id: str | None = Field(default=None, max_length=100) description: str | None = None status: ActivityStatus | None = None priority: ActivityPriority | None = None custom_type_label: str | None = Field(default=None, max_length=100) class SalesActivityRead(ORMBase): id: UUID tenant_id: UUID subject: str activity_type: ActivityType status: ActivityStatus priority: ActivityPriority related_type: ActivityRelatedType | None related_id: UUID | None lead_id: UUID | None contact_id: UUID | None organization_id: UUID | None opportunity_id: UUID | None due_at: datetime | None completed_at: datetime | None owner_user_id: str | None description: str | None custom_type_label: str | None created_at: datetime updated_at: datetime class LookupCreate(BaseModel): code: str = Field(max_length=50) name: str = Field(max_length=150) is_active: bool = True class ActivityStatusLookupCreate(LookupCreate): is_terminal: bool = False class ActivityPriorityLookupCreate(LookupCreate): rank: int = 0 class LookupRead(ORMBase): id: UUID tenant_id: UUID code: str name: str is_active: bool created_at: datetime class ParticipantCreate(BaseModel): activity_id: UUID user_id: str | None = None contact_id: UUID | None = None role_label: str | None = None is_required: bool = False class ParticipantRead(ORMBase): id: UUID tenant_id: UUID activity_id: UUID user_id: str | None contact_id: UUID | None role_label: str | None is_required: bool created_at: datetime class ReminderCreate(BaseModel): activity_id: UUID remind_at: datetime channel: str = "in_app" class ReminderRead(ORMBase): id: UUID tenant_id: UUID activity_id: UUID remind_at: datetime channel: str is_sent: bool created_at: datetime class TaskCreate(BaseModel): title: str = Field(max_length=255) description: str | None = None owner_user_id: str | None = None assignee_user_id: str | None = None priority: str = "medium" due_at: datetime | None = None recurrence: RecurrenceRule = RecurrenceRule.NONE opportunity_id: UUID | None = None lead_id: UUID | None = None contact_id: UUID | None = None organization_id: UUID | None = None activity_id: UUID | None = None class TaskRead(ORMBase): id: UUID tenant_id: UUID activity_id: UUID | None title: str description: str | None owner_user_id: str | None assignee_user_id: str | None status: str priority: str due_at: datetime | None completed_at: datetime | None recurrence: RecurrenceRule opportunity_id: UUID | None lead_id: UUID | None contact_id: UUID | None organization_id: UUID | None completion_percent: int is_deleted: bool created_at: datetime updated_at: datetime class ChecklistItemCreate(BaseModel): task_id: UUID title: str = Field(max_length=255) position: int = 0 class ChecklistItemRead(ORMBase): id: UUID tenant_id: UUID task_id: UUID title: str position: int is_completed: bool completed_at: datetime | None created_at: datetime class MeetingCreate(BaseModel): subject: str = Field(max_length=255) start_at: datetime end_at: datetime location: str | None = None online_meeting_url: str | None = None agenda: str | None = None notes: str | None = None owner_user_id: str | None = None opportunity_id: UUID | None = None lead_id: UUID | None = None contact_id: UUID | None = None organization_id: UUID | None = None activity_id: UUID | None = None class MeetingFinishRequest(BaseModel): outcome: str | None = None notes: str | None = None class MeetingRead(ORMBase): id: UUID tenant_id: UUID activity_id: UUID | None subject: str start_at: datetime end_at: datetime location: str | None online_meeting_url: str | None agenda: str | None notes: str | None outcome: str | None owner_user_id: str | None opportunity_id: UUID | None lead_id: UUID | None contact_id: UUID | None organization_id: UUID | None is_finished: bool finished_at: datetime | None created_at: datetime updated_at: datetime class MeetingAttendeeCreate(BaseModel): meeting_id: UUID user_id: str | None = None contact_id: UUID | None = None email: str | None = None display_name: str | None = None class MeetingAttendeeRead(ORMBase): id: UUID tenant_id: UUID meeting_id: UUID user_id: str | None contact_id: UUID | None email: str | None display_name: str | None response_status: str created_at: datetime class CallLogCreate(BaseModel): direction: CallDirection opportunity_id: UUID subject: str | None = None duration_seconds: int = 0 outcome_id: UUID | None = None outcome_label: str | None = None recording_ref: str | None = None notes: str | None = None owner_user_id: str | None = None contact_id: UUID | None = None lead_id: UUID | None = None organization_id: UUID | None = None called_at: datetime | None = None activity_id: UUID | None = None class CallLogRead(ORMBase): id: UUID tenant_id: UUID activity_id: UUID | None direction: CallDirection subject: str | None duration_seconds: int outcome_id: UUID | None outcome_label: str | None recording_ref: str | None notes: str | None owner_user_id: str | None opportunity_id: UUID | None contact_id: UUID | None lead_id: UUID | None organization_id: UUID | None called_at: datetime created_at: datetime class EmailThreadCreate(BaseModel): subject: str = Field(max_length=255) opportunity_id: UUID | None = None contact_id: UUID | None = None organization_id: UUID | None = None lead_id: UUID | None = None class EmailThreadRead(ORMBase): id: UUID tenant_id: UUID subject: str opportunity_id: UUID | None contact_id: UUID | None organization_id: UUID | None lead_id: UUID | None last_message_at: datetime | None created_at: datetime class EmailMessageCreate(BaseModel): thread_id: UUID subject: str = Field(max_length=255) status: EmailDeliveryStatus = EmailDeliveryStatus.SENT opportunity_id: UUID | None = None notification_ref: str | None = None opened: bool = False clicked: bool = False class EmailMessageRead(ORMBase): id: UUID tenant_id: UUID thread_id: UUID subject: str status: EmailDeliveryStatus opened: bool clicked: bool opportunity_id: UUID | None notification_ref: str | None sent_at: datetime | None created_at: datetime class TimelineEventRead(ORMBase): id: UUID tenant_id: UUID event_type: TimelineEventType entity_type: CollaborationEntityType entity_id: UUID related_opportunity_id: UUID | None related_lead_id: UUID | None related_contact_id: UUID | None related_organization_id: UUID | None actor_user_id: str | None title: str payload: dict | None occurred_at: datetime is_immutable: bool created_at: datetime class CommentCreate(BaseModel): entity_type: CollaborationEntityType entity_id: UUID body: str parent_comment_id: UUID | None = None body_format: str = "richtext" is_pinned: bool = False mention_user_ids: list[str] = Field(default_factory=list) class CommentUpdate(BaseModel): body: str | None = None is_pinned: bool | None = None class CommentRead(ORMBase): id: UUID tenant_id: UUID entity_type: CollaborationEntityType entity_id: UUID parent_comment_id: UUID | None body: str body_format: str version: int is_pinned: bool is_deleted: bool created_by: str | None updated_by: str | None created_at: datetime updated_at: datetime class MentionRead(ORMBase): id: UUID tenant_id: UUID comment_id: UUID | None entity_type: CollaborationEntityType entity_id: UUID mentioned_user_id: str mentioned_by: str | None is_read: bool created_at: datetime class BookmarkCreate(BaseModel): entity_type: CollaborationEntityType entity_id: UUID label: str | None = None class BookmarkRead(ORMBase): id: UUID tenant_id: UUID user_id: str entity_type: CollaborationEntityType entity_id: UUID label: str | None created_at: datetime class FavoriteCreate(BaseModel): entity_type: CollaborationEntityType entity_id: UUID class FavoriteRead(ORMBase): id: UUID tenant_id: UUID user_id: str entity_type: CollaborationEntityType entity_id: UUID created_at: datetime class TeamRoleCreate(BaseModel): code: str = Field(max_length=50) name: str = Field(max_length=150) role_kind: TeamRoleCode = TeamRoleCode.CUSTOM is_active: bool = True class TeamRoleRead(ORMBase): id: UUID tenant_id: UUID code: str name: str role_kind: TeamRoleCode is_active: bool created_at: datetime class TeamMemberCreate(BaseModel): user_id: str = Field(max_length=100) team_key: str = Field(max_length=100) display_name: str | None = None role_id: UUID | None = None role_code: TeamRoleCode = TeamRoleCode.SALESPERSON is_active: bool = True class TeamMemberRead(ORMBase): id: UUID tenant_id: UUID user_id: str display_name: str | None team_key: str role_id: UUID | None role_code: TeamRoleCode is_active: bool created_at: datetime class TeamAssignmentCreate(BaseModel): team_key: str member_id: UUID entity_type: CollaborationEntityType entity_id: UUID class TeamAssignmentRead(ORMBase): id: UUID tenant_id: UUID team_key: str member_id: UUID entity_type: CollaborationEntityType entity_id: UUID assigned_by: str | None created_at: datetime class NotificationPreferenceUpsert(BaseModel): mentions_enabled: bool = True task_reminders_enabled: bool = True meeting_reminders_enabled: bool = True timeline_digest_enabled: bool = False class NotificationPreferenceRead(ORMBase): id: UUID tenant_id: UUID user_id: str mentions_enabled: bool task_reminders_enabled: bool meeting_reminders_enabled: bool timeline_digest_enabled: bool created_at: datetime