335 lines
14 KiB
C#
335 lines
14 KiB
C#
using adas_core.Application.Exceptions;
|
|
using adas_core.Application.Repositories.Interfaces;
|
|
using adas_core.Application.Services.Interfaces;
|
|
using adas_core.Domain.Enums;
|
|
using adas_core.Domain.Models.AppSettings;
|
|
using adas_core.Domain.Models.Filter;
|
|
using adas_core.Domain.Models.MongoModels;
|
|
using Microsoft.Extensions.Options;
|
|
using MongoDB.Bson;
|
|
using MongoDB.Driver;
|
|
using System.Text.RegularExpressions;
|
|
|
|
namespace adas_core.Infrastructure.Repositories;
|
|
|
|
/// <summary>
|
|
/// Repositorio para manejar las operaciones CRUD de ConfigObservation en MongoDB.
|
|
/// </summary>
|
|
public class ConfigObservationRepository : MongoRepository<ConfigObservation>, IConfigObservationRepository
|
|
{
|
|
private readonly ApiSettings _apiSettings;
|
|
private readonly IMasterListServiceFactory _masterListServiceFactory;
|
|
|
|
/// <summary>
|
|
/// Constructor para ConfigObservationRepository, inyecta las dependencias necesarias.
|
|
/// </summary>
|
|
/// <param name="apiSettings">Configuración de la API.</param>
|
|
/// <param name="database">Instancia de la base de datos MongoDB.</param>
|
|
/// <param name="masterListServiceFactory">Fábrica de servicios de lista maestra.</param>
|
|
public ConfigObservationRepository(IOptions<ApiSettings> apiSettings, IMongoDatabase database,
|
|
IMasterListServiceFactory masterListServiceFactory) : base(database)
|
|
{
|
|
_masterListServiceFactory = masterListServiceFactory;
|
|
_apiSettings = apiSettings.Value;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Obtiene el nombre de la colección de MongoDB para ConfigObservation, utilizando la configuración proporcionada o un valor predeterminado.
|
|
/// </summary>
|
|
/// <returns>El nombre de la colección de MongoDB para ConfigObservation.</returns>
|
|
public override string GetCollectionName()
|
|
{
|
|
return _apiSettings.ConfigObservations ?? "config_observations";
|
|
}
|
|
|
|
/// <summary>
|
|
/// Busca un ConfigObservation por su ID en la base de datos MongoDB.
|
|
/// </summary>
|
|
/// <param name="id">El ID del ConfigObservation a buscar.</param>
|
|
/// <returns>El ConfigObservation encontrado, o null si no se encuentra.</returns>
|
|
public async Task<ConfigObservation?> FindById(ObjectId id)
|
|
{
|
|
var result = await Collection.FindAsync(Builders<ConfigObservation>.Filter.Eq(x => x.Id, id));
|
|
return await result.FirstOrDefaultAsync();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Actualiza un ConfigObservation existente en la base de datos MongoDB.
|
|
/// </summary>
|
|
/// <param name="configObservation">El ConfigObservation con los datos actualizados.</param>
|
|
/// <returns>El ConfigObservation actualizado, o null si no se encuentra.</returns>
|
|
public async Task<ConfigObservation?> Update(ConfigObservation configObservation)
|
|
{
|
|
await UpdateOneAsync(configObservation.Id, configObservation);
|
|
return configObservation;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Elimina un ConfigObservation por su ID en la base de datos MongoDB.
|
|
/// </summary>
|
|
/// <param name="id"></param>
|
|
/// <returns></returns>
|
|
public async Task<ConfigObservation?> Delete(ObjectId id)
|
|
{
|
|
return await DeleteAsync(id);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Busca todos los IDs de ConfigObservation en la base de datos MongoDB.
|
|
/// </summary>
|
|
/// <returns>Una lista de todos los IDs de ConfigObservation.</returns>
|
|
public async Task<List<ObjectId>> FindAllIds()
|
|
{
|
|
var allCollection = await Collection.FindAsync(_ => true);
|
|
|
|
return allCollection.ToList().Select(item => item.Id).ToList();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Busca todos los ConfigObservation en la base de datos MongoDB.
|
|
/// </summary>
|
|
/// <returns>Una colección de todos los ConfigObservation.</returns>
|
|
public async Task<ICollection<ConfigObservation>> FindAll()
|
|
{
|
|
var result = await Collection.FindAsync(_ => true);
|
|
return await result.ToListAsync();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Busca todos los nombres de ConfigObservation en la base de datos MongoDB, eliminando duplicados y espacios en blanco.
|
|
/// </summary>
|
|
/// <param name="id">El ID del ConfigObservation para filtrar los nombres (opcional).</param>
|
|
/// <returns>Una lista de nombres de ConfigObservation.</returns>
|
|
public async Task<List<string>> GetConfigNames(string id)
|
|
{
|
|
var allConfigs = await Collection.Find(_ => true).ToListAsync();
|
|
|
|
var distinctNames = allConfigs
|
|
.Where(item => !string.IsNullOrWhiteSpace(item.Name))
|
|
.Select(item => item.Name!.Trim())
|
|
.Distinct(StringComparer.OrdinalIgnoreCase)
|
|
.ToList();
|
|
|
|
return distinctNames;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Busca todos los nombres de ConfigObservation en la base de datos MongoDB, eliminando duplicados y espacios en blanco.
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public async Task<List<string>> GetConfigNames()
|
|
{
|
|
var allConfigs = await Collection.Find(_ => true).ToListAsync();
|
|
|
|
var distinctNames = allConfigs
|
|
.Where(item => !string.IsNullOrWhiteSpace(item.Name))
|
|
.Select(item => item.Name!.Trim())
|
|
.Distinct(StringComparer.OrdinalIgnoreCase)
|
|
.ToList();
|
|
|
|
return distinctNames;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Cuenta el número total de ConfigObservation en la base de datos MongoDB.
|
|
/// </summary>
|
|
/// <returns>El número total de ConfigObservation.</returns>
|
|
public async Task<long> Count()
|
|
{
|
|
var filter = Builders<ConfigObservation>.Filter.Empty;
|
|
var result = await Collection.CountDocumentsAsync(filter);
|
|
return result;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Busca ConfigObservation en la base de datos MongoDB utilizando paginación y un filtro de texto opcional que busca en varios campos.
|
|
/// </summary>
|
|
/// <param name="filter">El filtro de paginación y búsqueda.</param>
|
|
/// <returns>Una colección de ConfigObservation que cumple con los criterios de búsqueda y paginación.</returns>
|
|
/// <exception cref="BadRequestException">Se lanza cuando el texto de búsqueda es demasiado largo.</exception>
|
|
public async Task<ICollection<ConfigObservation>> GetPaginatedItems(PaginationFilter filter)
|
|
{
|
|
var builder = Builders<ConfigObservation>.Filter;
|
|
var filterDefinition = builder.Empty;
|
|
|
|
if (!string.IsNullOrWhiteSpace(filter.FilteredRequest?.Text))
|
|
{
|
|
var searchText = filter.FilteredRequest.Text;
|
|
|
|
if (searchText.Length > 100)
|
|
throw new BadRequestException("Search text too long");
|
|
|
|
var searchTextEscaped = Regex.Escape(searchText);
|
|
|
|
var regex = new BsonRegularExpression(searchTextEscaped, "i");
|
|
|
|
var searchFilters = new List<FilterDefinition<ConfigObservation>>
|
|
{
|
|
builder.Regex(x => x.Name, regex),
|
|
builder.Regex(x => x.CodingSystem, regex),
|
|
builder.Regex(x => x.OriginalName, regex),
|
|
builder.Regex(x => x.Code, regex),
|
|
builder.Regex("uiConfiguration.screenLabel", regex)
|
|
};
|
|
|
|
filterDefinition = builder.Or(searchFilters);
|
|
}
|
|
|
|
var sortDefinition = Builders<ConfigObservation>.Sort.Ascending(x => x.Name);
|
|
|
|
var skip = Math.Max(0, (filter.PageNumber - 1) * filter.PageSize);
|
|
var limit = Math.Min(filter.PageSize, 100); // límite defensivo
|
|
|
|
var items = await Collection
|
|
.Find(filterDefinition)
|
|
.Sort(sortDefinition)
|
|
.Skip(skip)
|
|
.Limit(limit)
|
|
.ToListAsync();
|
|
|
|
return items;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Busca un ConfigObservation por su nombre en la base de datos MongoDB, utilizando una búsqueda insensible a mayúsculas y minúsculas.
|
|
/// </summary>
|
|
/// <param name="name">El nombre del ConfigObservation a buscar.</param>
|
|
/// <returns>El ConfigObservation que coincide con el nombre proporcionado, o null si no se encuentra.</returns>
|
|
/// <exception cref="BadRequestException">Se lanza cuando el nombre es nulo, vacío o demasiado largo.</exception>
|
|
public async Task<ConfigObservation?> FindByName(string name)
|
|
{
|
|
if (string.IsNullOrWhiteSpace(name))
|
|
throw new BadRequestException(HttpEnum.ErrorMessage.BadRequestInvalidFormat);
|
|
|
|
if (name.Length > 100)
|
|
throw new BadRequestException("Name too long");
|
|
|
|
var safeName = Regex.Escape(name);
|
|
|
|
var filter = Builders<ConfigObservation>.Filter.Regex(
|
|
x => x.Name,
|
|
new BsonRegularExpression($"^{safeName}$", "i")
|
|
);
|
|
|
|
return await Collection
|
|
.Find(filter)
|
|
.FirstOrDefaultAsync();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Busca un ConfigObservation por su sistema de codificación y código en la base de datos MongoDB, utilizando una búsqueda insensible a mayúsculas y minúsculas.
|
|
/// </summary>
|
|
/// <param name="codingSystem">El sistema de codificación del ConfigObservation a buscar.</param>
|
|
/// <param name="code">El código del ConfigObservation a buscar.</param>
|
|
/// <returns>El ConfigObservation que coincide con el sistema de codificación y código proporcionados, o null si no se encuentra.</returns>
|
|
public async Task<ConfigObservation?> GetByCodeSysAndCode(string? codingSystem, string? code)
|
|
{
|
|
var builder = Builders<ConfigObservation>.Filter;
|
|
var filter = builder.Empty;
|
|
|
|
if (!string.IsNullOrEmpty(codingSystem) && !string.IsNullOrEmpty(code))
|
|
{
|
|
filter &= builder.Eq(x => x.CodingSystem, codingSystem);
|
|
filter &= builder.Eq(x => x.Code, code);
|
|
}
|
|
|
|
if (filter == builder.Empty) return null;
|
|
|
|
var result = await Collection.FindAsync(filter);
|
|
|
|
return await result.FirstOrDefaultAsync();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Inserta un nuevo ConfigObservation en la base de datos MongoDB y devuelve el objeto insertado, incluyendo su ID generado.
|
|
/// </summary>
|
|
/// <param name="configObservationItem">El ConfigObservation a insertar en la base de datos.</param>
|
|
/// <returns>El ConfigObservation insertado, incluyendo su ID generado.</returns>
|
|
public async Task<ConfigObservation> InsertOneAsyncAndReturn(ConfigObservation configObservationItem)
|
|
{
|
|
await Collection.InsertOneAsync(configObservationItem);
|
|
return configObservationItem;
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Busca todos los ConfigObservation que coinciden con un nombre específico en la base de datos MongoDB, utilizando una búsqueda insensible a mayúsculas y minúsculas.
|
|
/// </summary>
|
|
/// <param name="name">El nombre del ConfigObservation a buscar.</param>
|
|
/// <returns>Una lista de ConfigObservation que coinciden con el nombre proporcionado.</returns>
|
|
public async Task<List<ConfigObservation>> FindAllByName(string name)
|
|
{
|
|
var builder = Builders<ConfigObservation>.Filter;
|
|
var filter = builder.Empty;
|
|
|
|
if (!string.IsNullOrEmpty(name)) filter &= builder.Eq(x => x.Name, name);
|
|
|
|
if (filter == builder.Empty) return [];
|
|
|
|
var result = await Collection.FindAsync(filter);
|
|
|
|
return await result.ToListAsync();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Busca un ConfigObservation que coincida con los parámetros proporcionados (código, sistema de codificación, nombre u nombre original) en la base de datos MongoDB, utilizando una búsqueda insensible a mayúsculas y minúsculas.
|
|
/// </summary>
|
|
/// <param name="code">El código del ConfigObservation a buscar.</param>
|
|
/// <param name="codingSystem">El sistema de codificación del ConfigObservation a buscar.</param>
|
|
/// <param name="name">El nombre del ConfigObservation a buscar.</param>
|
|
/// <param name="originalName">El nombre original del ConfigObservation a buscar.</param>
|
|
/// <returns>El ConfigObservation que coincide con los parámetros proporcionados, o null si no se encuentra.</returns>
|
|
public async Task<ConfigObservation?> GetSingleConfigObservationItem(string? code, string? codingSystem,
|
|
string? name, string? originalName)
|
|
{
|
|
var builder = Builders<ConfigObservation>.Filter;
|
|
var filterDefinition = builder.Empty;
|
|
if (!string.IsNullOrEmpty(codingSystem)) filterDefinition &= builder.Eq(x => x.CodingSystem, codingSystem);
|
|
|
|
if (!string.IsNullOrEmpty(code)) filterDefinition &= builder.Eq(x => x.Code, code);
|
|
|
|
if (!string.IsNullOrEmpty(name)) filterDefinition &= builder.Eq(x => x.Name, name);
|
|
|
|
if (!string.IsNullOrEmpty(originalName)) filterDefinition &= builder.Eq(x => x.OriginalName, originalName);
|
|
return await Collection
|
|
.Find(filterDefinition)
|
|
.FirstOrDefaultAsync();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Inserta una carga inicial de ConfigObservation en la base de datos MongoDB utilizando una lista maestra de observaciones de enfermería.
|
|
/// Si ya existen ConfigObservation en la base de datos, solo se insertan aquellos que faltan en comparación con la lista maestra.
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public sealed override async Task InsertInitialLoad()
|
|
{
|
|
var stringNurseObs = _masterListServiceFactory.StringNurseObs();
|
|
var isInitialized = await FindAll();
|
|
|
|
if (isInitialized.Count > 0)
|
|
{
|
|
var existingNames = isInitialized
|
|
.Where(c => c.Name != null) // Filtrar nulls para evitar errores de referencia
|
|
.Select(c => c.Name!) // Seleccionar solo los nombres (usamos '!' si confías en el filtro anterior)
|
|
.ToList();
|
|
var missingItems = stringNurseObs
|
|
.Where(x => !existingNames.Contains(x))
|
|
.ToList();
|
|
|
|
foreach (var item in missingItems)
|
|
await InsertOneAsync(new ConfigObservation
|
|
{
|
|
Name = item, Code = "NURSE-ADAS", CodingSystem = "ADAS",
|
|
InsertMode = ObservationEnum.InsertMode.Manual
|
|
});
|
|
return;
|
|
}
|
|
|
|
var masterListObsConfig = stringNurseObs.Select(c => new ConfigObservation
|
|
{
|
|
Name = c, Code = "NURSE-ADAS", CodingSystem = "ADAS", InsertMode = ObservationEnum.InsertMode.Manual
|
|
})
|
|
.ToList();
|
|
foreach (var item in masterListObsConfig) await InsertOneAsync(item);
|
|
}
|
|
} |