Fix /syncro billing: use timer_entry + labor products, not invoice line items
Timer entries use POST /tickets/{id}/timer_entry with labor product IDs
(not invoice products). "Make Invoice" converts timers to invoice.
Documented 7 common labor products with IDs. Fixed line_items path to
/invoices/{id}/line_items.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -84,26 +84,38 @@ API_KEY=$(sops -d D:/vault/msp-tools/syncro.sops.yaml | python -c "import sys,ya
|
|||||||
| Get customer | GET | `/customers/<id>` |
|
| Get customer | GET | `/customers/<id>` |
|
||||||
| Create customer | POST | `/customers` |
|
| Create customer | POST | `/customers` |
|
||||||
|
|
||||||
|
#### Timer Entries (add time to ticket)
|
||||||
|
|
||||||
|
| Operation | Method | Endpoint | Body |
|
||||||
|
|---|---|---|---|
|
||||||
|
| Add time | POST | `/tickets/<id>/timer_entry` | `{"start_at": "ISO8601", "end_at": "ISO8601", "notes": "...", "billable": true, "product_id": N}` |
|
||||||
|
| List timers | GET | `/ticket_timers?ticket_id=<id>` |
|
||||||
|
|
||||||
|
**IMPORTANT:** `product_id` must be a **labor product**, not an invoice product. Common labor products:
|
||||||
|
- `1190473` — Labor - Remote Business (standard remote work)
|
||||||
|
- `26118` — Labor - Onsite Business
|
||||||
|
- `26184` — Labor - Emergency or After Hours Business
|
||||||
|
- `9269129` — Labor - Prepaid Project Labor
|
||||||
|
- `9269124` — Labor - Internal Labor
|
||||||
|
- `26117` — Fee - Travel Time
|
||||||
|
- `68055` — Labor - Website Labor
|
||||||
|
|
||||||
#### Invoices
|
#### Invoices
|
||||||
|
|
||||||
| Operation | Method | Endpoint | Body |
|
| Operation | Method | Endpoint | Body |
|
||||||
|---|---|---|---|
|
|---|---|---|---|
|
||||||
| List invoices | GET | `/invoices?per_page=25` |
|
| List invoices | GET | `/invoices?per_page=25` |
|
||||||
| Get invoice | GET | `/invoices/<id>` |
|
| Get invoice | GET | `/invoices/<id>` |
|
||||||
| Create from ticket | POST | `/invoices` | `{"ticket_id": N, "customer_id": N}` |
|
| Create from ticket | POST | `/invoices` | `{"ticket_id": N, "customer_id": N, "category": "Standard"}` |
|
||||||
|
| Delete invoice | DELETE | `/invoices/<id>` | — |
|
||||||
|
|
||||||
#### Line Items
|
**"Make Invoice" flow:** Timer entries on the ticket become invoice line items when you POST `/invoices` with the ticket_id. This is the equivalent of clicking "Make Invoice" in the GUI.
|
||||||
|
|
||||||
|
#### Invoice Line Items
|
||||||
|
|
||||||
| Operation | Method | Endpoint | Body |
|
| Operation | Method | Endpoint | Body |
|
||||||
|---|---|---|---|
|
|---|---|---|---|
|
||||||
| Add line item | POST | `/line_items` | `{"invoice_id": N, "item": "...", "quantity": 1, "price": 125.00}` |
|
| Add line item | POST | `/invoices/<id>/line_items` | `{"item": "...", "quantity": 1, "price": 125.00, "product_id": N}` |
|
||||||
|
|
||||||
#### Ticket Timers
|
|
||||||
|
|
||||||
| Operation | Method | Endpoint |
|
|
||||||
|---|---|---|
|
|
||||||
| List | GET | `/ticket_timers?ticket_id=<id>` |
|
|
||||||
| Create | POST | `/ticket_timers` |
|
|
||||||
|
|
||||||
### Display formatting
|
### Display formatting
|
||||||
|
|
||||||
@@ -127,11 +139,16 @@ When showing ticket detail, include:
|
|||||||
### Billing workflow
|
### Billing workflow
|
||||||
|
|
||||||
When `/syncro bill <number>` is called:
|
When `/syncro bill <number>` is called:
|
||||||
1. Get ticket details + time entries
|
1. Get ticket details + existing time entries
|
||||||
2. Show summary: total billable time, line items that would be created
|
2. If no timer entries exist, ask: "Add time? How many hours + labor type?"
|
||||||
3. Ask for confirmation: "Create invoice for $X? [yes/no]"
|
3. Add timer entry via `POST /tickets/{id}/timer_entry` with correct labor product_id
|
||||||
4. On yes: POST `/invoices` with ticket_id, then add line items
|
4. Show summary: total billable time, labor product, estimated total
|
||||||
5. Update ticket status to "Invoiced"
|
5. Ask for confirmation: "Create invoice? [yes/no]"
|
||||||
|
6. On yes: `POST /invoices` with `{"ticket_id": N, "customer_id": N, "category": "Standard"}`
|
||||||
|
7. Update ticket status to "Invoiced"
|
||||||
|
|
||||||
|
**The flow is: timer entries → Make Invoice → Syncro auto-creates line items from timers.**
|
||||||
|
Do NOT create line items manually unless adding non-labor charges (parts, products, etc.).
|
||||||
|
|
||||||
### Error handling
|
### Error handling
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user