Mantenimiento de Miembros

This commit is contained in:
2026-01-13 21:02:34 -06:00
parent 06470a9173
commit 75aac3b273
50 changed files with 1440 additions and 1145 deletions

View File

@@ -0,0 +1,89 @@
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Hosting;
using System.IO;
using System.Threading.Tasks;
namespace Rs_system.Services;
public interface IFileStorageService
{
Task<string> SaveFileAsync(IFormFile file, string folderName);
Task<bool> DeleteFileAsync(string filePath);
string GetFileUrl(string filePath);
}
public class FileStorageService : IFileStorageService
{
private readonly IHostEnvironment _environment;
private readonly string _uploadsFolder;
public FileStorageService(IHostEnvironment environment)
{
_environment = environment;
_uploadsFolder = Path.Combine(_environment.ContentRootPath, "wwwroot", "uploads");
// Ensure uploads folder exists
if (!Directory.Exists(_uploadsFolder))
{
Directory.CreateDirectory(_uploadsFolder);
}
}
public async Task<string> SaveFileAsync(IFormFile file, string folderName)
{
if (file == null || file.Length == 0)
return string.Empty;
// Create folder if it doesn't exist
var folderPath = Path.Combine(_uploadsFolder, folderName);
if (!Directory.Exists(folderPath))
{
Directory.CreateDirectory(folderPath);
}
// Generate unique filename
var fileExtension = Path.GetExtension(file.FileName);
var fileName = $"{Guid.NewGuid()}{fileExtension}";
var filePath = Path.Combine(folderPath, fileName);
// Save file
using (var stream = new FileStream(filePath, FileMode.Create))
{
await file.CopyToAsync(stream);
}
// Return relative path for database storage
return Path.Combine("uploads", folderName, fileName).Replace("\\", "/");
}
public async Task<bool> DeleteFileAsync(string filePath)
{
if (string.IsNullOrEmpty(filePath))
return true;
try
{
var fullPath = Path.Combine(_environment.ContentRootPath, "wwwroot", filePath);
if (File.Exists(fullPath))
{
await Task.Run(() => File.Delete(fullPath));
return true;
}
return true; // File doesn't exist, consider it deleted
}
catch
{
return false;
}
}
public string GetFileUrl(string filePath)
{
if (string.IsNullOrEmpty(filePath))
return string.Empty;
return $"/{filePath}";
}
}

View File

@@ -0,0 +1,37 @@
using Microsoft.AspNetCore.Http;
using Rs_system.Models.ViewModels;
namespace Rs_system.Services;
public interface IMiembroService
{
/// <summary>
/// Gets all active members with their work group information
/// </summary>
Task<IEnumerable<MiembroViewModel>> GetAllAsync();
/// <summary>
/// Gets a member by ID
/// </summary>
Task<MiembroViewModel?> GetByIdAsync(long id);
/// <summary>
/// Creates a new member
/// </summary>
Task<bool> CreateAsync(MiembroViewModel viewModel, string createdBy, IFormFile? fotoFile = null);
/// <summary>
/// Updates an existing member
/// </summary>
Task<bool> UpdateAsync(long id, MiembroViewModel viewModel, IFormFile? fotoFile = null);
/// <summary>
/// Soft deletes a member
/// </summary>
Task<bool> DeleteAsync(long id);
/// <summary>
/// Gets all active work groups for dropdown
/// </summary>
Task<IEnumerable<(long Id, string Nombre)>> GetGruposTrabajoAsync();
}

View File

@@ -0,0 +1,224 @@
using Microsoft.AspNetCore.Http;
using Microsoft.EntityFrameworkCore;
using Rs_system.Data;
using Rs_system.Models;
using Rs_system.Models.ViewModels;
namespace Rs_system.Services;
public class MiembroService : IMiembroService
{
private readonly ApplicationDbContext _context;
private readonly IFileStorageService _fileStorageService;
public MiembroService(ApplicationDbContext context, IFileStorageService fileStorageService)
{
_context = context;
_fileStorageService = fileStorageService;
}
public async Task<IEnumerable<MiembroViewModel>> GetAllAsync()
{
return await _context.Miembros
.Include(m => m.Persona)
.Include(m => m.GrupoTrabajo)
.Where(m => !m.Eliminado && m.Activo)
.OrderBy(m => m.Persona.Apellidos)
.ThenBy(m => m.Persona.Nombres)
.Select(m => new MiembroViewModel
{
Id = m.Id,
Nombres = m.Persona.Nombres,
Apellidos = m.Persona.Apellidos,
FechaNacimiento = m.Persona.FechaNacimiento,
BautizadoEspirituSanto = m.BautizadoEspirituSanto,
Direccion = m.Persona.Direccion,
FechaIngresoCongregacion = m.FechaIngresoCongregacion,
Telefono = m.Persona.Telefono,
TelefonoEmergencia = m.TelefonoEmergencia,
GrupoTrabajoId = m.GrupoTrabajoId,
GrupoTrabajoNombre = m.GrupoTrabajo != null ? m.GrupoTrabajo.Nombre : null,
Activo = m.Activo,
FotoUrl = m.Persona.FotoUrl
})
.ToListAsync();
}
public async Task<MiembroViewModel?> GetByIdAsync(long id)
{
var miembro = await _context.Miembros
.Include(m => m.Persona)
.Include(m => m.GrupoTrabajo)
.FirstOrDefaultAsync(m => m.Id == id && !m.Eliminado);
if (miembro == null)
return null;
return new MiembroViewModel
{
Id = miembro.Id,
Nombres = miembro.Persona.Nombres,
Apellidos = miembro.Persona.Apellidos,
FechaNacimiento = miembro.Persona.FechaNacimiento,
BautizadoEspirituSanto = miembro.BautizadoEspirituSanto,
Direccion = miembro.Persona.Direccion,
FechaIngresoCongregacion = miembro.FechaIngresoCongregacion,
Telefono = miembro.Persona.Telefono,
TelefonoEmergencia = miembro.TelefonoEmergencia,
GrupoTrabajoId = miembro.GrupoTrabajoId,
GrupoTrabajoNombre = miembro.GrupoTrabajo?.Nombre,
Activo = miembro.Activo,
FotoUrl = miembro.Persona.FotoUrl
};
}
public async Task<bool> CreateAsync(MiembroViewModel viewModel, string createdBy, IFormFile? fotoFile = null)
{
var strategy = _context.Database.CreateExecutionStrategy();
try
{
await strategy.ExecuteAsync(async () =>
{
using var transaction = await _context.Database.BeginTransactionAsync();
// Handle photo upload
string? fotoUrl = null;
if (fotoFile != null)
{
fotoUrl = await _fileStorageService.SaveFileAsync(fotoFile, "miembros");
}
// 1. Create Persona
var persona = new Persona
{
Nombres = viewModel.Nombres,
Apellidos = viewModel.Apellidos,
FechaNacimiento = viewModel.FechaNacimiento,
Direccion = viewModel.Direccion,
Telefono = viewModel.Telefono,
FotoUrl = fotoUrl,
Activo = true,
CreadoEn = DateTime.UtcNow,
ActualizadoEn = DateTime.UtcNow
};
_context.Personas.Add(persona);
await _context.SaveChangesAsync();
// 2. Create Miembro linked to Persona
var miembro = new Miembro
{
PersonaId = persona.Id,
BautizadoEspirituSanto = viewModel.BautizadoEspirituSanto,
FechaIngresoCongregacion = viewModel.FechaIngresoCongregacion,
TelefonoEmergencia = viewModel.TelefonoEmergencia,
GrupoTrabajoId = viewModel.GrupoTrabajoId,
Activo = viewModel.Activo,
CreadoPor = createdBy,
CreadoEn = DateTime.UtcNow,
ActualizadoEn = DateTime.UtcNow
};
_context.Miembros.Add(miembro);
await _context.SaveChangesAsync();
await transaction.CommitAsync();
});
return true;
}
catch (Exception ex)
{
// Log exception here if logger is available
Console.WriteLine(ex.Message);
return false;
}
}
public async Task<bool> UpdateAsync(long id, MiembroViewModel viewModel, IFormFile? fotoFile = null)
{
var strategy = _context.Database.CreateExecutionStrategy();
try
{
await strategy.ExecuteAsync(async () =>
{
using var transaction = await _context.Database.BeginTransactionAsync();
var miembro = await _context.Miembros
.Include(m => m.Persona)
.FirstOrDefaultAsync(m => m.Id == id && !m.Eliminado);
if (miembro == null)
throw new InvalidOperationException("Miembro no encontrado");
// Handle photo upload
if (fotoFile != null)
{
// Delete old photo if exists
if (!string.IsNullOrEmpty(miembro.Persona.FotoUrl))
{
await _fileStorageService.DeleteFileAsync(miembro.Persona.FotoUrl);
}
// Save new photo
miembro.Persona.FotoUrl = await _fileStorageService.SaveFileAsync(fotoFile, "miembros");
}
// Update Persona
miembro.Persona.Nombres = viewModel.Nombres;
miembro.Persona.Apellidos = viewModel.Apellidos;
miembro.Persona.FechaNacimiento = viewModel.FechaNacimiento;
miembro.Persona.Direccion = viewModel.Direccion;
miembro.Persona.Telefono = viewModel.Telefono;
miembro.Persona.ActualizadoEn = DateTime.UtcNow;
// Update Miembro
miembro.BautizadoEspirituSanto = viewModel.BautizadoEspirituSanto;
miembro.FechaIngresoCongregacion = viewModel.FechaIngresoCongregacion;
miembro.TelefonoEmergencia = viewModel.TelefonoEmergencia;
miembro.GrupoTrabajoId = viewModel.GrupoTrabajoId;
miembro.Activo = viewModel.Activo;
miembro.ActualizadoEn = DateTime.UtcNow;
await _context.SaveChangesAsync();
await transaction.CommitAsync();
});
return true;
}
catch
{
return false;
}
}
public async Task<bool> DeleteAsync(long id)
{
try
{
var miembro = await _context.Miembros.FindAsync(id);
if (miembro == null || miembro.Eliminado)
return false;
miembro.Eliminado = true;
miembro.ActualizadoEn = DateTime.UtcNow;
await _context.SaveChangesAsync();
return true;
}
catch
{
return false;
}
}
public async Task<IEnumerable<(long Id, string Nombre)>> GetGruposTrabajoAsync()
{
return await _context.GruposTrabajo
.Where(g => g.Activo)
.OrderBy(g => g.Nombre)
.Select(g => new ValueTuple<long, string>(g.Id, g.Nombre))
.ToListAsync();
}
}