diff --git a/Controllers/LinesController.cs b/Controllers/LinesController.cs index 5c3c3df..d89bff2 100644 --- a/Controllers/LinesController.cs +++ b/Controllers/LinesController.cs @@ -1346,10 +1346,23 @@ namespace line_gestao_api.Controllers if (ws == null) return; - var headers = ws.RowsUsed() - .Where(IsChipsVirgensHeader) - .OrderBy(r => r.RowNumber()) - .ToList(); + var headers = new List(); + foreach (var rowIndex in new[] { 7, 8 }) + { + var row = ws.Row(rowIndex); + if (IsChipsVirgensHeader(row)) + { + headers.Add(row); + } + } + + if (headers.Count == 0) + { + headers = ws.RowsUsed() + .Where(IsChipsVirgensHeader) + .OrderBy(r => r.RowNumber()) + .ToList(); + } if (headers.Count == 0) return; await _db.ChipVirgemLines.ExecuteDeleteAsync(); @@ -1360,6 +1373,10 @@ namespace line_gestao_api.Controllers for (int i = 0; i < headers.Count; i++) { var headerRow = headers[i]; + var lastCol = headerRow.LastCellUsed()?.Address.ColumnNumber + ?? ws.LastColumnUsed()?.ColumnNumber() + ?? headerRow.LastCellUsed()?.Address.ColumnNumber + ?? 1; var itemColumns = headerRow.CellsUsed() .Where(c => NormalizeHeader(c.GetString()) == "ITEM") .Select(c => c.Address.ColumnNumber) @@ -1368,27 +1385,32 @@ namespace line_gestao_api.Controllers if (itemColumns.Count == 0) continue; var startRow = headerRow.RowNumber() + 1; - var endRow = i + 1 < headers.Count ? headers[i + 1].RowNumber() - 1 : lastRow; + var endRow = lastRow; for (int tableIndex = 0; tableIndex < itemColumns.Count; tableIndex++) { var startCol = itemColumns[tableIndex]; var endCol = tableIndex + 1 < itemColumns.Count ? itemColumns[tableIndex + 1] - 1 - : headerRow.LastCellUsed()?.Address.ColumnNumber ?? startCol; + : lastCol; - var map = BuildHeaderMapRange(headerRow, startCol, endCol); - int colItem = GetCol(map, "ITEM"); - if (colItem == 0) continue; + int colItem = startCol; + int colChip = FindHeaderColumn(headerRow, startCol, endCol, "CHIP"); + int colObs = FindHeaderColumn(headerRow, startCol, endCol, "OBS"); + if (colItem == 0 || colChip == 0 || colObs == 0) continue; for (int r = startRow; r <= endRow; r++) { var itemStr = GetCellString(ws, r, colItem); - if (string.IsNullOrWhiteSpace(itemStr)) continue; + 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 chipRaw = GetCellString(ws, r, colChip); + var numeroChip = NullIfEmptyDigits(chipRaw); + if (string.IsNullOrWhiteSpace(numeroChip) && !string.IsNullOrWhiteSpace(chipRaw)) + { + numeroChip = chipRaw.Trim(); + } + var observacoes = GetCellString(ws, r, colObs); if (string.IsNullOrWhiteSpace(numeroChip) && string.IsNullOrWhiteSpace(observacoes)) { continue; @@ -1459,6 +1481,8 @@ namespace line_gestao_api.Controllers var firstRow = ws.FirstRowUsed()?.RowNumber() ?? 1; var lastRow = ws.LastRowUsed()?.RowNumber() ?? firstRow; var rowIndex = firstRow; + decimal? lastValorDaNf = null; + decimal? lastValorUnit = null; while (rowIndex <= lastRow) { @@ -1481,6 +1505,8 @@ namespace line_gestao_api.Controllers && GetColAny(map, "CHIP") == 0 && GetColAny(map, "SERIAL") == 0; + lastValorDaNf = null; + lastValorUnit = null; rowIndex++; for (; rowIndex <= lastRow; rowIndex++) @@ -1501,9 +1527,25 @@ namespace line_gestao_api.Controllers 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")); + if (valorUnit.HasValue) + { + lastValorUnit = valorUnit; + } + else + { + valorUnit = lastValorUnit; + } 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"); + if (valorDaNf.HasValue) + { + lastValorDaNf = valorDaNf; + } + else + { + valorDaNf = lastValorDaNf; + } + var dataDaNf = TryDateNoUtc(ws, rowIndex, map, "DATA DA NF"); + var dataReceb = TryDateNoUtc(ws, rowIndex, map, "DATA DO RECEBIMENTO"); var qtd = TryNullableInt(GetCellByHeaderAny(ws, rowIndex, map, "QTD.", "QTD", "QUANTIDADE")); var now = DateTime.UtcNow; @@ -1621,15 +1663,17 @@ namespace line_gestao_api.Controllers { var hasItem = false; var hasNumeroChip = false; + var hasObs = false; foreach (var cell in row.CellsUsed()) { var k = NormalizeHeader(cell.GetString()); if (k == "ITEM") hasItem = true; if (k.Contains("CHIP")) hasNumeroChip = true; + if (k.Contains("OBS")) hasObs = true; } - return hasItem && hasNumeroChip; + return hasItem && hasNumeroChip && hasObs; } // ========================================================== @@ -1662,6 +1706,28 @@ namespace line_gestao_api.Controllers return map; } + private static int FindHeaderColumn(IXLRow headerRow, int startCol, int endCol, params string[] headerKeys) + { + var normalizedKeys = headerKeys.Select(NormalizeHeader).Where(k => !string.IsNullOrWhiteSpace(k)).ToArray(); + if (normalizedKeys.Length == 0) return 0; + + for (int col = startCol; col <= endCol; col++) + { + var key = NormalizeHeader(headerRow.Cell(col).GetString()); + if (string.IsNullOrWhiteSpace(key)) continue; + + foreach (var wanted in normalizedKeys) + { + if (key == wanted || key.Contains(wanted)) + { + return col; + } + } + } + + return 0; + } + private static DateTime? ToUtc(DateTime? dt) { if (dt == null) return null; @@ -1765,6 +1831,13 @@ namespace line_gestao_api.Controllers return TryDateCell(ws, row, c); } + private static DateTime? TryDateNoUtc(IXLWorksheet ws, int row, Dictionary map, string header) + { + var k = NormalizeHeader(header); + if (!map.TryGetValue(k, out var c)) return null; + return TryDateCellNoUtc(ws, row, c); + } + private static DateTime? TryDateCell(IXLWorksheet ws, int row, int col) { if (col <= 0) return null; @@ -1786,6 +1859,32 @@ namespace line_gestao_api.Controllers return null; } + private static DateTime? TryDateCellNoUtc(IXLWorksheet ws, int row, int col) + { + if (col <= 0) return null; + + var cell = ws.Cell(row, col); + + if (cell.DataType == XLDataType.DateTime) + return ToUtcDateOnly(cell.GetDateTime()); + + if (cell.TryGetValue(out var dt)) + return ToUtcDateOnly(dt); + + var s = cell.GetValue()?.Trim(); + if (string.IsNullOrWhiteSpace(s)) return null; + + if (DateTime.TryParse(s, new CultureInfo("pt-BR"), DateTimeStyles.None, out var d)) + return ToUtcDateOnly(d); + + return null; + } + + private static DateTime ToUtcDateOnly(DateTime dt) + { + return new DateTime(dt.Year, dt.Month, dt.Day, 12, 0, 0, DateTimeKind.Utc); + } + private static decimal? TryDecimal(string? s) { if (string.IsNullOrWhiteSpace(s)) return null;