Files
zeus-skills/ops/connectwise/connectwise-msp/references/ticket-time-notes.md
T

82 lines
3.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Ticket Time Entries, Notes & Status Changes — Working Payloads
Verified request/response shapes for documenting work on tickets via `scripts/cw_api.py`.
## Response shape normalization (do this FIRST in every script)
`cw_api.cw_request` returns `(data, http_status)` tuples, and list endpoints may wrap the payload one list deeper. Normalize before any `.get()` or loop, or scripts fail with `AttributeError: 'tuple' object has no attribute 'get'`:
```python
def norm(resp):
data = resp[0] if isinstance(resp, tuple) and len(resp) == 2 else resp
if isinstance(data, list) and data and isinstance(data[0], list):
data = data[0]
return [x for x in (data if isinstance(data, list) else [data]) if isinstance(x, dict)]
```
## Create a time entry on a ticket
`POST /time/entries`. Convert local Pacific time to UTC by adding 7 hours (1:30–3:30 PM PDT → 20:30–22:30Z):
```json
{
"company": {"id": <companyId>},
"member": {"id": 147},
"chargeToId": <ticketId>,
"chargeToType": "ServiceTicket",
"locationId": 11,
"businessUnitId": 1,
"workType": {"id": 3},
"workRole": {"id": 4},
"timeStart": "<ISO UTC>",
"timeEnd": "<ISO UTC>",
"actualHours": 2.0,
"billableOption": "Billable",
"notes": "<work note text>",
"addToDetailDescriptionFlag": true
}
```
- `addToDetailDescriptionFlag` does NOT produce a ticket note on this instance — post the note separately if the text must appear on the ticket.
- Verify with `GET /time/entries/{id}`: check `member.identifier`, `timeStart`/`timeEnd`, `actualHours`, and `notes` (top level; `_info.notes` only appears on the ticket timeEntries list view).
- `billableOption`: "Billable" or "NoCharge".
## Add a ticket note
`POST /service/tickets/{id}/notes`:
```json
{
"text": "<note text>",
"detailDescriptionFlag": true,
"internalAnalysisFlag": false,
"resolutionFlag": false
}
```
- Do NOT include `customerVisibleFlag` (or any field not on ServiceNote) — the API 400s the entire request: "Could not find member 'customerVisibleFlag' on object of type 'ServiceNote'".
- Notes are attributed to the API member (TinMan), not an arbitrary author.
- Verify with `GET /service/tickets/{id}/notes`.
## Change ticket status
1. Resolve the numeric status ID: `GET /service/boards/{boardId}/statuses`, match on `name` (VistaNet Help Desk board = 1; "In Progress" = id 1; names starting with `>` are closed-type statuses).
2. PATCH `/service/tickets/{id}` with a JSON Patch ARRAY:
```json
[{"op": "replace", "path": "status/id", "value": 1}]
```
3. Verify: `GET /service/tickets/{id}?fields=id,status`.
## Documentation audit of a scheduled day
```python
# UTC bounds: Pacific day 00:00–24:00 PDT → add 7 hours
params = {"conditions": f"member/id={memberId} AND dateStart >= [{startUtc}] AND dateStart <= [{endUtc}]",
"pageSize": 100}
entries = norm(cw_api.cw_request("GET", "schedule/entries", params=params))
# per entry: objectId = ticket id → GET /service/tickets/{id}/notes AND /service/tickets/{id}/timeEntries
# count only notes where note["member"]["identifier"] matches the member — time entries do NOT count as notes
# report per ticket: notes present / time-entry-only / nothing
```