Commit graph

21 commits

Author SHA1 Message Date
4137813fc7 Use central Anthropic key for AI insights; add update-check banner
AI insights now fetches the Claude API key from the central settings
service instead of storing its own encrypted copy, so wages and other
apps can share the same key. Also wires up the update-available banner
using the existing version-check hook pattern.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-24 20:43:03 +00:00
2a7ee1d6b8 Expand AI insight: fix broken competitor query, add continuity, 30-day horizon, holidays
- Fix gather_competitor_data() tier filter: it queried tier IN ('primary','secondary'),
  values that never exist (real values are 'own'/'competitor'/'market'), so the
  cheapest-competitor comparison has always silently returned nothing.
- Feed the previous insight back into the prompt so the model can note what's
  changed/resolved instead of repeating itself.
- Extend forecast horizon from 14 to 30 days; add a per-day revenue table
  alongside the existing occupancy table.
- Annotate the occupancy table with UK (England) bank holidays.
- Add a same-channel market-movement section (B.com vs B.com, rack vs rack)
  diffing rates against the last insight's snapshot, threshold £3.
- Add a parsed headline field + insight history list on the Dashboard,
  collapsed to headline/age and expandable to full content.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-24 18:03:31 +00:00
454f34d390 Add dow_align param to /forecast/revenue and /forecast/rooms
Allows callers to switch between 364-day DOW-aligned prior year
and same calendar-date prior year comparison.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-21 18:28:55 +00:00
185b2ec163 Fall back to DOW averages for dry/wet when spend settings not configured
Covers model returns data (covers * spend) but if resos spend settings are
absent the result is zero, which previously bypassed the DOW fallback. Now
fall back to DOW when the covers-based dry or wet is zero.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-21 18:17:42 +00:00
1fae3ce60b Fix sync not updating arrival/departure dates on re-sync
ON CONFLICT clause was missing arrival_date, departure_date, nights, and
room_number — so early checkouts (where NewBook updates booking_departure
to the actual checkout date) never propagated to the DB columns. Reverts
the COUNT(DISTINCT) workaround since the root cause is now fixed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-21 17:23:09 +00:00
455396c965 Fix cascading InFailedSQLTransactionError in covers forecast
When forecast_rooms_for_date throws inside covers_model, asyncpg aborts the
whole transaction. The exception was being caught with a warning but no rollback,
so every subsequent query in the same request failed. Added db.rollback() in
all three exception handlers (breakfast pickupv2, dinner pickupv2, per-day loop)
and moved public.py's rollback into a finally block so it always fires even
when covers_model returns normally with a corrupted transaction.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-21 16:50:09 +00:00
4bad66c91a Fix revenue endpoint 500 — rollback SQLAlchemy session after caught exceptions
When forecast_covers_range or forecast_revenue_for_date throw DB exceptions,
the swallowed exception leaves the async session in an aborted transaction state.
Subsequent queries (DOW averages, per-date accom) then fail with
InFailedSQLTransactionError. Adding db.rollback() in the except blocks
resets the session so the fallback path can continue cleanly.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-21 14:53:54 +00:00
da8c27d0de Add DOW-average fallback for dry/wet forecast when covers data is zero
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-20 12:41:53 +00:00
f0d4fb3beb Use occupied_rooms from occupancy report for past-date OTB, excluding overflow
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-20 12:37:28 +00:00
d8ad753a62 Fix available_rooms to use is_included flag from room category settings
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-20 12:32:45 +00:00
4e783bd508 Fix available_rooms query: use newbook_occupancy_report_data not daily_occupancy
The table is newbook_occupancy_report_data (per-category rows). Aggregate
SUM(available - maintenance) WHERE category_id != '5' to get the correct
available room count excluding overflow and maintenance.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-20 11:32:35 +00:00
e04ae18711 Fix /public/forecast/rooms to use available_rooms excluding overflow
Replace static system_config.total_rooms (80, includes overflow) with
per-day available_rooms from daily_occupancy table. This ensures
occupancy % is calculated against the correct base (non-overflow rooms)
consistent with how the rest of the app reports occupancy. Falls back
to system_config.total_rooms when daily_occupancy has no data for a date.
Also adds available_rooms per-day to the response payload.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-20 10:51:51 +00:00
5fbf155f62 Add weather sync job, API endpoints and settings UI
Fetches daily ERA5 weather from Open-Meteo (no API key).
Configurable location, timezone and sync time via Settings.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-07-13 21:10:03 +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
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
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
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
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
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