Files
smoothschedule/ANALYTICS_CHANGES.md
poduck e4ad7fca87 feat: Plan-based feature permissions and quota enforcement
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>
2025-12-02 11:21:11 -05:00

9.4 KiB

Advanced Analytics Implementation - Change Summary

Overview

Successfully implemented the Advanced Analytics feature with permission-based access control in the Django backend. All analytics endpoints are gated behind the advanced_analytics permission from the subscription plan.

Files Created

Analytics App (/smoothschedule/analytics/)

  1. __init__.py - Package initialization
  2. apps.py - Django app configuration
  3. admin.py - Admin interface (read-only app, no models)
  4. views.py - AnalyticsViewSet with 3 endpoints:
    • dashboard() - Summary statistics
    • appointments() - Detailed appointment analytics
    • revenue() - Revenue analytics (dual-permission gated)
  5. serializers.py - Response serializers for data validation
  6. urls.py - URL routing
  7. tests.py - Comprehensive pytest test suite
  8. migrations/ - Empty migrations directory
  9. README.md - Full API documentation
  10. IMPLEMENTATION_GUIDE.md - Developer implementation guide

Files Modified

1. /smoothschedule/core/permissions.py

Changes:

  • Added advanced_analytics and advanced_reporting to the FEATURE_NAMES dictionary in HasFeaturePermission

Before:

FEATURE_NAMES = {
    'can_use_sms_reminders': 'SMS Reminders',
    ...
    'can_use_calendar_sync': 'Calendar Sync',
}

After:

FEATURE_NAMES = {
    'can_use_sms_reminders': 'SMS Reminders',
    ...
    'can_use_calendar_sync': 'Calendar Sync',
    'advanced_analytics': 'Advanced Analytics',
    'advanced_reporting': 'Advanced Reporting',
}

2. /smoothschedule/config/urls.py

Changes:

  • Added analytics URL include in the API URL patterns

Before:

# Schedule API (internal)
path("", include("schedule.urls")),
# Payments API
path("payments/", include("payments.urls")),

After:

# Schedule API (internal)
path("", include("schedule.urls")),
# Analytics API
path("", include("analytics.urls")),
# Payments API
path("payments/", include("payments.urls")),

3. /smoothschedule/config/settings/base.py

Changes:

  • Added analytics app to LOCAL_APPS

Before:

LOCAL_APPS = [
    "smoothschedule.users",
    "core",
    "schedule",
    "payments",
    ...
]

After:

LOCAL_APPS = [
    "smoothschedule.users",
    "core",
    "schedule",
    "analytics",
    "payments",
    ...
]

API Endpoints

All endpoints are located at /api/analytics/ and require:

  • Authentication via token or session
  • advanced_analytics permission in tenant's subscription plan

1. Dashboard Summary

GET /api/analytics/analytics/dashboard/

Returns:

  • Total appointments (this month and all-time)
  • Active resources and services count
  • Upcoming appointments
  • Average appointment duration
  • Peak booking day and hour

2. Appointment Analytics

GET /api/analytics/analytics/appointments/

Query Parameters:

  • days (default: 30)
  • status (optional: confirmed, cancelled, no_show)
  • service_id (optional)
  • resource_id (optional)

Returns:

  • Total appointments
  • Breakdown by status
  • Breakdown by service and resource
  • Daily breakdown
  • Booking trends and rates

3. Revenue Analytics

GET /api/analytics/analytics/revenue/

Query Parameters:

  • days (default: 30)
  • service_id (optional)

Returns:

  • Total revenue in cents
  • Transaction count
  • Average transaction value
  • Revenue by service
  • Daily breakdown

Note: Requires both advanced_analytics AND can_accept_payments permissions

Permission Gating Implementation

How It Works

  1. Request arrives at endpoint
  2. IsAuthenticated check - Verifies user is logged in
  3. HasFeaturePermission('advanced_analytics') check:
    • Gets tenant from request
    • Calls tenant.has_feature('advanced_analytics')
    • Checks both direct field and subscription plan JSON
  4. If permission exists - View logic executes
  5. If permission missing - 403 Forbidden returned with message

Permission Check Logic

# In core/models.py - Tenant.has_feature()
def has_feature(self, permission_key):
    # Check direct field on Tenant model
    if hasattr(self, permission_key):
        return bool(getattr(self, permission_key))

    # Check subscription plan permissions JSON
    if self.subscription_plan:
        plan_perms = self.subscription_plan.permissions or {}
        return bool(plan_perms.get(permission_key, False))

    return False

Enabling Analytics for a Plan

Via Django Admin

  1. Go to /admin/platform_admin/subscriptionplan/
  2. Edit a plan
  3. Add to "Permissions" JSON field:
{
    "advanced_analytics": true
}

Via Django Shell

docker compose -f docker-compose.local.yml exec django python manage.py shell

from platform_admin.models import SubscriptionPlan
plan = SubscriptionPlan.objects.get(name='Professional')
perms = plan.permissions or {}
perms['advanced_analytics'] = True
plan.permissions = perms
plan.save()

Testing

Permission Tests Included

The analytics/tests.py file includes comprehensive tests:

  1. TestAnalyticsPermissions

    • test_analytics_requires_authentication - 401 without auth
    • test_analytics_denied_without_permission - 403 without permission
    • test_analytics_allowed_with_permission - 200 with permission
    • test_dashboard_endpoint_structure - Verify response structure
    • test_appointments_endpoint_with_filters - Query parameters work
    • test_revenue_requires_payments_permission - Dual permission check
    • test_multiple_permission_check - Both checks enforced
  2. TestAnalyticsData

    • test_dashboard_counts_appointments_correctly - Correct counts
    • test_appointments_counts_by_status - Status breakdown
    • test_cancellation_rate_calculation - Rate calculation

Running Tests

# Run all analytics tests
docker compose -f docker-compose.local.yml exec django pytest analytics/tests.py -v

# Run specific test
docker compose -f docker-compose.local.yml exec django pytest analytics/tests.py::TestAnalyticsPermissions::test_analytics_denied_without_permission -v

# Run with coverage
docker compose -f docker-compose.local.yml exec django pytest analytics/tests.py --cov=analytics

Error Responses

401 Unauthorized (No Authentication)

{
    "detail": "Authentication credentials were not provided."
}

403 Forbidden (No Permission)

{
    "detail": "Your current plan does not include Advanced Analytics. Please upgrade your subscription to access this feature."
}

403 Forbidden (Revenue Endpoint - Missing Payments Permission)

{
    "error": "Payment analytics not available",
    "detail": "Your plan does not include payment processing."
}

Example Usage

Get Dashboard Stats (with cURL)

TOKEN="your_auth_token_here"

curl -H "Authorization: Token $TOKEN" \
    http://lvh.me:8000/api/analytics/analytics/dashboard/ | jq

Get Appointment Analytics (with filters)

curl -H "Authorization: Token $TOKEN" \
    "http://lvh.me:8000/api/analytics/analytics/appointments/?days=7&status=confirmed" | jq

Get Revenue Analytics

curl -H "Authorization: Token $TOKEN" \
    http://lvh.me:8000/api/analytics/analytics/revenue/ | jq

Key Design Decisions

  1. ViewSet without models - Analytics is calculated on-the-fly, no database models
  2. Read-only endpoints - No POST/PUT/DELETE, only GET for querying
  3. Comprehensive permission naming - Both advanced_analytics and advanced_reporting supported for flexibility
  4. Dual permission check - Revenue endpoint requires both analytics and payments permissions
  5. Query parameter filtering - Flexible filtering for reports
  6. Detailed error messages - User-friendly upgrade prompts

Documentation Provided

  1. README.md - Complete API documentation with examples
  2. IMPLEMENTATION_GUIDE.md - Developer guide for enabling and debugging
  3. Code comments - Detailed docstrings in views and serializers
  4. Test file - Comprehensive test suite with examples

Next Steps

  1. Migrate - No migrations needed (no database models)
  2. Configure Plans - Add advanced_analytics permission to desired subscription plans
  3. Test - Run the test suite to verify functionality
  4. Deploy - Push to production
  5. Monitor - Check logs for any issues

Implementation Checklist

  • Create analytics app with ViewSet
  • Implement dashboard endpoint with summary statistics
  • Implement appointments endpoint with filtering
  • Implement revenue endpoint with dual permission check
  • Add permission to FEATURE_NAMES in core/permissions.py
  • Register app in INSTALLED_APPS
  • Add URL routing
  • Create serializers for response validation
  • Write comprehensive test suite
  • Document API endpoints
  • Document implementation details
  • Provide developer guide

Files Summary

Total Files Created: 11

  • 10 Python files (app code + tests)
  • 2 Documentation files

Total Files Modified: 3

  • core/permissions.py
  • config/urls.py
  • config/settings/base.py

Lines of Code:

  • views.py: ~350 lines
  • tests.py: ~260 lines
  • serializers.py: ~80 lines
  • Documentation: ~1000 lines

Questions or Issues?

Refer to:

  1. analytics/README.md - API usage and endpoints
  2. analytics/IMPLEMENTATION_GUIDE.md - Setup and debugging
  3. analytics/tests.py - Examples of correct usage
  4. core/permissions.py - Permission checking logic