Port occupancy sync + category ordering from the forecasting version

- Bookability showed no availability because newbook_occupancy_report_data
  was never populated: add reports_occupancy client method and
  sync_occupancy job, run before rates in both Sync Now and the daily
  schedule (single fast API call)
- Category order: default display_order to the Newbook category id on
  sync (was 0 → alphabetical), preserve manual order on re-sync, extend
  PATCH to accept display_order, add up/down reorder arrows in Settings

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
jtricerolph 2026-07-05 14:18:03 +00:00
parent c924d793e8
commit f51e1dcb76
5 changed files with 199 additions and 9 deletions

View file

@ -129,6 +129,32 @@ class NewbookRatesClient:
return sorted(categories.values(), key=lambda c: c["category_name"])
async def get_occupancy_report(self, from_date: date, to_date: date) -> List[Dict]:
"""
Fetch the occupancy report (reports_occupancy) for a date range.
Returns a list of category objects, each with nested per-date
occupancy: {category_id, category_name, occupancy: {date: {available,
occupied, maintenance, allotted, revenue_gross, revenue_net}}}.
Single response, no pagination.
"""
payload = self._get_auth_payload()
payload.update({
"period_from": f"{from_date.isoformat()} 00:00:00",
"period_to": f"{to_date.isoformat()} 23:59:59",
})
response = await self.client.post(
self._get_url("reports_occupancy"),
json=payload,
auth=(self.username, self.password)
)
response.raise_for_status()
data = response.json()
if not data.get("success"):
raise NewbookRatesError(f"Newbook occupancy report failed: {data.get('message')}")
return data.get("data") or []
async def get_category_rates(
self,
category_id: str,