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.
Code Review
Main App
20 days ago
Linear
Get notified by email when there are changes.
Code Review
Main App
20 days ago
Linear
Get notified by email when there are changes.