Validate and fix online scheduler close-rate date attribution

Objective

  • Validate, lock, and implement the date-attribution rules for online scheduler close rate so the Online / Self-Booked row on the Client Care Dashboard matches how stakeholders expect cohort reporting to work.
  • Resolve mismatches where the displayed close rate, # Created, and related counts do not reconcile with exports or sanity checks — especially for abandoned online scheduler quotes and timezone-scoped date ranges.
  • Track this separately from prior dashboard timezone and date-type work (ATT-1701, ATT-1809) so remaining online close-rate logic questions are resolved explicitly rather than folded into unrelated fixes.

Background

  • The Client Care Dashboard scheduler table (GET /cc-dashboard/scheduler-metrics) includes an aggregate Online / Self-Booked row (onlineScheduler in ccDashboard.ts), rendered in EmployeeTable.tsx as "Online / Self-Booked" with Close Rate, # Created, and # Confirmed.
  • Close rate formula (online row mirrors CSR schedulers): confirmed / (created inspections + open online quotes), where created = non-cancelled online inspections (scheduledBy: null) in the selected date range, and open quotes = online quotes with no linked inspection that count toward the denominator.
  • Current online open-quote query (as of today) dates each status on an outcome timestamp, not uniformly on createdAt:
  • pendingcreatedAt
  • rejectedrejectedAt
  • abandonedabandonedAt
  • Inline code comments note this outcome-based filter was added so rejected/abandoned quotes abandoned or rejected within the range are counted — addressing a prior gap vs the Tools dashboard Booking Channel Split widget (dashboard.ts + computeInternalVsOnline.ts), which uses rejectedAt for rejected quotes but does not include abandoned quotes in close-rate math.
  • By contrast, the main CC GET /metrics close-rate quote portion uses createdAt only for pending + rejected open quotes (no abandoned status in that query).
  • Inspection date basis on the CC dashboard is controlled by the Date Type filter (ATT-1809 Done): dateType=booked (default) uses scheduledTs (fallback datetime); dateType=inspection uses appointment datetime. Quotes in CC metrics comments say attribution stays on createdAt in both modes — but the online-scheduler open-quote branch currently overrides that for rejected/abandoned.
  • On the June 16 implementation call, the team raised that online scheduler close rate should use a created-date reporting window, and abandoned orders should likely count from their original createdAt, not abandonedAt, when measuring close rate.
  • Timezone: CC routes already resolve range boundaries per company via buildCompanyTzRanges / TZDayjs (same pattern as main dashboard after ATT-1701). Residual mismatches may still come from which date field is filtered, not only boundary math.
  • Online scheduler drafts auto-abandon after inactivity (draftAbandonmentWorker.ts sets status: 'abandoned' + abandonedAt). CSRs can resume abandoned quotes to pending; abandonedAt may remain set (ATT-1716 Backlog covers durable "started as abandoned" origin reporting — adjacent but separate).
  • No attachments, linked documents, or inline media on this ticket.

Product Decisions

Locked

(None yet — June 16 call surfaced direction; validation required before locking.)

Open

  1. Created-date cohort scope — Does "reporting window based on created date" apply to all online open-quote statuses in the denominator (pending, rejected, abandoned), or abandoned only while rejected keeps rejectedAt?
  2. Abandoned attribution — Confirm abandoned quotes with no linked inspection enter the denominator when createdAt falls in range (even if abandonedAt is later), including quotes later revived to pending/accepted that still carry abandonedAt.
  3. Inspection half of online row — Keep Date Type filter semantics (booked vs inspection) for confirmed/created inspections, or force a single date basis for the entire online close-rate row?
  4. Surface alignment — Fix CC Dashboard online row only, or also align Tools dashboard Booking Channel Split (InternalVsOnlineSplit.tsx / dashboard.ts) and/or GET /cc-dashboard/metrics top-level close rate?
  5. Quote statuses in denominator — Include on_hold online quotes? Exclude draft only (current behavior)? Any role for archived?
  6. Numerator definition — Confirmed = online inspections only (scheduledBy: null, status confirmed), or also accepted online quotes without a booked inspection?
  7. Validation / done criteria — What is the sign-off artifact (written formula doc, automated tests, manual reconciliation against a named export/report for a specific brand + date range)?
  8. Relationship to ATT-1716 — Is changing date attribution sufficient for v1, or does close rate also require a persisted "started as abandoned" origin flag before numbers are trusted?

Scope

Backend (attik-backend)

  • Primary touchpoint: src/routes/ccDashboard.tsGET /scheduler-metrics online open-quote query (~lines 1073–1091) and onlineOpenQuoteCount aggregation (Step 5b); computeRates() close-rate math for onlineScheduler.
  • Related reference implementations: GET /metrics open-quote filter (uses createdAt for pending/rejected); src/routes/dashboard.ts rejected-quote aggregation (rejectedAt range) and src/util/functions/dashboard/computeInternalVsOnline.ts for Booking Channel Split close percentages.
  • Quote model fields: quoteSchema.tscreatedType: 'online', status, createdAt, abandonedAt, rejectedAt, _finalInspectionId.
  • Timezone helpers: src/util/functions/dashboard/companyTzRanges.tstzScopedDateFieldOr used for quote date filters.
  • Out of scope unless Open #4 expands: Broad CC dashboard refactors unrelated to online close-rate date attribution.

Frontend (attik-frontend)

  • Client Care Dashboard: src/app/admin/client-care-dashboard/_components/EmployeeTable.tsx displays onlineScheduler metrics; likely no UI change unless product adds explanatory copy/tooltips for date basis after logic is locked.
  • Tools dashboard: src/components/dashboard/InternalVsOnlineSplit/InternalVsOnlineSplit.tsx — only in scope if product decides to align Booking Channel Split (Open #4).

Out of scope (unless product expands Open decisions)

  • ATT-1716 durable abandoned-origin dimension (separate backlog issue).
  • PostHog scheduler funnel analytics (ATT-1944).
  • CSR scheduler row open-quote logic (already createdAt-based; excludes abandoned today).

References

  • ATT-1809 — CC Dashboard Date Type filter (Done)
  • ATT-1701 — Dashboard timezone fix (Done)
  • ATT-1270 — Scheduler close rate / created column alignment (Done)
  • ATT-1716 — Started-as-abandoned origin reporting (Backlog, adjacent)
  • ATT-1095 — CC close-rate metrics spec (Done)
  • Backend: attik-backend/src/routes/ccDashboard.ts, attik-backend/src/util/functions/dashboard/computeInternalVsOnline.ts
  • Frontend: attik-frontend/src/app/admin/client-care-dashboard/_components/EmployeeTable.tsx

Please authenticate to join the conversation.

Upvoters
Status

Planned

Board
🏠

Main App

Date

1 day ago

Author

Linear

Subscribe to post

Get notified by email when there are changes.