Mantenimiento de Miembros
This commit is contained in:
89
RS_system/Services/IFileStorageService.cs
Normal file
89
RS_system/Services/IFileStorageService.cs
Normal 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}";
|
||||
}
|
||||
}
|
||||
37
RS_system/Services/IMiembroService.cs
Normal file
37
RS_system/Services/IMiembroService.cs
Normal 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();
|
||||
}
|
||||
224
RS_system/Services/MiembroService.cs
Normal file
224
RS_system/Services/MiembroService.cs
Normal 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();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user