diff --git a/Controllers/ChipsVirgensController.cs b/Controllers/ChipsVirgensController.cs new file mode 100644 index 0000000..36c9731 --- /dev/null +++ b/Controllers/ChipsVirgensController.cs @@ -0,0 +1,162 @@ +using line_gestao_api.Data; +using line_gestao_api.Dtos; +using line_gestao_api.Models; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using System.Text; + +namespace line_gestao_api.Controllers +{ + [ApiController] + [Route("api/chips-virgens")] + public class ChipsVirgensController : ControllerBase + { + private readonly AppDbContext _db; + + public ChipsVirgensController(AppDbContext db) + { + _db = db; + } + + [HttpGet] + public async Task>> GetAll( + [FromQuery] string? search, + [FromQuery] int page = 1, + [FromQuery] int pageSize = 20, + [FromQuery] string? sortBy = "item", + [FromQuery] string? sortDir = "asc") + { + page = page < 1 ? 1 : page; + pageSize = pageSize < 1 ? 20 : pageSize; + + var q = _db.ChipVirgemLines.AsNoTracking(); + + if (!string.IsNullOrWhiteSpace(search)) + { + var s = search.Trim(); + q = q.Where(x => + EF.Functions.ILike(x.NumeroDoChip ?? "", $"%{s}%") || + EF.Functions.ILike(x.Observacoes ?? "", $"%{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 + { + "numerodochip" => desc ? q.OrderByDescending(x => x.NumeroDoChip ?? "").ThenBy(x => x.Item) + : q.OrderBy(x => x.NumeroDoChip ?? "").ThenBy(x => x.Item), + "observacoes" => desc ? q.OrderByDescending(x => x.Observacoes ?? "").ThenBy(x => x.Item) + : q.OrderBy(x => x.Observacoes ?? "").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 ChipVirgemListDto + { + Id = x.Id, + Item = x.Item, + NumeroDoChip = x.NumeroDoChip, + Observacoes = x.Observacoes + }) + .ToListAsync(); + + return Ok(new PagedResult + { + Page = page, + PageSize = pageSize, + Total = total, + Items = items + }); + } + + [HttpGet("{id:guid}")] + public async Task> GetById(Guid id) + { + var x = await _db.ChipVirgemLines.AsNoTracking().FirstOrDefaultAsync(a => a.Id == id); + if (x == null) return NotFound(); + + return Ok(ToDetailDto(x)); + } + + [HttpPost] + public async Task> Create([FromBody] CreateChipVirgemDto req) + { + var now = DateTime.UtcNow; + + var e = new ChipVirgemLine + { + Id = Guid.NewGuid(), + Item = req.Item ?? 0, + NumeroDoChip = NullIfEmptyDigits(req.NumeroDoChip), + Observacoes = string.IsNullOrWhiteSpace(req.Observacoes) ? null : req.Observacoes.Trim(), + CreatedAt = now, + UpdatedAt = now + }; + + _db.ChipVirgemLines.Add(e); + await _db.SaveChangesAsync(); + + return CreatedAtAction(nameof(GetById), new { id = e.Id }, ToDetailDto(e)); + } + + [HttpPut("{id:guid}")] + public async Task Update(Guid id, [FromBody] UpdateChipVirgemRequest req) + { + var x = await _db.ChipVirgemLines.FirstOrDefaultAsync(a => a.Id == id); + if (x == null) return NotFound(); + + if (req.Item.HasValue) x.Item = req.Item.Value; + + x.NumeroDoChip = NullIfEmptyDigits(req.NumeroDoChip); + x.Observacoes = string.IsNullOrWhiteSpace(req.Observacoes) ? null : req.Observacoes.Trim(); + x.UpdatedAt = DateTime.UtcNow; + + await _db.SaveChangesAsync(); + return NoContent(); + } + + [HttpDelete("{id:guid}")] + public async Task Delete(Guid id) + { + var x = await _db.ChipVirgemLines.FirstOrDefaultAsync(a => a.Id == id); + if (x == null) return NotFound(); + + _db.ChipVirgemLines.Remove(x); + await _db.SaveChangesAsync(); + return NoContent(); + } + + private static ChipVirgemDetailDto ToDetailDto(ChipVirgemLine x) => new() + { + Id = x.Id, + Item = x.Item, + NumeroDoChip = x.NumeroDoChip, + Observacoes = x.Observacoes, + CreatedAt = x.CreatedAt, + UpdatedAt = x.UpdatedAt + }; + + private static string? NullIfEmptyDigits(string? s) + { + var d = OnlyDigits(s); + return string.IsNullOrWhiteSpace(d) ? null : d; + } + + 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(); + } + } +} diff --git a/Controllers/ControleRecebidosController.cs b/Controllers/ControleRecebidosController.cs new file mode 100644 index 0000000..4d46563 --- /dev/null +++ b/Controllers/ControleRecebidosController.cs @@ -0,0 +1,237 @@ +using line_gestao_api.Data; +using line_gestao_api.Dtos; +using line_gestao_api.Models; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using System.Text; + +namespace line_gestao_api.Controllers +{ + [ApiController] + [Route("api/controle-recebidos")] + public class ControleRecebidosController : ControllerBase + { + private readonly AppDbContext _db; + + public ControleRecebidosController(AppDbContext db) + { + _db = db; + } + + [HttpGet] + public async Task>> GetAll( + [FromQuery] int? ano, + [FromQuery] bool? isResumo, + [FromQuery] string? search, + [FromQuery] int page = 1, + [FromQuery] int pageSize = 20, + [FromQuery] string? sortBy = "item", + [FromQuery] string? sortDir = "asc") + { + page = page < 1 ? 1 : page; + pageSize = pageSize < 1 ? 20 : pageSize; + + var q = _db.ControleRecebidoLines.AsNoTracking(); + + if (ano.HasValue) + q = q.Where(x => x.Ano == ano.Value); + + if (isResumo.HasValue) + q = q.Where(x => x.IsResumo == isResumo.Value); + + if (!string.IsNullOrWhiteSpace(search)) + { + var s = search.Trim(); + q = q.Where(x => + EF.Functions.ILike(x.NotaFiscal ?? "", $"%{s}%") || + EF.Functions.ILike(x.Chip ?? "", $"%{s}%") || + EF.Functions.ILike(x.Serial ?? "", $"%{s}%") || + EF.Functions.ILike(x.ConteudoDaNf ?? "", $"%{s}%") || + EF.Functions.ILike(x.NumeroDaLinha ?? "", $"%{s}%") || + EF.Functions.ILike(x.Item.ToString(), $"%{s}%") || + EF.Functions.ILike(x.Ano.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 + { + "ano" => desc ? q.OrderByDescending(x => x.Ano).ThenBy(x => x.Item) + : q.OrderBy(x => x.Ano).ThenBy(x => x.Item), + "notafiscal" => desc ? q.OrderByDescending(x => x.NotaFiscal ?? "").ThenBy(x => x.Item) + : q.OrderBy(x => x.NotaFiscal ?? "").ThenBy(x => x.Item), + "datadanf" => desc ? q.OrderByDescending(x => x.DataDaNf).ThenBy(x => x.Item) + : q.OrderBy(x => x.DataDaNf).ThenBy(x => x.Item), + "datadorecebimento" => desc ? q.OrderByDescending(x => x.DataDoRecebimento).ThenBy(x => x.Item) + : q.OrderBy(x => x.DataDoRecebimento).ThenBy(x => x.Item), + "valordanf" => desc ? q.OrderByDescending(x => x.ValorDaNf ?? 0).ThenBy(x => x.Item) + : q.OrderBy(x => x.ValorDaNf ?? 0).ThenBy(x => x.Item), + "quantidade" => desc ? q.OrderByDescending(x => x.Quantidade ?? 0).ThenBy(x => x.Item) + : q.OrderBy(x => x.Quantidade ?? 0).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 ControleRecebidoListDto + { + Id = x.Id, + Ano = x.Ano, + Item = x.Item, + NotaFiscal = x.NotaFiscal, + Chip = x.Chip, + Serial = x.Serial, + ConteudoDaNf = x.ConteudoDaNf, + NumeroDaLinha = x.NumeroDaLinha, + ValorUnit = x.ValorUnit, + ValorDaNf = x.ValorDaNf, + DataDaNf = x.DataDaNf, + DataDoRecebimento = x.DataDoRecebimento, + Quantidade = x.Quantidade, + IsResumo = x.IsResumo + }) + .ToListAsync(); + + return Ok(new PagedResult + { + Page = page, + PageSize = pageSize, + Total = total, + Items = items + }); + } + + [HttpGet("{id:guid}")] + public async Task> GetById(Guid id) + { + var x = await _db.ControleRecebidoLines.AsNoTracking().FirstOrDefaultAsync(a => a.Id == id); + if (x == null) return NotFound(); + + return Ok(ToDetailDto(x)); + } + + [HttpPost] + public async Task> Create([FromBody] CreateControleRecebidoDto req) + { + var now = DateTime.UtcNow; + + var e = new ControleRecebidoLine + { + Id = Guid.NewGuid(), + Ano = req.Ano ?? DateTime.UtcNow.Year, + Item = req.Item ?? 0, + NotaFiscal = TrimOrNull(req.NotaFiscal), + Chip = NullIfEmptyDigits(req.Chip), + Serial = TrimOrNull(req.Serial), + ConteudoDaNf = TrimOrNull(req.ConteudoDaNf), + NumeroDaLinha = NullIfEmptyDigits(req.NumeroDaLinha), + ValorUnit = req.ValorUnit, + ValorDaNf = req.ValorDaNf, + DataDaNf = ToUtc(req.DataDaNf), + DataDoRecebimento = ToUtc(req.DataDoRecebimento), + Quantidade = req.Quantidade, + IsResumo = req.IsResumo ?? false, + CreatedAt = now, + UpdatedAt = now + }; + + _db.ControleRecebidoLines.Add(e); + await _db.SaveChangesAsync(); + + return CreatedAtAction(nameof(GetById), new { id = e.Id }, ToDetailDto(e)); + } + + [HttpPut("{id:guid}")] + public async Task Update(Guid id, [FromBody] UpdateControleRecebidoRequest req) + { + var x = await _db.ControleRecebidoLines.FirstOrDefaultAsync(a => a.Id == id); + if (x == null) return NotFound(); + + if (req.Ano.HasValue) x.Ano = req.Ano.Value; + if (req.Item.HasValue) x.Item = req.Item.Value; + + x.NotaFiscal = TrimOrNull(req.NotaFiscal); + x.Chip = NullIfEmptyDigits(req.Chip); + x.Serial = TrimOrNull(req.Serial); + x.ConteudoDaNf = TrimOrNull(req.ConteudoDaNf); + x.NumeroDaLinha = NullIfEmptyDigits(req.NumeroDaLinha); + x.ValorUnit = req.ValorUnit; + x.ValorDaNf = req.ValorDaNf; + x.DataDaNf = ToUtc(req.DataDaNf); + x.DataDoRecebimento = ToUtc(req.DataDoRecebimento); + x.Quantidade = req.Quantidade; + if (req.IsResumo.HasValue) x.IsResumo = req.IsResumo.Value; + + x.UpdatedAt = DateTime.UtcNow; + + await _db.SaveChangesAsync(); + return NoContent(); + } + + [HttpDelete("{id:guid}")] + public async Task Delete(Guid id) + { + var x = await _db.ControleRecebidoLines.FirstOrDefaultAsync(a => a.Id == id); + if (x == null) return NotFound(); + + _db.ControleRecebidoLines.Remove(x); + await _db.SaveChangesAsync(); + return NoContent(); + } + + private static ControleRecebidoDetailDto ToDetailDto(ControleRecebidoLine x) => new() + { + Id = x.Id, + Ano = x.Ano, + Item = x.Item, + NotaFiscal = x.NotaFiscal, + Chip = x.Chip, + Serial = x.Serial, + ConteudoDaNf = x.ConteudoDaNf, + NumeroDaLinha = x.NumeroDaLinha, + ValorUnit = x.ValorUnit, + ValorDaNf = x.ValorDaNf, + DataDaNf = x.DataDaNf, + DataDoRecebimento = x.DataDoRecebimento, + Quantidade = x.Quantidade, + IsResumo = x.IsResumo, + CreatedAt = x.CreatedAt, + UpdatedAt = x.UpdatedAt + }; + + 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 string? TrimOrNull(string? s) + { + if (string.IsNullOrWhiteSpace(s)) return null; + return s.Trim(); + } + + private static string? NullIfEmptyDigits(string? s) + { + var d = OnlyDigits(s); + return string.IsNullOrWhiteSpace(d) ? null : d; + } + + 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(); + } + } +} diff --git a/Controllers/LinesController.cs b/Controllers/LinesController.cs index 7c4b97d..b89bc42 100644 --- a/Controllers/LinesController.cs +++ b/Controllers/LinesController.cs @@ -634,6 +634,16 @@ namespace line_gestao_api.Controllers // ========================= await ImportTrocaNumeroFromWorkbook(wb); + // ========================= + // ✅ IMPORTA CHIPS VIRGENS + // ========================= + await ImportChipsVirgensFromWorkbook(wb); + + // ========================= + // ✅ IMPORTA CONTROLE DE RECEBIDOS + // ========================= + await ImportControleRecebidosFromWorkbook(wb); + await tx.CommitAsync(); return Ok(new ImportResultDto { Imported = imported }); } @@ -1303,6 +1313,225 @@ namespace line_gestao_api.Controllers } } + // ========================================================== + // ✅ IMPORTAÇÃO CHIPS VIRGENS + // ========================================================== + private async Task ImportChipsVirgensFromWorkbook(XLWorkbook wb) + { + var ws = wb.Worksheets.FirstOrDefault(w => NormalizeHeader(w.Name) == NormalizeHeader("CHIP VIRGENS E CONTROLE DE RECEBIDOS")) + ?? wb.Worksheets.FirstOrDefault(w => NormalizeHeader(w.Name) == NormalizeHeader("CHIPS VIRGENS")) + ?? wb.Worksheets.FirstOrDefault(w => + { + var name = NormalizeHeader(w.Name); + return name.Contains("CHIP") && name.Contains("VIRGEN"); + }); + + if (ws == null) return; + + var headerRow = ws.RowsUsed().FirstOrDefault(r => r.CellsUsed().Any(c => NormalizeHeader(c.GetString()) == "ITEM")); + if (headerRow == null) return; + + var map = BuildHeaderMap(headerRow); + int colItem = GetCol(map, "ITEM"); + if (colItem == 0) return; + + var startRow = headerRow.RowNumber() + 1; + var lastRow = ws.LastRowUsed()?.RowNumber() ?? startRow; + + await _db.ChipVirgemLines.ExecuteDeleteAsync(); + + var buffer = new List(500); + + for (int r = startRow; r <= lastRow; r++) + { + var itemStr = GetCellString(ws, r, colItem); + if (string.IsNullOrWhiteSpace(itemStr)) break; + + var numeroChip = NullIfEmptyDigits(GetCellByHeaderAny(ws, r, map, + "Nº DO CHIP", "N° DO CHIP", "NUMERO DO CHIP", "N DO CHIP", "NUM. DO CHIP")); + var observacoes = GetCellByHeaderAny(ws, r, map, "OBSERVAÇÕES", "OBSERVACOES", "OBS"); + + var now = DateTime.UtcNow; + + var e = new ChipVirgemLine + { + Id = Guid.NewGuid(), + Item = TryInt(itemStr), + NumeroDoChip = numeroChip, + Observacoes = string.IsNullOrWhiteSpace(observacoes) ? null : observacoes.Trim(), + CreatedAt = now, + UpdatedAt = now + }; + + buffer.Add(e); + + if (buffer.Count >= 500) + { + await _db.ChipVirgemLines.AddRangeAsync(buffer); + await _db.SaveChangesAsync(); + buffer.Clear(); + } + } + + if (buffer.Count > 0) + { + await _db.ChipVirgemLines.AddRangeAsync(buffer); + await _db.SaveChangesAsync(); + } + } + + // ========================================================== + // ✅ IMPORTAÇÃO CONTROLE DE RECEBIDOS (2022-2025) + // ========================================================== + private async Task ImportControleRecebidosFromWorkbook(XLWorkbook wb) + { + await _db.ControleRecebidoLines.ExecuteDeleteAsync(); + + var years = new[] { 2022, 2023, 2024, 2025 }; + + foreach (var year in years) + { + var ws = FindControleRecebidosWorksheet(wb, year); + if (ws == null) continue; + + await ImportControleRecebidosSheet(ws, year); + } + } + + private async Task ImportControleRecebidosSheet(IXLWorksheet ws, int year) + { + var buffer = new List(500); + + var firstRow = ws.FirstRowUsed()?.RowNumber() ?? 1; + var lastRow = ws.LastRowUsed()?.RowNumber() ?? firstRow; + var rowIndex = firstRow; + + while (rowIndex <= lastRow) + { + var row = ws.Row(rowIndex); + if (!IsControleRecebidosHeader(row)) + { + rowIndex++; + continue; + } + + var map = BuildHeaderMap(row); + int colItem = GetCol(map, "ITEM"); + if (colItem == 0) + { + rowIndex++; + continue; + } + + var isResumo = GetColAny(map, "QTD.", "QTD", "QUANTIDADE") > 0 + && GetColAny(map, "CHIP") == 0 + && GetColAny(map, "SERIAL") == 0; + + rowIndex++; + + for (; rowIndex <= lastRow; rowIndex++) + { + var currentRow = ws.Row(rowIndex); + if (IsControleRecebidosHeader(currentRow)) + { + rowIndex--; + break; + } + + var itemStr = GetCellString(ws, rowIndex, colItem); + if (string.IsNullOrWhiteSpace(itemStr)) break; + + var notaFiscal = GetCellByHeaderAny(ws, rowIndex, map, "NOTA FISCAL", "NOTA", "NF"); + var chip = NullIfEmptyDigits(GetCellByHeaderAny(ws, rowIndex, map, "CHIP")); + var serial = GetCellByHeaderAny(ws, rowIndex, map, "SERIAL"); + var conteudo = GetCellByHeaderAny(ws, rowIndex, map, "CONTEÚDO DA NF", "CONTEUDO DA NF"); + var numeroLinha = NullIfEmptyDigits(GetCellByHeaderAny(ws, rowIndex, map, "NÚMERO DA LINHA", "NUMERO DA LINHA")); + var valorUnit = TryDecimal(GetCellByHeaderAny(ws, rowIndex, map, "VALOR UNIT.", "VALOR UNIT", "VALOR UNITÁRIO", "VALOR UNITARIO")); + var valorDaNf = TryDecimal(GetCellByHeaderAny(ws, rowIndex, map, "VALOR DA NF", "VALOR DA N F")); + var dataDaNf = TryDate(ws, rowIndex, map, "DATA DA NF"); + var dataReceb = TryDate(ws, rowIndex, map, "DATA DO RECEBIMENTO"); + var qtd = TryNullableInt(GetCellByHeaderAny(ws, rowIndex, map, "QTD.", "QTD", "QUANTIDADE")); + + var now = DateTime.UtcNow; + + var e = new ControleRecebidoLine + { + Id = Guid.NewGuid(), + Ano = year, + Item = TryInt(itemStr), + NotaFiscal = string.IsNullOrWhiteSpace(notaFiscal) ? null : notaFiscal.Trim(), + Chip = chip, + Serial = string.IsNullOrWhiteSpace(serial) ? null : serial.Trim(), + ConteudoDaNf = string.IsNullOrWhiteSpace(conteudo) ? null : conteudo.Trim(), + NumeroDaLinha = numeroLinha, + ValorUnit = valorUnit, + ValorDaNf = valorDaNf, + DataDaNf = dataDaNf, + DataDoRecebimento = dataReceb, + Quantidade = qtd, + IsResumo = isResumo, + CreatedAt = now, + UpdatedAt = now + }; + + buffer.Add(e); + + if (buffer.Count >= 500) + { + await _db.ControleRecebidoLines.AddRangeAsync(buffer); + await _db.SaveChangesAsync(); + buffer.Clear(); + } + } + + rowIndex++; + } + + if (buffer.Count > 0) + { + await _db.ControleRecebidoLines.AddRangeAsync(buffer); + await _db.SaveChangesAsync(); + } + } + + private static IXLWorksheet? FindControleRecebidosWorksheet(XLWorkbook wb, int year) + { + var normalizedName = NormalizeHeader($"CONTROLE DE RECEBIDOS {year}"); + + var ws = wb.Worksheets.FirstOrDefault(w => NormalizeHeader(w.Name) == normalizedName); + if (ws != null) return ws; + + ws = wb.Worksheets.FirstOrDefault(w => + { + var name = NormalizeHeader(w.Name); + return name.Contains("CONTROLE") && name.Contains("RECEBIDOS") && name.Contains(year.ToString()); + }); + if (ws != null) return ws; + + if (year == 2024) + { + ws = wb.Worksheets.FirstOrDefault(w => NormalizeHeader(w.Name) == NormalizeHeader("CONTROLE DE RECEBIDOS")); + } + + return ws; + } + + private static bool IsControleRecebidosHeader(IXLRow row) + { + var hasItem = false; + var hasNota = false; + + foreach (var cell in row.CellsUsed()) + { + var k = NormalizeHeader(cell.GetString()); + if (k == "ITEM") hasItem = true; + if (k == "NOTAFISCAL") hasNota = true; + if (hasItem && hasNota) return true; + } + + return false; + } + // ========================================================== // HELPERS (SEUS) // ========================================================== diff --git a/Data/AppDbContext.cs b/Data/AppDbContext.cs index 8007767..ddd837c 100644 --- a/Data/AppDbContext.cs +++ b/Data/AppDbContext.cs @@ -35,6 +35,12 @@ public class AppDbContext : IdentityDbContext TrocaNumeroLines => Set(); + // ✅ tabela CHIPS VIRGENS + public DbSet ChipVirgemLines => Set(); + + // ✅ tabela CONTROLE DE RECEBIDOS + public DbSet ControleRecebidoLines => Set(); + // ✅ tabela NOTIFICAÇÕES public DbSet Notifications => Set(); @@ -147,6 +153,32 @@ public class AppDbContext : IdentityDbContext x.TenantId); }); + // ========================= + // ✅ CHIPS VIRGENS + // ========================= + modelBuilder.Entity(e => + { + e.HasIndex(x => x.Item); + e.HasIndex(x => x.NumeroDoChip); + e.HasIndex(x => x.TenantId); + }); + + // ========================= + // ✅ CONTROLE DE RECEBIDOS + // ========================= + modelBuilder.Entity(e => + { + e.HasIndex(x => x.Ano); + e.HasIndex(x => x.Item); + e.HasIndex(x => x.NotaFiscal); + e.HasIndex(x => x.Chip); + e.HasIndex(x => x.Serial); + e.HasIndex(x => x.NumeroDaLinha); + e.HasIndex(x => x.DataDaNf); + e.HasIndex(x => x.DataDoRecebimento); + e.HasIndex(x => x.TenantId); + }); + // ========================= // ✅ NOTIFICAÇÕES // ========================= @@ -177,6 +209,8 @@ public class AppDbContext : IdentityDbContext().HasQueryFilter(x => _tenantProvider.TenantId != null && x.TenantId == _tenantProvider.TenantId); modelBuilder.Entity().HasQueryFilter(x => _tenantProvider.TenantId != null && x.TenantId == _tenantProvider.TenantId); modelBuilder.Entity().HasQueryFilter(x => _tenantProvider.TenantId != null && x.TenantId == _tenantProvider.TenantId); + modelBuilder.Entity().HasQueryFilter(x => _tenantProvider.TenantId != null && x.TenantId == _tenantProvider.TenantId); + modelBuilder.Entity().HasQueryFilter(x => _tenantProvider.TenantId != null && x.TenantId == _tenantProvider.TenantId); modelBuilder.Entity().HasQueryFilter(x => _tenantProvider.TenantId != null && x.TenantId == _tenantProvider.TenantId); modelBuilder.Entity().HasQueryFilter(x => _tenantProvider.TenantId != null && x.TenantId == _tenantProvider.TenantId); } diff --git a/Dtos/ChipsVirgensDtos.cs b/Dtos/ChipsVirgensDtos.cs new file mode 100644 index 0000000..1a84ff0 --- /dev/null +++ b/Dtos/ChipsVirgensDtos.cs @@ -0,0 +1,29 @@ +using System; + +namespace line_gestao_api.Dtos +{ + public class ChipVirgemListDto + { + public Guid Id { get; set; } + public int Item { get; set; } + public string? NumeroDoChip { get; set; } + public string? Observacoes { get; set; } + } + + public class ChipVirgemDetailDto : ChipVirgemListDto + { + public DateTime CreatedAt { get; set; } + public DateTime UpdatedAt { get; set; } + } + + public class CreateChipVirgemDto + { + public int? Item { get; set; } + public string? NumeroDoChip { get; set; } + public string? Observacoes { get; set; } + } + + public class UpdateChipVirgemRequest : CreateChipVirgemDto + { + } +} diff --git a/Dtos/ControleRecebidosDtos.cs b/Dtos/ControleRecebidosDtos.cs new file mode 100644 index 0000000..ccf7fe9 --- /dev/null +++ b/Dtos/ControleRecebidosDtos.cs @@ -0,0 +1,49 @@ +using System; + +namespace line_gestao_api.Dtos +{ + public class ControleRecebidoListDto + { + public Guid Id { get; set; } + public int Ano { get; set; } + public int Item { get; set; } + public string? NotaFiscal { get; set; } + public string? Chip { get; set; } + public string? Serial { get; set; } + public string? ConteudoDaNf { get; set; } + public string? NumeroDaLinha { get; set; } + public decimal? ValorUnit { get; set; } + public decimal? ValorDaNf { get; set; } + public DateTime? DataDaNf { get; set; } + public DateTime? DataDoRecebimento { get; set; } + public int? Quantidade { get; set; } + public bool IsResumo { get; set; } + } + + public class ControleRecebidoDetailDto : ControleRecebidoListDto + { + public DateTime CreatedAt { get; set; } + public DateTime UpdatedAt { get; set; } + } + + public class CreateControleRecebidoDto + { + public int? Ano { get; set; } + public int? Item { get; set; } + public string? NotaFiscal { get; set; } + public string? Chip { get; set; } + public string? Serial { get; set; } + public string? ConteudoDaNf { get; set; } + public string? NumeroDaLinha { get; set; } + public decimal? ValorUnit { get; set; } + public decimal? ValorDaNf { get; set; } + public DateTime? DataDaNf { get; set; } + public DateTime? DataDoRecebimento { get; set; } + public int? Quantidade { get; set; } + public bool? IsResumo { get; set; } + } + + public class UpdateControleRecebidoRequest : CreateControleRecebidoDto + { + } +} diff --git a/Migrations/20260211120000_AddChipsVirgensControleRecebidos.Designer.cs b/Migrations/20260211120000_AddChipsVirgensControleRecebidos.Designer.cs new file mode 100644 index 0000000..a1b26a5 --- /dev/null +++ b/Migrations/20260211120000_AddChipsVirgensControleRecebidos.Designer.cs @@ -0,0 +1,963 @@ +// +using System; +using Microsoft.EntityFrameworkCore; +using Microsoft.EntityFrameworkCore.Infrastructure; +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("20260211120000_AddChipsVirgensControleRecebidos")] + partial class AddChipsVirgensControleRecebidos + { + 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("Microsoft.AspNetCore.Identity.IdentityRole", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("text"); + + b.Property("Name") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("NormalizedName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedName") + .IsUnique() + .HasDatabaseName("RoleNameIndex"); + + b.ToTable("AspNetRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("text"); + + b.Property("ClaimValue") + .HasColumnType("text"); + + b.Property("RoleId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetRoleClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("integer"); + + NpgsqlPropertyBuilderExtensions.UseIdentityByDefaultColumn(b.Property("Id")); + + b.Property("ClaimType") + .HasColumnType("text"); + + b.Property("ClaimValue") + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserClaims", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.Property("LoginProvider") + .HasColumnType("text"); + + b.Property("ProviderKey") + .HasColumnType("text"); + + b.Property("ProviderDisplayName") + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.HasKey("LoginProvider", "ProviderKey"); + + b.HasIndex("UserId"); + + b.ToTable("AspNetUserLogins", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("RoleId") + .HasColumnType("uuid"); + + b.HasKey("UserId", "RoleId"); + + b.HasIndex("RoleId"); + + b.ToTable("AspNetUserRoles", (string)null); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("LoginProvider") + .HasColumnType("text"); + + b.Property("Name") + .HasColumnType("text"); + + b.Property("Value") + .HasColumnType("text"); + + b.HasKey("UserId", "LoginProvider", "Name"); + + b.ToTable("AspNetUserTokens", (string)null); + }); + + modelBuilder.Entity("line_gestao_api.Models.ApplicationUser", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("AccessFailedCount") + .HasColumnType("integer"); + + b.Property("ConcurrencyStamp") + .IsConcurrencyToken() + .HasColumnType("text"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Email") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("EmailConfirmed") + .HasColumnType("boolean"); + + b.Property("IsActive") + .HasColumnType("boolean"); + + b.Property("LockoutEnabled") + .HasColumnType("boolean"); + + b.Property("LockoutEnd") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasMaxLength(120) + .HasColumnType("character varying(120)"); + + b.Property("NormalizedEmail") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("NormalizedUserName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.Property("PasswordHash") + .HasColumnType("text"); + + b.Property("PhoneNumber") + .HasColumnType("text"); + + b.Property("PhoneNumberConfirmed") + .HasColumnType("boolean"); + + b.Property("SecurityStamp") + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid"); + + b.Property("TwoFactorEnabled") + .HasColumnType("boolean"); + + b.Property("UserName") + .HasMaxLength(256) + .HasColumnType("character varying(256)"); + + b.HasKey("Id"); + + b.HasIndex("NormalizedEmail") + .HasDatabaseName("EmailIndex"); + + b.HasIndex("NormalizedUserName") + .IsUnique() + .HasDatabaseName("UserNameIndex"); + + b.HasIndex("TenantId", "NormalizedEmail") + .IsUnique(); + + b.ToTable("AspNetUsers", (string)null); + }); + + modelBuilder.Entity("line_gestao_api.Models.BillingClient", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Aparelho") + .HasColumnType("text"); + + b.Property("Cliente") + .IsRequired() + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("FormaPagamento") + .HasColumnType("text"); + + b.Property("FranquiaLine") + .HasColumnType("numeric"); + + b.Property("FranquiaVivo") + .HasColumnType("numeric"); + + b.Property("Item") + .HasColumnType("integer"); + + b.Property("Lucro") + .HasColumnType("numeric"); + + b.Property("QtdLinhas") + .HasColumnType("integer"); + + b.Property("TenantId") + .HasColumnType("uuid"); + + b.Property("Tipo") + .IsRequired() + .HasMaxLength(2) + .HasColumnType("character varying(2)"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ValorContratoLine") + .HasColumnType("numeric"); + + b.Property("ValorContratoVivo") + .HasColumnType("numeric"); + + b.HasKey("Id"); + + b.HasIndex("Cliente"); + + b.HasIndex("Item"); + + b.HasIndex("TenantId"); + + b.HasIndex("Tipo"); + + b.HasIndex("Tipo", "Cliente"); + + b.ToTable("billing_clients", (string)null); + }); + + modelBuilder.Entity("line_gestao_api.Models.MobileLine", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Cedente") + .HasMaxLength(150) + .HasColumnType("character varying(150)"); + + b.Property("Chip") + .HasMaxLength(40) + .HasColumnType("character varying(40)"); + + b.Property("Cliente") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Conta") + .HasMaxLength(80) + .HasColumnType("character varying(80)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DataBloqueio") + .HasColumnType("timestamp with time zone"); + + b.Property("DataEntregaCliente") + .HasColumnType("timestamp with time zone"); + + b.Property("DataEntregaOpera") + .HasColumnType("timestamp with time zone"); + + b.Property("Desconto") + .HasColumnType("numeric"); + + b.Property("FranquiaGestao") + .HasColumnType("numeric"); + + b.Property("FranquiaLine") + .HasColumnType("numeric"); + + b.Property("FranquiaVivo") + .HasColumnType("numeric"); + + b.Property("GestaoVozDados") + .HasColumnType("numeric"); + + b.Property("Item") + .HasColumnType("integer"); + + b.Property("Linha") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("LocacaoAp") + .HasColumnType("numeric"); + + b.Property("Lucro") + .HasColumnType("numeric"); + + b.Property("Modalidade") + .HasMaxLength(80) + .HasColumnType("character varying(80)"); + + b.Property("PlanoContrato") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("Skeelo") + .HasColumnType("numeric"); + + b.Property("Skil") + .HasMaxLength(80) + .HasColumnType("character varying(80)"); + + b.Property("Solicitante") + .HasMaxLength(150) + .HasColumnType("character varying(150)"); + + b.Property("Status") + .HasMaxLength(80) + .HasColumnType("character varying(80)"); + + b.Property("TenantId") + .HasColumnType("uuid"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Usuario") + .HasMaxLength(200) + .HasColumnType("character varying(200)"); + + b.Property("ValorContratoLine") + .HasColumnType("numeric"); + + b.Property("ValorContratoVivo") + .HasColumnType("numeric"); + + b.Property("ValorPlanoVivo") + .HasColumnType("numeric"); + + b.Property("VencConta") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("VivoGestaoDispositivo") + .HasColumnType("numeric"); + + b.Property("VivoNewsPlus") + .HasColumnType("numeric"); + + b.Property("VivoTravelMundo") + .HasColumnType("numeric"); + + b.HasKey("Id"); + + b.HasIndex("Chip"); + + b.HasIndex("Cliente"); + + b.HasIndex("Skil"); + + b.HasIndex("Status"); + + b.HasIndex("Usuario"); + + b.HasIndex("TenantId", "Linha") + .IsUnique(); + + b.ToTable("MobileLines"); + }); + + modelBuilder.Entity("line_gestao_api.Models.MuregLine", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DataDaMureg") + .HasColumnType("timestamp with time zone"); + + b.Property("ICCID") + .HasMaxLength(40) + .HasColumnType("character varying(40)"); + + b.Property("Item") + .HasColumnType("integer"); + + b.Property("LinhaAntiga") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("LinhaNova") + .HasMaxLength(30) + .HasColumnType("character varying(30)"); + + b.Property("MobileLineId") + .HasColumnType("uuid"); + + b.Property("TenantId") + .HasColumnType("uuid"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("ICCID"); + + b.HasIndex("Item"); + + b.HasIndex("LinhaAntiga"); + + b.HasIndex("LinhaNova"); + + b.HasIndex("MobileLineId"); + + b.HasIndex("TenantId"); + + b.ToTable("MuregLines"); + }); + + modelBuilder.Entity("line_gestao_api.Models.Notification", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Cliente") + .HasColumnType("text"); + + b.Property("Data") + .HasColumnType("timestamp with time zone"); + + b.Property("DedupKey") + .IsRequired() + .HasColumnType("text"); + + b.Property("DiasParaVencer") + .HasColumnType("integer"); + + b.Property("Lida") + .HasColumnType("boolean"); + + b.Property("LidaEm") + .HasColumnType("timestamp with time zone"); + + b.Property("Linha") + .HasColumnType("text"); + + b.Property("Mensagem") + .IsRequired() + .HasColumnType("text"); + + b.Property("ReferenciaData") + .HasColumnType("timestamp with time zone"); + + b.Property("TenantId") + .HasColumnType("uuid"); + + b.Property("Tipo") + .IsRequired() + .HasColumnType("text"); + + b.Property("Titulo") + .IsRequired() + .HasColumnType("text"); + + b.Property("UserId") + .HasColumnType("uuid"); + + b.Property("Usuario") + .HasColumnType("text"); + + b.Property("VigenciaLineId") + .HasColumnType("uuid"); + + b.HasKey("Id"); + + b.HasIndex("Cliente"); + + b.HasIndex("Data"); + + b.HasIndex("DedupKey") + .IsUnique(); + + b.HasIndex("Lida"); + + b.HasIndex("TenantId"); + + b.HasIndex("UserId"); + + b.HasIndex("VigenciaLineId"); + + b.ToTable("Notifications"); + }); + + modelBuilder.Entity("line_gestao_api.Models.Tenant", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Name") + .IsRequired() + .HasColumnType("text"); + + b.HasKey("Id"); + + b.ToTable("Tenants"); + }); + + modelBuilder.Entity("line_gestao_api.Models.ChipVirgemLine", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Item") + .HasColumnType("integer"); + + b.Property("NumeroDoChip") + .HasMaxLength(40) + .HasColumnType("character varying(40)"); + + b.Property("Observacoes") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("TenantId") + .HasColumnType("uuid"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("Item"); + + b.HasIndex("NumeroDoChip"); + + b.HasIndex("TenantId"); + + b.ToTable("ChipVirgemLines"); + }); + + modelBuilder.Entity("line_gestao_api.Models.ControleRecebidoLine", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Ano") + .HasColumnType("integer"); + + b.Property("Chip") + .HasMaxLength(40) + .HasColumnType("character varying(40)"); + + b.Property("ConteudoDaNf") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DataDaNf") + .HasColumnType("timestamp with time zone"); + + b.Property("DataDoRecebimento") + .HasColumnType("timestamp with time zone"); + + b.Property("IsResumo") + .HasColumnType("boolean"); + + b.Property("Item") + .HasColumnType("integer"); + + b.Property("NotaFiscal") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("NumeroDaLinha") + .HasMaxLength(40) + .HasColumnType("character varying(40)"); + + b.Property("Quantidade") + .HasColumnType("integer"); + + b.Property("Serial") + .HasMaxLength(80) + .HasColumnType("character varying(80)"); + + b.Property("TenantId") + .HasColumnType("uuid"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ValorDaNf") + .HasColumnType("numeric"); + + b.Property("ValorUnit") + .HasColumnType("numeric"); + + b.HasKey("Id"); + + b.HasIndex("Ano"); + + b.HasIndex("Chip"); + + b.HasIndex("DataDaNf"); + + b.HasIndex("DataDoRecebimento"); + + b.HasIndex("Item"); + + b.HasIndex("NotaFiscal"); + + b.HasIndex("NumeroDaLinha"); + + b.HasIndex("Serial"); + + b.HasIndex("TenantId"); + + b.ToTable("ControleRecebidoLines"); + }); + + modelBuilder.Entity("line_gestao_api.Models.TrocaNumeroLine", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DataTroca") + .HasColumnType("timestamp with time zone"); + + b.Property("ICCID") + .HasColumnType("text"); + + b.Property("Item") + .HasColumnType("integer"); + + b.Property("LinhaAntiga") + .HasColumnType("text"); + + b.Property("LinhaNova") + .HasColumnType("text"); + + b.Property("Motivo") + .HasColumnType("text"); + + b.Property("Observacao") + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("DataTroca"); + + b.HasIndex("ICCID"); + + b.HasIndex("Item"); + + b.HasIndex("LinhaAntiga"); + + b.HasIndex("LinhaNova"); + + b.HasIndex("TenantId"); + + b.ToTable("TrocaNumeroLines"); + }); + + modelBuilder.Entity("line_gestao_api.Models.UserData", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Celular") + .HasColumnType("text"); + + b.Property("Cliente") + .HasColumnType("text"); + + b.Property("Cpf") + .HasColumnType("text"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DataNascimento") + .HasColumnType("timestamp with time zone"); + + b.Property("Email") + .HasColumnType("text"); + + b.Property("Endereco") + .HasColumnType("text"); + + b.Property("Item") + .HasColumnType("integer"); + + b.Property("Linha") + .HasColumnType("text"); + + b.Property("Rg") + .HasColumnType("text"); + + b.Property("TelefoneFixo") + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("Cliente"); + + b.HasIndex("Cpf"); + + b.HasIndex("Email"); + + b.HasIndex("Item"); + + b.HasIndex("Linha"); + + b.HasIndex("TenantId"); + + b.ToTable("UserDatas"); + }); + + modelBuilder.Entity("line_gestao_api.Models.VigenciaLine", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Cliente") + .HasColumnType("text"); + + b.Property("Conta") + .HasColumnType("text"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DtEfetivacaoServico") + .HasColumnType("timestamp with time zone"); + + b.Property("DtTerminoFidelizacao") + .HasColumnType("timestamp with time zone"); + + b.Property("Item") + .HasColumnType("integer"); + + b.Property("Linha") + .HasColumnType("text"); + + b.Property("PlanoContrato") + .HasColumnType("text"); + + b.Property("TenantId") + .HasColumnType("uuid"); + + b.Property("Total") + .HasColumnType("numeric"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Usuario") + .HasColumnType("text"); + + b.HasKey("Id"); + + b.HasIndex("Cliente"); + + b.HasIndex("DtTerminoFidelizacao"); + + b.HasIndex("Item"); + + b.HasIndex("Linha"); + + b.HasIndex("TenantId"); + + b.ToTable("VigenciaLines"); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityRoleClaim", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserClaim", b => + { + b.HasOne("line_gestao_api.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserLogin", b => + { + b.HasOne("line_gestao_api.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserRole", b => + { + b.HasOne("Microsoft.AspNetCore.Identity.IdentityRole", null) + .WithMany() + .HasForeignKey("RoleId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + + b.HasOne("line_gestao_api.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("Microsoft.AspNetCore.Identity.IdentityUserToken", b => + { + b.HasOne("line_gestao_api.Models.ApplicationUser", null) + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Cascade) + .IsRequired(); + }); + + modelBuilder.Entity("line_gestao_api.Models.MuregLine", b => + { + b.HasOne("line_gestao_api.Models.MobileLine", "MobileLine") + .WithMany("Muregs") + .HasForeignKey("MobileLineId") + .OnDelete(DeleteBehavior.Restrict) + .IsRequired(); + + b.Navigation("MobileLine"); + }); + + modelBuilder.Entity("line_gestao_api.Models.Notification", b => + { + b.HasOne("line_gestao_api.Models.ApplicationUser", "User") + .WithMany() + .HasForeignKey("UserId") + .OnDelete(DeleteBehavior.Restrict); + + b.HasOne("line_gestao_api.Models.VigenciaLine", "VigenciaLine") + .WithMany() + .HasForeignKey("VigenciaLineId") + .OnDelete(DeleteBehavior.Restrict); + + b.Navigation("User"); + + b.Navigation("VigenciaLine"); + }); + + modelBuilder.Entity("line_gestao_api.Models.MobileLine", b => + { + b.Navigation("Muregs"); + }); +#pragma warning restore 612, 618 + } + } +} diff --git a/Migrations/20260211120000_AddChipsVirgensControleRecebidos.cs b/Migrations/20260211120000_AddChipsVirgensControleRecebidos.cs new file mode 100644 index 0000000..ed7c77d --- /dev/null +++ b/Migrations/20260211120000_AddChipsVirgensControleRecebidos.cs @@ -0,0 +1,129 @@ +using System; +using Microsoft.EntityFrameworkCore.Migrations; + +#nullable disable + +namespace line_gestao_api.Migrations +{ + /// + public partial class AddChipsVirgensControleRecebidos : Migration + { + /// + protected override void Up(MigrationBuilder migrationBuilder) + { + migrationBuilder.CreateTable( + name: "ChipVirgemLines", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: false), + Item = table.Column(type: "integer", nullable: false), + NumeroDoChip = table.Column(type: "character varying(40)", maxLength: 40, nullable: true), + Observacoes = table.Column(type: "character varying(500)", maxLength: 500, nullable: true), + CreatedAt = table.Column(type: "timestamp with time zone", nullable: false), + UpdatedAt = table.Column(type: "timestamp with time zone", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ChipVirgemLines", x => x.Id); + }); + + migrationBuilder.CreateTable( + name: "ControleRecebidoLines", + columns: table => new + { + Id = table.Column(type: "uuid", nullable: false), + TenantId = table.Column(type: "uuid", nullable: false), + Ano = table.Column(type: "integer", nullable: false), + Item = table.Column(type: "integer", nullable: false), + NotaFiscal = table.Column(type: "character varying(50)", maxLength: 50, nullable: true), + Chip = table.Column(type: "character varying(40)", maxLength: 40, nullable: true), + Serial = table.Column(type: "character varying(80)", maxLength: 80, nullable: true), + ConteudoDaNf = table.Column(type: "character varying(255)", maxLength: 255, nullable: true), + NumeroDaLinha = table.Column(type: "character varying(40)", maxLength: 40, nullable: true), + ValorUnit = table.Column(type: "numeric", nullable: true), + ValorDaNf = table.Column(type: "numeric", nullable: true), + DataDaNf = table.Column(type: "timestamp with time zone", nullable: true), + DataDoRecebimento = table.Column(type: "timestamp with time zone", nullable: true), + Quantidade = table.Column(type: "integer", nullable: true), + IsResumo = table.Column(type: "boolean", nullable: false), + CreatedAt = table.Column(type: "timestamp with time zone", nullable: false), + UpdatedAt = table.Column(type: "timestamp with time zone", nullable: false) + }, + constraints: table => + { + table.PrimaryKey("PK_ControleRecebidoLines", x => x.Id); + }); + + migrationBuilder.CreateIndex( + name: "IX_ChipVirgemLines_Item", + table: "ChipVirgemLines", + column: "Item"); + + migrationBuilder.CreateIndex( + name: "IX_ChipVirgemLines_NumeroDoChip", + table: "ChipVirgemLines", + column: "NumeroDoChip"); + + migrationBuilder.CreateIndex( + name: "IX_ChipVirgemLines_TenantId", + table: "ChipVirgemLines", + column: "TenantId"); + + migrationBuilder.CreateIndex( + name: "IX_ControleRecebidoLines_Ano", + table: "ControleRecebidoLines", + column: "Ano"); + + migrationBuilder.CreateIndex( + name: "IX_ControleRecebidoLines_Chip", + table: "ControleRecebidoLines", + column: "Chip"); + + migrationBuilder.CreateIndex( + name: "IX_ControleRecebidoLines_DataDaNf", + table: "ControleRecebidoLines", + column: "DataDaNf"); + + migrationBuilder.CreateIndex( + name: "IX_ControleRecebidoLines_DataDoRecebimento", + table: "ControleRecebidoLines", + column: "DataDoRecebimento"); + + migrationBuilder.CreateIndex( + name: "IX_ControleRecebidoLines_Item", + table: "ControleRecebidoLines", + column: "Item"); + + migrationBuilder.CreateIndex( + name: "IX_ControleRecebidoLines_NotaFiscal", + table: "ControleRecebidoLines", + column: "NotaFiscal"); + + migrationBuilder.CreateIndex( + name: "IX_ControleRecebidoLines_NumeroDaLinha", + table: "ControleRecebidoLines", + column: "NumeroDaLinha"); + + migrationBuilder.CreateIndex( + name: "IX_ControleRecebidoLines_Serial", + table: "ControleRecebidoLines", + column: "Serial"); + + migrationBuilder.CreateIndex( + name: "IX_ControleRecebidoLines_TenantId", + table: "ControleRecebidoLines", + column: "TenantId"); + } + + /// + protected override void Down(MigrationBuilder migrationBuilder) + { + migrationBuilder.DropTable( + name: "ChipVirgemLines"); + + migrationBuilder.DropTable( + name: "ControleRecebidoLines"); + } + } +} diff --git a/Migrations/AppDbContextModelSnapshot.cs b/Migrations/AppDbContextModelSnapshot.cs index 42edd29..f0e3565 100644 --- a/Migrations/AppDbContextModelSnapshot.cs +++ b/Migrations/AppDbContextModelSnapshot.cs @@ -582,6 +582,125 @@ namespace line_gestao_api.Migrations b.ToTable("Tenants"); }); + modelBuilder.Entity("line_gestao_api.Models.ChipVirgemLine", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("Item") + .HasColumnType("integer"); + + b.Property("NumeroDoChip") + .HasMaxLength(40) + .HasColumnType("character varying(40)"); + + b.Property("Observacoes") + .HasMaxLength(500) + .HasColumnType("character varying(500)"); + + b.Property("TenantId") + .HasColumnType("uuid"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.HasKey("Id"); + + b.HasIndex("Item"); + + b.HasIndex("NumeroDoChip"); + + b.HasIndex("TenantId"); + + b.ToTable("ChipVirgemLines"); + }); + + modelBuilder.Entity("line_gestao_api.Models.ControleRecebidoLine", b => + { + b.Property("Id") + .ValueGeneratedOnAdd() + .HasColumnType("uuid"); + + b.Property("Ano") + .HasColumnType("integer"); + + b.Property("Chip") + .HasMaxLength(40) + .HasColumnType("character varying(40)"); + + b.Property("ConteudoDaNf") + .HasMaxLength(255) + .HasColumnType("character varying(255)"); + + b.Property("CreatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("DataDaNf") + .HasColumnType("timestamp with time zone"); + + b.Property("DataDoRecebimento") + .HasColumnType("timestamp with time zone"); + + b.Property("IsResumo") + .HasColumnType("boolean"); + + b.Property("Item") + .HasColumnType("integer"); + + b.Property("NotaFiscal") + .HasMaxLength(50) + .HasColumnType("character varying(50)"); + + b.Property("NumeroDaLinha") + .HasMaxLength(40) + .HasColumnType("character varying(40)"); + + b.Property("Quantidade") + .HasColumnType("integer"); + + b.Property("Serial") + .HasMaxLength(80) + .HasColumnType("character varying(80)"); + + b.Property("TenantId") + .HasColumnType("uuid"); + + b.Property("UpdatedAt") + .HasColumnType("timestamp with time zone"); + + b.Property("ValorDaNf") + .HasColumnType("numeric"); + + b.Property("ValorUnit") + .HasColumnType("numeric"); + + b.HasKey("Id"); + + b.HasIndex("Ano"); + + b.HasIndex("Chip"); + + b.HasIndex("DataDaNf"); + + b.HasIndex("DataDoRecebimento"); + + b.HasIndex("Item"); + + b.HasIndex("NotaFiscal"); + + b.HasIndex("NumeroDaLinha"); + + b.HasIndex("Serial"); + + b.HasIndex("TenantId"); + + b.ToTable("ControleRecebidoLines"); + }); + modelBuilder.Entity("line_gestao_api.Models.TrocaNumeroLine", b => { b.Property("Id") diff --git a/Models/ChipVirgemLine.cs b/Models/ChipVirgemLine.cs new file mode 100644 index 0000000..1cec669 --- /dev/null +++ b/Models/ChipVirgemLine.cs @@ -0,0 +1,23 @@ +using System; +using System.ComponentModel.DataAnnotations; + +namespace line_gestao_api.Models +{ + public class ChipVirgemLine : ITenantEntity + { + public Guid Id { get; set; } = Guid.NewGuid(); + + public Guid TenantId { get; set; } + + public int Item { get; set; } + + [MaxLength(40)] + public string? NumeroDoChip { get; set; } + + [MaxLength(500)] + public string? Observacoes { get; set; } + + public DateTime CreatedAt { get; set; } = DateTime.UtcNow; + public DateTime UpdatedAt { get; set; } = DateTime.UtcNow; + } +} diff --git a/Models/ControleRecebidoLine.cs b/Models/ControleRecebidoLine.cs new file mode 100644 index 0000000..ba402a2 --- /dev/null +++ b/Models/ControleRecebidoLine.cs @@ -0,0 +1,43 @@ +using System; +using System.ComponentModel.DataAnnotations; + +namespace line_gestao_api.Models +{ + public class ControleRecebidoLine : ITenantEntity + { + public Guid Id { get; set; } = Guid.NewGuid(); + + public Guid TenantId { get; set; } + + public int Ano { get; set; } + public int Item { get; set; } + + [MaxLength(50)] + public string? NotaFiscal { get; set; } + + [MaxLength(40)] + public string? Chip { get; set; } + + [MaxLength(80)] + public string? Serial { get; set; } + + [MaxLength(255)] + public string? ConteudoDaNf { get; set; } + + [MaxLength(40)] + public string? NumeroDaLinha { get; set; } + + public decimal? ValorUnit { get; set; } + public decimal? ValorDaNf { get; set; } + + public DateTime? DataDaNf { get; set; } + public DateTime? DataDoRecebimento { get; set; } + + public int? Quantidade { get; set; } + + public bool IsResumo { get; set; } + + public DateTime CreatedAt { get; set; } = DateTime.UtcNow; + public DateTime UpdatedAt { get; set; } = DateTime.UtcNow; + } +}