no-mistakes(review): Fix F01/F02/F05: technician name, duplicate timeline, FM dashboard property counts
This commit is contained in:
@@ -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"<Ticket {self.ticket_number} ({self.status})>"
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user