Add a toggle on the Employee Performance scheduler stats table (Client Care Dashboard) so users can switch close-rate attribution between:
inspection.scheduledBy.Quote._finalInspectionId), credit close components to quote.createdBy; if no linked quote, fall back to scheduledBy.This lets CC leadership compare “who booked the job” vs “who originated the quote/lead” without changing revenue, upsell, cancel, or other non-close columns unless product decides otherwise.
Backend: GET /cc-dashboard/scheduler-metrics in apps/backend/src/routes/ccDashboard.ts
(scheduledBy, _companyId) for revenue, created, confirmed, upsell, cancel, add-on, etc.quote.createdBy → user mapping (Steps 5–5b).scheduledBy; orphan open quotes → createdBy.Frontend: EmployeeTable.tsx renders the table inside DashboardBlock; filters live in the controller slot (Online Scheduler checkbox + scheduler multi-select). Data fetched from CCDashboardClient.tsx via cc-dashboard/scheduler-metrics.
Data model:
cc_inspection_base view exposes scheduledBy but not quote linkage (createCcDashboardViews.ts).Quote._finalInspectionId ↔ inspection _id; quote originator: Quote.createdBy.Add closeAttribution=scheduledBy|quoteCreator (default scheduledBy) to GET /cc-dashboard/scheduler-metrics.
When closeAttribution=quoteCreator, re-attribute close-related fields only:
closeRateordersCreated (denominator basis)ordersConfirmed (numerator)Keep on scheduledBy (unless product expands scope): revenue, averageFee, upsellRate, oneCallCloseRate, selectedAddOnRate, cancel columns, # Core Confirmed.
Recommended approach (no view migration required):
scheduledBy aggregation for non-close metrics.closeAttribution=quoteCreator:$match same date/status filters as main query.$lookup quotes on { localField: '_id', foreignField: '_finalInspectionId', as: 'quote' }.$addFields: closeAttributionEmp: { $ifNull: [{ $arrayElemAt: ['$quote.createdBy', 0] }, '$scheduledBy'] }.$group by (closeAttributionEmp, _companyId) summing only created (non-cancelled), confirmed, and cancelled counts needed for close math.mergedMap by resolved userId (same employeeToUser / membership mapping as today).createdBy) — already matches Quote Creator mode.Online Scheduler row: clarify product rule when scheduledBy is null but a linked quote has createdBy — likely move those counts off the Online row onto the quote creator’s row.
EmployeeTable controller (alongside Online Scheduler / All Schedulers), e.g. segmented control:CCDashboardClient.tsx → fetchSchedulerMetrics params.dateType).scheduledBy only).Follow dateType / globalCategoryMatch pattern:
closeAttribution to @attik/types/ccDashboardView.types, DB model, saved-view API, and save payload in CCDashboardClient.scheduledBy: null) with internal quote creator — counts leave Online Scheduler row?createdBy is missing — confirm fallback to scheduledBy.# Created still matches close-rate denominator in both modes.Backend
apps/backend/src/routes/ccDashboard.ts — param parsing, close-only re-aggregation, merge logicFrontend
apps/frontend/src/app/admin/client-care-dashboard/_components/EmployeeTable.tsx — toggle UIapps/frontend/src/app/admin/client-care-dashboard/CCDashboardClient.tsx — state + fetch paramapps/frontend/src/app/admin/client-care-dashboard/_types.ts — type for paramcreatedBy (mapped to user via membership); unlinked inspections still use scheduledBy.createdBy in both modes.# Confirmed / # Created remains internally consistent per row in both modes.Please authenticate to join the conversation.
Planned
Main App
About 4 hours ago
Linear
Get notified by email when there are changes.
Planned
Main App
About 4 hours ago
Linear
Get notified by email when there are changes.