mirror of
https://github.com/Sea-Haven-Industries/afterhours-shift-manager.git
synced 2026-10-07 16:19:00 +00:00
* feat(api): collapse Slack, portal, and jobs onto Fargate (PLAT-216) Move HTTP and scheduled work onto one always-on Flask task so after-hours loses Lambda cold start without changing the Cognito or roster contracts. * fix(portal-api): keep CORS headers on unexpected 500s Portal SPA error handling needs Access-Control-Allow-Origin even when DynamoDB or other internals fail, otherwise the browser hides the 500. * fix(api): retarget holidays per account and ship App Home changelog (PLAT-216) * fix(iam): list ECS tasks and fail closed on non-prod Paychex (PLAT-216) * fix(portal-api): serve portal JSON with an explicit JSON content type
61 lines
1.9 KiB
Python
61 lines
1.9 KiB
Python
"""Lambda handler — repoints 3CX call flow for a holiday day-shift.
|
|
|
|
A holiday is a day-only shift (08:00-17:00 ET), one HOLIDAY record per date.
|
|
At 08:00 this Lambda is invoked with ``{"action": "activate", "date": ...}`` and
|
|
at 17:00 with ``{"action": "deactivate", ...}``.
|
|
"""
|
|
|
|
import json
|
|
import logging
|
|
import os
|
|
|
|
import shared.sentry_init # noqa: F401
|
|
from shared.holiday_flow import activate, deactivate
|
|
from shared.schedule import ShiftSchedule
|
|
from shared.secrets import get_secret
|
|
from shared.three_cx_client import ThreeCXClient
|
|
|
|
logger = logging.getLogger()
|
|
logger.setLevel(logging.INFO)
|
|
|
|
|
|
def _make_client() -> ThreeCXClient:
|
|
secret_prefix = os.environ["TCX_SECRET_PREFIX"]
|
|
return ThreeCXClient(
|
|
domain=get_secret(f"{secret_prefix}domain"),
|
|
auth_mode="oauth",
|
|
client_id=get_secret(f"{secret_prefix}client-id"),
|
|
client_secret=get_secret(f"{secret_prefix}client-secret"),
|
|
)
|
|
|
|
|
|
def _activate(schedule: ShiftSchedule, date: str) -> dict:
|
|
return activate(schedule, date, client_factory=_make_client)
|
|
|
|
|
|
def _deactivate(schedule: ShiftSchedule, date: str) -> dict:
|
|
return deactivate(schedule, date, client_factory=_make_client)
|
|
|
|
|
|
def handler(event, context):
|
|
action = event.get("action")
|
|
date = event.get("date")
|
|
logger.info("Holiday router invoked: action=%s date=%s", action, date)
|
|
|
|
if not date:
|
|
return {"error": True, "reason": "missing_date"}
|
|
|
|
schedule = ShiftSchedule()
|
|
try:
|
|
if action == "activate":
|
|
result = _activate(schedule, date)
|
|
elif action == "deactivate":
|
|
result = _deactivate(schedule, date)
|
|
else:
|
|
return {"error": True, "reason": "unknown_action", "action": action}
|
|
except Exception:
|
|
logger.exception("Holiday router failed for action=%s date=%s", action, date)
|
|
return {"error": True, "action": action, "date": date}
|
|
|
|
logger.info("Result: %s", json.dumps(result, default=str))
|
|
return result
|