line-gestao-api/Controllers/UserDataController.cs

193 lines
7.2 KiB
C#

using line_gestao_api.Data;
using line_gestao_api.Dtos;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
namespace line_gestao_api.Controllers
{
[ApiController]
[Route("api/user-data")]
public class UserDataController : ControllerBase
{
private readonly AppDbContext _db;
public UserDataController(AppDbContext db) => _db = db;
// ==========================================================
// GET /api/user-data (LINHAS - Tabela Interna)
// ==========================================================
[HttpGet]
public async Task<ActionResult<PagedResult<UserDataListDto>>> GetAll(
[FromQuery] string? search,
[FromQuery] string? client, // Filtro por cliente
[FromQuery] int page = 1,
[FromQuery] int pageSize = 20,
[FromQuery] string? sortBy = "item",
[FromQuery] string? sortDir = "asc")
{
page = page < 1 ? 1 : page;
pageSize = pageSize < 1 ? 20 : pageSize;
var q = _db.UserDatas.AsNoTracking();
// Filtro exato por cliente (quando abre o card)
if (!string.IsNullOrWhiteSpace(client))
{
var c = client.Trim();
q = q.Where(x => x.Cliente == c);
}
// Busca global
if (!string.IsNullOrWhiteSpace(search))
{
var s = search.Trim();
q = q.Where(x =>
EF.Functions.ILike(x.Linha ?? "", $"%{s}%") ||
EF.Functions.ILike(x.Cliente ?? "", $"%{s}%") ||
EF.Functions.ILike(x.Cpf ?? "", $"%{s}%") ||
EF.Functions.ILike(x.Email ?? "", $"%{s}%") ||
EF.Functions.ILike(x.Celular ?? "", $"%{s}%"));
}
var total = await q.CountAsync();
var sb = (sortBy ?? "item").Trim().ToLowerInvariant();
var desc = string.Equals((sortDir ?? "asc").Trim(), "desc", StringComparison.OrdinalIgnoreCase);
q = sb switch
{
"item" => desc ? q.OrderByDescending(x => x.Item) : q.OrderBy(x => x.Item),
"linha" => desc ? q.OrderByDescending(x => x.Linha) : q.OrderBy(x => x.Linha),
"cliente" => desc ? q.OrderByDescending(x => x.Cliente) : q.OrderBy(x => x.Cliente),
_ => desc ? q.OrderByDescending(x => x.Item) : q.OrderBy(x => x.Item),
};
var items = await q
.Skip((page - 1) * pageSize)
.Take(pageSize)
.Select(x => new UserDataListDto
{
Id = x.Id,
Item = x.Item,
Linha = x.Linha,
Cliente = x.Cliente,
Cpf = x.Cpf,
Rg = x.Rg,
DataNascimento = x.DataNascimento != null ? x.DataNascimento.Value.ToString("yyyy-MM-dd") : null,
Email = x.Email,
Endereco = x.Endereco,
Celular = x.Celular,
TelefoneFixo = x.TelefoneFixo
})
.ToListAsync();
return Ok(new PagedResult<UserDataListDto>
{
Page = page,
PageSize = pageSize,
Total = total,
Items = items
});
}
// ==========================================================
// GET /api/user-data/groups (CARDS + KPIs GERAIS)
// ==========================================================
[HttpGet("groups")]
public async Task<ActionResult<UserDataGroupResponse>> GetGroups(
[FromQuery] string? search,
[FromQuery] int page = 1,
[FromQuery] int pageSize = 10,
[FromQuery] string? sortBy = "cliente",
[FromQuery] string? sortDir = "asc")
{
page = page < 1 ? 1 : page;
pageSize = pageSize < 1 ? 10 : pageSize;
var q = _db.UserDatas.AsNoTracking()
.Where(x => x.Cliente != null && x.Cliente != "");
if (!string.IsNullOrWhiteSpace(search))
{
var s = search.Trim();
q = q.Where(x => EF.Functions.ILike(x.Cliente ?? "", $"%{s}%"));
}
// ✅ 1. CÁLCULO DOS KPIS GERAIS (Baseado em todos os dados filtrados, sem paginação)
var kpis = new UserDataKpisDto
{
TotalRegistros = await q.CountAsync(),
ClientesUnicos = await q.Select(x => x.Cliente).Distinct().CountAsync(),
ComCpf = await q.CountAsync(x => x.Cpf != null && x.Cpf != ""),
ComEmail = await q.CountAsync(x => x.Email != null && x.Email != "")
};
// ✅ 2. AGRUPAMENTO (Para os Cards)
var grouped = q
.GroupBy(x => x.Cliente!)
.Select(g => new UserDataClientGroupDto
{
Cliente = g.Key,
TotalRegistros = g.Count(),
ComCpf = g.Count(x => x.Cpf != null && x.Cpf != ""),
ComEmail = g.Count(x => x.Email != null && x.Email != "")
});
var totalGroups = await grouped.CountAsync();
// Ordenação
var desc = string.Equals((sortDir ?? "asc").Trim(), "desc", StringComparison.OrdinalIgnoreCase);
grouped = desc ? grouped.OrderByDescending(x => x.Cliente) : grouped.OrderBy(x => x.Cliente);
// Paginação dos Grupos
var items = await grouped
.Skip((page - 1) * pageSize)
.Take(pageSize)
.ToListAsync();
return Ok(new UserDataGroupResponse
{
Data = new PagedResult<UserDataClientGroupDto>
{
Page = page,
PageSize = pageSize,
Total = totalGroups, // Total de Clientes
Items = items
},
Kpis = kpis // KPIs Totais
});
}
[HttpGet("clients")]
public async Task<ActionResult<List<string>>> GetClients()
{
return await _db.UserDatas.AsNoTracking()
.Where(x => !string.IsNullOrEmpty(x.Cliente))
.Select(x => x.Cliente!)
.Distinct()
.OrderBy(x => x)
.ToListAsync();
}
[HttpGet("{id:guid}")]
public async Task<ActionResult<UserDataDetailDto>> GetById(Guid id)
{
var x = await _db.UserDatas.AsNoTracking().FirstOrDefaultAsync(a => a.Id == id);
if (x == null) return NotFound();
return Ok(new UserDataDetailDto
{
Id = x.Id,
Item = x.Item,
Linha = x.Linha,
Cliente = x.Cliente,
Cpf = x.Cpf,
Rg = x.Rg,
Email = x.Email,
Celular = x.Celular,
Endereco = x.Endereco,
TelefoneFixo = x.TelefoneFixo,
DataNascimento = x.DataNascimento
});
}
}
}