""" Views for report generation and management. """ from rest_framework import generics, status from rest_framework.decorators import api_view, permission_classes from rest_framework.permissions import IsAuthenticated from rest_framework.response import Response from django.http import FileResponse, Http404 from django.conf import settings from django.utils import timezone from datetime import timedelta from .models import Report, ReportTemplate from .serializers import ReportSerializer, ReportTemplateSerializer from .services import ReportGenerationService import os import logging logger = logging.getLogger(__name__) class ReportListView(generics.ListCreateAPIView): """List and create reports.""" serializer_class = ReportSerializer permission_classes = [IsAuthenticated] def get_queryset(self): return Report.objects.filter(user=self.request.user).order_by('-created_at') def perform_create(self, serializer): serializer.save(user=self.request.user) class ReportDetailView(generics.RetrieveDestroyAPIView): """Report detail view.""" serializer_class = ReportSerializer permission_classes = [IsAuthenticated] def get_queryset(self): return Report.objects.filter(user=self.request.user) @api_view(['POST']) @permission_classes([IsAuthenticated]) def generate_transaction_summary_report(request): """Generate transaction summary report.""" try: # Check user's report limits user = request.user limits = user.get_usage_limits() if not limits.get('reports_per_month', 0): return Response( {'error': 'Report generation not available for your subscription'}, status=status.HTTP_403_FORBIDDEN ) # Get parameters area = request.data.get('area') property_type = request.data.get('property_type') start_date = request.data.get('start_date') end_date = request.data.get('end_date') format_type = request.data.get('format', 'pdf') # Create report record report = Report.objects.create( user=user, title=f"Transaction Summary Report - {area or 'All Areas'}", report_type='transaction_summary', format=format_type, parameters={ 'area': area, 'property_type': property_type, 'start_date': start_date, 'end_date': end_date, }, expires_at=timezone.now() + timedelta(days=7) ) # Generate report asynchronously report_service = ReportGenerationService() report_service.generate_transaction_summary_report.delay( report.id, area, property_type, start_date, end_date, format_type ) return Response({ 'message': 'Report generation started', 'report_id': str(report.id), 'status': report.status }) except Exception as e: logger.error(f'Error generating transaction summary report: {e}') return Response( {'error': 'Failed to generate report'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR ) @api_view(['POST']) @permission_classes([IsAuthenticated]) def generate_area_analysis_report(request): """Generate area analysis report.""" try: user = request.user limits = user.get_usage_limits() if not limits.get('reports_per_month', 0): return Response( {'error': 'Report generation not available for your subscription'}, status=status.HTTP_403_FORBIDDEN ) area = request.data.get('area') format_type = request.data.get('format', 'pdf') if not area: return Response( {'error': 'Area parameter is required'}, status=status.HTTP_400_BAD_REQUEST ) report = Report.objects.create( user=user, title=f"Area Analysis Report - {area}", report_type='area_analysis', format=format_type, parameters={'area': area}, expires_at=timezone.now() + timedelta(days=7) ) report_service = ReportGenerationService() report_service.generate_area_analysis_report.delay( report.id, area, format_type ) return Response({ 'message': 'Report generation started', 'report_id': str(report.id), 'status': report.status }) except Exception as e: logger.error(f'Error generating area analysis report: {e}') return Response( {'error': 'Failed to generate report'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR ) @api_view(['POST']) @permission_classes([IsAuthenticated]) def generate_forecast_report(request): """Generate forecast report.""" try: user = request.user limits = user.get_usage_limits() if not limits.get('reports_per_month', 0): return Response( {'error': 'Report generation not available for your subscription'}, status=status.HTTP_403_FORBIDDEN ) area = request.data.get('area') property_type = request.data.get('property_type') forecast_periods = request.data.get('forecast_periods', 12) format_type = request.data.get('format', 'pdf') if not area or not property_type: return Response( {'error': 'Area and property_type parameters are required'}, status=status.HTTP_400_BAD_REQUEST ) report = Report.objects.create( user=user, title=f"Forecast Report - {area} - {property_type}", report_type='forecast_report', format=format_type, parameters={ 'area': area, 'property_type': property_type, 'forecast_periods': forecast_periods, }, expires_at=timezone.now() + timedelta(days=7) ) report_service = ReportGenerationService() report_service.generate_forecast_report.delay( report.id, area, property_type, forecast_periods, format_type ) return Response({ 'message': 'Report generation started', 'report_id': str(report.id), 'status': report.status }) except Exception as e: logger.error(f'Error generating forecast report: {e}') return Response( {'error': 'Failed to generate report'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR ) @api_view(['GET']) @permission_classes([IsAuthenticated]) def download_report(request, report_id): """Download a generated report.""" try: report = Report.objects.get(id=report_id, user=request.user) if report.status != 'completed': return Response( {'error': 'Report not ready for download'}, status=status.HTTP_400_BAD_REQUEST ) if not report.file_path or not os.path.exists(report.file_path): return Response( {'error': 'Report file not found'}, status=status.HTTP_404_NOT_FOUND ) # Determine content type content_type = 'application/pdf' if report.format == 'excel': content_type = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' elif report.format == 'csv': content_type = 'text/csv' response = FileResponse( open(report.file_path, 'rb'), content_type=content_type ) response['Content-Disposition'] = f'attachment; filename="{report.title}.{report.format}"' return response except Report.DoesNotExist: return Response( {'error': 'Report not found'}, status=status.HTTP_404_NOT_FOUND ) except Exception as e: logger.error(f'Error downloading report: {e}') return Response( {'error': 'Failed to download report'}, status=status.HTTP_500_INTERNAL_SERVER_ERROR ) class ReportTemplateListView(generics.ListAPIView): """List available report templates.""" serializer_class = ReportTemplateSerializer permission_classes = [IsAuthenticated] def get_queryset(self): return ReportTemplate.objects.filter(is_active=True)