diff --git a/.fail.txt b/.fail.txt new file mode 100644 index 00000000..83b26e2a --- /dev/null +++ b/.fail.txt @@ -0,0 +1,24 @@ +1650627518 +1650627183 +1650623589 +1650620815 +1650613747 +1650613746 +1650612759 +1650607364 +1650601747 +1650592886 +1650591734 +1650588959 +1650579125 +1650578451 +1650578046 +1650577261 +1650577256 +1650577242 +1650573500 +1650562080 +1650560328 +1650559789 +1650552739 +1650552617 diff --git a/.hours_calc.sh b/.hours_calc.sh deleted file mode 100644 index c57e0c93..00000000 --- a/.hours_calc.sh +++ /dev/null @@ -1,39 +0,0 @@ -#!/usr/bin/env bash -BASE="https://computerguru.syncromsp.com/api/v1" -API_KEY="Tde5174a6e9e312d14-02fd5bfe0f0ee40c87d027507c680e18" -gj() { # resilient GET that retries until JSON parses (handles 429) - local url="$1" tries=0 R - while [ $tries -lt 8 ]; do - R=$(curl -s "$url" /dev/null 2>&1; then printf '%s' "$R"; return 0; fi - tries=$((tries+1)); sleep 3 - done - return 1 -} -IDS=() -for page in 1 2 3 4 5 6; do - P=$(gj "${BASE}/invoices?per_page=100&page=${page}&api_key=${API_KEY}") - while read -r x; do [ -n "$x" ] && IDS+=("$x"); done < <(echo "$P" | jq -r --arg s "2026-06-01" --arg e "2026-06-12" '.invoices[] | select(.date>=$s and .date<=$e) | .id') - sleep 1 -done -echo "in-range invoices: ${#IDS[@]}" -: > ./.lab.txt; OK=0; FAIL=0 -for id in "${IDS[@]}"; do - if R=$(gj "${BASE}/invoices/${id}?api_key=${API_KEY}"); then - OK=$((OK+1)) - echo "$R" | jq -r '.invoice as $i | $i.line_items[]? | select(.item|test("labor";"i")) | "\($i.date)\t\(.quantity)\t\(.user_id)\t\(.item)\t#\($i.number)"' >> ./.lab.txt - else - FAIL=$((FAIL+1)); echo "FAILED id=$id" - fi - sleep 1 -done -echo "fetched OK=$OK failed=$FAIL" -echo "=== labor hours in window by tech ===" -awk -F'\t' '{h[$3]+=$2;n[$3]++} END{for(k in h) printf " user_id %-6s : %7.2f h (%d lines)\n",k,h[k],n[k]}' ./.lab.txt -echo "=== HOWARD (1750) lines 06-01..06-12 ===" -awk -F'\t' '$3=="1750"' ./.lab.txt | sort -echo "-----" -awk -F'\t' '$3=="1750"{s+=$2;n++} END{printf "HOWARD billed hours 2026-06-01..2026-06-12: %.2f h (%d lines)\n",s,n}' ./.lab.txt -echo "=== Howard by labor type ===" -awk -F'\t' '$3=="1750"{h[$4]+=$2} END{for(k in h) printf " %-42s %.2f h\n",k,h[k]}' ./.lab.txt -echo "DONE" diff --git a/.invcfg b/.invcfg deleted file mode 100644 index 53f6988e..00000000 --- a/.invcfg +++ /dev/null @@ -1,92 +0,0 @@ -url = "https://computerguru.syncromsp.com/api/v1/invoices/1650665832 ?api_key=Tde5174a6e9e312d14-02fd5bfe0f0ee40c87d027507c680e18" -output = "./.inv/1650665832 .json" -url = "https://computerguru.syncromsp.com/api/v1/invoices/1650664905 ?api_key=Tde5174a6e9e312d14-02fd5bfe0f0ee40c87d027507c680e18" -output = "./.inv/1650664905 .json" -url = "https://computerguru.syncromsp.com/api/v1/invoices/1650663398 ?api_key=Tde5174a6e9e312d14-02fd5bfe0f0ee40c87d027507c680e18" -output = "./.inv/1650663398 .json" -url = "https://computerguru.syncromsp.com/api/v1/invoices/1650663339 ?api_key=Tde5174a6e9e312d14-02fd5bfe0f0ee40c87d027507c680e18" -output = "./.inv/1650663339 .json" -url = "https://computerguru.syncromsp.com/api/v1/invoices/1650653134 ?api_key=Tde5174a6e9e312d14-02fd5bfe0f0ee40c87d027507c680e18" -output = "./.inv/1650653134 .json" -url = "https://computerguru.syncromsp.com/api/v1/invoices/1650651104 ?api_key=Tde5174a6e9e312d14-02fd5bfe0f0ee40c87d027507c680e18" -output = "./.inv/1650651104 .json" -url = "https://computerguru.syncromsp.com/api/v1/invoices/1650647313 ?api_key=Tde5174a6e9e312d14-02fd5bfe0f0ee40c87d027507c680e18" -output = "./.inv/1650647313 .json" -url = "https://computerguru.syncromsp.com/api/v1/invoices/1650647305 ?api_key=Tde5174a6e9e312d14-02fd5bfe0f0ee40c87d027507c680e18" -output = "./.inv/1650647305 .json" -url = "https://computerguru.syncromsp.com/api/v1/invoices/1650647233 ?api_key=Tde5174a6e9e312d14-02fd5bfe0f0ee40c87d027507c680e18" -output = "./.inv/1650647233 .json" -url = "https://computerguru.syncromsp.com/api/v1/invoices/1650639454 ?api_key=Tde5174a6e9e312d14-02fd5bfe0f0ee40c87d027507c680e18" -output = "./.inv/1650639454 .json" -url = "https://computerguru.syncromsp.com/api/v1/invoices/1650638663 ?api_key=Tde5174a6e9e312d14-02fd5bfe0f0ee40c87d027507c680e18" -output = "./.inv/1650638663 .json" -url = "https://computerguru.syncromsp.com/api/v1/invoices/1650637398 ?api_key=Tde5174a6e9e312d14-02fd5bfe0f0ee40c87d027507c680e18" -output = "./.inv/1650637398 .json" -url = "https://computerguru.syncromsp.com/api/v1/invoices/1650627518 ?api_key=Tde5174a6e9e312d14-02fd5bfe0f0ee40c87d027507c680e18" -output = "./.inv/1650627518 .json" -url = "https://computerguru.syncromsp.com/api/v1/invoices/1650627183 ?api_key=Tde5174a6e9e312d14-02fd5bfe0f0ee40c87d027507c680e18" -output = "./.inv/1650627183 .json" -url = "https://computerguru.syncromsp.com/api/v1/invoices/1650623589 ?api_key=Tde5174a6e9e312d14-02fd5bfe0f0ee40c87d027507c680e18" -output = "./.inv/1650623589 .json" -url = "https://computerguru.syncromsp.com/api/v1/invoices/1650620815 ?api_key=Tde5174a6e9e312d14-02fd5bfe0f0ee40c87d027507c680e18" -output = "./.inv/1650620815 .json" -url = "https://computerguru.syncromsp.com/api/v1/invoices/1650613747 ?api_key=Tde5174a6e9e312d14-02fd5bfe0f0ee40c87d027507c680e18" -output = "./.inv/1650613747 .json" -url = "https://computerguru.syncromsp.com/api/v1/invoices/1650613746 ?api_key=Tde5174a6e9e312d14-02fd5bfe0f0ee40c87d027507c680e18" -output = "./.inv/1650613746 .json" -url = "https://computerguru.syncromsp.com/api/v1/invoices/1650612759 ?api_key=Tde5174a6e9e312d14-02fd5bfe0f0ee40c87d027507c680e18" -output = "./.inv/1650612759 .json" -url = "https://computerguru.syncromsp.com/api/v1/invoices/1650607364 ?api_key=Tde5174a6e9e312d14-02fd5bfe0f0ee40c87d027507c680e18" -output = "./.inv/1650607364 .json" -url = "https://computerguru.syncromsp.com/api/v1/invoices/1650601747 ?api_key=Tde5174a6e9e312d14-02fd5bfe0f0ee40c87d027507c680e18" -output = "./.inv/1650601747 .json" -url = "https://computerguru.syncromsp.com/api/v1/invoices/1650592886 ?api_key=Tde5174a6e9e312d14-02fd5bfe0f0ee40c87d027507c680e18" -output = "./.inv/1650592886 .json" -url = "https://computerguru.syncromsp.com/api/v1/invoices/1650591734 ?api_key=Tde5174a6e9e312d14-02fd5bfe0f0ee40c87d027507c680e18" -output = "./.inv/1650591734 .json" -url = "https://computerguru.syncromsp.com/api/v1/invoices/1650588959 ?api_key=Tde5174a6e9e312d14-02fd5bfe0f0ee40c87d027507c680e18" -output = "./.inv/1650588959 .json" -url = "https://computerguru.syncromsp.com/api/v1/invoices/1650579125 ?api_key=Tde5174a6e9e312d14-02fd5bfe0f0ee40c87d027507c680e18" -output = "./.inv/1650579125 .json" -url = "https://computerguru.syncromsp.com/api/v1/invoices/1650578451 ?api_key=Tde5174a6e9e312d14-02fd5bfe0f0ee40c87d027507c680e18" -output = "./.inv/1650578451 .json" -url = "https://computerguru.syncromsp.com/api/v1/invoices/1650578046 ?api_key=Tde5174a6e9e312d14-02fd5bfe0f0ee40c87d027507c680e18" -output = "./.inv/1650578046 .json" -url = "https://computerguru.syncromsp.com/api/v1/invoices/1650577261 ?api_key=Tde5174a6e9e312d14-02fd5bfe0f0ee40c87d027507c680e18" -output = "./.inv/1650577261 .json" -url = "https://computerguru.syncromsp.com/api/v1/invoices/1650577256 ?api_key=Tde5174a6e9e312d14-02fd5bfe0f0ee40c87d027507c680e18" -output = "./.inv/1650577256 .json" -url = "https://computerguru.syncromsp.com/api/v1/invoices/1650577242 ?api_key=Tde5174a6e9e312d14-02fd5bfe0f0ee40c87d027507c680e18" -output = "./.inv/1650577242 .json" -url = "https://computerguru.syncromsp.com/api/v1/invoices/1650573500 ?api_key=Tde5174a6e9e312d14-02fd5bfe0f0ee40c87d027507c680e18" -output = "./.inv/1650573500 .json" -url = "https://computerguru.syncromsp.com/api/v1/invoices/1650562080 ?api_key=Tde5174a6e9e312d14-02fd5bfe0f0ee40c87d027507c680e18" -output = "./.inv/1650562080 .json" -url = "https://computerguru.syncromsp.com/api/v1/invoices/1650560328 ?api_key=Tde5174a6e9e312d14-02fd5bfe0f0ee40c87d027507c680e18" -output = "./.inv/1650560328 .json" -url = "https://computerguru.syncromsp.com/api/v1/invoices/1650559789 ?api_key=Tde5174a6e9e312d14-02fd5bfe0f0ee40c87d027507c680e18" -output = "./.inv/1650559789 .json" -url = "https://computerguru.syncromsp.com/api/v1/invoices/1650552739 ?api_key=Tde5174a6e9e312d14-02fd5bfe0f0ee40c87d027507c680e18" -output = "./.inv/1650552739 .json" -url = "https://computerguru.syncromsp.com/api/v1/invoices/1650552617 ?api_key=Tde5174a6e9e312d14-02fd5bfe0f0ee40c87d027507c680e18" -output = "./.inv/1650552617 .json" -url = "https://computerguru.syncromsp.com/api/v1/invoices/1650551711 ?api_key=Tde5174a6e9e312d14-02fd5bfe0f0ee40c87d027507c680e18" -output = "./.inv/1650551711 .json" -url = "https://computerguru.syncromsp.com/api/v1/invoices/1650547372 ?api_key=Tde5174a6e9e312d14-02fd5bfe0f0ee40c87d027507c680e18" -output = "./.inv/1650547372 .json" -url = "https://computerguru.syncromsp.com/api/v1/invoices/1650547363 ?api_key=Tde5174a6e9e312d14-02fd5bfe0f0ee40c87d027507c680e18" -output = "./.inv/1650547363 .json" -url = "https://computerguru.syncromsp.com/api/v1/invoices/1650546905 ?api_key=Tde5174a6e9e312d14-02fd5bfe0f0ee40c87d027507c680e18" -output = "./.inv/1650546905 .json" -url = "https://computerguru.syncromsp.com/api/v1/invoices/1650536651 ?api_key=Tde5174a6e9e312d14-02fd5bfe0f0ee40c87d027507c680e18" -output = "./.inv/1650536651 .json" -url = "https://computerguru.syncromsp.com/api/v1/invoices/1650536425 ?api_key=Tde5174a6e9e312d14-02fd5bfe0f0ee40c87d027507c680e18" -output = "./.inv/1650536425 .json" -url = "https://computerguru.syncromsp.com/api/v1/invoices/1650536407 ?api_key=Tde5174a6e9e312d14-02fd5bfe0f0ee40c87d027507c680e18" -output = "./.inv/1650536407 .json" -url = "https://computerguru.syncromsp.com/api/v1/invoices/1650535886 ?api_key=Tde5174a6e9e312d14-02fd5bfe0f0ee40c87d027507c680e18" -output = "./.inv/1650535886 .json" -url = "https://computerguru.syncromsp.com/api/v1/invoices/1650531028 ?api_key=Tde5174a6e9e312d14-02fd5bfe0f0ee40c87d027507c680e18" -output = "./.inv/1650531028 .json" -url = "https://computerguru.syncromsp.com/api/v1/invoices/1650530605 ?api_key=Tde5174a6e9e312d14-02fd5bfe0f0ee40c87d027507c680e18" -output = "./.inv/1650530605 .json" diff --git a/.lab.txt b/.lab.txt deleted file mode 100644 index e69de29b..00000000 diff --git a/session-logs/2026-06/2026-06-26-howard-june-billing-reconciliation.md b/session-logs/2026-06/2026-06-26-howard-june-billing-reconciliation.md index 4ac6101c..5ec42915 100644 --- a/session-logs/2026-06/2026-06-26-howard-june-billing-reconciliation.md +++ b/session-logs/2026-06/2026-06-26-howard-june-billing-reconciliation.md @@ -153,3 +153,18 @@ into the `/syncro` skill (attribution user_id 1750). #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).