Commit graph

29 commits

Author SHA1 Message Date
ba386e316e Fix Resos sync interrupted by health check restart
Yield to event loop after each booking DB commit so FastAPI can
respond to Docker health checks during long syncs.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-13 20:29:50 +00:00
0563ad7fc2 AI insights: UK dates, GBP, remove rate parity section
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-13 19:57:40 +00:00
9761e88e9b Add missing Resos tables to schema.sql
resos_custom_field_mapping, resos_opening_hours_mapping,
resos_manual_breakfast_periods, resos_bookings_data,
resos_bookings_stats, resos_booking_pace were never added to the
schema — they only existed in the original standalone Postgres instance.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-13 19:01:50 +00:00
7dfaa5a9fb Add bare /health location to nginx for management monitor compatibility
The management monitor checks http://{host}:{port}/health (no slug prefix).
Adds a location = /health alias alongside the existing /forecasting/health
so both the slug URL (browser/NPM) and the bare path (monitor) work.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-13 17:07:24 +00:00
1aa52c563e Add Resos connection status card to Settings — read-only, sourced from central Settings
Replaces the removed API key form with a status card showing whether the
Resos key is configured in the central Settings app, plus a Test Connection
button. Adds back the GET /settings/resos and POST /settings/resos/test
endpoints (now reading from central_settings rather than system_config).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-13 15:02:42 +00:00
3650c92175 Move Resos API key to central Settings service; add sidebar scrollbar styling
Removes the standalone resos_api_key from the forecasting app's own
system_config table. All credential fetches now go through
central_settings.get_resos_credentials() / get_resos_credentials_sync()
which pull from the Settings app (LXC 116) via the internal integration
endpoint — the same pattern already used for NewBook. The Resos API
Config section is removed from the forecasting Settings page; users
manage the key in the central Settings app instead.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-13 14:35:35 +00:00
9057d764fa Configurable inactivity timeout — disabled automatically in PWA/standalone mode 2026-07-13 12:29:01 +00:00
e4152b183b Add shared device inactivity timeout to AuthGate 2026-07-13 11:53:05 +00:00
dde41bc5d1 Escape HTML entities before rendering AI insight content
The renderContent() function used dangerouslySetInnerHTML without
first sanitizing the AI-generated text, allowing any HTML in the
model response to execute in the browser. Added escHtml() helper
and applied it before the bold-substitution regex.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-13 09:25:02 +00:00
fce9048902 Replace letter icons with Lucide PWA icons 2026-07-11 20:30:11 +00:00
1ee3f7919f Make forecasting installable as a PWA
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-11 11:27:00 +00:00
084555efdb Fix mid-session 401 redirecting iframe to wrong URL, causing portal EmbeddedFallback
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-10 11:43:58 +00:00
f3e02c3867 Fix expired session showing EmbeddedFallback in portal iframe
When the JWT expired, AuthGate redirected window.location to /auth/login
which loaded inside the portal iframe. The portal detected window.self !==
window.top and showed the EmbeddedFallback ("This app isn't available yet")
instead of the login page.

Redirect window.top instead so the portal itself navigates to /login.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-09 20:19:36 +00:00
76ed477c3a Remove bookability and competitor rates — moved to Rate Monitor app
Deletes bookability.py, competitor_rates.py, Bookability.tsx,
CompetitorRates.tsx. Removes their imports, router mounts, and nav items.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-05 12:14:26 +00:00
b14d3b414e schema: add forecast_runs, pickup_snapshots, pickup_curves tables
forecast_runs was missing, causing all manual/scheduled forecast jobs to
fail on startup. pickup_snapshots and pickup_curves are referenced by the
pickup model but were absent from schema.sql.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-05 11:17:02 +00:00
0e43841783 Clear stale sync_log 'running' entries on startup
After a container restart any in-progress jobs leave orphaned 'running' rows
with no completed_at. Added startup cleanup to mark them failed, so the UI
doesn't show a permanently stuck status.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-05 10:12:19 +00:00
1612468122 Bookability: run date refresh synchronously, update timestamp immediately
Backend now awaits the refresh in a thread executor instead of queuing a
background task, so the response returns only after data is written. Frontend
drops the 3s setTimeout and invalidates the cache immediately on success.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-05 10:08:20 +00:00
7223ae9c30 Bookability: show last-updated timestamp per date column
Backend adds valid_from to DateRateInfo and computes date_last_updated dict
(max valid_from across categories per date). Frontend renders it as a small
timestamp below the date in each column header — time only if today, date+time
if older. Full ISO string in title tooltip.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-05 10:03:17 +00:00
9e6801482f Fix Forecasts nav: useParams key was forecastId but route param is :page
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-05 09:48:14 +00:00
effad0a4e2 Fix schema: add missing tables and correct forecast_snapshots structure
- Add booking_com_hotels and booking_com_rates (competitor rate scraper tables)
- Fix forecast_snapshots: was using old pivoted schema (snapshot_date,
  prophet_value etc.); code expects normalised rows (perception_date, model,
  forecast_value, actual_value). Add DO block migration to drop+recreate if
  old schema is detected.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-05 09:28:52 +00:00
3c66e777e4 Patch fetch_room_categories and fetch_gl_accounts to use central NewBook creds
These two endpoints were missed in the central settings migration. They now try
the Settings service first and fall back to app-local system_config.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-05 09:26:49 +00:00
7c8ea1af15 Add favicon.svg for forecasting app
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-05 09:22:13 +00:00
c0b6af4383 Add booking_scrape_log table to schema.sql
Missing from initial schema; used by competitor rates scraper and cleanup_stale_batches on startup.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-05 09:19:49 +00:00
3e9442b1b9 Fix schema init: use psycopg2 directly to bypass SQLAlchemy param parsing
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-05 09:18:37 +00:00
c11914a66b Fix schema init: use exec_driver_sql to avoid PL/pgSQL bind-param collision
SQLAlchemy's text() treats $1/$2 in PL/pgSQL blocks as bindparams and raises
InvalidRequestError. exec_driver_sql sends raw SQL directly to psycopg2,
bypassing that processing. Without this all tables are missing on startup.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-05 09:12:56 +00:00
aeb99650bd NewBook credentials from central Settings service
Stack-wide NewBook config lives in the Settings app (LXC 116) and is
fetched live via SETTINGS_URL/SETTINGS_SECRET — same pattern as cashup,
room-planner and maintenance. App-local system_config credentials remain
as a fallback for standalone/dev use. The app's Settings → Newbook page
no longer edits credentials; it points to the central app and keeps
Test Connection.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-04 19:36:41 +00:00
851747b561 fix: pin top-bar/page-content grid rows at mobile widths
page-content kept grid-row 1/-1 from the desktop rule, so the
top-bar auto-placed into an implicit row below the content —
the nav menu rendered at the bottom of the page.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-04 19:17:01 +00:00
d128c6e6bb fix: restore app-local API key functions in auth.py
config.py and public.py import get_api_key_auth/get_all_api_keys/
create_api_key/revoke_api_key/delete_api_key — the public-API key
system is app-local (api_keys table), not part of the central auth
that was replaced, so it should have been kept in the port.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-04 19:11:00 +00:00
75d2c1fa9d Forecasting app: hybrid port to HNF stack
Python FastAPI ML backend kept intact; auth replaced with central hnf_session cookie verification. Frontend rebuilt on React 18 + TS + Vite with stack design system, Plotly charts retained. Shared Postgres via DATABASE_URL; schema applied on startup.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-04 18:49:34 +00:00