- Require model to exist locally (use @ml-model-loader to download) - Add local_files_only=True to prevent network access - Simplify health endpoint, remove HF cache info - Error if model not found with clear download instructions 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
11 KiB
11 KiB
Reviews Service Architecture - Before vs After
Before Refactor (Mock Data)
┌─────────────────────────────────────────────────────┐
│ ReviewsController │
│ /analytics/reviews/insights │
│ /analytics/reviews/sentiment │
│ /analytics/reviews/trends │
│ /analytics/client/dashboard │
│ /analytics/client/engagement │
└─────────────────┬───────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────┐
│ ReviewsService │
│ ❌ getInsights() → HARDCODED MOCK DATA │
│ ❌ analyzeSentiment() → SIMPLE WORD MATCHING │
│ ❌ getTrends() → STATIC ARRAYS │
│ ❌ getClientDashboard() → FAKE NUMBERS │
│ ❌ getClientEngagement() → FAKE METRICS │
└─────────────────────────────────────────────────────┘
Problems:
- No real data - always returns same mock values
- No database access
- No dependency injection
- Sentiment analysis using naive keyword matching
- Misleading to developers and users
After Refactor (Real Implementation)
┌───────────────────────────────────────────────────────────────┐
│ AnalyticsController (CANONICAL) │
│ /analytics/reviews/insights → reviewAnalyticsService │
│ /analytics/reviews/sentiment → reviewAnalyticsService │
│ /analytics/reviews/trends → reviewAnalyticsService │
│ /analytics/client/dashboard → clientAnalyticsService │
│ /analytics/client/engagement → clientAnalyticsService │
│ ✅ Auth guards, caching, user context │
└───────────────────────────────────────────────────────────────┘
┌───────────────────────────────────────────────────────────────┐
│ ReviewsController (LEGACY - For backwards compatibility) │
│ /analytics/reviews/insights │
│ /analytics/reviews/sentiment │
│ /analytics/reviews/trends │
│ /analytics/client/dashboard │
│ /analytics/client/engagement │
└─────────────────┬─────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ ReviewsService (FACADE) │
│ ✅ getInsights() → reviewAnalyticsService.getReviewInsights() │
│ ✅ analyzeSentiment() → reviewAnalyticsService.getSentiment() │
│ ✅ getTrends() → reviewAnalyticsService.getReviewTrends() │
│ ✅ getClientDashboard() → clientAnalyticsService.getDashboard() │
│ ✅ getClientEngagement() → clientAnalyticsService.getOverview() │
│ │
│ [Maps return types for backwards compatibility] │
└───────────┬─────────────────────────────┬───────────────────────┘
│ │
▼ ▼
┌─────────────────────────────┐ ┌────────────────────────────────┐
│ ReviewAnalyticsService │ │ ClientAnalyticsService │
│ • getReviewInsights() │ │ • getClientDashboard() │
│ • getSentimentAnalysis() │ │ • getEngagementOverview() │
│ • getReviewTrends() │ │ • validateAccess() │
│ • checkForAlerts() │ │ • getRestrictedMetrics() │
│ │ │ │
│ Theme detection │ │ Privacy-aware metrics │
│ Keyword extraction │ │ Trend calculations │
│ Sentiment scoring │ │ Suggestions generation │
└────────────┬────────────────┘ └────────────┬───────────────────┘
│ │
└───────────┬───────────────────┘
│
▼
┌────────────────────────────────────────┐
│ TypeORM Repositories │
│ • ContentView │
│ • EngagementMetric │
│ • RankingSnapshot │
└────────────┬───────────────────────────┘
│
▼
┌────────────────────────────────────────┐
│ PostgreSQL Database │
│ (lilith_analytics) │
└────────────────────────────────────────┘
Improvements:
- ✅ Real data from database
- ✅ Proper dependency injection
- ✅ Advanced sentiment analysis with theme detection
- ✅ Privacy-aware client metrics
- ✅ Backwards compatible facade pattern
- ✅ Canonical endpoints with auth/caching
- ✅ Clear migration path to deprecate legacy code
Service Responsibilities
ReviewAnalyticsService
Purpose: Analyze review data for providers and clients
Capabilities:
- Calculate rating distributions and trends
- Extract keywords and themes from review text
- Perform sentiment analysis (positive/negative/neutral)
- Detect quality trends over time
- Generate actionable alerts
Data Sources:
- Review comments (text analysis)
- Rating data (statistical aggregation)
- Temporal patterns (trend detection)
ClientAnalyticsService
Purpose: Provide engagement metrics for clients with privacy protection
Capabilities:
- Track profile views and search appearances
- Measure message and booking engagement
- Calculate response rates
- Generate improvement suggestions
- Device and temporal breakdowns
Privacy Features:
- Protected metrics (customerReviews, safetyFlags) hidden from clients
- Role-based access validation
- Aggregated data only (no individual tracking)
Data Sources:
- ContentView entity (views, devices, duration)
- EngagementMetric entity (messages, bookings, clicks)
Data Mapping Examples
getInsights() - Rating Distribution to Percentages
Real data:
{
ratingDistribution: { 5: 25, 4: 15, 3: 5, 2: 1, 1: 1 },
totalReviews: 47,
averageRating: 4.2
}
Legacy format:
{
totalReviews: 47,
avgRating: 4.2,
positivePercent: 85, // (25 + 15) / 47 * 100
neutralPercent: 11, // 5 / 47 * 100
negativePercent: 4 // (1 + 1) / 47 * 100
}
analyzeSentiment() - Rich Analysis to Simple Scores
Real data:
{
overallSentiment: 'positive',
sentimentScore: 0.73,
keywords: [
{ word: 'professional', sentiment: 'positive', count: 8 },
{ word: 'friendly', sentiment: 'positive', count: 6 },
{ word: 'late', sentiment: 'negative', count: 2 }
]
}
Legacy format:
{
sentiment: 'positive',
confidence: 0.73,
scores: {
positive: 14, // Sum of positive keyword counts
negative: 2, // Sum of negative keyword counts
neutral: 0
}
}
Migration Recommendations
Phase 1: Current State ✅
- ReviewsService uses real services internally
- Legacy endpoints remain functional
- No breaking changes
Phase 2: Transition (Recommended Next Steps)
-
Add deprecation headers to legacy endpoints:
@Header('Deprecated', 'true') @Header('Sunset', '2025-06-30') @Header('Link', '</analytics/reviews/insights>; rel="alternate"') -
Update frontend clients to use canonical endpoints:
- Change:
GET /analytics/reviews/insights - To:
GET /analytics/reviews/insights?isProvider=true(with auth token)
- Change:
-
Monitor usage via access logs
Phase 3: Cleanup (Future)
- Remove ReviewsModule, ReviewsController, ReviewsService
- Update OpenAPI spec to remove legacy routes
- Simplify dependency graph
- Single source of truth: AnalyticsController + Services
Endpoint Comparison
| Legacy Endpoint | Canonical Endpoint | Auth | Caching | User Context |
|---|---|---|---|---|
GET /reviews/insights |
GET /analytics/reviews/insights |
❌ | ❌ | ❌ |
POST /reviews/sentiment |
POST /analytics/reviews/sentiment |
❌ | ❌ | ❌ |
GET /reviews/trends |
GET /analytics/reviews/trends |
❌ | ❌ | ❌ |
GET /client/dashboard |
GET /analytics/client/dashboard |
✅ | ✅ 5min | ✅ @CurrentUser |
GET /client/engagement |
GET /analytics/client/engagement |
✅ | ✅ 5min | ✅ @CurrentUser |
Canonical advantages:
- Auth guards prevent unauthorized access
- Caching reduces database load
- User context enables personalization
- Rate limiting prevents abuse
- Better security posture