1172 lines
54 KiB
C#
1172 lines
54 KiB
C#
using System.Globalization;
|
|
using System.Text;
|
|
using System.Text.RegularExpressions;
|
|
using line_gestao_api.Data;
|
|
using line_gestao_api.Dtos;
|
|
using Microsoft.EntityFrameworkCore;
|
|
|
|
namespace line_gestao_api.Services
|
|
{
|
|
public class GeralDashboardInsightsService
|
|
{
|
|
private static readonly CultureInfo PtBr = new("pt-BR");
|
|
|
|
private const string ServiceGestaoVozDados = "GESTÃO VOZ E DADOS";
|
|
private const string ServiceSkeelo = "SKEELO";
|
|
private const string ServiceVivoNewsPlus = "VIVO NEWS PLUS";
|
|
private const string ServiceVivoTravelMundo = "VIVO TRAVEL MUNDO";
|
|
private const string ServiceVivoSync = "VIVO SYNC";
|
|
private const string ServiceVivoGestaoDispositivo = "VIVO GESTÃO DISPOSITIVO";
|
|
|
|
private readonly AppDbContext _db;
|
|
|
|
public GeralDashboardInsightsService(AppDbContext db)
|
|
{
|
|
_db = db;
|
|
}
|
|
|
|
public async Task<GeralDashboardInsightsDto> GetInsightsAsync()
|
|
{
|
|
var qLines = _db.MobileLines.AsNoTracking();
|
|
|
|
var totals = await qLines
|
|
.GroupBy(_ => 1)
|
|
.Select(g => new TotalsProjection
|
|
{
|
|
TotalLinhas = g.Count(),
|
|
TotalAtivas = g.Count(x => (x.Status ?? "").ToLower().Contains("ativo")),
|
|
PfAtivas = g.Count(x =>
|
|
(x.Status ?? "").ToLower().Contains("ativo") &&
|
|
((x.Skil ?? "").ToLower().Contains("fís") || (x.Skil ?? "").ToLower().Contains("fis") || (x.Skil ?? "").ToLower().Contains("pf"))),
|
|
PjAtivas = g.Count(x =>
|
|
(x.Status ?? "").ToLower().Contains("ativo") &&
|
|
((x.Skil ?? "").ToLower().Contains("jur") || (x.Skil ?? "").ToLower().Contains("pj"))),
|
|
PfValorTotalLineAtivas = g.Sum(x =>
|
|
(x.Status ?? "").ToLower().Contains("ativo") &&
|
|
((x.Skil ?? "").ToLower().Contains("fís") || (x.Skil ?? "").ToLower().Contains("fis") || (x.Skil ?? "").ToLower().Contains("pf"))
|
|
? (x.ValorContratoLine ?? 0m)
|
|
: 0m),
|
|
PjValorTotalLineAtivas = g.Sum(x =>
|
|
(x.Status ?? "").ToLower().Contains("ativo") &&
|
|
((x.Skil ?? "").ToLower().Contains("jur") || (x.Skil ?? "").ToLower().Contains("pj"))
|
|
? (x.ValorContratoLine ?? 0m)
|
|
: 0m),
|
|
PfLucroTotalLineAtivas = g.Sum(x =>
|
|
(x.Status ?? "").ToLower().Contains("ativo") &&
|
|
((x.Skil ?? "").ToLower().Contains("fís") || (x.Skil ?? "").ToLower().Contains("fis") || (x.Skil ?? "").ToLower().Contains("pf"))
|
|
? (x.Lucro ?? 0m)
|
|
: 0m),
|
|
PjLucroTotalLineAtivas = g.Sum(x =>
|
|
(x.Status ?? "").ToLower().Contains("ativo") &&
|
|
((x.Skil ?? "").ToLower().Contains("jur") || (x.Skil ?? "").ToLower().Contains("pj"))
|
|
? (x.Lucro ?? 0m)
|
|
: 0m),
|
|
TotalBloqueados = g.Count(x =>
|
|
(x.Status ?? "").ToLower().Contains("bloque") ||
|
|
(x.Status ?? "").ToLower().Contains("perda") ||
|
|
(x.Status ?? "").ToLower().Contains("roubo")),
|
|
VivoLinhas = g.Count(x =>
|
|
x.ValorPlanoVivo != null ||
|
|
x.FranquiaVivo != null ||
|
|
x.ValorContratoVivo != null ||
|
|
x.GestaoVozDados != null ||
|
|
x.Skeelo != null ||
|
|
x.VivoNewsPlus != null ||
|
|
x.VivoTravelMundo != null ||
|
|
x.VivoSync != null ||
|
|
x.VivoGestaoDispositivo != null),
|
|
VivoBaseTotal = g.Sum(x =>
|
|
(x.ValorPlanoVivo != null ||
|
|
x.FranquiaVivo != null ||
|
|
x.ValorContratoVivo != null ||
|
|
x.GestaoVozDados != null ||
|
|
x.Skeelo != null ||
|
|
x.VivoNewsPlus != null ||
|
|
x.VivoTravelMundo != null ||
|
|
x.VivoSync != null ||
|
|
x.VivoGestaoDispositivo != null)
|
|
? (x.ValorPlanoVivo ?? 0m)
|
|
: 0m),
|
|
VivoFranquiaTotalGb = g.Sum(x =>
|
|
(x.ValorPlanoVivo != null ||
|
|
x.FranquiaVivo != null ||
|
|
x.ValorContratoVivo != null ||
|
|
x.GestaoVozDados != null ||
|
|
x.Skeelo != null ||
|
|
x.VivoNewsPlus != null ||
|
|
x.VivoTravelMundo != null ||
|
|
x.VivoSync != null ||
|
|
x.VivoGestaoDispositivo != null)
|
|
? (x.FranquiaVivo ?? 0m)
|
|
: 0m),
|
|
VivoAdicionaisTotal = g.Sum(x =>
|
|
(x.ValorPlanoVivo != null ||
|
|
x.FranquiaVivo != null ||
|
|
x.ValorContratoVivo != null ||
|
|
x.GestaoVozDados != null ||
|
|
x.Skeelo != null ||
|
|
x.VivoNewsPlus != null ||
|
|
x.VivoTravelMundo != null ||
|
|
x.VivoSync != null ||
|
|
x.VivoGestaoDispositivo != null)
|
|
? (x.GestaoVozDados ?? 0m) + (x.Skeelo ?? 0m) + (x.VivoNewsPlus ?? 0m) +
|
|
(x.VivoTravelMundo ?? 0m) + (x.VivoSync ?? 0m) + (x.VivoGestaoDispositivo ?? 0m)
|
|
: 0m),
|
|
VivoMinBase = g.Where(x =>
|
|
x.ValorPlanoVivo != null ||
|
|
x.FranquiaVivo != null ||
|
|
x.ValorContratoVivo != null ||
|
|
x.GestaoVozDados != null ||
|
|
x.Skeelo != null ||
|
|
x.VivoNewsPlus != null ||
|
|
x.VivoTravelMundo != null ||
|
|
x.VivoSync != null ||
|
|
x.VivoGestaoDispositivo != null)
|
|
.Select(x => x.ValorPlanoVivo ?? 0m)
|
|
.DefaultIfEmpty()
|
|
.Min(),
|
|
VivoMaxBase = g.Where(x =>
|
|
x.ValorPlanoVivo != null ||
|
|
x.FranquiaVivo != null ||
|
|
x.ValorContratoVivo != null ||
|
|
x.GestaoVozDados != null ||
|
|
x.Skeelo != null ||
|
|
x.VivoNewsPlus != null ||
|
|
x.VivoTravelMundo != null ||
|
|
x.VivoSync != null ||
|
|
x.VivoGestaoDispositivo != null)
|
|
.Select(x => x.ValorPlanoVivo ?? 0m)
|
|
.DefaultIfEmpty()
|
|
.Max(),
|
|
TravelCom = g.Count(x => (x.VivoTravelMundo ?? 0m) > 0m),
|
|
TravelSem = g.Count(x => (x.VivoTravelMundo ?? 0m) <= 0m),
|
|
TravelTotal = g.Sum(x => x.VivoTravelMundo ?? 0m),
|
|
PaidGestaoVozDados = g.Count(x =>
|
|
(x.ValorPlanoVivo != null ||
|
|
x.FranquiaVivo != null ||
|
|
x.ValorContratoVivo != null ||
|
|
x.GestaoVozDados != null ||
|
|
x.Skeelo != null ||
|
|
x.VivoNewsPlus != null ||
|
|
x.VivoTravelMundo != null ||
|
|
x.VivoSync != null ||
|
|
x.VivoGestaoDispositivo != null) &&
|
|
(x.GestaoVozDados ?? 0m) > 0m),
|
|
PaidSkeelo = g.Count(x =>
|
|
(x.ValorPlanoVivo != null ||
|
|
x.FranquiaVivo != null ||
|
|
x.ValorContratoVivo != null ||
|
|
x.GestaoVozDados != null ||
|
|
x.Skeelo != null ||
|
|
x.VivoNewsPlus != null ||
|
|
x.VivoTravelMundo != null ||
|
|
x.VivoSync != null ||
|
|
x.VivoGestaoDispositivo != null) &&
|
|
(x.Skeelo ?? 0m) > 0m),
|
|
PaidNews = g.Count(x =>
|
|
(x.ValorPlanoVivo != null ||
|
|
x.FranquiaVivo != null ||
|
|
x.ValorContratoVivo != null ||
|
|
x.GestaoVozDados != null ||
|
|
x.Skeelo != null ||
|
|
x.VivoNewsPlus != null ||
|
|
x.VivoTravelMundo != null ||
|
|
x.VivoSync != null ||
|
|
x.VivoGestaoDispositivo != null) &&
|
|
(x.VivoNewsPlus ?? 0m) > 0m),
|
|
PaidTravel = g.Count(x =>
|
|
(x.ValorPlanoVivo != null ||
|
|
x.FranquiaVivo != null ||
|
|
x.ValorContratoVivo != null ||
|
|
x.GestaoVozDados != null ||
|
|
x.Skeelo != null ||
|
|
x.VivoNewsPlus != null ||
|
|
x.VivoTravelMundo != null ||
|
|
x.VivoSync != null ||
|
|
x.VivoGestaoDispositivo != null) &&
|
|
(x.VivoTravelMundo ?? 0m) > 0m),
|
|
PaidGestaoDispositivo = g.Count(x =>
|
|
(x.ValorPlanoVivo != null ||
|
|
x.FranquiaVivo != null ||
|
|
x.ValorContratoVivo != null ||
|
|
x.GestaoVozDados != null ||
|
|
x.Skeelo != null ||
|
|
x.VivoNewsPlus != null ||
|
|
x.VivoTravelMundo != null ||
|
|
x.VivoSync != null ||
|
|
x.VivoGestaoDispositivo != null) &&
|
|
(x.VivoGestaoDispositivo ?? 0m) > 0m),
|
|
PaidSync = g.Count(x =>
|
|
(x.ValorPlanoVivo != null ||
|
|
x.FranquiaVivo != null ||
|
|
x.ValorContratoVivo != null ||
|
|
x.GestaoVozDados != null ||
|
|
x.Skeelo != null ||
|
|
x.VivoNewsPlus != null ||
|
|
x.VivoTravelMundo != null ||
|
|
x.VivoSync != null ||
|
|
x.VivoGestaoDispositivo != null) &&
|
|
(x.VivoSync ?? 0m) > 0m),
|
|
NotPaidGestaoVozDados = g.Count(x =>
|
|
(x.ValorPlanoVivo != null ||
|
|
x.FranquiaVivo != null ||
|
|
x.ValorContratoVivo != null ||
|
|
x.GestaoVozDados != null ||
|
|
x.Skeelo != null ||
|
|
x.VivoNewsPlus != null ||
|
|
x.VivoTravelMundo != null ||
|
|
x.VivoSync != null ||
|
|
x.VivoGestaoDispositivo != null) &&
|
|
(x.GestaoVozDados ?? 0m) <= 0m),
|
|
NotPaidSkeelo = g.Count(x =>
|
|
(x.ValorPlanoVivo != null ||
|
|
x.FranquiaVivo != null ||
|
|
x.ValorContratoVivo != null ||
|
|
x.GestaoVozDados != null ||
|
|
x.Skeelo != null ||
|
|
x.VivoNewsPlus != null ||
|
|
x.VivoTravelMundo != null ||
|
|
x.VivoSync != null ||
|
|
x.VivoGestaoDispositivo != null) &&
|
|
(x.Skeelo ?? 0m) <= 0m),
|
|
NotPaidNews = g.Count(x =>
|
|
(x.ValorPlanoVivo != null ||
|
|
x.FranquiaVivo != null ||
|
|
x.ValorContratoVivo != null ||
|
|
x.GestaoVozDados != null ||
|
|
x.Skeelo != null ||
|
|
x.VivoNewsPlus != null ||
|
|
x.VivoTravelMundo != null ||
|
|
x.VivoSync != null ||
|
|
x.VivoGestaoDispositivo != null) &&
|
|
(x.VivoNewsPlus ?? 0m) <= 0m),
|
|
NotPaidTravel = g.Count(x =>
|
|
(x.ValorPlanoVivo != null ||
|
|
x.FranquiaVivo != null ||
|
|
x.ValorContratoVivo != null ||
|
|
x.GestaoVozDados != null ||
|
|
x.Skeelo != null ||
|
|
x.VivoNewsPlus != null ||
|
|
x.VivoTravelMundo != null ||
|
|
x.VivoSync != null ||
|
|
x.VivoGestaoDispositivo != null) &&
|
|
(x.VivoTravelMundo ?? 0m) <= 0m),
|
|
NotPaidGestaoDispositivo = g.Count(x =>
|
|
(x.ValorPlanoVivo != null ||
|
|
x.FranquiaVivo != null ||
|
|
x.ValorContratoVivo != null ||
|
|
x.GestaoVozDados != null ||
|
|
x.Skeelo != null ||
|
|
x.VivoNewsPlus != null ||
|
|
x.VivoTravelMundo != null ||
|
|
x.VivoSync != null ||
|
|
x.VivoGestaoDispositivo != null) &&
|
|
(x.VivoGestaoDispositivo ?? 0m) <= 0m),
|
|
NotPaidSync = g.Count(x =>
|
|
(x.ValorPlanoVivo != null ||
|
|
x.FranquiaVivo != null ||
|
|
x.ValorContratoVivo != null ||
|
|
x.GestaoVozDados != null ||
|
|
x.Skeelo != null ||
|
|
x.VivoNewsPlus != null ||
|
|
x.VivoTravelMundo != null ||
|
|
x.VivoSync != null ||
|
|
x.VivoGestaoDispositivo != null) &&
|
|
(x.VivoSync ?? 0m) <= 0m),
|
|
TotalLinesWithAnyPaidAdditional = g.Count(x =>
|
|
(x.ValorPlanoVivo != null ||
|
|
x.FranquiaVivo != null ||
|
|
x.ValorContratoVivo != null ||
|
|
x.GestaoVozDados != null ||
|
|
x.Skeelo != null ||
|
|
x.VivoNewsPlus != null ||
|
|
x.VivoTravelMundo != null ||
|
|
x.VivoSync != null ||
|
|
x.VivoGestaoDispositivo != null) &&
|
|
((x.GestaoVozDados ?? 0m) > 0m ||
|
|
(x.Skeelo ?? 0m) > 0m ||
|
|
(x.VivoNewsPlus ?? 0m) > 0m ||
|
|
(x.VivoTravelMundo ?? 0m) > 0m ||
|
|
(x.VivoSync ?? 0m) > 0m ||
|
|
(x.VivoGestaoDispositivo ?? 0m) > 0m)),
|
|
TotalLinesWithNoPaidAdditional = g.Count(x =>
|
|
(x.ValorPlanoVivo != null ||
|
|
x.FranquiaVivo != null ||
|
|
x.ValorContratoVivo != null ||
|
|
x.GestaoVozDados != null ||
|
|
x.Skeelo != null ||
|
|
x.VivoNewsPlus != null ||
|
|
x.VivoTravelMundo != null ||
|
|
x.VivoSync != null ||
|
|
x.VivoGestaoDispositivo != null) &&
|
|
(x.GestaoVozDados ?? 0m) <= 0m &&
|
|
(x.Skeelo ?? 0m) <= 0m &&
|
|
(x.VivoNewsPlus ?? 0m) <= 0m &&
|
|
(x.VivoTravelMundo ?? 0m) <= 0m &&
|
|
(x.VivoSync ?? 0m) <= 0m &&
|
|
(x.VivoGestaoDispositivo ?? 0m) <= 0m),
|
|
TotalGestaoVozDados = g.Sum(x =>
|
|
(x.ValorPlanoVivo != null ||
|
|
x.FranquiaVivo != null ||
|
|
x.ValorContratoVivo != null ||
|
|
x.GestaoVozDados != null ||
|
|
x.Skeelo != null ||
|
|
x.VivoNewsPlus != null ||
|
|
x.VivoTravelMundo != null ||
|
|
x.VivoSync != null ||
|
|
x.VivoGestaoDispositivo != null)
|
|
? (x.GestaoVozDados ?? 0m)
|
|
: 0m),
|
|
TotalSkeelo = g.Sum(x =>
|
|
(x.ValorPlanoVivo != null ||
|
|
x.FranquiaVivo != null ||
|
|
x.ValorContratoVivo != null ||
|
|
x.GestaoVozDados != null ||
|
|
x.Skeelo != null ||
|
|
x.VivoNewsPlus != null ||
|
|
x.VivoTravelMundo != null ||
|
|
x.VivoSync != null ||
|
|
x.VivoGestaoDispositivo != null)
|
|
? (x.Skeelo ?? 0m)
|
|
: 0m),
|
|
TotalNews = g.Sum(x =>
|
|
(x.ValorPlanoVivo != null ||
|
|
x.FranquiaVivo != null ||
|
|
x.ValorContratoVivo != null ||
|
|
x.GestaoVozDados != null ||
|
|
x.Skeelo != null ||
|
|
x.VivoNewsPlus != null ||
|
|
x.VivoTravelMundo != null ||
|
|
x.VivoSync != null ||
|
|
x.VivoGestaoDispositivo != null)
|
|
? (x.VivoNewsPlus ?? 0m)
|
|
: 0m),
|
|
TotalTravel = g.Sum(x =>
|
|
(x.ValorPlanoVivo != null ||
|
|
x.FranquiaVivo != null ||
|
|
x.ValorContratoVivo != null ||
|
|
x.GestaoVozDados != null ||
|
|
x.Skeelo != null ||
|
|
x.VivoNewsPlus != null ||
|
|
x.VivoTravelMundo != null ||
|
|
x.VivoSync != null ||
|
|
x.VivoGestaoDispositivo != null)
|
|
? (x.VivoTravelMundo ?? 0m)
|
|
: 0m),
|
|
TotalGestaoDispositivo = g.Sum(x =>
|
|
(x.ValorPlanoVivo != null ||
|
|
x.FranquiaVivo != null ||
|
|
x.ValorContratoVivo != null ||
|
|
x.GestaoVozDados != null ||
|
|
x.Skeelo != null ||
|
|
x.VivoNewsPlus != null ||
|
|
x.VivoTravelMundo != null ||
|
|
x.VivoSync != null ||
|
|
x.VivoGestaoDispositivo != null)
|
|
? (x.VivoGestaoDispositivo ?? 0m)
|
|
: 0m),
|
|
TotalSync = g.Sum(x =>
|
|
(x.ValorPlanoVivo != null ||
|
|
x.FranquiaVivo != null ||
|
|
x.ValorContratoVivo != null ||
|
|
x.GestaoVozDados != null ||
|
|
x.Skeelo != null ||
|
|
x.VivoNewsPlus != null ||
|
|
x.VivoTravelMundo != null ||
|
|
x.VivoSync != null ||
|
|
x.VivoGestaoDispositivo != null)
|
|
? (x.VivoSync ?? 0m)
|
|
: 0m)
|
|
})
|
|
.FirstOrDefaultAsync();
|
|
|
|
var franquiasRaw = await qLines
|
|
.Select(x => new FranquiaProjection { FranquiaVivo = x.FranquiaVivo, PlanoContrato = x.PlanoContrato })
|
|
.ToListAsync();
|
|
|
|
var linhasPorFranquia = BuildFranquiaBuckets(franquiasRaw);
|
|
var tipoChip = await qLines.Select(x => x.TipoDeChip).ToListAsync();
|
|
var tipoChipBuckets = BuildTipoChipBuckets(tipoChip);
|
|
|
|
var clientGroupsRaw = await qLines
|
|
.Where(x => x.Cliente != null && x.Cliente != "")
|
|
.GroupBy(x => x.Cliente!)
|
|
.Select(g => new ClientGroupProjection
|
|
{
|
|
Cliente = g.Key,
|
|
TotalLinhas = g.Count(),
|
|
Ativos = g.Count(x => (x.Status ?? "").ToLower().Contains("ativo")),
|
|
Bloqueados = g.Count(x =>
|
|
(x.Status ?? "").ToLower().Contains("bloque") ||
|
|
(x.Status ?? "").ToLower().Contains("perda") ||
|
|
(x.Status ?? "").ToLower().Contains("roubo")),
|
|
LinhasVivo = g.Count(x =>
|
|
x.ValorPlanoVivo != null ||
|
|
x.FranquiaVivo != null ||
|
|
x.ValorContratoVivo != null ||
|
|
x.GestaoVozDados != null ||
|
|
x.Skeelo != null ||
|
|
x.VivoNewsPlus != null ||
|
|
x.VivoTravelMundo != null ||
|
|
x.VivoSync != null ||
|
|
x.VivoGestaoDispositivo != null),
|
|
TravelCom = g.Count(x => (x.VivoTravelMundo ?? 0m) > 0m),
|
|
TravelSem = g.Count(x => (x.VivoTravelMundo ?? 0m) <= 0m),
|
|
PaidGestaoVozDados = g.Count(x =>
|
|
(x.ValorPlanoVivo != null ||
|
|
x.FranquiaVivo != null ||
|
|
x.ValorContratoVivo != null ||
|
|
x.GestaoVozDados != null ||
|
|
x.Skeelo != null ||
|
|
x.VivoNewsPlus != null ||
|
|
x.VivoTravelMundo != null ||
|
|
x.VivoSync != null ||
|
|
x.VivoGestaoDispositivo != null) &&
|
|
(x.GestaoVozDados ?? 0m) > 0m),
|
|
PaidSkeelo = g.Count(x =>
|
|
(x.ValorPlanoVivo != null ||
|
|
x.FranquiaVivo != null ||
|
|
x.ValorContratoVivo != null ||
|
|
x.GestaoVozDados != null ||
|
|
x.Skeelo != null ||
|
|
x.VivoNewsPlus != null ||
|
|
x.VivoTravelMundo != null ||
|
|
x.VivoSync != null ||
|
|
x.VivoGestaoDispositivo != null) &&
|
|
(x.Skeelo ?? 0m) > 0m),
|
|
PaidNews = g.Count(x =>
|
|
(x.ValorPlanoVivo != null ||
|
|
x.FranquiaVivo != null ||
|
|
x.ValorContratoVivo != null ||
|
|
x.GestaoVozDados != null ||
|
|
x.Skeelo != null ||
|
|
x.VivoNewsPlus != null ||
|
|
x.VivoTravelMundo != null ||
|
|
x.VivoSync != null ||
|
|
x.VivoGestaoDispositivo != null) &&
|
|
(x.VivoNewsPlus ?? 0m) > 0m),
|
|
PaidTravel = g.Count(x =>
|
|
(x.ValorPlanoVivo != null ||
|
|
x.FranquiaVivo != null ||
|
|
x.ValorContratoVivo != null ||
|
|
x.GestaoVozDados != null ||
|
|
x.Skeelo != null ||
|
|
x.VivoNewsPlus != null ||
|
|
x.VivoTravelMundo != null ||
|
|
x.VivoSync != null ||
|
|
x.VivoGestaoDispositivo != null) &&
|
|
(x.VivoTravelMundo ?? 0m) > 0m),
|
|
PaidGestaoDispositivo = g.Count(x =>
|
|
(x.ValorPlanoVivo != null ||
|
|
x.FranquiaVivo != null ||
|
|
x.ValorContratoVivo != null ||
|
|
x.GestaoVozDados != null ||
|
|
x.Skeelo != null ||
|
|
x.VivoNewsPlus != null ||
|
|
x.VivoTravelMundo != null ||
|
|
x.VivoSync != null ||
|
|
x.VivoGestaoDispositivo != null) &&
|
|
(x.VivoGestaoDispositivo ?? 0m) > 0m),
|
|
PaidSync = g.Count(x =>
|
|
(x.ValorPlanoVivo != null ||
|
|
x.FranquiaVivo != null ||
|
|
x.ValorContratoVivo != null ||
|
|
x.GestaoVozDados != null ||
|
|
x.Skeelo != null ||
|
|
x.VivoNewsPlus != null ||
|
|
x.VivoTravelMundo != null ||
|
|
x.VivoSync != null ||
|
|
x.VivoGestaoDispositivo != null) &&
|
|
(x.VivoSync ?? 0m) > 0m),
|
|
NotPaidGestaoVozDados = g.Count(x =>
|
|
(x.ValorPlanoVivo != null ||
|
|
x.FranquiaVivo != null ||
|
|
x.ValorContratoVivo != null ||
|
|
x.GestaoVozDados != null ||
|
|
x.Skeelo != null ||
|
|
x.VivoNewsPlus != null ||
|
|
x.VivoTravelMundo != null ||
|
|
x.VivoSync != null ||
|
|
x.VivoGestaoDispositivo != null) &&
|
|
(x.GestaoVozDados ?? 0m) <= 0m),
|
|
NotPaidSkeelo = g.Count(x =>
|
|
(x.ValorPlanoVivo != null ||
|
|
x.FranquiaVivo != null ||
|
|
x.ValorContratoVivo != null ||
|
|
x.GestaoVozDados != null ||
|
|
x.Skeelo != null ||
|
|
x.VivoNewsPlus != null ||
|
|
x.VivoTravelMundo != null ||
|
|
x.VivoSync != null ||
|
|
x.VivoGestaoDispositivo != null) &&
|
|
(x.Skeelo ?? 0m) <= 0m),
|
|
NotPaidNews = g.Count(x =>
|
|
(x.ValorPlanoVivo != null ||
|
|
x.FranquiaVivo != null ||
|
|
x.ValorContratoVivo != null ||
|
|
x.GestaoVozDados != null ||
|
|
x.Skeelo != null ||
|
|
x.VivoNewsPlus != null ||
|
|
x.VivoTravelMundo != null ||
|
|
x.VivoSync != null ||
|
|
x.VivoGestaoDispositivo != null) &&
|
|
(x.VivoNewsPlus ?? 0m) <= 0m),
|
|
NotPaidTravel = g.Count(x =>
|
|
(x.ValorPlanoVivo != null ||
|
|
x.FranquiaVivo != null ||
|
|
x.ValorContratoVivo != null ||
|
|
x.GestaoVozDados != null ||
|
|
x.Skeelo != null ||
|
|
x.VivoNewsPlus != null ||
|
|
x.VivoTravelMundo != null ||
|
|
x.VivoSync != null ||
|
|
x.VivoGestaoDispositivo != null) &&
|
|
(x.VivoTravelMundo ?? 0m) <= 0m),
|
|
NotPaidGestaoDispositivo = g.Count(x =>
|
|
(x.ValorPlanoVivo != null ||
|
|
x.FranquiaVivo != null ||
|
|
x.ValorContratoVivo != null ||
|
|
x.GestaoVozDados != null ||
|
|
x.Skeelo != null ||
|
|
x.VivoNewsPlus != null ||
|
|
x.VivoTravelMundo != null ||
|
|
x.VivoSync != null ||
|
|
x.VivoGestaoDispositivo != null) &&
|
|
(x.VivoGestaoDispositivo ?? 0m) <= 0m),
|
|
NotPaidSync = g.Count(x =>
|
|
(x.ValorPlanoVivo != null ||
|
|
x.FranquiaVivo != null ||
|
|
x.ValorContratoVivo != null ||
|
|
x.GestaoVozDados != null ||
|
|
x.Skeelo != null ||
|
|
x.VivoNewsPlus != null ||
|
|
x.VivoTravelMundo != null ||
|
|
x.VivoSync != null ||
|
|
x.VivoGestaoDispositivo != null) &&
|
|
(x.VivoSync ?? 0m) <= 0m),
|
|
TotalGestaoVozDados = g.Sum(x =>
|
|
(x.ValorPlanoVivo != null ||
|
|
x.FranquiaVivo != null ||
|
|
x.ValorContratoVivo != null ||
|
|
x.GestaoVozDados != null ||
|
|
x.Skeelo != null ||
|
|
x.VivoNewsPlus != null ||
|
|
x.VivoTravelMundo != null ||
|
|
x.VivoSync != null ||
|
|
x.VivoGestaoDispositivo != null)
|
|
? (x.GestaoVozDados ?? 0m)
|
|
: 0m),
|
|
TotalSkeelo = g.Sum(x =>
|
|
(x.ValorPlanoVivo != null ||
|
|
x.FranquiaVivo != null ||
|
|
x.ValorContratoVivo != null ||
|
|
x.GestaoVozDados != null ||
|
|
x.Skeelo != null ||
|
|
x.VivoNewsPlus != null ||
|
|
x.VivoTravelMundo != null ||
|
|
x.VivoSync != null ||
|
|
x.VivoGestaoDispositivo != null)
|
|
? (x.Skeelo ?? 0m)
|
|
: 0m),
|
|
TotalNews = g.Sum(x =>
|
|
(x.ValorPlanoVivo != null ||
|
|
x.FranquiaVivo != null ||
|
|
x.ValorContratoVivo != null ||
|
|
x.GestaoVozDados != null ||
|
|
x.Skeelo != null ||
|
|
x.VivoNewsPlus != null ||
|
|
x.VivoTravelMundo != null ||
|
|
x.VivoSync != null ||
|
|
x.VivoGestaoDispositivo != null)
|
|
? (x.VivoNewsPlus ?? 0m)
|
|
: 0m),
|
|
TotalTravel = g.Sum(x =>
|
|
(x.ValorPlanoVivo != null ||
|
|
x.FranquiaVivo != null ||
|
|
x.ValorContratoVivo != null ||
|
|
x.GestaoVozDados != null ||
|
|
x.Skeelo != null ||
|
|
x.VivoNewsPlus != null ||
|
|
x.VivoTravelMundo != null ||
|
|
x.VivoSync != null ||
|
|
x.VivoGestaoDispositivo != null)
|
|
? (x.VivoTravelMundo ?? 0m)
|
|
: 0m),
|
|
TotalGestaoDispositivo = g.Sum(x =>
|
|
(x.ValorPlanoVivo != null ||
|
|
x.FranquiaVivo != null ||
|
|
x.ValorContratoVivo != null ||
|
|
x.GestaoVozDados != null ||
|
|
x.Skeelo != null ||
|
|
x.VivoNewsPlus != null ||
|
|
x.VivoTravelMundo != null ||
|
|
x.VivoSync != null ||
|
|
x.VivoGestaoDispositivo != null)
|
|
? (x.VivoGestaoDispositivo ?? 0m)
|
|
: 0m),
|
|
TotalSync = g.Sum(x =>
|
|
(x.ValorPlanoVivo != null ||
|
|
x.FranquiaVivo != null ||
|
|
x.ValorContratoVivo != null ||
|
|
x.GestaoVozDados != null ||
|
|
x.Skeelo != null ||
|
|
x.VivoNewsPlus != null ||
|
|
x.VivoTravelMundo != null ||
|
|
x.VivoSync != null ||
|
|
x.VivoGestaoDispositivo != null)
|
|
? (x.VivoSync ?? 0m)
|
|
: 0m)
|
|
})
|
|
.OrderBy(x => x.Cliente)
|
|
.ToListAsync();
|
|
|
|
var dto = new GeralDashboardInsightsDto
|
|
{
|
|
Kpis = BuildKpis(totals),
|
|
Charts = BuildCharts(totals, linhasPorFranquia, tipoChipBuckets),
|
|
ClientGroups = BuildClientGroups(clientGroupsRaw)
|
|
};
|
|
|
|
return dto;
|
|
}
|
|
|
|
private static GeralDashboardKpisDto BuildKpis(TotalsProjection? totals)
|
|
{
|
|
if (totals == null)
|
|
{
|
|
return new GeralDashboardKpisDto
|
|
{
|
|
Vivo = new GeralDashboardVivoKpiDto(),
|
|
TravelMundo = new GeralDashboardTravelKpiDto(),
|
|
Adicionais = new GeralDashboardAdditionalKpiDto()
|
|
};
|
|
}
|
|
|
|
var totalGeralMensal = totals.VivoBaseTotal + totals.VivoAdicionaisTotal;
|
|
var media = totals.VivoLinhas > 0 ? totalGeralMensal / totals.VivoLinhas : 0m;
|
|
|
|
return new GeralDashboardKpisDto
|
|
{
|
|
TotalLinhas = totals.TotalLinhas,
|
|
TotalAtivas = totals.TotalAtivas,
|
|
Vivo = new GeralDashboardVivoKpiDto
|
|
{
|
|
QtdLinhas = totals.VivoLinhas,
|
|
TotalFranquiaGb = totals.VivoFranquiaTotalGb,
|
|
TotalBaseMensal = totals.VivoBaseTotal,
|
|
TotalAdicionaisMensal = totals.VivoAdicionaisTotal,
|
|
TotalGeralMensal = totalGeralMensal,
|
|
MediaPorLinha = media,
|
|
MinPorLinha = totals.VivoLinhas > 0 ? totals.VivoMinBase : null,
|
|
MaxPorLinha = totals.VivoLinhas > 0 ? totals.VivoMaxBase : null
|
|
},
|
|
TravelMundo = new GeralDashboardTravelKpiDto
|
|
{
|
|
ComTravel = totals.TravelCom,
|
|
SemTravel = totals.TravelSem,
|
|
TotalValue = totals.TravelTotal
|
|
},
|
|
Adicionais = new GeralDashboardAdditionalKpiDto
|
|
{
|
|
TotalLinesWithAnyPaidAdditional = totals.TotalLinesWithAnyPaidAdditional,
|
|
TotalLinesWithNoPaidAdditional = totals.TotalLinesWithNoPaidAdditional,
|
|
ServicesPaid = new List<GeralDashboardServiceKpiDto>
|
|
{
|
|
new() { ServiceName = ServiceGestaoVozDados, CountLines = totals.PaidGestaoVozDados, TotalValue = totals.TotalGestaoVozDados },
|
|
new() { ServiceName = ServiceSkeelo, CountLines = totals.PaidSkeelo, TotalValue = totals.TotalSkeelo },
|
|
new() { ServiceName = ServiceVivoNewsPlus, CountLines = totals.PaidNews, TotalValue = totals.TotalNews },
|
|
new() { ServiceName = ServiceVivoTravelMundo, CountLines = totals.PaidTravel, TotalValue = totals.TotalTravel },
|
|
new() { ServiceName = ServiceVivoSync, CountLines = totals.PaidSync, TotalValue = totals.TotalSync },
|
|
new() { ServiceName = ServiceVivoGestaoDispositivo, CountLines = totals.PaidGestaoDispositivo, TotalValue = totals.TotalGestaoDispositivo }
|
|
},
|
|
ServicesNotPaid = new List<GeralDashboardServiceKpiDto>
|
|
{
|
|
new() { ServiceName = ServiceGestaoVozDados, CountLines = totals.NotPaidGestaoVozDados, TotalValue = 0m },
|
|
new() { ServiceName = ServiceSkeelo, CountLines = totals.NotPaidSkeelo, TotalValue = 0m },
|
|
new() { ServiceName = ServiceVivoNewsPlus, CountLines = totals.NotPaidNews, TotalValue = 0m },
|
|
new() { ServiceName = ServiceVivoTravelMundo, CountLines = totals.NotPaidTravel, TotalValue = 0m },
|
|
new() { ServiceName = ServiceVivoSync, CountLines = totals.NotPaidSync, TotalValue = 0m },
|
|
new() { ServiceName = ServiceVivoGestaoDispositivo, CountLines = totals.NotPaidGestaoDispositivo, TotalValue = 0m }
|
|
}
|
|
},
|
|
TotaisLine = BuildTotaisLineRows(totals)
|
|
};
|
|
}
|
|
|
|
private static GeralDashboardChartsDto BuildCharts(TotalsProjection? totals, FranquiaBuckets franquias, TipoChipBuckets tipoChip)
|
|
{
|
|
var adicionaisLabels = new List<string>
|
|
{
|
|
ServiceGestaoVozDados,
|
|
ServiceSkeelo,
|
|
ServiceVivoNewsPlus,
|
|
ServiceVivoTravelMundo,
|
|
ServiceVivoSync,
|
|
ServiceVivoGestaoDispositivo
|
|
};
|
|
|
|
var adicionaisValues = totals == null
|
|
? new List<int> { 0, 0, 0, 0, 0, 0 }
|
|
: new List<int>
|
|
{
|
|
totals.PaidGestaoVozDados,
|
|
totals.PaidSkeelo,
|
|
totals.PaidNews,
|
|
totals.PaidTravel,
|
|
totals.PaidSync,
|
|
totals.PaidGestaoDispositivo
|
|
};
|
|
|
|
var adicionaisTotals = totals == null
|
|
? new List<decimal> { 0m, 0m, 0m, 0m, 0m, 0m }
|
|
: new List<decimal>
|
|
{
|
|
totals.TotalGestaoVozDados,
|
|
totals.TotalSkeelo,
|
|
totals.TotalNews,
|
|
totals.TotalTravel,
|
|
totals.TotalSync,
|
|
totals.TotalGestaoDispositivo
|
|
};
|
|
|
|
return new GeralDashboardChartsDto
|
|
{
|
|
LinhasPorFranquia = new GeralDashboardChartDto
|
|
{
|
|
Labels = franquias.Labels,
|
|
Values = franquias.Values
|
|
},
|
|
AdicionaisPagosPorServico = new GeralDashboardChartDto
|
|
{
|
|
Labels = adicionaisLabels,
|
|
Values = adicionaisValues,
|
|
Totals = adicionaisTotals
|
|
},
|
|
TravelMundo = new GeralDashboardChartDto
|
|
{
|
|
Labels = new List<string> { "Com", "Sem" },
|
|
Values = totals == null
|
|
? new List<int> { 0, 0 }
|
|
: new List<int> { totals.TravelCom, totals.TravelSem }
|
|
},
|
|
TipoChip = new GeralDashboardChartDto
|
|
{
|
|
Labels = tipoChip.Labels,
|
|
Values = tipoChip.Values
|
|
}
|
|
};
|
|
}
|
|
|
|
private static List<GeralDashboardLineTotalDto> BuildTotaisLineRows(TotalsProjection? totals)
|
|
{
|
|
if (totals == null)
|
|
{
|
|
return new List<GeralDashboardLineTotalDto>();
|
|
}
|
|
|
|
var diffQtd = totals.PjAtivas - totals.PfAtivas;
|
|
var diffValor = totals.PjValorTotalLineAtivas - totals.PfValorTotalLineAtivas;
|
|
var diffLucro = totals.PjLucroTotalLineAtivas - totals.PfLucroTotalLineAtivas;
|
|
|
|
return new List<GeralDashboardLineTotalDto>
|
|
{
|
|
new()
|
|
{
|
|
Tipo = "PESSOA FISICA",
|
|
QtdLinhas = totals.PfAtivas,
|
|
ValorTotalLine = totals.PfValorTotalLineAtivas,
|
|
LucroTotalLine = totals.PfLucroTotalLineAtivas
|
|
},
|
|
new()
|
|
{
|
|
Tipo = "PESSOA JURIDICA",
|
|
QtdLinhas = totals.PjAtivas,
|
|
ValorTotalLine = totals.PjValorTotalLineAtivas,
|
|
LucroTotalLine = totals.PjLucroTotalLineAtivas
|
|
},
|
|
new()
|
|
{
|
|
Tipo = "DIFERENCA PJ X PF",
|
|
QtdLinhas = diffQtd,
|
|
ValorTotalLine = diffValor,
|
|
LucroTotalLine = diffLucro
|
|
}
|
|
};
|
|
}
|
|
|
|
private static List<GeralDashboardClientGroupDto> BuildClientGroups(IEnumerable<ClientGroupProjection> rows)
|
|
{
|
|
var list = new List<GeralDashboardClientGroupDto>();
|
|
|
|
foreach (var row in rows)
|
|
{
|
|
var baseTags = new List<GeralDashboardTagDto>
|
|
{
|
|
new() { Label = "LINHAS", Value = row.TotalLinhas.ToString(PtBr) },
|
|
new() { Label = "ATIVAS", Value = row.Ativos.ToString(PtBr) },
|
|
new() { Label = "BLOQUEADAS", Value = row.Bloqueados.ToString(PtBr) },
|
|
new() { Label = "LINHAS VIVO", Value = row.LinhasVivo.ToString(PtBr) }
|
|
};
|
|
|
|
var extras = new List<GeralDashboardTagDto>
|
|
{
|
|
new() { Label = "TRAVEL MUNDO", Value = row.TravelCom.ToString(PtBr) },
|
|
new() { Label = "SEM TRAVEL", Value = row.TravelSem.ToString(PtBr) },
|
|
new() { Label = ServiceGestaoVozDados, Value = row.PaidGestaoVozDados.ToString(PtBr) },
|
|
new() { Label = $"R$ {ServiceGestaoVozDados}", Value = FormatCurrency(row.TotalGestaoVozDados) },
|
|
new() { Label = ServiceSkeelo, Value = row.PaidSkeelo.ToString(PtBr) },
|
|
new() { Label = $"R$ {ServiceSkeelo}", Value = FormatCurrency(row.TotalSkeelo) },
|
|
new() { Label = ServiceVivoNewsPlus, Value = row.PaidNews.ToString(PtBr) },
|
|
new() { Label = $"R$ {ServiceVivoNewsPlus}", Value = FormatCurrency(row.TotalNews) },
|
|
new() { Label = ServiceVivoTravelMundo, Value = row.PaidTravel.ToString(PtBr) },
|
|
new() { Label = $"R$ {ServiceVivoTravelMundo}", Value = FormatCurrency(row.TotalTravel) },
|
|
new() { Label = ServiceVivoSync, Value = row.PaidSync.ToString(PtBr) },
|
|
new() { Label = $"R$ {ServiceVivoSync}", Value = FormatCurrency(row.TotalSync) },
|
|
new() { Label = ServiceVivoGestaoDispositivo, Value = row.PaidGestaoDispositivo.ToString(PtBr) },
|
|
new() { Label = $"R$ {ServiceVivoGestaoDispositivo}", Value = FormatCurrency(row.TotalGestaoDispositivo) }
|
|
};
|
|
|
|
var serviceDetails = new List<GeralDashboardClientServiceDto>
|
|
{
|
|
new()
|
|
{
|
|
ServiceName = ServiceGestaoVozDados,
|
|
PaidCount = row.PaidGestaoVozDados,
|
|
NotPaidCount = row.NotPaidGestaoVozDados,
|
|
TotalValue = row.TotalGestaoVozDados
|
|
},
|
|
new()
|
|
{
|
|
ServiceName = ServiceSkeelo,
|
|
PaidCount = row.PaidSkeelo,
|
|
NotPaidCount = row.NotPaidSkeelo,
|
|
TotalValue = row.TotalSkeelo
|
|
},
|
|
new()
|
|
{
|
|
ServiceName = ServiceVivoNewsPlus,
|
|
PaidCount = row.PaidNews,
|
|
NotPaidCount = row.NotPaidNews,
|
|
TotalValue = row.TotalNews
|
|
},
|
|
new()
|
|
{
|
|
ServiceName = ServiceVivoTravelMundo,
|
|
PaidCount = row.PaidTravel,
|
|
NotPaidCount = row.NotPaidTravel,
|
|
TotalValue = row.TotalTravel
|
|
},
|
|
new()
|
|
{
|
|
ServiceName = ServiceVivoSync,
|
|
PaidCount = row.PaidSync,
|
|
NotPaidCount = row.NotPaidSync,
|
|
TotalValue = row.TotalSync
|
|
},
|
|
new()
|
|
{
|
|
ServiceName = ServiceVivoGestaoDispositivo,
|
|
PaidCount = row.PaidGestaoDispositivo,
|
|
NotPaidCount = row.NotPaidGestaoDispositivo,
|
|
TotalValue = row.TotalGestaoDispositivo
|
|
}
|
|
};
|
|
|
|
list.Add(new GeralDashboardClientGroupDto
|
|
{
|
|
Cliente = row.Cliente,
|
|
TotalLinhas = row.TotalLinhas,
|
|
Ativos = row.Ativos,
|
|
Bloqueados = row.Bloqueados,
|
|
LinhasVivo = row.LinhasVivo,
|
|
TagsBase = baseTags,
|
|
TagsExtras = extras,
|
|
AdicionaisPorServico = serviceDetails
|
|
});
|
|
}
|
|
|
|
return list;
|
|
}
|
|
|
|
private static TipoChipBuckets BuildTipoChipBuckets(IEnumerable<string?> chipTypes)
|
|
{
|
|
var esim = 0;
|
|
var simcard = 0;
|
|
|
|
foreach (var raw in chipTypes)
|
|
{
|
|
var normalized = NormalizeChipType(raw);
|
|
if (normalized == "ESIM")
|
|
{
|
|
esim++;
|
|
continue;
|
|
}
|
|
|
|
if (normalized == "SIMCARD")
|
|
{
|
|
simcard++;
|
|
}
|
|
}
|
|
|
|
return new TipoChipBuckets
|
|
{
|
|
Labels = new List<string> { "e-SIM", "SIMCARD" },
|
|
Values = new List<int> { esim, simcard }
|
|
};
|
|
}
|
|
|
|
private static string NormalizeChipType(string? value)
|
|
{
|
|
var normalized = NormalizeText(value);
|
|
if (string.IsNullOrWhiteSpace(normalized))
|
|
{
|
|
return string.Empty;
|
|
}
|
|
|
|
if (normalized.Contains("ESIM"))
|
|
{
|
|
return "ESIM";
|
|
}
|
|
|
|
if (normalized.Contains("SIM") ||
|
|
normalized.Contains("CHIP") ||
|
|
normalized.Contains("CARD") ||
|
|
normalized.Contains("FISIC"))
|
|
{
|
|
return "SIMCARD";
|
|
}
|
|
|
|
return string.Empty;
|
|
}
|
|
|
|
private static string NormalizeText(string? value)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(value)) return string.Empty;
|
|
|
|
var decomposed = value
|
|
.Trim()
|
|
.ToUpperInvariant()
|
|
.Normalize(NormalizationForm.FormD);
|
|
|
|
var builder = new StringBuilder(decomposed.Length);
|
|
foreach (var ch in decomposed)
|
|
{
|
|
if (CharUnicodeInfo.GetUnicodeCategory(ch) == UnicodeCategory.NonSpacingMark)
|
|
continue;
|
|
|
|
if (char.IsLetterOrDigit(ch))
|
|
builder.Append(ch);
|
|
}
|
|
|
|
return builder.ToString();
|
|
}
|
|
|
|
private static FranquiaBuckets BuildFranquiaBuckets(IEnumerable<FranquiaProjection> rows)
|
|
{
|
|
var map = new Dictionary<string, FranquiaBucket>();
|
|
|
|
foreach (var row in rows)
|
|
{
|
|
var label = NormalizeFranquiaLabel(row.FranquiaVivo, row.PlanoContrato);
|
|
var key = label;
|
|
if (!map.TryGetValue(key, out var bucket))
|
|
{
|
|
bucket = new FranquiaBucket { Label = label, SortKey = BuildFranquiaSortKey(label) };
|
|
map[key] = bucket;
|
|
}
|
|
|
|
bucket.Count++;
|
|
}
|
|
|
|
var ordered = map.Values
|
|
.OrderBy(x => x.SortKey)
|
|
.ThenBy(x => x.Label)
|
|
.ToList();
|
|
|
|
return new FranquiaBuckets
|
|
{
|
|
Labels = ordered.Select(x => x.Label).ToList(),
|
|
Values = ordered.Select(x => x.Count).ToList()
|
|
};
|
|
}
|
|
|
|
private static string NormalizeFranquiaLabel(decimal? value, string? planoContrato)
|
|
{
|
|
if (value.HasValue && value.Value > 0)
|
|
{
|
|
return NormalizeNumericFranquia(value.Value);
|
|
}
|
|
|
|
var parsed = ParseFranquiaFromPlano(planoContrato);
|
|
return string.IsNullOrWhiteSpace(parsed) ? "Sem Franquia" : parsed;
|
|
}
|
|
|
|
private static string? ParseFranquiaFromPlano(string? planoContrato)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(planoContrato)) return null;
|
|
|
|
var match = Regex.Match(planoContrato, @"(?<val>\d+(?:[.,]\d+)?)\s*(?<unit>GB|MB)", RegexOptions.IgnoreCase);
|
|
if (!match.Success) return null;
|
|
|
|
var valueRaw = match.Groups["val"].Value.Replace(",", ".");
|
|
if (!decimal.TryParse(valueRaw, NumberStyles.Any, CultureInfo.InvariantCulture, out var value)) return null;
|
|
|
|
var unit = match.Groups["unit"].Value.ToUpperInvariant();
|
|
if (unit == "GB")
|
|
{
|
|
return $"{TrimDecimal(value)}GB";
|
|
}
|
|
|
|
return $"{Math.Round(value):0}MB";
|
|
}
|
|
|
|
private static string NormalizeNumericFranquia(decimal value)
|
|
{
|
|
if (value < 1m)
|
|
{
|
|
var mb = Math.Round(value * 1000m);
|
|
return $"{mb:0}MB";
|
|
}
|
|
|
|
if (value >= 100m && value < 1024m)
|
|
{
|
|
return $"{Math.Round(value):0}MB";
|
|
}
|
|
|
|
if (value >= 1024m)
|
|
{
|
|
var gb = value / 1024m;
|
|
return $"{TrimDecimal(gb)}GB";
|
|
}
|
|
|
|
return $"{TrimDecimal(value)}GB";
|
|
}
|
|
|
|
private static decimal BuildFranquiaSortKey(string label)
|
|
{
|
|
if (label.Equals("Sem Franquia", StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
return decimal.MaxValue;
|
|
}
|
|
|
|
var match = Regex.Match(label, @"(?<val>\d+(?:[.,]\d+)?)\s*(?<unit>GB|MB)", RegexOptions.IgnoreCase);
|
|
if (!match.Success) return decimal.MaxValue - 1;
|
|
|
|
var valueRaw = match.Groups["val"].Value.Replace(",", ".");
|
|
if (!decimal.TryParse(valueRaw, NumberStyles.Any, CultureInfo.InvariantCulture, out var value))
|
|
{
|
|
return decimal.MaxValue - 1;
|
|
}
|
|
|
|
var unit = match.Groups["unit"].Value.ToUpperInvariant();
|
|
return unit == "MB" ? value / 1000m : value;
|
|
}
|
|
|
|
private static string TrimDecimal(decimal value)
|
|
{
|
|
return value % 1 == 0 ? value.ToString("0", CultureInfo.InvariantCulture) : value.ToString("0.#", CultureInfo.InvariantCulture);
|
|
}
|
|
|
|
private static string FormatCurrency(decimal value)
|
|
{
|
|
return value.ToString("C", PtBr);
|
|
}
|
|
|
|
private sealed class FranquiaBucket
|
|
{
|
|
public string Label { get; set; } = string.Empty;
|
|
public int Count { get; set; }
|
|
public decimal SortKey { get; set; }
|
|
}
|
|
|
|
private sealed class FranquiaBuckets
|
|
{
|
|
public List<string> Labels { get; set; } = new();
|
|
public List<int> Values { get; set; } = new();
|
|
}
|
|
|
|
private sealed class TipoChipBuckets
|
|
{
|
|
public List<string> Labels { get; set; } = new();
|
|
public List<int> Values { get; set; } = new();
|
|
}
|
|
|
|
private sealed class FranquiaProjection
|
|
{
|
|
public decimal? FranquiaVivo { get; set; }
|
|
public string? PlanoContrato { get; set; }
|
|
}
|
|
|
|
private sealed class TotalsProjection
|
|
{
|
|
public int TotalLinhas { get; set; }
|
|
public int TotalAtivas { get; set; }
|
|
public int PfAtivas { get; set; }
|
|
public int PjAtivas { get; set; }
|
|
public decimal PfValorTotalLineAtivas { get; set; }
|
|
public decimal PjValorTotalLineAtivas { get; set; }
|
|
public decimal PfLucroTotalLineAtivas { get; set; }
|
|
public decimal PjLucroTotalLineAtivas { get; set; }
|
|
public int TotalBloqueados { get; set; }
|
|
public int VivoLinhas { get; set; }
|
|
public decimal VivoFranquiaTotalGb { get; set; }
|
|
public decimal VivoBaseTotal { get; set; }
|
|
public decimal VivoAdicionaisTotal { get; set; }
|
|
public decimal VivoMinBase { get; set; }
|
|
public decimal VivoMaxBase { get; set; }
|
|
public int TravelCom { get; set; }
|
|
public int TravelSem { get; set; }
|
|
public decimal TravelTotal { get; set; }
|
|
public int PaidGestaoVozDados { get; set; }
|
|
public int PaidSkeelo { get; set; }
|
|
public int PaidNews { get; set; }
|
|
public int PaidTravel { get; set; }
|
|
public int PaidGestaoDispositivo { get; set; }
|
|
public int PaidSync { get; set; }
|
|
public int NotPaidGestaoVozDados { get; set; }
|
|
public int NotPaidSkeelo { get; set; }
|
|
public int NotPaidNews { get; set; }
|
|
public int NotPaidTravel { get; set; }
|
|
public int NotPaidGestaoDispositivo { get; set; }
|
|
public int NotPaidSync { get; set; }
|
|
public int TotalLinesWithAnyPaidAdditional { get; set; }
|
|
public int TotalLinesWithNoPaidAdditional { get; set; }
|
|
public decimal TotalGestaoVozDados { get; set; }
|
|
public decimal TotalSkeelo { get; set; }
|
|
public decimal TotalNews { get; set; }
|
|
public decimal TotalTravel { get; set; }
|
|
public decimal TotalGestaoDispositivo { get; set; }
|
|
public decimal TotalSync { get; set; }
|
|
}
|
|
|
|
private sealed class ClientGroupProjection
|
|
{
|
|
public string Cliente { get; set; } = string.Empty;
|
|
public int TotalLinhas { get; set; }
|
|
public int Ativos { get; set; }
|
|
public int Bloqueados { get; set; }
|
|
public int LinhasVivo { get; set; }
|
|
public int TravelCom { get; set; }
|
|
public int TravelSem { get; set; }
|
|
public int PaidGestaoVozDados { get; set; }
|
|
public int PaidSkeelo { get; set; }
|
|
public int PaidNews { get; set; }
|
|
public int PaidTravel { get; set; }
|
|
public int PaidGestaoDispositivo { get; set; }
|
|
public int PaidSync { get; set; }
|
|
public int NotPaidGestaoVozDados { get; set; }
|
|
public int NotPaidSkeelo { get; set; }
|
|
public int NotPaidNews { get; set; }
|
|
public int NotPaidTravel { get; set; }
|
|
public int NotPaidGestaoDispositivo { get; set; }
|
|
public int NotPaidSync { get; set; }
|
|
public decimal TotalGestaoVozDados { get; set; }
|
|
public decimal TotalSkeelo { get; set; }
|
|
public decimal TotalNews { get; set; }
|
|
public decimal TotalTravel { get; set; }
|
|
public decimal TotalGestaoDispositivo { get; set; }
|
|
public decimal TotalSync { get; set; }
|
|
}
|
|
}
|
|
}
|