This commit is contained in:
Eduardo Lopes 2026-01-30 12:55:35 -03:00 committed by GitHub
commit e4231c7948
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 184 additions and 12 deletions

View File

@ -350,6 +350,114 @@ namespace line_gestao_api.Controllers
if (string.IsNullOrWhiteSpace(req.Cliente))
return BadRequest(new { message = "O nome do Cliente é obrigatório." });
if (req.Linhas != null && req.Linhas.Count > 0)
{
var itens = req.Linhas;
var linhasNormalizadas = new List<string>(itens.Count);
for (var i = 0; i < itens.Count; i++)
{
var linhaOriginal = itens[i].Linha;
if (string.IsNullOrWhiteSpace(linhaOriginal))
return BadRequest(new { message = $"O número da Linha é obrigatório (linha {i + 1})." });
var linhaItemLimpa = OnlyDigits(linhaOriginal);
if (string.IsNullOrWhiteSpace(linhaItemLimpa))
return BadRequest(new { message = $"Número de linha inválido (linha {i + 1})." });
linhasNormalizadas.Add(linhaItemLimpa);
}
var duplicadas = linhasNormalizadas
.GroupBy(x => x)
.Where(g => g.Count() > 1)
.Select(g => g.Key)
.ToList();
if (duplicadas.Count > 0)
return Conflict(new { message = $"Existem linhas duplicadas na requisição: {string.Join(", ", duplicadas)}." });
var existentes = await _db.MobileLines
.AsNoTracking()
.Where(x => x.Linha != null && linhasNormalizadas.Contains(x.Linha))
.Select(x => x.Linha!)
.ToListAsync();
if (existentes.Count > 0)
return Conflict(new { message = $"As linhas {string.Join(", ", existentes)} já estão cadastradas no sistema." });
var maxItem = await _db.MobileLines.MaxAsync(x => (int?)x.Item) ?? 0;
var now = DateTime.UtcNow;
var created = new List<MobileLine>(itens.Count);
for (var i = 0; i < itens.Count; i++)
{
var item = itens[i];
var linhaItemLimpa = linhasNormalizadas[i];
var chipItemLimpo = OnlyDigits(item.Chip);
var newLine = new MobileLine
{
Id = Guid.NewGuid(),
Item = maxItem + 1 + i,
Cliente = req.Cliente.Trim().ToUpper(),
Linha = linhaItemLimpa,
Chip = string.IsNullOrWhiteSpace(chipItemLimpo) ? null : chipItemLimpo,
Usuario = item.Usuario?.Trim(),
Status = item.Status?.Trim(),
Skil = item.Skil?.Trim(),
Modalidade = item.Modalidade?.Trim(),
PlanoContrato = item.PlanoContrato?.Trim(),
Conta = item.Conta?.Trim(),
VencConta = item.VencConta?.Trim(),
DataBloqueio = ToUtc(item.DataBloqueio),
DataEntregaOpera = ToUtc(item.DataEntregaOpera),
DataEntregaCliente = ToUtc(item.DataEntregaCliente),
Cedente = item.Cedente?.Trim(),
Solicitante = item.Solicitante?.Trim(),
FranquiaVivo = item.FranquiaVivo,
ValorPlanoVivo = item.ValorPlanoVivo,
GestaoVozDados = item.GestaoVozDados,
Skeelo = item.Skeelo,
VivoNewsPlus = item.VivoNewsPlus,
VivoTravelMundo = item.VivoTravelMundo,
VivoGestaoDispositivo = item.VivoGestaoDispositivo,
ValorContratoVivo = item.ValorContratoVivo,
FranquiaLine = item.FranquiaLine,
FranquiaGestao = item.FranquiaGestao,
LocacaoAp = item.LocacaoAp,
ValorContratoLine = item.ValorContratoLine,
Desconto = item.Desconto,
Lucro = item.Lucro,
CreatedAt = now,
UpdatedAt = now
};
ApplyReservaRule(newLine);
created.Add(newLine);
}
_db.MobileLines.AddRange(created);
try
{
await _db.SaveChangesAsync();
}
catch (DbUpdateException)
{
return StatusCode(500, new { message = "Erro ao salvar no banco de dados." });
}
return StatusCode(StatusCodes.Status201Created, created.Select(ToDetailDto).ToList());
}
if (req.QtdLinhas.GetValueOrDefault(1) > 1)
return BadRequest(new { message = "Para criar múltiplas linhas, envie a lista em 'Linhas' com os dados de cada linha." });
if (string.IsNullOrWhiteSpace(req.Linha))
return BadRequest(new { message = "O número da Linha é obrigatório." });
@ -363,15 +471,13 @@ namespace line_gestao_api.Controllers
if (exists)
return Conflict(new { message = $"A linha {req.Linha} já está cadastrada no sistema." });
var maxItem = await _db.MobileLines.MaxAsync(x => (int?)x.Item) ?? 0;
var nextItem = maxItem + 1;
var maxItemSingle = await _db.MobileLines.MaxAsync(x => (int?)x.Item) ?? 0;
var nowSingle = DateTime.UtcNow;
var now = DateTime.UtcNow;
var newLine = new MobileLine
var newLineSingle = new MobileLine
{
Id = Guid.NewGuid(),
Item = nextItem,
Item = maxItemSingle + 1,
Cliente = req.Cliente.Trim().ToUpper(),
Linha = linhaLimpa,
Chip = string.IsNullOrWhiteSpace(chipLimpo) ? null : chipLimpo,
@ -405,13 +511,13 @@ namespace line_gestao_api.Controllers
Desconto = req.Desconto,
Lucro = req.Lucro,
CreatedAt = now,
UpdatedAt = now
CreatedAt = nowSingle,
UpdatedAt = nowSingle
};
ApplyReservaRule(newLine);
ApplyReservaRule(newLineSingle);
_db.MobileLines.Add(newLine);
_db.MobileLines.Add(newLineSingle);
try
{
@ -422,7 +528,7 @@ namespace line_gestao_api.Controllers
return StatusCode(500, new { message = "Erro ao salvar no banco de dados." });
}
return CreatedAtAction(nameof(GetById), new { id = newLine.Id }, ToDetailDto(newLine));
return CreatedAtAction(nameof(GetById), new { id = newLineSingle.Id }, ToDetailDto(newLineSingle));
}
// ==========================================================

View File

@ -1,4 +1,5 @@
using System;
using System.Collections.Generic;
namespace line_gestao_api.Dtos
{
@ -12,6 +13,8 @@ namespace line_gestao_api.Dtos
public string? Chip { get; set; } // ICCID
public string? Cliente { get; set; } // Obrigatório na validação do Controller
public string? Usuario { get; set; }
public int? QtdLinhas { get; set; } // Quantidade de linhas (uso legado)
public List<CreateMobileLineItemDto>? Linhas { get; set; } // Linhas individuais para criação em lote
// ==========================
// Classificação e Status
@ -66,4 +69,67 @@ namespace line_gestao_api.Dtos
public decimal? Desconto { get; set; }
public decimal? Lucro { get; set; }
}
public class CreateMobileLineItemDto
{
// ==========================
// Identificação Básica
// ==========================
public string? Linha { get; set; }
public string? Chip { get; set; }
public string? Usuario { get; set; }
// ==========================
// Classificação e Status
// ==========================
public string? Status { get; set; }
public string? Skil { get; set; }
public string? Modalidade { get; set; }
// ==========================
// Dados Contratuais
// ==========================
public string? PlanoContrato { get; set; }
public string? Conta { get; set; }
public string? VencConta { get; set; }
// ==========================
// 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; }
}
}