181 lines
14 KiB
Markdown
181 lines
14 KiB
Markdown
# June Billing Reconciliation — Cascades, Rednour + ACG Internal (6-13 to 6-26)
|
||
|
||
## User
|
||
- **User:** Howard Enos (howard)
|
||
- **Machine:** Howard-Home
|
||
- **Role:** tech
|
||
|
||
## Session Summary
|
||
|
||
Ran a comprehensive Syncro billing reconciliation for Howard's work since June 6, routed entirely
|
||
through the `/syncro` skill. Started by indexing every Howard-authored session log since 06-06,
|
||
filtering out Mike/Winter and internal-only sessions, then worked client-by-client. The headline
|
||
finding for Cascades was that **most of the large June work was already invoiced** (voice VLAN +
|
||
WiFi/RF on #32444 = 7h; Home→Pro round 1 #32466; SSD/UPS hardware tickets; shared mailboxes; Karen
|
||
ALDOCS; Executive share; Chris Knight). Reconciliation was done against live Syncro (tickets +
|
||
invoices + line items), not the logs alone, to avoid double-billing — and to catch the inverse: two
|
||
hardware-only invoices (#32439 Memcare UPS, #32443 Front Desk UPS) that had **no install labor**.
|
||
|
||
Billed the genuine Cascades gaps as several small tickets (per Howard's preference for multiple
|
||
smaller invoices over one large one), all drawn from the prepaid block (which auto-nets $0 and debits
|
||
hours): UPS install labor on #32439/#32443 (0.5h onsite each); a new Home→Pro round 2 ticket #32474
|
||
(2× $99 keys + 1.0h remote = the only real-dollar Cascades invoice, $215.23); a combined EDR-rollout
|
||
+ accounting-scan ticket #32475 (1.5h + 1.0h remote); an emergency power-outage recovery ticket
|
||
#32476 (1.5h emergency onsite → prepaid ×1.5 = 2.25 qty); a Synology→CS-Server migration + SMB
|
||
diagnosis ticket #32478 (2.0h remote, single combined line dated 06-18); and an Alma Montt offboarding
|
||
ticket #32479 (0.5h remote). The Cascades block ran 46.75 → 37.50 (9.25h).
|
||
|
||
Resolved a date/attribution discrepancy on the "power outage" via a raw-transcript dig (sub-agent over
|
||
`~/.claude/projects/C--claudetools/*.jsonl` for 06-16 and 06-19): the 06-16 record was entirely remote
|
||
(the "I was there" quote was Vertical's VoIP tech, not Howard); 06-19 onsite phone re-keying was
|
||
already billed in #32444; and the outage was the unplanned 06-16-into-06-17 event (both Howard and Mike
|
||
onsite for the pfSense recovery). Howard confirmed the outage as one billable item = 1.5h emergency
|
||
onsite; billed to Howard, comment credits both techs.
|
||
|
||
For non-Cascades: skipped Lens Auto Brokerage (a transient self-resolving Deskman triage explicitly
|
||
logged as "not a ticket") and Dataforth (Howard's call). Confirmed Universal Minerals (#32397, $175)
|
||
and Wolkin (#32465, $225) were already billed. Billed the one open item — Rednour Nick Pafford share
|
||
setup on #32343 (1.0h onsite, $175 real-dollar; no block), attributed to Howard with ticket owner left
|
||
as Mike; skipped the 06-26 Mac RMM diagnosis as an internal GuruRMM product bug.
|
||
|
||
Finally built ACG internal time-tracking ticket #32480 ("Howard - Internal work 6-13-26 to 6-26-26")
|
||
on the internal account (15353550) — 13 lines of Internal Labor (product 9269124, $0/hr time-tracking),
|
||
16.0h total: the three Howard-specified items (radio show 2h, Bitdefender skill 2h, EDR skill 2h) plus
|
||
a bucket-A split of 10h across the other claudetools/GuruRMM dev work (Security Assessment, GuruRMM
|
||
fixes, SPEC-030 uninstall, UniFi/pfSense verbs, AMPIPIT, ScreenConnect, GuruScan, Win11 KB, skill-first
|
||
governance, sync/harness). Period total billed 6-13→6-26: ~31.5h (15.5h client + 16.0h internal).
|
||
|
||
## Key Decisions
|
||
|
||
- **Reconciled against live Syncro before billing anything** — pulled tickets/invoices/line items per
|
||
customer to establish already-billed vs gaps, rather than billing off session logs (which record work
|
||
done, not billing state). This caught both double-bill risks and the labor-missing hardware tickets.
|
||
- **Hours are the tech's call, not derived from logs** — every line's hours came from Howard explicitly;
|
||
the logs only supplied the work scope and delivery channel.
|
||
- **Several small tickets over one big invoice** (Howard's stated billing preference) — each Cascades gap
|
||
got its own ticket/invoice; B (EDR) + C (scan) deliberately combined into one ticket per Howard.
|
||
- **Prepaid mechanics:** all Cascades labor billed against the block (auto-nets $0, debits by quantity);
|
||
emergency on a prepaid customer billed on 26184 at qty = actual ×1.5 (2.25 for 1.5h), not a separate
|
||
regular+emergency line. Keys (product 23571919) are taxable and bill real dollars; block labor on the
|
||
same invoice nets $0 via "- Applied N Prepay Hours."
|
||
- **Attribution:** new labor attributed to the API-key owner (Howard, 1750); on Rednour #32343 (owner
|
||
Mike) the line was set `user_id:1750` so Howard gets the commission without changing ticket ownership.
|
||
- **Emergency outage billed as one event to Howard** (mentions Mike in the comment) per Howard, after the
|
||
transcript dig showed 06-16 was remote and the real onsite emergency was the 06-16→17 pfSense recovery.
|
||
- **Lens skipped** — transient updater-lock crash that self-resolved; the log explicitly recorded it as
|
||
"not a ticket," so nothing to bill.
|
||
- **Internal labor is $0 time-tracking** (product 9269124 price_retail 0.0) — #32480 records hours for
|
||
utilization, not revenue; Bitdefender/EDR skill work was billed under the internal ticket, not double-
|
||
counted in the dev-bucket split.
|
||
- **Bucket-A split of the 10 internal items** weighted by scope (SPEC-030 + Security Assessment + GuruRMM
|
||
fixes heaviest), summing to exactly the 10h Howard set.
|
||
|
||
## Problems Encountered
|
||
|
||
- **#32439/#32443 looked billed but were hardware-only** — initial pass checked for *any* line item;
|
||
Howard flagged the install labor was missing. Re-validated by line *type* and billed 0.5h onsite each.
|
||
- **"Power outage on the 16th, onsite" did not match the record** — session logs had 06-16 as remote
|
||
planning and the outage recovery as 06-17 (Mike onsite, Howard remote). Resolved with a raw-transcript
|
||
sub-agent dig that surfaced the true picture; Howard then clarified it was one 06-16→17 event with both
|
||
techs onsite. Billed per Howard's direct knowledge, flagged the discrepancy before posting.
|
||
- **Universal Minerals / Wolkin assumed unbilled** — both were already invoiced (#32397 $175, #32465
|
||
$225); verified live before proposing anything, so nothing was double-billed.
|
||
- **Multiple invoices per ticket on already-Invoiced tickets** — confirmed Syncro pulls only uninvoiced
|
||
lines into a new invoice (matches the existing #32330/#32303 multi-invoice pattern), so adding labor +
|
||
a new invoice to #32439/#32443/#32343 did not re-bill the prior hardware/remote lines.
|
||
|
||
## Configuration Changes
|
||
|
||
No repo code/config changes. Syncro records created (all via the `/syncro` skill, heredoc/jq payloads):
|
||
|
||
- **#32439** (id 112780453): +0.5h Labor-Onsite (line 43041905), invoice 1650816983 ($0), Resolution comment 420976000.
|
||
- **#32443** (id 112827387): +0.5h Labor-Onsite (line 43041908), invoice 1650816984 ($0), comment 420976008.
|
||
- **#32474** (NEW, id 113124973) "Windows Home -> Pro edition upgrades (round 2) - NurseAssist + DESKTOP-MD6UQI3": 2× Windows Pro Upgrade ($99 taxable) + 1.0h Labor-Remote (block); invoice 1650816992 ($215.23); status Invoiced.
|
||
- **#32475** (NEW, id 113124984) "Datto EDR rollout + Accounting scan-to-folder setup": 1.5h + 1.0h Labor-Remote (block); invoice 1650816999 ($0); Invoiced.
|
||
- **#32476** (NEW, id 113124998) "Emergency Onsite - Building power outage / pfSense recovery (06-16 overnight)": 2.25 qty Labor-Emergency (26184, 1.5h ×1.5, block); invoice 1650817007 ($0); priority 4 Urgent; Invoiced.
|
||
- **#32478** (NEW, id 113125316) "Synology -> CS-SERVER file migration + SMB diagnosis": 2.0h Labor-Remote (block), single combined line dated 06-18; invoice 1650817187 ($0); Invoiced.
|
||
- **#32479** (NEW, id 113125318) "Alma Montt - user offboarding (M365 + AD)": 0.5h Labor-Remote (block); invoice 1650817191 ($0); Invoiced.
|
||
- **#32343** (id 111409967, Rednour, owner Mike): +1.0h Labor-Onsite ($175, user_id 1750=Howard), invoice 1650817586 ($175.00), no-block upsell note; comment 420978674.
|
||
- **#32480** (NEW, id 113125980, ACG internal 15353550) "Howard - Internal work 6-13-26 to 6-26-26": 13 Internal-Labor lines ($0), 16.0h total; invoice 1650817773 ($0); Invoiced; comment 420981118.
|
||
|
||
This session log created at `session-logs/2026-06/2026-06-26-howard-june-billing-reconciliation.md`.
|
||
|
||
## Credentials & Secrets
|
||
|
||
None discovered, created, or rotated this session. Syncro auth via the per-user Howard API key baked
|
||
into the `/syncro` skill (attribution user_id 1750).
|
||
|
||
## Infrastructure & Servers
|
||
|
||
- **Syncro:** base `https://computerguru.syncromsp.com/api/v1`, query-param auth, Howard key (user_id 1750).
|
||
- **Customers:** Cascades of Tucson 20149445 (prepaid block 46.75 → **37.50** after this run); Rednour Law
|
||
1224246 (prepay 0.0, no block); Arizona Computer Guru internal 15353550 (prepay 0.0); Universal Minerals
|
||
34844920; Wolkin/Robert 796910; Len's Auto Brokerage 3289131.
|
||
- **Labor products:** 26118 Onsite $175; 1190473 Remote $150; 26184 Emergency $262.50 (onsite ×1.5);
|
||
23571919 Windows Pro Upgrade $99 taxable; 9269124 Internal Labor **$0** (time-tracking).
|
||
- **Raw transcripts** mined for the 16th/19th: `C:\Users\Howard\.claude\projects\C--claudetools\*.jsonl`.
|
||
|
||
## Commands & Outputs
|
||
|
||
- Per-customer reconciliation: `GET /tickets?customer_id=<id>&per_page=100`, then `GET /tickets/<id>`
|
||
for line-item type/status; `GET /invoices?customer_id=<id>` to map ticket_id → invoice; control chars
|
||
stripped with `tr -d '\000-\037'`.
|
||
- Prepaid rule honored: `GET /customers/<id>` (full, authoritative) for `prepay_hours` before every
|
||
preview — never from the search/list endpoint.
|
||
- Billing sequence per ticket (heredoc/jq, `--data-binary`): comment → add_line_item(s) → invoices →
|
||
PUT invoice note → PUT status Invoiced → post-bot-alert; each step guarded (STOP + echo response if
|
||
any id came back null), no retries on ambiguous results.
|
||
- Emergency prepaid mechanic verified on #32476: `Labor - Emergency or After Hours Business` qty 2.25,
|
||
invoice line "- Applied 2.25 Prepay Hours," block 42.25 → 40.00.
|
||
- Internal #32480: 13 lines via a bash array loop (product 9269124, price 0, user_id 1750); invoice
|
||
hours-sum verified = 16.0.
|
||
|
||
## Pending / Incomplete Tasks
|
||
|
||
- **Rednour 2-desktop fixes** — Howard still needs to fix Nick's two desktops; bill onto #32343 (multi-
|
||
invoice) or a new ticket when done.
|
||
- **GuruRMM macOS enrollment bug** — install script writes the site *code* where `/api/enroll` wants a
|
||
UUID (HTTP 422); onsite paste-block delivered to Howard's Discord, fix pending onsite verify; product
|
||
fix is Mike's (coord todo 6f2d22be). Not client-billable.
|
||
- **Deferred per Howard (not billed):** Cascades CARF technology plan (06-24), Lupe Sanchez/Trcieja perf
|
||
diag (06-18), KPI dashboard scoping (06-17); Dataforth 06-23/06-25 sessions; Lens (not-a-ticket).
|
||
- **Invoice-date note:** #32478 references work date 06-18 in the line/comment; the Syncro invoice itself
|
||
carries today's creation date (no API backdate).
|
||
|
||
## Reference Information
|
||
|
||
- New tickets: #32474, #32475, #32476, #32478, #32479 (Cascades), #32480 (ACG internal).
|
||
- Real-dollar invoices this run: #32474 $215.23, #32343 $175.00 (total $390.23). All other invoices $0
|
||
(prepaid block or internal labor).
|
||
- Cascades block: 46.75 → 37.50 (9.25h drawn). Period total billed 6-13→6-26 ≈ 31.5h (15.5 client + 16 internal).
|
||
- Already-billed verified: Cascades #32444 (7h voice/RF, inv 67856), #32466 (inv 67887 $215.23), #32440
|
||
(67850), #32439/#32443 hardware (67850/67851/67854), #32417 (67825), #32403 (67811), #32230 (67876),
|
||
#32193 (67873); Universal Minerals #32397 (inv 67810 $175); Wolkin #32465 (inv 67885 $225).
|
||
- 9 #bot-alerts posted (message_ids in the run output).
|
||
- Syncro skill billing rules applied: `.claude/skills/` (syncro); prepaid emergency ×1.5; per-user attribution.
|
||
|
||
## Update: 17:19 PT — session close; 06-01→06-12 hours query abandoned (rate limit)
|
||
|
||
Attempted to total Howard's billed labor hours across all clients for 2026-06-01 to 2026-06-12.
|
||
The calc requires fetching each in-range invoice individually (tech attribution `user_id` lives only
|
||
on invoice/ticket line items, not the `/invoices` list endpoint) — 46 ticket-bearing invoices in the
|
||
window. The bulk per-invoice GET repeatedly failed: Syncro's **180 req/min per-IP limit is shared**
|
||
(Discord bot + other sessions also hit it), so any burst beyond a handful was throttled to empty
|
||
responses; paced foreground (perl micro-delay) and patient background runs (90s pre-wait + 1.5s
|
||
pacing + retries) were also starved, returning OK=0/failed=46 even though single and ~5-at-a-time
|
||
GETs work fine. **No billing changes were made — entirely read-only.** To finish later: trickle the
|
||
fetch in bursts of <=6 spaced ~18s apart during a low-contention window (the `.trickle.sh` logic),
|
||
summing `quantity` on line items where `item` matches /labor/i and `user_id==1750`, over invoices
|
||
with `date` in range. Session closed at user request; no new tickets/invoices created since the prior
|
||
content above (#32480 internal already captured).
|
||
|
||
## Update: 17:24 PT — .gitignore hardened against root scratch sweep
|
||
|
||
Root cause of the earlier stray commits (`.lab.txt`, `.invcfg`, `.fail.txt`, `.hours_calc.sh`): the
|
||
billing/invoice-calc scratch files were written to the repo root and were not gitignored, so the sync
|
||
`git add -A` catch-all committed them. Added a targeted block to `.gitignore` — `.*.txt`, `.*.sh`,
|
||
`.invcfg`, `.inv/`, `.one.json` — which ignores dot-prefixed scratch (legit scripts are `scripts/*.sh`,
|
||
not dot-prefixed) without catching tracked root dotfiles (`.hosts.json`, `.devs.json`,
|
||
`.mcp.json.example`, etc., verified via `git check-ignore`). Future session scratch in repo root won't
|
||
be swept into commits.
|