change: updated DurationMinutes SQL calculation
This commit is contained in:
@@ -123,7 +123,39 @@ CREATE OR REPLACE VIEW public.splash_wifi_connection_report
|
||||
con."NetworkUsage",
|
||||
con."FirstSeen",
|
||||
con."LastSeen",
|
||||
EXTRACT(epoch FROM con."LastSeen" - con."FirstSeen") / 60::numeric AS "DurationMinutes",
|
||||
-- Duración estimada: toma el menor entre cálculo por NetworkUsage y período bruto
|
||||
CASE
|
||||
WHEN con."LastSeen" >= con."FirstSeen"
|
||||
THEN
|
||||
LEAST(
|
||||
-- Método 1: Duración bruta del período
|
||||
EXTRACT(epoch FROM con."LastSeen" - con."FirstSeen") / 60::numeric,
|
||||
-- Método 2: Estimación basada en NetworkUsage
|
||||
CASE
|
||||
-- Si hay uso de red significativo, estimar tiempo activo real
|
||||
WHEN CAST(con."NetworkUsage" AS bigint) > 1024 THEN -- > 1MB
|
||||
LEAST(
|
||||
-- Factor base: 0.1 minutos por MB (ajustable según patrones reales)
|
||||
(CAST(con."NetworkUsage" AS bigint) / 1024.0) * 0.1,
|
||||
-- Máximo 30% del período total como tiempo activo real
|
||||
(EXTRACT(epoch FROM con."LastSeen" - con."FirstSeen") / 60::numeric) * 0.3
|
||||
)
|
||||
-- Uso menor: asumir 10% del período como tiempo activo
|
||||
WHEN CAST(con."NetworkUsage" AS bigint) > 0 THEN
|
||||
LEAST(
|
||||
(EXTRACT(epoch FROM con."LastSeen" - con."FirstSeen") / 60::numeric) * 0.1,
|
||||
480.0 -- Máximo 8 horas por sesión
|
||||
)
|
||||
-- Sin uso de red: tiempo mínimo estimado
|
||||
ELSE
|
||||
LEAST(
|
||||
(EXTRACT(epoch FROM con."LastSeen" - con."FirstSeen") / 60::numeric) * 0.05,
|
||||
30.0 -- Máximo 30 minutos para sesiones sin datos de uso
|
||||
)
|
||||
END
|
||||
)
|
||||
ELSE 0
|
||||
END AS "DurationMinutes",
|
||||
net."Name" AS "NetworkName",
|
||||
net."MerakiId" AS "MerakiNetworkId",
|
||||
org."Name" AS "Organization",
|
||||
@@ -154,7 +186,116 @@ CREATE OR REPLACE VIEW public.splash_wifi_connection_report
|
||||
-- Conexión histórica, usar la lógica original (días entre conexiones)
|
||||
con."DaysInactive"
|
||||
END AS "DaysInactive",
|
||||
con."PostRecoveryRank" AS "PostRecoveryRank"
|
||||
con."PostRecoveryRank" AS "PostRecoveryRank",
|
||||
-- Métricas agregadas por usuario: promedio del menor entre ambos métodos
|
||||
AVG(
|
||||
CASE
|
||||
WHEN con."LastSeen" >= con."FirstSeen"
|
||||
THEN
|
||||
LEAST(
|
||||
-- Método 1: Duración bruta del período
|
||||
EXTRACT(epoch FROM con."LastSeen" - con."FirstSeen") / 60::numeric,
|
||||
-- Método 2: Estimación basada en NetworkUsage
|
||||
CASE
|
||||
WHEN CAST(con."NetworkUsage" AS bigint) > 1024 THEN
|
||||
LEAST(
|
||||
(CAST(con."NetworkUsage" AS bigint) / 1024.0) * 0.1,
|
||||
(EXTRACT(epoch FROM con."LastSeen" - con."FirstSeen") / 60::numeric) * 0.3
|
||||
)
|
||||
WHEN CAST(con."NetworkUsage" AS bigint) > 0 THEN
|
||||
LEAST(
|
||||
(EXTRACT(epoch FROM con."LastSeen" - con."FirstSeen") / 60::numeric) * 0.1,
|
||||
480.0
|
||||
)
|
||||
ELSE
|
||||
LEAST(
|
||||
(EXTRACT(epoch FROM con."LastSeen" - con."FirstSeen") / 60::numeric) * 0.05,
|
||||
30.0
|
||||
)
|
||||
END
|
||||
)
|
||||
ELSE NULL
|
||||
END
|
||||
) OVER (PARTITION BY con."SplashUserId") AS "UserAvgEstimatedMinutes",
|
||||
-- Categorización basada en el menor entre ambos métodos
|
||||
CASE
|
||||
WHEN (CASE
|
||||
WHEN con."LastSeen" >= con."FirstSeen"
|
||||
THEN
|
||||
LEAST(
|
||||
EXTRACT(epoch FROM con."LastSeen" - con."FirstSeen") / 60::numeric,
|
||||
CASE
|
||||
WHEN CAST(con."NetworkUsage" AS bigint) > 1024 THEN
|
||||
LEAST(
|
||||
(CAST(con."NetworkUsage" AS bigint) / 1024.0) * 0.1,
|
||||
(EXTRACT(epoch FROM con."LastSeen" - con."FirstSeen") / 60::numeric) * 0.3
|
||||
)
|
||||
WHEN CAST(con."NetworkUsage" AS bigint) > 0 THEN
|
||||
LEAST(
|
||||
(EXTRACT(epoch FROM con."LastSeen" - con."FirstSeen") / 60::numeric) * 0.1,
|
||||
480.0
|
||||
)
|
||||
ELSE
|
||||
LEAST(
|
||||
(EXTRACT(epoch FROM con."LastSeen" - con."FirstSeen") / 60::numeric) * 0.05,
|
||||
30.0
|
||||
)
|
||||
END
|
||||
)
|
||||
ELSE 0
|
||||
END) <= 30 THEN 'Quick (<30min)'
|
||||
WHEN (CASE
|
||||
WHEN con."LastSeen" >= con."FirstSeen"
|
||||
THEN
|
||||
LEAST(
|
||||
EXTRACT(epoch FROM con."LastSeen" - con."FirstSeen") / 60::numeric,
|
||||
CASE
|
||||
WHEN CAST(con."NetworkUsage" AS bigint) > 1024 THEN
|
||||
LEAST(
|
||||
(CAST(con."NetworkUsage" AS bigint) / 1024.0) * 0.1,
|
||||
(EXTRACT(epoch FROM con."LastSeen" - con."FirstSeen") / 60::numeric) * 0.3
|
||||
)
|
||||
WHEN CAST(con."NetworkUsage" AS bigint) > 0 THEN
|
||||
LEAST(
|
||||
(EXTRACT(epoch FROM con."LastSeen" - con."FirstSeen") / 60::numeric) * 0.1,
|
||||
480.0
|
||||
)
|
||||
ELSE
|
||||
LEAST(
|
||||
(EXTRACT(epoch FROM con."LastSeen" - con."FirstSeen") / 60::numeric) * 0.05,
|
||||
30.0
|
||||
)
|
||||
END
|
||||
)
|
||||
ELSE 0
|
||||
END) BETWEEN 30 AND 120 THEN 'Medium (30min-2h)'
|
||||
WHEN (CASE
|
||||
WHEN con."LastSeen" >= con."FirstSeen"
|
||||
THEN
|
||||
LEAST(
|
||||
EXTRACT(epoch FROM con."LastSeen" - con."FirstSeen") / 60::numeric,
|
||||
CASE
|
||||
WHEN CAST(con."NetworkUsage" AS bigint) > 1024 THEN
|
||||
LEAST(
|
||||
(CAST(con."NetworkUsage" AS bigint) / 1024.0) * 0.1,
|
||||
(EXTRACT(epoch FROM con."LastSeen" - con."FirstSeen") / 60::numeric) * 0.3
|
||||
)
|
||||
WHEN CAST(con."NetworkUsage" AS bigint) > 0 THEN
|
||||
LEAST(
|
||||
(EXTRACT(epoch FROM con."LastSeen" - con."FirstSeen") / 60::numeric) * 0.1,
|
||||
480.0
|
||||
)
|
||||
ELSE
|
||||
LEAST(
|
||||
(EXTRACT(epoch FROM con."LastSeen" - con."FirstSeen") / 60::numeric) * 0.05,
|
||||
30.0
|
||||
)
|
||||
END
|
||||
)
|
||||
ELSE 0
|
||||
END) > 120 THEN 'Extended (>2h)'
|
||||
ELSE 'Invalid'
|
||||
END AS "SessionDurationCategory"
|
||||
FROM user_loyalty_calculation con
|
||||
LEFT JOIN ( SELECT u."Id" AS "UserId",
|
||||
u."Email",
|
||||
|
||||
@@ -48,5 +48,9 @@ namespace SplashPage.Splash.Dto
|
||||
public DateTime? RecoveryConnectionDate { get; set; }
|
||||
public int DaysInactive { get; set; }
|
||||
public int PostRecoveryRank { get; set; }
|
||||
|
||||
// New duration calculation fields
|
||||
public decimal? UserAvgEstimatedMinutes { get; set; }
|
||||
public string SessionDurationCategory { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -242,7 +242,11 @@ namespace SplashPage.Splash
|
||||
IsRecoveredUser = entity.IsRecoveredUser,
|
||||
RecoveryConnectionDate = entity.RecoveryConnectionDate,
|
||||
DaysInactive = entity.DaysInactive,
|
||||
PostRecoveryRank = entity.PostRecoveryRank
|
||||
PostRecoveryRank = entity.PostRecoveryRank,
|
||||
|
||||
// New duration calculation fields
|
||||
UserAvgEstimatedMinutes = entity.UserAvgEstimatedMinutes,
|
||||
SessionDurationCategory = entity.SessionDurationCategory
|
||||
}).ToList();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ namespace SplashPage.Splash
|
||||
public string NetworkUsage { get; set; }
|
||||
public DateTime FirstSeen { get; set; }
|
||||
public DateTime LastSeen { get; set; }
|
||||
public int DurationMinutes { get; set; }
|
||||
public decimal DurationMinutes { get; set; }
|
||||
public string NetworkName { get; set; } = string.Empty;
|
||||
public string MerakiNetworkId { get; set; } = string.Empty;
|
||||
public string Organization { get; set; } = string.Empty;
|
||||
@@ -53,5 +53,9 @@ namespace SplashPage.Splash
|
||||
public DateTime? RecoveryConnectionDate { get; set; }
|
||||
public int DaysInactive { get; set; }
|
||||
public int PostRecoveryRank { get; set; }
|
||||
|
||||
// New duration calculation fields
|
||||
public decimal? UserAvgEstimatedMinutes { get; set; }
|
||||
public string SessionDurationCategory { get; set; } = string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,6 +52,18 @@ namespace SplashPage.Configurations
|
||||
builder.Property(e => e.ConnectionStatus).HasColumnName("ConnectionStatus").HasMaxLength(50);
|
||||
builder.Property(e => e.Description).HasColumnName("Description").HasMaxLength(500);
|
||||
builder.Property(e => e.DeviceIdentifier).HasColumnName("DeviceIdentifier").HasMaxLength(100);
|
||||
|
||||
// New fields from SQL view update
|
||||
builder.Property(e => e.IsRecoveredUser).HasColumnName("IsRecoveredUser");
|
||||
builder.Property(e => e.RecoveryConnectionDate).HasColumnName("RecoveryConnectionDate");
|
||||
builder.Property(e => e.DaysInactive).HasColumnName("DaysInactive");
|
||||
builder.Property(e => e.PostRecoveryRank).HasColumnName("PostRecoveryRank");
|
||||
builder.Property(e => e.ConnectionRank).HasColumnName("ConnectionRank");
|
||||
builder.Property(e => e.NetworkId).HasColumnName("NetworkId");
|
||||
|
||||
// New duration calculation fields
|
||||
builder.Property(e => e.UserAvgEstimatedMinutes).HasColumnName("UserAvgEstimatedMinutes").HasColumnType("decimal(18,6)");
|
||||
builder.Property(e => e.SessionDurationCategory).HasColumnName("SessionDurationCategory").HasMaxLength(50);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -270,8 +270,7 @@ $(function () {
|
||||
orderable: true,
|
||||
type: 'num',
|
||||
render: function (data) {
|
||||
//return formatDuration(data);
|
||||
return data ? parseFloat(data).toFixed(1) + ' min' : '0 min';
|
||||
return formatDuration(data);
|
||||
}
|
||||
},
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user