using foodmarket.Application.Catalog; using foodmarket.Application.Common; using foodmarket.Domain.Catalog; using foodmarket.Infrastructure.Persistence; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; namespace foodmarket.Api.Controllers.Catalog; [ApiController] [Authorize] [Route("api/catalog/countries")] public class CountriesController : ControllerBase { private readonly AppDbContext _db; public CountriesController(AppDbContext db) => _db = db; [HttpGet] public async Task>> List([FromQuery] PagedRequest req, CancellationToken ct) { var q = _db.Countries.Include(c => c.DefaultCurrency).AsNoTracking().AsQueryable(); if (!string.IsNullOrWhiteSpace(req.Search)) { var s = req.Search.Trim().ToLower(); q = q.Where(c => c.Name.ToLower().Contains(s) || c.Code.ToLower().Contains(s)); } var total = await q.CountAsync(ct); q = (req.Sort, req.Desc) switch { ("code", false) => q.OrderBy(c => c.Code), ("code", true) => q.OrderByDescending(c => c.Code), ("currency", false) => q.OrderBy(c => c.DefaultCurrency != null ? c.DefaultCurrency.Code : null).ThenBy(c => c.Name), ("currency", true) => q.OrderByDescending(c => c.DefaultCurrency != null ? c.DefaultCurrency.Code : null).ThenBy(c => c.Name), ("vatRate", false) => q.OrderBy(c => c.VatRate).ThenBy(c => c.Name), ("vatRate", true) => q.OrderByDescending(c => c.VatRate).ThenBy(c => c.Name), ("name", true) => q.OrderByDescending(c => c.Name), _ => q.OrderBy(c => c.Name), }; var items = await q .Skip(req.Skip).Take(req.Take) .Select(c => new CountryDto( c.Id, c.Code, c.Name, c.DefaultCurrencyId, c.DefaultCurrency != null ? c.DefaultCurrency.Code : null, c.DefaultCurrency != null ? c.DefaultCurrency.Symbol : null, c.VatRate)) .ToListAsync(ct); return new PagedResult { Items = items, Total = total, Page = req.Page, PageSize = req.Take }; } [HttpGet("{id:guid}")] public async Task> Get(Guid id, CancellationToken ct) { var c = await _db.Countries.Include(x => x.DefaultCurrency).AsNoTracking().FirstOrDefaultAsync(x => x.Id == id, ct); return c is null ? NotFound() : Project(c); } [HttpPost, Authorize(Roles = "SuperAdmin")] public async Task> Create([FromBody] CountryInput input, CancellationToken ct) { var e = new Country { Code = input.Code.Trim().ToUpper(), Name = input.Name, DefaultCurrencyId = input.DefaultCurrencyId, VatRate = input.VatRate, }; _db.Countries.Add(e); await _db.SaveChangesAsync(ct); await _db.Entry(e).Reference(x => x.DefaultCurrency).LoadAsync(ct); return CreatedAtAction(nameof(Get), new { id = e.Id }, Project(e)); } [HttpPut("{id:guid}"), Authorize(Roles = "SuperAdmin")] public async Task Update(Guid id, [FromBody] CountryInput input, CancellationToken ct) { var e = await _db.Countries.FirstOrDefaultAsync(x => x.Id == id, ct); if (e is null) return NotFound(); e.Code = input.Code.Trim().ToUpper(); e.Name = input.Name; e.DefaultCurrencyId = input.DefaultCurrencyId; e.VatRate = input.VatRate; await _db.SaveChangesAsync(ct); return NoContent(); } [HttpDelete("{id:guid}"), Authorize(Roles = "SuperAdmin")] public async Task Delete(Guid id, CancellationToken ct) { var e = await _db.Countries.FirstOrDefaultAsync(x => x.Id == id, ct); if (e is null) return NotFound(); _db.Countries.Remove(e); await _db.SaveChangesAsync(ct); return NoContent(); } private static CountryDto Project(Country c) => new( c.Id, c.Code, c.Name, c.DefaultCurrencyId, c.DefaultCurrency?.Code, c.DefaultCurrency?.Symbol, c.VatRate); }