feat(platform): add filtered vehicle coverage summary
This commit is contained in:
@@ -142,6 +142,77 @@ func buildVehicleCoverageSQL(query url.Values) SQLQuery {
|
||||
}
|
||||
}
|
||||
|
||||
func buildVehicleCoverageSummarySQL(query url.Values) SQLQuery {
|
||||
args := []any{}
|
||||
where := []string{"s.vin IS NOT NULL", "s.vin <> ''"}
|
||||
having := []string{}
|
||||
if keyword := strings.TrimSpace(query.Get("keyword")); keyword != "" {
|
||||
where = append(where, "(s.vin LIKE ? OR s.plate LIKE ? OR b.vin LIKE ? OR b.plate LIKE ? OR b.phone LIKE ? OR b.oem LIKE ?)")
|
||||
like := "%" + keyword + "%"
|
||||
args = append(args, like, like, like, like, like, like)
|
||||
}
|
||||
if protocol := strings.TrimSpace(query.Get("protocol")); protocol != "" {
|
||||
where = append(where, "s.protocol = ?")
|
||||
args = append(args, protocol)
|
||||
}
|
||||
switch strings.TrimSpace(query.Get("coverage")) {
|
||||
case "single":
|
||||
having = append(having, "COUNT(DISTINCT s.protocol) = 1")
|
||||
case "multi":
|
||||
having = append(having, "COUNT(DISTINCT s.protocol) > 1")
|
||||
}
|
||||
switch strings.TrimSpace(query.Get("online")) {
|
||||
case "online":
|
||||
having = append(having, "COUNT(DISTINCT CASE WHEN s.updated_at >= DATE_SUB(NOW(), INTERVAL 1 MINUTE) THEN s.protocol END) > 0")
|
||||
case "offline":
|
||||
having = append(having, "COUNT(DISTINCT CASE WHEN s.updated_at >= DATE_SUB(NOW(), INTERVAL 1 MINUTE) THEN s.protocol END) = 0")
|
||||
}
|
||||
switch strings.TrimSpace(query.Get("bindingStatus")) {
|
||||
case "bound":
|
||||
having = append(having, "MAX(CASE WHEN b.vin IS NOT NULL AND b.vin <> '' THEN 1 ELSE 0 END) = 1")
|
||||
case "unbound":
|
||||
having = append(having, "MAX(CASE WHEN b.vin IS NOT NULL AND b.vin <> '' THEN 1 ELSE 0 END) = 0")
|
||||
}
|
||||
switch strings.TrimSpace(query.Get("serviceStatus")) {
|
||||
case "identity_required":
|
||||
having = append(having, "MAX(CASE WHEN b.vin IS NOT NULL AND b.vin <> '' THEN 1 ELSE 0 END) = 0")
|
||||
case "offline":
|
||||
having = append(having, "MAX(CASE WHEN b.vin IS NOT NULL AND b.vin <> '' THEN 1 ELSE 0 END) = 1")
|
||||
having = append(having, "COUNT(DISTINCT s.protocol) > 0")
|
||||
having = append(having, "COUNT(DISTINCT CASE WHEN s.updated_at >= DATE_SUB(NOW(), INTERVAL 1 MINUTE) THEN s.protocol END) = 0")
|
||||
case "degraded":
|
||||
having = append(having, "MAX(CASE WHEN b.vin IS NOT NULL AND b.vin <> '' THEN 1 ELSE 0 END) = 1")
|
||||
having = append(having, "COUNT(DISTINCT s.protocol) > 0")
|
||||
having = append(having, "COUNT(DISTINCT CASE WHEN s.updated_at >= DATE_SUB(NOW(), INTERVAL 1 MINUTE) THEN s.protocol END) > 0")
|
||||
having = append(having, "COUNT(DISTINCT CASE WHEN s.updated_at >= DATE_SUB(NOW(), INTERVAL 1 MINUTE) THEN s.protocol END) < COUNT(DISTINCT s.protocol)")
|
||||
case "healthy":
|
||||
having = append(having, "MAX(CASE WHEN b.vin IS NOT NULL AND b.vin <> '' THEN 1 ELSE 0 END) = 1")
|
||||
having = append(having, "COUNT(DISTINCT s.protocol) > 0")
|
||||
having = append(having, "COUNT(DISTINCT CASE WHEN s.updated_at >= DATE_SUB(NOW(), INTERVAL 1 MINUTE) THEN s.protocol END) = COUNT(DISTINCT s.protocol)")
|
||||
}
|
||||
havingSQL := ""
|
||||
if len(having) > 0 {
|
||||
havingSQL = ` HAVING ` + strings.Join(having, " AND ") + ` `
|
||||
}
|
||||
groupSQL := `SELECT s.vin, ` +
|
||||
`COUNT(DISTINCT s.protocol) AS source_count, ` +
|
||||
`COUNT(DISTINCT CASE WHEN s.updated_at >= DATE_SUB(NOW(), INTERVAL 1 MINUTE) THEN s.protocol END) AS online_source_count, ` +
|
||||
`MAX(CASE WHEN b.vin IS NOT NULL AND b.vin <> '' THEN 1 ELSE 0 END) AS bound ` +
|
||||
`FROM vehicle_realtime_snapshot s ` +
|
||||
`LEFT JOIN vehicle_identity_binding b ON b.vin = s.vin ` +
|
||||
`WHERE ` + strings.Join(where, " AND ") + ` ` +
|
||||
`GROUP BY s.vin ` + havingSQL
|
||||
return SQLQuery{
|
||||
Text: `SELECT COUNT(*) AS total_vehicles, ` +
|
||||
`COALESCE(SUM(CASE WHEN online_source_count > 0 THEN 1 ELSE 0 END), 0) AS online_vehicles, ` +
|
||||
`COALESCE(SUM(CASE WHEN source_count = 1 THEN 1 ELSE 0 END), 0) AS single_source_vehicles, ` +
|
||||
`COALESCE(SUM(CASE WHEN source_count > 1 THEN 1 ELSE 0 END), 0) AS multi_source_vehicles, ` +
|
||||
`COALESCE(SUM(CASE WHEN bound = 0 THEN 1 ELSE 0 END), 0) AS unbound_vehicles ` +
|
||||
`FROM (` + groupSQL + `) vehicle_coverage_summary`,
|
||||
Args: args,
|
||||
}
|
||||
}
|
||||
|
||||
func buildRealtimeLocationSQL(query url.Values) SQLQuery {
|
||||
limit := parsePositive(query.Get("limit"), 20)
|
||||
offset := parsePositive(query.Get("offset"), 0)
|
||||
|
||||
Reference in New Issue
Block a user