Reports Service
๐ Integration Pointsโ
Error Handlingโ
Internal Servicesโ
Common Errorsโ
-
-
Source data for all reports and analytics| Error | Status | Cause | Resolution |
-
Lead status (freshness) drives conversion metrics| ------------------ | ------ | --------------------------------------- | -------------------------- |
-
Lead assignments determine representative performance| No data available | 200 | No leads in date range | Returns empty data arrays |
-
| Invalid date range | 400 | enddate < startdate | Validate dates on frontend |
-
Campaigns Service:| Unauthorized | 401 | Invalid or expired token | Re-authenticate |
-
Campaign association for filtering| Forbidden | 403 | Accessing other user's data (non-admin) | Check role permissions |
-
Campaign type and integration for grouping
-
Campaign performance rankings
-
Error Response Pattern:
// All errors return 200 with empty data
{
success: true,
message: "SUCCESS",
data: {
total_leads: 0,
// ... all metrics as 0 or empty arrays
}
}
Utilitiesโ
- Pagination Utility (link removed - file does not exist):
generatePagination()- Creates pagination metadata- Calculates total_pages, has_next, has_prev
- Standardized pagination across all list endpoints
External Dependenciesโ
-
Mongoose Models:}
-
reportingModel - Report aggregations and analytics```
-
Lead Model - Source data for metrics
-
User Model - Representative information---
-
Campaign Model - Campaign details
-
Testing Recommendationsโ
๐งช Edge Cases & Special Handlingโ
Unit Testsโ
Role-Based Access Edge Casesโ
- reportData:
Non-Admin User Performance:
// Non-admin only sees their own metrics - Test role-based data access
if (role != 'admin') { - Test integration filtering
reportConditions.user_id = uid; - Test metric calculations
}
// Result: Single-rep report even if querying all reps2. **reportFilters**:
- Test filter generation with data
Admin with User_ID Filter: - Test empty data handling
// Admin can see specific rep performance
// user_id filter not automatically applied3. **reportReps**:
// Must explicitly filter by reps query param - Test pagination
``` - Test sorting by different fields
- Test role-based access (admin vs non-admin)
### Date Range Edge Cases - Test performance calculations
**No Date Range Provided**:### Integration Tests
- Defaults to all-time data
- Can be expensive on large datasets- Full report generation pipeline
- Consider requiring date range for performance- Cross-module data consistency (leads โ reports)
- Large dataset performance
**Invalid Date Formats**:- Concurrent report requests
- Model should validate ISO date format
- Invalid dates may result in empty results### Performance Tests
- Always validate dates before passing to model
- Report generation time for various date ranges
**Future Dates**:- Pagination performance with large rep counts
```javascript- Cache effectiveness
// startdate: '2026-01-01'- Database query optimization
// Result: Empty data set (no leads in future)
```---
### Aggregation Edge Cases## Security Considerations
**No Leads Found**:1. **Role-Based Access Control**:
```javascript
// Empty result sets - Admins see all account data
{ - Non-admins only see their assigned leads
total_leads: 0, - No cross-account data leakage
date_breakdown: [],
by_integration: [],2. **Data Privacy**:
by_rep: []
} - Reports aggregate data (no PII in summaries)
// Valid response, not an error - Individual lead details require separate endpoint access
``` - Rep names/emails sanitized in public leaderboards
**Representative with No Leads**:3. **Query Injection**:
- Rep won't appear in reportReps results
- Only reps with at least 1 assigned lead included - All parameters validated
- Empty arrays for reps with no activity in date range - MongoDB ObjectIds properly constructed
- Date strings validated before use
**Division by Zero (Conversion Rate)**:
```javascript4. **Rate Limiting**:
// Rep has 0 leads assigned - Consider rate limiting expensive report queries
conversion_rate = (0 / 0) * 100; // NaN - Implement request queuing for large date ranges
// Handle with $cond in aggregation:
{---
$cond: [
{ $eq: ['$leads_assigned', 0] },## Best Practices
0,
{ $multiply: [{ $divide: ['$contacted', '$assigned'] }, 100] }### For Frontend Developers
]
}1. **Default Date Ranges**:
### Sorting Edge Cases// Use common ranges for better caching
const dateRanges = {
**Invalid Sort Field**: today: { start: startOfDay(), end: now() },
- Model should default to 'count' if invalid last_7_days: { start: subtract(7, 'days'), end: now() },
- Prevents MongoDB aggregation errors last_30_days: { start: subtract(30, 'days'), end: now() },
this_month: { start: startOfMonth(), end: now() },
**Ties in Sorting**:};
```javascript```
// Multiple reps with same lead count
// Secondary sort by name for consistency2. **Progressive Loading**:
{ $sort: { count: -1, 'user.first_name': 1 } }
``` - Load summary metrics first (fast)
- Load detailed breakdowns on demand
### Pagination Edge Cases - Use skeleton loaders for better UX
**Page Out of Bounds**:3. **Caching Strategy**:
```javascript
// page=100 but only 5 total pages - Cache common reports client-side
// Result: Empty array with valid pagination - Invalidate on new lead creation
{ - Use stale-while-revalidate pattern
data: [],
pagination: { page: 100, total_pages: 5, has_next: false }4. **Chart Optimization**:
} - Limit data points for trend charts (max 90 days)
``` - Aggregate to weekly/monthly for longer ranges
- Use data decimation for performance
**Limit = 0 or Negative**:
- Should validate and set minimum limit (e.g., 1)---
- Or return 400 error for invalid limit
**Last Updated**: October 2025
## โ ๏ธ Important Notes**Status**: Production Ready
**Complexity**: LOW-MEDIUM
1. **Role-Based Filtering**: All report functions enforce account_id scoping. Non-admin users see only metrics for leads assigned to them. Admin users see all account metrics. Always validate role before querying.
2. **Date Range Performance**: Reports without date ranges can be expensive on large datasets. Consider requiring date ranges or implementing pagination for all-time reports. Pre-compute daily/weekly reports for large accounts.
3. **Aggregation Indexes**: Ensure compound indexes on frequently aggregated fields: `{account_id: 1, user_id: 1, created_at: 1, integration: 1, freshness: 1}`. Missing indexes cause full collection scans.
4. **Conversion Rate Calculation**: Conversion rate based on lead freshness status (new โ contacted โ converted). Division by zero handled in aggregation. NaN values indicate no assigned leads.
5. **Representative Performance**: Only reps with assigned leads appear in results. Reps with zero leads excluded from reportReps. This is intentional - empty metrics not useful for leaderboards.
6. **Default Sorting**: reportReps defaults to sorting by lead count descending (top performers first). Always specify sort and order for consistent results across requests.
7. **Pagination Required**: reportReps requires pagination to prevent overwhelming responses with many representatives. Always use limit parameter. Default page size should be reasonable (20-50).
8. **Filter Pre-Application**: reportFilters accepts pre-applied filters to narrow subsequent filter options. This creates dynamic filter UI where selections affect remaining options.
9. **Time-Series Granularity**: date_breakdown groups by day. For longer date ranges, consider grouping by week or month to reduce data points and improve performance.
10. **Cache Considerations**: Report data changes frequently but not real-time. Consider caching for 5-15 minutes to reduce database load. Invalidate cache on lead creation/update.
## ๐ Related Documentation
- [Leads Service](./leads.md) - Lead data source for reports
- [Campaigns Service](./campaigns.md) - Campaign association
- [Webhooks Service](./webhooks.md) - Lead capture affecting metrics
- Pagination Utility *(link removed - file does not exist)* - Pagination helper
- [Analytics Module](../analytics/overview.md) - Cross-module analytics