saas-market-analysis-dubai/apps/reports/views.py
2025-09-17 03:04:22 +05:30

259 lines
8.4 KiB
Python

"""
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)