This commit is contained in:
Eduardo Lopes 2026-02-02 10:10:27 -03:00 committed by GitHub
commit 95b596bf5f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 158 additions and 0 deletions

View File

@ -1,5 +1,7 @@
using ClosedXML.Excel;
using line_gestao_api.Data;
using line_gestao_api.Dtos;
using line_gestao_api.Models;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.EntityFrameworkCore;
@ -68,4 +70,160 @@ public class NotificationsController : ControllerBase
return NoContent();
}
[HttpPatch("read-all")]
[HttpPatch("/notifications/read-all")]
public async Task<IActionResult> MarkAllAsRead(
[FromQuery] string? filter,
[FromBody] NotificationSelectionRequest? request)
{
var utcNow = DateTime.UtcNow;
var query = ApplySelectionAndFilter(_db.Notifications, filter, request?.NotificationIds)
.Where(n => !n.Lida);
await query.ExecuteUpdateAsync(updates => updates
.SetProperty(n => n.Lida, true)
.SetProperty(n => n.LidaEm, utcNow));
return NoContent();
}
[HttpGet("export")]
[HttpGet("/notifications/export")]
public async Task<IActionResult> ExportNotifications([FromQuery] string? filter)
{
var query = ApplySelectionAndFilter(_db.Notifications.AsNoTracking(), filter, null);
return await ExportNotificationsAsync(query, filter);
}
[HttpPost("export")]
[HttpPost("/notifications/export")]
public async Task<IActionResult> ExportNotifications(
[FromQuery] string? filter,
[FromBody] NotificationSelectionRequest? request)
{
var query = ApplySelectionAndFilter(_db.Notifications.AsNoTracking(), filter, request?.NotificationIds);
return await ExportNotificationsAsync(query, filter);
}
private async Task<IActionResult> ExportNotificationsAsync(IQueryable<Notification> query, string? filter)
{
var rows = await (
from notification in query
join vigencia in _db.VigenciaLines.AsNoTracking()
on notification.VigenciaLineId equals vigencia.Id into vigencias
from vigencia in vigencias.DefaultIfEmpty()
orderby notification.ReferenciaData descending, notification.Data descending
select new NotificationExportRow(
notification.Linha ?? vigencia.Linha,
notification.Cliente ?? vigencia.Cliente,
notification.Usuario ?? vigencia.Usuario,
notification.ReferenciaData ?? vigencia.DtTerminoFidelizacao,
notification.Tipo))
.ToListAsync();
using var workbook = new XLWorkbook();
var worksheet = workbook.Worksheets.Add("Notificacoes");
var normalizedFilter = NormalizeFilter(filter);
var dateHeader = normalizedFilter switch
{
"vencidas" or "vencido" => "Data da Expiração",
"a-vencer" or "avencer" => "Data a Vencer",
_ => "Data de Referência"
};
var headers = new[]
{
"Número da Linha",
"Cliente",
"Usuário",
dateHeader,
"Status"
};
for (var i = 0; i < headers.Length; i++)
{
worksheet.Cell(1, i + 1).Value = headers[i];
}
var headerRange = worksheet.Range(1, 1, 1, headers.Length);
headerRange.Style.Font.Bold = true;
headerRange.Style.Fill.BackgroundColor = XLColor.LightGray;
headerRange.Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Center;
for (var i = 0; i < rows.Count; i++)
{
var row = rows[i];
var rowIndex = i + 2;
worksheet.Cell(rowIndex, 1).Value = row.Linha ?? string.Empty;
worksheet.Cell(rowIndex, 2).Value = row.Cliente ?? string.Empty;
worksheet.Cell(rowIndex, 3).Value = row.Usuario ?? string.Empty;
worksheet.Cell(rowIndex, 4).Value = row.DataReferencia;
worksheet.Cell(rowIndex, 5).Value = row.Tipo;
}
worksheet.Column(1).Width = 18;
worksheet.Column(2).Width = 26;
worksheet.Column(3).Width = 24;
worksheet.Column(4).Width = 20;
worksheet.Column(5).Width = 14;
worksheet.Column(4).Style.DateFormat.Format = "dd/MM/yyyy";
worksheet.Columns().AdjustToContents();
using var stream = new MemoryStream();
workbook.SaveAs(stream);
stream.Position = 0;
var fileName = $"notificacoes-{DateTime.UtcNow:yyyyMMddHHmmss}.xlsx";
return File(
stream.ToArray(),
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
fileName);
}
private static IQueryable<Notification> ApplySelectionAndFilter(
IQueryable<Notification> query,
string? filter,
IReadOnlyCollection<Guid>? notificationIds)
{
query = ApplyFilter(query, filter);
if (notificationIds is { Count: > 0 })
{
query = query.Where(n => notificationIds.Contains(n.Id));
}
return query;
}
private static IQueryable<Notification> ApplyFilter(IQueryable<Notification> query, string? filter)
{
var normalized = NormalizeFilter(filter);
return normalized switch
{
"a-vencer" or "avencer" => query.Where(n => n.Tipo == "AVencer"),
"vencidas" or "vencido" => query.Where(n => n.Tipo == "Vencido"),
_ => query
};
}
private static string? NormalizeFilter(string? filter)
{
return filter?.Trim().ToLowerInvariant();
}
private sealed record NotificationExportRow(
string? Linha,
string? Cliente,
string? Usuario,
DateTime? DataReferencia,
string Tipo);
public sealed class NotificationSelectionRequest
{
public List<Guid>? NotificationIds { get; set; }
}
}