diff --git a/backend/app/services/light_board.py b/backend/app/services/light_board.py index bc78c55..7e0d234 100644 --- a/backend/app/services/light_board.py +++ b/backend/app/services/light_board.py @@ -9,7 +9,7 @@ Status (rolling 30-day window): from datetime import date, timedelta from uuid import UUID -from sqlalchemy import select, func, and_ +from sqlalchemy import select, and_ from sqlalchemy.ext.asyncio import AsyncSession from app.models.user import User from app.models.customer import Customer @@ -86,18 +86,28 @@ async def get_light_board( } # ── All customers with their last visit per manager ── - # Subquery: latest visit date + method per (manager_id, customer_id) + # Subquery: latest visit (date + method) per (manager_id, customer_id). + # DISTINCT ON keeps exactly one row per pair even when multiple visits + # share the same latest date (e.g. companion/collaborative visits), + # preventing fan-out that would duplicate customer cards on the board. latest_visit = ( select( Visit.manager_id, Visit.customer_id, - func.max(Visit.visit_date).label("last_visit_date"), + Visit.visit_date.label("last_visit_date"), + Visit.visit_method.label("last_visit_method"), + ) + .distinct(Visit.manager_id, Visit.customer_id) + .order_by( + Visit.manager_id, + Visit.customer_id, + Visit.visit_date.desc(), + Visit.id.desc(), ) - .group_by(Visit.manager_id, Visit.customer_id) .subquery() ) - # Join: assignments → customers → latest_visit → visits (for method) + # Join: assignments → customers → latest_visit (date + method) rows = await db.execute( select( CustomerAssignment.manager_id, @@ -108,18 +118,13 @@ async def get_light_board( Customer.in_use_services, Customer.monthly_fee, latest_visit.c.last_visit_date, - Visit.visit_method, + latest_visit.c.last_visit_method, ) .join(Customer, Customer.id == CustomerAssignment.customer_id) .outerjoin(latest_visit, and_( latest_visit.c.manager_id == CustomerAssignment.manager_id, latest_visit.c.customer_id == CustomerAssignment.customer_id, )) - .outerjoin(Visit, and_( - Visit.manager_id == CustomerAssignment.manager_id, - Visit.customer_id == CustomerAssignment.customer_id, - Visit.visit_date == latest_visit.c.last_visit_date, - )) .where(CustomerAssignment.role == "primary") .order_by(Customer.name) )