Compare commits
2 Commits
bd17f86f66
...
56327ae074
| Author | SHA1 | Date |
|---|---|---|
|
|
56327ae074 | |
|
|
72709813c3 |
|
|
@ -0,0 +1,122 @@
|
||||||
|
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/[controller]")]
|
||||||
|
public class BillingController : ControllerBase
|
||||||
|
{
|
||||||
|
private readonly AppDbContext _db;
|
||||||
|
public BillingController(AppDbContext db) => _db = db;
|
||||||
|
|
||||||
|
[HttpGet]
|
||||||
|
public async Task<ActionResult<PagedResult<BillingClientListDto>>> GetAll(
|
||||||
|
[FromQuery] string? tipo = "PF",
|
||||||
|
[FromQuery] string? search = null,
|
||||||
|
[FromQuery] string? client = null,
|
||||||
|
[FromQuery] int page = 1,
|
||||||
|
[FromQuery] int pageSize = 20,
|
||||||
|
[FromQuery] string? sortBy = "cliente",
|
||||||
|
[FromQuery] string? sortDir = "asc")
|
||||||
|
{
|
||||||
|
page = page < 1 ? 1 : page;
|
||||||
|
pageSize = pageSize < 1 ? 20 : pageSize;
|
||||||
|
|
||||||
|
// ✅ FIX CS8072: calcula FORA do expression tree (sem ?. dentro do Where)
|
||||||
|
var t = string.Equals(tipo?.Trim(), "PJ", StringComparison.OrdinalIgnoreCase) ? "PJ" : "PF";
|
||||||
|
|
||||||
|
var q = _db.BillingClients.AsNoTracking()
|
||||||
|
.Where(x => x.Tipo == t);
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(search))
|
||||||
|
{
|
||||||
|
var s = search.Trim();
|
||||||
|
q = q.Where(x => EF.Functions.ILike(x.Cliente ?? "", $"%{s}%"));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(client))
|
||||||
|
{
|
||||||
|
var c = client.Trim();
|
||||||
|
q = q.Where(x => EF.Functions.ILike(x.Cliente ?? "", c));
|
||||||
|
}
|
||||||
|
|
||||||
|
var total = await q.CountAsync();
|
||||||
|
|
||||||
|
var sb = (sortBy ?? "cliente").Trim().ToLowerInvariant();
|
||||||
|
var desc = string.Equals((sortDir ?? "asc").Trim(), "desc", StringComparison.OrdinalIgnoreCase);
|
||||||
|
|
||||||
|
// ✅ Ordenação mais estável (coalesce + ThenBy)
|
||||||
|
q = sb switch
|
||||||
|
{
|
||||||
|
"item" => desc ? q.OrderByDescending(x => x.Item) : q.OrderBy(x => x.Item),
|
||||||
|
|
||||||
|
"qtdlinhas" => desc
|
||||||
|
? q.OrderByDescending(x => x.QtdLinhas ?? 0).ThenBy(x => x.Cliente)
|
||||||
|
: q.OrderBy(x => x.QtdLinhas ?? 0).ThenBy(x => x.Cliente),
|
||||||
|
|
||||||
|
"lucro" => desc
|
||||||
|
? q.OrderByDescending(x => x.Lucro ?? 0).ThenBy(x => x.Cliente)
|
||||||
|
: q.OrderBy(x => x.Lucro ?? 0).ThenBy(x => x.Cliente),
|
||||||
|
|
||||||
|
"valorcontratovivo" => desc
|
||||||
|
? q.OrderByDescending(x => x.ValorContratoVivo ?? 0).ThenBy(x => x.Cliente)
|
||||||
|
: q.OrderBy(x => x.ValorContratoVivo ?? 0).ThenBy(x => x.Cliente),
|
||||||
|
|
||||||
|
"valorcontratoline" => desc
|
||||||
|
? q.OrderByDescending(x => x.ValorContratoLine ?? 0).ThenBy(x => x.Cliente)
|
||||||
|
: q.OrderBy(x => x.ValorContratoLine ?? 0).ThenBy(x => x.Cliente),
|
||||||
|
|
||||||
|
_ => desc
|
||||||
|
? q.OrderByDescending(x => x.Cliente).ThenBy(x => x.Item)
|
||||||
|
: q.OrderBy(x => x.Cliente).ThenBy(x => x.Item)
|
||||||
|
};
|
||||||
|
|
||||||
|
var items = await q
|
||||||
|
.Skip((page - 1) * pageSize)
|
||||||
|
.Take(pageSize)
|
||||||
|
.Select(x => new BillingClientListDto
|
||||||
|
{
|
||||||
|
Id = x.Id,
|
||||||
|
Tipo = x.Tipo,
|
||||||
|
Item = x.Item,
|
||||||
|
Cliente = x.Cliente,
|
||||||
|
QtdLinhas = x.QtdLinhas,
|
||||||
|
FranquiaVivo = x.FranquiaVivo,
|
||||||
|
ValorContratoVivo = x.ValorContratoVivo,
|
||||||
|
FranquiaLine = x.FranquiaLine,
|
||||||
|
ValorContratoLine = x.ValorContratoLine,
|
||||||
|
Lucro = x.Lucro,
|
||||||
|
Aparelho = x.Aparelho,
|
||||||
|
FormaPagamento = x.FormaPagamento
|
||||||
|
})
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
return Ok(new PagedResult<BillingClientListDto>
|
||||||
|
{
|
||||||
|
Page = page,
|
||||||
|
PageSize = pageSize,
|
||||||
|
Total = total,
|
||||||
|
Items = items
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("clients")]
|
||||||
|
public async Task<ActionResult<List<string>>> GetClients([FromQuery] string? tipo = "PF")
|
||||||
|
{
|
||||||
|
// ✅ FIX CS8072: calcula FORA do expression tree
|
||||||
|
var t = string.Equals(tipo?.Trim(), "PJ", StringComparison.OrdinalIgnoreCase) ? "PJ" : "PF";
|
||||||
|
|
||||||
|
var clients = await _db.BillingClients.AsNoTracking()
|
||||||
|
.Where(x => x.Tipo == t && !string.IsNullOrEmpty(x.Cliente))
|
||||||
|
.Select(x => x.Cliente!)
|
||||||
|
.Distinct()
|
||||||
|
.OrderBy(x => x)
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
return Ok(clients);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -88,15 +88,108 @@ namespace line_gestao_api.Controllers
|
||||||
}
|
}
|
||||||
|
|
||||||
// ==========================================================
|
// ==========================================================
|
||||||
// ✅ 2. ENDPOINT: LISTAR NOMES DE CLIENTES
|
// ✅ 2. ENDPOINT: LISTAR NOMES DE CLIENTES (CORRIGIDO PARA ACEITAR SKIL)
|
||||||
// ==========================================================
|
// ==========================================================
|
||||||
[HttpGet("clients")]
|
[HttpGet("clients")]
|
||||||
public async Task<ActionResult<List<string>>> GetClients()
|
public async Task<ActionResult<List<string>>> GetClients([FromQuery] string? skil)
|
||||||
{
|
{
|
||||||
var clients = await _db.MobileLines
|
var query = _db.MobileLines.AsNoTracking();
|
||||||
.AsNoTracking()
|
|
||||||
|
// APLICA O FILTRO DE SKIL ANTES DE SELECIONAR OS NOMES
|
||||||
|
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}%"));
|
||||||
|
}
|
||||||
|
|
||||||
|
var clients = await query
|
||||||
|
.Where(x => !string.IsNullOrEmpty(x.Cliente))
|
||||||
|
.Select(x => x.Cliente)
|
||||||
|
.Distinct()
|
||||||
|
.OrderBy(x => x)
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
return Ok(clients);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==========================================================
|
||||||
|
// ✅ NOVO: ENDPOINTS DO FATURAMENTO (PF/PJ)
|
||||||
|
// ==========================================================
|
||||||
|
[HttpGet("billing")]
|
||||||
|
public async Task<ActionResult<PagedResult<BillingClient>>> GetBilling(
|
||||||
|
[FromQuery] string? tipo, // "PF", "PJ" ou null (todos)
|
||||||
|
[FromQuery] string? search, // busca por cliente
|
||||||
|
[FromQuery] int page = 1,
|
||||||
|
[FromQuery] int pageSize = 20,
|
||||||
|
[FromQuery] string? sortBy = "cliente",
|
||||||
|
[FromQuery] string? sortDir = "asc")
|
||||||
|
{
|
||||||
|
page = page < 1 ? 1 : page;
|
||||||
|
pageSize = pageSize < 1 ? 20 : pageSize;
|
||||||
|
|
||||||
|
var q = _db.BillingClients.AsNoTracking();
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(tipo))
|
||||||
|
{
|
||||||
|
var t = tipo.Trim().ToUpperInvariant();
|
||||||
|
if (t == "PF" || t == "PJ") q = q.Where(x => x.Tipo == t);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(search))
|
||||||
|
{
|
||||||
|
var s = search.Trim();
|
||||||
|
q = q.Where(x => EF.Functions.ILike(x.Cliente ?? "", $"%{s}%"));
|
||||||
|
}
|
||||||
|
|
||||||
|
var total = await q.CountAsync();
|
||||||
|
|
||||||
|
var sb = (sortBy ?? "cliente").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),
|
||||||
|
"tipo" => desc ? q.OrderByDescending(x => x.Tipo).ThenBy(x => x.Cliente) : q.OrderBy(x => x.Tipo).ThenBy(x => x.Cliente),
|
||||||
|
"qtdlinhas" => desc ? q.OrderByDescending(x => x.QtdLinhas ?? 0).ThenBy(x => x.Cliente) : q.OrderBy(x => x.QtdLinhas ?? 0).ThenBy(x => x.Cliente),
|
||||||
|
"franquiavivo" => desc ? q.OrderByDescending(x => x.FranquiaVivo ?? 0).ThenBy(x => x.Cliente) : q.OrderBy(x => x.FranquiaVivo ?? 0).ThenBy(x => x.Cliente),
|
||||||
|
"valorcontratovivo" => desc ? q.OrderByDescending(x => x.ValorContratoVivo ?? 0).ThenBy(x => x.Cliente) : q.OrderBy(x => x.ValorContratoVivo ?? 0).ThenBy(x => x.Cliente),
|
||||||
|
"franquialine" => desc ? q.OrderByDescending(x => x.FranquiaLine ?? 0).ThenBy(x => x.Cliente) : q.OrderBy(x => x.FranquiaLine ?? 0).ThenBy(x => x.Cliente),
|
||||||
|
"valorcontratoline" => desc ? q.OrderByDescending(x => x.ValorContratoLine ?? 0).ThenBy(x => x.Cliente) : q.OrderBy(x => x.ValorContratoLine ?? 0).ThenBy(x => x.Cliente),
|
||||||
|
"lucro" => desc ? q.OrderByDescending(x => x.Lucro ?? 0).ThenBy(x => x.Cliente) : q.OrderBy(x => x.Lucro ?? 0).ThenBy(x => x.Cliente),
|
||||||
|
_ => desc ? q.OrderByDescending(x => x.Cliente).ThenBy(x => x.Item) : q.OrderBy(x => x.Cliente).ThenBy(x => x.Item),
|
||||||
|
};
|
||||||
|
|
||||||
|
var items = await q
|
||||||
|
.Skip((page - 1) * pageSize)
|
||||||
|
.Take(pageSize)
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
return Ok(new PagedResult<BillingClient>
|
||||||
|
{
|
||||||
|
Page = page,
|
||||||
|
PageSize = pageSize,
|
||||||
|
Total = total,
|
||||||
|
Items = items
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("billing/clients")]
|
||||||
|
public async Task<ActionResult<List<string>>> GetBillingClients([FromQuery] string? tipo)
|
||||||
|
{
|
||||||
|
var q = _db.BillingClients.AsNoTracking();
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(tipo))
|
||||||
|
{
|
||||||
|
var t = tipo.Trim().ToUpperInvariant();
|
||||||
|
if (t == "PF" || t == "PJ") q = q.Where(x => x.Tipo == t);
|
||||||
|
}
|
||||||
|
|
||||||
|
var clients = await q
|
||||||
|
.Where(x => !string.IsNullOrEmpty(x.Cliente))
|
||||||
.Select(x => x.Cliente)
|
.Select(x => x.Cliente)
|
||||||
.Where(x => !string.IsNullOrEmpty(x))
|
|
||||||
.Distinct()
|
.Distinct()
|
||||||
.OrderBy(x => x)
|
.OrderBy(x => x)
|
||||||
.ToListAsync();
|
.ToListAsync();
|
||||||
|
|
@ -217,35 +310,29 @@ namespace line_gestao_api.Controllers
|
||||||
[HttpPost]
|
[HttpPost]
|
||||||
public async Task<ActionResult<MobileLineDetailDto>> Create([FromBody] CreateMobileLineDto req)
|
public async Task<ActionResult<MobileLineDetailDto>> Create([FromBody] CreateMobileLineDto req)
|
||||||
{
|
{
|
||||||
// Validações Básicas
|
|
||||||
if (string.IsNullOrWhiteSpace(req.Cliente))
|
if (string.IsNullOrWhiteSpace(req.Cliente))
|
||||||
return BadRequest(new { message = "O nome do Cliente é obrigatório." });
|
return BadRequest(new { message = "O nome do Cliente é obrigatório." });
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(req.Linha))
|
if (string.IsNullOrWhiteSpace(req.Linha))
|
||||||
return BadRequest(new { message = "O número da Linha é obrigatório." });
|
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 linhaLimpa = OnlyDigits(req.Linha);
|
||||||
var chipLimpo = OnlyDigits(req.Chip);
|
var chipLimpo = OnlyDigits(req.Chip);
|
||||||
|
|
||||||
if (string.IsNullOrWhiteSpace(linhaLimpa))
|
if (string.IsNullOrWhiteSpace(linhaLimpa))
|
||||||
return BadRequest(new { message = "Número de linha inválido." });
|
return BadRequest(new { message = "Número de linha inválido." });
|
||||||
|
|
||||||
// Verifica Duplicidade
|
|
||||||
var exists = await _db.MobileLines.AsNoTracking().AnyAsync(x => x.Linha == linhaLimpa);
|
var exists = await _db.MobileLines.AsNoTracking().AnyAsync(x => x.Linha == linhaLimpa);
|
||||||
if (exists)
|
if (exists)
|
||||||
return Conflict(new { message = $"A linha {req.Linha} já está cadastrada no sistema." });
|
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 maxItem = await _db.MobileLines.MaxAsync(x => (int?)x.Item) ?? 0;
|
||||||
var nextItem = maxItem + 1;
|
var nextItem = maxItem + 1;
|
||||||
|
|
||||||
// Mapeamento DTO -> Entity
|
|
||||||
var newLine = new MobileLine
|
var newLine = new MobileLine
|
||||||
{
|
{
|
||||||
Id = Guid.NewGuid(),
|
Id = Guid.NewGuid(),
|
||||||
Item = nextItem, // Define o Item calculado automaticamente
|
Item = nextItem,
|
||||||
Cliente = req.Cliente.Trim().ToUpper(),
|
Cliente = req.Cliente.Trim().ToUpper(),
|
||||||
Linha = linhaLimpa,
|
Linha = linhaLimpa,
|
||||||
Chip = chipLimpo,
|
Chip = chipLimpo,
|
||||||
|
|
@ -257,16 +344,13 @@ namespace line_gestao_api.Controllers
|
||||||
Conta = req.Conta?.Trim(),
|
Conta = req.Conta?.Trim(),
|
||||||
VencConta = req.VencConta?.Trim(),
|
VencConta = req.VencConta?.Trim(),
|
||||||
|
|
||||||
// Datas
|
|
||||||
DataBloqueio = ToUtc(req.DataBloqueio),
|
DataBloqueio = ToUtc(req.DataBloqueio),
|
||||||
DataEntregaOpera = ToUtc(req.DataEntregaOpera),
|
DataEntregaOpera = ToUtc(req.DataEntregaOpera),
|
||||||
DataEntregaCliente = ToUtc(req.DataEntregaCliente),
|
DataEntregaCliente = ToUtc(req.DataEntregaCliente),
|
||||||
|
|
||||||
// Logística
|
|
||||||
Cedente = req.Cedente?.Trim(),
|
Cedente = req.Cedente?.Trim(),
|
||||||
Solicitante = req.Solicitante?.Trim(),
|
Solicitante = req.Solicitante?.Trim(),
|
||||||
|
|
||||||
// Financeiro
|
|
||||||
FranquiaVivo = req.FranquiaVivo,
|
FranquiaVivo = req.FranquiaVivo,
|
||||||
ValorPlanoVivo = req.ValorPlanoVivo,
|
ValorPlanoVivo = req.ValorPlanoVivo,
|
||||||
GestaoVozDados = req.GestaoVozDados,
|
GestaoVozDados = req.GestaoVozDados,
|
||||||
|
|
@ -286,7 +370,6 @@ namespace line_gestao_api.Controllers
|
||||||
UpdatedAt = DateTime.UtcNow
|
UpdatedAt = DateTime.UtcNow
|
||||||
};
|
};
|
||||||
|
|
||||||
// Aplica regra de negócio para Reserva (se necessário)
|
|
||||||
ApplyReservaRule(newLine);
|
ApplyReservaRule(newLine);
|
||||||
|
|
||||||
_db.MobileLines.Add(newLine);
|
_db.MobileLines.Add(newLine);
|
||||||
|
|
@ -300,7 +383,6 @@ namespace line_gestao_api.Controllers
|
||||||
return StatusCode(500, new { message = "Erro ao salvar no banco de dados." });
|
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));
|
return CreatedAtAction(nameof(GetById), new { id = newLine.Id }, ToDetailDto(newLine));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -320,9 +402,6 @@ namespace line_gestao_api.Controllers
|
||||||
if (exists) return Conflict(new { message = "Já existe registro com essa LINHA.", linha = newLinha });
|
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.Conta = req.Conta?.Trim();
|
||||||
x.Linha = newLinha;
|
x.Linha = newLinha;
|
||||||
x.Chip = OnlyDigits(req.Chip);
|
x.Chip = OnlyDigits(req.Chip);
|
||||||
|
|
@ -376,30 +455,56 @@ namespace line_gestao_api.Controllers
|
||||||
}
|
}
|
||||||
|
|
||||||
// ==========================================================
|
// ==========================================================
|
||||||
// ✅ 8. IMPORT EXCEL
|
// ✅ 8. IMPORT EXCEL (GERAL + MUREG + FATURAMENTO PF/PJ no mesmo upload)
|
||||||
// ==========================================================
|
// ==========================================================
|
||||||
[HttpPost("import-excel")]
|
[HttpPost("import-excel")]
|
||||||
[Consumes("multipart/form-data")]
|
[Consumes("multipart/form-data")]
|
||||||
[RequestSizeLimit(50_000_000)]
|
[RequestSizeLimit(50_000_000)]
|
||||||
public async Task<ActionResult<ImportResultDto>> ImportExcel([FromForm] ImportExcelForm form)
|
public async Task<ActionResult<ImportResultDto>> ImportExcel([FromForm] ImportExcelForm form)
|
||||||
{
|
{
|
||||||
var file = form.File; if (file == null || file.Length == 0) return BadRequest("Arquivo inválido.");
|
var file = form.File;
|
||||||
using var stream = file.OpenReadStream(); using var wb = new XLWorkbook(stream);
|
if (file == null || file.Length == 0) return BadRequest("Arquivo inválido.");
|
||||||
|
|
||||||
|
using var stream = file.OpenReadStream();
|
||||||
|
using var wb = new XLWorkbook(stream);
|
||||||
|
|
||||||
|
// =========================
|
||||||
|
// ✅ IMPORTA GERAL (igual)
|
||||||
|
// =========================
|
||||||
var ws = wb.Worksheets.FirstOrDefault(w => w.Name.Trim().Equals("GERAL", StringComparison.OrdinalIgnoreCase));
|
var ws = wb.Worksheets.FirstOrDefault(w => w.Name.Trim().Equals("GERAL", StringComparison.OrdinalIgnoreCase));
|
||||||
if (ws == null) return BadRequest("Aba 'GERAL' não encontrada.");
|
if (ws == null) return BadRequest("Aba 'GERAL' não encontrada.");
|
||||||
|
|
||||||
var headerRow = ws.RowsUsed().FirstOrDefault(r => r.CellsUsed().Any(c => NormalizeHeader(c.GetString()) == "ITEM"));
|
var headerRow = ws.RowsUsed().FirstOrDefault(r => r.CellsUsed().Any(c => NormalizeHeader(c.GetString()) == "ITEM"));
|
||||||
if (headerRow == null) return BadRequest("Cabeçalho 'ITEM' não encontrado.");
|
if (headerRow == null) return BadRequest("Cabeçalho 'ITEM' não encontrado.");
|
||||||
|
|
||||||
var map = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
|
var map = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
|
||||||
foreach (var cell in headerRow.CellsUsed()) { var k = NormalizeHeader(cell.GetString()); if (!string.IsNullOrWhiteSpace(k) && !map.ContainsKey(k)) map[k] = cell.Address.ColumnNumber; }
|
foreach (var cell in headerRow.CellsUsed())
|
||||||
int colItem = GetCol(map, "ITEM"); if (colItem == 0) return BadRequest("Coluna 'ITEM' não encontrada.");
|
|
||||||
var startRow = headerRow.RowNumber() + 1;
|
|
||||||
await _db.MobileLines.ExecuteDeleteAsync();
|
|
||||||
var buffer = new List<MobileLine>(600); var imported = 0;
|
|
||||||
for (int r = startRow; r <= ws.LastRowUsed().RowNumber(); r++)
|
|
||||||
{
|
{
|
||||||
var itemStr = GetCellString(ws, r, colItem); if (string.IsNullOrWhiteSpace(itemStr)) break;
|
var k = NormalizeHeader(cell.GetString());
|
||||||
|
if (!string.IsNullOrWhiteSpace(k) && !map.ContainsKey(k)) map[k] = cell.Address.ColumnNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
int colItem = GetCol(map, "ITEM");
|
||||||
|
if (colItem == 0) return BadRequest("Coluna 'ITEM' não encontrada.");
|
||||||
|
|
||||||
|
var startRow = headerRow.RowNumber() + 1;
|
||||||
|
|
||||||
|
await _db.MobileLines.ExecuteDeleteAsync();
|
||||||
|
|
||||||
|
var buffer = new List<MobileLine>(600);
|
||||||
|
var imported = 0;
|
||||||
|
|
||||||
|
// ✅ FIX: ws.LastRowUsed() pode ser null
|
||||||
|
var lastRow = ws.LastRowUsed()?.RowNumber() ?? startRow;
|
||||||
|
|
||||||
|
for (int r = startRow; r <= lastRow; r++)
|
||||||
|
{
|
||||||
|
var itemStr = GetCellString(ws, r, colItem);
|
||||||
|
if (string.IsNullOrWhiteSpace(itemStr)) break;
|
||||||
|
|
||||||
var e = new MobileLine
|
var e = new MobileLine
|
||||||
{
|
{
|
||||||
|
Id = Guid.NewGuid(), // ✅ recomendado
|
||||||
Item = TryInt(itemStr),
|
Item = TryInt(itemStr),
|
||||||
Conta = GetCellByHeader(ws, r, map, "CONTA"),
|
Conta = GetCellByHeader(ws, r, map, "CONTA"),
|
||||||
Linha = OnlyDigits(GetCellByHeader(ws, r, map, "LINHA")),
|
Linha = OnlyDigits(GetCellByHeader(ws, r, map, "LINHA")),
|
||||||
|
|
@ -429,19 +534,232 @@ namespace line_gestao_api.Controllers
|
||||||
Solicitante = GetCellByHeader(ws, r, map, "SOLICITANTE"),
|
Solicitante = GetCellByHeader(ws, r, map, "SOLICITANTE"),
|
||||||
DataEntregaOpera = TryDate(ws, r, map, "DATA DA ENTREGA OPERA."),
|
DataEntregaOpera = TryDate(ws, r, map, "DATA DA ENTREGA OPERA."),
|
||||||
DataEntregaCliente = TryDate(ws, r, map, "DATA DA ENTREGA CLIENTE"),
|
DataEntregaCliente = TryDate(ws, r, map, "DATA DA ENTREGA CLIENTE"),
|
||||||
VencConta = GetCellByHeader(ws, r, map, "VENC. DA CONTA")
|
VencConta = GetCellByHeader(ws, r, map, "VENC. DA CONTA"),
|
||||||
|
CreatedAt = DateTime.UtcNow,
|
||||||
|
UpdatedAt = DateTime.UtcNow
|
||||||
};
|
};
|
||||||
ApplyReservaRule(e); buffer.Add(e); imported++;
|
|
||||||
if (buffer.Count >= 500) { await _db.MobileLines.AddRangeAsync(buffer); await _db.SaveChangesAsync(); buffer.Clear(); }
|
ApplyReservaRule(e);
|
||||||
|
|
||||||
|
buffer.Add(e);
|
||||||
|
imported++;
|
||||||
|
|
||||||
|
if (buffer.Count >= 500)
|
||||||
|
{
|
||||||
|
await _db.MobileLines.AddRangeAsync(buffer);
|
||||||
|
await _db.SaveChangesAsync();
|
||||||
|
buffer.Clear();
|
||||||
}
|
}
|
||||||
if (buffer.Count > 0) { await _db.MobileLines.AddRangeAsync(buffer); await _db.SaveChangesAsync(); }
|
}
|
||||||
|
|
||||||
|
if (buffer.Count > 0)
|
||||||
|
{
|
||||||
|
await _db.MobileLines.AddRangeAsync(buffer);
|
||||||
|
await _db.SaveChangesAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
// =========================
|
||||||
|
// ✅ IMPORTA MUREG (igual ao seu)
|
||||||
|
// =========================
|
||||||
|
await ImportMuregFromWorkbook(wb);
|
||||||
|
|
||||||
|
// =========================
|
||||||
|
// ✅ NOVO: IMPORTA FATURAMENTO PF/PJ
|
||||||
|
// =========================
|
||||||
|
await ImportBillingFromWorkbook(wb);
|
||||||
|
|
||||||
return Ok(new ImportResultDto { Imported = imported });
|
return Ok(new ImportResultDto { Imported = imported });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ==========================================================
|
||||||
|
// ✅ IMPORTAÇÃO DA ABA MUREG (mesmo upload)
|
||||||
|
// ==========================================================
|
||||||
|
private async Task ImportMuregFromWorkbook(XLWorkbook wb)
|
||||||
|
{
|
||||||
|
var wsM = wb.Worksheets.FirstOrDefault(w => w.Name.Trim().Equals("MUREG", StringComparison.OrdinalIgnoreCase))
|
||||||
|
?? wb.Worksheets.FirstOrDefault(w => w.Name.Trim().ToUpperInvariant().Contains("MUREG"));
|
||||||
|
|
||||||
|
if (wsM == null) return;
|
||||||
|
|
||||||
|
var headerRow = wsM.RowsUsed().FirstOrDefault(r => r.CellsUsed().Any(c => NormalizeHeader(c.GetString()) == "ITEM"));
|
||||||
|
if (headerRow == null) return;
|
||||||
|
|
||||||
|
var map = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
foreach (var cell in headerRow.CellsUsed())
|
||||||
|
{
|
||||||
|
var k = NormalizeHeader(cell.GetString());
|
||||||
|
if (!string.IsNullOrWhiteSpace(k) && !map.ContainsKey(k)) map[k] = cell.Address.ColumnNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
int colItem = GetCol(map, "ITEM");
|
||||||
|
if (colItem == 0) return;
|
||||||
|
|
||||||
|
var startRow = headerRow.RowNumber() + 1;
|
||||||
|
|
||||||
|
await _db.MuregLines.ExecuteDeleteAsync();
|
||||||
|
|
||||||
|
var buffer = new List<MuregLine>(600);
|
||||||
|
|
||||||
|
var lastRow = wsM.LastRowUsed()?.RowNumber() ?? startRow;
|
||||||
|
for (int r = startRow; r <= lastRow; r++)
|
||||||
|
{
|
||||||
|
var itemStr = GetCellString(wsM, r, colItem);
|
||||||
|
if (string.IsNullOrWhiteSpace(itemStr)) break;
|
||||||
|
|
||||||
|
var e = new MuregLine
|
||||||
|
{
|
||||||
|
Id = Guid.NewGuid(),
|
||||||
|
Item = TryInt(itemStr),
|
||||||
|
|
||||||
|
LinhaAntiga = OnlyDigits(GetCellByHeader(wsM, r, map, "LINHA ANTIGA")),
|
||||||
|
LinhaNova = OnlyDigits(GetCellByHeader(wsM, r, map, "LINHA NOVA")),
|
||||||
|
ICCID = OnlyDigits(GetCellByHeader(wsM, r, map, "ICCID")),
|
||||||
|
DataDaMureg = TryDate(wsM, r, map, "DATA DA MUREG"),
|
||||||
|
Cliente = GetCellByHeader(wsM, r, map, "CLIENTE"),
|
||||||
|
};
|
||||||
|
|
||||||
|
buffer.Add(e);
|
||||||
|
|
||||||
|
if (buffer.Count >= 500)
|
||||||
|
{
|
||||||
|
await _db.MuregLines.AddRangeAsync(buffer);
|
||||||
|
await _db.SaveChangesAsync();
|
||||||
|
buffer.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buffer.Count > 0)
|
||||||
|
{
|
||||||
|
await _db.MuregLines.AddRangeAsync(buffer);
|
||||||
|
await _db.SaveChangesAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==========================================================
|
||||||
|
// ✅ NOVO: IMPORTAÇÃO DO FATURAMENTO (PF/PJ)
|
||||||
|
// Tabs: "FATURAMENTO PF" e "FATURAMENTO PJ"
|
||||||
|
// ==========================================================
|
||||||
|
private async Task ImportBillingFromWorkbook(XLWorkbook wb)
|
||||||
|
{
|
||||||
|
await _db.BillingClients.ExecuteDeleteAsync();
|
||||||
|
|
||||||
|
// PF
|
||||||
|
var wsPf = wb.Worksheets.FirstOrDefault(w => w.Name.Trim().Equals("FATURAMENTO PF", StringComparison.OrdinalIgnoreCase))
|
||||||
|
?? wb.Worksheets.FirstOrDefault(w => w.Name.Trim().ToUpperInvariant().Contains("FATURAMENTO") && w.Name.Trim().ToUpperInvariant().Contains("PF"));
|
||||||
|
if (wsPf != null)
|
||||||
|
await ImportBillingSheet(wsPf, "PF");
|
||||||
|
|
||||||
|
// PJ
|
||||||
|
var wsPj = wb.Worksheets.FirstOrDefault(w => w.Name.Trim().Equals("FATURAMENTO PJ", StringComparison.OrdinalIgnoreCase))
|
||||||
|
?? wb.Worksheets.FirstOrDefault(w => w.Name.Trim().ToUpperInvariant().Contains("FATURAMENTO") && w.Name.Trim().ToUpperInvariant().Contains("PJ"));
|
||||||
|
if (wsPj != null)
|
||||||
|
await ImportBillingSheet(wsPj, "PJ");
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task ImportBillingSheet(IXLWorksheet ws, string tipo)
|
||||||
|
{
|
||||||
|
var headerRow =
|
||||||
|
ws.RowsUsed().FirstOrDefault(r =>
|
||||||
|
r.CellsUsed().Any(c => NormalizeHeader(c.GetString()) == "CLIENTE"));
|
||||||
|
|
||||||
|
if (headerRow == null) return;
|
||||||
|
|
||||||
|
var map = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);
|
||||||
|
foreach (var cell in headerRow.CellsUsed())
|
||||||
|
{
|
||||||
|
var k = NormalizeHeader(cell.GetString());
|
||||||
|
if (!string.IsNullOrWhiteSpace(k) && !map.ContainsKey(k))
|
||||||
|
map[k] = cell.Address.ColumnNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
var colCliente = GetCol(map, "CLIENTE");
|
||||||
|
if (colCliente == 0) return;
|
||||||
|
|
||||||
|
var colItem = GetCol(map, "ITEM");
|
||||||
|
if (colItem == 0 && colCliente > 1) colItem = colCliente - 1;
|
||||||
|
|
||||||
|
var startRow = headerRow.RowNumber() + 1;
|
||||||
|
var lastRow = ws.LastRowUsed()?.RowNumber() ?? startRow;
|
||||||
|
|
||||||
|
var buffer = new List<BillingClient>(400);
|
||||||
|
var seqItem = 0;
|
||||||
|
|
||||||
|
for (int r = startRow; r <= lastRow; r++)
|
||||||
|
{
|
||||||
|
var cliente = GetCellString(ws, r, colCliente);
|
||||||
|
if (string.IsNullOrWhiteSpace(cliente)) break;
|
||||||
|
|
||||||
|
seqItem++;
|
||||||
|
|
||||||
|
var itemStr = colItem > 0 ? GetCellString(ws, r, colItem) : "";
|
||||||
|
var item = !string.IsNullOrWhiteSpace(itemStr) ? TryInt(itemStr) : seqItem;
|
||||||
|
|
||||||
|
var qtdStr = GetCellByAnyHeader(ws, r, map, "QTD DE LINHAS", "QTDDLINHAS", "QTD LINHAS");
|
||||||
|
var qtd = TryNullableInt(qtdStr);
|
||||||
|
|
||||||
|
var franquiaVivoStr = GetCellByAnyHeader(ws, r, map, "FRAQUIA VIVO", "FRANQUIA VIVO");
|
||||||
|
var valorContratoVivoStr = GetCellByAnyHeader(ws, r, map, "VALOR CONTRATO VIVO", "VALOR DO CONTRATO VIVO", "VALOR CONTRATO VIVO R$");
|
||||||
|
|
||||||
|
var franquiaLineStr = GetCellByAnyHeader(ws, r, map, "FRAQUIA LINE", "FRANQUIA LINE");
|
||||||
|
var valorContratoLineStr = GetCellByAnyHeader(ws, r, map, "VALOR CONTRATO LINE", "VALOR DO CONTRATO LINE", "VALOR CONTRATO LINE R$");
|
||||||
|
|
||||||
|
var lucroStr = GetCellByAnyHeader(ws, r, map, "LUCRO");
|
||||||
|
|
||||||
|
var aparelho = GetCellByAnyHeader(ws, r, map, "APARELHO");
|
||||||
|
var formaPagto = GetCellByAnyHeader(ws, r, map, "FORMA DE PAGAMENTO", "FORMA PAGAMENTO", "FORMAPAGAMENTO");
|
||||||
|
|
||||||
|
var now = DateTime.UtcNow;
|
||||||
|
|
||||||
|
var e = new BillingClient
|
||||||
|
{
|
||||||
|
Id = Guid.NewGuid(),
|
||||||
|
Tipo = tipo,
|
||||||
|
Item = item,
|
||||||
|
Cliente = cliente.Trim(),
|
||||||
|
QtdLinhas = qtd,
|
||||||
|
|
||||||
|
FranquiaVivo = TryDecimal(franquiaVivoStr),
|
||||||
|
ValorContratoVivo = TryDecimal(valorContratoVivoStr),
|
||||||
|
|
||||||
|
FranquiaLine = TryDecimal(franquiaLineStr),
|
||||||
|
ValorContratoLine = TryDecimal(valorContratoLineStr),
|
||||||
|
|
||||||
|
Lucro = TryDecimal(lucroStr),
|
||||||
|
|
||||||
|
Aparelho = string.IsNullOrWhiteSpace(aparelho) ? null : aparelho.Trim(),
|
||||||
|
FormaPagamento = string.IsNullOrWhiteSpace(formaPagto) ? null : formaPagto.Trim(),
|
||||||
|
|
||||||
|
CreatedAt = now,
|
||||||
|
UpdatedAt = now
|
||||||
|
};
|
||||||
|
|
||||||
|
buffer.Add(e);
|
||||||
|
|
||||||
|
if (buffer.Count >= 300)
|
||||||
|
{
|
||||||
|
await _db.BillingClients.AddRangeAsync(buffer);
|
||||||
|
await _db.SaveChangesAsync();
|
||||||
|
buffer.Clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buffer.Count > 0)
|
||||||
|
{
|
||||||
|
await _db.BillingClients.AddRangeAsync(buffer);
|
||||||
|
await _db.SaveChangesAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ==========================================================
|
// ==========================================================
|
||||||
// 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 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()
|
private static MobileLineDetailDto ToDetailDto(MobileLine x) => new()
|
||||||
{
|
{
|
||||||
|
|
@ -488,13 +806,97 @@ namespace line_gestao_api.Controllers
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int GetCol(Dictionary<string, int> map, string name) => map.TryGetValue(NormalizeHeader(name), out var c) ? c : 0;
|
private static int GetCol(Dictionary<string, int> map, string name)
|
||||||
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) : ""; }
|
=> map.TryGetValue(NormalizeHeader(name), out var c) ? c : 0;
|
||||||
private static string GetCellString(IXLWorksheet ws, int row, int col) { var c = ws.Cell(row, col); return c == null ? "" : (c.GetValue<string>() ?? "").Trim(); }
|
|
||||||
private static DateTime? TryDate(IXLWorksheet ws, int row, Dictionary<string, int> map, string header) { var k = NormalizeHeader(header); if (!map.TryGetValue(k, out var c)) return null; var cell = ws.Cell(row, c); if (cell.DataType == XLDataType.DateTime) return ToUtc(cell.GetDateTime()); var s = cell.GetValue<string>()?.Trim(); if (string.IsNullOrWhiteSpace(s)) return null; if (DateTime.TryParse(s, new CultureInfo("pt-BR"), DateTimeStyles.None, out var d)) return ToUtc(d); return null; }
|
private static string GetCellByHeader(IXLWorksheet ws, int row, Dictionary<string, int> map, string header)
|
||||||
private static decimal? TryDecimal(string? s) { if (string.IsNullOrWhiteSpace(s)) return null; s = s.Replace("R$", "").Trim(); if (decimal.TryParse(s, NumberStyles.Any, new CultureInfo("pt-BR"), out var d)) return d; if (decimal.TryParse(s, NumberStyles.Any, CultureInfo.InvariantCulture, out d)) return d; return null; }
|
{
|
||||||
private static int TryInt(string s) => int.TryParse(OnlyDigits(s), out var n) ? n : 0;
|
var k = NormalizeHeader(header);
|
||||||
private static string OnlyDigits(string? s) { if (string.IsNullOrWhiteSpace(s)) return ""; var sb = new StringBuilder(); foreach (var c in s) if (char.IsDigit(c)) sb.Append(c); return sb.ToString(); }
|
return map.TryGetValue(k, out var c) ? GetCellString(ws, row, c) : "";
|
||||||
private static string NormalizeHeader(string? s) { if (string.IsNullOrWhiteSpace(s)) return ""; s = s.Trim().ToUpperInvariant().Normalize(NormalizationForm.FormD); var sb = new StringBuilder(); foreach (var c in s) if (CharUnicodeInfo.GetUnicodeCategory(c) != UnicodeCategory.NonSpacingMark) sb.Append(c); return sb.ToString().Normalize(NormalizationForm.FormC).Replace("ITEM", "ITEM").Replace("USUARIO", "USUARIO").Replace("GESTAO", "GESTAO").Replace("LOCACAO", "LOCACAO").Replace(" ", ""); }
|
}
|
||||||
|
|
||||||
|
private static string GetCellByAnyHeader(IXLWorksheet ws, int row, Dictionary<string, int> map, params string[] headers)
|
||||||
|
{
|
||||||
|
foreach (var h in headers)
|
||||||
|
{
|
||||||
|
var k = NormalizeHeader(h);
|
||||||
|
if (map.TryGetValue(k, out var c))
|
||||||
|
return GetCellString(ws, row, c);
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetCellString(IXLWorksheet ws, int row, int col)
|
||||||
|
{
|
||||||
|
return (ws.Cell(row, col).GetValue<string>() ?? "").Trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static DateTime? TryDate(IXLWorksheet ws, int row, Dictionary<string, int> map, string header)
|
||||||
|
{
|
||||||
|
var k = NormalizeHeader(header);
|
||||||
|
if (!map.TryGetValue(k, out var c)) return null;
|
||||||
|
|
||||||
|
var cell = ws.Cell(row, c);
|
||||||
|
|
||||||
|
if (cell.DataType == XLDataType.DateTime)
|
||||||
|
return ToUtc(cell.GetDateTime());
|
||||||
|
|
||||||
|
var s = cell.GetValue<string>()?.Trim();
|
||||||
|
if (string.IsNullOrWhiteSpace(s)) return null;
|
||||||
|
|
||||||
|
if (DateTime.TryParse(s, new CultureInfo("pt-BR"), DateTimeStyles.None, out var d))
|
||||||
|
return ToUtc(d);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static decimal? TryDecimal(string? s)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(s)) return null;
|
||||||
|
s = s.Replace("R$", "").Trim();
|
||||||
|
|
||||||
|
if (decimal.TryParse(s, NumberStyles.Any, new CultureInfo("pt-BR"), out var d)) return d;
|
||||||
|
if (decimal.TryParse(s, NumberStyles.Any, CultureInfo.InvariantCulture, out d)) return d;
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int TryInt(string s)
|
||||||
|
=> int.TryParse(OnlyDigits(s), out var n) ? n : 0;
|
||||||
|
|
||||||
|
private static int? TryNullableInt(string? s)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(s)) return null;
|
||||||
|
var d = OnlyDigits(s);
|
||||||
|
if (string.IsNullOrWhiteSpace(d)) return null;
|
||||||
|
return int.TryParse(d, out var n) ? n : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string OnlyDigits(string? s)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(s)) return "";
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
foreach (var c in s) if (char.IsDigit(c)) sb.Append(c);
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string NormalizeHeader(string? s)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(s)) return "";
|
||||||
|
s = s.Trim().ToUpperInvariant().Normalize(NormalizationForm.FormD);
|
||||||
|
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
foreach (var c in s)
|
||||||
|
if (CharUnicodeInfo.GetUnicodeCategory(c) != UnicodeCategory.NonSpacingMark)
|
||||||
|
sb.Append(c);
|
||||||
|
|
||||||
|
return sb.ToString()
|
||||||
|
.Normalize(NormalizationForm.FormC)
|
||||||
|
.Replace("ITEM", "ITEM")
|
||||||
|
.Replace("USUARIO", "USUARIO")
|
||||||
|
.Replace("GESTAO", "GESTAO")
|
||||||
|
.Replace("LOCACAO", "LOCACAO")
|
||||||
|
.Replace(" ", "");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,106 @@
|
||||||
|
using line_gestao_api.Data;
|
||||||
|
using line_gestao_api.Dtos;
|
||||||
|
using line_gestao_api.Models;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
|
||||||
|
namespace line_gestao_api.Controllers
|
||||||
|
{
|
||||||
|
[ApiController]
|
||||||
|
[Route("api/mureg")]
|
||||||
|
public class MuregController : ControllerBase
|
||||||
|
{
|
||||||
|
private readonly AppDbContext _db;
|
||||||
|
|
||||||
|
public MuregController(AppDbContext db)
|
||||||
|
{
|
||||||
|
_db = db;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ImportExcelForm
|
||||||
|
{
|
||||||
|
public IFormFile File { get; set; } = default!;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==========================================================
|
||||||
|
// ✅ GET: /api/mureg (com paginação, busca e ordenação)
|
||||||
|
// ==========================================================
|
||||||
|
[HttpGet]
|
||||||
|
public async Task<ActionResult<PagedResult<MuregListDto>>> GetAll(
|
||||||
|
[FromQuery] string? search,
|
||||||
|
[FromQuery] int page = 1,
|
||||||
|
[FromQuery] int pageSize = 10,
|
||||||
|
[FromQuery] string? sortBy = "item",
|
||||||
|
[FromQuery] string? sortDir = "asc")
|
||||||
|
{
|
||||||
|
page = page < 1 ? 1 : page;
|
||||||
|
pageSize = pageSize < 1 ? 10 : pageSize;
|
||||||
|
|
||||||
|
var q = _db.MuregLines.AsNoTracking();
|
||||||
|
|
||||||
|
if (!string.IsNullOrWhiteSpace(search))
|
||||||
|
{
|
||||||
|
var s = search.Trim();
|
||||||
|
q = q.Where(x =>
|
||||||
|
EF.Functions.ILike((x.LinhaAntiga ?? ""), $"%{s}%") ||
|
||||||
|
EF.Functions.ILike((x.LinhaNova ?? ""), $"%{s}%") ||
|
||||||
|
EF.Functions.ILike((x.ICCID ?? ""), $"%{s}%") ||
|
||||||
|
EF.Functions.ILike((x.Cliente ?? ""), $"%{s}%") ||
|
||||||
|
EF.Functions.ILike(x.Item.ToString(), $"%{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),
|
||||||
|
"linhaantiga" => desc ? q.OrderByDescending(x => x.LinhaAntiga ?? "").ThenBy(x => x.Item) : q.OrderBy(x => x.LinhaAntiga ?? "").ThenBy(x => x.Item),
|
||||||
|
"linhanova" => desc ? q.OrderByDescending(x => x.LinhaNova ?? "").ThenBy(x => x.Item) : q.OrderBy(x => x.LinhaNova ?? "").ThenBy(x => x.Item),
|
||||||
|
"iccid" => desc ? q.OrderByDescending(x => x.ICCID ?? "").ThenBy(x => x.Item) : q.OrderBy(x => x.ICCID ?? "").ThenBy(x => x.Item),
|
||||||
|
"datadamureg" => desc ? q.OrderByDescending(x => x.DataDaMureg).ThenBy(x => x.Item) : q.OrderBy(x => x.DataDaMureg).ThenBy(x => x.Item),
|
||||||
|
"cliente" => desc ? q.OrderByDescending(x => x.Cliente ?? "").ThenBy(x => x.Item) : q.OrderBy(x => x.Cliente ?? "").ThenBy(x => x.Item),
|
||||||
|
_ => desc ? q.OrderByDescending(x => x.Item) : q.OrderBy(x => x.Item)
|
||||||
|
};
|
||||||
|
|
||||||
|
var items = await q
|
||||||
|
.Skip((page - 1) * pageSize)
|
||||||
|
.Take(pageSize)
|
||||||
|
.Select(x => new MuregListDto
|
||||||
|
{
|
||||||
|
Id = x.Id,
|
||||||
|
Item = x.Item,
|
||||||
|
LinhaAntiga = x.LinhaAntiga,
|
||||||
|
LinhaNova = x.LinhaNova,
|
||||||
|
ICCID = x.ICCID,
|
||||||
|
DataDaMureg = x.DataDaMureg,
|
||||||
|
Cliente = x.Cliente
|
||||||
|
})
|
||||||
|
.ToListAsync();
|
||||||
|
|
||||||
|
return Ok(new PagedResult<MuregListDto>
|
||||||
|
{
|
||||||
|
Page = page,
|
||||||
|
PageSize = pageSize,
|
||||||
|
Total = total,
|
||||||
|
Items = items
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==========================================================
|
||||||
|
// ✅ POST: /api/mureg/import-excel (opcional)
|
||||||
|
// Se você usar o botão "Importar" da tela MUREG, ele vai bater aqui
|
||||||
|
// ==========================================================
|
||||||
|
[HttpPost("import-excel")]
|
||||||
|
[Consumes("multipart/form-data")]
|
||||||
|
[RequestSizeLimit(50_000_000)]
|
||||||
|
public async Task<IActionResult> ImportExcel([FromForm] ImportExcelForm form)
|
||||||
|
{
|
||||||
|
// Se você quiser manter "importa só no GERAL", pode remover este endpoint.
|
||||||
|
// Eu deixei para não quebrar o botão do seu front (que chama /api/mureg/import-excel).
|
||||||
|
return BadRequest(new { message = "Importe a planilha pela página GERAL. O MUREG será carregado automaticamente." });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -9,21 +9,55 @@ public class AppDbContext : DbContext
|
||||||
|
|
||||||
public DbSet<User> Users => Set<User>();
|
public DbSet<User> Users => Set<User>();
|
||||||
|
|
||||||
// ✅ NOVO: tabela para espelhar a planilha (GERAL)
|
// ✅ tabela para espelhar a planilha (GERAL)
|
||||||
public DbSet<MobileLine> MobileLines => Set<MobileLine>();
|
public DbSet<MobileLine> MobileLines => Set<MobileLine>();
|
||||||
|
|
||||||
|
// ✅ tabela para espelhar a aba MUREG
|
||||||
|
public DbSet<MuregLine> MuregLines => Set<MuregLine>();
|
||||||
|
|
||||||
|
// ✅ tabela para espelhar o FATURAMENTO (PF/PJ)
|
||||||
|
public DbSet<BillingClient> BillingClients => Set<BillingClient>();
|
||||||
|
|
||||||
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
protected override void OnModelCreating(ModelBuilder modelBuilder)
|
||||||
{
|
{
|
||||||
base.OnModelCreating(modelBuilder);
|
base.OnModelCreating(modelBuilder);
|
||||||
|
|
||||||
// ✅ MANTIDO: índice único do User (não mexi em nada aqui)
|
// ✅ MANTIDO: índice único do User
|
||||||
modelBuilder.Entity<User>()
|
modelBuilder.Entity<User>()
|
||||||
.HasIndex(u => u.Email)
|
.HasIndex(u => u.Email)
|
||||||
.IsUnique();
|
.IsUnique();
|
||||||
|
|
||||||
// ✅ NOVO: índice único para evitar duplicar a mesma linha (telefone)
|
// ✅ MANTIDO: índice único para evitar duplicar a mesma linha (telefone)
|
||||||
modelBuilder.Entity<MobileLine>()
|
modelBuilder.Entity<MobileLine>()
|
||||||
.HasIndex(x => x.Linha)
|
.HasIndex(x => x.Linha)
|
||||||
.IsUnique();
|
.IsUnique();
|
||||||
|
|
||||||
|
// ✅ MANTIDO: índices do MUREG
|
||||||
|
modelBuilder.Entity<MuregLine>().HasIndex(x => x.Item);
|
||||||
|
modelBuilder.Entity<MuregLine>().HasIndex(x => x.Cliente);
|
||||||
|
modelBuilder.Entity<MuregLine>().HasIndex(x => x.ICCID);
|
||||||
|
modelBuilder.Entity<MuregLine>().HasIndex(x => x.LinhaNova);
|
||||||
|
|
||||||
|
// ==========================================================
|
||||||
|
// ✅ NOVO: MAPEAMENTO DO FATURAMENTO
|
||||||
|
// (evita problema de tabela "BillingClients" vs postgres case)
|
||||||
|
// ==========================================================
|
||||||
|
modelBuilder.Entity<BillingClient>(e =>
|
||||||
|
{
|
||||||
|
// 🔥 Nome físico fixo da tabela no Postgres
|
||||||
|
e.ToTable("billing_clients");
|
||||||
|
|
||||||
|
e.HasKey(x => x.Id);
|
||||||
|
|
||||||
|
// (opcional, mas bom pra padronizar)
|
||||||
|
e.Property(x => x.Tipo).HasMaxLength(2);
|
||||||
|
e.Property(x => x.Cliente).HasMaxLength(255);
|
||||||
|
|
||||||
|
// índices úteis para filtros/ordenação
|
||||||
|
e.HasIndex(x => x.Tipo);
|
||||||
|
e.HasIndex(x => x.Cliente);
|
||||||
|
e.HasIndex(x => new { x.Tipo, x.Cliente });
|
||||||
|
e.HasIndex(x => x.Item);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
namespace line_gestao_api.Dtos
|
||||||
|
{
|
||||||
|
public class BillingClientListDto
|
||||||
|
{
|
||||||
|
public Guid Id { get; set; }
|
||||||
|
public string Tipo { get; set; } = "";
|
||||||
|
public int Item { get; set; }
|
||||||
|
public string Cliente { get; set; } = "";
|
||||||
|
|
||||||
|
public int? QtdLinhas { get; set; }
|
||||||
|
public decimal? FranquiaVivo { get; set; }
|
||||||
|
public decimal? ValorContratoVivo { get; set; }
|
||||||
|
public decimal? FranquiaLine { get; set; }
|
||||||
|
public decimal? ValorContratoLine { get; set; }
|
||||||
|
public decimal? Lucro { get; set; }
|
||||||
|
|
||||||
|
public string? Aparelho { get; set; }
|
||||||
|
public string? FormaPagamento { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace line_gestao_api.Dtos
|
||||||
|
{
|
||||||
|
public class MuregListDto
|
||||||
|
{
|
||||||
|
public Guid Id { get; set; }
|
||||||
|
public int Item { get; set; }
|
||||||
|
public string? LinhaAntiga { get; set; }
|
||||||
|
public string? LinhaNova { get; set; }
|
||||||
|
public string? ICCID { get; set; }
|
||||||
|
public DateTime? DataDaMureg { get; set; }
|
||||||
|
public string? Cliente { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,231 @@
|
||||||
|
// <auto-generated />
|
||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||||
|
using line_gestao_api.Data;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace line_gestao_api.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(AppDbContext))]
|
||||||
|
[Migration("20251229122650_AddMuregLines")]
|
||||||
|
partial class AddMuregLines
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "10.0.1")
|
||||||
|
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||||
|
|
||||||
|
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||||
|
|
||||||
|
modelBuilder.Entity("line_gestao_api.Models.MobileLine", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<string>("Cedente")
|
||||||
|
.HasMaxLength(150)
|
||||||
|
.HasColumnType("character varying(150)");
|
||||||
|
|
||||||
|
b.Property<string>("Chip")
|
||||||
|
.HasMaxLength(40)
|
||||||
|
.HasColumnType("character varying(40)");
|
||||||
|
|
||||||
|
b.Property<string>("Cliente")
|
||||||
|
.HasMaxLength(200)
|
||||||
|
.HasColumnType("character varying(200)");
|
||||||
|
|
||||||
|
b.Property<string>("Conta")
|
||||||
|
.HasMaxLength(80)
|
||||||
|
.HasColumnType("character varying(80)");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("DataBloqueio")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("DataEntregaCliente")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("DataEntregaOpera")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<decimal?>("Desconto")
|
||||||
|
.HasColumnType("numeric");
|
||||||
|
|
||||||
|
b.Property<decimal?>("FranquiaGestao")
|
||||||
|
.HasColumnType("numeric");
|
||||||
|
|
||||||
|
b.Property<decimal?>("FranquiaLine")
|
||||||
|
.HasColumnType("numeric");
|
||||||
|
|
||||||
|
b.Property<decimal?>("FranquiaVivo")
|
||||||
|
.HasColumnType("numeric");
|
||||||
|
|
||||||
|
b.Property<decimal?>("GestaoVozDados")
|
||||||
|
.HasColumnType("numeric");
|
||||||
|
|
||||||
|
b.Property<int>("Item")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<string>("Linha")
|
||||||
|
.HasMaxLength(30)
|
||||||
|
.HasColumnType("character varying(30)");
|
||||||
|
|
||||||
|
b.Property<decimal?>("LocacaoAp")
|
||||||
|
.HasColumnType("numeric");
|
||||||
|
|
||||||
|
b.Property<decimal?>("Lucro")
|
||||||
|
.HasColumnType("numeric");
|
||||||
|
|
||||||
|
b.Property<string>("Modalidade")
|
||||||
|
.HasMaxLength(80)
|
||||||
|
.HasColumnType("character varying(80)");
|
||||||
|
|
||||||
|
b.Property<string>("PlanoContrato")
|
||||||
|
.HasMaxLength(200)
|
||||||
|
.HasColumnType("character varying(200)");
|
||||||
|
|
||||||
|
b.Property<decimal?>("Skeelo")
|
||||||
|
.HasColumnType("numeric");
|
||||||
|
|
||||||
|
b.Property<string>("Skil")
|
||||||
|
.HasMaxLength(80)
|
||||||
|
.HasColumnType("character varying(80)");
|
||||||
|
|
||||||
|
b.Property<string>("Solicitante")
|
||||||
|
.HasMaxLength(150)
|
||||||
|
.HasColumnType("character varying(150)");
|
||||||
|
|
||||||
|
b.Property<string>("Status")
|
||||||
|
.HasMaxLength(80)
|
||||||
|
.HasColumnType("character varying(80)");
|
||||||
|
|
||||||
|
b.Property<DateTime>("UpdatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<string>("Usuario")
|
||||||
|
.HasMaxLength(200)
|
||||||
|
.HasColumnType("character varying(200)");
|
||||||
|
|
||||||
|
b.Property<decimal?>("ValorContratoLine")
|
||||||
|
.HasColumnType("numeric");
|
||||||
|
|
||||||
|
b.Property<decimal?>("ValorContratoVivo")
|
||||||
|
.HasColumnType("numeric");
|
||||||
|
|
||||||
|
b.Property<decimal?>("ValorPlanoVivo")
|
||||||
|
.HasColumnType("numeric");
|
||||||
|
|
||||||
|
b.Property<string>("VencConta")
|
||||||
|
.HasMaxLength(50)
|
||||||
|
.HasColumnType("character varying(50)");
|
||||||
|
|
||||||
|
b.Property<decimal?>("VivoGestaoDispositivo")
|
||||||
|
.HasColumnType("numeric");
|
||||||
|
|
||||||
|
b.Property<decimal?>("VivoNewsPlus")
|
||||||
|
.HasColumnType("numeric");
|
||||||
|
|
||||||
|
b.Property<decimal?>("VivoTravelMundo")
|
||||||
|
.HasColumnType("numeric");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("Linha")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.ToTable("MobileLines");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("line_gestao_api.Models.MuregLine", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<string>("Cliente")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("DataDaMureg")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<string>("ICCID")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<int>("Item")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<string>("LinhaAntiga")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("LinhaNova")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<DateTime>("UpdatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("Cliente");
|
||||||
|
|
||||||
|
b.HasIndex("ICCID");
|
||||||
|
|
||||||
|
b.HasIndex("Item");
|
||||||
|
|
||||||
|
b.HasIndex("LinhaNova");
|
||||||
|
|
||||||
|
b.ToTable("MuregLines");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("line_gestao_api.Models.User", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<string>("Email")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(120)
|
||||||
|
.HasColumnType("character varying(120)");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(120)
|
||||||
|
.HasColumnType("character varying(120)");
|
||||||
|
|
||||||
|
b.Property<string>("PasswordHash")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("Phone")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(20)
|
||||||
|
.HasColumnType("character varying(20)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("Email")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.ToTable("Users");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,61 @@
|
||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace line_gestao_api.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class AddMuregLines : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "MuregLines",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||||
|
Item = table.Column<int>(type: "integer", nullable: false),
|
||||||
|
LinhaAntiga = table.Column<string>(type: "text", nullable: true),
|
||||||
|
LinhaNova = table.Column<string>(type: "text", nullable: true),
|
||||||
|
ICCID = table.Column<string>(type: "text", nullable: true),
|
||||||
|
DataDaMureg = table.Column<DateTime>(type: "timestamp with time zone", nullable: true),
|
||||||
|
Cliente = table.Column<string>(type: "text", nullable: true),
|
||||||
|
CreatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
|
||||||
|
UpdatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_MuregLines", x => x.Id);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_MuregLines_Cliente",
|
||||||
|
table: "MuregLines",
|
||||||
|
column: "Cliente");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_MuregLines_ICCID",
|
||||||
|
table: "MuregLines",
|
||||||
|
column: "ICCID");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_MuregLines_Item",
|
||||||
|
table: "MuregLines",
|
||||||
|
column: "Item");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_MuregLines_LinhaNova",
|
||||||
|
table: "MuregLines",
|
||||||
|
column: "LinhaNova");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "MuregLines");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,231 @@
|
||||||
|
// <auto-generated />
|
||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||||
|
using line_gestao_api.Data;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace line_gestao_api.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(AppDbContext))]
|
||||||
|
[Migration("20260105182438_AddBillingClients")]
|
||||||
|
partial class AddBillingClients
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "10.0.1")
|
||||||
|
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||||
|
|
||||||
|
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||||
|
|
||||||
|
modelBuilder.Entity("line_gestao_api.Models.MobileLine", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<string>("Cedente")
|
||||||
|
.HasMaxLength(150)
|
||||||
|
.HasColumnType("character varying(150)");
|
||||||
|
|
||||||
|
b.Property<string>("Chip")
|
||||||
|
.HasMaxLength(40)
|
||||||
|
.HasColumnType("character varying(40)");
|
||||||
|
|
||||||
|
b.Property<string>("Cliente")
|
||||||
|
.HasMaxLength(200)
|
||||||
|
.HasColumnType("character varying(200)");
|
||||||
|
|
||||||
|
b.Property<string>("Conta")
|
||||||
|
.HasMaxLength(80)
|
||||||
|
.HasColumnType("character varying(80)");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("DataBloqueio")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("DataEntregaCliente")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("DataEntregaOpera")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<decimal?>("Desconto")
|
||||||
|
.HasColumnType("numeric");
|
||||||
|
|
||||||
|
b.Property<decimal?>("FranquiaGestao")
|
||||||
|
.HasColumnType("numeric");
|
||||||
|
|
||||||
|
b.Property<decimal?>("FranquiaLine")
|
||||||
|
.HasColumnType("numeric");
|
||||||
|
|
||||||
|
b.Property<decimal?>("FranquiaVivo")
|
||||||
|
.HasColumnType("numeric");
|
||||||
|
|
||||||
|
b.Property<decimal?>("GestaoVozDados")
|
||||||
|
.HasColumnType("numeric");
|
||||||
|
|
||||||
|
b.Property<int>("Item")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<string>("Linha")
|
||||||
|
.HasMaxLength(30)
|
||||||
|
.HasColumnType("character varying(30)");
|
||||||
|
|
||||||
|
b.Property<decimal?>("LocacaoAp")
|
||||||
|
.HasColumnType("numeric");
|
||||||
|
|
||||||
|
b.Property<decimal?>("Lucro")
|
||||||
|
.HasColumnType("numeric");
|
||||||
|
|
||||||
|
b.Property<string>("Modalidade")
|
||||||
|
.HasMaxLength(80)
|
||||||
|
.HasColumnType("character varying(80)");
|
||||||
|
|
||||||
|
b.Property<string>("PlanoContrato")
|
||||||
|
.HasMaxLength(200)
|
||||||
|
.HasColumnType("character varying(200)");
|
||||||
|
|
||||||
|
b.Property<decimal?>("Skeelo")
|
||||||
|
.HasColumnType("numeric");
|
||||||
|
|
||||||
|
b.Property<string>("Skil")
|
||||||
|
.HasMaxLength(80)
|
||||||
|
.HasColumnType("character varying(80)");
|
||||||
|
|
||||||
|
b.Property<string>("Solicitante")
|
||||||
|
.HasMaxLength(150)
|
||||||
|
.HasColumnType("character varying(150)");
|
||||||
|
|
||||||
|
b.Property<string>("Status")
|
||||||
|
.HasMaxLength(80)
|
||||||
|
.HasColumnType("character varying(80)");
|
||||||
|
|
||||||
|
b.Property<DateTime>("UpdatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<string>("Usuario")
|
||||||
|
.HasMaxLength(200)
|
||||||
|
.HasColumnType("character varying(200)");
|
||||||
|
|
||||||
|
b.Property<decimal?>("ValorContratoLine")
|
||||||
|
.HasColumnType("numeric");
|
||||||
|
|
||||||
|
b.Property<decimal?>("ValorContratoVivo")
|
||||||
|
.HasColumnType("numeric");
|
||||||
|
|
||||||
|
b.Property<decimal?>("ValorPlanoVivo")
|
||||||
|
.HasColumnType("numeric");
|
||||||
|
|
||||||
|
b.Property<string>("VencConta")
|
||||||
|
.HasMaxLength(50)
|
||||||
|
.HasColumnType("character varying(50)");
|
||||||
|
|
||||||
|
b.Property<decimal?>("VivoGestaoDispositivo")
|
||||||
|
.HasColumnType("numeric");
|
||||||
|
|
||||||
|
b.Property<decimal?>("VivoNewsPlus")
|
||||||
|
.HasColumnType("numeric");
|
||||||
|
|
||||||
|
b.Property<decimal?>("VivoTravelMundo")
|
||||||
|
.HasColumnType("numeric");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("Linha")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.ToTable("MobileLines");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("line_gestao_api.Models.MuregLine", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<string>("Cliente")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("DataDaMureg")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<string>("ICCID")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<int>("Item")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<string>("LinhaAntiga")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("LinhaNova")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<DateTime>("UpdatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("Cliente");
|
||||||
|
|
||||||
|
b.HasIndex("ICCID");
|
||||||
|
|
||||||
|
b.HasIndex("Item");
|
||||||
|
|
||||||
|
b.HasIndex("LinhaNova");
|
||||||
|
|
||||||
|
b.ToTable("MuregLines");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("line_gestao_api.Models.User", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<string>("Email")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(120)
|
||||||
|
.HasColumnType("character varying(120)");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(120)
|
||||||
|
.HasColumnType("character varying(120)");
|
||||||
|
|
||||||
|
b.Property<string>("PasswordHash")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("Phone")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(20)
|
||||||
|
.HasColumnType("character varying(20)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("Email")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.ToTable("Users");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace line_gestao_api.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class AddBillingClients : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,293 @@
|
||||||
|
// <auto-generated />
|
||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||||
|
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||||
|
using line_gestao_api.Data;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace line_gestao_api.Migrations
|
||||||
|
{
|
||||||
|
[DbContext(typeof(AppDbContext))]
|
||||||
|
[Migration("20260105201423_CreateBillingClients")]
|
||||||
|
partial class CreateBillingClients
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void BuildTargetModel(ModelBuilder modelBuilder)
|
||||||
|
{
|
||||||
|
#pragma warning disable 612, 618
|
||||||
|
modelBuilder
|
||||||
|
.HasAnnotation("ProductVersion", "10.0.1")
|
||||||
|
.HasAnnotation("Relational:MaxIdentifierLength", 63);
|
||||||
|
|
||||||
|
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||||
|
|
||||||
|
modelBuilder.Entity("line_gestao_api.Models.BillingClient", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<string>("Aparelho")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("Cliente")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(255)
|
||||||
|
.HasColumnType("character varying(255)");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<string>("FormaPagamento")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<decimal?>("FranquiaLine")
|
||||||
|
.HasColumnType("numeric");
|
||||||
|
|
||||||
|
b.Property<decimal?>("FranquiaVivo")
|
||||||
|
.HasColumnType("numeric");
|
||||||
|
|
||||||
|
b.Property<int>("Item")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<decimal?>("Lucro")
|
||||||
|
.HasColumnType("numeric");
|
||||||
|
|
||||||
|
b.Property<int?>("QtdLinhas")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<string>("Tipo")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(2)
|
||||||
|
.HasColumnType("character varying(2)");
|
||||||
|
|
||||||
|
b.Property<DateTime>("UpdatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<decimal?>("ValorContratoLine")
|
||||||
|
.HasColumnType("numeric");
|
||||||
|
|
||||||
|
b.Property<decimal?>("ValorContratoVivo")
|
||||||
|
.HasColumnType("numeric");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("Cliente");
|
||||||
|
|
||||||
|
b.HasIndex("Item");
|
||||||
|
|
||||||
|
b.HasIndex("Tipo");
|
||||||
|
|
||||||
|
b.HasIndex("Tipo", "Cliente");
|
||||||
|
|
||||||
|
b.ToTable("billing_clients", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("line_gestao_api.Models.MobileLine", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<string>("Cedente")
|
||||||
|
.HasMaxLength(150)
|
||||||
|
.HasColumnType("character varying(150)");
|
||||||
|
|
||||||
|
b.Property<string>("Chip")
|
||||||
|
.HasMaxLength(40)
|
||||||
|
.HasColumnType("character varying(40)");
|
||||||
|
|
||||||
|
b.Property<string>("Cliente")
|
||||||
|
.HasMaxLength(200)
|
||||||
|
.HasColumnType("character varying(200)");
|
||||||
|
|
||||||
|
b.Property<string>("Conta")
|
||||||
|
.HasMaxLength(80)
|
||||||
|
.HasColumnType("character varying(80)");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("DataBloqueio")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("DataEntregaCliente")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("DataEntregaOpera")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<decimal?>("Desconto")
|
||||||
|
.HasColumnType("numeric");
|
||||||
|
|
||||||
|
b.Property<decimal?>("FranquiaGestao")
|
||||||
|
.HasColumnType("numeric");
|
||||||
|
|
||||||
|
b.Property<decimal?>("FranquiaLine")
|
||||||
|
.HasColumnType("numeric");
|
||||||
|
|
||||||
|
b.Property<decimal?>("FranquiaVivo")
|
||||||
|
.HasColumnType("numeric");
|
||||||
|
|
||||||
|
b.Property<decimal?>("GestaoVozDados")
|
||||||
|
.HasColumnType("numeric");
|
||||||
|
|
||||||
|
b.Property<int>("Item")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<string>("Linha")
|
||||||
|
.HasMaxLength(30)
|
||||||
|
.HasColumnType("character varying(30)");
|
||||||
|
|
||||||
|
b.Property<decimal?>("LocacaoAp")
|
||||||
|
.HasColumnType("numeric");
|
||||||
|
|
||||||
|
b.Property<decimal?>("Lucro")
|
||||||
|
.HasColumnType("numeric");
|
||||||
|
|
||||||
|
b.Property<string>("Modalidade")
|
||||||
|
.HasMaxLength(80)
|
||||||
|
.HasColumnType("character varying(80)");
|
||||||
|
|
||||||
|
b.Property<string>("PlanoContrato")
|
||||||
|
.HasMaxLength(200)
|
||||||
|
.HasColumnType("character varying(200)");
|
||||||
|
|
||||||
|
b.Property<decimal?>("Skeelo")
|
||||||
|
.HasColumnType("numeric");
|
||||||
|
|
||||||
|
b.Property<string>("Skil")
|
||||||
|
.HasMaxLength(80)
|
||||||
|
.HasColumnType("character varying(80)");
|
||||||
|
|
||||||
|
b.Property<string>("Solicitante")
|
||||||
|
.HasMaxLength(150)
|
||||||
|
.HasColumnType("character varying(150)");
|
||||||
|
|
||||||
|
b.Property<string>("Status")
|
||||||
|
.HasMaxLength(80)
|
||||||
|
.HasColumnType("character varying(80)");
|
||||||
|
|
||||||
|
b.Property<DateTime>("UpdatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<string>("Usuario")
|
||||||
|
.HasMaxLength(200)
|
||||||
|
.HasColumnType("character varying(200)");
|
||||||
|
|
||||||
|
b.Property<decimal?>("ValorContratoLine")
|
||||||
|
.HasColumnType("numeric");
|
||||||
|
|
||||||
|
b.Property<decimal?>("ValorContratoVivo")
|
||||||
|
.HasColumnType("numeric");
|
||||||
|
|
||||||
|
b.Property<decimal?>("ValorPlanoVivo")
|
||||||
|
.HasColumnType("numeric");
|
||||||
|
|
||||||
|
b.Property<string>("VencConta")
|
||||||
|
.HasMaxLength(50)
|
||||||
|
.HasColumnType("character varying(50)");
|
||||||
|
|
||||||
|
b.Property<decimal?>("VivoGestaoDispositivo")
|
||||||
|
.HasColumnType("numeric");
|
||||||
|
|
||||||
|
b.Property<decimal?>("VivoNewsPlus")
|
||||||
|
.HasColumnType("numeric");
|
||||||
|
|
||||||
|
b.Property<decimal?>("VivoTravelMundo")
|
||||||
|
.HasColumnType("numeric");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("Linha")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.ToTable("MobileLines");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("line_gestao_api.Models.MuregLine", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<string>("Cliente")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("DataDaMureg")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<string>("ICCID")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<int>("Item")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<string>("LinhaAntiga")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("LinhaNova")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<DateTime>("UpdatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("Cliente");
|
||||||
|
|
||||||
|
b.HasIndex("ICCID");
|
||||||
|
|
||||||
|
b.HasIndex("Item");
|
||||||
|
|
||||||
|
b.HasIndex("LinhaNova");
|
||||||
|
|
||||||
|
b.ToTable("MuregLines");
|
||||||
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("line_gestao_api.Models.User", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<string>("Email")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(120)
|
||||||
|
.HasColumnType("character varying(120)");
|
||||||
|
|
||||||
|
b.Property<string>("Name")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(120)
|
||||||
|
.HasColumnType("character varying(120)");
|
||||||
|
|
||||||
|
b.Property<string>("PasswordHash")
|
||||||
|
.IsRequired()
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("Phone")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(20)
|
||||||
|
.HasColumnType("character varying(20)");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("Email")
|
||||||
|
.IsUnique();
|
||||||
|
|
||||||
|
b.ToTable("Users");
|
||||||
|
});
|
||||||
|
#pragma warning restore 612, 618
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,66 @@
|
||||||
|
using System;
|
||||||
|
using Microsoft.EntityFrameworkCore.Migrations;
|
||||||
|
|
||||||
|
#nullable disable
|
||||||
|
|
||||||
|
namespace line_gestao_api.Migrations
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
public partial class CreateBillingClients : Migration
|
||||||
|
{
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Up(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.CreateTable(
|
||||||
|
name: "billing_clients",
|
||||||
|
columns: table => new
|
||||||
|
{
|
||||||
|
Id = table.Column<Guid>(type: "uuid", nullable: false),
|
||||||
|
Tipo = table.Column<string>(type: "character varying(2)", maxLength: 2, nullable: false),
|
||||||
|
Item = table.Column<int>(type: "integer", nullable: false),
|
||||||
|
Cliente = table.Column<string>(type: "character varying(255)", maxLength: 255, nullable: false),
|
||||||
|
QtdLinhas = table.Column<int>(type: "integer", nullable: true),
|
||||||
|
FranquiaVivo = table.Column<decimal>(type: "numeric", nullable: true),
|
||||||
|
ValorContratoVivo = table.Column<decimal>(type: "numeric", nullable: true),
|
||||||
|
FranquiaLine = table.Column<decimal>(type: "numeric", nullable: true),
|
||||||
|
ValorContratoLine = table.Column<decimal>(type: "numeric", nullable: true),
|
||||||
|
Lucro = table.Column<decimal>(type: "numeric", nullable: true),
|
||||||
|
Aparelho = table.Column<string>(type: "text", nullable: true),
|
||||||
|
FormaPagamento = table.Column<string>(type: "text", nullable: true),
|
||||||
|
CreatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false),
|
||||||
|
UpdatedAt = table.Column<DateTime>(type: "timestamp with time zone", nullable: false)
|
||||||
|
},
|
||||||
|
constraints: table =>
|
||||||
|
{
|
||||||
|
table.PrimaryKey("PK_billing_clients", x => x.Id);
|
||||||
|
});
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_billing_clients_Cliente",
|
||||||
|
table: "billing_clients",
|
||||||
|
column: "Cliente");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_billing_clients_Item",
|
||||||
|
table: "billing_clients",
|
||||||
|
column: "Item");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_billing_clients_Tipo",
|
||||||
|
table: "billing_clients",
|
||||||
|
column: "Tipo");
|
||||||
|
|
||||||
|
migrationBuilder.CreateIndex(
|
||||||
|
name: "IX_billing_clients_Tipo_Cliente",
|
||||||
|
table: "billing_clients",
|
||||||
|
columns: new[] { "Tipo", "Cliente" });
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override void Down(MigrationBuilder migrationBuilder)
|
||||||
|
{
|
||||||
|
migrationBuilder.DropTable(
|
||||||
|
name: "billing_clients");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -22,6 +22,68 @@ namespace line_gestao_api.Migrations
|
||||||
|
|
||||||
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
NpgsqlModelBuilderExtensions.UseIdentityByDefaultColumns(modelBuilder);
|
||||||
|
|
||||||
|
modelBuilder.Entity("line_gestao_api.Models.BillingClient", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<string>("Aparelho")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("Cliente")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(255)
|
||||||
|
.HasColumnType("character varying(255)");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<string>("FormaPagamento")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<decimal?>("FranquiaLine")
|
||||||
|
.HasColumnType("numeric");
|
||||||
|
|
||||||
|
b.Property<decimal?>("FranquiaVivo")
|
||||||
|
.HasColumnType("numeric");
|
||||||
|
|
||||||
|
b.Property<int>("Item")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<decimal?>("Lucro")
|
||||||
|
.HasColumnType("numeric");
|
||||||
|
|
||||||
|
b.Property<int?>("QtdLinhas")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<string>("Tipo")
|
||||||
|
.IsRequired()
|
||||||
|
.HasMaxLength(2)
|
||||||
|
.HasColumnType("character varying(2)");
|
||||||
|
|
||||||
|
b.Property<DateTime>("UpdatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<decimal?>("ValorContratoLine")
|
||||||
|
.HasColumnType("numeric");
|
||||||
|
|
||||||
|
b.Property<decimal?>("ValorContratoVivo")
|
||||||
|
.HasColumnType("numeric");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("Cliente");
|
||||||
|
|
||||||
|
b.HasIndex("Item");
|
||||||
|
|
||||||
|
b.HasIndex("Tipo");
|
||||||
|
|
||||||
|
b.HasIndex("Tipo", "Cliente");
|
||||||
|
|
||||||
|
b.ToTable("billing_clients", (string)null);
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("line_gestao_api.Models.MobileLine", b =>
|
modelBuilder.Entity("line_gestao_api.Models.MobileLine", b =>
|
||||||
{
|
{
|
||||||
b.Property<Guid>("Id")
|
b.Property<Guid>("Id")
|
||||||
|
|
@ -144,6 +206,49 @@ namespace line_gestao_api.Migrations
|
||||||
b.ToTable("MobileLines");
|
b.ToTable("MobileLines");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
modelBuilder.Entity("line_gestao_api.Models.MuregLine", b =>
|
||||||
|
{
|
||||||
|
b.Property<Guid>("Id")
|
||||||
|
.ValueGeneratedOnAdd()
|
||||||
|
.HasColumnType("uuid");
|
||||||
|
|
||||||
|
b.Property<string>("Cliente")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<DateTime>("CreatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<DateTime?>("DataDaMureg")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.Property<string>("ICCID")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<int>("Item")
|
||||||
|
.HasColumnType("integer");
|
||||||
|
|
||||||
|
b.Property<string>("LinhaAntiga")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<string>("LinhaNova")
|
||||||
|
.HasColumnType("text");
|
||||||
|
|
||||||
|
b.Property<DateTime>("UpdatedAt")
|
||||||
|
.HasColumnType("timestamp with time zone");
|
||||||
|
|
||||||
|
b.HasKey("Id");
|
||||||
|
|
||||||
|
b.HasIndex("Cliente");
|
||||||
|
|
||||||
|
b.HasIndex("ICCID");
|
||||||
|
|
||||||
|
b.HasIndex("Item");
|
||||||
|
|
||||||
|
b.HasIndex("LinhaNova");
|
||||||
|
|
||||||
|
b.ToTable("MuregLines");
|
||||||
|
});
|
||||||
|
|
||||||
modelBuilder.Entity("line_gestao_api.Models.User", b =>
|
modelBuilder.Entity("line_gestao_api.Models.User", b =>
|
||||||
{
|
{
|
||||||
b.Property<Guid>("Id")
|
b.Property<Guid>("Id")
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
namespace line_gestao_api.Models
|
||||||
|
{
|
||||||
|
public class BillingClient
|
||||||
|
{
|
||||||
|
public Guid Id { get; set; }
|
||||||
|
public string Tipo { get; set; } = "PF"; // "PF" ou "PJ"
|
||||||
|
|
||||||
|
public int Item { get; set; }
|
||||||
|
public string Cliente { get; set; } = "";
|
||||||
|
|
||||||
|
public int? QtdLinhas { get; set; }
|
||||||
|
|
||||||
|
public decimal? FranquiaVivo { get; set; }
|
||||||
|
public decimal? ValorContratoVivo { get; set; }
|
||||||
|
|
||||||
|
public decimal? FranquiaLine { get; set; }
|
||||||
|
public decimal? ValorContratoLine { get; set; }
|
||||||
|
|
||||||
|
public decimal? Lucro { get; set; }
|
||||||
|
|
||||||
|
public string? Aparelho { get; set; }
|
||||||
|
public string? FormaPagamento { get; set; }
|
||||||
|
|
||||||
|
public DateTime CreatedAt { get; set; }
|
||||||
|
public DateTime UpdatedAt { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace line_gestao_api.Models
|
||||||
|
{
|
||||||
|
public class MuregLine
|
||||||
|
{
|
||||||
|
public Guid Id { get; set; } = Guid.NewGuid();
|
||||||
|
|
||||||
|
public int Item { get; set; }
|
||||||
|
|
||||||
|
public string? LinhaAntiga { get; set; }
|
||||||
|
public string? LinhaNova { get; set; }
|
||||||
|
public string? ICCID { get; set; }
|
||||||
|
|
||||||
|
public DateTime? DataDaMureg { get; set; }
|
||||||
|
|
||||||
|
public string? Cliente { get; set; }
|
||||||
|
|
||||||
|
public DateTime CreatedAt { get; set; } = DateTime.UtcNow;
|
||||||
|
public DateTime UpdatedAt { get; set; } = DateTime.UtcNow;
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue