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>
This commit is contained in:
352
ANALYTICS_CHANGES.md
Normal file
352
ANALYTICS_CHANGES.md
Normal file
@@ -0,0 +1,352 @@
|
||||
# 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:**
|
||||
```python
|
||||
FEATURE_NAMES = {
|
||||
'can_use_sms_reminders': 'SMS Reminders',
|
||||
...
|
||||
'can_use_calendar_sync': 'Calendar Sync',
|
||||
}
|
||||
```
|
||||
|
||||
**After:**
|
||||
```python
|
||||
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:**
|
||||
```python
|
||||
# Schedule API (internal)
|
||||
path("", include("schedule.urls")),
|
||||
# Payments API
|
||||
path("payments/", include("payments.urls")),
|
||||
```
|
||||
|
||||
**After:**
|
||||
```python
|
||||
# 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:**
|
||||
```python
|
||||
LOCAL_APPS = [
|
||||
"smoothschedule.users",
|
||||
"core",
|
||||
"schedule",
|
||||
"payments",
|
||||
...
|
||||
]
|
||||
```
|
||||
|
||||
**After:**
|
||||
```python
|
||||
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
|
||||
|
||||
```python
|
||||
# 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:
|
||||
```json
|
||||
{
|
||||
"advanced_analytics": true
|
||||
}
|
||||
```
|
||||
|
||||
### Via Django Shell
|
||||
```bash
|
||||
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
|
||||
|
||||
```bash
|
||||
# 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)
|
||||
```json
|
||||
{
|
||||
"detail": "Authentication credentials were not provided."
|
||||
}
|
||||
```
|
||||
|
||||
### 403 Forbidden (No Permission)
|
||||
```json
|
||||
{
|
||||
"detail": "Your current plan does not include Advanced Analytics. Please upgrade your subscription to access this feature."
|
||||
}
|
||||
```
|
||||
|
||||
### 403 Forbidden (Revenue Endpoint - Missing Payments Permission)
|
||||
```json
|
||||
{
|
||||
"error": "Payment analytics not available",
|
||||
"detail": "Your plan does not include payment processing."
|
||||
}
|
||||
```
|
||||
|
||||
## Example Usage
|
||||
|
||||
### Get Dashboard Stats (with cURL)
|
||||
```bash
|
||||
TOKEN="your_auth_token_here"
|
||||
|
||||
curl -H "Authorization: Token $TOKEN" \
|
||||
http://lvh.me:8000/api/analytics/analytics/dashboard/ | jq
|
||||
```
|
||||
|
||||
### Get Appointment Analytics (with filters)
|
||||
```bash
|
||||
curl -H "Authorization: Token $TOKEN" \
|
||||
"http://lvh.me:8000/api/analytics/analytics/appointments/?days=7&status=confirmed" | jq
|
||||
```
|
||||
|
||||
### Get Revenue Analytics
|
||||
```bash
|
||||
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
|
||||
|
||||
- [x] Create analytics app with ViewSet
|
||||
- [x] Implement dashboard endpoint with summary statistics
|
||||
- [x] Implement appointments endpoint with filtering
|
||||
- [x] Implement revenue endpoint with dual permission check
|
||||
- [x] Add permission to FEATURE_NAMES in core/permissions.py
|
||||
- [x] Register app in INSTALLED_APPS
|
||||
- [x] Add URL routing
|
||||
- [x] Create serializers for response validation
|
||||
- [x] Write comprehensive test suite
|
||||
- [x] Document API endpoints
|
||||
- [x] Document implementation details
|
||||
- [x] 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
|
||||
Reference in New Issue
Block a user