from rest_framework import serializers from ..models import ( Dashboard, DashboardWidget, DataSource, Report, ReportExecution, MetricDefinition, MetricValue ) class BaseSerializer(serializers.ModelSerializer): """Base serializer with common functionality""" class Meta: fields = ['id'] read_only_fields = ['created_at', 'updated_at'] class DataSourceSerializer(serializers.ModelSerializer): """Serializer for DataSource model""" source_type_display = serializers.CharField(source='get_source_type_display', read_only=True) class Meta: model = DataSource fields = [ 'source_id', 'name', 'description', 'source_type', 'source_type_display', 'connection_string', 'query', 'refresh_interval', 'is_active', 'last_updated', 'created_at', 'updated_at' ] read_only_fields = ['source_id', 'last_updated', 'created_at', 'updated_at'] class MetricDefinitionSerializer(serializers.ModelSerializer): """Serializer for MetricDefinition model""" metric_type_display = serializers.CharField(source='get_metric_type_display', read_only=True) data_source_name = serializers.CharField(source='data_source.name', read_only=True) class Meta: model = MetricDefinition fields = [ 'metric_id', 'name', 'description', 'metric_type', 'metric_type_display', 'data_source', 'data_source_name', 'calculation_formula', 'target_value', 'threshold_warning', 'threshold_critical', 'unit', 'is_active', 'created_at', 'updated_at' ] read_only_fields = ['metric_id', 'created_at', 'updated_at'] class MetricValueSerializer(serializers.ModelSerializer): """Serializer for MetricValue model""" metric_name = serializers.CharField(source='metric.name', read_only=True) metric_unit = serializers.CharField(source='metric.unit', read_only=True) status_display = serializers.CharField(source='get_status_display', read_only=True) class Meta: model = MetricValue fields = [ 'value_id', 'metric', 'metric_name', 'metric_unit', 'value', 'timestamp', 'status', 'status_display', 'notes', 'created_at', 'updated_at' ] read_only_fields = ['value_id', 'created_at', 'updated_at'] class DashboardWidgetSerializer(serializers.ModelSerializer): """Serializer for DashboardWidget model""" widget_type_display = serializers.CharField(source='get_widget_type_display', read_only=True) data_source_name = serializers.CharField(source='data_source.name', read_only=True) class Meta: model = DashboardWidget fields = [ 'widget_id', 'title', 'description', 'widget_type', 'widget_type_display', 'data_source', 'data_source_name', 'configuration', 'position_x', 'position_y', 'width', 'height', 'refresh_interval', 'is_visible', 'created_at', 'updated_at' ] read_only_fields = ['widget_id', 'created_at', 'updated_at'] class DashboardSerializer(serializers.ModelSerializer): """Serializer for Dashboard model""" created_by_name = serializers.CharField(source='created_by.get_full_name', read_only=True) widgets = DashboardWidgetSerializer(many=True, read_only=True) widget_count = serializers.IntegerField(read_only=True) class Meta: model = Dashboard fields = [ 'dashboard_id', 'name', 'description', 'layout', 'is_public', 'is_default', 'created_by', 'created_by_name', 'widgets', 'widget_count', 'created_at', 'updated_at' ] read_only_fields = ['dashboard_id', 'widget_count', 'created_at', 'updated_at'] class ReportSerializer(serializers.ModelSerializer): """Serializer for Report model""" report_type_display = serializers.CharField(source='get_report_type_display', read_only=True) created_by_name = serializers.CharField(source='created_by.get_full_name', read_only=True) data_source_name = serializers.CharField(source='data_source.name', read_only=True) class Meta: model = Report fields = [ 'report_id', 'name', 'description', 'report_type', 'report_type_display', 'data_source', 'data_source_name', 'query', 'parameters', 'schedule', 'is_active', 'created_by', 'created_by_name', 'created_at', 'updated_at' ] read_only_fields = ['report_id', 'created_at', 'updated_at'] class ReportExecutionSerializer(serializers.ModelSerializer): """Serializer for ReportExecution model""" report_name = serializers.CharField(source='report.name', read_only=True) executed_by_name = serializers.CharField(source='executed_by.get_full_name', read_only=True) status_display = serializers.CharField(source='get_status_display', read_only=True) duration_seconds = serializers.IntegerField(read_only=True) class Meta: model = ReportExecution fields = [ 'execution_id', 'report', 'report_name', 'executed_by', 'executed_by_name', 'start_time', 'end_time', 'duration_seconds', 'status', 'status_display', 'parameters', 'result_count', 'file_path', 'error_message', 'created_at', 'updated_at' ] read_only_fields = [ 'execution_id', 'duration_seconds', 'created_at', 'updated_at' ] class AnalyticsStatsSerializer(serializers.Serializer): """Serializer for analytics statistics""" total_dashboards = serializers.IntegerField() total_reports = serializers.IntegerField() total_metrics = serializers.IntegerField() active_data_sources = serializers.IntegerField() reports_executed_today = serializers.IntegerField() failed_executions = serializers.IntegerField() avg_execution_time = serializers.FloatField() popular_reports = serializers.ListField() metric_status_breakdown = serializers.DictField() class DashboardCreateSerializer(serializers.Serializer): """Serializer for creating dashboards""" name = serializers.CharField() description = serializers.CharField(required=False, allow_blank=True) layout = serializers.JSONField(required=False) is_public = serializers.BooleanField(default=False) widgets = serializers.ListField( child=serializers.DictField(), required=False ) def validate_widgets(self, value): """Validate dashboard widgets""" for widget in value: required_fields = ['title', 'widget_type', 'data_source_id'] for field in required_fields: if field not in widget: raise serializers.ValidationError(f"Widget missing required field: {field}") return value class ReportExecuteSerializer(serializers.Serializer): """Serializer for executing reports""" report_id = serializers.IntegerField() parameters = serializers.JSONField(required=False) format = serializers.ChoiceField( choices=['JSON', 'CSV', 'PDF', 'EXCEL'], default='JSON' ) def validate_report_id(self, value): """Validate that the report exists and is active""" try: report = Report.objects.get(id=value) if not report.is_active: raise serializers.ValidationError("Report is not active.") return value except Report.DoesNotExist: raise serializers.ValidationError("Invalid report ID.") class MetricCalculateSerializer(serializers.Serializer): """Serializer for calculating metrics""" metric_id = serializers.IntegerField() start_date = serializers.DateTimeField(required=False) end_date = serializers.DateTimeField(required=False) def validate_metric_id(self, value): """Validate that the metric exists and is active""" try: metric = MetricDefinition.objects.get(id=value) if not metric.is_active: raise serializers.ValidationError("Metric is not active.") return value except MetricDefinition.DoesNotExist: raise serializers.ValidationError("Invalid metric ID.") def validate(self, data): """Validate date range""" if data.get('start_date') and data.get('end_date'): if data['end_date'] <= data['start_date']: raise serializers.ValidationError("End date must be after start date.") return data class DataSourceTestSerializer(serializers.Serializer): """Serializer for testing data sources""" source_id = serializers.IntegerField() test_query = serializers.CharField(required=False, allow_blank=True) def validate_source_id(self, value): """Validate that the data source exists""" try: DataSource.objects.get(id=value) return value except DataSource.DoesNotExist: raise serializers.ValidationError("Invalid data source ID.") class WidgetDataSerializer(serializers.Serializer): """Serializer for widget data""" widget_id = serializers.IntegerField() refresh = serializers.BooleanField(default=False) def validate_widget_id(self, value): """Validate that the widget exists""" try: DashboardWidget.objects.get(id=value) return value except DashboardWidget.DoesNotExist: raise serializers.ValidationError("Invalid widget ID.")