Files

478 lines
17 KiB
C#

using adas_core.Application.Repositories.Interfaces;
using adas_core.Domain.Enums;
using adas_core.Domain.Models;
using adas_core.Domain.Models.AppSettings;
using adas_core.Domain.Models.DTO;
using adas_core.Domain.Models.Masters;
using adas_core.Domain.Models.MongoModels;
using Microsoft.Extensions.Options;
using MongoDB.Bson;
using MongoDB.Driver;
using Serilog;
using MongoUtils = adas_core.Infrastructure.Utils.MongoUtils;
namespace adas_core.Infrastructure.Repositories;
public class AdmissionRepository : MongoRepository<Admission>, IAdmissionRepository
{
private readonly ApiSettings _apiSettings;
public AdmissionRepository(IOptions<ApiSettings> apiSettings, IMongoDatabase database) : base(database)
{
if (apiSettings == null) throw new ArgumentNullException(nameof(apiSettings));
_apiSettings = apiSettings.Value;
}
public override string GetCollectionName()
{
return _apiSettings.Admissions;
}
public override async Task InsertOneAsync(Admission admission)
{
try
{
admission.AdmissionDate = DateTime.UtcNow;
await base.InsertOneAsync(admission);
}
catch (Exception e)
{
Log.Warning("Exception trying to insert admission: {admission}. Exception {e}", admission, e);
}
}
public async Task Delete(ObjectId id)
{
try
{
var filter = Builders<Admission>.Filter.Eq(x => x.Id, id);
await Collection.DeleteOneAsync(filter, null);
}
catch (Exception e)
{
Log.Error("Exception trying to delete admission: {id}. Exception {e}", id, e);
throw;
}
}
public async Task Update(Admission admission)
{
try
{
await UpdateOneAsync(admission.Id, admission);
}
catch (Exception e)
{
Log.Error("Exception trying to update admission: {admission}. Exception {e}", admission, e);
throw;
}
}
public async Task UpdateLocation(ObjectId id, ObjectId newLocation)
{
var filterBuilder = Builders<Admission>.Filter;
var filter = filterBuilder.Eq(p => p.Id, id);
var update = Builders<Admission>.Update
.Set(p => p.PointOfCareId, newLocation);
await Collection.UpdateOneAsync(filter, update);
}
public async Task UpdatePatient(ObjectId id, Person patient)
{
var filterBuilder = Builders<Admission>.Filter;
var filter = filterBuilder.Eq(p => p.Id, id);
var update = Builders<Admission>.Update
.Set(p => p.Person, patient);
await Collection.UpdateOneAsync(filter, update);
}
public async Task<IEnumerable<Admission>> FindAll()
{
try
{
var result = await Collection.FindAsync(_ => true);
return await result.ToListAsync();
}
catch (Exception ex)
{
Log.Error("Error getting all admissions. Exception: {ex}", ex);
return [];
}
}
public async Task<Admission?> SearchByPatientNumberAndDistinctUnit(string patientNumber, ObjectId unitId)
{
if (string.IsNullOrWhiteSpace(patientNumber)) return null;
// Paciente ubicado en un PoC pero en diferente unidad
var patient = await Collection.Find(Builders<Admission>.Filter.And(
Builders<Admission>.Filter.Eq(p => p.Nhc, patientNumber),
Builders<Admission>.Filter.Ne(p => p.UnitId, unitId)
)).ToListAsync();
// Si hay mas de una coincidencia devolvemos null por que puede no estar completo el patientNumber
if (patient.Count > 1) return null;
return patient.FirstOrDefault();
}
public async Task<Admission?> FindById(ObjectId id)
{
try
{
var filter = Builders<Admission>.Filter.Eq(p => p.Id, id);
var result = await Collection.FindAsync(filter);
return await result.FirstOrDefaultAsync();
}
catch (Exception ex)
{
Log.Error("Error searching admission by id: {id}. Exception: {ex}", id, ex);
return null;
}
}
public async Task<Admission?> FindByNhc(string nhc)
{
try
{
var filter = Builders<Admission>.Filter.Eq(p => p.Nhc, nhc);
var result = await Collection.FindAsync(filter);
return await result.FirstOrDefaultAsync();
}
catch (Exception ex)
{
Log.Error("Error searching admission by NHC: {nhc}. Exception: {ex}", nhc, ex);
return null;
}
}
public async Task<List<Admission>> FindByLocation(PatientLocation location)
{
try
{
var filter = Builders<Admission>.Filter.Where(p =>
p.PatientLocation != null &&
location.UnitName == p.PatientLocation.UnitName &&
location.Bed == p.PatientLocation.Bed &&
location.Room == p.PatientLocation.Room);
return await Collection.Find(filter).ToListAsync();
}
catch (Exception ex)
{
Log.Error("Error searching admission by location: {location}. Exception: {ex}", location, ex);
return [];
}
}
public async Task<IEnumerable<Admission>?> FindByOrigin(string origin)
{
try
{
var filter = string.IsNullOrEmpty(origin)
? Builders<Admission>.Filter.Empty
: Builders<Admission>.Filter.Where(p => p.Origin != null && origin.Equals(p.Origin.Name));
var result = await Collection.FindAsync(filter);
return result.ToEnumerable();
}
catch (Exception ex)
{
Log.Error("Error searching admissions by origin: {origin}. Exception: {ex}", origin, ex);
return null;
}
}
public async Task<Admission?> InsertOneAsyncAndReturn(Admission origin)
{
try
{
await Collection.InsertOneAsync(origin);
return origin;
}
catch (Exception ex)
{
Log.Error(ex.Message);
return null;
}
}
public async Task<List<Admission>> GetAdmissionByUnitIdWithOutPoC(ObjectId unitId)
{
try
{
var filter = Builders<Admission>.Filter.Where(p => p.UnitId == unitId && p.PointOfCareId == null);
var result = await Collection.FindAsync(filter);
return result.ToList();
}
catch (Exception ex)
{
Log.Error(ex.Message);
return [];
}
}
public async Task<long> CountByUnitId(ObjectId unitId)
{
try
{
var filter = Builders<Admission>.Filter.Where(p => p.UnitId == unitId);
var result = await Collection.CountDocumentsAsync(filter);
return result;
}
catch (Exception ex)
{
Log.Error(ex.Message);
return 0;
}
}
public async Task<List<Admission>> FindByPointOfCareId(ObjectId pocId)
{
try
{
var filter = Builders<Admission>.Filter.Where(p => p.PointOfCareId == pocId);
var result = await Collection.FindAsync(filter);
return result.ToList();
}
catch (Exception ex)
{
Log.Error(ex.Message);
return [];
}
}
public async Task<List<Admission>> FindByUnitIds(List<ObjectId> unitIds)
{
var filterUnit = Builders<Admission>.Filter.In("unitId", unitIds);
return await Collection.Find(filterUnit).ToListAsync();
}
public async Task<IEnumerable<Admission>> UpdateMasterListOption(List<ObjectId> unitIds,
UpdateOptionMasterListDto opt, string typeName)
{
var isParsed = Enum.TryParse<MasterListType>(typeName, out var parsedTypeName);
if (isParsed)
{
var filterUnit = Builders<Admission>.Filter.In("unitId", unitIds);
switch (parsedTypeName)
{
case MasterListType.OriginList:
var originFilter = Builders<Admission>.Filter.Eq(
"origin.name", opt.OldOption?.Name
);
var filterUpdateorigin = Builders<Admission>.Filter.And(filterUnit, originFilter);
var updateorigin = Builders<Admission>.Update
.Set("origin.name", opt.UpdatedOption?.Name);
await Collection.UpdateManyAsync(filterUpdateorigin, updateorigin);
await Collection.UpdateManyAsync(Builders<Admission>.Filter.And(filterUnit,
Builders<Admission>.Filter.Eq(
"originAux", opt.OldOption?.Name
)), Builders<Admission>.Update
.Set("originAux", opt.UpdatedOption?.Name));
// Filtro para devolver los documentos actualizados (OR entre diagnosis.name y diagnosisAux)
var originFilterToReturn = Builders<Admission>.Filter.Eq("origin.name", opt.UpdatedOption?.Name);
var originAuxFilterToReturn = Builders<Admission>.Filter.Eq("originAux", opt.UpdatedOption?.Name);
var filterToReturnorigin = Builders<Admission>.Filter.And(
filterUnit,
Builders<Admission>.Filter.Or(originFilterToReturn, originAuxFilterToReturn)
);
// Devolver los documentos actualizados
var updatedDocumentsorigin = await Collection.Find(filterToReturnorigin).ToListAsync();
return updatedDocumentsorigin;
case MasterListType.DiagnosisList:
var diagnosisFilter = Builders<Admission>.Filter.Eq(
"diagnosis.name", opt.OldOption?.Name
);
var filterUpdateDiagnosis = Builders<Admission>.Filter.And(filterUnit, diagnosisFilter);
var updateDiagnosis = Builders<Admission>.Update
.Set("diagnosis.name", opt.UpdatedOption?.Name)
.Set("diagnosis.description", opt.UpdatedOption?.Description);
await Collection.UpdateManyAsync(filterUpdateDiagnosis, updateDiagnosis);
await Collection.UpdateManyAsync(Builders<Admission>.Filter.And(filterUnit,
Builders<Admission>.Filter.Eq(
"diagnosisAux", opt.OldOption?.Name
)), Builders<Admission>.Update
.Set("diagnosisAux", opt.UpdatedOption?.Name));
// Filtro para devolver los documentos actualizados (OR entre diagnosis.name y diagnosisAux)
var diagnosisFilterToReturn =
Builders<Admission>.Filter.Eq("diagnosis.name", opt.UpdatedOption?.Name);
var diagnosisAuxFilterToReturn =
Builders<Admission>.Filter.Eq("diagnosisAux", opt.UpdatedOption?.Name);
var filterToReturn = Builders<Admission>.Filter.And(
filterUnit,
Builders<Admission>.Filter.Or(diagnosisFilterToReturn, diagnosisAuxFilterToReturn)
);
// Devolver los documentos actualizados
var updatedDocuments = await Collection.Find(filterToReturn).ToListAsync();
return updatedDocuments;
case MasterListType.AllergyList:
// allergies []
break;
case MasterListType.InsulationList:
// insulation
break;
case MasterListType.LanguageBarrierList:
// languageBarrier
break;
case MasterListType.PassiveSittingList:
// passiveSitting
break;
}
}
return new List<Admission>();
}
public async Task<IEnumerable<Admission>> DeleteMasterListOption(List<ObjectId> unitIds, OptionList opt,
string typeName)
{
var isParsed = Enum.TryParse<MasterListType>(typeName, out var parsedTypeName);
if (isParsed)
{
var filterUnit = Builders<Admission>.Filter.In("unitId", unitIds);
switch (parsedTypeName)
{
case MasterListType.OriginList:
// origin
// originAux
// Filtro para devolver los documentos actualizados (OR entre diagnosis.name y diagnosisAux)
var originFilterToReturn = Builders<Admission>.Filter.Eq("origin.name", opt.Name);
var originAuxFilterToReturn = Builders<Admission>.Filter.Eq("originAux", opt.Name);
var filterToReturnOrigin = Builders<Admission>.Filter.And(
filterUnit,
Builders<Admission>.Filter.Or(originFilterToReturn, originAuxFilterToReturn)
);
// Devolver los documentos actualizados
var updatedDocumentOrigin = await Collection.Find(filterToReturnOrigin).ToListAsync();
var originFilter = Builders<Admission>.Filter.Eq(
"origin.name", opt.Name
);
var filterUpdateOrigin = Builders<Admission>.Filter.And(filterUnit, originFilter);
var updateorigin = Builders<Admission>.Update
.Set(x => x.Origin, null);
await Collection.UpdateManyAsync(filterUpdateOrigin, updateorigin);
await Collection.UpdateManyAsync(Builders<Admission>.Filter.And(filterUnit,
Builders<Admission>.Filter.Eq(
"originAux", opt.Name
)), Builders<Admission>.Update
.Set(x => x.OriginAux, ""));
return updatedDocumentOrigin;
case MasterListType.DiagnosisList:
// Filtro para devolver los documentos actualizados (OR entre diagnosis.name y diagnosisAux)
var diagnosisFilterToReturn = Builders<Admission>.Filter.Eq("diagnosis.name", opt.Name);
var diagnosisAuxFilterToReturn = Builders<Admission>.Filter.Eq("diagnosisAux", opt.Name);
var filterToReturn = Builders<Admission>.Filter.And(
filterUnit,
Builders<Admission>.Filter.Or(diagnosisFilterToReturn, diagnosisAuxFilterToReturn)
);
// Devolver los documentos actualizados
var updatedDocuments = await Collection.Find(filterToReturn).ToListAsync();
var diagnosisFilter = Builders<Admission>.Filter.Eq(
"diagnosis.name", opt.Name
);
var filterUpdateDiagnosis = Builders<Admission>.Filter.And(filterUnit, diagnosisFilter);
var updateDiagnosis = Builders<Admission>.Update
.Set(x => x.Diagnosis, null);
await Collection.UpdateManyAsync(filterUpdateDiagnosis, updateDiagnosis);
await Collection.UpdateManyAsync(Builders<Admission>.Filter.And(filterUnit,
Builders<Admission>.Filter.Eq(
"diagnosisAux", opt.Name
)), Builders<Admission>.Update
.Set(x => x.DiagnosisAux, null));
return updatedDocuments;
case MasterListType.AllergyList:
// allergies []
break;
case MasterListType.InsulationList:
// insulation
break;
case MasterListType.LanguageBarrierList:
// languageBarrier
break;
case MasterListType.PassiveSittingList:
// passiveSitting
break;
}
}
return new List<Admission>();
}
public async Task<bool> DeleteAdmissionsByUnitId(ObjectId unitId)
{
try
{
var filter = Builders<Admission>.Filter.Eq(p => p.UnitId, unitId);
await Collection.DeleteManyAsync(filter);
return true;
}
catch (Exception e)
{
Log.Logger.Error(e.Message);
return false;
}
}
public override async Task CreateIndexes()
{
var optionsUq = new CreateIndexOptions<Admission>
{
Background = true,
Unique = true,
PartialFilterExpression = Builders<Admission>.Filter.Exists(p => p.Nhc)
};
var indexes = new List<CreateIndexModel<Admission>>
{
new("{ nhc: 1 }", optionsUq)
};
await MongoUtils.EnsureIndexes(Collection, indexes);
}
public async Task<IEnumerable<Admission>?> FindByDiagnosis(string diagnosis)
{
try
{
var filter =
Builders<Admission>.Filter.Where(p => p.Diagnosis != null && diagnosis.Equals(p.Diagnosis.Name));
var result = await Collection.FindAsync(filter);
return result.ToEnumerable();
}
catch (Exception ex)
{
Log.Error("Error searching admissions by diagnosis: {origin}. Exception: {ex}", diagnosis, ex);
return null;
}
}
}