# Syncro Emergency / After-Hours Billing

Rules for applying emergency or after-hours labor premiums in Syncro tickets.

---

## Definitions

| Term | Meaning |
|---|---|
| **Normal hours** | 9:00 AM – 5:00 PM, Monday–Friday |
| **After-hours** | Before 9 AM or after 5 PM on weekdays, or any time on weekends/holidays |
| **Emergency** | Customer explicitly requested emergency or same-day rates |
| **Same-day** | Work done same day it was requested, during normal hours — only billable as emergency if customer requests it |

---

## When to Apply the Premium

**Claude-created tickets:** Apply emergency premium **only if explicitly requested** by the customer or instructed by Mike/Howard.

**Suggest it** (do not apply automatically) when:
- Work is performed after-hours or on a weekend
- Ticket notes indicate the customer called in urgently outside normal hours

Do not apply for same-day work unless the customer asks for the emergency rate.

---

## Ticket Subject Prefix

| Condition | Prefix |
|---|---|
| Customer explicitly requested emergency rates | `Emergency -` |
| Work performed outside normal hours (not customer-requested) | `Afterhours -` |
| Normal hours, no emergency request | No prefix |

Examples:
- `Emergency - Servers down, HP ProLiant host powered off`
- `Afterhours - Printer not connecting after office hours`

---

## Billing Method — Two Scenarios

### Step 1: Determine if Customer is a Block Customer

Check customer notes in Syncro for "block hours," "prepay hours," or "prepaid." Block customers have invoices with $0.00 totals and line item descriptions containing "Prepay Hours."

Known block customers as of 2026-05-25: Valley Wide Plastering (VWP), Dataforth Corporation, Cascades Retirement Properties. Always verify — blocks can be exhausted or moved to QB tracking.

---

### Scenario A — Block / Prepaid Hours Customer

Use **two line items**, both using the same standard labor product as the non-emergency work:

| Line | Product | Qty | Description |
|---|---|---|---|
| 1 | Standard labor product (see table below) | Actual hours worked | Description of work performed |
| 2 | Same standard labor product | 0.5 × line 1 qty | `Emergency/Same day rate` |

**Example:** 1 hour of emergency remote business on a block account:
- Line 1: `Labor - Remote Business` (1190473) — 1.0 hr — "Emergency remote - Servers down, powered on via iLO"
- Line 2: `Labor - Remote Business` (1190473) — 0.5 hr — "Emergency/Same day rate"

Reference: Invoice 67594 (VWP, 2026-05-12), Ticket #32269.

---

### Scenario B — Non-Block / Direct Billing Customer

Use a **single emergency labor product** for the full hours worked. All delivery channels use product 26184 — the rate varies by how work was delivered:

| Delivery channel | Product | Product ID | Rate |
|---|---|---|---|
| Remote | Labor - Emergency or After Hours Business | 26184 | $225.00/hr |
| In-Shop | Labor - Emergency or After Hours Business | 26184 | $225.00/hr |
| Onsite | Labor - Emergency or After Hours Business | 26184 | $262.50/hr |

Residential rates are legacy — ACG no longer bills residential. Do not use product 42584.

**IMPORTANT:** Product 26184's `price_retail` from the live API returns $262.50 (the onsite rate). For remote and in-shop work, you MUST explicitly pass `"price_retail": 225.00` — do NOT use the live-fetched rate blindly for those channels.

**Example:** 4 hours of emergency in-shop work, direct billing:
- Line 1: `Labor - Emergency or After Hours Business` (26184) — 4.0 hr @ $225.00

Reference: Ticket #32188 (VWP, direct billing, 2026-04-22). Rates confirmed by Winter 2026-06-23.

---

## Standard Labor Products (Reference)

Emergency rates use product 26184 for all channels, but the `price_retail` differs by delivery method — do NOT blindly use the live API rate for remote/in-shop (the API returns the onsite default of $262.50). Residential rates are legacy and not in use.

**For non-emergency work:** fetch `price_retail` from `GET /api/v1/products/{id}` before billing. For emergency work: use the rates below (confirmed by Winter 2026-06-23).

| Service type | Product | Product ID | Rate | Notes |
|---|---|---|---|---|
| Remote Business | Labor - Remote Business | 1190473 | $150.00/hr | Non-block cash billing |
| Onsite Business | Labor - Onsite Business | 26118 | $175.00/hr | |
| In-Shop Business | Labor - In Shop Business | 573881 | $150.00/hr | |
| Block/Prepaid (any type) | Labor - Remote Business | 1190473 | $0.00 | Price = $0; draws from block in hours |
| Emergency Remote | Labor - Emergency or After Hours Business | 26184 | **$225.00/hr** | Override price_retail — API default is wrong for this channel |
| Emergency In-Shop | Labor - Emergency or After Hours Business | 26184 | **$225.00/hr** | Override price_retail — API default is wrong for this channel |
| Emergency Onsite | Labor - Emergency or After Hours Business | 26184 | **$262.50/hr** | API default is correct for onsite |

---

## Adding Line Items to an Existing Ticket (API)

**Confirmed working endpoint** (tested 2026-05-25, ticket #32320 and test #32321):

```
POST https://computerguru.syncromsp.com/api/v1/tickets/{ticket_id}/add_line_item
Authorization: <api_key from vault: msp-tools/syncro.sops.yaml → credentials.credential>
Content-Type: application/json
```

**Required body fields** — both `name` and `description` are required; either missing returns 422:

```json
{
  "product_id": 1190473,
  "name": "Labor - Remote Business",
  "description": "Work performed description",
  "quantity": 2.0,
  "price_retail": 0.0,
  "taxable": false
}
```

- `price_retail`: **CRITICAL — use `price_retail`, NOT `price`.** Using `price` silently discards the value and bills $0.00 even though the API returns HTTP 200. Confirmed broken 2026-05-27 (ticket #32335).
  - Block customers: `"price_retail": 0.0`
  - Non-block customers: fetch live rate first (`GET /api/v1/products/{product_id}` → `.product.price_retail`), then pass that value
- `taxable`: always `false` for labor (Arizona labor is never taxable)
- Success response: HTTP 200 with the new line item's `id` — verify `price_retail` in the response matches what you sent

**Pre-billing check** — before adding line items, verify the ticket has no existing labor to avoid duplicates:
```
GET https://computerguru.syncromsp.com/api/v1/tickets/{ticket_id}
```
Check `.ticket.line_items[]` in the response.

---

## Straddle (Mixed Normal + Emergency Hours)

If work begins during normal hours and continues into after-hours (or vice versa):
- Ask: "Does the after-hours portion warrant splitting the labor?" (brief overlap usually doesn't)
- If splitting: bill normal hours on standard product, after-hours/emergency portion on the appropriate emergency product or as a second prepay line

---

## Products NOT to Use

| Product | ID | Why not |
|---|---|---|
| LLF - Remote Labor (Emergency/Afterhours) | 145022 | Legacy contract product, no longer applicable |
| Fee - On-Site Business Emergenc | 45871 | Not in current use — do not add without explicit instruction |
| Fee - On-Site Residential Emerg | 45870 | Not in current use — do not add without explicit instruction |
| Labor - Emergency or After Hours Residential | 42584 | Residential rates are legacy — ACG no longer uses residential billing |
| Labor - Remote Residential | 1190471 | Residential rates are legacy — ACG no longer uses residential billing |

---

## Quick Decision Tree

```
Was emergency rate explicitly requested by customer?
  YES → Apply premium (see billing method below)
  NO  → Is work happening after-hours or on a weekend?
          YES → Suggest emergency rate to Mike/Howard; do not apply automatically
          NO  → Bill at standard rates, no prefix
```

```
Is customer a block/prepaid customer?
  YES → Two line items: actual hrs (standard product) + 0.5x hrs (same product, "Emergency/Same day rate")
  NO  → One line item: emergency product 26184 (business) for full hours
```
