feat(platform): expose no-data vehicles
This commit is contained in:
@@ -67,10 +67,10 @@ func buildVehicleCoverageSQL(query url.Values) SQLQuery {
|
||||
limit := parsePositive(query.Get("limit"), 20)
|
||||
offset := parsePositive(query.Get("offset"), 0)
|
||||
args := []any{}
|
||||
where := []string{"s.vin IS NOT NULL", "s.vin <> ''"}
|
||||
where := []string{"v.vin IS NOT NULL", "v.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 ?)")
|
||||
where = append(where, "(v.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)
|
||||
}
|
||||
@@ -99,6 +99,9 @@ func buildVehicleCoverageSQL(query url.Values) SQLQuery {
|
||||
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 "no_data":
|
||||
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")
|
||||
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")
|
||||
@@ -119,13 +122,16 @@ func buildVehicleCoverageSQL(query url.Values) SQLQuery {
|
||||
if len(having) > 0 {
|
||||
havingSQL = ` HAVING ` + strings.Join(having, " AND ") + ` `
|
||||
}
|
||||
groupSQL := `FROM vehicle_realtime_snapshot s ` +
|
||||
`LEFT JOIN vehicle_identity_binding b ON b.vin = s.vin ` +
|
||||
vehicleSetSQL := `SELECT vin FROM vehicle_identity_binding WHERE vin IS NOT NULL AND vin <> '' ` +
|
||||
`UNION SELECT vin FROM vehicle_realtime_snapshot WHERE vin IS NOT NULL AND vin <> ''`
|
||||
groupSQL := `FROM (` + vehicleSetSQL + `) v ` +
|
||||
`LEFT JOIN vehicle_identity_binding b ON b.vin = v.vin ` +
|
||||
`LEFT JOIN vehicle_realtime_snapshot s ON s.vin = v.vin ` +
|
||||
`WHERE ` + strings.Join(where, " AND ") + ` ` +
|
||||
`GROUP BY s.vin, b.plate, b.phone, b.oem, b.vin ` +
|
||||
`GROUP BY v.vin, b.plate, b.phone, b.oem, b.vin ` +
|
||||
havingSQL
|
||||
return SQLQuery{
|
||||
Text: `SELECT s.vin, ` +
|
||||
Text: `SELECT v.vin, ` +
|
||||
`COALESCE(NULLIF(MAX(NULLIF(s.plate, '')), ''), b.plate, '') AS plate, ` +
|
||||
`COALESCE(b.phone, '') AS phone, COALESCE(b.oem, '') AS oem, ` +
|
||||
`COALESCE(GROUP_CONCAT(DISTINCT s.protocol ORDER BY s.protocol SEPARATOR ','), '') AS protocols, ` +
|
||||
@@ -135,19 +141,19 @@ func buildVehicleCoverageSQL(query url.Values) SQLQuery {
|
||||
`COALESCE(DATE_FORMAT(MAX(s.updated_at), '%Y-%m-%d %H:%i:%s'), '') AS last_seen, ` +
|
||||
`CASE WHEN b.vin IS NOT NULL AND b.vin <> '' THEN 'bound' ELSE 'unbound' END AS binding_status ` +
|
||||
groupSQL +
|
||||
`ORDER BY MAX(s.updated_at) DESC, s.vin ASC LIMIT ? OFFSET ?`,
|
||||
`ORDER BY MAX(s.updated_at) DESC, v.vin ASC LIMIT ? OFFSET ?`,
|
||||
Args: args,
|
||||
CountText: `SELECT COUNT(*) FROM (SELECT s.vin ` + groupSQL + `) vehicle_coverage_count`,
|
||||
CountText: `SELECT COUNT(*) FROM (SELECT v.vin ` + groupSQL + `) vehicle_coverage_count`,
|
||||
CountArgs: countArgs,
|
||||
}
|
||||
}
|
||||
|
||||
func buildVehicleCoverageSummarySQL(query url.Values) SQLQuery {
|
||||
args := []any{}
|
||||
where := []string{"s.vin IS NOT NULL", "s.vin <> ''"}
|
||||
where := []string{"v.vin IS NOT NULL", "v.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 ?)")
|
||||
where = append(where, "(v.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)
|
||||
}
|
||||
@@ -176,6 +182,9 @@ func buildVehicleCoverageSummarySQL(query url.Values) SQLQuery {
|
||||
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 "no_data":
|
||||
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")
|
||||
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")
|
||||
@@ -194,19 +203,23 @@ func buildVehicleCoverageSummarySQL(query url.Values) SQLQuery {
|
||||
if len(having) > 0 {
|
||||
havingSQL = ` HAVING ` + strings.Join(having, " AND ") + ` `
|
||||
}
|
||||
groupSQL := `SELECT s.vin, ` +
|
||||
vehicleSetSQL := `SELECT vin FROM vehicle_identity_binding WHERE vin IS NOT NULL AND vin <> '' ` +
|
||||
`UNION SELECT vin FROM vehicle_realtime_snapshot WHERE vin IS NOT NULL AND vin <> ''`
|
||||
groupSQL := `SELECT v.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 ` +
|
||||
`FROM (` + vehicleSetSQL + `) v ` +
|
||||
`LEFT JOIN vehicle_identity_binding b ON b.vin = v.vin ` +
|
||||
`LEFT JOIN vehicle_realtime_snapshot s ON s.vin = v.vin ` +
|
||||
`WHERE ` + strings.Join(where, " AND ") + ` ` +
|
||||
`GROUP BY s.vin ` + havingSQL
|
||||
`GROUP BY v.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 source_count = 0 THEN 1 ELSE 0 END), 0) AS no_data_vehicles, ` +
|
||||
`COALESCE(SUM(CASE WHEN bound = 0 THEN 1 ELSE 0 END), 0) AS unbound_vehicles ` +
|
||||
`FROM (` + groupSQL + `) vehicle_coverage_summary`,
|
||||
Args: args,
|
||||
|
||||
Reference in New Issue
Block a user