closed.py 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. from datetime import date, timedelta
  2. from typing import Callable, TYPE_CHECKING
  3. from fastapi import APIRouter, BackgroundTasks
  4. from pydantic import BaseModel
  5. from room_cal.store import DEFAULT_CALENDAR_NAME
  6. from room_cal.closed import Closed, ClosedData
  7. from room_cal.actions.fetch_closed import fetch_closed
  8. from room_cal.actions.push_closed import push_closed
  9. from room_cal.workflows import _bg, _push
  10. from room_cal._api_source import API_SOURCE
  11. from room_cal._periodic import register_periodic
  12. from room_cal._utils import local_today, get_config
  13. if TYPE_CHECKING:
  14. from room_cal.service_api import ServiceAPI
  15. router = APIRouter(prefix='/workflow')
  16. _SOURCE = API_SOURCE
  17. class SetClosedBody(BaseModel):
  18. services: list[str] = []
  19. async def set_closed(
  20. target_date: date,
  21. services: list[str],
  22. *,
  23. source: dict = _SOURCE,
  24. schedule: Callable | None = None,
  25. ) -> None:
  26. await Closed(DEFAULT_CALENDAR_NAME).set(target_date, ClosedData(services=services, source=source))
  27. await _push(push_closed(target_date, target_date), schedule)
  28. async def delete_closed(
  29. target_date: date,
  30. *,
  31. source: dict = _SOURCE,
  32. schedule: Callable | None = None,
  33. ) -> None:
  34. await Closed(DEFAULT_CALENDAR_NAME).set(target_date, ClosedData(services=[], source=source))
  35. await _push(push_closed(target_date, target_date), schedule)
  36. async def sync_closed(
  37. start_date: date,
  38. end_date: date,
  39. *,
  40. schedule: Callable | None = None,
  41. ) -> None:
  42. result = await fetch_closed(start_date, end_date)
  43. if result.changed:
  44. await _push(push_closed(start_date, end_date), schedule)
  45. @router.post('/closed/{target_date}', status_code=204)
  46. async def workflow_set_closed(target_date: date, body: SetClosedBody, bg: BackgroundTasks):
  47. await set_closed(target_date, body.services, schedule=lambda c: bg.add_task(_bg, c))
  48. @router.delete('/closed/{target_date}', status_code=204)
  49. async def workflow_delete_closed(target_date: date, bg: BackgroundTasks):
  50. await delete_closed(target_date, schedule=lambda c: bg.add_task(_bg, c))
  51. @router.post('/closed/{start_date}/{end_date}', status_code=204)
  52. async def workflow_sync_closed(start_date: date, end_date: date, bg: BackgroundTasks):
  53. await sync_closed(start_date, end_date, schedule=lambda c: bg.add_task(_bg, c))
  54. async def _periodic_push_short(api: 'ServiceAPI') -> None:
  55. start = local_today()
  56. window = get_config().global_.reservation_window_days
  57. await push_closed(start, start + timedelta(days=window), api=api)
  58. async def _periodic_push_long(api: 'ServiceAPI') -> None:
  59. start = local_today()
  60. window = get_config().global_.long_window_days
  61. await push_closed(start, start + timedelta(days=window), api=api)
  62. register_periodic(_periodic_push_short, timedelta(hours=6))
  63. register_periodic(_periodic_push_long, timedelta(days=1))