Adição Lote de Linhas
This commit is contained in:
parent
5101c3665a
commit
0ab7fa955f
|
|
@ -785,6 +785,162 @@ namespace line_gestao_api.Controllers
|
||||||
return CreatedAtAction(nameof(GetById), new { id = newLine.Id }, ToDetailDto(newLine, vigencia));
|
return CreatedAtAction(nameof(GetById), new { id = newLine.Id }, ToDetailDto(newLine, vigencia));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ==========================================================
|
||||||
|
// ✅ 5.1. CREATE BATCH
|
||||||
|
// ==========================================================
|
||||||
|
[HttpPost("batch")]
|
||||||
|
[Authorize(Roles = "admin,gestor")]
|
||||||
|
public async Task<ActionResult<CreateMobileLinesBatchResultDto>> CreateBatch([FromBody] CreateMobileLinesBatchRequestDto req)
|
||||||
|
{
|
||||||
|
var requests = req?.Lines ?? new List<CreateMobileLineDto>();
|
||||||
|
if (requests.Count == 0)
|
||||||
|
return BadRequest(new { message = "Informe ao menos uma linha para cadastro em lote." });
|
||||||
|
|
||||||
|
if (requests.Count > 1000)
|
||||||
|
return BadRequest(new { message = "O lote excede o limite de 1000 linhas por envio." });
|
||||||
|
|
||||||
|
var requestedLinhas = requests
|
||||||
|
.Select(x => OnlyDigits(x?.Linha))
|
||||||
|
.Where(x => !string.IsNullOrWhiteSpace(x))
|
||||||
|
.Distinct(StringComparer.Ordinal)
|
||||||
|
.ToList();
|
||||||
|
|
||||||
|
var existingLinhas = requestedLinhas.Count == 0
|
||||||
|
? new HashSet<string>(StringComparer.Ordinal)
|
||||||
|
: (await _db.MobileLines.AsNoTracking()
|
||||||
|
.Where(x => x.Linha != null && requestedLinhas.Contains(x.Linha))
|
||||||
|
.Select(x => x.Linha!)
|
||||||
|
.ToListAsync())
|
||||||
|
.ToHashSet(StringComparer.Ordinal);
|
||||||
|
|
||||||
|
await using var tx = await _db.Database.BeginTransactionAsync();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var nextItem = (await _db.MobileLines.MaxAsync(x => (int?)x.Item) ?? 0);
|
||||||
|
var seenBatchLinhas = new HashSet<string>(StringComparer.Ordinal);
|
||||||
|
var createdLines = new List<(MobileLine line, VigenciaLine? vigencia)>(requests.Count);
|
||||||
|
|
||||||
|
for (var i = 0; i < requests.Count; i++)
|
||||||
|
{
|
||||||
|
var entry = requests[i];
|
||||||
|
var lineNo = i + 1;
|
||||||
|
|
||||||
|
if (entry == null)
|
||||||
|
return BadRequest(new { message = $"Linha do lote #{lineNo} está vazia." });
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(entry.Cliente))
|
||||||
|
return BadRequest(new { message = $"Linha do lote #{lineNo}: o nome do Cliente é obrigatório." });
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(entry.Linha))
|
||||||
|
return BadRequest(new { message = $"Linha do lote #{lineNo}: o número da Linha é obrigatório." });
|
||||||
|
|
||||||
|
if (!entry.DtEfetivacaoServico.HasValue)
|
||||||
|
return BadRequest(new { message = $"Linha do lote #{lineNo}: a Dt. Efetivação Serviço é obrigatória." });
|
||||||
|
|
||||||
|
if (!entry.DtTerminoFidelizacao.HasValue)
|
||||||
|
return BadRequest(new { message = $"Linha do lote #{lineNo}: a Dt. Término Fidelização é obrigatória." });
|
||||||
|
|
||||||
|
var linhaLimpa = OnlyDigits(entry.Linha);
|
||||||
|
var chipLimpo = OnlyDigits(entry.Chip);
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(linhaLimpa))
|
||||||
|
return BadRequest(new { message = $"Linha do lote #{lineNo}: número de linha inválido." });
|
||||||
|
|
||||||
|
if (!seenBatchLinhas.Add(linhaLimpa))
|
||||||
|
return Conflict(new { message = $"A linha {entry.Linha} está duplicada dentro do lote (registro #{lineNo})." });
|
||||||
|
|
||||||
|
if (existingLinhas.Contains(linhaLimpa))
|
||||||
|
return Conflict(new { message = $"A linha {entry.Linha} já está cadastrada no sistema (registro #{lineNo})." });
|
||||||
|
|
||||||
|
nextItem++;
|
||||||
|
|
||||||
|
var planSuggestion = await AutoFillRules.ResolvePlanSuggestionAsync(_db, entry.PlanoContrato);
|
||||||
|
var franquiaVivo = entry.FranquiaVivo ?? planSuggestion?.FranquiaGb;
|
||||||
|
var valorPlanoVivo = entry.ValorPlanoVivo ?? planSuggestion?.ValorPlano;
|
||||||
|
var now = DateTime.UtcNow;
|
||||||
|
|
||||||
|
var newLine = new MobileLine
|
||||||
|
{
|
||||||
|
Id = Guid.NewGuid(),
|
||||||
|
Item = nextItem,
|
||||||
|
Cliente = entry.Cliente.Trim().ToUpper(),
|
||||||
|
Linha = linhaLimpa,
|
||||||
|
Chip = string.IsNullOrWhiteSpace(chipLimpo) ? null : chipLimpo,
|
||||||
|
Usuario = entry.Usuario?.Trim(),
|
||||||
|
Status = entry.Status?.Trim(),
|
||||||
|
Skil = entry.Skil?.Trim(),
|
||||||
|
Modalidade = entry.Modalidade?.Trim(),
|
||||||
|
PlanoContrato = entry.PlanoContrato?.Trim(),
|
||||||
|
Conta = entry.Conta?.Trim(),
|
||||||
|
VencConta = entry.VencConta?.Trim(),
|
||||||
|
|
||||||
|
DataBloqueio = ToUtc(entry.DataBloqueio),
|
||||||
|
DataEntregaOpera = ToUtc(entry.DataEntregaOpera),
|
||||||
|
DataEntregaCliente = ToUtc(entry.DataEntregaCliente),
|
||||||
|
|
||||||
|
Cedente = entry.Cedente?.Trim(),
|
||||||
|
Solicitante = entry.Solicitante?.Trim(),
|
||||||
|
|
||||||
|
FranquiaVivo = franquiaVivo,
|
||||||
|
ValorPlanoVivo = valorPlanoVivo,
|
||||||
|
GestaoVozDados = entry.GestaoVozDados,
|
||||||
|
Skeelo = entry.Skeelo,
|
||||||
|
VivoNewsPlus = entry.VivoNewsPlus,
|
||||||
|
VivoTravelMundo = entry.VivoTravelMundo,
|
||||||
|
VivoSync = entry.VivoSync,
|
||||||
|
VivoGestaoDispositivo = entry.VivoGestaoDispositivo,
|
||||||
|
ValorContratoVivo = entry.ValorContratoVivo,
|
||||||
|
FranquiaLine = entry.FranquiaLine,
|
||||||
|
FranquiaGestao = entry.FranquiaGestao,
|
||||||
|
LocacaoAp = entry.LocacaoAp,
|
||||||
|
ValorContratoLine = entry.ValorContratoLine,
|
||||||
|
Desconto = entry.Desconto,
|
||||||
|
Lucro = entry.Lucro,
|
||||||
|
TipoDeChip = entry.TipoDeChip?.Trim(),
|
||||||
|
|
||||||
|
CreatedAt = now,
|
||||||
|
UpdatedAt = now
|
||||||
|
};
|
||||||
|
|
||||||
|
ApplyReservaRule(newLine);
|
||||||
|
|
||||||
|
_db.MobileLines.Add(newLine);
|
||||||
|
|
||||||
|
var vigencia = await UpsertVigenciaFromMobileLineAsync(
|
||||||
|
newLine,
|
||||||
|
entry.DtEfetivacaoServico,
|
||||||
|
entry.DtTerminoFidelizacao,
|
||||||
|
overrideDates: false);
|
||||||
|
|
||||||
|
createdLines.Add((newLine, vigencia));
|
||||||
|
}
|
||||||
|
|
||||||
|
await _db.SaveChangesAsync();
|
||||||
|
await tx.CommitAsync();
|
||||||
|
await _vigenciaNotificationSyncService.SyncCurrentTenantAsync();
|
||||||
|
|
||||||
|
return Ok(new CreateMobileLinesBatchResultDto
|
||||||
|
{
|
||||||
|
Created = createdLines.Count,
|
||||||
|
Items = createdLines
|
||||||
|
.Select(x => new CreateMobileLinesBatchCreatedItemDto
|
||||||
|
{
|
||||||
|
Id = x.line.Id,
|
||||||
|
Item = x.line.Item,
|
||||||
|
Linha = x.line.Linha,
|
||||||
|
Cliente = x.line.Cliente
|
||||||
|
})
|
||||||
|
.ToList()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch (DbUpdateException)
|
||||||
|
{
|
||||||
|
await tx.RollbackAsync();
|
||||||
|
return StatusCode(500, new { message = "Erro ao salvar o lote no banco de dados." });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ==========================================================
|
// ==========================================================
|
||||||
// ✅ 6. UPDATE
|
// ✅ 6. UPDATE
|
||||||
// ==========================================================
|
// ==========================================================
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,24 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace line_gestao_api.Dtos
|
||||||
|
{
|
||||||
|
public class CreateMobileLinesBatchRequestDto
|
||||||
|
{
|
||||||
|
public List<CreateMobileLineDto> Lines { get; set; } = new();
|
||||||
|
}
|
||||||
|
|
||||||
|
public class CreateMobileLinesBatchResultDto
|
||||||
|
{
|
||||||
|
public int Created { get; set; }
|
||||||
|
public List<CreateMobileLinesBatchCreatedItemDto> Items { get; set; } = new();
|
||||||
|
}
|
||||||
|
|
||||||
|
public class CreateMobileLinesBatchCreatedItemDto
|
||||||
|
{
|
||||||
|
public Guid Id { get; set; }
|
||||||
|
public int Item { get; set; }
|
||||||
|
public string? Linha { get; set; }
|
||||||
|
public string? Cliente { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue