app.bettersight.io/backend
JasonFraser d4f2c7d96b Phase 4: Sheet-initiated pull integration (Apps Script) + template import
Rearchitects the Sheet integration per updated CLAUDE.md §15: a
stateless Flask backend has no way to reach into whichever Sheet a PM
has open, so the Sheet pulls its latest results on demand rather than
Flask ever pushing to it. This is also the simpler path for
non-technical users — no Sheet ID to find/paste, no service-account
sharing, just one button in the sidebar.

Apps Script (appscript/, new):
- appsscript.json — Editor Add-on manifest, spreadsheets.currentonly
  scope (touches only whichever Sheet is open, nothing else in Drive)
- Code.gs — onOpen/onInstall/onHomepage, opens the sidebar
- Validation.gs — validateLicence() (6hr cache, POST /validate-email),
  plus markOnboardingStepOnce_() shared helper
- Sync.gs — pullLatestResults()/getWorkbookTabs()/detectColumns(),
  with a real header-alias map for every STANDARD_FIELDS column
  (majorityPrice matches "Rack Rate"/"Standard Price"/etc, not just
  one exact label) so silent write failures don't happen from a PM
  naming a column slightly differently than expected
- Sidebar.html — tab selector + Pull latest results + last-pull status

Backend:
- GET /research/history/latest (email-resolved) replaces the removed
  POST /sheet/push and GET /sheet/tabs
- GET /account/template now reads TEMPLATE_SHEET_URL instead of a
  hardcoded placeholder
- PATCH /account/onboarding now accepts either a JWT session (dashboard)
  or an email in the body (Apps Script has no JWT, only the PM's Google
  email) — this was a real gap: Sync.gs's onboarding-flag calls would
  have 401'd against the JWT-only version
- onboarding_service.DEFAULT_CHECKLIST corrected to the current schema
  (template_imported/sidebar_installed/sync_from_sheet, not the stale
  push_to_sheet/download_template)
- Fixed the same stale field names in CLAUDE.md §32's onboarding
  runbook example payload, so it doesn't teach a future tenant-creation
  script the wrong schema

Frontend:
- PushToSheet.vue removed, replaced by SyncToSheet.vue — a clipboard
  copy button + instructions to use the sidebar, no tab selector (tab
  selection lives in the sidebar, where the workbook is actually open)
- AccountPage.vue's template section rebuilt as three items: open
  template, two-step import instructions + sidebar install link, and
  a deliberately no-op verification input (never validated/fetched/
  stored — the confirmation is purely the PM telling themselves it's
  done, per explicit instruction not to create a dependency on their
  workbook)
- useOnboardingTour.js step 5 updated to match

220 backend tests passing. Frontend production build verified clean.
Apps Script (.gs/.html) cannot be unit-tested in this environment —
no Google Apps Script runtime available locally; verified only by
careful cross-file consistency review (function names/signatures
matching across Code.gs/Validation.gs/Sync.gs/Sidebar.html).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-01 17:29:20 -04:00
..
config Phase 2: refactor legacy app.py into core/industries/config structure 2026-07-01 12:44:35 -04:00
core Phase 2: refactor legacy app.py into core/industries/config structure 2026-07-01 12:44:35 -04:00
industries Phase 2: refactor legacy app.py into core/industries/config structure 2026-07-01 12:44:35 -04:00
pb_migrations Phase 1: data foundation — schema, repositories, services, routes, jobs 2026-07-01 12:21:04 -04:00
repositories Phase 4: Sheet-initiated pull integration (Apps Script) + template import 2026-07-01 17:29:20 -04:00
services Phase 4: Sheet-initiated pull integration (Apps Script) + template import 2026-07-01 17:29:20 -04:00
templates/emails Fill in missing Resend templates + Freescout support links 2026-07-01 13:32:56 -04:00
tests Phase 4: Sheet-initiated pull integration (Apps Script) + template import 2026-07-01 17:29:20 -04:00
api.py Phase 4: Sheet-initiated pull integration (Apps Script) + template import 2026-07-01 17:29:20 -04:00
app.py Phase 1: data foundation — schema, repositories, services, routes, jobs 2026-07-01 12:21:04 -04:00
errors.py Phase 1: data foundation — schema, repositories, services, routes, jobs 2026-07-01 12:21:04 -04:00
extensions.py Phase 1: data foundation — schema, repositories, services, routes, jobs 2026-07-01 12:21:04 -04:00
jobs.py Phase 1: data foundation — schema, repositories, services, routes, jobs 2026-07-01 12:21:04 -04:00
requirements.txt Phase 2: refactor legacy app.py into core/industries/config structure 2026-07-01 12:44:35 -04:00