Fix QA findings: null guard on end_datetime, reminders in night briefing, extract filter
- W1: Guard end_datetime null checks in DayBriefing (lines 48, 95, 112) - W2: Include active reminders in pre-5AM night briefing fallback - S1: Extract _not_parent_template filter constant in dashboard.py Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
b18fc0f2c8
commit
084daf5c7f
@ -14,6 +14,13 @@ from app.routers.auth import get_current_session
|
|||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|
||||||
|
# Reusable filter: exclude parent template events (they have a real recurrence_rule).
|
||||||
|
# Some legacy events have "" instead of NULL, so allow both.
|
||||||
|
_not_parent_template = or_(
|
||||||
|
CalendarEvent.recurrence_rule == None,
|
||||||
|
CalendarEvent.recurrence_rule == "",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@router.get("/dashboard")
|
@router.get("/dashboard")
|
||||||
async def get_dashboard(
|
async def get_dashboard(
|
||||||
@ -31,7 +38,7 @@ async def get_dashboard(
|
|||||||
events_query = select(CalendarEvent).where(
|
events_query = select(CalendarEvent).where(
|
||||||
CalendarEvent.start_datetime >= today_start,
|
CalendarEvent.start_datetime >= today_start,
|
||||||
CalendarEvent.start_datetime <= today_end,
|
CalendarEvent.start_datetime <= today_end,
|
||||||
or_(CalendarEvent.recurrence_rule == None, CalendarEvent.recurrence_rule == ""),
|
_not_parent_template,
|
||||||
)
|
)
|
||||||
events_result = await db.execute(events_query)
|
events_result = await db.execute(events_query)
|
||||||
todays_events = events_result.scalars().all()
|
todays_events = events_result.scalars().all()
|
||||||
@ -77,7 +84,7 @@ async def get_dashboard(
|
|||||||
starred_query = select(CalendarEvent).where(
|
starred_query = select(CalendarEvent).where(
|
||||||
CalendarEvent.is_starred == True,
|
CalendarEvent.is_starred == True,
|
||||||
CalendarEvent.start_datetime > now,
|
CalendarEvent.start_datetime > now,
|
||||||
or_(CalendarEvent.recurrence_rule == None, CalendarEvent.recurrence_rule == ""),
|
_not_parent_template,
|
||||||
).order_by(CalendarEvent.start_datetime.asc()).limit(5)
|
).order_by(CalendarEvent.start_datetime.asc()).limit(5)
|
||||||
starred_result = await db.execute(starred_query)
|
starred_result = await db.execute(starred_query)
|
||||||
starred_events = starred_result.scalars().all()
|
starred_events = starred_result.scalars().all()
|
||||||
@ -158,7 +165,7 @@ async def get_upcoming(
|
|||||||
events_query = select(CalendarEvent).where(
|
events_query = select(CalendarEvent).where(
|
||||||
CalendarEvent.start_datetime >= today_start,
|
CalendarEvent.start_datetime >= today_start,
|
||||||
CalendarEvent.start_datetime <= cutoff_datetime,
|
CalendarEvent.start_datetime <= cutoff_datetime,
|
||||||
or_(CalendarEvent.recurrence_rule == None, CalendarEvent.recurrence_rule == ""),
|
_not_parent_template,
|
||||||
)
|
)
|
||||||
events_result = await db.execute(events_query)
|
events_result = await db.execute(events_query)
|
||||||
events = events_result.scalars().all()
|
events = events_result.scalars().all()
|
||||||
|
|||||||
@ -45,11 +45,13 @@ export default function DayBriefing({ upcomingItems, dashboardData, weatherData
|
|||||||
if (hour >= 21 || hour < 5) {
|
if (hour >= 21 || hour < 5) {
|
||||||
// Before 5 AM, "today" still matters — mention remaining items
|
// Before 5 AM, "today" still matters — mention remaining items
|
||||||
if (todayItems.length > 0 && hour < 5) {
|
if (todayItems.length > 0 && hour < 5) {
|
||||||
const remainingToday = todayEvents.filter((e) => isAfter(new Date(e.end_datetime), now));
|
const remainingToday = todayEvents.filter((e) => e.end_datetime && isAfter(new Date(e.end_datetime), now));
|
||||||
if (remainingToday.length > 0) {
|
if (remainingToday.length > 0) {
|
||||||
parts.push(`${remainingToday.length} event${remainingToday.length > 1 ? 's' : ''} still on today.`);
|
parts.push(`${remainingToday.length} event${remainingToday.length > 1 ? 's' : ''} still on today.`);
|
||||||
} else if (todayTodos.length > 0) {
|
} else if (todayTodos.length > 0) {
|
||||||
parts.push(`${todayTodos.length} task${todayTodos.length > 1 ? 's' : ''} due today.`);
|
parts.push(`${todayTodos.length} task${todayTodos.length > 1 ? 's' : ''} due today.`);
|
||||||
|
} else if (activeReminders.length > 0) {
|
||||||
|
parts.push(`${activeReminders.length} reminder${activeReminders.length > 1 ? 's' : ''} set for today.`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -92,7 +94,7 @@ export default function DayBriefing({ upcomingItems, dashboardData, weatherData
|
|||||||
}
|
}
|
||||||
// Afternoon (12PM–5PM)
|
// Afternoon (12PM–5PM)
|
||||||
else if (hour < 17) {
|
else if (hour < 17) {
|
||||||
const remainingEvents = todayEvents.filter((e) => isAfter(new Date(e.end_datetime), now));
|
const remainingEvents = todayEvents.filter((e) => e.end_datetime && isAfter(new Date(e.end_datetime), now));
|
||||||
const completedTodos = todayTodos.length === 0;
|
const completedTodos = todayTodos.length === 0;
|
||||||
if (remainingEvents.length === 0 && completedTodos) {
|
if (remainingEvents.length === 0 && completedTodos) {
|
||||||
parts.push('The rest of your afternoon is clear.');
|
parts.push('The rest of your afternoon is clear.');
|
||||||
@ -109,7 +111,7 @@ export default function DayBriefing({ upcomingItems, dashboardData, weatherData
|
|||||||
}
|
}
|
||||||
// Evening (5PM–9PM)
|
// Evening (5PM–9PM)
|
||||||
else {
|
else {
|
||||||
const eveningEvents = todayEvents.filter((e) => isAfter(new Date(e.end_datetime), now));
|
const eveningEvents = todayEvents.filter((e) => e.end_datetime && isAfter(new Date(e.end_datetime), now));
|
||||||
if (eveningEvents.length === 0 && tomorrowItems.length === 0) {
|
if (eveningEvents.length === 0 && tomorrowItems.length === 0) {
|
||||||
parts.push('Nothing left tonight, and tomorrow is clear too.');
|
parts.push('Nothing left tonight, and tomorrow is clear too.');
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user