259 lines
8.4 KiB
Python
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)
|
|
|