Field Calendar Week-Revenue Gutter (2026-07-31)
What: The “Wk” week-button gutter on the field calendar month view
(right edge, after Sunday) shows per-week revenue for up_owner only:
invoiced amount (green, top) over a ”+$X” live estimate for the week’s
not-yet-invoiced inspections (muted, below). Tooltip and the week detail
panel show full amounts with project counts. Other roles and the PPDR
calendar keep the plain “Wk” button. Dustin’s ask: “just for Dustin” —
deliberately NOT extended to up_admin (financial data).
Backend (entirely-api 268251b):
GET /portal/calendar/week-revenue?start_date&end_dateinroutes/portal_calendar_drag.py,require_role({"up_owner"}).services/calendar_revenue_service.py: visits from theget_site_visits_in_rangeRPC; a project attributes to the Mon–Sun week of its latest non-cancelled in-range visit (no double-count across weeks). Skips: desk-review projects (PPDR calendar owns those), declined, Closed-without-invoice. Actual = storedprojects.invoice_totalfor invoice_status Sent/Paid + the legacy Closed+invoice_number archival case. Potential =build_invoice_context(record_id, enrich=False).subtotalper the no-duplicate-calculator rule; estimates TTL-cached 10 min, statuses always fresh → amounts move potential→actual as invoices send.build_invoice_contextgainedenrich: bool = True. enrich=False simulates missing WTR/ENC parent lines in-memory instead of writingcreate_synthetic_sow_line— a passive calendar view must never create SOW lines or clear ABSoW reconciliation stamps (verified: 0 absow audit events after live smoke tests that priced WTR projects).
Frontend (entirely-portal 48f1aca): CalendarPage fetches revenue
alongside events when user.role === 'up_owner' && variant === 'field';
gutter column widens 24px→58px; falls back to “Wk” until loaded.
Tests: tests/test_calendar_week_revenue.py (11 — date parsing incl.
UTC→ET shift, Monday bucketing, latest-visit dedupe, classification).
Verified live: endpoint 401 anon / 403 scheduler / 200 owner with
5 weeks of correct data (~3.7s cold, cached after); bundle
index-Dh335gvw.js live with the feature string.