# ConnectWise PSA Integration — Testing Checklist

> **Purpose:** Step-by-step guide to connect ResolutionFlow to a ConnectWise developer sandbox and validate each integration feature end-to-end.
>
> **Date created:** 2026-04-14
> **Branch:** main

---

## Prerequisites

Before starting, make sure you have:

- [ ] ResolutionFlow backend running (`uvicorn app.main:app --reload` from `backend/`)
- [ ] ResolutionFlow frontend running (`npm run dev` from `frontend/`)
- [ ] A ConnectWise developer sandbox account

---

## Step 1 — Get Your ConnectWise Developer Credentials

You need four pieces of information from your ConnectWise sandbox.

**Company ID**
- This is the company name you log in with on the CW login screen (e.g. if your URL is `na.myconnectwise.net` and your login company is `resolutionflow`, the Company ID is `resolutionflow`)

**Site URL**
- Developer sandboxes are typically `na.myconnectwise.net` or `aus.connectwisedev.com`
- Do **not** include `https://` — enter just the hostname (e.g. `na.myconnectwise.net`)

**API Public Key + Private Key**
1. Log into your CW sandbox
2. Go to **System → Members** → open your own member record
3. Click the **API Keys** tab
4. Click **New** → give it a name (e.g. "ResolutionFlow Dev")
5. Save — the **Private Key** is shown only once, copy it now
6. Note both the **Public Key** (shown on the list) and **Private Key**

**Client ID** (already configured server-side)
- The `CW_CLIENT_ID` is set in `backend/app/core/config.py` — this identifies the ResolutionFlow app to ConnectWise and is shared across all tenants. You do not need to enter this in the UI.

---

## Step 2 — Connect ResolutionFlow to ConnectWise

- [ ] Log into ResolutionFlow as a **Team Admin or Super Admin** user
- [ ] Navigate to **Account → Integrations**
- [ ] On the **Connection** tab, fill in the form:
  - Display Name: anything (e.g. `CW Dev Sandbox`)
  - Site URL: your sandbox hostname (e.g. `na.myconnectwise.net`)
  - Company ID: your CW company ID
  - Public Key: from Step 1
  - Private Key: from Step 1
- [ ] Click **Connect** — the backend tests the credentials before saving
- [ ] Verify: "Connected" status appears with a green dot
- [ ] Click **Test Connection** button and confirm it returns a success message + server version

---

## Step 3 — Member Mapping

Maps ResolutionFlow users to ConnectWise members so that PSA posts are attributed to the right technician.

- [ ] Click the **Member Mapping** tab
- [ ] Click **Auto-Match by Email** — ResolutionFlow matches users to CW members with the same email address
- [ ] Verify the matched count in the toast notification
- [ ] If any users are unmatched, manually assign them via the dropdown
- [ ] Click **Save Mappings** if you made manual changes

---

## Step 4 — Ticket Search (via FlowPilot session)

- [ ] Start a new FlowPilot session (from the Dashboard)
- [ ] Look for the **Link Ticket** button in the session header
- [ ] Search for a ticket by keyword or ticket number
- [ ] Verify: ticket results appear showing summary, board, status, priority
- [ ] Select a ticket and confirm it links to the session

---

## Step 5 — Ticket Context Injection

Once a ticket is linked, FlowPilot should enrich its context with CW data.

- [ ] With a ticket linked, send a message to FlowPilot
- [ ] Verify: FlowPilot's response references ticket details (company name, status, configurations, etc.)
- [ ] Check backend logs to confirm `GET /integrations/psa/tickets/{id}/context` is being called

---

## Step 6 — PSA Post (push session notes to ticket)

This is the core feature — pushing session documentation back to the ConnectWise ticket.

- [ ] In the linked session, click **Update** (or the PSA post button in the session header)
- [ ] Review the **Preview** — confirm the generated content looks correct
- [ ] Select a **Note Type**:
  - `Internal Analysis` — internal-only note (visible to techs, not clients)
  - `Resolution` — marks as resolved, notifies client
  - `Description` — main ticket description note
- [ ] Optionally select a **Status** to update the ticket to (e.g. "In Progress" → "Resolved")
- [ ] Click **Post to Ticket**
- [ ] Verify: success toast appears
- [ ] Verify in ConnectWise: open the ticket and confirm the note was posted with correct content and attribution (your member name)

---

## Step 7 — FlowPilot Settings

Configure how FlowPilot behaves with PSA automation.

- [ ] Go to **Account → Integrations → FlowPilot** tab
- [ ] Review each setting:
  - **Auto Push** — automatically post session doc on session close
  - **Auto Time Entry** — automatically log hours from session duration
  - **Time Rounding** — 15min / 30min / exact / none
  - **Note Visibility** — internal only vs. internal + external
  - **Include Diagnostic Steps** — whether to include step-by-step notes
  - **Prompt Status on Resolution** — ask to update CW status when resolving
  - **Prompt Status on Escalation** — ask to update CW status when escalating
- [ ] Adjust to your preference and save

---

## Step 8 — End-to-End Smoke Test

Run a complete session to confirm the full flow works together.

- [ ] Start a new FlowPilot session with a test ticket in CW
- [ ] Link the ticket at session start
- [ ] Work through a troubleshooting flow (even a simple one)
- [ ] Resolve or escalate the session
- [ ] Post the session documentation to the CW ticket
- [ ] Open the ticket in ConnectWise and confirm:
  - [ ] Note content is correct and well-formatted
  - [ ] Note is attributed to the correct CW member
  - [ ] Ticket status was updated (if you chose to update)
  - [ ] Duration / time entry was logged (if auto-time-entry is on)

---

## Known Issues / Bugs Fixed

| Bug | Status | Location |
|-----|--------|----------|
| `create_time_entry()` used `self._client` instead of `self.client` | Fixed 2026-04-14 | `services/psa/connectwise/provider.py:539` |

---

## What's NOT Yet Implemented

| Feature | Notes |
|---------|-------|
| Autotask PSA | Schema accepts `autotask` as provider but no implementation exists |
| Retry queue for failed posts | `retry_count` / `next_retry_at` columns exist in DB but no background job |
| `psa_activity_log` population | Table exists, no endpoints write to it yet |
| Post History tab | Currently a placeholder — post history is viewable per-session only |
