From 55604966533c48fde306a5ed3132af10b0050fa5 Mon Sep 17 00:00:00 2001 From: root Date: Thu, 23 Jul 2026 19:13:10 +0000 Subject: [PATCH] no-mistakes(review): Fix F01/F02/F05: technician name, duplicate timeline, FM dashboard property counts --- app/models/ticket.py | 4 ++++ app/schemas/ticket.py | 1 + app/services/ticket.py | 6 +++--- app/templates/dashboard/fm.html | 15 ++++++--------- 4 files changed, 14 insertions(+), 12 deletions(-) diff --git a/app/models/ticket.py b/app/models/ticket.py index c270dcb..aad9282 100644 --- a/app/models/ticket.py +++ b/app/models/ticket.py @@ -70,6 +70,10 @@ class Ticket(Base): photos = relationship("TicketPhoto", back_populates="ticket") escalations = relationship("Escalation", back_populates="ticket") + @property + def assigned_technician_name(self) -> str | None: + return self.assigned_technician.full_name if self.assigned_technician else None + def __repr__(self) -> str: return f"" diff --git a/app/schemas/ticket.py b/app/schemas/ticket.py index e958899..e4bdfdf 100644 --- a/app/schemas/ticket.py +++ b/app/schemas/ticket.py @@ -92,6 +92,7 @@ class TicketBrief(BaseModel): unit_id: int | None = None category_id: int | None = None assigned_to: int | None = None + assigned_technician_name: str | None = None reporter: str | None = None description: str | None = None sla_deadline: datetime | None = None diff --git a/app/services/ticket.py b/app/services/ticket.py index c22f061..5bb51d9 100644 --- a/app/services/ticket.py +++ b/app/services/ticket.py @@ -196,7 +196,7 @@ async def list_tickets( # Paginate offset = (page - 1) * page_size - query = query.order_by(Ticket.created_at.desc()).offset(offset).limit(page_size) + query = query.order_by(Ticket.created_at.desc()).offset(offset).limit(page_size).options(selectinload(Ticket.assigned_technician)) result = await db.execute(query) tickets = list(result.scalars().all()) @@ -214,8 +214,8 @@ async def update_ticket( # Handle status transitions separately new_status = data.get("status") + old_status = ticket.status if new_status is not None: - old_status = ticket.status if old_status != new_status: valid_targets = VALID_TRANSITIONS.get(old_status, []) if new_status not in valid_targets: @@ -277,7 +277,7 @@ async def update_ticket( # Handle standalone note (no status change) note_only = data.get("note") - if note_only and (new_status is None or new_status == ticket.status): + if note_only and not (new_status is not None and old_status != new_status): await _log_status_change( db, ticket.id, diff --git a/app/templates/dashboard/fm.html b/app/templates/dashboard/fm.html index 94ab73c..894b26d 100644 --- a/app/templates/dashboard/fm.html +++ b/app/templates/dashboard/fm.html @@ -203,16 +203,13 @@ // Emergency this.emergencyCount = active.filter(t => t.priority === 'urgent').length; - // East vs West — we need full tickets with unit info - // For now, estimate from overall data or show placeholder - // We'll load again with property filter or just use total + // East vs West — compute from loaded tickets using unit map try { - const east = await app().apiGet('/api/tickets?property=East&page_size=1'); - const west = await app().apiGet('/api/tickets?property=West&page_size=1'); - const eastTotal = east?.total || 0; - const westTotal = west?.total || 0; - this.kpi.eastJobs = eastTotal; - this.kpi.westJobs = westTotal; + const units = await app().apiGet('/api/tickets/units'); + const unitMap = {}; + if (units) units.forEach(u => { unitMap[u.id] = u.property; }); + this.kpi.eastJobs = active.filter(t => t.unit_id && unitMap[t.unit_id] === 'East').length; + this.kpi.westJobs = active.filter(t => t.unit_id && unitMap[t.unit_id] === 'West').length; } catch (e) { console.error('Property stats error', e); } // Tech workload (simulated from assigned_to counts)