# Lifecycle Insights Feature Replacement — Pulse Design Doc > **Purpose**: Document how Lifecycle Insights (LCI) works across the four target features — Warranty, Assessments, Budget Forecast, and QBR/Business Reviews — so we can build equivalent functionality in Pulse, using Autotask (and Datto RMM) as the primary data source. > > **Reference client**: Hynes Industries (321 assets, multiple locations) > **Source tool**: app.lifecycleinsights.io > **Date captured**: 2026-03-16 --- ## 1. Asset List & Warranty ### What LCI Shows **Summary banner** (top of Asset List page): - Total Assets: 321 - **EOL Status** breakdown: - 104 Good Standing - 60 Approaching EOL - 6 Past EOL - 151 Unknown - **OS Status** breakdown: - 177 Supported - 27 Not Supported - 117 Unknown - **Warranty Status** breakdown: - 91 Under Warranty - 20 Approaching Warranty Expiration (within ~90 days) - 97 Expired Warranty - 113 Unknown **Per-asset table columns**: | Column | Example | |--------|---------| | Device Name | YNGHYNLT030 | | Status | Active / Retired / Hidden | | Last User (RMM) | HYNES\shopfloor | | Location | Youngstown (Main) / Painesville (Branch) / Kokomo (Branch) | | Type | Workstation / Hypervisor Host / Network Device | | Make | Dell / Lenovo | | Model | Latitude 5591 / ThinkSystem SR630 | | Serial Number | 2KNXWT2 | | Operating System | Microsoft Windows 10 Pro 10.0.19044 | | Purchase Date | 04-23-2019 | | Warranty Expiration | 04-24-2023 | | End of Life | 04-23-2024 | | Replacement Cost | $3,000 | | Age (years) | 6.9 | **Table features**: - Sortable columns (click header) - Filter buttons: Show Only NON Hidden / Duplicate / Hidden / All Assets - Duplicate detection badge - Pagination (321 rows, 25/50/75/100/200 per page) - Search box **Warranty status logic** (inferred): - **Under Warranty**: warranty expiration date > today - **Approaching**: warranty expiration within ~90 days - **Expired**: warranty expiration date < today - **Unknown**: no warranty expiration date on record **EOL logic** (inferred): - EOL date is OS/hardware specific (LCI maintains a lookup table — shown on dashboard) - **Good Standing**: EOL date > today + threshold (~1 year) - **Approaching EOL**: EOL date within ~1 year - **Past EOL**: EOL date < today - **Unknown**: no EOL date derivable ### Data Sources - **Device inventory**: comes from RMM (Datto RMM in Hynes's case) — device name, make, model, serial, OS, last user, location - **Purchase/warranty dates**: can come from RMM or be manually entered - **EOL dates**: LCI maintains a global EOL lookup table by OS/software version (visible on dashboard — e.g., "Windows 10 Pro: 10-14-2025") - **Replacement cost**: manually set per asset type, or inherited from category defaults - **Locations**: mapped from RMM site groupings ### Pulse Implementation Notes **Data model** (new migration needed): ```sql -- assets table (core) asset_id, autotask_id, datto_rmm_uid, device_name, status, last_user, location_id, asset_type, make, model, serial_number, os_name, os_version, purchase_date, warranty_expiry_date, eol_date, replacement_cost, age_years, company_id (FK → companies), is_hidden, is_duplicate, created_at, updated_at, last_synced_at -- eol_reference table (global) software_name, eol_date -- asset_locations table location_id, company_id, location_name ``` **Warranty status computed field**: ```ts function warrantyStatus(expiryDate: Date | null): 'under' | 'approaching' | 'expired' | 'unknown' { if (!expiryDate) return 'unknown'; const daysUntil = differenceInDays(expiryDate, new Date()); if (daysUntil < 0) return 'expired'; if (daysUntil <= 90) return 'approaching'; return 'under'; } ``` **Autotask as source**: Autotask has a Configuration Items module that maps to devices. Datto RMM syncs device details into Autotask CIs. Fields available via Autotask API: `warrantyExpirationDate`, `purchaseOrderNumber`, `purchaseDate`, `installDate`, `serialNumber`, `referenceNumber`, manufacturer, product (model), location, deviceType. --- ## 2. Budget Forecast ### What LCI Shows **Purpose**: Project technology spend for the next 6–8 quarters, broken into categories. **Views**: 1. **Detail View** — collapsible sections per time period, category breakdown 2. **Spreadsheet View** — bar chart + grid with rows per category, columns per quarter 3. **Budget Board** — (not fully captured; likely a Kanban/card layout) **Filters available**: - Location (site filter) - Asset Type - Asset Status - "Generate Budget Forecast as of" date (defaults to today; can run future projections) **Time buckets**: - Overdue (past-due items) - Recommendations Not Scheduled (approved recommendations with no date) - Then rolling quarters: e.g., Jan-Mar 2026, Apr-Jun 2026, Jul-Sep 2026, etc. (6–8 quarters shown) **Categories**: | Category | What it represents | |----------|--------------------| | Workstation | Assets reaching EOL scheduled for replacement | | Hypervisor Host | Server/hypervisor assets reaching EOL | | Network Device | Network hardware replacements | | Contracts/Subscriptions | Contract renewals (from Autotask contracts) | | Recommendations | Open recommendations with cost + target date | **Hynes Industries example data** (Spreadsheet View): | Category | Overdue | Not Sched | Apr-Jun 26 | Jul-Sep 26 | Oct-Dec 26 | Jan-Mar 27 | Apr-Jun 27 | Total | |----------|---------|-----------|------------|------------|------------|------------|------------|-------| | Hypervisor Host | $22,500 | — | — | — | — | — | — | $22,500 | | Workstation | — | — | — | — | — | $18,000 | $21,000 | $39,000 | | Contracts/Subscriptions | — | — | $37,231 | $43,590 | $164,414 | $27,737 | $37,231 | $313,549 | | Recommendations | $254,754 | $107,000 | $31,245 | $15,045 | $29,795 | — | — | $437,839 | | **TOTAL** | **$277,254** | **$107,000** | **$68,476** | **$58,635** | **$194,209** | **$45,737** | **$58,231** | **$812,888** | ### How Each Category is Populated **Workstation / Hypervisor / Network Device**: - Source: assets with EOL date falling within the quarter - Cost: `replacement_cost` per asset - Scheduled quarter = quarter containing the asset's `eol_date` **Contracts/Subscriptions**: - Source: Autotask Contracts with `end_date` or renewal dates - Cost: contract value - Quarter = quarter of contract end/renewal date **Recommendations**: - Source: open Recommendations (see Recommendations module) - Cost: `estimated_cost` on the recommendation - Quarter = recommendation's `planned_date` (or "Not Scheduled" if no date) - "Overdue" = planned_date < today ### Pulse Implementation Notes **Budget Forecast is computed at query time** — no separate stored table needed beyond assets + contracts + recommendations with dates and costs. ```sql -- Pseudo-query for budget forecast SELECT quarter_bucket, category, COUNT(*) AS quantity, SUM(cost) AS budget_cost FROM ( -- EOL assets SELECT date_trunc('quarter', eol_date) AS quarter_bucket, asset_type AS category, replacement_cost AS cost FROM assets WHERE company_id = $1 AND eol_date IS NOT NULL AND status = 'active' UNION ALL -- Contracts SELECT date_trunc('quarter', end_date), 'Contracts/Subscriptions', contract_value FROM contracts WHERE company_id = $1 UNION ALL -- Recommendations SELECT date_trunc('quarter', COALESCE(planned_date, NULL)), 'Recommendations', estimated_cost FROM recommendations WHERE company_id = $1 AND status NOT IN ('Completed', 'Declined') ) combined GROUP BY quarter_bucket, category ORDER BY quarter_bucket; ``` **API route**: `GET /api/budget-forecast/[companyId]?asOf=DATE&location=X&assetType=Y` --- ## 3. Assessments ### What LCI Shows **Structure** (from Assessments Menu page): 1. **Assessment Events** — each time you run an assessment for a client = one "event" 2. **Assessment Templates** — define *what* you're measuring (items + categories) 3. **Assessment Items** — individual questions/checklist items 4. **Event Types** — classify events (e.g., baseline, annual review, gap assessment) 5. **Analytics by Customer** — score history, trends, category breakdowns 6. **Analytics All Customers** — cross-client comparison **Wulf Consulting uses**: "Wulf Consulting: Default Assessment" template **Hynes Industries history** (from dashboard): - Latest: completed 01-29-2025 (411 days ago) by Jake Hammel - Score type: "baseline assessment with a score of --" (baseline = no numeric score, just captures state) - Assessment Event Score History chart shows one data point at 2025-01 **Data Quality Scores** (dashboard, related to assessments): - EOL: 53/100 - Warranty: 65/100 - Make: 92/100 - Serial: 83/100 - Model: 95/100 - Overall: 67/100 ### Assessment Data Model (inferred) ``` AssessmentTemplate ├── id, name, company_id (MSP-level) ├── items[] → AssessmentItem │ ├── id, category, question_text, weight, scoring_type │ └── possible_scores: [0,1,2,3,4,5] or pass/fail └── event_type_config AssessmentEvent ├── id, template_id, client_id (company) ├── event_type (baseline / annual / gap) ├── completed_date, completed_by (technician) ├── overall_score (numeric or null for baseline) └── responses[] → AssessmentResponse ├── item_id, score, notes └── linked_recommendation_id (optional) AssessmentEventScore (for history/chart) ├── event_id, category, score, max_score ``` **Key behaviors**: - Templates are MSP-defined (not per-client) - One client can have many events over time (score history chart) - Assessment items can generate Recommendations (linked) - Scores tracked by category (enables radar/bar chart per category) - "Baseline" events don't produce a numeric score — they capture current state only ### Pulse Implementation Notes **Migration**: Create `assessment_templates`, `assessment_items`, `assessment_events`, `assessment_responses` tables. **Admin UI**: Template builder (drag-drop items into categories), Event runner (per-client form), Analytics view (score history chart per client). **Autotask link**: Assessment items that result in action → create Autotask ticket or recommendation. --- ## 4. Business Reviews / QBR ### What LCI Shows — FULLY CAPTURED **Page**: `Business Review Meetings for Hynes Industries` **Meeting table columns**: | Column | Values | |--------|--------| | Meeting Date | e.g., 03-03-2026 | | Meeting Type | Business Review / Virtual Meeting / (blank) | | Primary Contact | Ryan Day | | Account Manager | Jake Hammel | | Status | Completed / Scheduled / Auto-Scheduled / Preparation / Skipped/Cxl | | Notes | Rich text notes (Pre-Meeting / During Meeting / Post-Meeting sections) | | Recommendations | (linked recommendations column) | | Reports / Artifacts | (PDF download column) | | Delete | delete action | **Status types explained**: - **Completed** — meeting happened and notes are finalized - **Scheduled** — manually scheduled upcoming meeting - **Auto-Scheduled** — system automatically created this slot based on cadence - **Preparation** — notes are being drafted before meeting - **Skipped/Cxl** — meeting was skipped or cancelled **Cadence for Hynes**: Bi-weekly (every 2 weeks), Ryan Day as primary contact, Jake Hammel as account manager. Running since September 2023. **Notes structure** (rich text, per meeting): ``` Pre-Meeting: [prep notes, project status, talking points] Meeting / During Meeting: [live notes taken during call] Post-Meeting: [follow-up actions, decisions made] ``` **Real example notes** (from Hynes 09-19-2023): > "Follow up with Ryan on 2024 CAPX Budget... Updated Ryan that moving forward new workstations won't have the BitLocker Password Prompt... Amy Young - Executive Admin - Get her to view details on the Hynes conference room calendars..." **Scale**: Hynes has ~56 business review records from 09-2023 to 03-2026 (bi-weekly cadence = ~2/month × 30 months). The "47 overdue" from the dashboard is because many Auto-Scheduled meetings were never formally completed. **Filters on page**: - "Show Meetings with Date in Past" toggle **Actions**: - ADD NEW — create a new meeting record - Each row has: delete, reports/artifacts (PDF generation) ### Business Reviews Data Model (confirmed) ```sql business_reviews id, company_id, meeting_date DATE, meeting_type VARCHAR, -- 'Business Review', 'Virtual Meeting', etc. primary_contact_id INT, -- FK → contacts account_manager_id INT, -- FK → users (MSP staff) status VARCHAR, -- Completed/Scheduled/Auto-Scheduled/Preparation/Skipped-Cxl notes_pre_meeting TEXT, notes_during_meeting TEXT, notes_post_meeting TEXT, created_at, updated_at business_review_artifacts -- linked PDFs / reports id, business_review_id, artifact_type, file_url, created_at business_review_recommendations -- join table business_review_id, recommendation_id ``` **Key behaviors**: - System auto-generates meeting slots based on cadence (configurable per client) - Each meeting has pre/during/post note sections - Meetings can link to specific recommendations (show progress at meeting) - PDF reports can be attached or generated per meeting - "47 overdue" = count of Auto-Scheduled meetings with date in past and no Completed status - Agenda links (from dashboard widget) are separate from meeting notes — persistent links per client ### Pulse Implementation Notes **QBR = structured meeting log** with recurring cadence + notes + linked recommendations. - Auto-generate meeting slots via a cron job based on `meeting_cadence_days` per company - The "Overdue" count = `SELECT COUNT(*) FROM business_reviews WHERE company_id = $1 AND meeting_date < NOW() AND status != 'Completed'` - PDF generation: render current EOL health + budget + recommendations at time of export - Agenda links widget: simple per-client URL bookmarks (`business_review_links` table) --- ## 5. Recommendations — FULLY CAPTURED ### What LCI Shows **Page**: `Recommendations for Hynes Industries` — 26 total records **Table columns**: | Column | Notes | |--------|-------| | Name | Free-text project/recommendation name | | Location | Youngstown (Main) / Painesville (Branch) / Kokomo (Branch) / blank (all sites) | | Start | Target start date (optional) | | End | Target end date (optional) | | Status | New / Proposed / Planned / In Progress / On Hold / Completed / Declined | | Tags | (free-form tags) | | Priority | Low / Medium / High | | Description | Rich text description of scope | | Labor Cost | $ | | Materials Cost | $ | | Replacement Cost | $ | | Recurring Cost | Monthly $X → shown as "Monthly / $X" | | Total Cost | Sum of all cost components | | Delete | delete action | **Filters**: - Search box - Include Completed toggle - Include Declined toggle - "SHOW AUTOTASK OPPS" button — links to Autotask opportunities **Views**: List (default) — table view **Hynes Industries full recommendation list** (real data): | Name | Status | Priority | Total Cost | |------|--------|----------|------------| | 2024 - Fish Bowl Renovation | Completed | Medium | $11,000 | | 2024 - Pepwave Licensing Renewal | Completed | Medium | $0 | | 2024 - Planned Multiple Switch Lifecycle | Completed | Medium | $24,000 | | 2024 - Planned Workstation Lifecycle | In Progress | Medium | $9,800 | | 2024 - VLAN Cleanup | Completed | Medium | $10,000 | | 2024: O365 Backup | Completed | Medium | $3,560 (monthly) | | 2024: Password Management | Completed | Medium | $8,340 (monthly) | | 2024: SEIM Tool | Completed | High | $20,020 (monthly) | | 2024: ZTNA - Phase 1 | Completed | High | $16,350 (monthly) | | 2025 - Painesville Zoom Room | Declined | Low | $11,000 | | 2025 - Planned Infrastructure Lifecycle | Completed | High | $6,830 (monthly) | | 2025 - Planned Workstation Lifecycle | Completed | High | $3,000 | | 2025 - PV Planned Multiple Switch Lifecycle | In Progress | High | $5,000 | | 2025 - YNG Planned Multiple Switch Lifecycle | Completed | High | $2,900 | | 2025: Windows 10 to 11 Upgrade | Completed | High | $40,400 | | 2026 - Exterior Cameras - Partial Build | On Hold | Low | $57,000 | | 2026 - PEN Test | On Hold | High | $20,000 | | 2026 - Pepwave Licensing Renewal | Planned | High | $350 | | 2026 - Planned Host/SAN Lifecycle | Proposed | High | $120,000 | | 2026 - Planned Multiple Switch Lifecycle | Proposed | High | $31,000 | | 2026 - Planned Workstation Budget | Proposed | Medium | $86,600 | | 2026 - Zebra Printers Lifecycle | Proposed | High | $80,534 (monthly) | | 2026: ZTNA: Phase 2 | On Hold | High | $30,000 | | Auvik SaaS | Declined | Medium | $1,760 (monthly) | | Physical Switch & IDF Cleanup | On Hold | Medium | $0 | | Receptionist Hardware | Completed | Medium | $1,800 | **How recommendations feed Budget Forecast**: - Status `Proposed`, `Planned`, `In Progress`, `On Hold` → included in budget forecast - `start` date (or `end` date) → determines which quarter they appear in - No date → "Not Scheduled" bucket - Past date → "Overdue" bucket - `Completed` / `Declined` → excluded from forecast ### Recommendations Data Model ```sql recommendations id, company_id, name VARCHAR, location_id INT (nullable), start_date DATE (nullable), end_date DATE (nullable), status VARCHAR, -- New/Proposed/Planned/In Progress/On Hold/Completed/Declined tags TEXT[], priority VARCHAR, -- Low/Medium/High description TEXT, labor_cost DECIMAL, materials_cost DECIMAL, replacement_cost DECIMAL, recurring_cost DECIMAL, -- monthly amount recurring_period VARCHAR, -- 'Monthly' total_cost DECIMAL, -- computed or stored autotask_opportunity_id INT (nullable), created_at, updated_at recommendation_assets -- assets linked to this recommendation recommendation_id, asset_id ``` ### Pulse Implementation Notes - Recommendations are **Pulse-native** (not pulled from Autotask) but can push/link to Autotask Opportunities - `total_cost = labor_cost + materials_cost + replacement_cost + (recurring_cost × months_in_period)` - Budget Forecast query filters: `status NOT IN ('Completed', 'Declined')` - Dashboard widget shows count + total cost grouped by status - The `SHOW AUTOTASK OPPS` button = link to Autotask opportunities filtered to this company --- ## 6. Dashboard Summary The LCI dashboard aggregates all four features for a client into one view: | Widget | Data | |--------|------| | CSAT Score | From Crewhu integration (external) | | Budget Forecast chart | 6-quarter bar chart | | EOL Health | % OK / Past EOL / Near EOL donut | | Data Quality Score | Per-field completeness scores | | Microsoft License Summary | From M365 / CSP data | | EOL Replacement Cost | Bar chart by status | | Latest Assessment | Score + date | | Recommendation Status | Count + cost per status | | Assessment Score History | Line/bar chart | | Software/OS EOL Table | Global reference table | | Tech Debt by Asset Type | Stacked bar | | Missing Data Fields | Counts of missing fields | | Total Technology Debt | $ value of overdue/EOL assets | | Headlines | Alerts: overdue contracts, overdue QBRs, latest assessment age | --- ## 6. Integrations & Data Flow ``` Datto RMM ──────────────────┐ ▼ Autotask CIs ───────────► LCI Asset Sync │ Autotask Contracts ──────────┤ │ Autotask Recommendations ────┤ (or LCI-native) │ ▼ LCI PostgreSQL │ ┌────────┼────────┐ ▼ ▼ ▼ Budget Assessments QBR Forecast Events Reports ``` **For Pulse**: - Assets: Autotask Configuration Items API → `assets` table - Contracts: Autotask Contracts API → `contracts` table (already partially done) - Recommendations: Either Autotask Opportunities/Quotes or Pulse-native table - CSAT: Not currently integrated (Crewhoo is external) — can be skipped initially - EOL Reference: Static lookup table (maintained manually or seeded from LCI's public list) - Warranty dates: Come from Autotask CI `warrantyExpirationDate` field --- ## 7. Build Priority Order 1. **Asset List + Warranty** — highest value, data already in Autotask CIs 2. **Budget Forecast** — derived from assets + contracts (both already syncing) 3. **QBR / Business Reviews** — report generation + scheduling 4. **Assessments** — most complex, requires template builder + event runner --- ## 9. Pages Still to Explore **Fully captured**: Asset List, Budget Forecast (detail + spreadsheet), Recommendations (all 26), Business Reviews (all ~56 meetings), Dashboard. **Still needed for complete picture**: - `app.lifecycleinsights.io/assessmentevents` — see an actual scored assessment event (items, categories, scores per item). The Hynes event from 01-29-2025 was a baseline with no numeric score. - `app.lifecycleinsights.io/assessmentanalytics` — analytics/trends view per client - `app.lifecycleinsights.io/managetemplates` — what a template looks like with items + categories - MDS client — verify data model generalizes (different asset mix, different contact structure) These can be explored via Claude_in_Chrome (already connected to local Chrome where you're logged in) without needing another MFA login.