Refactor duty authentication and event type handling
- Introduced a new function `get_authenticated_username` to centralize Mini App authentication logic, improving code readability and maintainability. - Updated the duty fetching logic to map unknown event types to "duty" for consistent API responses. - Enhanced the `get_duties` function to include duties starting on the last day of the specified date range. - Improved session management in the database layer to ensure rollback on exceptions. - Added tests to validate the new authentication flow and event type handling.
This commit is contained in:
@@ -85,14 +85,15 @@ def get_duties(
|
||||
) -> list[tuple[Duty, str]]:
|
||||
"""Return list of (Duty, full_name) overlapping the given date range.
|
||||
|
||||
from_date/to_date are YYYY-MM-DD (first/last day of month in client's local calendar).
|
||||
Duty.start_at and end_at are stored in UTC (ISO 8601 with Z); lexicographic comparison
|
||||
with date strings yields correct overlap.
|
||||
from_date/to_date are YYYY-MM-DD (inclusive). Duty.start_at and end_at are stored
|
||||
in UTC (ISO 8601 with Z). Use to_date_next so duties starting on to_date are included
|
||||
(start_at like 2025-01-31T09:00:00Z is > "2025-01-31" lexicographically).
|
||||
"""
|
||||
to_date_next = (datetime.fromisoformat(to_date + "T00:00:00") + timedelta(days=1)).strftime("%Y-%m-%d")
|
||||
q = (
|
||||
session.query(Duty, User.full_name)
|
||||
.join(User, Duty.user_id == User.id)
|
||||
.filter(Duty.start_at <= to_date, Duty.end_at >= from_date)
|
||||
.filter(Duty.start_at < to_date_next, Duty.end_at >= from_date)
|
||||
)
|
||||
return list(q.all())
|
||||
|
||||
|
||||
@@ -40,7 +40,10 @@ class DutyInDb(DutyBase):
|
||||
|
||||
|
||||
class DutyWithUser(DutyInDb):
|
||||
"""Duty with full_name and event_type for calendar display."""
|
||||
"""Duty with full_name and event_type for calendar display.
|
||||
|
||||
event_type: only these values are returned; unknown DB values are mapped to "duty" in the API.
|
||||
"""
|
||||
|
||||
full_name: str
|
||||
event_type: Literal["duty", "unavailable", "vacation"] = "duty"
|
||||
|
||||
@@ -19,10 +19,13 @@ _SessionLocal = None
|
||||
|
||||
@contextmanager
|
||||
def session_scope(database_url: str) -> Generator[Session, None, None]:
|
||||
"""Context manager: yields a session and closes it on exit."""
|
||||
"""Context manager: yields a session, rolls back on exception, closes on exit."""
|
||||
session = get_session(database_url)
|
||||
try:
|
||||
yield session
|
||||
except Exception:
|
||||
session.rollback()
|
||||
raise
|
||||
finally:
|
||||
session.close()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user