# Command Sovereignty β€” Remodeling Sector Gap Plan

**Target companies:** Omnia, Renuity, Tundraland, Power Home Remodeling
**Revenue range:** $20M–$100M+ annually, PE-backed or scaling, multi-service line

---

## Current capabilities that directly serve this segment

| Capability | Why it matters to remodeling | Status |
|---|---|---|
| QuickBooks connector | Actuals ingestion for revenue/rexpense tracking | βœ… Built |
| Revenue Leak engine (21 detectors) | Catches abandoned deals, stale leads, overdue invoices | βœ… Built |
| Forecast automation (actuals + pipeline) | Know if you'll hit the number weeks early | βœ… Built |
| Cascading goals (org β†’ dept β†’ team β†’ rep) | Targets flow down instead of staying on a whiteboard | βœ… Built |
| Scale optimization (ROAS / LTV:CAC by channel) | See which lead source is actually profitable | βœ… Built |
| Strategic Intelligence (FP&A waterfall) | Drill into variance instead of guessing | βœ… Built |
| Multi-tenant portals | Multiple operating companies/brands each get their own view | βœ… Built |
| Google Ads connector | Lead cost tracking for paid search | βœ… Built |
| Facebook Ads connector | Lead cost tracking for social ads | βœ… Built |
| HubSpot connector | CRM pipeline + deal tracking | βœ… Built |
| ServiceTitan connector | CRM/project management integration | βœ… Built |
| AngiLead model + API routes | Data model and CRUD API for Angi leads | βœ… Built (partial) |
| Twilio SMS/Call integration | Speed-to-lead tracking, automated follow-up | βœ… Built |

---

## Gaps to close

### 1. Angi Connector (webhook receiver + setup flow) β€” βœ… DONE

**What exists:** `AngiLead` model in models.py (line 926), API proxy routes for CRUD, SMS/call integration referencing AngiLead, **working webhook endpoint**, multi-tenant auth.

**What was built (2026-07-22):**
- Webhook endpoint `POST /api/connectors/webhooks/angi` with `x-api-key` multi-tenant authentication
- New AngiLead fields: `interview_qa` (Text/JSON), `tcpa_compliance` (Boolean), `match_type` (String)
- Real field mapping: `service_type`β†’`project_type`, `project_description`β†’`description`, `tcpa_consent`β†’`tcpa_compliance`
- `to_dict()` serialization of new fields
- AngiLead creation includes all new fields on webhook receipt

**What's missing:**
- Webhook receiver endpoint that accepts Angi's JSON POST (`POST /api/connectors/angi/webhook/<connector_id>`)
- Field mapping: Angi sends `name`, `firstName`, `lastName`, `address`, `city`, `stateProvince`, `postalCode`, `primaryPhone`, `email`, `srOid`, `leadOid`, `fee`, `taskName`, `comments`, `matchType`, `leadDescription`, `interview[]`, `automatedContactCompliant`
- Connector config UI: company enters their webhook URL (Command Sovereity's endpoint) + API key, emails it to `crmintegrations@angi.com` for Angi to configure
- Lead acceptance/rejection callbacks to Angi (if needed)
- Duplicate detection across companies sharing Angi leads (shared leads are a common Angi pattern)

**Auth model:** Angi uses `x-api-key` header (partner-provided key, max 160 chars). No OAuth β€” it's a webhook push from Angi β†’ our endpoint.

**Implementation:**
- `POST /api/connectors/angi/webhook/<connector_id>` β€” receives lead, maps fields, creates `AngiLead`, triggers speed-to-lead alerts
- Connector settings page: shows webhook URL, API key generation, setup instructions for Angi
- Test mode: company emails test webhook URL to Angi, we validate payload
- Duplicate detection: check `angi_lead_id` + `company_id` unique constraint (already in model)
- Cost tracking: store `fee` from Angi payload as `cost_per_lead`

**Estimated effort:** 1 day

---

### 2. Change Order Revenue Leakage Detection

**Problem:** Remodeling companies lose 10-15% of project revenue in uncaptured change orders. A $500k kitchen remodel ends up with $650k in work but only $500k invoiced.

**Detector concept:** `change_order_capture_rate` β€” compare original estimate (from ServiceTitan/Jobber/HubSpot) to final invoice (from QuickBooks). Flag projects where actual scope exceeded estimate by >15% but invoice didn't reflect the increase.

**Data sources needed:**
- ServiceTitan: original estimate amount vs. final invoice amount (connector exists, needs estimate endpoint)
- Jobber: same pattern (connector doesn't exist yet β€” see gap #4)
- QuickBooks: final invoice amounts (connector exists)

**Implementation:**
- New leak detector: compares estimate β†’ invoice delta per project
- Alert: "Project #12345 β€” estimated $12,000, invoiced $12,000. Customer approved $18,000 in scope changes. ~$6,000 in uncaptured change orders."
- Dashboard widget: change order capture rate by project manager/team

**Estimated effort:** 2-3 days (depends on ServiceTitan estimate data availability)

---

### 3. Estimate-to-Close Funnel Tracking

**Problem:** Lead β†’ Estimate β†’ Close is the core funnel in remodeling. We track deals in HubSpot but not estimates from estimating software. The drop-off point between estimate delivered and estimate accepted is the biggest revenue leak.

**What to build:**
- Funnel stage tracking: Lead received β†’ Contacted β†’ Estimate delivered β†’ Estimate accepted β†’ Won/Lost
- Time-in-stage metrics: average days from estimate to close
- Drop-off analysis: which project types have worst estimate acceptance rates
- Integration with ServiceTitan/Jobber estimate endpoints

**Data model additions:**
- `Estimate` model (or extend `AngiLead` with estimate tracking)
- Estimate stages with timestamps
- Funnel conversion rates by project type, rep, region

**Implementation:**
- Extend `AngiLead` lifecycle to include estimate stages: `estimate_delivered`, `estimate_accepted`, `estimate_rejected`
- ServiceTitan connector: pull estimate data when available
- Dashboard: funnel visualization with conversion rates and time-in-stage

**Estimated effort:** 3-4 days

---

### 4. Jobber Connector

**Problem:** Many remodeling companies use Jobber instead of ServiceTitan. Renuity and others in the mid-market segment have migrated to Jobber.

**API:** Jobber has a documented REST API with OAuth 2.0. Covers estimates, jobs, customers, invoices, tasks.

**What to build:**
- OAuth 2.0 flow: company clicks "Connect Jobber," authenticates, we store tokens
- Sync: estimates, jobs, customers, invoices
- Map Jobber data to our existing `AngiLead`/`Opportunity` models
- Reuse connector architecture from existing ServiceTitan/QuickBooks connectors

**Key endpoints:**
- `GET /v1/estimates` β€” estimate tracking
- `GET /v1/jobs` β€” project tracking
- `GET /v1/customers` β€” customer data
- `GET /v1/invoices` β€” revenue data

**Estimated effort:** 3-4 days

---

### 5. Project Slippage Detection

**Problem:** Design-build projects (Tundraland, Renuity) run over schedule. A 6-week bathroom remodel becomes 9 weeks. Each week of slippage eats margin (crew costs, equipment rentals, overhead).

**Detector concept:** `project_schedule_variance` β€” compare estimated completion date to actual/forecasted completion. Flag projects >10% behind schedule.

**Data sources needed:**
- ServiceTitan/Jobber: job start date, estimated end date, current status, milestones
- QuickBooks: time-based expenses that indicate ongoing work past deadline

**Implementation:**
- New leak detector: tracks schedule variance per active project
- Alert: "Project #67890 β€” estimated completion July 15, now forecasted July 29. 2-week slippage. Estimated margin impact: $2,400."
- Rollup: average slippage by project type, project manager, region

**Estimated effort:** 2-3 days (depends on job date data from connectors)

---

### 6. Backlog Burn-Down Tracking

**Problem:** Storm restoration companies (Omnia) and remodelers live by their backlog. They need to know: "At current conversion rate, how many weeks of backlog do we have? When do we need more leads?"

**What to build:**
- Backlog calculation: sum of all active/scheduled project values
- Burn rate: average weekly revenue from completed projects
- Weeks of coverage: backlog / burn_rate
- Alert when coverage drops below threshold (e.g., 4 weeks)
- Re-forecasting: update projection weekly as new deals close and projects complete

**Data sources:**
- ServiceTitan/Jobber: scheduled jobs, estimated values
- QuickBooks: completed project revenue
- HubSpot/Angi: pipeline value

**Estimated effort:** 2 days

---

### 7. Margin Per Job/Room Tracking

**Problem:** Kitchen, bath, deck, roof projects have wildly different margins. Companies need to know which project types are actually profitable after labor, materials, and overhead.

**What to build:**
- Project-level P&L: estimate cost vs. actual cost from QuickBooks expenses
- Margin by project type, by project manager, by region
- Alert when project margin drops below threshold

**Data sources:**
- ServiceTitan/Jobber: estimated materials + labor
- QuickBooks: actual expenses, payroll allocation
- Command Sovereignty: calculate margin delta

**Estimated effort:** 3-4 days

---

### 8. Multi-Location Rollup Analytics

**Problem:** Renuity operates in multiple markets. Leadership needs a rollup view: total revenue, conversion rates, leak detection across all locations, with the ability to drill into any single market.

**What to build:**
- Group companies by parent organization
- Rollup dashboard: aggregate KPIs across all locations
- Drill-down: click into any location for detailed view
- Comparative analysis: which location has best/worst metrics

**Current state:** Multi-tenant portals exist, but analytics are per-company not rollup.

**Estimated effort:** 4-5 days

---

## Implementation Priority

| Priority | Feature | Effort | Impact | Rationale |
|---|---|---|---|---|
| **P0** | Angi Connector (webhook) | 1 day | High | Quick win, immediate value, companies already use Angi |
| **P1** | Backlog Burn-Down | 2 days | High | Critical for storm restoration / remodeling ops |
| **P1** | Change Order Detection | 2-3 days | High | Directly catches revenue leakage |
| **P2** | Estimate-to-Close Funnel | 3-4 days | Medium | Closes the lead→close visibility gap |
| **P2** | Jobber Connector | 3-4 days | Medium | Expands CRM coverage beyond ServiceTitan |
| **P3** | Project Slippage Detection | 2-3 days | Medium | Margin protection for design-build |
| **P3** | Margin Per Job Tracking | 3-4 days | Medium | Profitability visibility by project type |
| **P4** | Multi-Location Rollup | 4-5 days | Low-Medium | Needed for multi-market companies |

**Total estimated effort:** ~25-30 days (single developer)

---

## Angi Connector β€” Detailed Implementation Plan (P0)

### Angi webhook payload β†’ our model mapping

| Angi field | Our field | Notes |
|---|---|---|
| `firstName`, `lastName` | `first_name`, `last_name` | Direct map |
| `email` | `email` | Direct map |
| `primaryPhone` | `phone` | Direct map |
| `address`, `city`, `stateProvince`, `postalCode` | `address`, `city`, `state`, `zip_code` | Rename stateProvince |
| `srOid` or `leadOid` | `angi_lead_id` | Use srOid as primary |
| `taskName` | `project_type` | Direct map |
| `comments` | `description` | Direct map |
| `fee` | `cost_per_lead` | Direct map |
| `leadSource` | `lead_source` | Direct map |
| `interview[]` | (new) `interview_qa` JSON field | Store as JSON array |
| `automatedContactCompliant` | (new) `tcpa_compliant` boolean | TCPA tracking |
| `matchType` | (new) `match_type` string | Track lead type |

### New fields to add to AngiLead model
```python
interview_qa = db.Column(db.Text, nullable=True)  # JSON array
tcpa_compliant = db.Column(db.Boolean, default=True)
match_type = db.Column(db.String(50), default='')
```

### Files to create/modify
1. `app/routes/connectors/angi_webhook.py` β€” webhook receiver endpoint
2. `app/routes/connectors/angi_config.py` β€” connector settings (webhook URL display, API key gen)
3. `app/models.py` β€” add 3 new fields to AngiLead
4. `app/services/leak_detectors/` β€” add angi-specific detector: `angi_lead_cost_roi` (compare cost_per_lead to closed deal value)
5. `frontend/src/pages/Connectors/AngiSettings.tsx` β€” UI for connector setup
6. `tests/test_angi_webhook.py` β€” webhook payload handling tests

### Endpoint spec
```
POST /api/connectors/angi/webhook/<connector_id>
Headers: x-api-key: <partner_key>
Content-Type: application/json

Response: 200 { "status": "success", "leadId": "<our_lead_id>" }
Response: 401 { "status": "error", "message": "Invalid API key" }
Response: 200 { "status": "success", "duplicate": true } (for duplicate leads)
```