Weekly Lead History Aggregator
The Weekly Lead History Aggregator is a scheduled background job that collects and compiles lead activity data at the end of each week. This data powers historical reports, trend analysis, and hierarchical performance tracking across the organization.
Overview
The WeeklyLeadHistoryScheduler runs every Tuesday morning at 6:00 AM to aggregate the previous week's lead data. It rolls up metrics from individual telecallers through the entire management hierarchy, creating a comprehensive historical record.
Key Characteristics
- Fixed Schedule: Tuesday 6:00 AM (weekly snapshot)
- Historical Lookback: Analyzes 7 days of activity
- Hierarchical Rollup: Aggregates from TC → BDO → Senior Manager → GM → AVP
- Comprehensive Metrics: Tracks 12+ key performance indicators
- Non-blocking: Runs asynchronously to avoid impacting production
Schedule Configuration
Cron Expression Details
Cron: 0 0 6 ? * TUE
Field Breakdown:
┌─────────────┬─────────────────────────────────────┐
│ Field │ Value & Meaning │
├─────────────┼─────────────────────────────────────┤
│ Seconds │ 0 (at 00 seconds) │
│ Minutes │ 0 (at 00 minutes = top of hour) │
│ Hours │ 6 (6:00 AM) │
│ Day of Month│ ? (no specific date) │
│ Month │ * (every month) │
│ Day of Week │ TUE (Tuesday only) │
└─────────────┴─────────────────────────────────────┘
Frequency: Once per week (every Tuesday at 6 AM)
Purpose: Weekend review, Monday planning preparationData Collection Pipeline
Hierarchical Aggregation
The system aggregates data from bottom-up through the organizational hierarchy:
Metrics Tracked Per Week
The scheduler collects and calculates the following metrics for each staff member at each hierarchy level:
Core Volume Metrics
| Metric | Calculation | Example |
|---|---|---|
| NewLeadsAssigned | COUNT(LeadId) WHERE Status IN (NEW, IN_PROGRESS) | 42 leads |
| SVFixed | COUNT(LeadId) WHERE Status = 'SV_FIXED' | 8 leads |
| CallProgress | COUNT(LeadId) WHERE Status = 'CP' | 12 leads |
| Trashed | COUNT(LeadId) WHERE Status = 'TRASHED' | 5 leads |
| NoResponse | COUNT(LeadId) WHERE Status = 'NO_RESPONSE' | 17 leads |
Conversion & Efficiency Metrics
| Metric | Formula | Purpose |
|---|---|---|
| ConversionRate | (SVFixed / NewLeadsAssigned) × 100 | % successful closure |
| ActivityRate | (CallProgress + SVFixed) / NewLeadsAssigned × 100 | % actively engaged |
| WasteRate | Trashed / NewLeadsAssigned × 100 | % dead/invalid leads |
| FollowupCreated | COUNT(FollowupCalls) WHERE ReviewDateTime in week | # follow-ups needed |
| FollowupCompleted | COUNT(FollowupCalls) WHERE IsCompleted = 1 in week | # follow-ups done |
| FollowupCompletionRate | (FollowupCompleted / FollowupCreated) × 100 | Follow-up adherence |
Response Time Metrics
| Metric | Calculation | Insight |
|---|---|---|
| AvgResponseTime | AVG(DATEDIFF(hour, CreatedDate, FirstCallDate)) | Call speed |
| MedianResponseTime | PERCENTILE_CONT(0.5) of response times | Typical turnaround |
| SameDataCallRate | COUNT(LeadId) WHERE FirstCallDate same day as CreatedDate / Total | Urgency response |
Aggregation Formulas
Execution Sequence Diagram
SQL Query Example: TC-Level Aggregation
-- Collect metrics for single telecaller for past week
DECLARE @WeekStart DATETIME = DATEADD(DAY, -7, CAST(GETDATE() as DATE));
DECLARE @WeekEnd DATETIME = CAST(GETDATE() as DATE);
DECLARE @StaffId INT = 1234;
SELECT
@StaffId as StaffId,
@WeekStart as WeekStartDate,
COUNT(DISTINCT el.LeadId) as NewLeadsAssigned,
COUNT(DISTINCT CASE WHEN el.Status = 'SV_FIXED' THEN el.LeadId END) as SVFixed,
COUNT(DISTINCT CASE WHEN el.Status = 'CP' THEN el.LeadId END) as CallProgress,
COUNT(DISTINCT CASE WHEN el.Status = 'TRASHED' THEN el.LeadId END) as Trashed,
COUNT(DISTINCT CASE WHEN el.Status = 'NO_RESPONSE' THEN el.LeadId END) as NoResponse,
COUNT(DISTINCT fc.FollowupId) as FollowupCreated,
COUNT(DISTINCT CASE WHEN fc.IsCompleted = 1 THEN fc.FollowupId END) as FollowupCompleted,
-- Conversion Rate
CAST(
COUNT(DISTINCT CASE WHEN el.Status = 'SV_FIXED' THEN el.LeadId END)
as FLOAT
) / NULLIF(COUNT(DISTINCT el.LeadId), 0) * 100 as ConversionRate,
-- Follow-up Completion Rate
CAST(
COUNT(DISTINCT CASE WHEN fc.IsCompleted = 1 THEN fc.FollowupId END)
as FLOAT
) / NULLIF(COUNT(DISTINCT fc.FollowupId), 0) * 100 as FollowupCompletionRate,
-- Average Response Time (hours)
AVG(CAST(DATEDIFF(HOUR, el.CreatedDate, cl.CallDate) as FLOAT)) as AvgResponseHours
FROM ExternalLeads el
LEFT JOIN CallLog cl ON el.LeadId = cl.LeadId
AND cl.CallDate = (SELECT MIN(CallDate) FROM CallLog WHERE LeadId = el.LeadId)
LEFT JOIN FollowupCalls fc ON el.LeadId = fc.LeadId
WHERE el.StaffId = @StaffId
AND (el.CreatedDate BETWEEN @WeekStart AND @WeekEnd
OR el.ModifiedDate BETWEEN @WeekStart AND @WeekEnd)SQL Query Example: Rollup to Manager Level
-- Aggregate all assigned TCs to manager level
DECLARE @WeekStart DATETIME = DATEADD(DAY, -7, CAST(GETDATE() as DATE));
DECLARE @ManagerId INT = 5678;
SELECT
@ManagerId as ManagerId,
'BDO' as HierarchyLevel,
@WeekStart as WeekStartDate,
SUM(wlh.NewLeadsAssigned) as TotalNewLeads,
SUM(wlh.SVFixed) as TotalSVFixed,
SUM(wlh.CallProgress) as TotalCallProgress,
SUM(wlh.Trashed) as TotalTrashed,
SUM(wlh.NoResponse) as TotalNoResponse,
-- Team Conversion Rate
CAST(SUM(wlh.SVFixed) as FLOAT) / NULLIF(SUM(wlh.NewLeadsAssigned), 0) * 100 as TeamConversionRate,
-- Team Follow-up Completion
CAST(SUM(wlh.FollowupCompleted) as FLOAT) / NULLIF(SUM(wlh.FollowupCreated), 0) * 100 as TeamFollowupRate,
-- Average Response Time (weighted)
AVG(wlh.AvgResponseHours) as AvgTeamResponseHours
FROM WeeklyLeadHistory wlh
INNER JOIN TeleLeaderMapping tlm ON wlh.StaffId = tlm.StaffId
WHERE tlm.LeaderId = @ManagerId
AND tlm.IsActive = 1
AND wlh.HierarchyLevel = 'Telecaller'
AND wlh.WeekStartDate = @WeekStart
GROUP BY @ManagerId, 'BDO', @WeekStartWeeklyLeadHistory Table Schema
Data Retention & Archival
Historical data is maintained according to this retention policy:
| Period | Retention | Action |
|---|---|---|
| Current & Previous 12 weeks | Online (Hot) | Live queries, real-time dashboards |
| 13 weeks to 2 years | Archive (Warm) | Annual reviews, trend analysis |
| 2+ years | Long-term storage | Compliance & audit only |
Error Handling & Monitoring
public async Task Execute(IJobExecutionContext context)
{
var stopwatch = Stopwatch.StartNew();
var recordsProcessed = 0;
try
{
// Prevent concurrent execution
if (await _lockService.IsLocked("WeeklyAggregation"))
{
_logger.LogWarning("Weekly aggregation already running, skipping");
return;
}
await _lockService.Lock("WeeklyAggregation");
var weekStart = GetWeekStart();
var weekEnd = GetWeekEnd();
// Phase 1: Collect data
var leads = await _db.ExternalLeads
.Where(l => l.CreatedDate >= weekStart && l.CreatedDate <= weekEnd)
.ToListAsync();
recordsProcessed = leads.Count;
// Phase 2: Aggregate by staff
var staffMetrics = AggregateByStaff(leads);
// Phase 3: Rollup hierarchy
var hierarchyMetrics = RollupHierarchy(staffMetrics);
// Phase 4: Store results
await _db.WeeklyLeadHistory.AddRangeAsync(hierarchyMetrics);
await _db.SaveChangesAsync();
stopwatch.Stop();
_logger.LogInformation(
$"Weekly aggregation completed: {recordsProcessed} leads processed " +
$"in {stopwatch.ElapsedMilliseconds}ms");
context.JobDetail.JobDataMap.Put("Status", "SUCCESS");
context.JobDetail.JobDataMap.Put("RecordsProcessed", recordsProcessed);
}
catch (Exception ex)
{
_logger.LogError($"Weekly aggregation failed: {ex}");
context.JobDetail.JobDataMap.Put("Status", "FAILED");
context.JobDetail.JobDataMap.Put("Error", ex.Message);
throw;
}
finally
{
await _lockService.Unlock("WeeklyAggregation");
}
}Integration Points
The weekly data feeds into:
- Executive Dashboard: AVP-level metrics for strategic planning
- Forecasting Models: Historical trends for capacity planning
- Compensation: Performance bonuses based on conversion rates
- Compliance Reports: Call attempt documentation
- Training Programs: Identifying performance patterns