line-gestao-api/Controllers/ControleRecebidosController.cs

266 lines
10 KiB
C#

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;
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<ActionResult<PagedResult<ControleRecebidoListDto>>> 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<ControleRecebidoListDto>
{
Page = page,
PageSize = pageSize,
Total = total,
Items = items
});
}
[HttpGet("{id:guid}")]
public async Task<ActionResult<ControleRecebidoDetailDto>> 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<ActionResult<ControleRecebidoDetailDto>> Create([FromBody] CreateControleRecebidoDto req)
{
var now = DateTime.UtcNow;
var ano = req.Ano ?? (req.DataDaNf?.Year ?? DateTime.UtcNow.Year);
var item = req.Item ?? 0;
if (item <= 0)
{
var maxItem = await _db.ControleRecebidoLines
.AsNoTracking()
.Where(x => x.Ano == ano)
.MaxAsync(x => (int?)x.Item) ?? 0;
item = maxItem + 1;
}
var quantidade = req.Quantidade;
var valorUnit = req.ValorUnit;
var valorDaNf = req.ValorDaNf;
if (!valorDaNf.HasValue && valorUnit.HasValue && quantidade.HasValue)
{
valorDaNf = Math.Round(valorUnit.Value * quantidade.Value, 2);
}
else if (!valorUnit.HasValue && valorDaNf.HasValue && quantidade.HasValue && quantidade.Value > 0)
{
valorUnit = Math.Round(valorDaNf.Value / quantidade.Value, 2);
}
var e = new ControleRecebidoLine
{
Id = Guid.NewGuid(),
Ano = ano,
Item = item,
NotaFiscal = TrimOrNull(req.NotaFiscal),
Chip = NullIfEmptyDigits(req.Chip),
Serial = TrimOrNull(req.Serial),
ConteudoDaNf = TrimOrNull(req.ConteudoDaNf),
NumeroDaLinha = NullIfEmptyDigits(req.NumeroDaLinha),
ValorUnit = valorUnit,
ValorDaNf = valorDaNf,
DataDaNf = ToUtc(req.DataDaNf),
DataDoRecebimento = ToUtc(req.DataDoRecebimento),
Quantidade = 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}")]
[Authorize(Roles = "admin")]
public async Task<IActionResult> 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}")]
[Authorize(Roles = "admin")]
public async Task<IActionResult> 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();
}
}
}