""" Repository for Service model operations. """ from typing import List, Optional, Dict, Any from datetime import date from django.db.models import QuerySet from django.utils import timezone from backend.core.models import Service, Profile from backend.core.repositories.base import BaseRepository class ServiceRepository(BaseRepository[Service]): """ Repository for Service model operations. """ model = Service @classmethod def get_by_account(cls, account_id: str) -> QuerySet[Service]: """ Get services by account. Args: account_id: The account ID Returns: QuerySet of services for the account """ return Service.objects.filter(account_id=account_id) @classmethod def get_by_team_member(cls, profile_id: str) -> QuerySet[Service]: """ Get services by team member. Args: profile_id: The profile ID Returns: QuerySet of services assigned to the team member """ return Service.objects.filter(team_members__id=profile_id) @classmethod def get_by_status(cls, status: str) -> QuerySet[Service]: """ Get services by status. Args: status: The service status Returns: QuerySet of services with the specified status """ return Service.objects.filter(status=status) @classmethod def get_by_date_range(cls, start_date: date = None, end_date: date = None) -> QuerySet[Service]: """ Get services within a date range. Args: start_date: Start date (inclusive) end_date: End date (inclusive) Returns: QuerySet of services within the date range """ return cls.filter_by_date_range(start_date, end_date) @classmethod def get_upcoming(cls) -> QuerySet[Service]: """ Get upcoming services. Returns: QuerySet of upcoming services """ return Service.objects.filter(date__gte=timezone.now().date()) @classmethod def get_past_due(cls) -> QuerySet[Service]: """ Get past due services. Returns: QuerySet of past due services """ return Service.objects.filter( date__lt=timezone.now().date(), status__in=['scheduled', 'in_progress'] ) @classmethod def get_for_today(cls) -> QuerySet[Service]: """ Get services scheduled for today. Returns: QuerySet of services scheduled for today """ return Service.objects.filter(date=timezone.now().date()) @classmethod def search(cls, search_term: str, search_fields: List[str] = None) -> QuerySet[Service]: """ Search services by account or notes. Args: search_term: The search term search_fields: Optional list of fields to search (ignored, using predefined fields) Returns: QuerySet of matching services """ return super().search( search_term, ['account__name', 'notes'] ) @classmethod def filter_services( cls, account_id: str = None, status: str = None, date_from: date = None, date_to: date = None, team_member_id: str = None ) -> QuerySet[Service]: """ Filter services by multiple criteria. Args: account_id: Filter by account ID status: Filter by status date_from: Filter by start date (inclusive) date_to: Filter by end date (inclusive) team_member_id: Filter by team member ID Returns: QuerySet of matching services """ queryset = Service.objects.all() if account_id: queryset = queryset.filter(account_id=account_id) if status: queryset = queryset.filter(status=status) if date_from: queryset = queryset.filter(date__gte=date_from) if date_to: queryset = queryset.filter(date__lte=date_to) if team_member_id: queryset = queryset.filter(team_members__id=team_member_id) return queryset @classmethod def create_with_team_members(cls, data: Dict[str, Any], team_member_ids: List[str]) -> Service: """ Create a service with team members. Args: data: Service data team_member_ids: List of team member IDs Returns: The created service """ # Create the service service = cls.create(data) # Add team members if team_member_ids: team_members = Profile.objects.filter(id__in=team_member_ids) service.team_members.set(team_members) return service @classmethod def update_status(cls, service_id: str, status: str) -> Optional[Service]: """ Update service status. Args: service_id: The service ID status: The new status Returns: The updated service or None if not found """ service = cls.get_by_id(service_id) if not service: return None service.status = status # Set completed_at if status is 'completed' if status == 'completed' and not service.completed_at: service.completed_at = timezone.now() service.save() return service @classmethod def assign_team_members(cls, service_id: str, team_member_ids: List[str]) -> Optional[Service]: """ Assign team members to a service. Args: service_id: The service ID team_member_ids: List of team member IDs Returns: The updated service or None if not found """ service = cls.get_by_id(service_id) if not service: return None team_members = Profile.objects.filter(id__in=team_member_ids) service.team_members.set(team_members) return service