""" Reporting services for analytics and business intelligence. """ from typing import Dict, Any, List from datetime import date, timedelta from django.utils import timezone from backend.core.repositories.services.services import ServiceRepository from backend.core.repositories.projects.projects import ProjectRepository from backend.core.repositories.invoices.invoices import InvoiceRepository from backend.core.repositories.reports.reports import ReportRepository from backend.core.repositories.revenues.revenues import RevenueRepository from backend.core.repositories.labor.labor import LaborRepository class ReportingService: """ Service for generating business reports and analytics. """ @staticmethod def get_monthly_summary(year: int, month: int) -> Dict[str, Any]: """ Get monthly business summary. Args: year: Year month: Month (1-12) Returns: Dictionary with monthly summary data """ # Calculate date range for the month start_date = date(year, month, 1) if month == 12: end_date = date(year + 1, 1, 1) - timedelta(days=1) else: end_date = date(year, month + 1, 1) - timedelta(days=1) # Get services in the month services = ServiceRepository.get_by_date_range(start_date, end_date) # Get projects in the month projects = ProjectRepository.get_by_date_range(start_date, end_date) # Get invoices in the month invoices = InvoiceRepository.get_by_date_range(start_date, end_date) # Get paid invoices in the month paid_invoices = invoices.filter(status='paid') # Calculate total revenue and labor for the month total_revenue = RevenueRepository.get_total_revenue(None, start_date, end_date) total_labor = LaborRepository.get_total_labor_cost(None, start_date, end_date) # Calculate profit profit = total_revenue - total_labor # Service statistics service_stats = { 'total': services.count(), 'completed': services.filter(status='completed').count(), 'cancelled': services.filter(status='cancelled').count(), 'completion_rate': services.filter( status='completed').count() / services.count() if services.count() > 0 else 0 } # Project statistics project_stats = { 'total': projects.count(), 'completed': projects.filter(status='completed').count(), 'cancelled': projects.filter(status='cancelled').count(), 'completion_rate': projects.filter( status='completed').count() / projects.count() if projects.count() > 0 else 0, 'total_amount': sum(p.amount for p in projects), 'total_labor': sum(p.labor for p in projects), 'profit': sum(p.amount - p.labor for p in projects) } # Invoice statistics invoice_stats = { 'total': invoices.count(), 'paid': paid_invoices.count(), 'payment_rate': paid_invoices.count() / invoices.count() if invoices.count() > 0 else 0, 'total_amount': sum(i.total_amount for i in invoices), 'paid_amount': sum(i.total_amount for i in paid_invoices) } return { 'period': { 'year': year, 'month': month, 'start_date': start_date.isoformat(), 'end_date': end_date.isoformat() }, 'financials': { 'revenue': total_revenue, 'labor': total_labor, 'profit': profit, 'profit_margin': (profit / total_revenue) * 100 if total_revenue > 0 else 0 }, 'services': service_stats, 'projects': project_stats, 'invoices': invoice_stats } @staticmethod def get_team_performance(start_date: date = None, end_date: date = None) -> List[Dict[str, Any]]: """ Get team member performance metrics. Args: start_date: Start date (inclusive) end_date: End date (inclusive) Returns: List of team member performance data """ # Set default date range to current month if not provided if not start_date: today = timezone.now().date() start_date = date(today.year, today.month, 1) if not end_date: end_date = timezone.now().date() # Get team members with activity team_activity = ReportRepository.get_team_summary(start_date, end_date) team_performance = [] for member_id, summary in team_activity.get('member_summaries', {}).items(): # Get services completed by the team member services_completed = ServiceRepository.get_by_team_member(member_id).filter( status='completed', date__gte=start_date, date__lte=end_date ).count() # Get projects completed by the team member projects_completed = ProjectRepository.get_by_team_member(member_id).filter( status='completed', date__gte=start_date, date__lte=end_date ).count() # Calculate metrics performance = { 'member_id': member_id, 'name': summary['name'], 'reports_submitted': summary['report_count'], 'services_completed': services_completed, 'projects_completed': projects_completed, 'total_work_items': services_completed + projects_completed } team_performance.append(performance) # Sort by total work items descending team_performance.sort(key=lambda x: x['total_work_items'], reverse=True) return team_performance