181 lines
		
	
	
		
			6.1 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
		
		
			
		
	
	
			181 lines
		
	
	
		
			6.1 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
|  | // src/Elecciones.Api/Controllers/AdminController.cs | ||
|  | using Elecciones.Database; | ||
|  | using Microsoft.AspNetCore.Mvc; | ||
|  | using Microsoft.EntityFrameworkCore; | ||
|  | using Elecciones.Core.DTOs.ApiRequests; | ||
|  | using Elecciones.Database.Entities; | ||
|  | using Microsoft.AspNetCore.Authorization; | ||
|  | using Elecciones.Core.Enums; | ||
|  | 
 | ||
|  | namespace Elecciones.Api.Controllers; | ||
|  | 
 | ||
|  | [ApiController] | ||
|  | [Route("api/[controller]")]
 | ||
|  | [Authorize] | ||
|  | public class AdminController : ControllerBase | ||
|  | { | ||
|  |   private readonly EleccionesDbContext _dbContext; | ||
|  |   private readonly ILogger<AdminController> _logger; | ||
|  | 
 | ||
|  |   public AdminController(EleccionesDbContext dbContext, ILogger<AdminController> logger) | ||
|  |   { | ||
|  |     _dbContext = dbContext; | ||
|  |     _logger = logger; | ||
|  |   } | ||
|  | 
 | ||
|  |   // Endpoint para obtener todas las agrupaciones para el panel de admin | ||
|  |   [HttpGet("agrupaciones")] | ||
|  |   public async Task<IActionResult> GetAgrupaciones() | ||
|  |   { | ||
|  |     var agrupaciones = await _dbContext.AgrupacionesPoliticas | ||
|  |         .AsNoTracking() | ||
|  |         .OrderBy(a => a.Nombre) | ||
|  |         .ToListAsync(); | ||
|  | 
 | ||
|  |     return Ok(agrupaciones); | ||
|  |   } | ||
|  | 
 | ||
|  |   [HttpPut("agrupaciones/{id}")] | ||
|  |   public async Task<IActionResult> UpdateAgrupacion(string id, [FromBody] UpdateAgrupacionDto agrupacionDto) | ||
|  |   { | ||
|  |     // Buscamos la agrupación en la base de datos por su ID. | ||
|  |     var agrupacion = await _dbContext.AgrupacionesPoliticas.FindAsync(id); | ||
|  | 
 | ||
|  |     if (agrupacion == null) | ||
|  |     { | ||
|  |       // Si no existe, devolvemos un error 404 Not Found. | ||
|  |       return NotFound(new { message = $"No se encontró la agrupación con ID {id}" }); | ||
|  |     } | ||
|  | 
 | ||
|  |     // Actualizamos las propiedades de la entidad con los valores del DTO. | ||
|  |     agrupacion.NombreCorto = agrupacionDto.NombreCorto; | ||
|  |     agrupacion.Color = agrupacionDto.Color; | ||
|  |     agrupacion.LogoUrl = agrupacionDto.LogoUrl; | ||
|  | 
 | ||
|  |     // Guardamos los cambios en la base de datos. | ||
|  |     await _dbContext.SaveChangesAsync(); | ||
|  |     _logger.LogInformation("Se actualizó la agrupación: {Id}", id); | ||
|  | 
 | ||
|  |     // Devolvemos una respuesta 204 No Content, que es el estándar para un PUT exitoso sin devolver datos. | ||
|  |     return NoContent(); | ||
|  |   } | ||
|  | 
 | ||
|  |   [HttpPut("agrupaciones/orden-diputados")] | ||
|  |   public async Task<IActionResult> UpdateDiputadosOrden([FromBody] List<string> idsAgrupacionesOrdenadas) | ||
|  |   { | ||
|  |     // Reseteamos solo el orden de diputados | ||
|  |     await _dbContext.AgrupacionesPoliticas.ExecuteUpdateAsync(s => s.SetProperty(a => a.OrdenDiputados, (int?)null)); | ||
|  | 
 | ||
|  |     for (int i = 0; i < idsAgrupacionesOrdenadas.Count; i++) | ||
|  |     { | ||
|  |       var agrupacion = await _dbContext.AgrupacionesPoliticas.FindAsync(idsAgrupacionesOrdenadas[i]); | ||
|  |       if (agrupacion != null) agrupacion.OrdenDiputados = i + 1; | ||
|  |     } | ||
|  |     await _dbContext.SaveChangesAsync(); | ||
|  |     return Ok(); | ||
|  |   } | ||
|  | 
 | ||
|  |   [HttpPut("agrupaciones/orden-senadores")] | ||
|  |   public async Task<IActionResult> UpdateSenadoresOrden([FromBody] List<string> idsAgrupacionesOrdenadas) | ||
|  |   { | ||
|  |     // Reseteamos solo el orden de senadores | ||
|  |     await _dbContext.AgrupacionesPoliticas.ExecuteUpdateAsync(s => s.SetProperty(a => a.OrdenSenadores, (int?)null)); | ||
|  | 
 | ||
|  |     for (int i = 0; i < idsAgrupacionesOrdenadas.Count; i++) | ||
|  |     { | ||
|  |       var agrupacion = await _dbContext.AgrupacionesPoliticas.FindAsync(idsAgrupacionesOrdenadas[i]); | ||
|  |       if (agrupacion != null) agrupacion.OrdenSenadores = i + 1; | ||
|  |     } | ||
|  |     await _dbContext.SaveChangesAsync(); | ||
|  |     return Ok(); | ||
|  |   } | ||
|  | 
 | ||
|  |   // LEER todas las configuraciones | ||
|  |   [HttpGet("configuracion")] | ||
|  |   public async Task<IActionResult> GetConfiguracion() | ||
|  |   { | ||
|  |     var configs = await _dbContext.Configuraciones.AsNoTracking().ToListAsync(); | ||
|  |     // Devolvemos un diccionario para que sea fácil de consumir en el frontend | ||
|  |     return Ok(configs.ToDictionary(c => c.Clave, c => c.Valor)); | ||
|  |   } | ||
|  | 
 | ||
|  |   // GUARDAR un conjunto de configuraciones | ||
|  |   [HttpPut("configuracion")] | ||
|  |   public async Task<IActionResult> UpdateConfiguracion([FromBody] Dictionary<string, string> nuevasConfiguraciones) | ||
|  |   { | ||
|  |     foreach (var kvp in nuevasConfiguraciones) | ||
|  |     { | ||
|  |       var config = await _dbContext.Configuraciones.FindAsync(kvp.Key); | ||
|  |       if (config == null) | ||
|  |       { | ||
|  |         // Si no existe, la creamos | ||
|  |         _dbContext.Configuraciones.Add(new Configuracion { Clave = kvp.Key, Valor = kvp.Value }); | ||
|  |       } | ||
|  |       else | ||
|  |       { | ||
|  |         // Si existe, la actualizamos | ||
|  |         config.Valor = kvp.Value; | ||
|  |       } | ||
|  |     } | ||
|  |     await _dbContext.SaveChangesAsync(); | ||
|  |     return NoContent(); | ||
|  |   } | ||
|  | 
 | ||
|  |   // LEER: Obtener todas las bancadas para una cámara, con su partido y ocupante actual | ||
|  |   [HttpGet("bancadas/{camara}")] | ||
|  |   public async Task<IActionResult> GetBancadas(TipoCamara camara) | ||
|  |   { | ||
|  |     var bancadas = await _dbContext.Bancadas | ||
|  |         .AsNoTracking() | ||
|  |         .Include(b => b.AgrupacionPolitica) | ||
|  |         .Include(b => b.Ocupante) | ||
|  |         .Where(b => b.Camara == camara) | ||
|  |         .OrderBy(b => b.Id) // Ordenar por ID para consistencia | ||
|  |         .ToListAsync(); | ||
|  | 
 | ||
|  |     return Ok(bancadas); | ||
|  |   } | ||
|  | 
 | ||
|  |   // ACTUALIZAR: Asignar un partido y/o un ocupante a una bancada específica | ||
|  |   [HttpPut("bancadas/{bancadaId}")] | ||
|  |   public async Task<IActionResult> UpdateBancada(int bancadaId, [FromBody] UpdateBancadaDto dto) | ||
|  |   { | ||
|  |     var bancada = await _dbContext.Bancadas | ||
|  |         .Include(b => b.Ocupante) | ||
|  |         .FirstOrDefaultAsync(b => b.Id == bancadaId); | ||
|  | 
 | ||
|  |     if (bancada == null) | ||
|  |     { | ||
|  |       return NotFound(new { message = "La bancada especificada no existe." }); | ||
|  |     } | ||
|  | 
 | ||
|  |     // 1. Actualizar la agrupación de la bancada | ||
|  |     bancada.AgrupacionPoliticaId = dto.AgrupacionPoliticaId; | ||
|  | 
 | ||
|  |     // 2. Lógica de "Upsert" (Update/Insert/Delete) para el ocupante | ||
|  |     if (string.IsNullOrEmpty(dto.NombreOcupante)) | ||
|  |     { | ||
|  |       // Si no se envía nombre, se elimina el ocupante existente | ||
|  |       if (bancada.Ocupante != null) | ||
|  |       { | ||
|  |         _dbContext.OcupantesBancas.Remove(bancada.Ocupante); | ||
|  |       } | ||
|  |     } | ||
|  |     else | ||
|  |     { | ||
|  |       // Si se envía un nombre, se crea o actualiza el ocupante | ||
|  |       if (bancada.Ocupante == null) | ||
|  |       { | ||
|  |         bancada.Ocupante = new OcupanteBanca(); // Crea uno nuevo si no existía | ||
|  |       } | ||
|  |       bancada.Ocupante.NombreOcupante = dto.NombreOcupante; | ||
|  |       bancada.Ocupante.FotoUrl = dto.FotoUrl; | ||
|  |       bancada.Ocupante.Periodo = dto.Periodo; | ||
|  |     } | ||
|  | 
 | ||
|  |     await _dbContext.SaveChangesAsync(); | ||
|  |     _logger.LogInformation("Se actualizó la bancada con ID: {BancadaId}", bancadaId); | ||
|  | 
 | ||
|  |     return NoContent(); | ||
|  |   } | ||
|  | } |