Backend: - Add HasQuota() permission factory for quota limits (resources, users, services, appointments, email templates, automated tasks) - Add HasFeaturePermission() factory for feature-based permissions (SMS, masked calling, custom domains, white label, plugins, webhooks, calendar sync, analytics) - Add has_feature() method to Tenant model for flexible permission checking - Add new tenant permission fields: can_create_plugins, can_use_webhooks, can_use_calendar_sync, can_export_data - Create Data Export API with CSV/JSON support for appointments, customers, resources, services - Create Analytics API with dashboard, appointments, revenue endpoints - Add calendar sync views and URL configuration Frontend: - Add usePlanFeatures hook for checking feature availability - Add UpgradePrompt components (inline, banner, overlay variants) - Add LockedSection wrapper and LockedButton for feature gating - Update settings pages with permission checks 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
74 lines
2.8 KiB
Python
74 lines
2.8 KiB
Python
"""
|
|
Analytics Serializers
|
|
|
|
Read-only serializers for analytics data.
|
|
"""
|
|
from rest_framework import serializers
|
|
|
|
|
|
class DashboardStatsSerializer(serializers.Serializer):
|
|
"""Serializer for dashboard summary statistics"""
|
|
total_appointments_this_month = serializers.IntegerField()
|
|
total_appointments_all_time = serializers.IntegerField()
|
|
active_resources_count = serializers.IntegerField()
|
|
active_services_count = serializers.IntegerField()
|
|
upcoming_appointments_count = serializers.IntegerField()
|
|
average_appointment_duration_minutes = serializers.FloatField()
|
|
peak_booking_day = serializers.CharField()
|
|
peak_booking_hour = serializers.IntegerField()
|
|
period = serializers.DictField()
|
|
|
|
|
|
class ServiceBreakdownSerializer(serializers.Serializer):
|
|
"""Service breakdown statistics"""
|
|
service_id = serializers.IntegerField()
|
|
service_name = serializers.CharField()
|
|
count = serializers.IntegerField()
|
|
revenue_cents = serializers.IntegerField(required=False, allow_null=True)
|
|
|
|
|
|
class ResourceBreakdownSerializer(serializers.Serializer):
|
|
"""Resource breakdown statistics"""
|
|
resource_id = serializers.IntegerField()
|
|
resource_name = serializers.CharField()
|
|
count = serializers.IntegerField()
|
|
|
|
|
|
class StatusBreakdownSerializer(serializers.Serializer):
|
|
"""Status breakdown for appointments"""
|
|
confirmed = serializers.IntegerField()
|
|
cancelled = serializers.IntegerField()
|
|
no_show = serializers.IntegerField()
|
|
|
|
|
|
class DailyBreakdownSerializer(serializers.Serializer):
|
|
"""Daily breakdown of analytics"""
|
|
date = serializers.DateField()
|
|
count = serializers.IntegerField(required=False)
|
|
revenue_cents = serializers.IntegerField(required=False, allow_null=True)
|
|
transaction_count = serializers.IntegerField(required=False)
|
|
status_breakdown = StatusBreakdownSerializer(required=False)
|
|
|
|
|
|
class AppointmentAnalyticsSerializer(serializers.Serializer):
|
|
"""Serializer for appointment analytics response"""
|
|
total = serializers.IntegerField()
|
|
by_status = StatusBreakdownSerializer()
|
|
by_service = ServiceBreakdownSerializer(many=True)
|
|
by_resource = ResourceBreakdownSerializer(many=True)
|
|
daily_breakdown = DailyBreakdownSerializer(many=True)
|
|
booking_trend_percent = serializers.FloatField()
|
|
cancellation_rate_percent = serializers.FloatField()
|
|
no_show_rate_percent = serializers.FloatField()
|
|
period_days = serializers.IntegerField()
|
|
|
|
|
|
class RevenueAnalyticsSerializer(serializers.Serializer):
|
|
"""Serializer for revenue analytics response"""
|
|
total_revenue_cents = serializers.IntegerField()
|
|
transaction_count = serializers.IntegerField()
|
|
average_transaction_value_cents = serializers.IntegerField()
|
|
by_service = ServiceBreakdownSerializer(many=True)
|
|
daily_breakdown = DailyBreakdownSerializer(many=True)
|
|
period_days = serializers.IntegerField()
|