2.3 KiB
name, description, type
| name | description | type |
|---|---|---|
| Syncro emergency/after-hours billing — check prepay_hours first | Emergency labor is 1.5× multiplier, not additive. Branch by customer.prepay_hours — wrong branch doubles or undercharges. Applies to every /syncro bill for emergency work. | feedback |
Rule: Before adding any Emergency/after-hours labor line item on a Syncro ticket, GET /customers/<id> and read prepay_hours.
- If
prepay_hours == 0(no prepaid block): use product26184(Labor - Emergency/After Hours) at quantity = actual hours. The $262.50/hr rate already has the 1.5× multiplier baked in. - If
prepay_hours > 0(customer has a prepaid block): use product26118(Labor - Onsite) at quantity = actual hours × 1.5. Prepaid blocks debit by QUANTITY, not dollars, so we bump qty instead of swapping to the Emergency product.
Never stack 26118 + 26184 for the same hour of work. Pick one path based on the prepaid state.
Why: Learned on ticket #32203 (Desert Auto Tech) 2026-04-23. Howard asked to bill "1 hour onsite + 1 hour emergency onsite." I posted both as separate additive line items and the invoice came out at $437.50 when the correct bill for 1 actual hour of emergency work was $262.50. Winter caught it and explained the rule: "the goal is to have it bill at time and a half." The Emergency product = time-and-a-half by rate; prepaid accounts = time-and-a-half by quantity. Swapping products AND multiplying quantity double-counts.
How to apply:
- Every
/syncro billfor emergency/after-hours work: checkprepay_hoursBEFORE choosing the product. Do not shortcut this. - For a 2-hour emergency job:
- Non-prepaid customer → one line, 2.0 hrs ×
26184→ $525.00 - Prepaid customer → one line, 3.0 hrs ×
26118→ 3 hours debit from block
- Non-prepaid customer → one line, 2.0 hrs ×
- Always set
price_retailexplicitly onadd_line_item. The old "omit and let Syncro auto-calc" guidance was wrong — the rate does not populate from the product config, and the invoice will post at $0 ifprice_retailis missing. Fetch the current rate withGET /products/<id>. - Never let a customer-facing invoice post without verifying
.invoice.totalmatches the expectedqty × price_retail. - Full rules and examples live in
.claude/commands/syncro.mdunder the "Labor product IDs" section.