From 90748d09013acbaf9b0c126d5af18085e7372357 Mon Sep 17 00:00:00 2001 From: Mike Swanson Date: Thu, 21 May 2026 10:02:57 -0700 Subject: [PATCH] fix(syncro): omit contact_id by default; Syncro assigns primary automatically MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Only set contact_id when ticket is opened by/regarding a named contact. Removed address_id, appointment_owner, and do_not_invite fields from the default gather step — these are edge cases, not routine inputs. Updated preview template to reflect default primary contact behavior. Co-Authored-By: Claude Sonnet 4.6 --- .claude/commands/syncro.md | 46 ++++++++++++++------------------------ 1 file changed, 17 insertions(+), 29 deletions(-) diff --git a/.claude/commands/syncro.md b/.claude/commands/syncro.md index 6b1947a..8bc44eb 100644 --- a/.claude/commands/syncro.md +++ b/.claude/commands/syncro.md @@ -306,29 +306,23 @@ Collect in one pass (do not ask field by field): | 5 | **Do Not Email** | Suppress customer notification on ticket create? (yes for internal/reminder tickets) | | 6 | **Due Date** | ISO date | | 7 | **Assigned Tech** | Who owns the ticket. Defaults to API key owner if not specified (mike → 1735, howard → 1750). MUST always be included in the POST payload — never omit. | -| 8 | **Contact** | Look up from `GET /customers/{id}` → `.contacts[]`; show list, ask user to pick | -| 9 | **Address/Site** | `address_id` — also comes from customer contacts with address data | -| 10 | **Appointment Type** | From table above; omit section if no appointment needed | -| 11 | **Location** | Free text; usually blank unless onsite at non-primary address | -| 12 | **Start Time** | ISO8601 datetime; omit if no scheduled appointment | -| 13 | **End Time** | Default: start + 90 minutes | -| 14 | **Appointment Owner** | Usually same as assigned tech; noted for calendar attribution (not a separate API field — inherits from ticket `user_id`) | -| 15 | **Do Not Invite** | If not onsite, suppress calendar invite — note: not directly controllable via API; inform user if they need this set manually | -| 16 | **Asset** | Search `GET /customer_assets?customer_id=N&query=` if a specific device is involved | +| 8 | **Contact** | Omit unless the ticket is opened by or specifically regarding a named contact. When omitted, Syncro assigns the customer's primary contact automatically. Only look up and set `contact_id` when the user names a specific person. | +| 9 | **Appointment Type** | From table above; omit section if no appointment needed | +| 10 | **Location** | Free text; usually blank unless onsite at non-primary address | +| 11 | **Start Time** | ISO8601 datetime; omit if no scheduled appointment | +| 12 | **End Time** | Default: start + 90 minutes | +| 13 | **Asset** | Search `GET /customer_assets?customer_id=N&query=` if a specific device is involved | -#### Step 2 — Look up customer data - -Before showing the preview, fetch what you need: +**Contact lookup (only when a specific contact is named):** ```bash -# Get contacts and addresses -curl -s "${BASE}/customers/${CUST_ID}?api_key=${API_KEY}" | jq '{contacts: [.customer.contacts[] | {id, name, address1, email}]}' - -# Search assets -curl -s "${BASE}/customer_assets?customer_id=${CUST_ID}&query=&api_key=${API_KEY}" | jq '[.assets[] | {id, name, asset_type}]' +curl -s "${BASE}/customers/${CUST_ID}?api_key=${API_KEY}" | \ + jq '[.customer.contacts[] | {id, name, email}]' ``` -#### Step 3 — Show preview and confirm +Match by name, confirm with user, then include `contact_id` in the ticket POST. Never include `contact_id: null` — omit the field entirely when using the default. + +#### Step 2 — Show preview and confirm Display the full ticket before posting. Include all populated fields. Wait for explicit confirmation. @@ -342,11 +336,10 @@ Priority: Description: Due Date: Assigned To: -Contact: -Address:
+Contact: (or named contact if specified) Do Not Email: -APPOINTMENT +APPOINTMENT (omit section if no appointment) ----------- Type: Start: @@ -358,7 +351,7 @@ ASSET: Confirm? (yes/no) ``` -#### Step 4 — Execute (after confirmation) +#### Step 3 — Execute (after confirmation) **Call 1 — Create ticket:** @@ -373,12 +366,7 @@ RESP=$(curl -s -X POST "${BASE}/tickets?api_key=${API_KEY}" \ "status": "New", "priority": "2 Normal", "user_id": N, - "due_date": "YYYY-MM-DD", - "contact_id": N, - "address_id": N, - "start_at": "ISO8601", - "end_at": "ISO8601", - "asset_ids": [N] + "due_date": "YYYY-MM-DD" } JSON ) @@ -386,7 +374,7 @@ TICKET_ID=$(echo "$RESP" | jq -r '.ticket.id') CUST_ID=$(echo "$RESP" | jq -r '.ticket.customer_id') ``` -Omit null/blank fields from the payload before piping. The `'JSON'` quoting on the heredoc opener is required — it suppresses bash variable and backtick expansion inside, which matters when descriptions contain `$` (passwords, prices, regex, etc.). +Omit `contact_id` unless a specific contact was named — Syncro assigns the primary automatically. Omit `asset_ids` unless an asset was identified. Omit `do_not_email` unless suppression was requested. Never include fields with null values. The `'JSON'` quoting on the heredoc suppresses `$` expansion inside the payload. **Call 2 — Post initial description as "Initial Issue" comment:**