sync: auto-sync from DESKTOP-0O8A1RL at 2026-05-22 13:42:56

Author: Mike Swanson
Machine: DESKTOP-0O8A1RL
Timestamp: 2026-05-22 13:42:56
This commit is contained in:
2026-05-22 13:42:59 -07:00
parent ee865426c7
commit 66c65fa9bb
2 changed files with 185 additions and 88 deletions

View File

@@ -298,3 +298,116 @@ PUT /estimates/23967407 {"ticket_id": 110843061} → ticket_id: 110843061 [OK]
- Best Buy product: https://www.bestbuy.com/site/asus-v500-desktop-intel-core-i7-16gb-memory-1tb-ssd-dark-grey/6613707.p
- Customer: Arizona Computer Guru (ID 15353550)
- Skill updated: `.claude/commands/syncro.md`
---
## Update: 13:41 PT — Syncro estimates API: recalculation and private notes workflow
## User
- **User:** Mike Swanson (mike)
- **Machine:** DESKTOP-0O8A1RL
- **Role:** admin
- **Session Span:** ~12:0013:41 PT (continued from prior context-compacted session)
---
## Session Summary
This session continued from a context-compacted conversation that had built test estimate #7183 on the ACG internal account and documented the Syncro estimates workflow in syncro.md. The first task on resume was adding `/syncro estimate` to the usage table in syncro.md, which had been identified as pending before compaction.
The user reported that estimate #7183 had incorrect totals in Syncro until manually triggering a recalculation in the GUI, and asked whether the API exposed a recalculate endpoint. Testing against a fresh test estimate (#7184) confirmed the stale-total behavior: after using `PUT /estimates/{id}/line_items/{id}` to set hardware prices, the estimate-level `total` and `subtotal` remain at their pre-update values on subsequent GET calls. A `POST /estimates/{id}/recalculate` endpoint returned 404. The fix is a `PUT /estimates/{id}` with any innocuous field (e.g., `{"date": "YYYY-MM-DD"}`), which triggers server-side recalculation — the PUT response and all subsequent GETs then show correct totals. Test estimate #7183 was deleted per user request; #7184 was created and deleted during testing.
The user then raised that Winter (the office manager) attaches private notes with purchase links to each line item on estimates. Investigation found that the estimate model has no notes surface via API: `POST /estimates/{id}/notes` and `/comments` both return 404, and `note`/`private_note`/`notes`/`body` fields passed to `PUT /estimates/{id}` are silently ignored and not stored. The solution is to always create a ticket first and link the estimate to it via `ticket_id`. Private notes can then be added to the ticket using `POST /tickets/{id}/comment` with `hidden: true, do_not_email: true`. A full end-to-end test (ticket #32315 + estimate #7187) confirmed the workflow. A key gotcha discovered during testing: the comment endpoint is `/comment` (singular) — `/comments` (plural) returns 404.
The full verified workflow (ticket → estimate → line items → hardware PUT prices → PUT recalc touch → private notes on ticket) was documented in syncro.md, replacing the prior minimal estimate code example with a complete annotated workflow template.
---
## Key Decisions
- **PUT touch for recalc rather than GET polling:** The PUT approach is synchronous — the response contains correct totals. GET after a PUT touch is also immediately correct. There is no need to poll or retry.
- **Always create ticket before estimate:** No API workaround exists for notes on standalone estimates. The ticket-first requirement is now a hard rule in the workflow, not an optional step.
- **Private notes use `do_not_email: true`:** Prevents Syncro from notifying the customer about internal sourcing notes. Combined with `hidden: true` (staff-only visibility), this matches Winter's workflow intent.
- **`/comment` vs `/comments`:** Discovered empirically — the plural form returns 404, which would silently fail in an automated workflow. Documented prominently in syncro.md.
---
## Problems Encountered
- **`POST /estimates/{id}/recalculate` returns 404:** No dedicated recalculate endpoint. Resolved by discovering the PUT-touch pattern.
- **`POST /tickets/{id}/comments` (plural) returns 404:** Initial test used the plural form by analogy with other REST APIs. The correct Syncro endpoint is `/comment` (singular). Discovered by testing both forms and comparing HTTP status codes.
- **jq parse error on comment POST:** First attempt to parse the comment response failed with `jq: parse error: Invalid numeric literal`. Root cause was the `https://` URL string in the `body` field containing `//` which caused a heredoc/shell expansion issue in the test command. Resolved by removing the URL scheme in the test payload; the actual workflow uses single-quoted heredocs which are safe.
---
## Configuration Changes
**Modified:**
- `.claude/commands/syncro.md` — Three changes:
1. Usage table: updated `/syncro estimate` description from "Create a new estimate with line items" to "Create ticket + linked estimate with line items and private purchase notes"
2. Estimates section: replaced minimal code example with full annotated workflow template (ticket → estimate → line items → PUT prices → PUT recalc → private notes)
3. Added two new documented behaviors: stale-total recalc via PUT touch, and private notes via linked ticket comment endpoint
---
## Credentials & Secrets
- Syncro API key used (Mike's): `T259810e5c9917386b-52c2aeea7cdb5ff41c6685a73cebbeb3` — sourced from `msp-tools/syncro.sops.yaml` in SOPS vault
---
## Infrastructure & Servers
- Syncro PSA API: `https://computerguru.syncromsp.com/api/v1`
- Test customer: ACG internal account (customer_id: 15353550)
---
## Commands & Outputs
```bash
# Confirmed: no recalculate endpoint
POST /estimates/{id}/recalculate -> 404
# Stale total reproduced
POST /estimates/23967344/line_items price_retail: 500.00
# -> price: "0.0" (hardware product ignores POST price)
PUT /estimates/23967344/line_items/124967833 {"price": 500.00}
# -> price: "500.0"
GET /estimates/23967344
# -> total: "0.0", subtotal: "0.0" (STALE)
# PUT touch fixes it
PUT /estimates/23967344 {"date": "2026-05-22"}
# -> total: "543.5", subtotal: "500.0" (LIVE)
GET /estimates/23967344
# -> total: "543.5", subtotal: "500.0" (correct on subsequent GETs too)
# Private notes: ticket must exist first
POST /tickets {"customer_id": 15353550, "subject": "Estimate: ...", "status": "New", "problem_type": "Estimate"}
# -> ticket id: 110841689, number: 32315
POST /estimates {"customer_id": 15353550, "ticket_id": 110841689, ...}
# -> estimate id: 23967371, number: 7187, ticket_id: 110841689
POST /tickets/110841689/comment {"subject": "...", "body": "...", "hidden": true, "do_not_email": true}
# -> comment id: 412474488, hidden: true [OK]
POST /tickets/110841689/comments (plural — wrong)
# -> 404
```
---
## Pending / Incomplete Tasks
None for this session. Syncro estimate workflow is fully documented and verified.
---
## Reference Information
- syncro.md: `D:/claudetools/.claude/commands/syncro.md` — Estimates section (~line 586)
- Test estimates created/deleted this session: #7183, #7184, #7185, #7186, #7187
- Test ticket created/deleted: #32315 (id: 110841689)
- ACG internal customer: https://computerguru.syncromsp.com/customers/15353550