Compare commits
No commits in common. "bd17f86f66e36cd6a7b942bd597ea01b5e2bb88c" and "c81a7d1ed90256cf5643dbca722aa9e5a9ee540f" have entirely different histories.
bd17f86f66
...
c81a7d1ed9
|
|
@ -27,13 +27,14 @@ namespace line_gestao_api.Controllers
|
|||
}
|
||||
|
||||
// ==========================================================
|
||||
// ✅ 1. ENDPOINT: AGRUPAR POR CLIENTE
|
||||
// ✅ 1. ENDPOINT: AGRUPAR POR CLIENTE (COM BUSCA E PAGINAÇÃO)
|
||||
// ==========================================================
|
||||
// Alterado para aceitar 'search', 'page' e retornar PagedResult
|
||||
[HttpGet("groups")]
|
||||
public async Task<ActionResult<PagedResult<ClientGroupDto>>> GetClientGroups(
|
||||
[FromQuery] string? skil,
|
||||
[FromQuery] string? search,
|
||||
[FromQuery] int page = 1,
|
||||
[FromQuery] string? search, // 🔍 Busca por Nome do Cliente
|
||||
[FromQuery] int page = 1, // 📄 Paginação
|
||||
[FromQuery] int pageSize = 10)
|
||||
{
|
||||
page = page < 1 ? 1 : page;
|
||||
|
|
@ -41,23 +42,30 @@ namespace line_gestao_api.Controllers
|
|||
|
||||
var query = _db.MobileLines.AsNoTracking().Where(x => !string.IsNullOrEmpty(x.Cliente));
|
||||
|
||||
// Filtro SKIL
|
||||
// 1. Filtro SKIL (PF, PJ ou RESERVA)
|
||||
if (!string.IsNullOrWhiteSpace(skil))
|
||||
{
|
||||
var sSkil = skil.Trim();
|
||||
|
||||
if (sSkil.Equals("RESERVA", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
query = query.Where(x => x.Skil == "RESERVA" || EF.Functions.ILike(x.Skil ?? "", "%RESERVA%"));
|
||||
}
|
||||
else
|
||||
{
|
||||
query = query.Where(x => EF.Functions.ILike(x.Skil ?? "", $"%{sSkil}%"));
|
||||
}
|
||||
}
|
||||
|
||||
// Filtro SEARCH (Busca pelo Nome do Cliente)
|
||||
// 2. Filtro SEARCH (Busca pelo Nome do Cliente nos grupos)
|
||||
// Aqui garantimos que se o usuário digitar "ADR", filtramos apenas os clientes que tem ADR no nome
|
||||
if (!string.IsNullOrWhiteSpace(search))
|
||||
{
|
||||
var s = search.Trim();
|
||||
query = query.Where(x => EF.Functions.ILike(x.Cliente ?? "", $"%{s}%"));
|
||||
}
|
||||
|
||||
// Montagem do Agrupamento
|
||||
var groupedQuery = query
|
||||
.GroupBy(x => x.Cliente)
|
||||
.Select(g => new ClientGroupDto
|
||||
|
|
@ -66,18 +74,21 @@ namespace line_gestao_api.Controllers
|
|||
TotalLinhas = g.Count(),
|
||||
Ativos = g.Count(x => EF.Functions.ILike(x.Status ?? "", "%ativo%")),
|
||||
Bloqueados = g.Count(x => EF.Functions.ILike(x.Status ?? "", "%bloque%") ||
|
||||
EF.Functions.ILike(x.Status ?? "", "%perda%") ||
|
||||
EF.Functions.ILike(x.Status ?? "", "%roubo%"))
|
||||
EF.Functions.ILike(x.Status ?? "", "%perda%") ||
|
||||
EF.Functions.ILike(x.Status ?? "", "%roubo%"))
|
||||
});
|
||||
|
||||
// Contagem total para a paginação
|
||||
var totalGroups = await groupedQuery.CountAsync();
|
||||
|
||||
// Aplicação da Paginação
|
||||
var items = await groupedQuery
|
||||
.OrderBy(x => x.Cliente)
|
||||
.Skip((page - 1) * pageSize)
|
||||
.Take(pageSize)
|
||||
.ToListAsync();
|
||||
|
||||
// Retorna formato paginado
|
||||
return Ok(new PagedResult<ClientGroupDto>
|
||||
{
|
||||
Page = page,
|
||||
|
|
@ -105,7 +116,7 @@ namespace line_gestao_api.Controllers
|
|||
}
|
||||
|
||||
// ==========================================================
|
||||
// ✅ 3. GET ALL (TABELA / DETALHES DO GRUPO)
|
||||
// ✅ 3. GET ALL (TABELA / DETALHES DO GRUPO / BUSCA ESPECÍFICA)
|
||||
// ==========================================================
|
||||
[HttpGet]
|
||||
public async Task<ActionResult<PagedResult<MobileLineListDto>>> GetAll(
|
||||
|
|
@ -122,6 +133,7 @@ namespace line_gestao_api.Controllers
|
|||
|
||||
var q = _db.MobileLines.AsNoTracking();
|
||||
|
||||
// Filtro SKIL
|
||||
if (!string.IsNullOrWhiteSpace(skil))
|
||||
{
|
||||
var sSkil = skil.Trim();
|
||||
|
|
@ -131,18 +143,21 @@ namespace line_gestao_api.Controllers
|
|||
q = q.Where(x => EF.Functions.ILike(x.Skil ?? "", $"%{sSkil}%"));
|
||||
}
|
||||
|
||||
// Filtro Cliente Específico (usado ao expandir o grupo)
|
||||
if (!string.IsNullOrWhiteSpace(client))
|
||||
{
|
||||
q = q.Where(x => EF.Functions.ILike(x.Cliente ?? "", client.Trim()));
|
||||
var sClient = client.Trim();
|
||||
q = q.Where(x => EF.Functions.ILike(x.Cliente ?? "", sClient));
|
||||
}
|
||||
|
||||
// Busca Genérica (usada quando o frontend detecta números ou busca específica)
|
||||
if (!string.IsNullOrWhiteSpace(search))
|
||||
{
|
||||
var s = search.Trim();
|
||||
q = q.Where(x =>
|
||||
EF.Functions.ILike(x.Linha ?? "", $"%{s}%") ||
|
||||
EF.Functions.ILike(x.Chip ?? "", $"%{s}%") ||
|
||||
EF.Functions.ILike(x.Cliente ?? "", $"%{s}%") ||
|
||||
EF.Functions.ILike(x.Cliente ?? "", $"%{s}%") || // Busca cliente aqui também caso seja modo tabela
|
||||
EF.Functions.ILike(x.Usuario ?? "", $"%{s}%") ||
|
||||
EF.Functions.ILike(x.Conta ?? "", $"%{s}%") ||
|
||||
EF.Functions.ILike(x.Status ?? "", $"%{s}%"));
|
||||
|
|
@ -201,183 +216,33 @@ namespace line_gestao_api.Controllers
|
|||
}
|
||||
|
||||
// ==========================================================
|
||||
// ✅ 4. GET BY ID
|
||||
// DEMAIS MÉTODOS (CRUD, IMPORT, HELPERS) - MANTIDOS
|
||||
// ==========================================================
|
||||
[HttpGet("{id:guid}")]
|
||||
public async Task<ActionResult<MobileLineDetailDto>> GetById(Guid id)
|
||||
{
|
||||
var x = await _db.MobileLines.AsNoTracking().FirstOrDefaultAsync(a => a.Id == id);
|
||||
if (x == null) return NotFound();
|
||||
return Ok(ToDetailDto(x));
|
||||
}
|
||||
[HttpGet("{id:guid}")] public async Task<ActionResult<MobileLineDetailDto>> GetById(Guid id) { var x = await _db.MobileLines.AsNoTracking().FirstOrDefaultAsync(a => a.Id == id); if (x == null) return NotFound(); return Ok(ToDetailDto(x)); }
|
||||
|
||||
// ==========================================================
|
||||
// ✅ 5. CREATE (AUTO-INCREMENTO DE ID/ITEM)
|
||||
// ==========================================================
|
||||
[HttpPost]
|
||||
public async Task<ActionResult<MobileLineDetailDto>> Create([FromBody] CreateMobileLineDto req)
|
||||
{
|
||||
// Validações Básicas
|
||||
if (string.IsNullOrWhiteSpace(req.Cliente))
|
||||
return BadRequest(new { message = "O nome do Cliente é obrigatório." });
|
||||
|
||||
if (string.IsNullOrWhiteSpace(req.Linha))
|
||||
return BadRequest(new { message = "O número da Linha é obrigatório." });
|
||||
|
||||
// Sanitização da Linha e Chip (Remove máscara)
|
||||
var linhaLimpa = OnlyDigits(req.Linha);
|
||||
var chipLimpo = OnlyDigits(req.Chip);
|
||||
|
||||
if (string.IsNullOrWhiteSpace(linhaLimpa))
|
||||
return BadRequest(new { message = "Número de linha inválido." });
|
||||
|
||||
// Verifica Duplicidade
|
||||
var exists = await _db.MobileLines.AsNoTracking().AnyAsync(x => x.Linha == linhaLimpa);
|
||||
if (exists)
|
||||
return Conflict(new { message = $"A linha {req.Linha} já está cadastrada no sistema." });
|
||||
|
||||
// Lógica de Auto-Incremento do Item
|
||||
// Busca o maior ID (Item) atual e soma 1. Se não houver nenhum, começa do 1.
|
||||
var maxItem = await _db.MobileLines.MaxAsync(x => (int?)x.Item) ?? 0;
|
||||
var nextItem = maxItem + 1;
|
||||
|
||||
// Mapeamento DTO -> Entity
|
||||
var newLine = new MobileLine
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
Item = nextItem, // Define o Item calculado automaticamente
|
||||
Cliente = req.Cliente.Trim().ToUpper(),
|
||||
Linha = linhaLimpa,
|
||||
Chip = chipLimpo,
|
||||
Usuario = req.Usuario?.Trim(),
|
||||
Status = req.Status?.Trim(),
|
||||
Skil = req.Skil?.Trim(),
|
||||
Modalidade = req.Modalidade?.Trim(),
|
||||
PlanoContrato = req.PlanoContrato?.Trim(),
|
||||
Conta = req.Conta?.Trim(),
|
||||
VencConta = req.VencConta?.Trim(),
|
||||
|
||||
// Datas
|
||||
DataBloqueio = ToUtc(req.DataBloqueio),
|
||||
DataEntregaOpera = ToUtc(req.DataEntregaOpera),
|
||||
DataEntregaCliente = ToUtc(req.DataEntregaCliente),
|
||||
|
||||
// Logística
|
||||
Cedente = req.Cedente?.Trim(),
|
||||
Solicitante = req.Solicitante?.Trim(),
|
||||
|
||||
// Financeiro
|
||||
FranquiaVivo = req.FranquiaVivo,
|
||||
ValorPlanoVivo = req.ValorPlanoVivo,
|
||||
GestaoVozDados = req.GestaoVozDados,
|
||||
Skeelo = req.Skeelo,
|
||||
VivoNewsPlus = req.VivoNewsPlus,
|
||||
VivoTravelMundo = req.VivoTravelMundo,
|
||||
VivoGestaoDispositivo = req.VivoGestaoDispositivo,
|
||||
ValorContratoVivo = req.ValorContratoVivo,
|
||||
FranquiaLine = req.FranquiaLine,
|
||||
FranquiaGestao = req.FranquiaGestao,
|
||||
LocacaoAp = req.LocacaoAp,
|
||||
ValorContratoLine = req.ValorContratoLine,
|
||||
Desconto = req.Desconto,
|
||||
Lucro = req.Lucro,
|
||||
|
||||
CreatedAt = DateTime.UtcNow,
|
||||
UpdatedAt = DateTime.UtcNow
|
||||
};
|
||||
|
||||
// Aplica regra de negócio para Reserva (se necessário)
|
||||
ApplyReservaRule(newLine);
|
||||
|
||||
_db.MobileLines.Add(newLine);
|
||||
|
||||
try
|
||||
{
|
||||
await _db.SaveChangesAsync();
|
||||
}
|
||||
catch (DbUpdateException)
|
||||
{
|
||||
return StatusCode(500, new { message = "Erro ao salvar no banco de dados." });
|
||||
}
|
||||
|
||||
// Retorna o objeto criado com o código 201 Created
|
||||
return CreatedAtAction(nameof(GetById), new { id = newLine.Id }, ToDetailDto(newLine));
|
||||
}
|
||||
|
||||
// ==========================================================
|
||||
// ✅ 6. UPDATE (ITEM PROTEGIDO)
|
||||
// ==========================================================
|
||||
[HttpPut("{id:guid}")]
|
||||
public async Task<IActionResult> Update(Guid id, [FromBody] UpdateMobileLineRequest req)
|
||||
{
|
||||
var x = await _db.MobileLines.FirstOrDefaultAsync(a => a.Id == id);
|
||||
if (x == null) return NotFound();
|
||||
|
||||
var newLinha = OnlyDigits(req.Linha);
|
||||
if (!string.IsNullOrWhiteSpace(newLinha) && !string.Equals((x.Linha ?? ""), newLinha, StringComparison.Ordinal))
|
||||
{
|
||||
var exists = await _db.MobileLines.AsNoTracking().AnyAsync(m => m.Linha == newLinha && m.Id != id);
|
||||
if (exists) return Conflict(new { message = "Já existe registro com essa LINHA.", linha = newLinha });
|
||||
}
|
||||
if (!string.IsNullOrWhiteSpace(newLinha) && !string.Equals((x.Linha ?? ""), newLinha, StringComparison.Ordinal)) { var exists = await _db.MobileLines.AsNoTracking().AnyAsync(m => m.Linha == newLinha && m.Id != id); if (exists) return Conflict(new { message = "Já existe registro com essa LINHA.", linha = newLinha }); }
|
||||
|
||||
// OBS: Não atualizamos x.Item aqui para garantir a integridade histórica.
|
||||
// O Item é gerado na criação e não muda na edição.
|
||||
|
||||
x.Conta = req.Conta?.Trim();
|
||||
x.Linha = newLinha;
|
||||
x.Chip = OnlyDigits(req.Chip);
|
||||
x.Cliente = req.Cliente?.Trim();
|
||||
x.Usuario = req.Usuario?.Trim();
|
||||
x.PlanoContrato = req.PlanoContrato?.Trim();
|
||||
x.FranquiaVivo = req.FranquiaVivo;
|
||||
x.ValorPlanoVivo = req.ValorPlanoVivo;
|
||||
x.GestaoVozDados = req.GestaoVozDados;
|
||||
x.Skeelo = req.Skeelo;
|
||||
x.VivoNewsPlus = req.VivoNewsPlus;
|
||||
x.VivoTravelMundo = req.VivoTravelMundo;
|
||||
x.VivoGestaoDispositivo = req.VivoGestaoDispositivo;
|
||||
x.ValorContratoVivo = req.ValorContratoVivo;
|
||||
x.FranquiaLine = req.FranquiaLine;
|
||||
x.FranquiaGestao = req.FranquiaGestao;
|
||||
x.LocacaoAp = req.LocacaoAp;
|
||||
x.ValorContratoLine = req.ValorContratoLine;
|
||||
x.Desconto = req.Desconto;
|
||||
x.Lucro = req.Lucro;
|
||||
x.Status = req.Status?.Trim();
|
||||
x.DataBloqueio = ToUtc(req.DataBloqueio);
|
||||
x.Skil = req.Skil?.Trim();
|
||||
x.Modalidade = req.Modalidade?.Trim();
|
||||
x.Cedente = req.Cedente?.Trim();
|
||||
x.Solicitante = req.Solicitante?.Trim();
|
||||
x.DataEntregaOpera = ToUtc(req.DataEntregaOpera);
|
||||
x.DataEntregaCliente = ToUtc(req.DataEntregaCliente);
|
||||
x.VencConta = req.VencConta?.Trim();
|
||||
|
||||
ApplyReservaRule(x);
|
||||
x.UpdatedAt = DateTime.UtcNow;
|
||||
|
||||
try { await _db.SaveChangesAsync(); }
|
||||
catch (DbUpdateException) { return Conflict(new { message = "Conflito ao salvar." }); }
|
||||
x.Item = req.Item; x.Conta = req.Conta?.Trim(); x.Linha = newLinha; x.Chip = OnlyDigits(req.Chip); x.Cliente = req.Cliente?.Trim(); x.Usuario = req.Usuario?.Trim();
|
||||
x.PlanoContrato = req.PlanoContrato?.Trim(); x.FranquiaVivo = req.FranquiaVivo; x.ValorPlanoVivo = req.ValorPlanoVivo; x.GestaoVozDados = req.GestaoVozDados;
|
||||
x.Skeelo = req.Skeelo; x.VivoNewsPlus = req.VivoNewsPlus; x.VivoTravelMundo = req.VivoTravelMundo; x.VivoGestaoDispositivo = req.VivoGestaoDispositivo;
|
||||
x.ValorContratoVivo = req.ValorContratoVivo; x.FranquiaLine = req.FranquiaLine; x.FranquiaGestao = req.FranquiaGestao; x.LocacaoAp = req.LocacaoAp;
|
||||
x.ValorContratoLine = req.ValorContratoLine; x.Desconto = req.Desconto; x.Lucro = req.Lucro; x.Status = req.Status?.Trim();
|
||||
x.DataBloqueio = ToUtc(req.DataBloqueio); x.Skil = req.Skil?.Trim(); x.Modalidade = req.Modalidade?.Trim(); x.Cedente = req.Cedente?.Trim();
|
||||
x.Solicitante = req.Solicitante?.Trim(); x.DataEntregaOpera = ToUtc(req.DataEntregaOpera); x.DataEntregaCliente = ToUtc(req.DataEntregaCliente);
|
||||
x.VencConta = req.VencConta?.Trim(); ApplyReservaRule(x); x.UpdatedAt = DateTime.UtcNow;
|
||||
|
||||
try { await _db.SaveChangesAsync(); } catch (DbUpdateException) { return Conflict(new { message = "Conflito ao salvar." }); }
|
||||
return NoContent();
|
||||
}
|
||||
|
||||
// ==========================================================
|
||||
// ✅ 7. DELETE
|
||||
// ==========================================================
|
||||
[HttpDelete("{id:guid}")]
|
||||
public async Task<IActionResult> Delete(Guid id)
|
||||
{
|
||||
var x = await _db.MobileLines.FirstOrDefaultAsync(a => a.Id == id);
|
||||
if (x == null) return NotFound();
|
||||
_db.MobileLines.Remove(x);
|
||||
await _db.SaveChangesAsync();
|
||||
return NoContent();
|
||||
}
|
||||
[HttpDelete("{id:guid}")] public async Task<IActionResult> Delete(Guid id) { var x = await _db.MobileLines.FirstOrDefaultAsync(a => a.Id == id); if (x == null) return NotFound(); _db.MobileLines.Remove(x); await _db.SaveChangesAsync(); return NoContent(); }
|
||||
|
||||
// ==========================================================
|
||||
// ✅ 8. IMPORT EXCEL
|
||||
// ==========================================================
|
||||
[HttpPost("import-excel")]
|
||||
[Consumes("multipart/form-data")]
|
||||
[RequestSizeLimit(50_000_000)]
|
||||
|
|
@ -438,56 +303,10 @@ namespace line_gestao_api.Controllers
|
|||
return Ok(new ImportResultDto { Imported = imported });
|
||||
}
|
||||
|
||||
// ==========================================================
|
||||
// HELPERS
|
||||
// ==========================================================
|
||||
// Helpers
|
||||
private static DateTime? ToUtc(DateTime? dt) { if (dt == null) return null; var v = dt.Value; return v.Kind == DateTimeKind.Utc ? v : (v.Kind == DateTimeKind.Local ? v.ToUniversalTime() : DateTime.SpecifyKind(v, DateTimeKind.Utc)); }
|
||||
|
||||
private static MobileLineDetailDto ToDetailDto(MobileLine x) => new()
|
||||
{
|
||||
Id = x.Id,
|
||||
Item = x.Item,
|
||||
Conta = x.Conta,
|
||||
Linha = x.Linha,
|
||||
Chip = x.Chip,
|
||||
Cliente = x.Cliente,
|
||||
Usuario = x.Usuario,
|
||||
PlanoContrato = x.PlanoContrato,
|
||||
FranquiaVivo = x.FranquiaVivo,
|
||||
ValorPlanoVivo = x.ValorPlanoVivo,
|
||||
GestaoVozDados = x.GestaoVozDados,
|
||||
Skeelo = x.Skeelo,
|
||||
VivoNewsPlus = x.VivoNewsPlus,
|
||||
VivoTravelMundo = x.VivoTravelMundo,
|
||||
VivoGestaoDispositivo = x.VivoGestaoDispositivo,
|
||||
ValorContratoVivo = x.ValorContratoVivo,
|
||||
FranquiaLine = x.FranquiaLine,
|
||||
FranquiaGestao = x.FranquiaGestao,
|
||||
LocacaoAp = x.LocacaoAp,
|
||||
ValorContratoLine = x.ValorContratoLine,
|
||||
Desconto = x.Desconto,
|
||||
Lucro = x.Lucro,
|
||||
Status = x.Status,
|
||||
DataBloqueio = x.DataBloqueio,
|
||||
Skil = x.Skil,
|
||||
Modalidade = x.Modalidade,
|
||||
Cedente = x.Cedente,
|
||||
Solicitante = x.Solicitante,
|
||||
DataEntregaOpera = x.DataEntregaOpera,
|
||||
DataEntregaCliente = x.DataEntregaCliente,
|
||||
VencConta = x.VencConta
|
||||
};
|
||||
|
||||
private static void ApplyReservaRule(MobileLine x)
|
||||
{
|
||||
if ((x.Cliente ?? "").Trim().ToUpper() == "RESERVA" || (x.Usuario ?? "").Trim().ToUpper() == "RESERVA")
|
||||
{
|
||||
x.Cliente = "RESERVA";
|
||||
x.Usuario = "RESERVA";
|
||||
x.Skil = "RESERVA";
|
||||
}
|
||||
}
|
||||
|
||||
private static MobileLineDetailDto ToDetailDto(MobileLine x) => new() { Id = x.Id, Item = x.Item, Conta = x.Conta, Linha = x.Linha, Chip = x.Chip, Cliente = x.Cliente, Usuario = x.Usuario, PlanoContrato = x.PlanoContrato, FranquiaVivo = x.FranquiaVivo, ValorPlanoVivo = x.ValorPlanoVivo, GestaoVozDados = x.GestaoVozDados, Skeelo = x.Skeelo, VivoNewsPlus = x.VivoNewsPlus, VivoTravelMundo = x.VivoTravelMundo, VivoGestaoDispositivo = x.VivoGestaoDispositivo, ValorContratoVivo = x.ValorContratoVivo, FranquiaLine = x.FranquiaLine, FranquiaGestao = x.FranquiaGestao, LocacaoAp = x.LocacaoAp, ValorContratoLine = x.ValorContratoLine, Desconto = x.Desconto, Lucro = x.Lucro, Status = x.Status, DataBloqueio = x.DataBloqueio, Skil = x.Skil, Modalidade = x.Modalidade, Cedente = x.Cedente, Solicitante = x.Solicitante, DataEntregaOpera = x.DataEntregaOpera, DataEntregaCliente = x.DataEntregaCliente, VencConta = x.VencConta };
|
||||
private static void ApplyReservaRule(MobileLine x) { if ((x.Cliente ?? "").Trim().ToUpper() == "RESERVA" || (x.Usuario ?? "").Trim().ToUpper() == "RESERVA") { x.Cliente = "RESERVA"; x.Usuario = "RESERVA"; x.Skil = "RESERVA"; } }
|
||||
private static int GetCol(Dictionary<string, int> map, string name) => map.TryGetValue(NormalizeHeader(name), out var c) ? c : 0;
|
||||
private static string GetCellByHeader(IXLWorksheet ws, int row, Dictionary<string, int> map, string header) { var k = NormalizeHeader(header); return map.TryGetValue(k, out var c) ? GetCellString(ws, row, c) : ""; }
|
||||
private static string GetCellString(IXLWorksheet ws, int row, int col) { var c = ws.Cell(row, col); return c == null ? "" : (c.GetValue<string>() ?? "").Trim(); }
|
||||
|
|
|
|||
|
|
@ -1,69 +0,0 @@
|
|||
using System;
|
||||
|
||||
namespace line_gestao_api.Dtos
|
||||
{
|
||||
public class CreateMobileLineDto
|
||||
{
|
||||
// ==========================
|
||||
// Identificação Básica
|
||||
// ==========================
|
||||
public int Item { get; set; }
|
||||
public string? Linha { get; set; } // Obrigatório na validação do Controller
|
||||
public string? Chip { get; set; } // ICCID
|
||||
public string? Cliente { get; set; } // Obrigatório na validação do Controller
|
||||
public string? Usuario { get; set; }
|
||||
|
||||
// ==========================
|
||||
// Classificação e Status
|
||||
// ==========================
|
||||
public string? Status { get; set; } // Ex: ATIVA, BLOQUEADA
|
||||
public string? Skil { get; set; } // Ex: PF, PJ, RESERVA
|
||||
public string? Modalidade { get; set; }
|
||||
|
||||
// ==========================
|
||||
// Dados Contratuais
|
||||
// ==========================
|
||||
public string? PlanoContrato { get; set; }
|
||||
public string? Conta { get; set; }
|
||||
public string? VencConta { get; set; } // Dia do vencimento (string)
|
||||
|
||||
// ==========================
|
||||
// Datas Importantes
|
||||
// ==========================
|
||||
public DateTime? DataBloqueio { get; set; }
|
||||
public DateTime? DataEntregaOpera { get; set; }
|
||||
public DateTime? DataEntregaCliente { get; set; }
|
||||
|
||||
// ==========================
|
||||
// Responsáveis / Logística
|
||||
// ==========================
|
||||
public string? Cedente { get; set; }
|
||||
public string? Solicitante { get; set; }
|
||||
|
||||
// ==========================
|
||||
// Financeiro - Vivo
|
||||
// ==========================
|
||||
public decimal? FranquiaVivo { get; set; }
|
||||
public decimal? ValorPlanoVivo { get; set; }
|
||||
public decimal? GestaoVozDados { get; set; }
|
||||
public decimal? Skeelo { get; set; }
|
||||
public decimal? VivoNewsPlus { get; set; }
|
||||
public decimal? VivoTravelMundo { get; set; }
|
||||
public decimal? VivoGestaoDispositivo { get; set; }
|
||||
public decimal? ValorContratoVivo { get; set; }
|
||||
|
||||
// ==========================
|
||||
// Financeiro - Line Móvel
|
||||
// ==========================
|
||||
public decimal? FranquiaLine { get; set; }
|
||||
public decimal? FranquiaGestao { get; set; }
|
||||
public decimal? LocacaoAp { get; set; }
|
||||
public decimal? ValorContratoLine { get; set; }
|
||||
|
||||
// ==========================
|
||||
// Resultado Financeiro
|
||||
// ==========================
|
||||
public decimal? Desconto { get; set; }
|
||||
public decimal? Lucro { get; set; }
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue