Creado apartir del commit b888de6c92056de294456f581a56e25e734d4ab7 de develop
This commit is contained in:
@@ -0,0 +1,478 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,185 @@
|
||||
using adas_core.Application.Repositories.Interfaces;
|
||||
using adas_core.Domain.Models;
|
||||
using adas_core.Domain.Models.AppSettings;
|
||||
using adas_core.Domain.Models.GroupedObservations;
|
||||
using adas_core.Domain.Models.MongoModels;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using MongoDB.Bson;
|
||||
using MongoDB.Driver;
|
||||
using MongoUtils = adas_core.Infrastructure.Utils.MongoUtils;
|
||||
|
||||
namespace adas_core.Infrastructure.Repositories;
|
||||
|
||||
public class AlarmRepository : MongoRepository<PatientObservationAlarm>, IAlarmRepository
|
||||
{
|
||||
private readonly ApiSettings _apiSettings;
|
||||
private readonly ILogger<AlarmRepository> _logger;
|
||||
|
||||
public AlarmRepository(IOptions<ApiSettings> apiSettings, IMongoDatabase database, ILogger<AlarmRepository> logger)
|
||||
: base(database)
|
||||
{
|
||||
if (apiSettings == null) throw new ArgumentNullException(nameof(apiSettings));
|
||||
_logger = logger;
|
||||
_apiSettings = apiSettings.Value;
|
||||
} //For testing
|
||||
|
||||
|
||||
|
||||
public async Task<List<PatientObservationAlarm>> AggregatedPatientLastObservationsByField(ObjectId patientId,
|
||||
List<Field>? filterObservations = null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var results = new List<PatientObservationAlarm>();
|
||||
IAsyncCursor<PatientObservationAlarm>? cursor;
|
||||
var builder = Builders<PatientObservationAlarm>.Filter;
|
||||
|
||||
if (filterObservations != null)
|
||||
{
|
||||
foreach (var obs in filterObservations)
|
||||
{
|
||||
FilterDefinition<PatientObservationAlarm> filter;
|
||||
|
||||
if (obs is { OnlyExpired: true, Name: not null })
|
||||
filter = builder.And(
|
||||
builder.Eq(o => o.PatientId, patientId),
|
||||
builder.Eq(o => o.Name, obs.Name),
|
||||
builder.Eq("Expired", obs.OnlyExpired)
|
||||
//builder.Eq(o => o.Expired, obs.OnlyExpired)
|
||||
);
|
||||
else
|
||||
filter = builder.And(
|
||||
builder.Eq(o => o.PatientId, patientId),
|
||||
builder.Eq(o => o.Name, obs.Name)
|
||||
);
|
||||
|
||||
cursor = await Collection.FindAsync(
|
||||
filter,
|
||||
new FindOptions<PatientObservationAlarm>
|
||||
{
|
||||
Sort = Builders<PatientObservationAlarm>.Sort.Descending("time").Descending("id"),
|
||||
Limit = obs.Last
|
||||
});
|
||||
|
||||
results.AddRange(cursor.ToEnumerable());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var filter = builder.Eq(o => o.PatientId, patientId);
|
||||
|
||||
cursor = await Collection.FindAsync(
|
||||
filter,
|
||||
new FindOptions<PatientObservationAlarm>
|
||||
{ Sort = Builders<PatientObservationAlarm>.Sort.Descending("time").Descending("id") });
|
||||
|
||||
results.AddRange(cursor.ToEnumerable());
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError("Error aggregated patient last observations by field {exMessage}", ex.Message);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<List<PatientObservationAlarm>> AggregatedPatientNotExpiredObservationsByField(
|
||||
ObjectId patientId,
|
||||
List<Field>? filterObservations,
|
||||
List<ConfigObservation> configAlarm)
|
||||
{
|
||||
try
|
||||
{
|
||||
var results = new List<PatientObservationAlarm>();
|
||||
IAsyncCursor<PatientObservationAlarm>? cursor;
|
||||
var builder = Builders<PatientObservationAlarm>.Filter;
|
||||
|
||||
if (filterObservations != null)
|
||||
{
|
||||
foreach (var obs in filterObservations)
|
||||
{
|
||||
FilterDefinition<PatientObservationAlarm> filter;
|
||||
var conf = configAlarm.FirstOrDefault(c => c.Name == obs.Name);
|
||||
|
||||
if (obs is { OnlyExpired: true, Name: not null })
|
||||
filter = builder.And(
|
||||
builder.Eq(o => o.PatientId, patientId),
|
||||
builder.Eq(o => o.Name, obs.Name),
|
||||
builder.Eq("Expired", obs.OnlyExpired)
|
||||
//builder.Eq(o => o.Expired, obs.OnlyExpired)
|
||||
);
|
||||
else
|
||||
filter = builder.And(
|
||||
builder.Eq(o => o.PatientId, patientId),
|
||||
builder.Eq(o => o.Name, obs.Name)
|
||||
);
|
||||
|
||||
if (conf is { Expires: not null })
|
||||
{
|
||||
var dateNow = DateTime.UtcNow.AddSeconds(conf.Expires.Value * -1);
|
||||
filter = builder.And(
|
||||
filter,
|
||||
builder.Gte(o => o.Time, dateNow)
|
||||
);
|
||||
}
|
||||
|
||||
cursor = await Collection.FindAsync(
|
||||
filter,
|
||||
new FindOptions<PatientObservationAlarm>
|
||||
{ Sort = Builders<PatientObservationAlarm>.Sort.Descending("time").Descending("id") });
|
||||
|
||||
results.AddRange(cursor.ToEnumerable());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
var filter = builder.Eq(o => o.PatientId, patientId);
|
||||
|
||||
cursor = await Collection.FindAsync(
|
||||
filter,
|
||||
new FindOptions<PatientObservationAlarm>
|
||||
{ Sort = Builders<PatientObservationAlarm>.Sort.Descending("time").Descending("id") });
|
||||
|
||||
results.AddRange(cursor.ToEnumerable());
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError("Error aggregated patient last observations by field {exMessage}", ex.Message);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public override string GetCollectionName()
|
||||
{
|
||||
return _apiSettings.PatientsAlarms ?? "patients_alarms";
|
||||
}
|
||||
|
||||
public override async Task CreateIndexes()
|
||||
{
|
||||
try
|
||||
{
|
||||
var options = new CreateIndexOptions { Background = true, Unique = false };
|
||||
var indexes = new List<CreateIndexModel<PatientObservationAlarm>>
|
||||
{
|
||||
new("{ patientid: 1 }", options),
|
||||
new("{ patientid: 1, name: 1 }", options),
|
||||
new("{ name: 1 }", options),
|
||||
new("{ patientid: 1, name: 1 , time: 1}", options)
|
||||
};
|
||||
await MongoUtils.EnsureIndexes(Collection, indexes);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.LogError(
|
||||
"error creating indexes for observation collection {eMessage} TRACE: {eStackTrace}", e.Message,
|
||||
e.StackTrace);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
using adas_core.Application.Repositories.Interfaces;
|
||||
using adas_core.Domain.Models;
|
||||
using adas_core.Domain.Models.AppSettings;
|
||||
using Microsoft.Extensions.Options;
|
||||
using MongoDB.Driver;
|
||||
using MongoUtils = adas_core.Infrastructure.Utils.MongoUtils;
|
||||
|
||||
namespace adas_core.Infrastructure.Repositories;
|
||||
|
||||
public class AppointmentArchiveRepository : MongoRepository<PatientAppointment>, IAppointmentArchiveRepository
|
||||
{
|
||||
private readonly ApiSettings _apiSettings;
|
||||
|
||||
|
||||
public AppointmentArchiveRepository(IOptions<ApiSettings> apiSettings, IMongoDatabase database) : base(database)
|
||||
{
|
||||
if (apiSettings == null) throw new ArgumentNullException(nameof(apiSettings));
|
||||
_apiSettings = apiSettings.Value;
|
||||
} //For testing
|
||||
|
||||
|
||||
|
||||
public override async Task InsertOneAsync(PatientAppointment appointment)
|
||||
{
|
||||
await Collection.InsertOneAsync(appointment);
|
||||
}
|
||||
|
||||
|
||||
public async Task DeleteBeforeDate(DateTime date)
|
||||
{
|
||||
var filter = Builders<PatientAppointment>.Filter.Lt(pa => pa.CreateTime, date);
|
||||
await Collection.DeleteManyAsync(filter);
|
||||
}
|
||||
|
||||
public async Task<long> InsertBatch(IEnumerable<PatientAppointment> appointment)
|
||||
{
|
||||
var writes = new List<WriteModel<PatientAppointment>>();
|
||||
writes.AddRange(appointment.Select(d => new InsertOneModel<PatientAppointment>(d)));
|
||||
|
||||
var bulkInsert = await Collection.BulkWriteAsync(writes);
|
||||
|
||||
return bulkInsert.InsertedCount;
|
||||
}
|
||||
|
||||
public override string GetCollectionName()
|
||||
{
|
||||
return _apiSettings.ArchivePatientsAppointments ?? "archive_patients_appointments";
|
||||
}
|
||||
|
||||
public override async Task CreateIndexes()
|
||||
{
|
||||
var options = new CreateIndexOptions<PatientAppointment> { Background = true, Unique = false };
|
||||
|
||||
var indexes = new List<CreateIndexModel<PatientAppointment>>
|
||||
{
|
||||
new("{ patientid: 1 }", options)
|
||||
};
|
||||
|
||||
await MongoUtils.EnsureIndexes(Collection, indexes);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
using adas_core.Application.Repositories.Interfaces;
|
||||
using adas_core.Domain.Models;
|
||||
using adas_core.Domain.Models.AppSettings;
|
||||
using adas_core.Domain.Models.MongoModels;
|
||||
using Microsoft.Extensions.Options;
|
||||
using MongoDB.Bson;
|
||||
using MongoDB.Driver;
|
||||
using MongoUtils = adas_core.Infrastructure.Utils.MongoUtils;
|
||||
|
||||
namespace adas_core.Infrastructure.Repositories;
|
||||
|
||||
public class AppointmentRepository : MongoRepository<PatientAppointment>, IAppointmentRepository
|
||||
{
|
||||
private readonly ApiSettings _apiSettings;
|
||||
|
||||
public AppointmentRepository(
|
||||
IOptions<ApiSettings> apiSettings,
|
||||
IMongoDatabase database) : base(database)
|
||||
{
|
||||
if (apiSettings == null) throw new ArgumentNullException(nameof(apiSettings));
|
||||
_apiSettings = apiSettings.Value;
|
||||
} //For testing
|
||||
|
||||
|
||||
|
||||
public override string GetCollectionName()
|
||||
{
|
||||
return _apiSettings.PatientsAppointments ?? "patients_appointments";
|
||||
}
|
||||
|
||||
public async Task<List<PatientAppointment>> GetByPatient(ObjectId patientId)
|
||||
{
|
||||
var filter = Builders<PatientAppointment>.Filter.Eq(ob => ob.PatientId, patientId);
|
||||
var options = new FindOptions<PatientAppointment>
|
||||
{
|
||||
Sort = Builders<PatientAppointment>.Sort.Descending("createTime")
|
||||
};
|
||||
|
||||
var result = await Collection.FindAsync(filter, options);
|
||||
|
||||
return result.ToList();
|
||||
}
|
||||
public async Task<List<PatientAppointment>> FindByPoC(PointOfCare poc)
|
||||
{
|
||||
var location = new PatientLocation()
|
||||
{
|
||||
Bed = poc.Bed,
|
||||
Room = poc.Room,
|
||||
UnitName = poc.UnitName
|
||||
};
|
||||
return await FindByLocation(location);
|
||||
}
|
||||
|
||||
|
||||
public override async Task InsertOneAsync(PatientAppointment appointment)
|
||||
{
|
||||
appointment.CreateTime ??= DateTime.UtcNow;
|
||||
await base.InsertOneAsync(appointment);
|
||||
}
|
||||
|
||||
public async Task Update(PatientAppointment appointment)
|
||||
{
|
||||
await UpdateOneAsync(appointment.Id, appointment);
|
||||
}
|
||||
|
||||
public new async Task DeleteAsync(ObjectId id)
|
||||
{
|
||||
var filter = Builders<PatientAppointment>.Filter.Eq(t => t.Id, id); // Replace 'T' with your actual class name.
|
||||
await Collection.DeleteOneAsync(filter);
|
||||
}
|
||||
|
||||
|
||||
public Task<IAsyncCursor<PatientAppointment>> FindByPatientIdAsync(ObjectId patientId)
|
||||
{
|
||||
var filter = Builders<PatientAppointment>.Filter.Eq(ob => ob.PatientId, patientId);
|
||||
return Collection.FindAsync(filter);
|
||||
}
|
||||
|
||||
|
||||
public async Task DeleteByPatientId(ObjectId patientId)
|
||||
{
|
||||
var filter = Builders<PatientAppointment>.Filter.Eq(po => po.PatientId, patientId);
|
||||
await Collection.DeleteManyAsync(filter);
|
||||
}
|
||||
|
||||
|
||||
public async Task<PatientAppointment?> FindByPatientAndVisitNumber(ObjectId patientId, string visitNumber)
|
||||
{
|
||||
var builder = Builders<PatientAppointment>.Filter;
|
||||
var filter = builder.And(
|
||||
builder.Eq(ob => ob.PatientId, patientId),
|
||||
builder.Eq(ob => ob.VisitNumber, visitNumber)
|
||||
);
|
||||
|
||||
var result = await Collection.FindAsync(filter);
|
||||
|
||||
return await result.FirstOrDefaultAsync();
|
||||
}
|
||||
|
||||
|
||||
public async Task<PatientAppointment?> FindByPatientAndReason(ObjectId patientId, string? appointmentReason)
|
||||
{
|
||||
var builder = Builders<PatientAppointment>.Filter;
|
||||
var filter = builder.And(
|
||||
builder.Eq(ob => ob.PatientId, patientId),
|
||||
builder.Eq(ob => ob.AppointmentReason, appointmentReason)
|
||||
);
|
||||
|
||||
var result = await Collection.FindAsync(filter);
|
||||
|
||||
return await result.FirstOrDefaultAsync();
|
||||
}
|
||||
|
||||
public async Task<List<PatientAppointment>> FindByLocation(PatientLocation location)
|
||||
{
|
||||
var builder = Builders<PatientAppointmentResourceGroup>.Filter;
|
||||
var existsFilter = builder.Exists(rg => rg.Locations);
|
||||
var locationFilter = builder.ElemMatch(rg => rg.Locations,
|
||||
l => l.Bed == location.Bed && l.UnitName == location.UnitName);
|
||||
|
||||
var combinedFilter = builder.And(existsFilter, locationFilter);
|
||||
|
||||
var filter = Builders<PatientAppointment>.Filter.ElemMatch(pa => pa.ResourceGroups, combinedFilter);
|
||||
|
||||
var result = await Collection.FindAsync(filter);
|
||||
return result?.ToList()??[];
|
||||
}
|
||||
|
||||
public async Task UpdateManyObjectId(string nameId, ObjectId id, ObjectId oldId)
|
||||
{
|
||||
await UpdateManyObjectIdAsync(nameId, id, oldId);
|
||||
}
|
||||
|
||||
public override async Task CreateIndexes()
|
||||
{
|
||||
var options = new CreateIndexOptions { Background = true, Unique = false };
|
||||
var indexes = new List<CreateIndexModel<PatientAppointment>>
|
||||
{
|
||||
new("{ patientid: 1 }", options)
|
||||
};
|
||||
|
||||
await MongoUtils.EnsureIndexes(Collection, indexes);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,183 @@
|
||||
using adas_core.Application.Repositories.Interfaces;
|
||||
using adas_core.Domain.Models.AppSettings;
|
||||
using adas_core.Domain.Models.MongoModels;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using MongoDB.Bson;
|
||||
using MongoDB.Driver;
|
||||
using MongoUtils = adas_core.Infrastructure.Utils.MongoUtils;
|
||||
|
||||
namespace adas_core.Infrastructure.Repositories;
|
||||
|
||||
public class ArchivePatientCarePlanRepository : MongoRepository<PatientCarePlan>, IArchivePatientCarePlanRepository
|
||||
{
|
||||
#region Properties
|
||||
|
||||
private readonly ApiSettings _apiSettings;
|
||||
private readonly ILogger<ArchivePatientCarePlanRepository> _logger;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
|
||||
|
||||
public ArchivePatientCarePlanRepository(
|
||||
IOptions<ApiSettings> apiSettings,
|
||||
IMongoDatabase database,
|
||||
ILogger<ArchivePatientCarePlanRepository> logger) : base(database)
|
||||
{
|
||||
_logger = logger;
|
||||
_apiSettings = apiSettings.Value;
|
||||
}
|
||||
|
||||
public override async Task CreateIndexes()
|
||||
{
|
||||
var options = new CreateIndexOptions<PatientCarePlan> { Background = true, Unique = false };
|
||||
|
||||
var indexes = new List<CreateIndexModel<PatientCarePlan>>
|
||||
{
|
||||
new("{ patientId: 1 }", options)
|
||||
};
|
||||
|
||||
await MongoUtils.EnsureIndexes(Collection, indexes);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Create
|
||||
|
||||
public override async Task InsertOneAsync(PatientCarePlan patient)
|
||||
{
|
||||
try
|
||||
{
|
||||
await base.InsertOneAsync(patient);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.LogError(
|
||||
"Exception trying to insert patient: {patient}. on archive patient procedure Exception {e}", patient,
|
||||
e);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public override async Task InsertManyAsync(List<PatientCarePlan> patient)
|
||||
{
|
||||
try
|
||||
{
|
||||
await base.InsertManyAsync(patient);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.LogError(
|
||||
"Exception trying to insert many PatientCarePlan. on archive patient procedure Exception {e}", e);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Read
|
||||
|
||||
public override string GetCollectionName()
|
||||
{
|
||||
return _apiSettings.ArchivePatientProcedure ?? "archive_patients_care_plan";
|
||||
}
|
||||
|
||||
public async Task<List<PatientCarePlan>?> FindByPatientId(ObjectId patientId)
|
||||
{
|
||||
var result = await Collection.FindAsync(Builders<PatientCarePlan>.Filter.Eq(p => p.PatientId, patientId));
|
||||
return result.ToList();
|
||||
}
|
||||
|
||||
public async Task<List<PatientCarePlan>?> FindByPatientId(string patientId)
|
||||
{
|
||||
var isParsed = ObjectId.TryParse(patientId, out var patientIdParsed);
|
||||
if (!isParsed) return [];
|
||||
var result = await Collection.FindAsync(Builders<PatientCarePlan>.Filter.Eq(p => p.PatientId, patientIdParsed));
|
||||
return result.ToList();
|
||||
}
|
||||
|
||||
public async Task<List<PatientCarePlan>?> FindByPatientNumber(string patientId)
|
||||
{
|
||||
var result = await Collection.FindAsync(Builders<PatientCarePlan>.Filter.Eq(p => p.PatientNumber, patientId));
|
||||
return result.ToList();
|
||||
}
|
||||
|
||||
public async Task<List<PatientCarePlan>> FindAll()
|
||||
{
|
||||
var result = await Collection.Find(Builders<PatientCarePlan>.Filter.Empty).ToListAsync();
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<List<PatientCarePlan>?> FindByIds(ObjectId oldPatientId, string? oldPatientPatientId,
|
||||
string? oldPatientPatientNumber)
|
||||
{
|
||||
var patientFound = await FindByPatientId(oldPatientId);
|
||||
if (patientFound != null) return patientFound;
|
||||
if (oldPatientPatientId != null)
|
||||
{
|
||||
patientFound = await FindByPatientId(oldPatientPatientId);
|
||||
if (patientFound is { Count: > 0 }) return patientFound;
|
||||
}
|
||||
|
||||
if (oldPatientPatientNumber != null)
|
||||
{
|
||||
patientFound = await FindByPatientNumber(oldPatientPatientNumber);
|
||||
if (patientFound is { Count: > 0 }) return patientFound;
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Update
|
||||
|
||||
// public async Task Update(Patient patient)
|
||||
// {
|
||||
// patient.UpdateDate = DateTime.UtcNow;
|
||||
// await UpdateOneAsync(patient.Id, patient);
|
||||
// }
|
||||
//
|
||||
// public async void UpdatePatientData(Patient oldPatient, Patient newPatient)
|
||||
// {
|
||||
// var filterBuilder = Builders<Patient>.Filter;
|
||||
// var updateBuilder = Builders<Patient>.Update
|
||||
// .Set(p => p.Person, newPatient.Person)
|
||||
// .Set(p => p.UpdateDate, DateTime.UtcNow)
|
||||
// .Set(p => p.Location, newPatient.Location)
|
||||
// .Set(p => p.PatientNumber, newPatient.PatientNumber)
|
||||
// .Set(p => p.UnitString, newPatient.UnitString)
|
||||
// .Set(p => p.Room, newPatient.Room)
|
||||
// .Set(p => p.PatientId, newPatient.PatientId);
|
||||
// var filter = filterBuilder.Eq(p => p.Id, oldPatient.Id);
|
||||
// var update = updateBuilder;
|
||||
//
|
||||
// await Collection.UpdateOneAsync(filter, update);
|
||||
// }
|
||||
|
||||
// public async void UpdateProcedure(Patient patientFound)
|
||||
// {
|
||||
// var filterBuilder = Builders<Patient>.Filter;
|
||||
// var updateBuilder = Builders<Patient>.Update
|
||||
// .Set(p => p.Procedures, patientFound.Procedures);
|
||||
// var filter = filterBuilder.Eq(p => p.Id, patientFound.Id);
|
||||
// var update = updateBuilder;
|
||||
//
|
||||
// await Collection.UpdateOneAsync(filter, update);
|
||||
// }
|
||||
//
|
||||
// public async void UpdateTreatment(Patient patientFound)
|
||||
// {
|
||||
// var filterBuilder = Builders<Patient>.Filter;
|
||||
// var updateBuilder = Builders<Patient>.Update
|
||||
// .Set(p => p.Treatment, patientFound.Treatment);
|
||||
// var filter = filterBuilder.Eq(p => p.Id, patientFound.Id);
|
||||
// var update = updateBuilder;
|
||||
//
|
||||
// await Collection.UpdateOneAsync(filter, update);
|
||||
// }
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
using adas_core.Application.Repositories.Interfaces;
|
||||
using adas_core.Domain.Models.AppSettings;
|
||||
using adas_core.Domain.Models.MongoModels;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using MongoDB.Bson;
|
||||
using MongoDB.Driver;
|
||||
|
||||
namespace adas_core.Infrastructure.Repositories;
|
||||
|
||||
public class AuthorityRepository(
|
||||
IOptions<ApiSettings> apiSettings,
|
||||
IMongoDatabase database,
|
||||
ILogger<AuthorityRepository> logger)
|
||||
: MongoRepository<Authorization>(database), IAuthorityRepository
|
||||
{
|
||||
private readonly ApiSettings _apiSettings = apiSettings.Value;
|
||||
private readonly ILogger _logger = logger;
|
||||
|
||||
public void CreateNewAuthority(string roleName, ObjectId userId)
|
||||
{
|
||||
var newAuthorization = new Authorization
|
||||
{
|
||||
UserId = userId,
|
||||
DisplayId = ObjectId.GenerateNewId().ToString(),
|
||||
Rol = roleName
|
||||
};
|
||||
|
||||
Collection.InsertOne(newAuthorization);
|
||||
_logger.LogDebug("New authority created for user {UserId} with role {RoleName}", userId, roleName);
|
||||
}
|
||||
|
||||
public async Task<List<Authorization>> GetUserAuthorities(ObjectId userId)
|
||||
{
|
||||
var filter = Builders<Authorization>.Filter.Eq(p => p.UserId, userId);
|
||||
var result = await Collection.FindAsync(filter);
|
||||
_logger.LogDebug("Retrieved authorities for user {UserId}", userId);
|
||||
return result.ToList();
|
||||
}
|
||||
|
||||
public async Task<List<Authorization>> GetAllAuthorities()
|
||||
{
|
||||
var result = await Collection.FindAsync(Builders<Authorization>.Filter.Empty);
|
||||
_logger.LogDebug("Retrieved all authorities");
|
||||
return result.ToList();
|
||||
}
|
||||
|
||||
public async Task<List<Authorization>> GetByUnitId(ObjectId unitId)
|
||||
{
|
||||
var filter = Builders<Authorization>.Filter.Eq(a => a.UnitId, unitId.ToString());
|
||||
|
||||
var result = await Collection.FindAsync(filter);
|
||||
|
||||
_logger.LogDebug("Retrieved authorities for unit {UnitId}", unitId);
|
||||
|
||||
return result.ToList();
|
||||
}
|
||||
|
||||
public async Task<bool> DeleteAllAuthoritiesByUser(ObjectId userId)
|
||||
{
|
||||
try
|
||||
{
|
||||
var filter = Builders<Authorization>.Filter.Eq(p => p.UserId, userId);
|
||||
await Collection.DeleteManyAsync(filter);
|
||||
|
||||
_logger.LogDebug("Deleted all authorities for user {UserId}", userId);
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public async Task<bool> DeleteAllAuthoritiesByUnit(ObjectId unitId)
|
||||
{
|
||||
try
|
||||
{
|
||||
var filter = Builders<Authorization>.Filter.Eq(p => p.UnitId, unitId.ToString());
|
||||
await Collection.DeleteManyAsync(filter);
|
||||
_logger.LogDebug("Deleted all authorities for unit {UnitId}", unitId);
|
||||
return true;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<bool> DeleteAllAuthoritiesByDisplay(ObjectId displayId)
|
||||
{
|
||||
try
|
||||
{
|
||||
var filter = Builders<Authorization>.Filter.Eq(p => p.DisplayId, displayId.ToString());
|
||||
await Collection.DeleteManyAsync(filter);
|
||||
_logger.LogDebug("Deleted all authorities for display {DisplayId}", displayId);
|
||||
return true;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public override string GetCollectionName()
|
||||
{
|
||||
return _apiSettings.Authorizations;
|
||||
}
|
||||
|
||||
public async Task<Authorization> GetById(ObjectId authId)
|
||||
{
|
||||
var filter = Builders<Authorization>.Filter.Eq(p => p.Id, authId);
|
||||
return await Collection.Find(filter).FirstOrDefaultAsync();
|
||||
}
|
||||
|
||||
public sealed override async Task InsertInitialLoad()
|
||||
{
|
||||
var user = Db.GetCollection<User>(apiSettings.Value.Users);
|
||||
var filter = Builders<User>.Filter.Eq(p => p.UserName, "System");
|
||||
var search = await user.FindAsync(filter);
|
||||
var systemUSer = search.FirstOrDefault();
|
||||
if (systemUSer != null)
|
||||
{
|
||||
var auths = await GetUserAuthorities(systemUSer.Id);
|
||||
if (!auths.Exists(c => c.PanelAuthorization))
|
||||
await InsertOneAsync(new Authorization
|
||||
{ CanUpdate = false, PanelAuthorization = true, Rol = "AuthAdmin", UserId = systemUSer.Id });
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
using adas_core.Application.Exceptions;
|
||||
using adas_core.Application.Repositories.Interfaces;
|
||||
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 Newtonsoft.Json;
|
||||
using Serilog;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace adas_core.Infrastructure.Repositories;
|
||||
|
||||
public class CameraRepository : MongoRepository<Camera>, ICameraRepository
|
||||
{
|
||||
private readonly ApiSettings _apiSettings;
|
||||
|
||||
|
||||
public CameraRepository(IMongoDatabase database, IOptions<ApiSettings> apiSettings) : base(database)
|
||||
{
|
||||
_apiSettings = apiSettings.Value;
|
||||
}
|
||||
|
||||
public override string GetCollectionName()
|
||||
{
|
||||
return _apiSettings.Cameras;
|
||||
}
|
||||
|
||||
public async Task<Camera?> GetById(ObjectId cameraId)
|
||||
{
|
||||
try
|
||||
{
|
||||
var filter = Builders<Camera>.Filter.Eq(x => x.Id, cameraId);
|
||||
var result = await Collection.FindAsync(filter, null);
|
||||
return result.FirstOrDefault();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error("Exception trying to get relay by id: {id}. Exception {e}", cameraId, e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<Camera?> GetByName(string name)
|
||||
{
|
||||
var filterBuilder = Builders<Camera>.Filter;
|
||||
|
||||
var filter = filterBuilder.Eq(r => r.Name, name);
|
||||
|
||||
return await Collection.Find(filter).FirstOrDefaultAsync();
|
||||
}
|
||||
|
||||
public List<Camera> GetCameraInList(List<ObjectId> configurationRelayList)
|
||||
{
|
||||
var filterBuilder = Builders<Camera>.Filter;
|
||||
|
||||
var filter = filterBuilder.And(
|
||||
filterBuilder.In(r => r.Id, configurationRelayList));
|
||||
|
||||
return Collection.Find(filter).ToList();
|
||||
}
|
||||
|
||||
public IFindFluent<Camera, Camera> GetPaginatedCameras(PaginationFilter filter)
|
||||
{
|
||||
var filterBuilder = Builders<Camera>.Filter;
|
||||
var sort = Builders<Camera>.Sort.Ascending("name");
|
||||
var filters = new List<FilterDefinition<Camera>>();
|
||||
|
||||
if (filter.FilteredRequest == null)
|
||||
return CreateFindFluent(filters, sort);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(filter.FilteredRequest.Text))
|
||||
{
|
||||
var textFilter = filter.FilteredRequest.Text;
|
||||
|
||||
if (textFilter.Length > 100)
|
||||
throw new BadRequestException("Text filter too long");
|
||||
|
||||
var safeInput = Regex.Escape(textFilter);
|
||||
|
||||
filters.Add(
|
||||
filterBuilder.Regex(
|
||||
p => p.Name,
|
||||
new BsonRegularExpression(safeInput, "i")
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return CreateFindFluent(filters, sort);
|
||||
}
|
||||
|
||||
public async Task<Camera?> InsertOneCamera(Camera camera)
|
||||
{
|
||||
try
|
||||
{
|
||||
await Collection.InsertOneAsync(camera);
|
||||
return await GetById(camera.Id);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error("Error inserting camera: {camera}. Exception: {ex}",
|
||||
JsonConvert.SerializeObject(camera, Formatting.Indented), ex);
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<Camera?> UpdateCameraAsync(ObjectId objectId, Camera camera)
|
||||
{
|
||||
var filter = Builders<Camera>.Filter.Eq("_id", objectId);
|
||||
var update = Builders<Camera>.Update
|
||||
.Set(c => c.Streams, camera.Streams)
|
||||
.Set(c => c.Name, camera.Name)
|
||||
.Set(c => c.Username, camera.Username)
|
||||
.Set(c => c.Password, camera.Password)
|
||||
.Set(c => c.Driver, camera.Driver)
|
||||
.Set(c => c.Ip, camera.Ip)
|
||||
.Set(c => c.Streams, camera.Streams)
|
||||
.Set(c => c.Ptz, camera.Ptz);
|
||||
return await Collection.FindOneAndUpdateAsync(filter, update,
|
||||
new FindOneAndUpdateOptions<Camera, Camera> { ReturnDocument = ReturnDocument.After });
|
||||
}
|
||||
|
||||
public async Task<List<Camera>> GetSearchByNameCameras(string textToSearch)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(textToSearch))
|
||||
return [];
|
||||
|
||||
if (textToSearch.Length > 100)
|
||||
throw new BadRequestException("Search text too long");
|
||||
|
||||
var safeInput = Regex.Escape(textToSearch);
|
||||
|
||||
var filter = Builders<Camera>.Filter.Regex(
|
||||
c => c.Name,
|
||||
new BsonRegularExpression(safeInput, "i")
|
||||
);
|
||||
|
||||
return await Collection.Find(filter).ToListAsync();
|
||||
}
|
||||
|
||||
private IFindFluent<Camera, Camera> CreateFindFluent(List<FilterDefinition<Camera>> filters, SortDefinition<Camera> sort)
|
||||
{
|
||||
var combinedFilter = filters.Any()
|
||||
? Builders<Camera>.Filter.And(filters)
|
||||
: Builders<Camera>.Filter.Empty;
|
||||
return Collection.Find(combinedFilter).Sort(sort);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,245 @@
|
||||
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;
|
||||
|
||||
public class ConfigObservationRepository : MongoRepository<ConfigObservation>, IConfigObservationRepository
|
||||
{
|
||||
private readonly ApiSettings _apiSettings;
|
||||
private readonly IMasterListServiceFactory _masterListServiceFactory;
|
||||
|
||||
public ConfigObservationRepository(IOptions<ApiSettings> apiSettings, IMongoDatabase database,
|
||||
IMasterListServiceFactory masterListServiceFactory) : base(database)
|
||||
{
|
||||
_masterListServiceFactory = masterListServiceFactory;
|
||||
_apiSettings = apiSettings.Value;
|
||||
}
|
||||
|
||||
|
||||
public override string GetCollectionName()
|
||||
{
|
||||
return _apiSettings.ConfigObservations ?? "config_observations";
|
||||
}
|
||||
|
||||
public async Task<ConfigObservation?> FindById(ObjectId id)
|
||||
{
|
||||
var result = await Collection.FindAsync(Builders<ConfigObservation>.Filter.Eq(x => x.Id, id));
|
||||
return await result.FirstOrDefaultAsync();
|
||||
}
|
||||
|
||||
public async Task<ConfigObservation?> Update(ConfigObservation configObservation)
|
||||
{
|
||||
await UpdateOneAsync(configObservation.Id, configObservation);
|
||||
return configObservation;
|
||||
}
|
||||
|
||||
public async Task<ConfigObservation?> Delete(ObjectId id)
|
||||
{
|
||||
return await DeleteAsync(id);
|
||||
}
|
||||
|
||||
public async Task<List<ObjectId>> FindAllIds()
|
||||
{
|
||||
var allCollection = await Collection.FindAsync(_ => true);
|
||||
|
||||
return allCollection.ToList().Select(item => item.Id).ToList();
|
||||
}
|
||||
|
||||
public async Task<ICollection<ConfigObservation>> FindAll()
|
||||
{
|
||||
var result = await Collection.FindAsync(_ => true);
|
||||
return await result.ToListAsync();
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
public async Task<long> Count()
|
||||
{
|
||||
var filter = Builders<ConfigObservation>.Filter.Empty;
|
||||
var result = await Collection.CountDocumentsAsync(filter);
|
||||
return result;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
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();
|
||||
}
|
||||
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
public async Task<ConfigObservation> InsertOneAsyncAndReturn(ConfigObservation configObservationItem)
|
||||
{
|
||||
await Collection.InsertOneAsync(configObservationItem);
|
||||
return configObservationItem;
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
using adas_core.Application.Repositories.Interfaces;
|
||||
using adas_core.Domain.Models.AppSettings;
|
||||
using adas_core.Domain.Models.MongoModels;
|
||||
using Microsoft.Extensions.Options;
|
||||
using MongoDB.Driver;
|
||||
|
||||
namespace adas_core.Infrastructure.Repositories;
|
||||
|
||||
public class ConfigPumpsRepository : MongoRepository<ConfigPumps>, IConfigPumpsRepository
|
||||
{
|
||||
private readonly ApiSettings _apiSettings;
|
||||
|
||||
public ConfigPumpsRepository(IOptions<ApiSettings> apiSettings, IMongoDatabase database) : base(database)
|
||||
{
|
||||
if (apiSettings == null) throw new ArgumentNullException(nameof(apiSettings));
|
||||
_apiSettings = apiSettings.Value;
|
||||
} //For testing
|
||||
|
||||
|
||||
|
||||
public override string GetCollectionName()
|
||||
{
|
||||
return _apiSettings.ConfigPumps ?? "config_pumps";
|
||||
}
|
||||
|
||||
public async Task<List<ConfigPumps>?> GetAllConfigs()
|
||||
{
|
||||
var result = await Collection.FindAsync(Builders<ConfigPumps>.Filter.Empty);
|
||||
|
||||
return result.ToList();
|
||||
}
|
||||
|
||||
public async Task<ConfigPumps?> FindById(string id)
|
||||
{
|
||||
var result = await Collection.FindAsync(Builders<ConfigPumps>.Filter.Eq(x => x.Id, id));
|
||||
|
||||
return await result.FirstOrDefaultAsync();
|
||||
}
|
||||
|
||||
public async Task<ConfigPumps?> UpdateConfig(ConfigPumps config)
|
||||
{
|
||||
var filter = Builders<ConfigPumps>.Filter.Eq("_id", config.Id);
|
||||
var update = Builders<ConfigPumps>.Update.Set(c => c.Items, config.Items);
|
||||
|
||||
return await Collection.FindOneAndUpdateAsync(filter, update,
|
||||
new FindOneAndUpdateOptions<ConfigPumps, ConfigPumps> { ReturnDocument = ReturnDocument.After });
|
||||
}
|
||||
|
||||
public async Task<bool> DeleteConfig(ConfigPumps config)
|
||||
{
|
||||
var filter = Builders<ConfigPumps>.Filter.Eq("_id", config.Id);
|
||||
await Collection.DeleteOneAsync(filter);
|
||||
|
||||
var result = await FindById(config.Id);
|
||||
return result == null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
using adas_core.Application.Repositories.Interfaces;
|
||||
using adas_core.Domain.Models.AppSettings;
|
||||
using adas_core.Domain.Models.MongoModels;
|
||||
using Microsoft.Extensions.Options;
|
||||
using MongoDB.Driver;
|
||||
|
||||
namespace adas_core.Infrastructure.Repositories;
|
||||
|
||||
public class ConfigUnitsRepository : MongoRepository<ConfigUnits>, IConfigUnitsRepository
|
||||
{
|
||||
private readonly ApiSettings _apiSettings;
|
||||
|
||||
public ConfigUnitsRepository(IOptions<ApiSettings> apiSettings, IMongoDatabase database) : base(database)
|
||||
{
|
||||
if (apiSettings == null) throw new ArgumentNullException(nameof(apiSettings));
|
||||
_apiSettings = apiSettings.Value;
|
||||
} //For testing
|
||||
|
||||
|
||||
|
||||
|
||||
public override string GetCollectionName()
|
||||
{
|
||||
return _apiSettings.ConfigUnits ?? "config_units";
|
||||
}
|
||||
|
||||
public async Task<ConfigUnits?> FindById(string id)
|
||||
{
|
||||
var resutl = await Collection.FindAsync(Builders<ConfigUnits>.Filter.Eq(x => x.Id, id));
|
||||
return resutl.FirstOrDefault();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
using adas_core.Application.Repositories.Interfaces;
|
||||
using adas_core.Domain.Models.AppSettings;
|
||||
using adas_core.Domain.Models.DTO;
|
||||
using adas_core.Domain.Models.MongoModels;
|
||||
using MongoDB.Bson;
|
||||
using MongoDB.Driver;
|
||||
using MongoUtils = adas_core.Infrastructure.Utils.MongoUtils;
|
||||
|
||||
namespace adas_core.Infrastructure.Repositories;
|
||||
|
||||
public class DeviceRepository : MongoRepository<Device>, IDeviceRepository
|
||||
{
|
||||
private readonly ApiSettings _apiSettings;
|
||||
|
||||
public DeviceRepository(ApiSettings apiSettings, IMongoDatabase database) : base(database)
|
||||
{
|
||||
_apiSettings = apiSettings;
|
||||
}
|
||||
|
||||
public override string GetCollectionName()
|
||||
{
|
||||
return _apiSettings.Devices ?? "devices";
|
||||
}
|
||||
|
||||
public override async Task CreateIndexes()
|
||||
{
|
||||
var options = new CreateIndexOptions { Background = true, Unique = true };
|
||||
var indexes = new List<CreateIndexModel<Device>>
|
||||
{
|
||||
new(Builders<Device>.IndexKeys.Ascending(d => d.MacAddr), options),
|
||||
new(Builders<Device>.IndexKeys.Ascending(d => d.SerialNumber), new CreateIndexOptions { Background = true }),
|
||||
new(Builders<Device>.IndexKeys.Ascending(d => d.Uuid), new CreateIndexOptions { Background = true }),
|
||||
new(Builders<Device>.IndexKeys.Ascending(d => d.Key), new CreateIndexOptions { Background = true })
|
||||
};
|
||||
|
||||
await MongoUtils.EnsureIndexes(Collection, indexes);
|
||||
}
|
||||
|
||||
public async Task<Device?> FindByMacAddr(string deviceDtoMacAddr)
|
||||
{
|
||||
return await Collection
|
||||
.Find(d => d.MacAddr == deviceDtoMacAddr)
|
||||
.FirstOrDefaultAsync();
|
||||
}
|
||||
|
||||
public async Task<Device?> FindBySerialNumber(string deviceDtoSerialNumber)
|
||||
{
|
||||
return await Collection
|
||||
.Find(d => d.SerialNumber == deviceDtoSerialNumber)
|
||||
.FirstOrDefaultAsync();
|
||||
}
|
||||
|
||||
public async Task<Device?> FindByUuid(string deviceDtoUuid)
|
||||
{
|
||||
return await Collection
|
||||
.Find(d => d.Uuid == deviceDtoUuid)
|
||||
.FirstOrDefaultAsync();
|
||||
}
|
||||
|
||||
public async Task<Device?> FindByKey(string deviceDtoKey)
|
||||
{
|
||||
return await Collection
|
||||
.Find(d => d.Key == deviceDtoKey)
|
||||
.FirstOrDefaultAsync();
|
||||
}
|
||||
|
||||
public async Task UpdateDeviceStats(ObjectId id, DeviceDto deviceExist)
|
||||
{
|
||||
var update = Builders<Device>.Update
|
||||
.Set(d => d.Battery, deviceExist.Battery)
|
||||
.Set(d => d.Connected, deviceExist.Connected)
|
||||
.Set(d => d.Ready, deviceExist.Ready)
|
||||
.Set(d => d.Name, deviceExist.Name)
|
||||
.Set(d => d.UpdatedAt, DateTime.UtcNow);
|
||||
|
||||
await Collection.UpdateOneAsync(
|
||||
d => d.Id == id,
|
||||
update
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
using adas_core.Application.Repositories.Interfaces;
|
||||
using adas_core.Domain.Models;
|
||||
using adas_core.Domain.Models.AppSettings;
|
||||
using Microsoft.Extensions.Options;
|
||||
using MongoDB.Driver;
|
||||
using MongoUtils = adas_core.Infrastructure.Utils.MongoUtils;
|
||||
|
||||
namespace adas_core.Infrastructure.Repositories;
|
||||
|
||||
public class DiagnosisArchiveRepository : MongoRepository<PatientDiagnosis>, IDiagnosisArchiveRepository
|
||||
{
|
||||
private readonly ApiSettings _apiSettings;
|
||||
|
||||
public DiagnosisArchiveRepository(IOptions<ApiSettings> apiSettings, IMongoDatabase database) : base(database)
|
||||
{
|
||||
if (apiSettings == null) throw new ArgumentNullException(nameof(apiSettings));
|
||||
_apiSettings = apiSettings.Value;
|
||||
} //For testing
|
||||
|
||||
|
||||
public override async Task InsertOneAsync(PatientDiagnosis patientDiagnosis)
|
||||
{
|
||||
await Collection.InsertOneAsync(patientDiagnosis);
|
||||
}
|
||||
|
||||
public async Task DeleteBeforeDate(DateTime date)
|
||||
{
|
||||
var filter = Builders<PatientDiagnosis>.Filter.Lt(po => po.Time, date);
|
||||
await Collection.DeleteManyAsync(filter);
|
||||
}
|
||||
|
||||
public async Task<long> InsertBatch(IEnumerable<PatientDiagnosis> observations)
|
||||
{
|
||||
var writes = new List<WriteModel<PatientDiagnosis>>();
|
||||
writes.AddRange(observations.Select(d => new InsertOneModel<PatientDiagnosis>(d)));
|
||||
|
||||
var bulkInsert = await Collection.BulkWriteAsync(writes);
|
||||
|
||||
return bulkInsert.InsertedCount;
|
||||
}
|
||||
|
||||
public override string GetCollectionName()
|
||||
{
|
||||
return _apiSettings.ArchivePatientsDiagnosis ?? "archive_patients_diagnosis";
|
||||
}
|
||||
|
||||
public override async Task CreateIndexes()
|
||||
{
|
||||
var options = new CreateIndexOptions<PatientDiagnosis> { Background = true, Unique = false };
|
||||
|
||||
var indexes = new List<CreateIndexModel<PatientDiagnosis>>
|
||||
{
|
||||
new("{ patientid: 1 }", options)
|
||||
};
|
||||
|
||||
await MongoUtils.EnsureIndexes(Collection, indexes);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
using adas_core.Application.Repositories.Interfaces;
|
||||
using adas_core.Domain.Models;
|
||||
using adas_core.Domain.Models.AppSettings;
|
||||
using Microsoft.Extensions.Options;
|
||||
using MongoDB.Bson;
|
||||
using MongoDB.Driver;
|
||||
using MongoUtils = adas_core.Infrastructure.Utils.MongoUtils;
|
||||
|
||||
namespace adas_core.Infrastructure.Repositories;
|
||||
|
||||
public class DiagnosisRepository : MongoRepository<PatientDiagnosis>, IDiagnosisRepository
|
||||
{
|
||||
private readonly ApiSettings _apiSettings;
|
||||
|
||||
|
||||
public DiagnosisRepository(IOptions<ApiSettings> apiSettings, IMongoDatabase database) : base(database)
|
||||
{
|
||||
if (apiSettings == null) throw new ArgumentNullException(nameof(apiSettings));
|
||||
_apiSettings = apiSettings.Value;
|
||||
} //For testing
|
||||
|
||||
|
||||
public override string GetCollectionName()
|
||||
{
|
||||
return _apiSettings.PatientsDiagnosis ?? "patients_diagnosis";
|
||||
}
|
||||
|
||||
public async Task<List<PatientDiagnosis>> GetByPatient(ObjectId patientId)
|
||||
{
|
||||
var filter = Builders<PatientDiagnosis>.Filter.Eq(ob => ob.PatientId, patientId);
|
||||
var result = await Collection.FindAsync(filter,
|
||||
new FindOptions<PatientDiagnosis> { Sort = Builders<PatientDiagnosis>.Sort.Descending("time") });
|
||||
|
||||
return result.ToList();
|
||||
}
|
||||
|
||||
public new async Task DeleteAsync(ObjectId id)
|
||||
{
|
||||
var filter = Builders<PatientDiagnosis>.Filter.Eq(t => t.Id, id);
|
||||
await Collection.DeleteOneAsync(filter);
|
||||
}
|
||||
|
||||
|
||||
public override async Task InsertOneAsync(PatientDiagnosis diagnosis)
|
||||
{
|
||||
await Collection.InsertOneAsync(diagnosis);
|
||||
}
|
||||
|
||||
public async Task DeleteByPatientId(ObjectId patientId)
|
||||
{
|
||||
var filter = Builders<PatientDiagnosis>.Filter.Eq(po => po.PatientId, patientId);
|
||||
await Collection.DeleteManyAsync(filter);
|
||||
}
|
||||
|
||||
public async Task<PatientDiagnosis?> FindByPatientIdAndCode(ObjectId patientId, string? code, string? codingSystem)
|
||||
{
|
||||
var builder = Builders<PatientDiagnosis>.Filter;
|
||||
var filter = builder.And(
|
||||
builder.Eq(ob => ob.PatientId, patientId),
|
||||
builder.Eq(ob => ob.Code, code),
|
||||
builder.Eq(ob => ob.CodingSystem, codingSystem)
|
||||
);
|
||||
|
||||
var result = await Collection.FindAsync(filter);
|
||||
|
||||
return await result.FirstOrDefaultAsync();
|
||||
}
|
||||
|
||||
|
||||
public async Task<IAsyncCursor<PatientDiagnosis>> FindByPatientIdAsync(ObjectId patientId)
|
||||
{
|
||||
var filter = Builders<PatientDiagnosis>.Filter.Eq(ob => ob.PatientId, patientId);
|
||||
|
||||
return await Collection.FindAsync(filter);
|
||||
}
|
||||
|
||||
public async Task UpdateManyObjectId(string nameId, ObjectId id, ObjectId oldId)
|
||||
{
|
||||
await UpdateManyObjectIdAsync(nameId, id, oldId);
|
||||
}
|
||||
|
||||
public override async Task CreateIndexes()
|
||||
{
|
||||
var options = new CreateIndexOptions { Background = true, Unique = false };
|
||||
var indexes = new List<CreateIndexModel<PatientDiagnosis>>
|
||||
{
|
||||
new("{ patientid: 1 }", options)
|
||||
};
|
||||
|
||||
await MongoUtils.EnsureIndexes(Collection, indexes);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,333 @@
|
||||
using adas_core.Application.Exceptions;
|
||||
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 DischargeRepository : MongoRepository<Discharge>, IDischargeRepository
|
||||
{
|
||||
private readonly ApiSettings _apiSettings;
|
||||
|
||||
public DischargeRepository(IOptions<ApiSettings> apiSettings, IMongoDatabase database) : base(database)
|
||||
{
|
||||
_apiSettings = apiSettings.Value;
|
||||
}
|
||||
|
||||
public override string GetCollectionName()
|
||||
{
|
||||
return _apiSettings.Discharges;
|
||||
}
|
||||
|
||||
public override async Task InsertOneAsync(Discharge discharge)
|
||||
{
|
||||
try
|
||||
{
|
||||
discharge.DischargeDate = DateTime.UtcNow;
|
||||
await base.InsertOneAsync(discharge);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Warning("Exception trying to insert discharge: {discharge}. Exception {e}", discharge, e);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task Delete(ObjectId id)
|
||||
{
|
||||
try
|
||||
{
|
||||
var filter = Builders<Discharge>.Filter.Eq(x => x.Id, id);
|
||||
await Collection.DeleteOneAsync(filter, null);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error("Exception trying to delete discharge: {id}. Exception {e}", id, e);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task Update(Discharge discharge)
|
||||
{
|
||||
try
|
||||
{
|
||||
await UpdateOneAsync(discharge.Id, discharge);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error("Exception trying to update discharge: {discharge}. Exception {e}", discharge, e);
|
||||
throw new ConflictException(HttpEnum.ErrorMessage.ConflictUpdateFailed);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public async Task UpdateUnit(ObjectId id, string unit)
|
||||
{
|
||||
var filterBuilder = Builders<Discharge>.Filter;
|
||||
var filter = filterBuilder.Eq(p => p.Id, id);
|
||||
|
||||
var update = Builders<Discharge>.Update
|
||||
.Set(p => p.PatientLocation!.UnitName, unit);
|
||||
|
||||
await Collection.UpdateOneAsync(filter, update);
|
||||
}
|
||||
|
||||
public async Task UpdatePatient(ObjectId id, Patient patient)
|
||||
{
|
||||
var filterBuilder = Builders<Discharge>.Filter;
|
||||
var filter = filterBuilder.Eq(p => p.Id, id);
|
||||
|
||||
var update = Builders<Discharge>.Update
|
||||
.Set(p => p.Patient, patient);
|
||||
|
||||
await Collection.UpdateOneAsync(filter, update);
|
||||
}
|
||||
|
||||
|
||||
public async Task<IEnumerable<Discharge>> FindAll()
|
||||
{
|
||||
try
|
||||
{
|
||||
var result = await Collection.FindAsync(_ => true);
|
||||
return await result.ToListAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error("Error getting all discharges. Exception: {ex}", ex);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<Discharge?> FindById(ObjectId id)
|
||||
{
|
||||
try
|
||||
{
|
||||
var filter = Builders<Discharge>.Filter.Eq(p => p.Id, id);
|
||||
var result = await Collection.FindAsync(filter);
|
||||
|
||||
return await result.FirstOrDefaultAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error("Error searching discharge by id: {id}. Exception: {ex}", id, ex);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public async Task<IEnumerable<Discharge>?> FindByUnit(string unit)
|
||||
{
|
||||
try
|
||||
{
|
||||
var filter = Builders<Discharge>.Filter.Eq(p => p.PatientLocation!.UnitName, unit);
|
||||
var result = await Collection.FindAsync(filter);
|
||||
|
||||
return result.ToEnumerable();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error("Error searching discharge by Unit id: {unit}. Exception: {ex}", unit, ex);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<long> CountByUnitId(ObjectId unitId)
|
||||
{
|
||||
try
|
||||
{
|
||||
return await Collection.CountDocumentsAsync(
|
||||
Builders<Discharge>.Filter.Eq(p => p.UnitId, unitId));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error(e.Message);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<Discharge>?> FindByDestination(string destination)
|
||||
{
|
||||
try
|
||||
{
|
||||
var filter = string.IsNullOrEmpty(destination)
|
||||
? Builders<Discharge>.Filter.Empty
|
||||
: Builders<Discharge>.Filter.Eq(p => p.Destination, destination);
|
||||
|
||||
var result = await Collection.FindAsync(filter);
|
||||
|
||||
return result.ToEnumerable();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error("Error searching discharges by destination: {destination}. Exception: {ex}", destination, ex);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<Discharge>?> GetDischargesByUnitIds(IEnumerable<ObjectId>? unitIds)
|
||||
{
|
||||
var filterUnit = Builders<Discharge>.Filter.In("unitId", unitIds);
|
||||
return await Collection.Find(filterUnit).ToListAsync();
|
||||
}
|
||||
|
||||
|
||||
public async Task<IEnumerable<Discharge>?> FindByPoCId(ObjectId pocId)
|
||||
{
|
||||
try
|
||||
{
|
||||
var filter = Builders<Discharge>.Filter.Eq(p => p.PointOfCareId, pocId);
|
||||
|
||||
var result = await Collection.FindAsync(filter);
|
||||
|
||||
return result.ToEnumerable();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error("Error searching discharges by PointOfCare: {destination}. Exception: {ex}", pocId, ex);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<Discharge>?> FindByService(string service)
|
||||
{
|
||||
try
|
||||
{
|
||||
var filter = Builders<Discharge>.Filter.Eq(p => p.Service, service);
|
||||
var result = await Collection.FindAsync(filter);
|
||||
|
||||
return result.ToEnumerable();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error("Error searching discharges by service: {origin}. Exception: {ex}", service, ex);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<Discharge?> GetDischargeByLocation(PatientLocation location)
|
||||
{
|
||||
try
|
||||
{
|
||||
var filter = Builders<Discharge>.Filter.Eq(p => p.PatientLocation, location);
|
||||
var result = await Collection.FindAsync(filter);
|
||||
|
||||
return await result.FirstOrDefaultAsync();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error($"Unable to get discharge by location on repository Exception: {e}");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<Discharge?> GetDischargeByPointOfCareId(ObjectId id)
|
||||
{
|
||||
try
|
||||
{
|
||||
var filter = Builders<Discharge>.Filter.Eq(p => p.PointOfCareId, id);
|
||||
var result = await Collection.FindAsync(filter);
|
||||
|
||||
return await result.FirstOrDefaultAsync();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error($"Unable to get discharge by location on repository Exception: {e}");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public Task<IEnumerable<Discharge>> UpdateMasterListOption(List<ObjectId> unitIds, UpdateOptionMasterListDto opt,
|
||||
string typeName)
|
||||
{
|
||||
var isParsed = Enum.TryParse<MasterListType>(typeName, out var parsedTypeName);
|
||||
if (isParsed)
|
||||
switch (parsedTypeName)
|
||||
{
|
||||
case MasterListType.DestinationList:
|
||||
// destination
|
||||
// destinationOption
|
||||
break;
|
||||
case MasterListType.ServiceList:
|
||||
// service
|
||||
break;
|
||||
}
|
||||
|
||||
return Task.FromResult<IEnumerable<Discharge>>(new List<Discharge>());
|
||||
}
|
||||
|
||||
|
||||
public async Task<bool> DeleteByUnitId(ObjectId unitId)
|
||||
{
|
||||
try
|
||||
{
|
||||
var filter = Builders<Discharge>.Filter.Where(p => p.UnitId == unitId);
|
||||
await Collection.DeleteManyAsync(filter);
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(ex.Message);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public Task<IEnumerable<Discharge>> DeleteMasterListOption(List<ObjectId> unitIds, OptionList opt, string typeName)
|
||||
{
|
||||
var isParsed = Enum.TryParse<MasterListType>(typeName, out var parsedTypeName);
|
||||
if (isParsed)
|
||||
switch (parsedTypeName)
|
||||
{
|
||||
case MasterListType.DestinationList:
|
||||
// destination
|
||||
// destinationOption
|
||||
break;
|
||||
case MasterListType.ServiceList:
|
||||
// service
|
||||
break;
|
||||
}
|
||||
|
||||
return Task.FromResult<IEnumerable<Discharge>>(new List<Discharge>());
|
||||
}
|
||||
|
||||
public async Task<Discharge?> GetByPatientId(ObjectId patientId)
|
||||
{
|
||||
try
|
||||
{
|
||||
var filter = Builders<Discharge>.Filter.Eq(p => p.PatientId, patientId);
|
||||
var result = await Collection.FindAsync(filter);
|
||||
|
||||
return await result.FirstOrDefaultAsync();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error($"Unable to get discharge by patient id on repository Exception: {e}");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public override async Task CreateIndexes()
|
||||
{
|
||||
var optionsUq = new CreateIndexOptions<Discharge>
|
||||
{
|
||||
Background = true,
|
||||
Unique = true,
|
||||
PartialFilterExpression = Builders<Discharge>.Filter.Exists(p => p.MedicalDischarge) &
|
||||
Builders<Discharge>.Filter.Exists(p => p.AdminDischarge)
|
||||
};
|
||||
var indexes = new List<CreateIndexModel<Discharge>>
|
||||
{
|
||||
new("{ medicalDischarge: 1 }", optionsUq),
|
||||
new("{ adminDischarge: 1 }", optionsUq)
|
||||
};
|
||||
|
||||
await MongoUtils.EnsureIndexes(Collection, indexes);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
using adas_core.Application.Repositories.Interfaces;
|
||||
using adas_core.Domain.Models.AppSettings;
|
||||
using adas_core.Domain.Models.MongoModels;
|
||||
using adas_core.Domain.Models.Responses;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using MongoDB.Bson;
|
||||
using MongoDB.Driver;
|
||||
|
||||
namespace adas_core.Infrastructure.Repositories;
|
||||
|
||||
public class DisplayCardConfigRepository : MongoRepository<CardConfig>, IDisplayCardConfigRepository
|
||||
{
|
||||
private readonly ApiSettings _apiSettings;
|
||||
private readonly ILogger<DisplayCardConfigRepository> _logger;
|
||||
|
||||
|
||||
public DisplayCardConfigRepository(
|
||||
IMongoDatabase database,
|
||||
ApiSettings apiSettings,
|
||||
ILogger<DisplayCardConfigRepository> logger
|
||||
) : base(database)
|
||||
{
|
||||
_apiSettings = apiSettings;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public override string GetCollectionName()
|
||||
{
|
||||
return _apiSettings.DisplayCardConfig;
|
||||
}
|
||||
|
||||
public async Task<List<CardConfig>> GetAll()
|
||||
{
|
||||
var result = await Collection.Find(Builders<CardConfig>.Filter.Empty).ToListAsync();
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<CardConfig?> GetById(ObjectId configId)
|
||||
{
|
||||
try
|
||||
{
|
||||
var result = await Collection.FindAsync(Builders<CardConfig>.Filter.Eq(p => p.Id, configId));
|
||||
return await result.FirstOrDefaultAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError("Error on config card display repository on GetById Exception: {ex}", ex.Message);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<CardConfig?> InsertOneAsyncAndReturn(CardConfig config)
|
||||
{
|
||||
try
|
||||
{
|
||||
await Collection.InsertOneAsync(config);
|
||||
return config;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex.Message);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<UpdateResponse<CardConfig?>> UpdateOne(CardConfig? config)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (config == null) return new UpdateResponse<CardConfig?>(0, null);
|
||||
var filter = Builders<CardConfig>.Filter.Eq(c => c.Id, config.Id);
|
||||
var update = Builders<CardConfig>.Update.Set(c => c.Rows, config.Rows);
|
||||
|
||||
var result = await Collection.UpdateOneAsync(filter, update);
|
||||
|
||||
var updatedDoc = await Collection.Find(filter).FirstOrDefaultAsync();
|
||||
|
||||
return new UpdateResponse<CardConfig?>(result.ModifiedCount, updatedDoc);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.LogError(e.Message);
|
||||
return new UpdateResponse<CardConfig?>(0, null);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<CardConfig?> DeleteOne(ObjectId configId)
|
||||
{
|
||||
return await DeleteAsync(configId);
|
||||
}
|
||||
|
||||
public Task<object> UpdateCardConfigId(ObjectId? displayConfigId, ObjectId? resultId)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
using adas_core.Application.Repositories.Interfaces;
|
||||
using adas_core.Domain.Models.AppSettings;
|
||||
using adas_core.Domain.Models.MongoModels;
|
||||
using adas_core.Domain.Models.Responses;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using MongoDB.Bson;
|
||||
using MongoDB.Driver;
|
||||
|
||||
namespace adas_core.Infrastructure.Repositories;
|
||||
|
||||
public class DisplayChartConfigRepository : MongoRepository<ChartConfig>, IDisplayChartConfigRepository
|
||||
{
|
||||
private readonly ApiSettings _apiSettings;
|
||||
private readonly ILogger<DisplayDetailConfigRepository> _logger;
|
||||
|
||||
|
||||
|
||||
public DisplayChartConfigRepository(IMongoDatabase database, ApiSettings apiSettings,
|
||||
ILogger<DisplayDetailConfigRepository> logger) : base(database)
|
||||
{
|
||||
_apiSettings = apiSettings;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public override string GetCollectionName()
|
||||
{
|
||||
return _apiSettings.DisplayChartConfig;
|
||||
}
|
||||
|
||||
public async Task<List<ChartConfig>> GetAll()
|
||||
{
|
||||
var result = await Collection.Find(Builders<ChartConfig>.Filter.Empty).ToListAsync();
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<ChartConfig?> GetById(ObjectId configId)
|
||||
{
|
||||
try
|
||||
{
|
||||
var result = await Collection.FindAsync(Builders<ChartConfig>.Filter.Eq(p => p.Id, configId));
|
||||
return await result.FirstOrDefaultAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError("Error on config card display repository on GetById Exception: {ex}", ex.Message);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<ChartConfig?> InsertOneAsyncAndReturn(ChartConfig config)
|
||||
{
|
||||
try
|
||||
{
|
||||
await Collection.InsertOneAsync(config);
|
||||
return config;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex.Message);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<UpdateResponse<ChartConfig?>> UpdateOne(ChartConfig? config)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (config == null) return new UpdateResponse<ChartConfig?>(0, null);
|
||||
var filter = Builders<ChartConfig>.Filter.Eq(c => c.Id, config.Id);
|
||||
var update = Builders<ChartConfig>.Update
|
||||
.Set(c => c.BaseConfig, config.BaseConfig)
|
||||
.Set(c => c.AxesConfig, config.AxesConfig)
|
||||
.Set(c => c.SeriesConfig, config.SeriesConfig);
|
||||
|
||||
// Realizamos la actualización
|
||||
var result = await Collection.UpdateOneAsync(filter, update);
|
||||
|
||||
// Buscamos el documento actual (ya actualizado o el existente si no hubo cambios)
|
||||
var updatedDoc = await Collection.Find(filter).FirstOrDefaultAsync();
|
||||
|
||||
// result.ModifiedCount será 1 si cambió algo, o 0 si los datos eran idénticos
|
||||
return new UpdateResponse<ChartConfig?>(result.ModifiedCount, updatedDoc);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.LogError(e.Message);
|
||||
return new UpdateResponse<ChartConfig?>(0, null);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<ChartConfig?> DeleteOne(ObjectId configId)
|
||||
{
|
||||
return await DeleteAsync(configId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,775 @@
|
||||
using adas_core.Application.Exceptions;
|
||||
using adas_core.Application.Repositories.Interfaces;
|
||||
using adas_core.Domain.Enums;
|
||||
using adas_core.Domain.Models.AppSettings;
|
||||
using adas_core.Domain.Models.DTO.Display;
|
||||
using adas_core.Domain.Models.Filter;
|
||||
using adas_core.Domain.Models.GroupedObservations;
|
||||
using adas_core.Domain.Models.MongoModels;
|
||||
using adas_core.Domain.Models.Responses;
|
||||
using adas_core.Domain.Utils;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using MongoDB.Bson;
|
||||
using MongoDB.Driver;
|
||||
using Newtonsoft.Json;
|
||||
using Serilog;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace adas_core.Infrastructure.Repositories;
|
||||
|
||||
public class DisplayConfigRepository : MongoRepository<DisplayConfig>, IDisplayConfigRepository
|
||||
{
|
||||
private readonly ApiSettings _apiSettings;
|
||||
|
||||
private readonly ILogger<DisplayConfigRepository> _logger;
|
||||
private readonly IUnitRepository _unitRepository;
|
||||
|
||||
|
||||
|
||||
|
||||
public DisplayConfigRepository(
|
||||
IMongoDatabase database,
|
||||
ApiSettings apiSettings,
|
||||
ILogger<DisplayConfigRepository> logger,
|
||||
IUnitRepository unitRepository) : base(database)
|
||||
{
|
||||
_apiSettings = apiSettings;
|
||||
_logger = logger;
|
||||
_unitRepository = unitRepository;
|
||||
}
|
||||
|
||||
public override string GetCollectionName()
|
||||
{
|
||||
return _apiSettings.DisplaysConfig;
|
||||
}
|
||||
|
||||
public async Task<List<DisplayConfig>> GetAll()
|
||||
{
|
||||
var result = await Collection.Find(Builders<DisplayConfig>.Filter.Empty).ToListAsync();
|
||||
return result;
|
||||
}
|
||||
|
||||
public IFindFluent<DisplayConfig, DisplayConfigSummary> GetAllPaginated(PaginationFilter filter)
|
||||
{
|
||||
var filterBuilder = Builders<DisplayConfig>.Filter;
|
||||
var sort = Builders<DisplayConfig>.Sort.Ascending("hospital");
|
||||
var filters = new List<FilterDefinition<DisplayConfig>>();
|
||||
|
||||
if (filter.FilteredRequest == null)
|
||||
return CreateFindFluentMinimal(filters, sort);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(filter.FilteredRequest.Text))
|
||||
{
|
||||
var textFilter = filter.FilteredRequest.Text;
|
||||
|
||||
if (textFilter.Length > 100)
|
||||
throw new BadRequestException("Text filter too long");
|
||||
|
||||
var textFilterEscaped = Regex.Escape(textFilter);
|
||||
|
||||
var orFilters = new List<FilterDefinition<DisplayConfig>>
|
||||
{
|
||||
filterBuilder.Regex(p => p.Hospital, new BsonRegularExpression(textFilterEscaped, "i"))
|
||||
};
|
||||
|
||||
// búsqueda por Id solo si es válido
|
||||
if (ObjectId.TryParse(textFilter, out var id))
|
||||
{
|
||||
orFilters.Add(filterBuilder.Eq("_id", id));
|
||||
}
|
||||
|
||||
filters.Add(filterBuilder.Or(orFilters));
|
||||
}
|
||||
|
||||
if (filter.FilteredRequest.DisplayType != null)
|
||||
{
|
||||
filters.Add(filterBuilder.Eq(d => d.Type, filter.FilteredRequest.DisplayType));
|
||||
}
|
||||
|
||||
return CreateFindFluentMinimal(filters, sort);
|
||||
}
|
||||
|
||||
public async Task<List<DisplayConfig>> GetByType(DisplayConfigEnums.DisplayType type)
|
||||
{
|
||||
var filter = Builders<DisplayConfig>.Filter.Eq(p => p.Type, type);
|
||||
var result = await Collection.Find(filter).ToListAsync();
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<DisplayConfig?> GetById(ObjectId id)
|
||||
{
|
||||
try
|
||||
{
|
||||
var aggregate = Collection.Aggregate()
|
||||
.Match(Builders<DisplayConfig>.Filter.Eq(p => p.Id, id))
|
||||
|
||||
// CardConfig
|
||||
.Lookup(
|
||||
_apiSettings.DisplayCardConfig,
|
||||
"cardConfigId",
|
||||
"_id",
|
||||
"cardConfig"
|
||||
)
|
||||
.Unwind("cardConfig", new AggregateUnwindOptions<BsonDocument>
|
||||
{
|
||||
PreserveNullAndEmptyArrays = true
|
||||
})
|
||||
|
||||
// DetailConfig
|
||||
.Lookup(
|
||||
_apiSettings.DisplayDetailConfig,
|
||||
"detailConfigId",
|
||||
"_id",
|
||||
"detailConfig"
|
||||
)
|
||||
.Unwind("detailConfig", new AggregateUnwindOptions<BsonDocument>
|
||||
{
|
||||
PreserveNullAndEmptyArrays = true
|
||||
})
|
||||
// ChartConfig
|
||||
.Lookup(
|
||||
_apiSettings.DisplayChartConfig,
|
||||
"chartConfigIdList",
|
||||
"_id",
|
||||
"chartConfig"
|
||||
)
|
||||
// Lookup para cardRotatingLayout.dataId
|
||||
.Lookup(
|
||||
_apiSettings.DisplayCardConfig,
|
||||
"cardRotatingLayout.dataId",
|
||||
"_id",
|
||||
"rotatingLayoutData"
|
||||
)
|
||||
|
||||
// Enriquecer cada elemento del array
|
||||
.AppendStage<BsonDocument>(new BsonDocument("$addFields",
|
||||
new BsonDocument("cardRotatingLayout",
|
||||
new BsonDocument("$map",
|
||||
new BsonDocument
|
||||
{
|
||||
{ "input", "$cardRotatingLayout" },
|
||||
{ "as", "item" },
|
||||
{
|
||||
"in",
|
||||
new BsonDocument("$mergeObjects", new BsonArray
|
||||
{
|
||||
"$$item",
|
||||
new BsonDocument("data",
|
||||
new BsonDocument("$arrayElemAt", new BsonArray
|
||||
{
|
||||
new BsonDocument("$filter", new BsonDocument
|
||||
{
|
||||
{ "input", "$rotatingLayoutData" },
|
||||
{ "as", "d" },
|
||||
{
|
||||
"cond",
|
||||
new BsonDocument("$eq", new BsonArray
|
||||
{
|
||||
"$$d._id",
|
||||
"$$item.dataId"
|
||||
})
|
||||
}
|
||||
}),
|
||||
0
|
||||
})
|
||||
)
|
||||
})
|
||||
}
|
||||
})
|
||||
)
|
||||
))
|
||||
|
||||
// limpiar auxiliar
|
||||
.AppendStage<BsonDocument>(new BsonDocument("$unset", "rotatingLayoutData"))
|
||||
.As<DisplayConfig>();
|
||||
|
||||
return await aggregate.FirstOrDefaultAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError("Error on config display repository on GetById Exception: {ex}", ex.Message);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<DisplayConfig?> GetDefault(DisplayConfigEnums.DisplayType type)
|
||||
{
|
||||
var filter = Builders<DisplayConfig>.Filter.And(
|
||||
Builders<DisplayConfig>.Filter.Eq(p => p.Type, type),
|
||||
Builders<DisplayConfig>.Filter.Eq(p => p.Hospital, "Default")
|
||||
);
|
||||
|
||||
var result = await Collection.FindAsync(filter);
|
||||
return result.FirstOrDefault();
|
||||
}
|
||||
|
||||
public async Task<DisplayConfig?> InsertOneAsyncAndReturn(DisplayConfig config)
|
||||
{
|
||||
try
|
||||
{
|
||||
await Collection.InsertOneAsync(config);
|
||||
return config;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex.Message);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<SmartDisplay?> UpdateSmartDisplay(ObjectId displayConfigId, SmartDisplay? newDisplayConfig)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (newDisplayConfig == null) return null;
|
||||
|
||||
var filter = Builders<DisplayConfig>.Filter.Eq("Id", displayConfigId);
|
||||
var update = Builders<DisplayConfig>.Update
|
||||
.Set(c => ((SmartDisplay)c).Pumps, newDisplayConfig.Pumps)
|
||||
.Set(c => ((SmartDisplay)c).HasCameras, newDisplayConfig.HasCameras)
|
||||
.Set(c => ((SmartDisplay)c).HasSound, newDisplayConfig.HasSound)
|
||||
.Set(c => ((SmartDisplay)c).CamerasAreActive, newDisplayConfig.CamerasAreActive)
|
||||
.Set(c => ((SmartDisplay)c).IsRotationEnabled, newDisplayConfig.IsRotationEnabled)
|
||||
.Set(c => ((SmartDisplay)c).CanChangeCameraMode, newDisplayConfig.CanChangeCameraMode)
|
||||
.Set(c => ((SmartDisplay)c).FieldList, newDisplayConfig.FieldList)
|
||||
.Set(c => ((SmartDisplay)c).ChartConfig, newDisplayConfig.ChartConfig)
|
||||
.Set(c => ((SmartDisplay)c).GraphLayout, newDisplayConfig.GraphLayout)
|
||||
.Set(c => ((SmartDisplay)c).SensorList, newDisplayConfig.SensorList)
|
||||
.Set(c => ((SmartDisplay)c).AlarmFieldList, newDisplayConfig.AlarmFieldList)
|
||||
.Set(c => c.HomeConfig, newDisplayConfig.HomeConfig)
|
||||
.Set(c => c.DetailConfigId, newDisplayConfig.DetailConfigId)
|
||||
.Set(c => ((SmartDisplay)c).CameraStreamType, newDisplayConfig.CameraStreamType)
|
||||
.Set(c => ((SmartDisplay)c).ColorConfig, newDisplayConfig.ColorConfig)
|
||||
.Set(c => ((SmartDisplay)c).RequestGroupedFieldList, newDisplayConfig.RequestGroupedFieldList)
|
||||
.Set(c => c.Hospital, newDisplayConfig.Hospital)
|
||||
// .Set(c => c.CardConfig, newDisplayConfig.CardConfig)
|
||||
.Set(c => c.DisplaySectionIdList, newDisplayConfig.DisplaySectionIdList)
|
||||
;
|
||||
|
||||
var c = await Collection.FindOneAndUpdateAsync(filter, update,
|
||||
new FindOneAndUpdateOptions<DisplayConfig, DisplayConfig> { ReturnDocument = ReturnDocument.After });
|
||||
return c as SmartDisplay;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.LogError($"Error on config display repository on UpdateSmartDisplay Exception: {e.Message}");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<bool> UpdateConfigColor(ObjectId objectIdConfigDisplay, ColorConfig colorConfig)
|
||||
{
|
||||
var filter = Builders<DisplayConfig>.Filter.Eq("Id", objectIdConfigDisplay);
|
||||
var updateDefinition = new List<UpdateDefinition<DisplayConfig>>();
|
||||
if (colorConfig.Level != null)
|
||||
updateDefinition.Add(Builders<DisplayConfig>.Update.Set("colorConfig.level", colorConfig.Level));
|
||||
if (colorConfig.Text != null)
|
||||
updateDefinition.Add(Builders<DisplayConfig>.Update.Set("colorConfig.text", colorConfig.Text));
|
||||
if (colorConfig.Arrow != null)
|
||||
updateDefinition.Add(Builders<DisplayConfig>.Update.Set("colorConfig.arrow", colorConfig.Arrow));
|
||||
if (colorConfig.Indicator != null)
|
||||
updateDefinition.Add(Builders<DisplayConfig>.Update.Set("colorConfig.indicator", colorConfig.Indicator));
|
||||
if (colorConfig.Graph != null)
|
||||
updateDefinition.Add(Builders<DisplayConfig>.Update.Set("colorConfig.graph", colorConfig.Graph));
|
||||
if (colorConfig.BoxNumber != null)
|
||||
updateDefinition.Add(Builders<DisplayConfig>.Update.Set("colorConfig.boxNumber", colorConfig.BoxNumber));
|
||||
if (colorConfig.BoxStatusColor != null)
|
||||
updateDefinition.Add(
|
||||
Builders<DisplayConfig>.Update.Set("colorConfig.boxStatusColor", colorConfig.BoxStatusColor));
|
||||
if (colorConfig.Test != null)
|
||||
updateDefinition.Add(Builders<DisplayConfig>.Update.Set("colorConfig.test", colorConfig.Test));
|
||||
if (colorConfig.Therapy != null)
|
||||
updateDefinition.Add(Builders<DisplayConfig>.Update.Set("colorConfig.therapy", colorConfig.Therapy));
|
||||
if (colorConfig.Procedure != null)
|
||||
updateDefinition.Add(Builders<DisplayConfig>.Update.Set("colorConfig.procedure", colorConfig.Procedure));
|
||||
var update = Builders<DisplayConfig>.Update.Combine(updateDefinition);
|
||||
try
|
||||
{
|
||||
var result = await Collection.UpdateOneAsync(filter, update);
|
||||
if (result.ModifiedCount > 0) return true; // Retorna el objeto actualizado si la modificación fue exitosa
|
||||
|
||||
return false; // Retorna nulo si no se encontró el documento o no se modificó
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error("Error UpdateConfigColor: {name}. Exception: {ex}", objectIdConfigDisplay, ex);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<bool> UpdateHeaderConfig(ObjectId objectIdConfigDisplay, HeaderConfig headerConfig)
|
||||
{
|
||||
var filter = Builders<DisplayConfig>.Filter.Eq("Id", objectIdConfigDisplay);
|
||||
var updateDefinition = new List<UpdateDefinition<DisplayConfig>>();
|
||||
if (headerConfig.PartnerLogo != null)
|
||||
updateDefinition.Add(
|
||||
Builders<DisplayConfig>.Update.Set("headerConfig.partnerLogo", headerConfig.PartnerLogo));
|
||||
if (headerConfig.CompanyLogo != null)
|
||||
updateDefinition.Add(
|
||||
Builders<DisplayConfig>.Update.Set("headerConfig.companyLogo", headerConfig.CompanyLogo));
|
||||
if (headerConfig.CenterLogo != null)
|
||||
updateDefinition.Add(
|
||||
Builders<DisplayConfig>.Update.Set("headerConfig.centerLogo", headerConfig.CenterLogo));
|
||||
if (headerConfig.MeddisLogo != null)
|
||||
updateDefinition.Add(
|
||||
Builders<DisplayConfig>.Update.Set("headerConfig.meddisLogo", headerConfig.MeddisLogo));
|
||||
if (headerConfig.UnitName != null)
|
||||
updateDefinition.Add(Builders<DisplayConfig>.Update.Set("headerConfig.unitName", headerConfig.UnitName));
|
||||
if (headerConfig.Cameras != null)
|
||||
updateDefinition.Add(Builders<DisplayConfig>.Update.Set("headerConfig.cameras", headerConfig.Cameras));
|
||||
if (headerConfig.Sensors != null)
|
||||
updateDefinition.Add(Builders<DisplayConfig>.Update.Set("headerConfig.sensors", headerConfig.Sensors));
|
||||
if (headerConfig.Fullscreen != null)
|
||||
updateDefinition.Add(
|
||||
Builders<DisplayConfig>.Update.Set("headerConfig.fullscreen", headerConfig.Fullscreen));
|
||||
if (headerConfig.Sounds != null)
|
||||
updateDefinition.Add(Builders<DisplayConfig>.Update.Set("headerConfig.sounds", headerConfig.Sounds));
|
||||
if (headerConfig.Sidebar != null)
|
||||
updateDefinition.Add(Builders<DisplayConfig>.Update.Set("headerConfig.sidebar", headerConfig.Sidebar));
|
||||
if (headerConfig.CurrentDateTime != null)
|
||||
updateDefinition.Add(Builders<DisplayConfig>.Update.Set("headerConfig.currentDateTime",
|
||||
headerConfig.CurrentDateTime));
|
||||
if (headerConfig.SectionTitle != null)
|
||||
updateDefinition.Add(
|
||||
Builders<DisplayConfig>.Update.Set("headerConfig.sectionTitle", headerConfig.SectionTitle));
|
||||
var update = Builders<DisplayConfig>.Update.Combine(updateDefinition);
|
||||
try
|
||||
{
|
||||
var result = await Collection.UpdateOneAsync(filter, update);
|
||||
if (result.ModifiedCount > 0) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error("Error UpdateConfigColor: {name}. Exception: {ex}", objectIdConfigDisplay, ex);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<bool> UpdateSetHomeBanner(ObjectId objectIdConfigDisplay, List<BannerItem> bannerItems)
|
||||
{
|
||||
var filter = Builders<DisplayConfig>.Filter.Eq("Id", objectIdConfigDisplay);
|
||||
var update = Builders<DisplayConfig>.Update
|
||||
.Set(c => ((DisplayNurse)c).HomeBanner, bannerItems);
|
||||
try
|
||||
{
|
||||
var result = await Collection.UpdateOneAsync(filter, update);
|
||||
if (result.ModifiedCount > 0) return true; // Retorna el objeto actualizado si la modificación fue exitosa
|
||||
|
||||
return false; // Retorna nulo si no se encontró el documento o no se modificó
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error("Error UpdateConfigColor: {name}. Exception: {ex}", objectIdConfigDisplay, ex);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<bool> UpdateBaseConfig(ObjectId objectIdConfigDisplay, DisplayConfig baseConfig)
|
||||
{
|
||||
var filter = Builders<DisplayConfig>.Filter.Eq("Id", objectIdConfigDisplay);
|
||||
// TODO NO ESPERA EL CARDCONFIG
|
||||
var (updateDefinition, _) = GetBaseUpdateDefinition(baseConfig);
|
||||
var update = Builders<DisplayConfig>.Update.Combine(updateDefinition);
|
||||
|
||||
try
|
||||
{
|
||||
var result = await Collection.UpdateOneAsync(filter, update);
|
||||
if (result.ModifiedCount > 0)
|
||||
// await UpdateFieldList(objectIdConfigDisplay, GenerateFieldListFromStrig(fieldList));
|
||||
return true; // Retorna el objeto actualizado si la modificación fue exitosa
|
||||
|
||||
return false; // Retorna nulo si no se encontró el documento o no se modificó
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error("Error UpdateBaseConfig: {name}. Exception: {ex}", objectIdConfigDisplay, ex);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<DisplayNurse?> UpdateDisplayNurse(ObjectId displayConfigId, DisplayNurseDto? newDisplayConfig,
|
||||
List<string> nurseObs)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (newDisplayConfig == null) return null;
|
||||
var filter = Builders<DisplayConfig>.Filter.Eq("Id", displayConfigId);
|
||||
var updateDefinition = new List<UpdateDefinition<DisplayConfig>>();
|
||||
if (newDisplayConfig.CardConfigId != null)
|
||||
updateDefinition.Add(
|
||||
Builders<DisplayConfig>.Update.Set(c => c.CardConfigId, newDisplayConfig.CardConfigId));
|
||||
if (newDisplayConfig.DetailConfigId != null)
|
||||
updateDefinition.Add(
|
||||
Builders<DisplayConfig>.Update.Set(c => c.DetailConfigId, newDisplayConfig.DetailConfigId));
|
||||
if (newDisplayConfig.HomeConfig != null)
|
||||
updateDefinition.Add(
|
||||
Builders<DisplayConfig>.Update.Set(c => c.HomeConfig, newDisplayConfig.HomeConfig));
|
||||
if (newDisplayConfig.Hospital != null)
|
||||
updateDefinition.Add(Builders<DisplayConfig>.Update.Set(c => c.Hospital, newDisplayConfig.Hospital));
|
||||
if (newDisplayConfig.HeaderConfig != null)
|
||||
updateDefinition.Add(
|
||||
Builders<DisplayConfig>.Update.Set(c => c.HeaderConfig, newDisplayConfig.HeaderConfig));
|
||||
if (newDisplayConfig.HomeBanner != null && newDisplayConfig.HomeBanner.Count != 0)
|
||||
updateDefinition.Add(Builders<DisplayConfig>.Update.Set(c => ((DisplayNurse)c).HomeBanner,
|
||||
newDisplayConfig.HomeBanner));
|
||||
if (newDisplayConfig.ColorConfig != null)
|
||||
updateDefinition.Add(Builders<DisplayConfig>.Update.Set(c => ((DisplayNurse)c).ColorConfig,
|
||||
newDisplayConfig.ColorConfig));
|
||||
if (newDisplayConfig.FormConfig != null)
|
||||
updateDefinition.Add(Builders<DisplayConfig>.Update.Set(c => ((DisplayNurse)c).FormConfig,
|
||||
newDisplayConfig.FormConfig));
|
||||
|
||||
var originalList = ExtractObservationFields(newDisplayConfig, nurseObs);
|
||||
if (originalList.Count > 0)
|
||||
updateDefinition.Add(
|
||||
Builders<DisplayConfig>.Update.Set(c => ((DisplayNurse)c).FieldList, originalList));
|
||||
|
||||
var update = Builders<DisplayConfig>.Update.Combine(updateDefinition);
|
||||
var c = await Collection.FindOneAndUpdateAsync(filter, update,
|
||||
new FindOneAndUpdateOptions<DisplayConfig, DisplayConfig> { ReturnDocument = ReturnDocument.After });
|
||||
if (c == null)
|
||||
{
|
||||
_logger.LogError("Error on config display repository on UpdateDisplayNurse unable to FindOneAndUpdate");
|
||||
return null;
|
||||
}
|
||||
|
||||
return c as DisplayNurse;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.LogError("Error on config display repository on UpdateDisplayNurse Exception: {eMessage}",
|
||||
e.Message);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<bool> UpdateDisplayConfigHospitalName(ObjectId objectIdConfigDisplay, string name)
|
||||
{
|
||||
var filter = Builders<DisplayConfig>.Filter.Eq(c => c.Id, objectIdConfigDisplay);
|
||||
var update = Builders<DisplayConfig>.Update.Set(c => c.Hospital, name);
|
||||
|
||||
var updatedConfig = await Collection.FindOneAndUpdateAsync(
|
||||
filter,
|
||||
update,
|
||||
new FindOneAndUpdateOptions<DisplayConfig> { ReturnDocument = ReturnDocument.After }
|
||||
);
|
||||
|
||||
if (updatedConfig == null)
|
||||
{
|
||||
_logger.LogError("Error in UpdateDisplayConfigHospitalName: Unable to find and update DisplayConfig.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public async Task<bool> UpdateFieldList(ObjectId objectIdConfigDisplay, List<Field> fields)
|
||||
{
|
||||
var filter = Builders<DisplayConfig>.Filter.Eq(x => x.Id, objectIdConfigDisplay);
|
||||
var update = Builders<DisplayConfig>.Update.Set(x => x.FieldList, fields);
|
||||
|
||||
var result = await Collection.UpdateOneAsync(filter, update);
|
||||
return result.ModifiedCount > 0;
|
||||
}
|
||||
|
||||
public async Task<DisplayConfig?> GetDefaultByUnitIdAndType(ObjectId unitId,
|
||||
DisplayConfigEnums.DisplayType displayType)
|
||||
{
|
||||
var unit = await _unitRepository.FindById(unitId);
|
||||
switch (displayType)
|
||||
{
|
||||
case DisplayConfigEnums.DisplayType.DisplayNurse:
|
||||
if (unit?.Configuration.PlanDisplayConfiguration == null) return null;
|
||||
return await GetById(unit.Configuration.PlanDisplayConfiguration.Value) as DisplayNurse;
|
||||
case DisplayConfigEnums.DisplayType.SmartDisplay:
|
||||
if (unit?.Configuration.SmartDisplayConfiguration == null) return null;
|
||||
return await GetById(unit.Configuration.SmartDisplayConfiguration.Value) as SmartDisplay;
|
||||
case DisplayConfigEnums.DisplayType.StandarDisplay:
|
||||
if (unit?.Configuration.StandarDisplayConfiguration == null) return null;
|
||||
return await GetById(unit.Configuration.StandarDisplayConfiguration.Value) as StandarDisplay;
|
||||
default: return null;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<DisplayConfig?> DeleteDisplayConfig(ObjectId objectIdConfigDisplay)
|
||||
{
|
||||
return await DeleteAsync(objectIdConfigDisplay);
|
||||
}
|
||||
|
||||
public Task<List<DisplayConfigMinimalResponse>> GetAllCompact()
|
||||
{
|
||||
var filter = Builders<DisplayConfig>.Filter.Empty;
|
||||
return Collection
|
||||
.Find(filter)
|
||||
.Project(d => new DisplayConfigMinimalResponse
|
||||
{
|
||||
Id = d.Id,
|
||||
Hospital = d.Hospital ?? "",
|
||||
Type = d.Type
|
||||
}).ToListAsync();
|
||||
}
|
||||
|
||||
public async Task<List<ObjectId>> GetAllByCardConfigId(ObjectId cardConfigId)
|
||||
{
|
||||
var filter = Builders<DisplayConfig>.Filter.Eq(d => d.CardConfigId, cardConfigId);
|
||||
|
||||
var result = await Collection.Find(filter)
|
||||
.Project(d => d.Id)
|
||||
.ToListAsync();
|
||||
|
||||
return result;
|
||||
}
|
||||
public async Task<List<ObjectId>> GetAllByCardConfigIdAndRotating(ObjectId cardConfigId)
|
||||
{
|
||||
var mainFilter = Builders<DisplayConfig>.Filter.Eq(d => d.CardConfigId, cardConfigId);
|
||||
|
||||
var rotatingFilter = Builders<DisplayConfig>.Filter.ElemMatch(
|
||||
"cardRotatingLayout",
|
||||
Builders<BsonDocument>.Filter.Eq("dataId", cardConfigId)
|
||||
);
|
||||
|
||||
var combinedFilter = Builders<DisplayConfig>.Filter.Or(mainFilter, rotatingFilter);
|
||||
|
||||
var result = await Collection.Find(combinedFilter)
|
||||
.Project(d => d.Id)
|
||||
.ToListAsync();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<bool> UpdateCardConfigId(ObjectId? displayConfigId, ObjectId? resultId)
|
||||
{
|
||||
var filter = Builders<DisplayConfig>.Filter.Eq(x => x.Id, displayConfigId);
|
||||
var update = Builders<DisplayConfig>.Update.Set(x => x.CardConfigId, resultId);
|
||||
|
||||
var result = await Collection.UpdateOneAsync(filter, update);
|
||||
return result.ModifiedCount > 0;
|
||||
}
|
||||
|
||||
public async Task<bool> AddChartId(ObjectId? displayConfigId, ObjectId newChartIdToAdd)
|
||||
{
|
||||
var filter = Builders<DisplayConfig>.Filter.Eq(x => x.Id, displayConfigId);
|
||||
var update = Builders<DisplayConfig>.Update
|
||||
.AddToSet(c => ((SmartDisplay)c).ChartConfigIdList, newChartIdToAdd);
|
||||
|
||||
var result = await Collection.UpdateOneAsync(filter, update);
|
||||
return result.ModifiedCount > 0;
|
||||
}
|
||||
|
||||
public async Task<UpdateResult> UpdateDeletedChartConfig(ObjectId deletedId)
|
||||
{
|
||||
try
|
||||
{
|
||||
var filter = Builders<DisplayConfig>.Filter.AnyEq("chartConfigIdList", deletedId);
|
||||
|
||||
var update = Builders<DisplayConfig>.Update.Pull("chartConfigIdList", deletedId);
|
||||
|
||||
return await Collection.UpdateManyAsync(filter, update);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError("Error actualizando referencias de ChartConfig borrado: {ex}", ex.Message);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public Task<ChartConfig> GetChartConfig(ObjectId objectIdConfigChart)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public async Task<bool> UpdateDetailConfigId(ObjectId? displayConfigId, ObjectId? resultId)
|
||||
{
|
||||
var filter = Builders<DisplayConfig>.Filter.Eq(x => x.Id, displayConfigId);
|
||||
var update = Builders<DisplayConfig>.Update.Set(x => x.DetailConfigId, resultId);
|
||||
|
||||
var result = await Collection.UpdateOneAsync(filter, update);
|
||||
return result.ModifiedCount > 0;
|
||||
}
|
||||
|
||||
public async Task<List<ObjectId>> GetAllByCardDetailConfigId(ObjectId baseConfigId)
|
||||
{
|
||||
var filter = Builders<DisplayConfig>.Filter.Eq(d => d.DetailConfigId, baseConfigId);
|
||||
|
||||
var result = await Collection.Find(filter)
|
||||
.Project(d => d.Id)
|
||||
.ToListAsync();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public sealed override async Task InsertInitialLoad()
|
||||
{
|
||||
// 1. Obtener todos los valores y castear al tipo IEnumerable<DisplayType>
|
||||
var allTypes = (DisplayConfigEnums.DisplayType[])Enum.GetValues(typeof(DisplayConfigEnums.DisplayType));
|
||||
|
||||
// 2. Usar LINQ para filtrar y convertir de nuevo a un array (o lista)
|
||||
var displayTypesToIterate = allTypes
|
||||
.Where(dt => dt != DisplayConfigEnums.DisplayType.Unknown) // Filtra el valor 'Unknown'
|
||||
.ToArray();
|
||||
foreach (var type in displayTypesToIterate)
|
||||
{
|
||||
var defaultConfigByType = await GetDefault(type);
|
||||
if (defaultConfigByType == null)
|
||||
switch (type)
|
||||
{
|
||||
case DisplayConfigEnums.DisplayType.DisplayNurse:
|
||||
var nurse = new DisplayNurse
|
||||
{
|
||||
Hospital = "Default",
|
||||
Type = DisplayConfigEnums.DisplayType.DisplayNurse,
|
||||
ColorConfig = new ColorConfig(),
|
||||
FormConfig = new FormConfig
|
||||
{
|
||||
Admission = new FormItemOverview { Nhc = true },
|
||||
Demographic = new FormItemOverview { Nhc = true },
|
||||
Discharge = new FormItemOverview { Nhc = true },
|
||||
IncomeInfo = new FormItemOverview { Nhc = true }
|
||||
},
|
||||
HomeBanner = []
|
||||
};
|
||||
await InsertOneAsyncAndReturn(nurse);
|
||||
break;
|
||||
case DisplayConfigEnums.DisplayType.SmartDisplay:
|
||||
var smart = new SmartDisplay
|
||||
{
|
||||
Hospital = "Default",
|
||||
Type = DisplayConfigEnums.DisplayType.SmartDisplay,
|
||||
ColorConfig = new ColorConfig()
|
||||
};
|
||||
await InsertOneAsyncAndReturn(smart);
|
||||
break;
|
||||
case DisplayConfigEnums.DisplayType.StandarDisplay:
|
||||
var standar = new StandarDisplay
|
||||
{
|
||||
Type = DisplayConfigEnums.DisplayType.StandarDisplay,
|
||||
Hospital = "Default"
|
||||
};
|
||||
await InsertOneAsyncAndReturn(standar);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Si alguno no existe crearlos
|
||||
}
|
||||
|
||||
private List<Field> ExtractObservationFields(DisplayNurseDto newDisplayConfig, List<string> nurseObs)
|
||||
{
|
||||
var fieldSet = new HashSet<string>();
|
||||
var regex = new Regex(@"""ManualObservationName""\s*:\s*\[\s*((?:""[^""]*""\s*,?\s*)+)\]",
|
||||
RegexOptions.Compiled);
|
||||
|
||||
// --- 1. CardConfig ---
|
||||
if (newDisplayConfig.CardConfig?.Rows is { Count: > 0 })
|
||||
FillHashSet(JsonConvert.SerializeObject(newDisplayConfig.CardConfig.Rows), regex, fieldSet);
|
||||
if (newDisplayConfig.CardConfig?.Rows is { Count: > 0 })
|
||||
foreach (var row in newDisplayConfig.CardConfig.Rows)
|
||||
ExtractFromCells(row.Cells, fieldSet);
|
||||
// --- 2. DetailConfig ---
|
||||
if (newDisplayConfig.DetailConfig?.NurseRows is { Count: > 0 })
|
||||
FillHashSet(JsonConvert.SerializeObject(newDisplayConfig.DetailConfig?.NurseRows), regex, fieldSet);
|
||||
if (newDisplayConfig.DetailConfig?.NurseRows is { Count: > 0 })
|
||||
foreach (var row in newDisplayConfig.DetailConfig.NurseRows)
|
||||
ExtractFromDetailsCells(row.Cells, fieldSet);
|
||||
// --- Result: convert to List<Field> ---
|
||||
return fieldSet
|
||||
.Distinct()
|
||||
.Select(name => new Field { Name = name, Last = nurseObs.Contains(name) ? 1 : 2 })
|
||||
.ToList();
|
||||
}
|
||||
|
||||
private void FillHashSet(string newDisplayConfig, Regex regex, HashSet<string> fieldSet)
|
||||
{
|
||||
var matches = regex.Matches(newDisplayConfig);
|
||||
|
||||
foreach (Match match in matches)
|
||||
if (match.Groups.Count > 1)
|
||||
{
|
||||
var arrayContent = match.Groups[1].Value;
|
||||
var items = Regex.Matches(arrayContent, @"""([^""]+)""");
|
||||
foreach (Match item in items) fieldSet.Add(item.Groups[1].Value);
|
||||
}
|
||||
}
|
||||
|
||||
private void ExtractFromCells(List<Cell>? cells, HashSet<string> fieldSet)
|
||||
{
|
||||
if (cells is null)
|
||||
return;
|
||||
|
||||
foreach (var cell in cells)
|
||||
{
|
||||
// 1. Extraer ObservationName
|
||||
if (cell.ObservationName is { Count: > 0 })
|
||||
foreach (var obsName in cell.ObservationName)
|
||||
fieldSet.Add(obsName);
|
||||
|
||||
// 2. Recursión: sub-observaciones
|
||||
if (cell.SubObs is { Count: > 0 })
|
||||
ExtractFromCells(cell.SubObs, fieldSet);
|
||||
}
|
||||
}
|
||||
|
||||
private void ExtractFromDetailsCells(List<CellDetails>? cells, HashSet<string> fieldSet)
|
||||
{
|
||||
if (cells is null)
|
||||
return;
|
||||
|
||||
foreach (var cell in cells)
|
||||
{
|
||||
// 1. Extraer ObservationName
|
||||
if (cell.ObservationName is { Count: > 0 })
|
||||
foreach (var obsName in cell.ObservationName)
|
||||
fieldSet.Add(obsName);
|
||||
|
||||
// 2. Recursión: sub-observaciones
|
||||
if (cell.Cells is { Count: > 0 })
|
||||
ExtractFromDetailsCells(cell.Cells, fieldSet);
|
||||
}
|
||||
}
|
||||
|
||||
private IFindFluent<DisplayConfig, DisplayConfigSummary> CreateFindFluentMinimal(
|
||||
List<FilterDefinition<DisplayConfig>> filters,
|
||||
SortDefinition<DisplayConfig> sort)
|
||||
{
|
||||
var combinedFilter = filters.Any()
|
||||
? Builders<DisplayConfig>.Filter.And(filters)
|
||||
: Builders<DisplayConfig>.Filter.Empty;
|
||||
|
||||
return Collection
|
||||
.Find(combinedFilter)
|
||||
.Sort(sort)
|
||||
.Project(d => new DisplayConfigSummary
|
||||
{
|
||||
Id = d.Id,
|
||||
Name = d.Hospital ?? "",
|
||||
Type = d.Type
|
||||
});
|
||||
}
|
||||
|
||||
private (List<UpdateDefinition<DisplayConfig>> Updates, List<string> Fields) GetBaseUpdateDefinition(
|
||||
DisplayConfig baseConfig)
|
||||
{
|
||||
var fieldList = new List<string>();
|
||||
var updateDefinition = new List<UpdateDefinition<DisplayConfig>>();
|
||||
// if (baseConfig.CardConfig != null)
|
||||
// {
|
||||
// updateDefinition.Add(Builders<DisplayConfig>.Update.Set(c => c.CardConfig, baseConfig.CardConfig));
|
||||
// fieldList.AddRange(baseConfig.CardConfig.GetAllObservationNames());
|
||||
// }
|
||||
if (baseConfig.DetailConfig != null)
|
||||
{
|
||||
updateDefinition.Add(Builders<DisplayConfig>.Update.Set(c => c.DetailConfig, baseConfig.DetailConfig));
|
||||
fieldList.AddRange(baseConfig.DetailConfig.GetAllObservationNames());
|
||||
}
|
||||
|
||||
if (baseConfig.HomeConfig != null)
|
||||
updateDefinition.Add(Builders<DisplayConfig>.Update.Set(c => c.HomeConfig, baseConfig.HomeConfig));
|
||||
if (baseConfig.Hospital != null)
|
||||
updateDefinition.Add(Builders<DisplayConfig>.Update.Set(c => c.Hospital, baseConfig.Hospital));
|
||||
if (baseConfig.HeaderConfig != null)
|
||||
updateDefinition.Add(Builders<DisplayConfig>.Update.Set(c => c.HeaderConfig, baseConfig.HeaderConfig));
|
||||
return (updateDefinition, fieldList);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
using adas_core.Application.Repositories.Interfaces;
|
||||
using adas_core.Domain.Models.AppSettings;
|
||||
using adas_core.Domain.Models.MongoModels;
|
||||
using adas_core.Domain.Models.Responses;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using MongoDB.Bson;
|
||||
using MongoDB.Driver;
|
||||
|
||||
namespace adas_core.Infrastructure.Repositories;
|
||||
|
||||
public class DisplayDetailConfigRepository : MongoRepository<CardDetailsConfig>, IDisplayDetailConfigRepository
|
||||
{
|
||||
private readonly ApiSettings _apiSettings;
|
||||
private readonly ILogger<DisplayDetailConfigRepository> _logger;
|
||||
|
||||
|
||||
|
||||
public DisplayDetailConfigRepository(
|
||||
IMongoDatabase database,
|
||||
ApiSettings apiSettings,
|
||||
ILogger<DisplayDetailConfigRepository> logger
|
||||
) : base(database)
|
||||
{
|
||||
_apiSettings = apiSettings;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public override string GetCollectionName()
|
||||
{
|
||||
return _apiSettings.DisplayDetailConfig;
|
||||
}
|
||||
|
||||
public async Task<List<CardDetailsConfig>> GetAll()
|
||||
{
|
||||
var result = await Collection.Find(Builders<CardDetailsConfig>.Filter.Empty).ToListAsync();
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<CardDetailsConfig?> GetById(ObjectId configId)
|
||||
{
|
||||
try
|
||||
{
|
||||
var result = await Collection.FindAsync(Builders<CardDetailsConfig>.Filter.Eq(p => p.Id, configId));
|
||||
return await result.FirstOrDefaultAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError("Error on config card display repository on GetById Exception: {ex}", ex.Message);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<CardDetailsConfig?> InsertOneAsyncAndReturn(CardDetailsConfig config)
|
||||
{
|
||||
try
|
||||
{
|
||||
await Collection.InsertOneAsync(config);
|
||||
return config;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex.Message);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<UpdateResponse<CardDetailsConfig?>> UpdateOne(CardDetailsConfig? config)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (config == null) return new UpdateResponse<CardDetailsConfig?>(0, null);
|
||||
var filter = Builders<CardDetailsConfig>.Filter.Eq(c => c.Id, config.Id);
|
||||
var update = Builders<CardDetailsConfig>.Update
|
||||
.Set(c => c.NurseRows, config.NurseRows)
|
||||
.Set(c => c.SmartSections, config.SmartSections)
|
||||
.Set(c => c.Header, config.Header);
|
||||
|
||||
// Realizamos la actualización
|
||||
var result = await Collection.UpdateOneAsync(filter, update);
|
||||
|
||||
// Buscamos el documento actual (ya actualizado o el existente si no hubo cambios)
|
||||
var updatedDoc = await Collection.Find(filter).FirstOrDefaultAsync();
|
||||
|
||||
// result.ModifiedCount será 1 si cambió algo, o 0 si los datos eran idénticos
|
||||
return new UpdateResponse<CardDetailsConfig?>(result.ModifiedCount, updatedDoc);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.LogError(e.Message);
|
||||
return new UpdateResponse<CardDetailsConfig?>(0, null);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<CardDetailsConfig?> DeleteOne(ObjectId configId)
|
||||
{
|
||||
return await DeleteAsync(configId);
|
||||
}
|
||||
|
||||
public Task<object> UpdateCardConfigId(ObjectId? displayConfigId, ObjectId? resultId)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,355 @@
|
||||
using adas_core.Application.Exceptions;
|
||||
using adas_core.Application.Repositories.Interfaces;
|
||||
using adas_core.Domain.Models.AppSettings;
|
||||
using adas_core.Domain.Models.Filter;
|
||||
using adas_core.Domain.Models.MongoModels;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using MongoDB.Bson;
|
||||
using MongoDB.Driver;
|
||||
using Serilog;
|
||||
using System.Text.RegularExpressions;
|
||||
using MongoUtils = adas_core.Infrastructure.Utils.MongoUtils;
|
||||
|
||||
namespace adas_core.Infrastructure.Repositories;
|
||||
|
||||
public class DisplayRepository : MongoRepository<Display>, IDisplayRepository
|
||||
{
|
||||
#region Properties
|
||||
|
||||
private readonly ApiSettings _apiSettings;
|
||||
|
||||
private readonly ILogger<DisplayRepository> _logger;
|
||||
// private readonly Idisplay<DisplayRepository> _logger;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
|
||||
public DisplayRepository(
|
||||
IOptions<ApiSettings> apiSettings,
|
||||
IMongoDatabase database,
|
||||
ILogger<DisplayRepository> logger) : base(database)
|
||||
{
|
||||
_logger = logger;
|
||||
_apiSettings = apiSettings.Value;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
#region Create
|
||||
|
||||
public override async Task CreateIndexes()
|
||||
{
|
||||
var options = new CreateIndexOptions<Display> { Background = true, Unique = false };
|
||||
|
||||
var indexes = new List<CreateIndexModel<Display>>
|
||||
{
|
||||
new("{ displayConfigId: 1 }", options),
|
||||
new("{ unitId: 1 }", options)
|
||||
};
|
||||
|
||||
await MongoUtils.EnsureIndexes(Collection, indexes);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Read
|
||||
|
||||
public override string GetCollectionName()
|
||||
{
|
||||
return _apiSettings.Displays;
|
||||
}
|
||||
|
||||
public async Task<List<Display>> GetAll()
|
||||
{
|
||||
var result = await Collection.Find(Builders<Display>.Filter.Empty).ToListAsync();
|
||||
return result;
|
||||
}
|
||||
|
||||
public IFindFluent<Display, Display> GetPaginatedDisplays(PaginationFilter filter)
|
||||
{
|
||||
var filterBuilder = Builders<Display>.Filter;
|
||||
var sort = Builders<Display>.Sort.Ascending("name");
|
||||
var filters = new List<FilterDefinition<Display>>();
|
||||
|
||||
if (filter.FilteredRequest == null)
|
||||
return CreateFindFluent(filters, sort);
|
||||
|
||||
// Text filter seguro
|
||||
if (!string.IsNullOrWhiteSpace(filter.FilteredRequest.Text))
|
||||
{
|
||||
var textFilter = filter.FilteredRequest.Text;
|
||||
|
||||
if (textFilter.Length > 100)
|
||||
throw new BadRequestException("Text filter too long");
|
||||
|
||||
var escapedTextFilter = Regex.Escape(textFilter);
|
||||
|
||||
filters.Add(filterBuilder.Regex(
|
||||
d => d.Name,
|
||||
new BsonRegularExpression(escapedTextFilter, "i")
|
||||
));
|
||||
}
|
||||
|
||||
// UnitId
|
||||
if (!string.IsNullOrWhiteSpace(filter.FilteredRequest.UnitId) &&
|
||||
ObjectId.TryParse(filter.FilteredRequest.UnitId, out var unitId))
|
||||
{
|
||||
filters.Add(filterBuilder.Eq(d => d.UnitId, unitId));
|
||||
}
|
||||
// UnitName fallback
|
||||
else if (!string.IsNullOrWhiteSpace(filter.FilteredRequest.UnitName))
|
||||
{
|
||||
filters.Add(filterBuilder.Eq(d => d.Unit!.Name, filter.FilteredRequest.UnitName));
|
||||
}
|
||||
|
||||
// DisplayType
|
||||
if (filter.FilteredRequest.DisplayType != null)
|
||||
{
|
||||
filters.Add(filterBuilder.Eq(d => d.Type, filter.FilteredRequest.DisplayType));
|
||||
}
|
||||
|
||||
return CreateFindFluent(filters, sort);
|
||||
}
|
||||
|
||||
private IFindFluent<Display, Display> CreateFindFluent(List<FilterDefinition<Display>> filters,
|
||||
SortDefinition<Display> sort)
|
||||
{
|
||||
var combinedFilter = filters.Any()
|
||||
? Builders<Display>.Filter.And(filters)
|
||||
: Builders<Display>.Filter.Empty; // Filtra todo si no hay filtros
|
||||
return Collection.Find(combinedFilter).Sort(sort);
|
||||
}
|
||||
|
||||
public async Task<List<Display>> GetByPointOfCare(PointOfCare pointOfCare)
|
||||
{
|
||||
var filter = Builders<Display>.Filter.AnyEq(x => x.PointOfCareIdList, pointOfCare.Id);
|
||||
var result = await Collection.Find(filter).ToListAsync();
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<Display?> GetByName(string name)
|
||||
{
|
||||
var result = await Collection.FindAsync(Builders<Display>.Filter.Eq(p => p.Name, name));
|
||||
return await result.FirstOrDefaultAsync();
|
||||
}
|
||||
|
||||
public async Task<Display?> GetById(ObjectId id)
|
||||
{
|
||||
var result = await Collection.FindAsync(Builders<Display>.Filter.Eq(p => p.Id, id));
|
||||
|
||||
return await result.FirstOrDefaultAsync();
|
||||
}
|
||||
|
||||
public async Task<Display?> GetByIdWithConfigDisplay(ObjectId id)
|
||||
{
|
||||
var pipeline = new BsonDocument[]
|
||||
{
|
||||
new("$match", new BsonDocument("_id", id)),
|
||||
new("$lookup", new BsonDocument
|
||||
{
|
||||
{ "from", "config_displays" },
|
||||
{ "localField", "displayConfigId" }, // Asumiendo que este es el campo que refiere a config_display
|
||||
{ "foreignField", "_id" },
|
||||
{ "as", "DisplayNurse" }
|
||||
}),
|
||||
new("$unwind", new BsonDocument
|
||||
{
|
||||
{ "path", "$configDisplay" },
|
||||
{ "preserveNullAndEmptyArrays", true }
|
||||
})
|
||||
};
|
||||
|
||||
var result = await Collection.AggregateAsync<Display>(pipeline, new AggregateOptions { AllowDiskUse = true });
|
||||
return await result.FirstOrDefaultAsync();
|
||||
}
|
||||
|
||||
public async Task<List<Display>> GetByUnitId(ObjectId id)
|
||||
{
|
||||
var filter = Builders<Display>.Filter.Eq(p => p.UnitId, id);
|
||||
var result = await Collection.Find(filter).ToListAsync();
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<long> CountByUnitId(ObjectId unitId)
|
||||
{
|
||||
try
|
||||
{
|
||||
return await Collection.CountDocumentsAsync(Builders<Display>.Filter.Eq(p => p.UnitId, unitId));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.LogError(e.Message);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<List<Display>> GetByConfigId(ObjectId id)
|
||||
{
|
||||
var result = await Collection.FindAsync(Builders<Display>.Filter.Eq(p => p.DisplayConfigId, id));
|
||||
return result.ToList();
|
||||
}
|
||||
|
||||
public async Task<List<Display>> GetByCardConfigId(ObjectId configId)
|
||||
{
|
||||
try
|
||||
{
|
||||
var aggregate = Collection.Aggregate()
|
||||
// 1. Unimos la colección Display con DisplayConfig
|
||||
.Lookup(
|
||||
_apiSettings.DisplaysConfig, // Nombre de la colección externa
|
||||
"displayConfigId", // Campo local en la colección 'Display'
|
||||
"_id", // Campo en la colección 'DisplayConfig'
|
||||
"displayConfig" // Nombre de la propiedad en la clase C# (debe coincidir)
|
||||
)
|
||||
// 2. Convertimos el array resultante del lookup en un objeto único
|
||||
.Unwind("displayConfig", new AggregateUnwindOptions<BsonDocument>
|
||||
{
|
||||
PreserveNullAndEmptyArrays = false // Si no tiene config, no nos interesa
|
||||
})
|
||||
// 3. Filtramos por la propiedad interna del objeto ya "unido"
|
||||
// Nota: Usamos el nombre del campo tal cual está en el BSON (normalmente camelCase)
|
||||
.Match(Builders<BsonDocument>.Filter.Eq("displayConfig.cardConfigId", configId))
|
||||
|
||||
// 4. Casteamos el resultado de vuelta a nuestra clase Display
|
||||
.As<Display>();
|
||||
|
||||
return await aggregate.ToListAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError("Error en GetByCardConfigId: {ex}", ex.Message);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<long> IsDisplayConfigInUse(ObjectId displayConfigId)
|
||||
{
|
||||
return await Collection.CountDocumentsAsync(
|
||||
Builders<Display>.Filter.Eq(p => p.DisplayConfigId, displayConfigId));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Update
|
||||
|
||||
public async Task<Display?> UpdatePointOfCareList(ObjectId objectId, List<ObjectId> listPocObId)
|
||||
{
|
||||
try
|
||||
{
|
||||
var filter = Builders<Display>.Filter.Eq("Id", objectId);
|
||||
var update = Builders<Display>.Update
|
||||
.Set(c => c.PointOfCareIdList, listPocObId);
|
||||
|
||||
return await Collection.FindOneAndUpdateAsync(filter, update,
|
||||
new FindOneAndUpdateOptions<Display, Display> { ReturnDocument = ReturnDocument.After });
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.LogError($"Unable to update pointOfCareList from Display Exception {e}");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<Display?> UpdateConfig(ObjectId objectId, DisplayConfig config)
|
||||
{
|
||||
try
|
||||
{
|
||||
var filter = Builders<Display>.Filter.Eq("Id", objectId);
|
||||
var update = Builders<Display>.Update
|
||||
.Set(c => c.DisplayConfig, config);
|
||||
|
||||
return await Collection.FindOneAndUpdateAsync(filter, update,
|
||||
new FindOneAndUpdateOptions<Display, Display> { ReturnDocument = ReturnDocument.After });
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.LogError($"Unable to update config from Display Exception {e.Message}");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<Display?> UpdateConfigId(ObjectId objectId, ObjectId displayConfigId)
|
||||
{
|
||||
try
|
||||
{
|
||||
var filter = Builders<Display>.Filter.Eq("Id", objectId);
|
||||
var update = Builders<Display>.Update
|
||||
.Set(c => c.DisplayConfigId, displayConfigId);
|
||||
|
||||
return await Collection.FindOneAndUpdateAsync(filter, update,
|
||||
new FindOneAndUpdateOptions<Display, Display> { ReturnDocument = ReturnDocument.After });
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.LogError($"Unable to update config from Display Exception {e.Message}");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<Display?> UpdateConfigPreset(ObjectId objectIdDisplay, ObjectId objectIdConfigDisplay)
|
||||
{
|
||||
try
|
||||
{
|
||||
var filter = Builders<Display>.Filter.Eq("Id", objectIdDisplay);
|
||||
var update = Builders<Display>.Update
|
||||
.Set(c => c.DisplayConfigId, objectIdConfigDisplay);
|
||||
|
||||
return await Collection.FindOneAndUpdateAsync(filter, update,
|
||||
new FindOneAndUpdateOptions<Display, Display> { ReturnDocument = ReturnDocument.After });
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.LogError($"Unable to update config from Display Exception: {e.Message}");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<Display> UpdateName(Display display, string name)
|
||||
{
|
||||
try
|
||||
{
|
||||
var filter = Builders<Display>.Filter.Eq("_id", display.Id);
|
||||
|
||||
var update = Builders<Display>.Update
|
||||
.Set(d => d.Name, name);
|
||||
|
||||
return await Collection.FindOneAndUpdateAsync(filter, update,
|
||||
new FindOneAndUpdateOptions<Display, Display> { ReturnDocument = ReturnDocument.After });
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex.Message);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Delete
|
||||
|
||||
public async Task<bool> DeleteManyByUnitId(ObjectId unitId)
|
||||
{
|
||||
try
|
||||
{
|
||||
var filter = Builders<Display>.Filter.Where(p => p.UnitId == unitId);
|
||||
await Collection.DeleteManyAsync(filter);
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Logger.Error(e.Message);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
using adas_core.Application.Repositories.Interfaces;
|
||||
using adas_core.Domain.Enums;
|
||||
using adas_core.Domain.Models.AppSettings;
|
||||
using adas_core.Domain.Models.MongoModels;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using MongoDB.Bson;
|
||||
using MongoDB.Driver;
|
||||
using MongoUtils = adas_core.Infrastructure.Utils.MongoUtils;
|
||||
|
||||
namespace adas_core.Infrastructure.Repositories;
|
||||
|
||||
public class HistoricalConfigChangesRepository : MongoRepository<HistoricalConfigChanges>,
|
||||
IHistoricalConfigChangesRepository
|
||||
{
|
||||
private readonly ApiSettings _apiSettings;
|
||||
private readonly ILogger<HistoricalConfigChangesRepository> _logger;
|
||||
|
||||
public HistoricalConfigChangesRepository(IOptions<ApiSettings> apiSettings, IMongoDatabase database,
|
||||
ILogger<HistoricalConfigChangesRepository> logger) : base(database)
|
||||
{
|
||||
if (apiSettings == null) throw new ArgumentNullException(nameof(apiSettings));
|
||||
_apiSettings = apiSettings.Value;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
|
||||
public override string GetCollectionName()
|
||||
{
|
||||
return _apiSettings.HistoricalConfigChanges ?? "historicalConfigChanges";
|
||||
}
|
||||
|
||||
public override async Task<HistoricalConfigChanges?> InsertOneAsync(HistoricalConfigChanges historicalConfigChanges)
|
||||
{
|
||||
try
|
||||
{
|
||||
await Collection.InsertOneAsync(historicalConfigChanges);
|
||||
return await FindById(historicalConfigChanges.Id);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError("Error inserting historicalConfigChanges {exMessage}", ex.Message);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public async Task<HistoricalConfigChanges?> Delete(ObjectId id)
|
||||
{
|
||||
return await DeleteAsync(id);
|
||||
}
|
||||
|
||||
public async Task<ICollection<HistoricalConfigChanges>> FindAll()
|
||||
{
|
||||
var result = await Collection.FindAsync(_ => true);
|
||||
return await result.ToListAsync();
|
||||
}
|
||||
|
||||
public async Task<List<ObjectId>> FindAllIds()
|
||||
{
|
||||
List<ObjectId> listCollection = [];
|
||||
var allCollection = await Collection.FindAsync(_ => true);
|
||||
|
||||
listCollection.AddRange(allCollection.ToList().Select(item => item.Id));
|
||||
|
||||
return listCollection;
|
||||
}
|
||||
|
||||
public async Task<HistoricalConfigChanges?> FindById(ObjectId id)
|
||||
{
|
||||
var result = await Collection.FindAsync(Builders<HistoricalConfigChanges>.Filter.Eq(x => x.Id, id));
|
||||
return await result.FirstOrDefaultAsync();
|
||||
}
|
||||
|
||||
|
||||
public async Task<HistoricalConfigChanges?> Update(HistoricalConfigChanges historicalConfigChanges)
|
||||
{
|
||||
var filter = Builders<HistoricalConfigChanges>.Filter.Eq("_id", historicalConfigChanges.Id);
|
||||
var update = Builders<HistoricalConfigChanges>.Update
|
||||
.Set(c => c, historicalConfigChanges);
|
||||
|
||||
return await Collection.FindOneAndUpdateAsync(
|
||||
filter,
|
||||
update,
|
||||
new FindOneAndUpdateOptions<HistoricalConfigChanges, HistoricalConfigChanges>
|
||||
{
|
||||
ReturnDocument = ReturnDocument.After
|
||||
});
|
||||
}
|
||||
|
||||
public async Task<ICollection<HistoricalConfigChanges>> FindLastHistoricalConfigChangesByType(
|
||||
DisplayConfigEnums.ConfigTypes cfgType, int num = 10)
|
||||
{
|
||||
var filterDefinitionBuilder = Builders<HistoricalConfigChanges>.Filter;
|
||||
var filter = filterDefinitionBuilder.Eq(c => c.ConfigType, cfgType);
|
||||
|
||||
var result = await Collection.FindAsync(
|
||||
filter,
|
||||
new FindOptions<HistoricalConfigChanges>
|
||||
{ Sort = Builders<HistoricalConfigChanges>.Sort.Descending("time"), Limit = num }
|
||||
);
|
||||
|
||||
return await result.ToListAsync();
|
||||
}
|
||||
|
||||
public async Task<ICollection<HistoricalConfigChanges>> FindLastHistoricalConfigChangesByUser(string user,
|
||||
DisplayConfigEnums.ConfigTypes? cfgType = null, int num = 10)
|
||||
{
|
||||
var filterDefinitionBuilder = Builders<HistoricalConfigChanges>.Filter;
|
||||
var filter = filterDefinitionBuilder.Eq(c => c.Username, user);
|
||||
|
||||
if (cfgType != null) filter &= filterDefinitionBuilder.Eq(c => c.ConfigType, cfgType.Value);
|
||||
|
||||
var result = await Collection.FindAsync(
|
||||
filter,
|
||||
new FindOptions<HistoricalConfigChanges>
|
||||
{ Sort = Builders<HistoricalConfigChanges>.Sort.Descending("time"), Limit = num }
|
||||
);
|
||||
|
||||
return await result.ToListAsync();
|
||||
}
|
||||
|
||||
public override async Task CreateIndexes()
|
||||
{
|
||||
try
|
||||
{
|
||||
var options = new CreateIndexOptions { Background = true, Unique = false };
|
||||
var indexes = new List<CreateIndexModel<HistoricalConfigChanges>>
|
||||
{
|
||||
new("{ configType: 1, time:-1 }", options),
|
||||
new("{ username: 1, time: -1 }", options)
|
||||
};
|
||||
await MongoUtils.EnsureIndexes(Collection, indexes);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.LogError(
|
||||
"error creating indexes for HistoricalConfigChanges collection {eMessage} TRACE: {eStackTrace}",
|
||||
e.Message, e.StackTrace);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
using adas_core.Application.Exceptions;
|
||||
using adas_core.Application.Repositories.Interfaces;
|
||||
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 Serilog;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace adas_core.Infrastructure.Repositories;
|
||||
|
||||
public class LightBeaconRepository : MongoRepository<LightBeacon>, ILightBeaconRepository
|
||||
{
|
||||
private readonly ApiSettings _apiSettings;
|
||||
|
||||
|
||||
public LightBeaconRepository(IMongoDatabase database, IOptions<ApiSettings> apiSettings) : base(database)
|
||||
{
|
||||
_apiSettings = apiSettings.Value;
|
||||
}
|
||||
|
||||
public override string GetCollectionName()
|
||||
{
|
||||
return _apiSettings.LightBeacons;
|
||||
}
|
||||
|
||||
public List<LightBeacon> GetLightBeaconInList(List<ObjectId> configurationRelayList)
|
||||
{
|
||||
var filterBuilder = Builders<LightBeacon>.Filter;
|
||||
|
||||
var filter = filterBuilder.And(
|
||||
filterBuilder.In(r => r.Id, configurationRelayList));
|
||||
|
||||
return Collection.Find(filter).ToList();
|
||||
}
|
||||
|
||||
public async Task<LightBeacon?> GetById(ObjectId relayId)
|
||||
{
|
||||
try
|
||||
{
|
||||
var filter = Builders<LightBeacon>.Filter.Eq(x => x.Id, relayId);
|
||||
var result = await Collection.FindAsync(filter, null);
|
||||
return result.FirstOrDefault();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error("Exception trying to get relay by id: {id}. Exception {e}", relayId, e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<LightBeacon?> GetByName(string? requestRelayName)
|
||||
{
|
||||
var filterBuilder = Builders<LightBeacon>.Filter;
|
||||
|
||||
var filter = filterBuilder.Eq(r => r.Name, requestRelayName);
|
||||
|
||||
return await Collection.Find(filter).FirstOrDefaultAsync();
|
||||
}
|
||||
|
||||
public async Task<LightBeacon?> InsertOneAsyncAndReturn(LightBeacon beacon)
|
||||
{
|
||||
try
|
||||
{
|
||||
await Collection.InsertOneAsync(beacon);
|
||||
return beacon;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(ex.Message);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public IFindFluent<LightBeacon, LightBeacon> GetPaginatedRelays(PaginationFilter filter)
|
||||
{
|
||||
var filterBuilder = Builders<LightBeacon>.Filter;
|
||||
var sort = Builders<LightBeacon>.Sort.Ascending("name");
|
||||
var filters = new List<FilterDefinition<LightBeacon>>();
|
||||
|
||||
if (filter.FilteredRequest == null)
|
||||
return CreateFindFluent(filters, sort);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(filter.FilteredRequest.Text))
|
||||
{
|
||||
var textFilter = filter.FilteredRequest.Text;
|
||||
|
||||
if (textFilter.Length > 100)
|
||||
throw new BadRequestException("Text filter too long");
|
||||
|
||||
var textFilterEscaped = Regex.Escape(textFilter);
|
||||
|
||||
filters.Add(
|
||||
filterBuilder.Regex(
|
||||
p => p.Name,
|
||||
new BsonRegularExpression(textFilterEscaped, "i")
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return CreateFindFluent(filters, sort);
|
||||
}
|
||||
|
||||
public Task<List<LightBeacon>> GetSearchByName(string textToSearch)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private IFindFluent<LightBeacon, LightBeacon> CreateFindFluent(List<FilterDefinition<LightBeacon>> filters, SortDefinition<LightBeacon> sort)
|
||||
{
|
||||
var combinedFilter = filters.Any()
|
||||
? Builders<LightBeacon>.Filter.And(filters)
|
||||
: Builders<LightBeacon>.Filter.Empty;
|
||||
return Collection.Find(combinedFilter).Sort(sort);
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,142 @@
|
||||
using adas_core.Application.Repositories.Interfaces;
|
||||
using adas_core.Domain.Models;
|
||||
using adas_core.Domain.Models.AppSettings;
|
||||
using adas_core.Domain.Models.Filter;
|
||||
using Microsoft.Extensions.Options;
|
||||
using MongoDB.Bson;
|
||||
using MongoDB.Driver;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace adas_core.Infrastructure.Repositories;
|
||||
|
||||
public class MedicineRepository : MongoRepository<Medicine>, IMedicineRepository
|
||||
{
|
||||
private readonly ApiSettings _apiSettings;
|
||||
|
||||
public MedicineRepository(IOptions<ApiSettings> apiSettings, IMongoDatabase database) : base(database)
|
||||
{
|
||||
if (apiSettings == null) throw new ArgumentNullException(nameof(apiSettings));
|
||||
_apiSettings = apiSettings.Value;
|
||||
} //For testing
|
||||
|
||||
|
||||
|
||||
public override string GetCollectionName()
|
||||
{
|
||||
return _apiSettings.Medicines ?? "medicines";
|
||||
}
|
||||
|
||||
public async Task<Medicine?> GetMedicine(string code)
|
||||
{
|
||||
var result = await Collection.FindAsync(x => x.Codes.Contains(code) || x.Notes.Contains(code));
|
||||
|
||||
return await result.FirstOrDefaultAsync();
|
||||
}
|
||||
|
||||
|
||||
public async Task<List<Medicine>> GetMedicineByCodeOrNote(List<string> codeNotes)
|
||||
{
|
||||
var filter = Builders<Medicine>.Filter.AnyIn("Codes", codeNotes.ToArray());
|
||||
var result = await Collection.FindAsync(filter);
|
||||
|
||||
return result.ToList();
|
||||
}
|
||||
|
||||
public async Task<Medicine?> GetMedicineByName(string name)
|
||||
{
|
||||
var filter = Builders<Medicine>.Filter.Eq(p => p.Name, name);
|
||||
var result = await Collection.FindAsync(filter);
|
||||
|
||||
return await result.FirstOrDefaultAsync();
|
||||
}
|
||||
|
||||
public async Task<List<Medicine>> GetAll()
|
||||
{
|
||||
var result = await Collection.FindAsync(_ => true);
|
||||
|
||||
return result.ToList();
|
||||
}
|
||||
|
||||
public async Task<Medicine?> GetMedicineById(ObjectId medicineId)
|
||||
{
|
||||
var filter = Builders<Medicine>.Filter.Eq(p => p.Id, medicineId);
|
||||
var result = await Collection.FindAsync(filter);
|
||||
|
||||
return await result.FirstOrDefaultAsync();
|
||||
}
|
||||
|
||||
public async Task<Medicine?> PostMedicine(Medicine medicine)
|
||||
{
|
||||
await Collection.InsertOneAsync(medicine);
|
||||
var result = await Collection.FindAsync(v => v.Name == medicine.Name);
|
||||
|
||||
return await result.FirstOrDefaultAsync();
|
||||
}
|
||||
|
||||
public async Task<Medicine?> UpdateMedicine(Medicine medicine)
|
||||
{
|
||||
await UpdateOneAsync(medicine.Id, medicine);
|
||||
|
||||
return medicine;
|
||||
}
|
||||
|
||||
public async Task DeleteMedicineById(ObjectId medicineId)
|
||||
{
|
||||
var filter = Builders<Medicine>.Filter.Eq(po => po.Id, medicineId);
|
||||
|
||||
await Collection.DeleteOneAsync(filter);
|
||||
}
|
||||
|
||||
public IFindFluent<Medicine, Medicine> GetPaginatedMedicines(PaginationFilter filter)
|
||||
{
|
||||
// Crear variable con la clase que construye los filtros que necesitamos
|
||||
var filterBuilder = Builders<Medicine>.Filter;
|
||||
// Crear una lista de filtros que pueden venir de tu servicio
|
||||
var filters = new List<FilterDefinition<Medicine>>();
|
||||
// Ordenar los resultados por "time" en orden descendente
|
||||
var sort = Builders<Medicine>.Sort.Ascending("name");
|
||||
if (filter.FilteredRequest != null)
|
||||
{
|
||||
var requestFilter = filter.FilteredRequest;
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(requestFilter.MedicineName))
|
||||
{
|
||||
var escapedTextFilter = Regex.Escape(requestFilter.MedicineName);
|
||||
filters.Add(filterBuilder.Regex(m => m.Name,
|
||||
new BsonRegularExpression(escapedTextFilter, "i")));
|
||||
}
|
||||
if (!string.IsNullOrWhiteSpace(requestFilter.MedicineCode))
|
||||
filters.Add(filterBuilder.AnyEq(m => m.Codes, requestFilter.MedicineCode));
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(requestFilter.MedicineType))
|
||||
filters.Add(filterBuilder.AnyEq(m => m.Type, requestFilter.MedicineType));
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(requestFilter.MedicineGroup))
|
||||
filters.Add(filterBuilder.AnyEq(m => m.Group, requestFilter.MedicineGroup));
|
||||
}
|
||||
|
||||
if (filters.Count == 0)
|
||||
return Collection.Find(_ => true).Sort(sort);
|
||||
|
||||
var combinedFilter = Builders<Medicine>.Filter.And(filters);
|
||||
|
||||
return Collection
|
||||
.Find(combinedFilter)
|
||||
.Sort(sort);
|
||||
}
|
||||
|
||||
public IAggregateFluent<BsonDocument> GetDistinctFieldDataQuery(string field)
|
||||
{
|
||||
return Collection.Aggregate()
|
||||
.Unwind(field)
|
||||
.Group(new BsonDocument { { "_id", $"${field}" } })
|
||||
.Sort(new BsonDocument { { "_id", 1 } })
|
||||
.Project(new BsonDocument { { field, "$_id" }, { "_id", 0 } });
|
||||
}
|
||||
|
||||
|
||||
public Task<List<string>> GetAllGroups()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
using adas_core.Application.Repositories.Interfaces;
|
||||
using adas_core.Domain.Models.AppSettings;
|
||||
using adas_core.Infrastructure.Utils;
|
||||
using Microsoft.Extensions.Options;
|
||||
using MongoDB.Bson;
|
||||
using MongoDB.Driver;
|
||||
using Serilog;
|
||||
|
||||
namespace adas_core.Infrastructure.Repositories;
|
||||
|
||||
public abstract class MongoRepository<T> : IMongoRepository<T>
|
||||
{
|
||||
protected readonly IMongoDatabase Db;
|
||||
|
||||
private IMongoCollection<T>? _collection;
|
||||
|
||||
// protected MongoRepository(IOptions<DatabaseSettings> dbSettings)
|
||||
// {
|
||||
// Db = MongoDbHostBuilderExtension.GetMongoDb(dbSettings);
|
||||
// }
|
||||
|
||||
protected MongoRepository(IMongoDatabase database)
|
||||
{
|
||||
Db = database;
|
||||
}
|
||||
|
||||
public abstract string GetCollectionName();
|
||||
|
||||
public IMongoCollection<T> Collection
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_collection == null)
|
||||
{
|
||||
var collectionName = GetCollectionName();
|
||||
if (!CollectionExists(collectionName)) Db.CreateCollection(collectionName);
|
||||
_collection = Db.GetCollection<T>(collectionName);
|
||||
_ = CreateIndexes();
|
||||
_ = InsertInitialLoad();
|
||||
}
|
||||
|
||||
return _collection;
|
||||
}
|
||||
set => _collection = value;
|
||||
}
|
||||
|
||||
public virtual async Task InsertOneAsync(T obj)
|
||||
{
|
||||
try
|
||||
{
|
||||
await Collection.InsertOneAsync(obj);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error("An error occurred: {ExMessage}", ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task UpdateOneAsync(ObjectId id, T obj)
|
||||
{
|
||||
try
|
||||
{
|
||||
var filter = Builders<T>.Filter.Eq("_id", id);
|
||||
|
||||
await Collection.ReplaceOneAsync(filter, obj, new ReplaceOptions { IsUpsert = true });
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error("Error updating id: {Id}. Exception:{Ex}, stackTrace: {Trace}", id.ToString(), ex.Message,
|
||||
ex.StackTrace);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<T?> DeleteAsync(ObjectId id)
|
||||
{
|
||||
try
|
||||
{
|
||||
var filter = Builders<T>.Filter.Eq("_id", id);
|
||||
return await Collection.FindOneAndDeleteAsync(filter);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error("An error occurred: {ExMessage}", ex.Message);
|
||||
return default;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual Task CreateIndexes()
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public virtual Task InsertInitialLoad()
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public virtual async Task InsertManyAsync(List<T> obj)
|
||||
{
|
||||
try
|
||||
{
|
||||
InsertManyOptions options = new() { IsOrdered = false };
|
||||
await Collection.InsertManyAsync(obj, options);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error("An error occurred: {ExMessage}", ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
protected async Task UpdateManyObjectIdAsync(string nameId, ObjectId id, ObjectId oldId)
|
||||
{
|
||||
try
|
||||
{
|
||||
var update = Builders<T>.Update.Set(nameId, id);
|
||||
var filter = Builders<T>.Filter.Eq(nameId, oldId);
|
||||
|
||||
await Collection.UpdateManyAsync(filter, update);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error("An error occurred: {ExMessage}", ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
protected async Task<T?> DeleteAsync(string id)
|
||||
{
|
||||
try
|
||||
{
|
||||
var filter = Builders<T>.Filter.Eq("_id", id);
|
||||
return await Collection.FindOneAndDeleteAsync(filter);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error("An error occurred: {ExMessage}", ex.Message);
|
||||
return default;
|
||||
}
|
||||
}
|
||||
|
||||
protected bool CollectionExists(string collectionName)
|
||||
{
|
||||
try
|
||||
{
|
||||
var filter = new BsonDocument("name", collectionName);
|
||||
var options = new ListCollectionNamesOptions { Filter = filter };
|
||||
|
||||
return Db.ListCollectionNames(options).Any();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error("An error occurred: {ExMessage}", ex.Message);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,161 @@
|
||||
using adas_core.Application.Repositories.Interfaces;
|
||||
using adas_core.Domain.Models.AppSettings;
|
||||
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 NoticeRepository : MongoRepository<Notice>, INoticeRepository
|
||||
{
|
||||
private readonly ApiSettings _apiSettings;
|
||||
|
||||
public NoticeRepository(IOptions<ApiSettings>? apiSettings, IMongoDatabase database) : base(database)
|
||||
{
|
||||
if (apiSettings != null)
|
||||
_apiSettings = apiSettings.Value;
|
||||
else
|
||||
throw new ArgumentNullException(nameof(apiSettings));
|
||||
}
|
||||
|
||||
|
||||
|
||||
public override string GetCollectionName()
|
||||
{
|
||||
return _apiSettings.Notices;
|
||||
}
|
||||
|
||||
public override async Task InsertOneAsync(Notice notice)
|
||||
{
|
||||
try
|
||||
{
|
||||
notice.NoticeDate = DateTime.UtcNow;
|
||||
await Collection.InsertOneAsync(notice);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Warning("Exception trying to insert notice: {notice}. Exception {e}", notice, e);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task Delete(ObjectId id)
|
||||
{
|
||||
try
|
||||
{
|
||||
var filter = Builders<Notice>.Filter.Eq(x => x.Id, id);
|
||||
await Collection.DeleteOneAsync(filter, null);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error("Exception trying to delete notice: {id}. Exception {e}", id, e);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task Update(Notice notice)
|
||||
{
|
||||
try
|
||||
{
|
||||
await UpdateOneAsync(notice.Id, notice);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error("Exception trying to update notice: {notice}. Exception {e}", notice, e);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<Notice>> FindAll()
|
||||
{
|
||||
try
|
||||
{
|
||||
var result = await Collection.FindAsync(_ => true);
|
||||
return await result.ToListAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error("Error getting all notices. Exception: {ex}", ex);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<Notice?> FindById(ObjectId id)
|
||||
{
|
||||
try
|
||||
{
|
||||
var filter = Builders<Notice>.Filter.Eq(p => p.Id, id);
|
||||
var result = await Collection.FindAsync(filter);
|
||||
|
||||
return await result.FirstOrDefaultAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error("Error searching notice by id: {id}. Exception: {ex}", id, ex);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<Notice>?> FindByDate(DateTime date)
|
||||
{
|
||||
try
|
||||
{
|
||||
var filter = Builders<Notice>.Filter.Eq(p => p.NoticeDate, date);
|
||||
var result = await Collection.FindAsync(filter);
|
||||
|
||||
return result.ToEnumerable();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error("Error searching notice by date: {date}. Exception: {ex}", date, ex);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<Notice>?> FindByType(string type)
|
||||
{
|
||||
try
|
||||
{
|
||||
var filter = Builders<Notice>.Filter.Eq(p => p.NoticeType, type);
|
||||
var result = await Collection.FindAsync(filter);
|
||||
|
||||
return result.ToEnumerable();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error("Error searching notice by type: {date}. Exception: {ex}", type, ex);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<Notice>?> FindByDisplayId(ObjectId displayId)
|
||||
{
|
||||
try
|
||||
{
|
||||
var filter = Builders<Notice>.Filter.Eq(p => p.DisplayId, displayId);
|
||||
var result = await Collection.FindAsync(filter);
|
||||
|
||||
return result.ToEnumerable();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error("Error searching notices by display id: {id}. Exception: {ex}", displayId, ex);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public override async Task CreateIndexes()
|
||||
{
|
||||
var options = new CreateIndexOptions { Background = true, Unique = false };
|
||||
|
||||
var indexes = new List<CreateIndexModel<Notice>>
|
||||
{
|
||||
new("{ noticeType: 1, noticeDate: -1 }", options),
|
||||
new("{ noticeDate: -1 }", options)
|
||||
};
|
||||
|
||||
await MongoUtils.EnsureIndexes(Collection, indexes);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,160 @@
|
||||
using System.Diagnostics;
|
||||
using adas_core.Application.Repositories.Interfaces;
|
||||
using adas_core.Domain.Models;
|
||||
using adas_core.Domain.Models.AppSettings;
|
||||
using Microsoft.Extensions.Options;
|
||||
using MongoDB.Bson;
|
||||
using MongoDB.Driver;
|
||||
using Serilog;
|
||||
|
||||
namespace adas_core.Infrastructure.Repositories;
|
||||
|
||||
public class ObservationArchiveRepository : MongoRepository<PatientObservation>, IObservationArchiveRepository
|
||||
{
|
||||
private readonly ApiSettings _apiSettings;
|
||||
|
||||
public ObservationArchiveRepository(IOptions<ApiSettings> apiSettings, IMongoDatabase database) : base(database)
|
||||
{
|
||||
if (apiSettings == null) throw new ArgumentNullException(nameof(apiSettings));
|
||||
_apiSettings = apiSettings.Value;
|
||||
} //For testing
|
||||
|
||||
|
||||
|
||||
|
||||
public async Task<List<PatientObservation>> AggregatedPatientLastObservations(ObjectId patientId, int num,
|
||||
DateTime lastDate, List<string>? filterObservations = null)
|
||||
{
|
||||
filterObservations = await AggregatePatientObservations(patientId, filterObservations);
|
||||
var results = new List<PatientObservation>();
|
||||
|
||||
foreach (var obs in filterObservations)
|
||||
{
|
||||
var filter = Builders<PatientObservation>.Filter.And(
|
||||
Builders<PatientObservation>.Filter.Eq(o => o.PatientId, patientId),
|
||||
Builders<PatientObservation>.Filter.Eq(o => o.Name, obs),
|
||||
Builders<PatientObservation>.Filter.Lte(o => o.Time, lastDate)
|
||||
);
|
||||
|
||||
var sort = Builders<PatientObservation>.Sort.Descending(o => o.Time);
|
||||
|
||||
results.AddRange(Collection.Find(filter).Sort(sort).Limit(num).ToEnumerable());
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
public override string GetCollectionName()
|
||||
{
|
||||
return _apiSettings.ArchivePatientsObservations ?? "archive_patients_observations";
|
||||
}
|
||||
|
||||
public new async Task InsertOneAsync(PatientObservation patientObservation)
|
||||
{
|
||||
const int maxRetries = 2; // Número máximo de reintentos
|
||||
var retryCount = 0;
|
||||
|
||||
while (true)
|
||||
try
|
||||
{
|
||||
await Collection.InsertOneAsync(patientObservation);
|
||||
return;
|
||||
}
|
||||
catch (MongoWriteException ex) when (ex.WriteError.Category == ServerErrorCategory.DuplicateKey)
|
||||
{
|
||||
retryCount++;
|
||||
|
||||
Log.Warning(
|
||||
"Duplicate key error encountered. Retrying with new ObjectId. Attempt {attempt} of {maxRetries}",
|
||||
retryCount, maxRetries);
|
||||
|
||||
patientObservation.Id = new ObjectId();
|
||||
Log.Information("Generated ObjectId: {objectId}", patientObservation.Id);
|
||||
|
||||
if (retryCount >= maxRetries)
|
||||
{
|
||||
Log.Error("Maximum retry attempts reached. Could not insert document due to duplicate key error.");
|
||||
throw; // Re-lanzar la excepción después de alcanzar el número máximo de reintentos
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error("Error inserting patient observation: {exMessage}", ex.Message);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task DeleteBeforeDate(DateTime date)
|
||||
{
|
||||
var filter = Builders<PatientObservation>.Filter.Lt(po => po.Time, date);
|
||||
await Collection.DeleteManyAsync(filter);
|
||||
}
|
||||
|
||||
public async Task<long> InsertBatch(IEnumerable<PatientObservation> observations)
|
||||
{
|
||||
var writes = new List<WriteModel<PatientObservation>>();
|
||||
writes.AddRange(observations.Select(d => new InsertOneModel<PatientObservation>(d)));
|
||||
|
||||
var bulkInsert = await Collection.BulkWriteAsync(writes);
|
||||
|
||||
return bulkInsert.InsertedCount;
|
||||
}
|
||||
|
||||
public async Task<List<PatientObservation>> FindAllFromPatient(ObjectId patientId)
|
||||
{
|
||||
var filter = Builders<PatientObservation>.Filter.Eq(p => p.PatientId, patientId);
|
||||
var result = await Collection.FindAsync(filter);
|
||||
|
||||
return await result.ToListAsync();
|
||||
}
|
||||
|
||||
private async Task<List<string>> AggregatePatientObservations(ObjectId patientId,
|
||||
List<string>? filterObservations = null)
|
||||
{
|
||||
var matchPatient = new BsonDocument
|
||||
{
|
||||
{ "patientid", patientId },
|
||||
{ "name", new BsonDocument { { "$ne", BsonNull.Value } } }
|
||||
};
|
||||
|
||||
if (filterObservations == null || !filterObservations.Any())
|
||||
{
|
||||
// GET DISTINCT OBSERVATIONS
|
||||
var distinctObs = new BsonDocument
|
||||
{
|
||||
{
|
||||
"$group", new BsonDocument
|
||||
{
|
||||
{ "_id", "1" },
|
||||
{
|
||||
"obs", new BsonDocument
|
||||
{
|
||||
{ "$addToSet", "$name" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
var distinctPipeline = new[]
|
||||
{
|
||||
new()
|
||||
{
|
||||
{
|
||||
"$match", matchPatient
|
||||
}
|
||||
},
|
||||
distinctObs
|
||||
};
|
||||
Debug.WriteLine("AggregatedArchivedPatientLastObservations distinct obs: \n" + distinctPipeline.ToJson());
|
||||
var resultList =
|
||||
await Collection.AggregateAsync<BsonDocument>(distinctPipeline,
|
||||
new AggregateOptions { AllowDiskUse = true });
|
||||
var result = resultList.ToList().FirstOrDefault();
|
||||
|
||||
if (result != null && result.Any())
|
||||
filterObservations = result.GetValue("obs").AsBsonArray.Select(it => it.AsString).ToList();
|
||||
}
|
||||
|
||||
return filterObservations ?? [];
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,34 @@
|
||||
using adas_core.Application.Repositories.Interfaces;
|
||||
using adas_core.Domain.Models.AppSettings;
|
||||
using adas_core.Domain.Models.MongoModels;
|
||||
using Microsoft.Extensions.Options;
|
||||
using MongoDB.Driver;
|
||||
|
||||
namespace adas_core.Infrastructure.Repositories;
|
||||
|
||||
public class PoCMappingRepository : MongoRepository<PoCMapping>, IPoCMappingRepository
|
||||
{
|
||||
private readonly ApiSettings _apiSettings;
|
||||
|
||||
public PoCMappingRepository(IOptions<ApiSettings> apiSettings, IMongoDatabase database) : base(database)
|
||||
{
|
||||
_apiSettings = apiSettings.Value;
|
||||
} //For testing
|
||||
|
||||
|
||||
|
||||
public override string GetCollectionName()
|
||||
{
|
||||
return _apiSettings.Mappings;
|
||||
}
|
||||
|
||||
public async Task<PoCMapping?> FindByKey(string key)
|
||||
{
|
||||
var filterBuilder = Builders<PoCMapping>.Filter;
|
||||
var filter = filterBuilder.Eq(config => config.Id, key);
|
||||
|
||||
var result = await Collection.FindAsync(filter);
|
||||
|
||||
return await result.FirstOrDefaultAsync();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
using adas_core.Application.Repositories.Interfaces;
|
||||
using adas_core.Domain.Models;
|
||||
using adas_core.Domain.Models.AppSettings;
|
||||
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 PatientArchiveRepository : MongoRepository<Patient>, IPatientArchiveRepository
|
||||
{
|
||||
private readonly ApiSettings _apiSettings;
|
||||
|
||||
|
||||
public PatientArchiveRepository(IOptions<ApiSettings> apiSettings, IMongoDatabase database) : base(database)
|
||||
{
|
||||
if (apiSettings == null) throw new ArgumentNullException(nameof(apiSettings));
|
||||
_apiSettings = apiSettings.Value;
|
||||
} //For testing
|
||||
|
||||
|
||||
|
||||
|
||||
public override string GetCollectionName()
|
||||
{
|
||||
return _apiSettings.ArchivePatient ?? "archive_patient";
|
||||
}
|
||||
|
||||
public async Task<Patient?> FindByPatientNumber(string patientNumber)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(patientNumber)) return null;
|
||||
|
||||
var filterBuilder = Builders<Patient>.Filter;
|
||||
var filter = filterBuilder.Eq(p => p.PatientNumber, patientNumber);
|
||||
|
||||
var result = await Collection.FindAsync(filter);
|
||||
|
||||
return await result.FirstOrDefaultAsync();
|
||||
}
|
||||
|
||||
|
||||
public async Task<List<Patient>> FindAll()
|
||||
{
|
||||
var filterBuilder = Builders<Patient>.Filter;
|
||||
var filter = filterBuilder.Empty;
|
||||
|
||||
var result = await Collection.FindAsync(filter);
|
||||
|
||||
return await result.ToListAsync();
|
||||
}
|
||||
|
||||
public async Task<Patient?> 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<Patient>.Filter.And(
|
||||
Builders<Patient>.Filter.Eq(p => p.PatientNumber, patientNumber)
|
||||
)).ToListAsync();
|
||||
// Si hay mas de una coincidencia devolvemos null por que puede no estar completo el patientNumber
|
||||
return patient.Count > 1 ? null : patient.FirstOrDefault();
|
||||
}
|
||||
|
||||
public override async Task InsertOneAsync(Patient obj)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (obj.PatientNumber != null)
|
||||
{
|
||||
var patient = await FindByPatientNumber(obj.PatientNumber);
|
||||
if (patient != null)
|
||||
{
|
||||
patient.Allergies = obj.Allergies;
|
||||
patient.Doctors = obj.Doctors;
|
||||
patient.Procedures?.AddRange(obj.Procedures ?? []);
|
||||
patient.Tests?.AddRange(obj.Tests ?? []);
|
||||
patient.Treatment?.AddRange(obj.Treatment ?? []);
|
||||
patient.Diagnosis = obj.Diagnosis;
|
||||
patient.DiagnosisAux = obj.DiagnosisAux;
|
||||
patient.Insulation = obj.Insulation;
|
||||
patient.Mobility = obj.Mobility;
|
||||
patient.Origin = obj.Origin;
|
||||
patient.OriginAux = obj.OriginAux;
|
||||
patient.Person = patient.Person;
|
||||
patient.ArchiveDate = DateTime.UtcNow;
|
||||
patient.Visits = obj.Visits;
|
||||
patient.AccessControl = obj.AccessControl;
|
||||
patient.AdmTime = obj.AdmTime;
|
||||
patient.PointOfCareId = obj.PointOfCareId;
|
||||
patient.UnitId = obj.UnitId;
|
||||
patient.TherapeuticCeiling = obj.TherapeuticCeiling;
|
||||
patient.Altable = obj.Altable;
|
||||
if (patient.HistoricalLocations == null)
|
||||
patient.HistoricalLocations = obj.HistoricalLocations;
|
||||
else if (obj.HistoricalLocations != null)
|
||||
foreach (var objHistoricalLocation in obj.HistoricalLocations)
|
||||
if (!patient.HistoricalLocations.Any(c=> c.AdmTime == objHistoricalLocation.AdmTime))
|
||||
patient.HistoricalLocations.Add(objHistoricalLocation);
|
||||
|
||||
await UpdateOneAsync(patient.Id, patient);
|
||||
}
|
||||
else
|
||||
{
|
||||
await base.InsertOneAsync(obj);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
await base.InsertOneAsync(obj);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Warning("Exception trying to insert archive patient: {obj}. Exception {e}", obj, e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public override async Task CreateIndexes()
|
||||
{
|
||||
var options = new CreateIndexOptions { Background = true, Unique = false };
|
||||
var indexes = new List<CreateIndexModel<Patient>>
|
||||
{
|
||||
new("{ patientNumber: 1 }", options)
|
||||
};
|
||||
await MongoUtils.EnsureIndexes(Collection, indexes);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
using adas_core.Application.Repositories.Interfaces;
|
||||
using adas_core.Domain.Models.AppSettings;
|
||||
using adas_core.Domain.Models.MongoModels;
|
||||
using Microsoft.Extensions.Options;
|
||||
using MongoDB.Bson;
|
||||
using MongoDB.Driver;
|
||||
|
||||
namespace adas_core.Infrastructure.Repositories;
|
||||
|
||||
public class PatientCarePlanRepository : MongoRepository<PatientCarePlan>, IPatientCarePlanRepository
|
||||
{
|
||||
#region Properties
|
||||
|
||||
private readonly ApiSettings _apiSettings;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Update
|
||||
|
||||
public async Task UpdateManyObjectId(string patientid, ObjectId patientId, ObjectId oldId)
|
||||
{
|
||||
await UpdateManyObjectIdAsync(patientid, patientId, oldId);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
|
||||
|
||||
|
||||
public PatientCarePlanRepository(
|
||||
IOptions<ApiSettings> apiSettings,
|
||||
IMongoDatabase database
|
||||
) : base(database)
|
||||
{
|
||||
_apiSettings = apiSettings.Value;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Read
|
||||
|
||||
public override string GetCollectionName()
|
||||
{
|
||||
return _apiSettings.PatientCarePlan ?? "patients_care_plan";
|
||||
}
|
||||
|
||||
public async Task<List<PatientCarePlan>> FindByPatientId(ObjectId patientId)
|
||||
{
|
||||
var result = await Collection.FindAsync(Builders<PatientCarePlan>.Filter.Eq(p => p.PatientId, patientId));
|
||||
return result.ToList();
|
||||
}
|
||||
|
||||
public async Task<List<PatientCarePlan>> FindByUserId(ObjectId userId)
|
||||
{
|
||||
var result = await Collection.FindAsync(Builders<PatientCarePlan>.Filter.Eq(p => p.UserId, userId));
|
||||
return result.ToList();
|
||||
}
|
||||
|
||||
public async Task<List<PatientCarePlan>> FindAll()
|
||||
{
|
||||
var result = await Collection.Find(Builders<PatientCarePlan>.Filter.Empty).ToListAsync();
|
||||
return result;
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,973 @@
|
||||
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.Filter;
|
||||
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 System.Text.RegularExpressions;
|
||||
using MongoUtils = adas_core.Infrastructure.Utils.MongoUtils;
|
||||
|
||||
namespace adas_core.Infrastructure.Repositories;
|
||||
|
||||
public class PatientRepository : MongoRepository<Patient>, IPatientRepository
|
||||
{
|
||||
private readonly ApiSettings _apiSettings;
|
||||
|
||||
public PatientRepository(IOptions<ApiSettings> apiSettings, IMongoDatabase database) : base(database)
|
||||
{
|
||||
if (apiSettings == null) throw new ArgumentNullException(nameof(apiSettings));
|
||||
_apiSettings = apiSettings.Value;
|
||||
} //For testing
|
||||
|
||||
// public PatientRepository(IOptions<ApiSettings> apiSettings, IOptions<DatabaseSettings> dbSetting) :
|
||||
// base(dbSetting)
|
||||
// {
|
||||
// if (apiSettings == null) throw new ArgumentNullException(nameof(apiSettings));
|
||||
// _apiSettings = apiSettings.Value;
|
||||
// }
|
||||
|
||||
public override string GetCollectionName()
|
||||
{
|
||||
return _apiSettings.Patients ?? "patients";
|
||||
}
|
||||
|
||||
public async Task<Patient?> FindById(ObjectId id)
|
||||
{
|
||||
try
|
||||
{
|
||||
var filter = Builders<Patient>.Filter.Eq(p => p.Id, id);
|
||||
var result = await Collection.FindAsync(filter);
|
||||
|
||||
return await result.FirstOrDefaultAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error("Error searching patient by id: {id}. Exception: {ex}", id, ex);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<Patient?> FindByPointOfCareId(ObjectId id)
|
||||
{
|
||||
try
|
||||
{
|
||||
var filter = Builders<Patient>.Filter.Eq(p => p.PointOfCareId, id);
|
||||
var result = await Collection.FindAsync(filter);
|
||||
|
||||
return await result.FirstOrDefaultAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error("Error searching patient by id: {id}. Exception: {ex}", id, ex);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<Patient> FindByUnitAndPocId(ObjectId unit, ObjectId pointOfCare)
|
||||
{
|
||||
try
|
||||
{
|
||||
var filter = Builders<Patient>.Filter.And(
|
||||
Builders<Patient>.Filter.Eq(p => p.PointOfCareId, pointOfCare),
|
||||
Builders<Patient>.Filter.Eq(p => p.UnitId, unit)
|
||||
);
|
||||
var result = await Collection.FindAsync(filter);
|
||||
|
||||
return await result.FirstOrDefaultAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error("Error searching patient by unitId: {unitid} pointOfCareid: {id}. Exception: {ex}", unit,
|
||||
pointOfCare, ex);
|
||||
return null!;
|
||||
}
|
||||
}
|
||||
|
||||
//Deprecated
|
||||
public async Task<Patient?> FindByLocation(PatientLocation? location)
|
||||
{
|
||||
if (location == null)
|
||||
return null;
|
||||
// Primero encontrar la unidad
|
||||
|
||||
var filterBuilder = Builders<Patient>.Filter;
|
||||
var filter = filterBuilder.Empty;
|
||||
|
||||
if (!string.IsNullOrEmpty(location.UnitName) && !string.IsNullOrEmpty(location.Bed))
|
||||
filter = filterBuilder.And(
|
||||
filterBuilder.Eq(p => p.UnitString, location.UnitName),
|
||||
filterBuilder.Eq(p => p.Bed, location.Bed)
|
||||
);
|
||||
else if (!string.IsNullOrEmpty(location.Bed)) filter = filterBuilder.Eq(p => p.Bed, location.Bed);
|
||||
|
||||
var result = await Collection.Find(filter).Limit(1).FirstOrDefaultAsync();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
public override async Task InsertOneAsync(Patient patient)
|
||||
{
|
||||
try
|
||||
{
|
||||
patient.CreationDate = DateTime.UtcNow;
|
||||
await base.InsertOneAsync(patient);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine(e);
|
||||
|
||||
var patientAux = await FindByLocation(patient.Location);
|
||||
if (patientAux != null && patientAux.PatientNumber == patient.PatientNumber)
|
||||
{
|
||||
Log.Warning("Exception trying to insert an existing patient: {patient}. Exception {e}", patient, e);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.Error("Exception trying to insert patient: {patient}. Exception {e}", patient, e);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public async Task Update(Patient patient)
|
||||
{
|
||||
patient.UpdateDate = DateTime.UtcNow;
|
||||
await UpdateOneAsync(patient.Id, patient);
|
||||
}
|
||||
|
||||
public async Task Delete(ObjectId id)
|
||||
{
|
||||
var filter = Builders<Patient>.Filter.Eq(x => x.Id, id);
|
||||
await Collection.DeleteOneAsync(filter, null);
|
||||
}
|
||||
|
||||
public async Task UpdateLocation(ObjectId id, PatientLocation location)
|
||||
{
|
||||
var patient = await FindById(id);
|
||||
if (patient == null)
|
||||
{
|
||||
Log.Warning("Patient not found for updating location: {id}", id);
|
||||
return;
|
||||
}
|
||||
|
||||
patient.UpdateDate = DateTime.UtcNow;
|
||||
patient.Location = location;
|
||||
await UpdateOneAsync(patient.Id, patient);
|
||||
/*var filterBuilder = Builders<Patient>.Filter;
|
||||
var filter = filterBuilder.Eq(p => p.Id, id);
|
||||
|
||||
var update = Builders<Patient>.Update
|
||||
.Set(p => p.Bed, location?.Bed)
|
||||
.Set(p => p.UnitString, location?.UnitName)
|
||||
.Set(p => p.UpdateDate, DateTime.UtcNow)
|
||||
.AddToSet(p => p.HistoricalLocations, new KeyValuePair<string, PatientLocation>(DateTime.UtcNow.ToString("o"), location));
|
||||
|
||||
var result = await Collection.UpdateOneAsync(filter, update);
|
||||
|
||||
Log.Debug("Update location result: {result}", result);*/
|
||||
}
|
||||
|
||||
public async Task UpdateLocation(ObjectId id, ObjectId location)
|
||||
{
|
||||
var patient = await FindById(id);
|
||||
if (patient == null)
|
||||
{
|
||||
Log.Warning("Patient not found for updating location: {id}", id);
|
||||
return;
|
||||
}
|
||||
|
||||
patient.UpdateDate = DateTime.UtcNow;
|
||||
patient.PointOfCareId = location;
|
||||
await UpdateOneAsync(patient.Id, patient);
|
||||
}
|
||||
|
||||
public async Task UpdateAttendingDoctor(ObjectId id, Person attendingDoctor)
|
||||
{
|
||||
var update = Builders<Patient>.Update
|
||||
.Set(p => p.AttendingDoctor, attendingDoctor)
|
||||
.Set(p => p.UpdateDate, DateTime.UtcNow);
|
||||
|
||||
await Collection.UpdateOneAsync(p => p.Id == id, update);
|
||||
}
|
||||
|
||||
public async Task UpdatePatientData(ObjectId id, string patientNumber, Person data, bool updatePatientNumber = true)
|
||||
{
|
||||
var filterBuilder = Builders<Patient>.Filter;
|
||||
var updateBuilder = Builders<Patient>.Update.Set(p => p.Person, data).Set(p => p.UpdateDate, DateTime.UtcNow);
|
||||
|
||||
var filter = filterBuilder.Eq(p => p.Id, id);
|
||||
var update = updateBuilder;
|
||||
|
||||
if (updatePatientNumber) update = update.Set(p => p.PatientNumber, patientNumber);
|
||||
|
||||
await Collection.UpdateOneAsync(filter, update);
|
||||
}
|
||||
|
||||
|
||||
public async Task<Patient?> FindByPatientNumber(string patientNumber)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(patientNumber)) return null;
|
||||
|
||||
//Último paciente admitido
|
||||
var patient = await Collection.Find(Builders<Patient>.Filter.And(
|
||||
Builders<Patient>.Filter.Eq(p => p.DisTime, null),
|
||||
Builders<Patient>.Filter.Eq(p => p.PatientNumber, patientNumber)
|
||||
))
|
||||
.Sort(Builders<Patient>.Sort.Descending(p => p.AdmTime))
|
||||
.Limit(1)
|
||||
.FirstOrDefaultAsync();
|
||||
|
||||
|
||||
//Último con fecha de alta más reciente
|
||||
patient ??= await Collection.Find(Builders<Patient>.Filter.And(
|
||||
Builders<Patient>.Filter.Ne(p => p.DisTime, null),
|
||||
Builders<Patient>.Filter.Eq(p => p.PatientNumber, patientNumber)
|
||||
))
|
||||
.Sort(Builders<Patient>.Sort.Descending(p => p.DisTime))
|
||||
.Limit(1)
|
||||
.FirstOrDefaultAsync();
|
||||
|
||||
return patient;
|
||||
}
|
||||
|
||||
public async Task<Patient?> SearchByPatientNumberAndDistinctUnit(string patientNumber, ObjectId unitId)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(patientNumber)) return null;
|
||||
|
||||
// Paciente ubicado en un PoC pero en diferente unidad
|
||||
var patient = await Collection.Find(Builders<Patient>.Filter.And(
|
||||
Builders<Patient>.Filter.Eq(p => p.PatientNumber, patientNumber),
|
||||
Builders<Patient>.Filter.Ne(p => p.UnitId, unitId)
|
||||
)).ToListAsync();
|
||||
// Si hay mas de una coincidencia devolvemos null por que puede no estar completo el patientNumber
|
||||
return patient.Count > 1 ? null : patient.FirstOrDefault();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error(
|
||||
"Error Search By Patient Number And Distinct Unit on patient repository patientNumber: {patientNumber}, unitId: {unitId}, Excepción: {e}",
|
||||
patientNumber, unitId, e.Message);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<List<Patient>> FindAllPatientWithFinishedProcedures(int archiveProcedureEndDateAfterMinutes)
|
||||
{
|
||||
var currentDateTime = DateTime.UtcNow;
|
||||
|
||||
// Filtro para documentos que contienen al menos un procedimiento con opción "procedure"
|
||||
var filter = Builders<Patient>.Filter.ElemMatch(
|
||||
x => x.Procedures,
|
||||
procedure =>
|
||||
//procedure.OptionType == "procedure" &&
|
||||
procedure.EndDate.HasValue
|
||||
);
|
||||
|
||||
// Ejecutar la consulta inicial y traer los documentos
|
||||
var patientsWithProcedures = await Collection.Find(filter).ToListAsync();
|
||||
|
||||
// Aplicar el filtro adicional en memoria
|
||||
var patientsWithFinishedProcedures = patientsWithProcedures.Where(patient =>
|
||||
patient.Procedures != null &&
|
||||
patient.Procedures.Any(procedure =>
|
||||
procedure is
|
||||
{
|
||||
//OptionType: "procedure",
|
||||
EndDate: not null
|
||||
} &&
|
||||
procedure.EndDate.Value.AddMinutes(archiveProcedureEndDateAfterMinutes) < currentDateTime
|
||||
)
|
||||
).ToList();
|
||||
|
||||
return patientsWithFinishedProcedures;
|
||||
}
|
||||
|
||||
public async Task<List<Patient>> FindAllPatientWithFinishedTests(int archiveTestEndDateAfterMinutes)
|
||||
{
|
||||
var currentDateTime = DateTime.UtcNow;
|
||||
|
||||
// Filtro para documentos que contienen al menos un procedimiento con opción "procedure"
|
||||
var filter = Builders<Patient>.Filter.ElemMatch(
|
||||
x => x.Tests,
|
||||
procedure => //procedure.OptionType == "test" &&
|
||||
procedure.EndDate.HasValue
|
||||
);
|
||||
|
||||
// Ejecutar la consulta inicial y traer los documentos
|
||||
var patientsWithTests = await Collection.Find(filter).ToListAsync();
|
||||
|
||||
// Aplicar el filtro adicional en memoria
|
||||
var patientsWithFinishedTests = patientsWithTests.Where(patient =>
|
||||
patient.Tests != null &&
|
||||
patient.Tests.Any(procedure =>
|
||||
procedure is
|
||||
{
|
||||
//OptionType: "test",
|
||||
EndDate: not null
|
||||
} &&
|
||||
procedure.EndDate.Value.AddMinutes(archiveTestEndDateAfterMinutes) < currentDateTime
|
||||
)
|
||||
).ToList();
|
||||
|
||||
return patientsWithFinishedTests;
|
||||
}
|
||||
|
||||
public async Task<List<Patient>> FindAllPatientWithFinishedTreatment(int archiveTreatmentEndDateAfterMinutes)
|
||||
{
|
||||
var currentDateTime = DateTime.UtcNow;
|
||||
|
||||
// Filtro para documentos que contienen al menos un procedimiento con opción "procedure"
|
||||
var filter = Builders<Patient>.Filter.ElemMatch(
|
||||
x => x.Treatment,
|
||||
treatment => treatment.EndDate.HasValue
|
||||
);
|
||||
|
||||
// Ejecutar la consulta inicial y traer los documentos
|
||||
var patientsWithTreatment = await Collection.Find(filter).ToListAsync();
|
||||
|
||||
// Aplicar el filtro adicional en memoria
|
||||
var patientsWithFinishedTreatments = patientsWithTreatment.Where(patient =>
|
||||
patient.Treatment != null &&
|
||||
patient.Treatment.Any(treatment =>
|
||||
treatment.EndDate.HasValue &&
|
||||
treatment.EndDate.Value.AddMinutes(archiveTreatmentEndDateAfterMinutes) < currentDateTime
|
||||
)
|
||||
).ToList();
|
||||
|
||||
return patientsWithFinishedTreatments;
|
||||
}
|
||||
|
||||
public async Task<List<Patient>> UpdateMasterListOption(List<ObjectId> unitIds, UpdateOptionMasterListDto opt,
|
||||
string typeName)
|
||||
{
|
||||
var isParsed = Enum.TryParse<MasterListType>(typeName, out var parsedTypeName);
|
||||
if (isParsed)
|
||||
{
|
||||
// Tener en cuenta los datos auxiliares ya que pueden ser texto libre o asignarse el establecido en la lista
|
||||
// originAux / diagnosisAux modificar en caso de ser el mismo que el padre
|
||||
// Notificar a todos los fronts con el nuevo valor de cada paciente por el id de los poc's afectados(?)
|
||||
var filterUnit = Builders<Patient>.Filter.In("unitId", unitIds);
|
||||
switch (parsedTypeName)
|
||||
{
|
||||
case MasterListType.DiagnosisList:
|
||||
|
||||
var diagnosisFilter = Builders<Patient>.Filter.Eq(
|
||||
"diagnosis.name", opt.OldOption?.Name
|
||||
);
|
||||
var filterUpdateDiagnosis = Builders<Patient>.Filter.And(filterUnit, diagnosisFilter);
|
||||
var updateDiagnosis = Builders<Patient>.Update
|
||||
.Set("diagnosis.name", opt.UpdatedOption?.Name)
|
||||
.Set("diagnosis.description", opt.UpdatedOption?.Description);
|
||||
await Collection.UpdateManyAsync(filterUpdateDiagnosis, updateDiagnosis);
|
||||
|
||||
await Collection.UpdateManyAsync(Builders<Patient>.Filter.And(filterUnit,
|
||||
Builders<Patient>.Filter.Eq(
|
||||
"diagnosisAux", opt.OldOption?.Name
|
||||
)), Builders<Patient>.Update
|
||||
.Set("diagnosisAux", opt.UpdatedOption?.Name));
|
||||
|
||||
// Filtro para devolver los documentos actualizados (OR entre diagnosis.name y diagnosisAux)
|
||||
var diagnosisFilterToReturn =
|
||||
Builders<Patient>.Filter.Eq("diagnosis.name", opt.UpdatedOption?.Name);
|
||||
var diagnosisAuxFilterToReturn =
|
||||
Builders<Patient>.Filter.Eq("diagnosisAux", opt.UpdatedOption?.Name);
|
||||
var filterToReturn = Builders<Patient>.Filter.And(
|
||||
filterUnit,
|
||||
Builders<Patient>.Filter.Or(diagnosisFilterToReturn, diagnosisAuxFilterToReturn)
|
||||
);
|
||||
|
||||
// Devolver los documentos actualizados
|
||||
var updatedDocuments = await Collection.Find(filterToReturn).ToListAsync();
|
||||
return updatedDocuments;
|
||||
case MasterListType.DoctorList:
|
||||
// Filtro para encontrar el elemento en el array `doctors` que coincida con el nombre
|
||||
var doctorFilter = Builders<Patient>.Filter.ElemMatch(
|
||||
"doctors",
|
||||
Builders<Patient>.Filter.Eq("name", opt.OldOption?.Name)
|
||||
);
|
||||
var filterUpdateDoctor = Builders<Patient>.Filter.And(filterUnit, doctorFilter);
|
||||
|
||||
// Actualizar todos los elementos de la lista `doctors` que coincidan
|
||||
var updateDoctor = Builders<Patient>.Update.Set(
|
||||
"doctors.$[nameElem].name", opt.UpdatedOption?.Name
|
||||
);
|
||||
|
||||
// Definir filtros únicos para cada campo utilizado
|
||||
var arrayFilters = new List<ArrayFilterDefinition>
|
||||
{
|
||||
new BsonDocumentArrayFilterDefinition<BsonDocument>(
|
||||
new BsonDocument("nameElem.name", opt.OldOption?.Name))
|
||||
};
|
||||
|
||||
// Agregar filtro para `optionType` solo si es necesario
|
||||
if (!string.IsNullOrEmpty(opt.OldOption?.OptionType))
|
||||
{
|
||||
updateDoctor = updateDoctor.Set(
|
||||
"doctors.$[typeElem].optionType", opt.UpdatedOption?.OptionType
|
||||
);
|
||||
|
||||
arrayFilters.Add(
|
||||
new BsonDocumentArrayFilterDefinition<BsonDocument>(
|
||||
new BsonDocument("typeElem.optionType", opt.OldOption.OptionType)));
|
||||
}
|
||||
|
||||
var updateOptions = new UpdateOptions { ArrayFilters = arrayFilters };
|
||||
|
||||
// Ejecutar la actualización
|
||||
await Collection.UpdateManyAsync(filterUpdateDoctor, updateDoctor, updateOptions);
|
||||
|
||||
// Devolver los documentos actualizados
|
||||
var doctorFilterToReturn = Builders<Patient>.Filter.ElemMatch(
|
||||
"doctors",
|
||||
Builders<Patient>.Filter.Eq("name", opt.UpdatedOption?.Name)
|
||||
);
|
||||
|
||||
var filterToReturnDoctor = Builders<Patient>.Filter.And(filterUnit, doctorFilterToReturn);
|
||||
|
||||
var updatedDoctorDocuments = await Collection.Find(filterToReturnDoctor).ToListAsync();
|
||||
|
||||
return updatedDoctorDocuments;
|
||||
case MasterListType.InsulationList:
|
||||
break;
|
||||
case MasterListType.OriginList:
|
||||
var originFilter = Builders<Patient>.Filter.Eq(
|
||||
"origin.name", opt.OldOption?.Name
|
||||
);
|
||||
var filterUpdateOrigin = Builders<Patient>.Filter.And(filterUnit, originFilter);
|
||||
var updateOrigin = Builders<Patient>.Update
|
||||
.Set("origin.name", opt.UpdatedOption?.Name);
|
||||
await Collection.UpdateManyAsync(filterUpdateOrigin, updateOrigin);
|
||||
|
||||
await Collection.UpdateManyAsync(Builders<Patient>.Filter.And(filterUnit,
|
||||
Builders<Patient>.Filter.Eq(
|
||||
"originAux", opt.OldOption?.Name
|
||||
)), Builders<Patient>.Update
|
||||
.Set("originAux", opt.UpdatedOption?.Name));
|
||||
|
||||
// Filtro para devolver los documentos actualizados (OR entre diagnosis.name y diagnosisAux)
|
||||
var originFilterToReturn = Builders<Patient>.Filter.Eq("origin.name", opt.UpdatedOption?.Name);
|
||||
var originAuxFilterToReturn = Builders<Patient>.Filter.Eq("originAux", opt.UpdatedOption?.Name);
|
||||
var originfilterToReturn = Builders<Patient>.Filter.And(
|
||||
filterUnit,
|
||||
Builders<Patient>.Filter.Or(originFilterToReturn, originAuxFilterToReturn)
|
||||
);
|
||||
|
||||
// Devolver los documentos actualizados
|
||||
var updatedDocumentsorigin = await Collection.Find(originfilterToReturn).ToListAsync();
|
||||
return updatedDocumentsorigin;
|
||||
|
||||
case MasterListType.DoctorTypeList:
|
||||
case MasterListType.AllergyList:
|
||||
case MasterListType.DestinationList:
|
||||
case MasterListType.ProcedureList:
|
||||
case MasterListType.ServiceList:
|
||||
case MasterListType.TreatmentList:
|
||||
case MasterListType.AltableOptionList:
|
||||
case MasterListType.DischargeStatusList:
|
||||
case MasterListType.InternalDestinationList:
|
||||
case MasterListType.LanguageBarrierList:
|
||||
case MasterListType.MobilityOptionList:
|
||||
case MasterListType.PassiveSittingList:
|
||||
case MasterListType.PatientStatusList:
|
||||
case MasterListType.TherapeuticCeilingList:
|
||||
case MasterListType.VisitOptionList:
|
||||
case MasterListType.AccessControlList:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
public async Task<List<Patient>> GetPatientsByUnitIds(List<ObjectId> unitIds, string typeName)
|
||||
{
|
||||
var isParsed = Enum.TryParse<MasterListType>(typeName, out _);
|
||||
if (!isParsed) return [];
|
||||
|
||||
var filterUnit = Builders<Patient>.Filter.In("unitId", unitIds);
|
||||
return await Collection.Find(filterUnit).ToListAsync();
|
||||
}
|
||||
|
||||
public async Task<long> CountByUnitId(ObjectId unitId)
|
||||
{
|
||||
try
|
||||
{
|
||||
var filter = Builders<Patient>.Filter.Eq(p => p.UnitId, unitId);
|
||||
return await Collection.CountDocumentsAsync(filter);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Logger.Error(e.Message);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public async Task<IEnumerable<Patient>> DeleteMasterListOption(List<ObjectId> unitIds, OptionList opt,
|
||||
string typeName)
|
||||
{
|
||||
var isParsed = Enum.TryParse<MasterListType>(typeName, out var parsedTypeName);
|
||||
if (isParsed)
|
||||
{
|
||||
// Tener en cuenta los datos auxiliares ya que pueden ser texto libre o asignarse el establecido en la lista
|
||||
// originAux / diagnosisAux modificar en caso de ser el mismo que el padre
|
||||
// Notificar a todos los fronts con el nuevo valor de cada paciente por el id de los poc's afectados(?)
|
||||
var filterUnit = Builders<Patient>.Filter.In("unitId", unitIds);
|
||||
switch (parsedTypeName)
|
||||
{
|
||||
case MasterListType.DiagnosisList:
|
||||
|
||||
// Filtro para devolver los documentos actualizados (OR entre diagnosis.name y diagnosisAux)
|
||||
var diagnosisFilterToReturn = Builders<Patient>.Filter.Eq("diagnosis.name", opt.Name);
|
||||
var diagnosisAuxFilterToReturn = Builders<Patient>.Filter.Eq("diagnosisAux", opt.Name);
|
||||
var filterToReturn = Builders<Patient>.Filter.And(
|
||||
filterUnit,
|
||||
Builders<Patient>.Filter.Or(diagnosisFilterToReturn, diagnosisAuxFilterToReturn)
|
||||
);
|
||||
|
||||
// Devolver los documentos actualizados
|
||||
var updatedDocuments = await Collection.Find(filterToReturn).ToListAsync();
|
||||
|
||||
var diagnosisFilter = Builders<Patient>.Filter.Eq(
|
||||
"diagnosis.name", opt.Name
|
||||
);
|
||||
var filterUpdateDiagnosis = Builders<Patient>.Filter.And(filterUnit, diagnosisFilter);
|
||||
var updateDiagnosis = Builders<Patient>.Update
|
||||
.Set(x => x.Diagnosis, null);
|
||||
await Collection.UpdateManyAsync(filterUpdateDiagnosis, updateDiagnosis);
|
||||
|
||||
await Collection.UpdateManyAsync(Builders<Patient>.Filter.And(filterUnit,
|
||||
Builders<Patient>.Filter.Eq(
|
||||
"diagnosisAux", opt.Name
|
||||
)), Builders<Patient>.Update
|
||||
.Set(x => x.DiagnosisAux, null));
|
||||
|
||||
|
||||
return updatedDocuments;
|
||||
case MasterListType.DoctorList:
|
||||
// Devolvemos los datos
|
||||
var doctorFilterToReturn = Builders<Patient>.Filter.ElemMatch(
|
||||
"doctors",
|
||||
Builders<Patient>.Filter.Eq("_id", opt.Id)
|
||||
);
|
||||
var filterToReturnDoctor = Builders<Patient>.Filter.And(filterUnit, doctorFilterToReturn);
|
||||
var updatedDoctorDocuments = await Collection.Find(filterToReturnDoctor).ToListAsync();
|
||||
|
||||
// Filtro para encontrar el elemento en el array `doctors` que coincida con el nombre
|
||||
var doctorFilter = Builders<Patient>.Filter.ElemMatch(
|
||||
"doctors",
|
||||
Builders<Patient>.Filter.Eq("_id", opt.Id)
|
||||
);
|
||||
var filterUpdateDoctor = Builders<Patient>.Filter.And(filterUnit, doctorFilter);
|
||||
|
||||
// Actualización del campo `name` en el array `doctors`
|
||||
var updateDoctor = Builders<Patient>.Update.PullFilter(
|
||||
"doctors", Builders<BsonDocument>.Filter.And(
|
||||
Builders<BsonDocument>.Filter.Eq("_id", opt.Id)
|
||||
));
|
||||
|
||||
// Ejecutar la actualización
|
||||
await Collection.UpdateManyAsync(filterUpdateDoctor, updateDoctor);
|
||||
|
||||
return updatedDoctorDocuments;
|
||||
case MasterListType.InsulationList:
|
||||
break;
|
||||
case MasterListType.OriginList:
|
||||
// Filtro para devolver los documentos actualizados (OR entre diagnosis.name y diagnosisAux)
|
||||
var originFilterToReturn = Builders<Patient>.Filter.Eq("origin.name", opt.Name);
|
||||
var originAuxFilterToReturn = Builders<Patient>.Filter.Eq("originAux", opt.Name);
|
||||
var filterOriginToReturn = Builders<Patient>.Filter.And(
|
||||
filterUnit,
|
||||
Builders<Patient>.Filter.Or(originFilterToReturn, originAuxFilterToReturn)
|
||||
);
|
||||
|
||||
// Devolver los documentos actualizados
|
||||
var updatedDocumentsOrigin = await Collection.Find(filterOriginToReturn).ToListAsync();
|
||||
|
||||
var originFilter = Builders<Patient>.Filter.Eq(
|
||||
"origin.name", opt.Name
|
||||
);
|
||||
var filterUpdateOrigin = Builders<Patient>.Filter.And(filterUnit, originFilter);
|
||||
var updateOrigin = Builders<Patient>.Update
|
||||
.Set(x => x.Diagnosis, null);
|
||||
await Collection.UpdateManyAsync(filterUpdateOrigin, updateOrigin);
|
||||
|
||||
await Collection.UpdateManyAsync(Builders<Patient>.Filter.And(filterUnit,
|
||||
Builders<Patient>.Filter.Eq(
|
||||
"originAux", opt.Name
|
||||
)), Builders<Patient>.Update
|
||||
.Set(x => x.OriginAux, null));
|
||||
|
||||
|
||||
return updatedDocumentsOrigin;
|
||||
|
||||
case MasterListType.DoctorTypeList:
|
||||
case MasterListType.AllergyList:
|
||||
case MasterListType.DestinationList:
|
||||
case MasterListType.ProcedureList:
|
||||
case MasterListType.ServiceList:
|
||||
case MasterListType.TreatmentList:
|
||||
case MasterListType.AltableOptionList:
|
||||
case MasterListType.DischargeStatusList:
|
||||
case MasterListType.InternalDestinationList:
|
||||
case MasterListType.LanguageBarrierList:
|
||||
case MasterListType.MobilityOptionList:
|
||||
case MasterListType.PassiveSittingList:
|
||||
case MasterListType.PatientStatusList:
|
||||
case MasterListType.TherapeuticCeilingList:
|
||||
case MasterListType.VisitOptionList:
|
||||
case MasterListType.AccessControlList:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return new List<Patient>();
|
||||
}
|
||||
|
||||
public async Task<Patient?> FindByPatientId(string patientId)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(patientId)) return null;
|
||||
|
||||
//Último paciente admitido
|
||||
var patient = await Collection.Find(p => !p.DisTime.HasValue && patientId == p.PatientId)
|
||||
.Sort(Builders<Patient>.Sort.Descending(p => p.AdmTime)).Limit(1).FirstOrDefaultAsync();
|
||||
|
||||
//Último con fecha de alta más reciente
|
||||
patient ??= await Collection.Find(p => p.DisTime.HasValue && patientId == p.PatientId)
|
||||
.Sort(Builders<Patient>.Sort.Descending(p => p.DisTime)).Limit(1).FirstOrDefaultAsync();
|
||||
|
||||
return patient;
|
||||
}
|
||||
|
||||
public async Task<Patient?> FindByPatientId(ObjectId patientId)
|
||||
{
|
||||
//Último paciente admitido
|
||||
var patient = await Collection.Find(p => !p.DisTime.HasValue && patientId == p.Id)
|
||||
.Sort(Builders<Patient>.Sort.Descending(p => p.AdmTime)).Limit(1).FirstOrDefaultAsync();
|
||||
|
||||
//Último con fecha de alta más reciente
|
||||
patient ??= await Collection.Find(p => p.DisTime.HasValue && patientId == p.Id)
|
||||
.Sort(Builders<Patient>.Sort.Descending(p => p.DisTime)).Limit(1).FirstOrDefaultAsync();
|
||||
|
||||
return patient;
|
||||
}
|
||||
|
||||
public async Task<List<Patient>> FindAll()
|
||||
{
|
||||
return (await Collection.FindAsync(Builders<Patient>.Filter.Empty)).ToList();
|
||||
//return (await Collection.FindAsync(_ => true)).ToList();
|
||||
}
|
||||
|
||||
public async Task<List<Patient>> FindByPointOfCare(string pointOfCare)
|
||||
{
|
||||
var filterBuilder = Builders<Patient>.Filter;
|
||||
var filter = filterBuilder.Eq(pa => pa.UnitString, pointOfCare);
|
||||
|
||||
var result = await Collection.FindAsync(filter);
|
||||
|
||||
return await result.ToListAsync();
|
||||
}
|
||||
|
||||
public async Task<List<Patient>> FindByPointOfCare(ObjectId pointOfCare)
|
||||
{
|
||||
var filterBuilder = Builders<Patient>.Filter;
|
||||
var filter = filterBuilder.Eq(pa => pa.PointOfCareId, pointOfCare);
|
||||
|
||||
var result = await Collection.FindAsync(filter);
|
||||
|
||||
return await result.ToListAsync();
|
||||
}
|
||||
|
||||
public async Task<List<Patient>> FindInActivePoC()
|
||||
{
|
||||
var virtualPointOfCareValues = Enum.GetValues(typeof(VirtualPointOfCare)).Cast<VirtualPointOfCare>()
|
||||
.Select(p => p.ToString())
|
||||
.ToList();
|
||||
|
||||
//var filterBuilder = Builders<Patient>.Filter;
|
||||
|
||||
// Define el pipeline de agregación
|
||||
var pipeline = new[]
|
||||
{
|
||||
new BsonDocument("$lookup", new BsonDocument
|
||||
{
|
||||
{ "from", "pointOfCares" }, // Colección de PointOfCare
|
||||
{ "localField", "pointOfCareId" },
|
||||
{ "foreignField", "_id" },
|
||||
{ "as", "pointOfCareInfo" }
|
||||
}),
|
||||
new BsonDocument("$unwind", "$pointOfCareInfo"),
|
||||
new BsonDocument("$match", new BsonDocument
|
||||
{
|
||||
{ "pointOfCareInfo.bed", new BsonDocument("$nin", new BsonArray(virtualPointOfCareValues)) }
|
||||
})
|
||||
};
|
||||
|
||||
var result = await Collection.Aggregate<Patient>(pipeline).ToListAsync();
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
public async Task<List<Patient>> FindInInactivePoC()
|
||||
{
|
||||
var virtualPointOfCareValues = Enum.GetValues(typeof(VirtualPointOfCare)).Cast<VirtualPointOfCare>()
|
||||
.Select(p => p.ToString())
|
||||
.ToList();
|
||||
|
||||
//var filterBuilder = Builders<Patient>.Filter;
|
||||
|
||||
// Define el pipeline de agregación
|
||||
var pipeline = new[]
|
||||
{
|
||||
new BsonDocument("$lookup", new BsonDocument
|
||||
{
|
||||
{ "from", "pointOfCares" }, // Colección de PointOfCare
|
||||
{ "localField", "pointOfCareId" },
|
||||
{ "foreignField", "_id" },
|
||||
{ "as", "pointOfCareInfo" }
|
||||
}),
|
||||
new BsonDocument("$unwind", "$pointOfCareInfo"),
|
||||
new BsonDocument("$match", new BsonDocument
|
||||
{
|
||||
{ "pointOfCareInfo.bed", new BsonDocument("$in", new BsonArray(virtualPointOfCareValues)) }
|
||||
})
|
||||
};
|
||||
|
||||
var result = await Collection.Aggregate<Patient>(pipeline).ToListAsync();
|
||||
return result;
|
||||
}
|
||||
|
||||
public IFindFluent<Patient, Patient> GetPaginatedPatients(PaginationFilter filter)
|
||||
{
|
||||
var filterBuilder = Builders<Patient>.Filter;
|
||||
var sort = Builders<Patient>.Sort.Descending("admTime");
|
||||
var filters = new List<FilterDefinition<Patient>>();
|
||||
|
||||
if (filter.FilteredRequest != null)
|
||||
{
|
||||
AddDefaultFilters(filters, filter, filterBuilder);
|
||||
// return CreateFindFluent(filters, sort);
|
||||
}
|
||||
|
||||
var requestFilter = filter.FilteredRequest;
|
||||
|
||||
if(requestFilter == null) return CreateFindFluent(filters, sort);
|
||||
|
||||
AddTimeFilters(requestFilter, filters, filterBuilder);
|
||||
|
||||
if (!string.IsNullOrEmpty(filter.FilteredRequest?.Text))
|
||||
{
|
||||
var textFilter = filter.FilteredRequest.Text;
|
||||
var textFilterEscaped = Regex.Escape(textFilter);
|
||||
|
||||
var orFilters = new List<FilterDefinition<Patient>>
|
||||
{
|
||||
filterBuilder.Regex(p => p.Person!.FirstName, new BsonRegularExpression(textFilterEscaped, "i")),
|
||||
filterBuilder.Regex(p => p.Person!.SecondName, new BsonRegularExpression(textFilterEscaped, "i")),
|
||||
filterBuilder.Regex(p => p.Person!.LastName, new BsonRegularExpression(textFilterEscaped, "i")),
|
||||
filterBuilder.Regex(p => p.PatientNumber, new BsonRegularExpression(textFilterEscaped, "i"))
|
||||
};
|
||||
|
||||
if (ObjectId.TryParse(textFilter, out var id)) orFilters.Add(filterBuilder.Eq("_id", id));
|
||||
|
||||
filters.Add(filterBuilder.Or(orFilters));
|
||||
}
|
||||
|
||||
if (filter.FilteredRequest?.UnitId != null && ObjectId.TryParse(filter.FilteredRequest.UnitId, out var unitId))
|
||||
filters.Add(filterBuilder.Eq("unitId", unitId));
|
||||
if (filter.FilteredRequest?.PocId != null && ObjectId.TryParse(filter.FilteredRequest.PocId, out var pocId))
|
||||
filters.Add(filterBuilder.Eq("pointOfCareId", pocId));
|
||||
return CreateFindFluent(filters, sort);
|
||||
}
|
||||
|
||||
|
||||
public async Task<List<Patient>> FindPatientsNotUpdatedSince(DateTime date)
|
||||
{
|
||||
var filter = Builders<Patient>.Filter.Or(
|
||||
Builders<Patient>.Filter.Lt(p => p.UpdateDate, date),
|
||||
Builders<Patient>.Filter.Eq(p => p.UpdateDate, null)
|
||||
);
|
||||
return await Collection.Find(filter).ToListAsync();
|
||||
|
||||
//return await Collection.Find(p => p.UpdateDate < date).ToListAsync();
|
||||
}
|
||||
|
||||
public async Task<List<Patient>> FindDischargedPatients()
|
||||
{
|
||||
try
|
||||
{
|
||||
var filter = Builders<Patient>.Filter.Ne(p => p.DisTime, null);
|
||||
var cursor = await Collection.FindAsync(filter);
|
||||
var patients = await cursor.ToListAsync();
|
||||
|
||||
return patients;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error("Error finding discharged patients {exMessage}", ex.Message);
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<Patient?> UpdateOne(Patient updatedPatient)
|
||||
{
|
||||
var filter = Builders<Patient>.Filter.Eq("_id", updatedPatient.Id);
|
||||
|
||||
var update = Builders<Patient>.Update
|
||||
.Set(p => p.PatientNumber, updatedPatient.PatientNumber)
|
||||
.Set(p => p.Person, updatedPatient.Person)
|
||||
.Set(p => p.UpdateDate, DateTime.UtcNow);
|
||||
|
||||
return await Collection.FindOneAndUpdateAsync(filter, update,
|
||||
new FindOneAndUpdateOptions<Patient, Patient> { ReturnDocument = ReturnDocument.After });
|
||||
}
|
||||
|
||||
public async Task<Patient?> UpdatePatientIncomingData(ObjectId patientId, Patient person)
|
||||
{
|
||||
var filter = Builders<Patient>.Filter.Eq("_id", patientId);
|
||||
var update = Builders<Patient>.Update
|
||||
.Set(p => p.OriginAux, person.OriginAux)
|
||||
.Set(p => p.DiagnosisAux, person.DiagnosisAux)
|
||||
.Set(p => p.Diagnosis, person.Diagnosis)
|
||||
.Set(p => p.UpdateDate, DateTime.UtcNow)
|
||||
.Set(p => p.AdmTime, person.AdmTime)
|
||||
.Set(p => p.Origin, person.Origin);
|
||||
|
||||
return await Collection.FindOneAndUpdateAsync(filter, update,
|
||||
new FindOneAndUpdateOptions<Patient, Patient> { ReturnDocument = ReturnDocument.After });
|
||||
}
|
||||
|
||||
public async Task<Patient?> UpdatePatientDemographicData(ObjectId patientId, Patient person)
|
||||
{
|
||||
var filter = Builders<Patient>.Filter.Eq("_id", patientId);
|
||||
var update = Builders<Patient>.Update
|
||||
.Set(p => p.UpdateDate, DateTime.UtcNow)
|
||||
.Set(p => p.Allergies, person.Allergies)
|
||||
.Set(p => p.LanguageBarrier, person.LanguageBarrier)
|
||||
.Set(p => p.DiagnosisAux, person.DiagnosisAux)
|
||||
.Set(p => p.Diagnosis, person.Diagnosis)
|
||||
.Set(p => p.Person, person.Person);
|
||||
|
||||
|
||||
return await Collection.FindOneAndUpdateAsync(filter, update,
|
||||
new FindOneAndUpdateOptions<Patient, Patient> { ReturnDocument = ReturnDocument.After });
|
||||
}
|
||||
|
||||
|
||||
public override async Task CreateIndexes()
|
||||
{
|
||||
var options = new CreateIndexOptions<Patient> { Background = true, Unique = false };
|
||||
var optionsUq = new CreateIndexOptions<Patient>
|
||||
{
|
||||
Background = true,
|
||||
Unique = true
|
||||
//PartialFilterExpression = Builders<Patient>.Filter.Exists(p => p.PointOfCareId) &
|
||||
// Builders<Patient>.Filter.Exists(p => p.UnitId)
|
||||
};
|
||||
var indexes = new List<CreateIndexModel<Patient>>
|
||||
{
|
||||
new("{ patientNumber: 1 }", optionsUq),
|
||||
new("{ admTime: 1 }", options)
|
||||
//new("{ pointOfCareId: 1, unitId: 1 }", optionsUq),
|
||||
//new("{ pointOfCareId: 1 }", optionsUq)
|
||||
};
|
||||
|
||||
await MongoUtils.EnsureIndexes(Collection, indexes);
|
||||
}
|
||||
|
||||
private static void AddTimeFilters(FilteredRequest requestFilter, List<FilterDefinition<Patient>> filters,
|
||||
FilterDefinitionBuilder<Patient> filterBuilder)
|
||||
{
|
||||
// Filter by admission time
|
||||
if (requestFilter.StartAdmTime.HasValue)
|
||||
filters.Add(filterBuilder.Gte(p => p.AdmTime, requestFilter.StartAdmTime.Value));
|
||||
if (requestFilter.EndAdmTime.HasValue)
|
||||
filters.Add(filterBuilder.Lte(p => p.AdmTime, requestFilter.EndAdmTime.Value));
|
||||
|
||||
// Filter by discharge time
|
||||
if (requestFilter.StartDischargeTime.HasValue)
|
||||
filters.Add(filterBuilder.Gte(p => p.DisTime, requestFilter.StartDischargeTime.Value));
|
||||
if (requestFilter.EndDischargeTime.HasValue)
|
||||
filters.Add(filterBuilder.Lte(p => p.DisTime, requestFilter.EndDischargeTime.Value));
|
||||
|
||||
// Filter by last observation time
|
||||
if (requestFilter.StartLastObsTime.HasValue)
|
||||
filters.Add(filterBuilder.Gte(p => p.LastObservationDate, requestFilter.StartLastObsTime.Value));
|
||||
if (requestFilter.EndLastObsTime.HasValue)
|
||||
filters.Add(filterBuilder.Lte(p => p.LastObservationDate, requestFilter.EndLastObsTime.Value));
|
||||
|
||||
// Filter by creation date
|
||||
if (requestFilter.StartCreationDateTime.HasValue)
|
||||
filters.Add(filterBuilder.Gte(p => p.CreationDate, requestFilter.StartCreationDateTime.Value));
|
||||
if (requestFilter.EndCreationDateTime.HasValue)
|
||||
filters.Add(filterBuilder.Lte(p => p.CreationDate, requestFilter.EndCreationDateTime.Value));
|
||||
|
||||
// Filter by update date
|
||||
if (requestFilter.StartUpDateTime.HasValue)
|
||||
filters.Add(filterBuilder.Gte(p => p.UpdateDate, requestFilter.StartUpDateTime.Value));
|
||||
if (requestFilter.EndUpDateTime.HasValue)
|
||||
filters.Add(filterBuilder.Lte(p => p.UpdateDate, requestFilter.EndUpDateTime.Value));
|
||||
|
||||
// Filter by birth date (with Person null check)
|
||||
if (requestFilter.StartBirthDate.HasValue || requestFilter.EndBirthDate.HasValue)
|
||||
{
|
||||
// Check if Person is not null
|
||||
filters.Add(filterBuilder.Exists(p => p.Person));
|
||||
|
||||
// Apply birth date filters only if Person is not null
|
||||
if (requestFilter.StartBirthDate.HasValue)
|
||||
filters.Add(filterBuilder.Gte(p => p.Person!.BirthDate, requestFilter.StartBirthDate.Value));
|
||||
if (requestFilter.EndBirthDate.HasValue)
|
||||
filters.Add(filterBuilder.Lte(p => p.Person!.BirthDate, requestFilter.EndBirthDate.Value));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public async Task<List<Patient>> FindAllByPointOfCareId(ObjectId pointOfCare)
|
||||
{
|
||||
var filterBuilder = Builders<Patient>.Filter;
|
||||
var filter = filterBuilder.Eq(pa => pa.PointOfCareId, pointOfCare);
|
||||
|
||||
var result = await Collection.FindAsync(filter);
|
||||
|
||||
return await result.ToListAsync();
|
||||
}
|
||||
|
||||
private void AddDefaultFilters(List<FilterDefinition<Patient>> filters, PaginationFilter filter,
|
||||
FilterDefinitionBuilder<Patient> filterBuilder)
|
||||
{
|
||||
// Verifica si PatientId tiene valor
|
||||
if (filter.FilteredRequest?.PatientId != null)
|
||||
{
|
||||
if(ObjectId.TryParse(filter.FilteredRequest.PatientId, out var patientId))
|
||||
filters.Add(
|
||||
filterBuilder.Eq(p => p.Id, patientId)
|
||||
);
|
||||
}
|
||||
|
||||
// Verifica si PatientNumber tiene valor
|
||||
else if (filter.FilteredRequest?.PatientNumber != null)
|
||||
filters.Add(
|
||||
filterBuilder.Eq(p => p.PatientNumber, filter.FilteredRequest.PatientNumber)
|
||||
);
|
||||
}
|
||||
|
||||
private IFindFluent<Patient, Patient> CreateFindFluent(List<FilterDefinition<Patient>> filters,
|
||||
SortDefinition<Patient> sort)
|
||||
{
|
||||
var combinedFilter = filters.Any()
|
||||
? Builders<Patient>.Filter.And(filters)
|
||||
: Builders<Patient>.Filter.Empty;
|
||||
|
||||
return Collection.Find(combinedFilter).Sort(sort);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
using adas_core.Application.Repositories.Interfaces;
|
||||
using adas_core.Domain.Models;
|
||||
using adas_core.Domain.Models.AppSettings;
|
||||
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 PoCSettingsRepository : MongoRepository<PoCSettings>, IPoCSettingsRepository
|
||||
{
|
||||
private readonly ApiSettings _apiSettings;
|
||||
|
||||
public PoCSettingsRepository(IOptions<ApiSettings> apiSettings, IMongoDatabase database) : base(database)
|
||||
{
|
||||
if (apiSettings == null) throw new ArgumentNullException(nameof(apiSettings));
|
||||
_apiSettings = apiSettings.Value;
|
||||
}
|
||||
|
||||
|
||||
public override string GetCollectionName()
|
||||
{
|
||||
return _apiSettings.PoCSettings ?? "poc_settings";
|
||||
}
|
||||
|
||||
public async Task Delete(ObjectId id)
|
||||
{
|
||||
try
|
||||
{
|
||||
var filter = Builders<PoCSettings>.Filter.Eq(x => x.Id, id);
|
||||
await Collection.DeleteOneAsync(filter, null);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error("Error deleting PoCSettings by id: {id}. Exception: {ex}", id, ex);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<List<PoCSettings>> FindAll()
|
||||
{
|
||||
try
|
||||
{
|
||||
return (await Collection.FindAsync(Builders<PoCSettings>.Filter.Empty)).ToList();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error("Error searching PoCSettings. Exception: {ex}", ex);
|
||||
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<PoCSettings?> FindById(ObjectId id)
|
||||
{
|
||||
try
|
||||
{
|
||||
var filter = Builders<PoCSettings>.Filter.Eq(p => p.Id, id);
|
||||
var result = await Collection.FindAsync(filter);
|
||||
|
||||
return await result.FirstOrDefaultAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error("Error searching PoCSettings by id: {id}. Exception: {ex}", id, ex);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<PoCSettings?> FindByLocation(PatientLocation location)
|
||||
{
|
||||
try
|
||||
{
|
||||
var filterBuilder = Builders<PoCSettings>.Filter;
|
||||
var filter = filterBuilder.Ne(p => p.PatientLocation, null);
|
||||
// TODO
|
||||
// if (!string.IsNullOrEmpty(location.PointOfCare) && !string.IsNullOrEmpty(location.Bed))
|
||||
// {
|
||||
// filter = filterBuilder.And(
|
||||
// filter,
|
||||
// filterBuilder.Eq(p => p.PatientLocation!.PointOfCare, location.PointOfCare),
|
||||
// filterBuilder.Eq(p => p.PatientLocation!.Bed, location.Bed)
|
||||
// );
|
||||
// }
|
||||
|
||||
var result = await Collection.Find(filter).Limit(1).FirstOrDefaultAsync();
|
||||
|
||||
return result;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Debug("Error searching by location. Exception: {ex}", ex);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public async Task Update(PoCSettings pocSettings)
|
||||
{
|
||||
try
|
||||
{
|
||||
await UpdateOneAsync(pocSettings.Id, pocSettings);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Debug("Error updating PoC Settings: {pocS}. Exception: {ex}", pocSettings.ToString(), ex);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public override async Task CreateIndexes()
|
||||
{
|
||||
var options = new CreateIndexOptions { Background = true, Unique = false };
|
||||
//var optionsUq = new CreateIndexOptions<PoCSettings>()
|
||||
//{
|
||||
// Background = true,
|
||||
// Unique = true,
|
||||
// PartialFilterExpression = Builders<PoCSettings>.Filter.Exists(p => p.PatientLocation) &
|
||||
// Builders<PoCSettings>.Filter.Exists(p => p.ManualRelayStatus)
|
||||
//};
|
||||
var indexes = new List<CreateIndexModel<PoCSettings>>
|
||||
{
|
||||
new("{ patientLocation: 1 }", options)
|
||||
//new("{ relayStatus: 1, bed: 1 }", optionsUq)
|
||||
};
|
||||
|
||||
await MongoUtils.EnsureIndexes(Collection, indexes);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,614 @@
|
||||
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.Filter;
|
||||
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 PointOfCareRepository : MongoRepository<PointOfCare>, IPointOfCareRepository
|
||||
{
|
||||
private readonly ApiSettings _apiSettings;
|
||||
|
||||
public PointOfCareRepository(IOptions<ApiSettings>? apiSettings, IMongoDatabase database) : base(database)
|
||||
{
|
||||
if (apiSettings != null)
|
||||
_apiSettings = apiSettings.Value;
|
||||
else
|
||||
throw new ArgumentNullException(nameof(apiSettings));
|
||||
}
|
||||
|
||||
|
||||
|
||||
public override string GetCollectionName()
|
||||
{
|
||||
return _apiSettings.Locations;
|
||||
}
|
||||
|
||||
public override async Task InsertOneAsync(PointOfCare pointOfCare)
|
||||
{
|
||||
try
|
||||
{
|
||||
await base.InsertOneAsync(pointOfCare);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine(e);
|
||||
Log.Error("Exception trying to insert pointOfCare: {pointOfCare}. Exception {e}", pointOfCare, e);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task Delete(ObjectId id)
|
||||
{
|
||||
try
|
||||
{
|
||||
var filter = Builders<PointOfCare>.Filter.Eq(x => x.Id, id);
|
||||
await Collection.DeleteOneAsync(filter, null);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error("Exception trying to delete pointOfCare: {id}. Exception {e}", id, e);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<bool> DeleteManyByUnitId(ObjectId unitId)
|
||||
{
|
||||
try
|
||||
{
|
||||
var filter = Builders<PointOfCare>.Filter.Where(p => p.UnitId == unitId);
|
||||
await Collection.DeleteManyAsync(filter);
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error(e.Message);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task Update(PointOfCare pointOfCare)
|
||||
{
|
||||
try
|
||||
{
|
||||
await UpdateOneAsync(pointOfCare.Id, pointOfCare);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error("Exception trying to update pointOfCare: {pointOfCare}. Exception {e}", pointOfCare, e);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task UpdateUnitId(ObjectId id, Unit unit)
|
||||
{
|
||||
var filterBuilder = Builders<PointOfCare>.Filter;
|
||||
var filter = filterBuilder.Eq(p => p.Id, id);
|
||||
|
||||
var update = Builders<PointOfCare>.Update
|
||||
.Set(p => p.UnitName, unit.Name)
|
||||
.Set(p => p.UnitId, unit.Id);
|
||||
|
||||
await Collection.UpdateOneAsync(filter, update);
|
||||
}
|
||||
|
||||
public async Task UpdateRelayConfig(ObjectId pocId, List<Relay> relayConfig)
|
||||
{
|
||||
var filterBuilder = Builders<PointOfCare>.Filter;
|
||||
var filter = filterBuilder.Eq(p => p.Id, pocId);
|
||||
var relayIds = relayConfig.Select(r => r.Id).ToList();
|
||||
var update = Builders<PointOfCare>.Update
|
||||
.Set(p => p.Configuration!.RelayIdList, relayIds);
|
||||
|
||||
await Collection.UpdateOneAsync(filter, update);
|
||||
}
|
||||
public async Task UpdateRelayConfig(ObjectId pocId, List<ObjectId> relayConfig)
|
||||
{
|
||||
var filterBuilder = Builders<PointOfCare>.Filter;
|
||||
var filter = filterBuilder.Eq(p => p.Id, pocId);
|
||||
var update = Builders<PointOfCare>.Update
|
||||
.Set(p => p.Configuration!.RelayIdList, relayConfig);
|
||||
|
||||
await Collection.UpdateOneAsync(filter, update);
|
||||
}
|
||||
|
||||
public async Task UpdateConfiguration(ObjectId id, PointOfCareConfiguration configuration)
|
||||
{
|
||||
var filterBuilder = Builders<PointOfCare>.Filter;
|
||||
var filter = filterBuilder.Eq(p => p.Id, id);
|
||||
|
||||
var update = Builders<PointOfCare>.Update
|
||||
.Set(p => p.Configuration, configuration);
|
||||
|
||||
await Collection.UpdateOneAsync(filter, update);
|
||||
}
|
||||
|
||||
public async Task<PointOfCare?> FindById(ObjectId id)
|
||||
{
|
||||
try
|
||||
{
|
||||
var filter = Builders<PointOfCare>.Filter.Eq(p => p.Id, id);
|
||||
return await Collection.Find(filter).FirstOrDefaultAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error("Error searching pointOfCare by id: {id}. Exception: {ex}", id, ex);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public async Task<IEnumerable<PointOfCare>> FindByUnitAndStatus(ObjectId unitId, StatusEnum.PointOfCare status,
|
||||
bool excludeVirtual = false)
|
||||
{
|
||||
try
|
||||
{
|
||||
var filterBuilder = Builders<PointOfCare>.Filter;
|
||||
|
||||
var filter = filterBuilder.And(
|
||||
filterBuilder.Eq(p => p.UnitId, unitId),
|
||||
filterBuilder.Eq(p => p.Status, status)
|
||||
);
|
||||
if (excludeVirtual)
|
||||
filter = filterBuilder.And(
|
||||
filter,
|
||||
filterBuilder.Ne(p => p.Bed, VirtualPointOfCare.Pushed.ToString()),
|
||||
filterBuilder.Ne(p => p.Bed, VirtualPointOfCare.Unknown.ToString()),
|
||||
filterBuilder.Ne(p => p.Bed, VirtualPointOfCare.Deleted.ToString()),
|
||||
filterBuilder.Ne(p => p.Bed, VirtualPointOfCare.NoBed.ToString()),
|
||||
filterBuilder.Ne(p => p.Bed, VirtualPointOfCare.Cancelled.ToString()),
|
||||
filterBuilder.Ne(p => p.Bed, VirtualPointOfCare.Recovered.ToString()),
|
||||
filterBuilder.Ne(p => p.Bed, VirtualPointOfCare.Moved.ToString())
|
||||
);
|
||||
var result = await Collection.FindAsync(filter);
|
||||
|
||||
return result.ToEnumerable();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error("Error searching pointOfCares by Unit: {unit} and status: {}. Exception: {ex}", unitId.ToString(),
|
||||
status.ToString(), ex);
|
||||
return new List<PointOfCare>();
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<PointOfCare?> FindByBedAndUnitId(string? bed, ObjectId unitId)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (string.IsNullOrEmpty(bed)) return null;
|
||||
var filterBuilder = Builders<PointOfCare>.Filter;
|
||||
List<FilterDefinition<PointOfCare>> filters =
|
||||
[
|
||||
filterBuilder.Eq(p => p.Bed, bed),
|
||||
filterBuilder.Eq(p => p.UnitId, unitId)
|
||||
// Combina todos los filtros en uno solo usando el operador & si hay más de un filtro, de lo contrario, usa un filtro vacío.
|
||||
];
|
||||
|
||||
// Combina todos los filtros en uno solo usando el operador & si hay más de un filtro, de lo contrario, usa un filtro vacío.
|
||||
var combinedFilter = filters.Count > 0
|
||||
? filters.Aggregate((current, next) => current & next)
|
||||
: filterBuilder.Empty;
|
||||
|
||||
var result = await Collection.Find(combinedFilter).Limit(1).FirstOrDefaultAsync();
|
||||
|
||||
return result;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error("Error searching pointOfCares by patient location unitId: {unitId}, bed: {bed}. Exception: {ex}",
|
||||
unitId, bed, ex);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<PointOfCare>?> FindAllByUnitId(ObjectId unit)
|
||||
{
|
||||
try
|
||||
{
|
||||
var filter = Builders<PointOfCare>.Filter.Eq(p => p.UnitId, unit);
|
||||
var result = await Collection.FindAsync(filter);
|
||||
|
||||
return result.ToEnumerable();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error("Error searching pointOfCares by Unit: {unit}. Exception: {ex}", unit, ex);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<PointOfCare>?> FindByRoom(string room)
|
||||
{
|
||||
try
|
||||
{
|
||||
var filter = Builders<PointOfCare>.Filter.Eq(p => p.Room, room);
|
||||
var result = await Collection.FindAsync(filter);
|
||||
|
||||
return result.ToEnumerable();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error("Error searching pointOfCares by room: {room}. Exception: {ex}", room, ex);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<PointOfCare>?> FindByBed(string bed)
|
||||
{
|
||||
try
|
||||
{
|
||||
var filter = Builders<PointOfCare>.Filter.Eq(p => p.Bed, bed);
|
||||
var result = await Collection.FindAsync(filter);
|
||||
|
||||
return result.ToEnumerable();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error("Error searching pointOfCares by bed: {bed}. Exception: {ex}", bed, ex);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<List<PointOfCare>> FindByFilter(FilterDefinition<PointOfCare> filter,
|
||||
ProjectionDefinition<PointOfCare>? projection = null)
|
||||
{
|
||||
if (projection != null)
|
||||
return await Collection.Find(filter).Project<PointOfCare>(projection).ToListAsync();
|
||||
return await Collection.Find(filter).ToListAsync();
|
||||
}
|
||||
|
||||
public async Task<long> CountByUnitId(ObjectId unitId)
|
||||
{
|
||||
try
|
||||
{
|
||||
var filterBuilder = Builders<PointOfCare>.Filter;
|
||||
var excludedBeds = new[]
|
||||
{
|
||||
VirtualPointOfCare.Pushed.ToString(),
|
||||
VirtualPointOfCare.Unknown.ToString(),
|
||||
VirtualPointOfCare.Deleted.ToString(),
|
||||
VirtualPointOfCare.NoBed.ToString(),
|
||||
VirtualPointOfCare.Cancelled.ToString(),
|
||||
VirtualPointOfCare.UnitData.ToString(),
|
||||
VirtualPointOfCare.Recovered.ToString(),
|
||||
VirtualPointOfCare.Moved.ToString()
|
||||
};
|
||||
var filter = filterBuilder.And(
|
||||
filterBuilder.Eq(p => p.UnitId, unitId),
|
||||
filterBuilder.Nin(p => p.Bed, excludedBeds)
|
||||
);
|
||||
|
||||
return await Collection.CountDocumentsAsync(filter);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Logger.Error(e.Message);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
public async Task<long> CountVirtualsByUnitId(ObjectId unitId)
|
||||
{
|
||||
try
|
||||
{
|
||||
var filterBuilder = Builders<PointOfCare>.Filter;
|
||||
|
||||
// Lista de estados que NO quieres contar
|
||||
var excludedBeds = new[]
|
||||
{
|
||||
VirtualPointOfCare.Pushed.ToString(),
|
||||
VirtualPointOfCare.Unknown.ToString(),
|
||||
VirtualPointOfCare.Deleted.ToString(),
|
||||
VirtualPointOfCare.NoBed.ToString(),
|
||||
VirtualPointOfCare.Cancelled.ToString(),
|
||||
VirtualPointOfCare.Recovered.ToString(),
|
||||
VirtualPointOfCare.UnitData.ToString(),
|
||||
VirtualPointOfCare.Moved.ToString()
|
||||
};
|
||||
|
||||
// Filtramos por UnitId Y que el Bed NO esté en la lista de excluidos
|
||||
var filter = filterBuilder.And(
|
||||
filterBuilder.Eq(p => p.UnitId, unitId),
|
||||
filterBuilder.In(p => p.Bed, excludedBeds)
|
||||
);
|
||||
|
||||
return await Collection.CountDocumentsAsync(filter);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Logger.Error(e.Message);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
public async Task<PointOfCare?> GetPoCConfiguration(ObjectId pocId)
|
||||
{
|
||||
var filter = Builders<PointOfCare>.Filter.Eq(p => p.Id, pocId);
|
||||
|
||||
var projection = Builders<PointOfCare>.Projection
|
||||
.Include(p => p.Id)
|
||||
.Include(p => p.Configuration);
|
||||
|
||||
return await Collection.Find(filter).Project<PointOfCare>(projection).FirstOrDefaultAsync();
|
||||
}
|
||||
|
||||
public async Task<List<PointOfCare>?> GetAll()
|
||||
{
|
||||
var filter = Builders<PointOfCare>.Filter.Empty;
|
||||
return await Collection.Find(filter).ToListAsync();
|
||||
}
|
||||
public async Task<PointOfCare?> FindByIdAllConfig(ObjectId id)
|
||||
{
|
||||
return await Collection.Aggregate()
|
||||
.Match(c=>c.Id == id)
|
||||
.Lookup(_apiSettings.LightBeacons, "configuration.beaconIdList", "_id", "beacons")
|
||||
.Lookup(_apiSettings.Cameras, "configuration.cameraIdList", "_id", "cameras")
|
||||
.Lookup(_apiSettings.Relays, "configuration.relayIdList", "_id", "relays")
|
||||
.Project<PointOfCare>(new BsonDocument
|
||||
{
|
||||
{ "_id", 1 },
|
||||
{ "room", 1 },
|
||||
{ "bed", 1 },
|
||||
{ "hall", 1 },
|
||||
{ "unitId", 1 },
|
||||
{ "status", 1 },
|
||||
{ "admissionId", 1 },
|
||||
{ "configuration", new BsonDocument
|
||||
{
|
||||
{ "beaconList", "$beacons" },
|
||||
{ "cameraList", "$cameras" },
|
||||
{ "relayList", "$relays" },
|
||||
{ "beaconIdList", "$configuration.beaconIdList" },
|
||||
{ "cameraIdList", "$configuration.cameraIdList" },
|
||||
{ "relayIdList", "$configuration.relayIdList" },
|
||||
{ "type", "$configuration.type" },
|
||||
{ "id", "$configuration.id" }
|
||||
}
|
||||
}
|
||||
}).FirstOrDefaultAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Obtiene de forma asíncrona todos los identificadores únicos de cámaras que están
|
||||
/// vinculados a algún PointOfCare.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Se retorna un <see cref="HashSet{ObjectId}"/> para optimizar la búsqueda de pertenencia (Contains) en el servicio.
|
||||
/// Mientras que una <see cref="List{T}"/> requiere un tiempo de búsqueda lineal $O(n)$, el HashSet utiliza
|
||||
/// una tabla hash que permite verificar si una cámara está en uso en tiempo constante $O(1)$.
|
||||
/// Esto es crítico para mantener el rendimiento al comparar los IDs de la página actual
|
||||
/// contra el total de cámaras en uso, independientemente del volumen de datos.
|
||||
/// </remarks>
|
||||
/// <returns>Un conjunto hash con los <see cref="ObjectId"/> de las cámaras en uso.</returns>
|
||||
public async Task<HashSet<ObjectId>> FindAllIdCamerasInUse()
|
||||
{
|
||||
var distinctIds = await Collection
|
||||
.DistinctAsync<ObjectId>("configuration.cameraIdList", Builders<PointOfCare>.Filter.Empty);
|
||||
|
||||
var list = await distinctIds.ToListAsync();
|
||||
return new HashSet<ObjectId>(list);
|
||||
}
|
||||
public async Task<HashSet<ObjectId>> FindAllIdBeaconsInUse()
|
||||
{
|
||||
var distinctIds = await Collection
|
||||
.DistinctAsync<ObjectId>("configuration.beaconIdList", Builders<PointOfCare>.Filter.Empty);
|
||||
|
||||
var list = await distinctIds.ToListAsync();
|
||||
return new HashSet<ObjectId>(list);
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<PointOfCare>?> FindAllByUnitIdWithDevices(ObjectId unitId)
|
||||
{
|
||||
try
|
||||
{
|
||||
var pipeline = Collection.Aggregate()
|
||||
// 1. Filtramos primero por UnitId (muy importante para rendimiento)
|
||||
.Match(p => p.UnitId == unitId)
|
||||
|
||||
// 2. Realizamos los Lookups usando las colecciones desde settings
|
||||
.Lookup(_apiSettings.LightBeacons, "configuration.beaconIdList", "_id", "beacons")
|
||||
.Lookup(_apiSettings.Cameras, "configuration.cameraIdList", "_id", "cameras")
|
||||
.Lookup(_apiSettings.Relays, "configuration.relayIdList", "_id", "relays")
|
||||
|
||||
// 3. Proyectamos para que coincida exactamente con tu modelo C#
|
||||
.Project<PointOfCare>(new BsonDocument
|
||||
{
|
||||
{ "_id", 1 },
|
||||
{ "room", 1 },
|
||||
{ "bed", 1 },
|
||||
{ "hall", 1 },
|
||||
{ "unitId", 1 },
|
||||
{ "status", 1 },
|
||||
{ "admissionId", 1 },
|
||||
{ "configuration", new BsonDocument
|
||||
{
|
||||
// Mapeamos los arrays temporales a las propiedades de la clase
|
||||
{ "beaconList", "$beacons" },
|
||||
{ "cameraList", "$cameras" },
|
||||
{ "relayList", "$relays" },
|
||||
{ "beaconIdList", "$configuration.beaconIdList" },
|
||||
{ "cameraIdList", "$configuration.cameraIdList" },
|
||||
{ "relayIdList", "$configuration.relayIdList" },
|
||||
{ "type", "$configuration.type" },
|
||||
{ "id", "$configuration.id" }
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return await pipeline.ToListAsync();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error("Error searching pointOfCares by Unit: {unit}. Exception: {ex}", unitId, ex);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<HashSet<ObjectId>> FindAllIdRelaysInUse()
|
||||
{
|
||||
var distinctIds = await Collection
|
||||
.DistinctAsync<ObjectId>("configuration.relayIdList", Builders<PointOfCare>.Filter.Empty);
|
||||
|
||||
var list = await distinctIds.ToListAsync();
|
||||
return new HashSet<ObjectId>(list);
|
||||
}
|
||||
|
||||
public async Task<List<PointOfCare>?> GetAllConfigs()
|
||||
{
|
||||
var pipeline = Collection.Aggregate()
|
||||
.Lookup(
|
||||
_apiSettings.LightBeacons,
|
||||
"configuration.beaconIdList",
|
||||
"_id",
|
||||
"beacons"
|
||||
)
|
||||
.Lookup(
|
||||
_apiSettings.Cameras,
|
||||
"configuration.cameraIdList",
|
||||
"_id",
|
||||
"cameras"
|
||||
)
|
||||
.Lookup(
|
||||
_apiSettings.Relays,
|
||||
"configuration.relayIdList",
|
||||
"_id",
|
||||
"relays"
|
||||
)
|
||||
.Project<PointOfCare>(new BsonDocument
|
||||
{
|
||||
{ "_id", 1 },
|
||||
{ "room", 1 },
|
||||
{ "bed", 1 },
|
||||
{ "hall", 1 },
|
||||
{ "unitId", 1 },
|
||||
{ "status", 1 },
|
||||
{ "admissionId", 1 },
|
||||
|
||||
{ "configuration", new BsonDocument
|
||||
{
|
||||
{ "beaconList", "$beacons" },
|
||||
{ "cameraList", "$cameras" },
|
||||
{ "relayList", "$relays" },
|
||||
{ "type", "$configuration.type" },
|
||||
{ "id", "$configuration.id" }
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return await pipeline.ToListAsync();
|
||||
}
|
||||
|
||||
public async Task<List<PointOfCare>?> GetAllLocationInfo()
|
||||
{
|
||||
var filter = Builders<PointOfCare>.Filter.Empty;
|
||||
|
||||
var projection = Builders<PointOfCare>.Projection
|
||||
.Include(p => p.Id)
|
||||
.Include(p => p.UnitId)
|
||||
.Include(p => p.Room)
|
||||
.Include(p => p.Bed);
|
||||
|
||||
var result = await Collection.Find(filter).Project<PointOfCare>(projection).ToListAsync();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public IFindFluent<PointOfCare, PointOfCare> GetPaginatedPoCs(PaginationFilter filter)
|
||||
{
|
||||
var filterBuilder = Builders<PointOfCare>.Filter;
|
||||
var sort = Builders<PointOfCare>.Sort.Descending("_id");
|
||||
var filters = new List<FilterDefinition<PointOfCare>>();
|
||||
|
||||
if (filter.FilteredRequest == null) return CreateFindFluent(filters, sort);
|
||||
|
||||
// Verifica UnitName contiene el valor de FilteredRequest.Text
|
||||
if (!string.IsNullOrEmpty(filter.FilteredRequest?.UnitId) &&
|
||||
ObjectId.TryParse(filter.FilteredRequest.UnitId, out var unitId))
|
||||
filters.Add(filterBuilder.Eq(d => d.UnitId, unitId));
|
||||
else if (!string.IsNullOrEmpty(filter.FilteredRequest?.UnitName))
|
||||
filters.Add(filterBuilder.Eq(d => d.Unit!.Name, filter.FilteredRequest?.UnitName));
|
||||
|
||||
if (filter.FilteredRequest?.PointOfCareStatus != null)
|
||||
{
|
||||
var statusFilter = filter.FilteredRequest.PointOfCareStatus;
|
||||
|
||||
filters.Add(filterBuilder.Eq(p => p.Status, statusFilter));
|
||||
}
|
||||
|
||||
return CreateFindFluent(filters, sort);
|
||||
}
|
||||
|
||||
//Deprecated PatientLocation by UnitName
|
||||
public async Task<PointOfCare?> FindByPatientLocation(PatientLocation patientLocation)
|
||||
{
|
||||
try
|
||||
{
|
||||
var filterBuilder = Builders<PointOfCare>.Filter;
|
||||
List<FilterDefinition<PointOfCare>> filters = [];
|
||||
|
||||
if (!string.IsNullOrEmpty(patientLocation.UnitName))
|
||||
filters.Add(filterBuilder.Eq(p => p.UnitName, patientLocation.UnitName));
|
||||
|
||||
if (!string.IsNullOrEmpty(patientLocation.Bed))
|
||||
filters.Add(filterBuilder.Eq(p => p.Bed, patientLocation.Bed));
|
||||
|
||||
if (!string.IsNullOrEmpty(patientLocation.Room))
|
||||
filters.Add(filterBuilder.Eq(p => p.Room, patientLocation.Room));
|
||||
|
||||
// Combina todos los filtros en uno solo usando el operador & si hay más de un filtro, de lo contrario, usa un filtro vacío.
|
||||
var combinedFilter = filters.Count > 0
|
||||
? filters.Aggregate((current, next) => current & next)
|
||||
: filterBuilder.Empty;
|
||||
|
||||
var result = await Collection.Find(combinedFilter).Limit(1).FirstOrDefaultAsync();
|
||||
|
||||
return result;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error("Error searching pointOfCares by patient location: {bed}. Exception: {ex}", patientLocation, ex);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public override async Task CreateIndexes()
|
||||
{
|
||||
var options = new CreateIndexOptions { Background = true, Unique = false };
|
||||
var indexes = new List<CreateIndexModel<PointOfCare>>
|
||||
{
|
||||
new("{ unitId: 1 }", options),
|
||||
new("{ room: 1 }", options),
|
||||
new("{ bed: 1 }", options)
|
||||
};
|
||||
|
||||
await MongoUtils.EnsureIndexes(Collection, indexes);
|
||||
}
|
||||
|
||||
public async Task UpdateStatus(ObjectId id, StatusEnum.PointOfCare status)
|
||||
{
|
||||
var filterBuilder = Builders<PointOfCare>.Filter;
|
||||
var filter = filterBuilder.Eq(p => p.Id, id);
|
||||
|
||||
var update = Builders<PointOfCare>.Update
|
||||
.Set(p => p.Status, status);
|
||||
|
||||
await Collection.UpdateOneAsync(filter, update);
|
||||
}
|
||||
|
||||
private IFindFluent<PointOfCare, PointOfCare> CreateFindFluent(List<FilterDefinition<PointOfCare>> filters,
|
||||
SortDefinition<PointOfCare> sort)
|
||||
{
|
||||
var combinedFilter = filters.Any()
|
||||
? Builders<PointOfCare>.Filter.And(filters)
|
||||
: Builders<PointOfCare>.Filter.Empty; // Filtra todo si no hay filtros
|
||||
return Collection.Find(combinedFilter).Sort(sort);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
using adas_core.Application.Repositories.Interfaces;
|
||||
using adas_core.Domain.Models.AppSettings;
|
||||
using adas_core.Domain.Models.Pumps;
|
||||
using Microsoft.Extensions.Options;
|
||||
using MongoDB.Bson;
|
||||
using MongoDB.Driver;
|
||||
|
||||
namespace adas_core.Infrastructure.Repositories;
|
||||
|
||||
public class PumpAlarmEventRepository : MongoRepository<PumpAlarmEvent>, IPumpAlarmEventRepository
|
||||
{
|
||||
private readonly ApiSettings _apiSettings;
|
||||
|
||||
public PumpAlarmEventRepository(IOptions<ApiSettings> apiSettings, IMongoDatabase database)
|
||||
: base(database)
|
||||
{
|
||||
_apiSettings = apiSettings.Value;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public override string GetCollectionName()
|
||||
{
|
||||
return _apiSettings.PumpAlarmEvent ?? "pump_alarm_event";
|
||||
}
|
||||
|
||||
public override async Task CreateIndexes()
|
||||
{
|
||||
var indexModels = new List<CreateIndexModel<PumpAlarmEvent>>
|
||||
{
|
||||
// Principal para consultas por bomba y orden temporal
|
||||
new(
|
||||
Builders<PumpAlarmEvent>.IndexKeys
|
||||
.Ascending(x => x.DeviceId)
|
||||
.Descending(x => x.Time),
|
||||
new CreateIndexOptions { Name = "ix_deviceId_time" }),
|
||||
|
||||
// Índice temporal
|
||||
new(
|
||||
Builders<PumpAlarmEvent>.IndexKeys.Descending(x => x.Time),
|
||||
new CreateIndexOptions { Name = "ix_time" }),
|
||||
|
||||
// por paciente
|
||||
new(
|
||||
Builders<PumpAlarmEvent>.IndexKeys.Ascending(x => x.PatientId),
|
||||
new CreateIndexOptions { Name = "ix_patientId" }),
|
||||
|
||||
//por tipo de alarma dentro de una bomba
|
||||
new(
|
||||
Builders<PumpAlarmEvent>.IndexKeys
|
||||
.Ascending(x => x.DeviceId)
|
||||
.Ascending(x => x.AlarmType),
|
||||
new CreateIndexOptions { Name = "ix_device_alarmType" })
|
||||
};
|
||||
|
||||
await Collection.Indexes.CreateManyAsync(indexModels);
|
||||
}
|
||||
|
||||
|
||||
public async Task InsertAsync(PumpAlarmEvent alarmEvent)
|
||||
{
|
||||
await Collection.InsertOneAsync(alarmEvent);
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<PumpAlarmEvent>> FindByDeviceIdAsync(string deviceId, DateTime? from = null,
|
||||
DateTime? to = null, int? limit = null)
|
||||
{
|
||||
var filter = Builders<PumpAlarmEvent>.Filter.Eq(x => x.DeviceId, deviceId);
|
||||
|
||||
if (from.HasValue)
|
||||
filter &= Builders<PumpAlarmEvent>.Filter.Gte(x => x.Time, from.Value);
|
||||
|
||||
if (to.HasValue)
|
||||
filter &= Builders<PumpAlarmEvent>.Filter.Lte(x => x.Time, to.Value);
|
||||
|
||||
var find = Collection.Find(filter).SortByDescending(x => x.Time);
|
||||
if (limit.HasValue) find = find.Limit(limit.Value) as IOrderedFindFluent<PumpAlarmEvent, PumpAlarmEvent>;
|
||||
|
||||
return await find.ToListAsync();
|
||||
}
|
||||
|
||||
public async Task<PumpAlarmEvent?> FindLastByDeviceIdAsync(string deviceId)
|
||||
{
|
||||
return await Collection
|
||||
.Find(x => x.DeviceId == deviceId)
|
||||
.SortByDescending(x => x.Time)
|
||||
.FirstOrDefaultAsync();
|
||||
}
|
||||
|
||||
public async Task DeleteByPatientId(ObjectId patientId)
|
||||
{
|
||||
await Collection.DeleteManyAsync(x => x.PatientId == patientId);
|
||||
}
|
||||
|
||||
|
||||
public async Task<long> UpdateManyObjectIdByFiledNameAsync(string fieldName, ObjectId newId, ObjectId oldId)
|
||||
{
|
||||
var filter = Builders<PumpAlarmEvent>.Filter.Eq(fieldName, oldId);
|
||||
var update = Builders<PumpAlarmEvent>.Update.Set(fieldName, newId);
|
||||
var result = await Collection.UpdateManyAsync(filter, update);
|
||||
return result.ModifiedCount;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,120 @@
|
||||
using adas_core.Application.Repositories.Interfaces;
|
||||
using adas_core.Domain.Enums;
|
||||
using adas_core.Domain.Models.AppSettings;
|
||||
using adas_core.Domain.Models.Pumps;
|
||||
using Microsoft.Extensions.Options;
|
||||
using MongoDB.Bson;
|
||||
using MongoDB.Driver;
|
||||
|
||||
namespace adas_core.Infrastructure.Repositories;
|
||||
|
||||
public class PumpAlarmStateRepository : MongoRepository<PumpAlarmState>, IPumpAlarmStateRepository
|
||||
{
|
||||
private readonly ApiSettings _apiSettings;
|
||||
|
||||
public PumpAlarmStateRepository(IOptions<ApiSettings> apiSettings, IMongoDatabase database)
|
||||
: base(database)
|
||||
{
|
||||
_apiSettings = apiSettings.Value;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public override string GetCollectionName()
|
||||
{
|
||||
return _apiSettings.PumpAlarmState ?? "pump_alarm_state";
|
||||
}
|
||||
|
||||
public override async Task CreateIndexes()
|
||||
{
|
||||
var indexModels = new List<CreateIndexModel<PumpAlarmState>>
|
||||
{
|
||||
// Clave única de alarma activa
|
||||
new(
|
||||
Builders<PumpAlarmState>.IndexKeys
|
||||
.Ascending(x => x.DeviceId)
|
||||
.Ascending(x => x.AlarmType)
|
||||
.Ascending(x => x.AlarmCodeMdc),
|
||||
new CreateIndexOptions { Unique = true, Name = "ux_device_alarm" }),
|
||||
|
||||
// Indexado por DeviceId
|
||||
new(
|
||||
Builders<PumpAlarmState>.IndexKeys.Ascending(x => x.DeviceId),
|
||||
new CreateIndexOptions { Name = "ix_device" }),
|
||||
|
||||
// indexado por PatientId
|
||||
new(
|
||||
Builders<PumpAlarmState>.IndexKeys.Ascending(x => x.PatientId),
|
||||
new CreateIndexOptions { Name = "ix_patientId" })
|
||||
};
|
||||
|
||||
await Collection.Indexes.CreateManyAsync(indexModels);
|
||||
}
|
||||
|
||||
public async Task<PumpAlarmState?> FindActiveAsync(string deviceId, PumpEnum.AlarmType? alarmType, string? alarmCodeMdc = null)
|
||||
{
|
||||
var filter = Builders<PumpAlarmState>.Filter.Eq(x => x.DeviceId, deviceId);
|
||||
|
||||
if (alarmType.HasValue)
|
||||
filter &= Builders<PumpAlarmState>.Filter.Eq(x => x.AlarmType, alarmType);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(alarmCodeMdc))
|
||||
filter &= Builders<PumpAlarmState>.Filter.Eq(x => x.AlarmCodeMdc, alarmCodeMdc);
|
||||
|
||||
return await Collection.Find(filter).FirstOrDefaultAsync();
|
||||
}
|
||||
|
||||
public async Task UpsertActiveAsync(PumpAlarmState state)
|
||||
{
|
||||
var filter =
|
||||
Builders<PumpAlarmState>.Filter.Eq(x => x.DeviceId, state.DeviceId) &
|
||||
Builders<PumpAlarmState>.Filter.Eq(x => x.AlarmType, state.AlarmType) &
|
||||
Builders<PumpAlarmState>.Filter.Eq(x => x.AlarmCodeMdc, state.AlarmCodeMdc);
|
||||
|
||||
// Revisar si ya existe un documento activo con esa combinación
|
||||
var existing = await Collection.Find(filter).FirstOrDefaultAsync();
|
||||
|
||||
if (existing != null)
|
||||
state.Id = existing.Id;
|
||||
else
|
||||
if (state.Id == ObjectId.Empty)
|
||||
state.Id = ObjectId.GenerateNewId();
|
||||
|
||||
await Collection.ReplaceOneAsync(
|
||||
filter,
|
||||
state,
|
||||
new ReplaceOptions { IsUpsert = true });
|
||||
}
|
||||
|
||||
|
||||
public async Task RemoveAsync(string? deviceId, PumpEnum.AlarmType? alarmType, string? alarmCodeMdc = null)
|
||||
{
|
||||
var filter = Builders<PumpAlarmState>.Filter.Eq(x => x.DeviceId, deviceId);
|
||||
|
||||
if (alarmType.HasValue)
|
||||
filter &= Builders<PumpAlarmState>.Filter.Eq(x => x.AlarmType, alarmType);
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(alarmCodeMdc))
|
||||
filter &= Builders<PumpAlarmState>.Filter.Eq(x => x.AlarmCodeMdc, alarmCodeMdc);
|
||||
|
||||
await Collection.DeleteManyAsync(filter);
|
||||
}
|
||||
|
||||
public async Task DeleteByPatientId(ObjectId patientId)
|
||||
{
|
||||
await Collection.DeleteManyAsync(p => p.PatientId == patientId);
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<PumpAlarmState>> FindAllActiveByDeviceAsync(string deviceId)
|
||||
{
|
||||
return await Collection.Find(x => x.DeviceId == deviceId).ToListAsync();
|
||||
}
|
||||
|
||||
public async Task<long> UpdateManyObjectIdByFieldNameAsync(string fieldName, ObjectId newId, ObjectId oldId)
|
||||
{
|
||||
var filter = Builders<PumpAlarmState>.Filter.Eq(fieldName, oldId);
|
||||
var update = Builders<PumpAlarmState>.Update.Set(fieldName, newId);
|
||||
var result = await Collection.UpdateManyAsync(filter, update);
|
||||
return result.ModifiedCount;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using adas_core.Application.Repositories.Interfaces;
|
||||
using adas_core.Domain.Models.AppSettings;
|
||||
using adas_core.Domain.Models.Pumps;
|
||||
using Microsoft.Extensions.Options;
|
||||
using MongoDB.Bson;
|
||||
using MongoDB.Driver;
|
||||
|
||||
namespace adas_core.Infrastructure.Repositories
|
||||
{
|
||||
/// <summary>
|
||||
/// Repositorio de archivo para observaciones de bombas.
|
||||
/// Colección: archive_pumpobservations (configurable por ApiSettings.ArchivePumpObservations).
|
||||
/// </summary>
|
||||
public class PumpArchiveRepository : MongoRepository<PumpObservation>, IPumpArchiveRepository
|
||||
{
|
||||
private readonly ApiSettings _apiSettings;
|
||||
|
||||
public PumpArchiveRepository(IOptions<ApiSettings> apiSettings, IMongoDatabase database)
|
||||
: base(database)
|
||||
{
|
||||
_apiSettings = apiSettings.Value;
|
||||
}
|
||||
|
||||
|
||||
public override string GetCollectionName()
|
||||
{
|
||||
// Nombre de colección pactado: "archive_pumpobservations"
|
||||
return _apiSettings.ArchivePatientsPumpobservations ?? "archive_pumpobservations";
|
||||
}
|
||||
|
||||
public override async Task CreateIndexes()
|
||||
{
|
||||
var indexModels = new List<CreateIndexModel<PumpObservation>>
|
||||
{
|
||||
// Búsquedas por paciente (audit / restauraciones)
|
||||
new CreateIndexModel<PumpObservation>(
|
||||
Builders<PumpObservation>.IndexKeys.Ascending(x => x.PatientId),
|
||||
new CreateIndexOptions { Name = "ix_patientId" }),
|
||||
|
||||
// Timeline por dispositivo (útil para auditorías por equipo)
|
||||
new CreateIndexModel<PumpObservation>(
|
||||
Builders<PumpObservation>.IndexKeys
|
||||
.Ascending(x => x.DeviceId)
|
||||
.Descending(x => x.Time),
|
||||
new CreateIndexOptions { Name = "ix_deviceId_time" }),
|
||||
|
||||
// Orden temporal simple
|
||||
new CreateIndexModel<PumpObservation>(
|
||||
Builders<PumpObservation>.IndexKeys.Descending(x => x.Time),
|
||||
new CreateIndexOptions { Name = "ix_time" })
|
||||
};
|
||||
|
||||
await Collection.Indexes.CreateManyAsync(indexModels);
|
||||
}
|
||||
|
||||
public async Task InsertAsync(PumpObservation obs)
|
||||
{
|
||||
await Collection.InsertOneAsync(obs);
|
||||
}
|
||||
|
||||
public async Task InsertManyAsync(IEnumerable<PumpObservation> observations)
|
||||
{
|
||||
var list = observations as IList<PumpObservation> ?? observations.ToList();
|
||||
if (list.Count == 0) return;
|
||||
|
||||
await Collection.InsertManyAsync(list);
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<PumpObservation>> FindByPatientIdAsync(
|
||||
ObjectId patientId, DateTime? from = null, DateTime? to = null, int? limit = null)
|
||||
{
|
||||
var filter = Builders<PumpObservation>.Filter.Eq(x => x.PatientId, patientId);
|
||||
|
||||
if (from.HasValue)
|
||||
filter &= Builders<PumpObservation>.Filter.Gte(x => x.Time, from.Value);
|
||||
|
||||
if (to.HasValue)
|
||||
filter &= Builders<PumpObservation>.Filter.Lte(x => x.Time, to.Value);
|
||||
|
||||
var query = Collection.Find(filter).SortByDescending(x => x.Time);
|
||||
|
||||
if (limit.HasValue)
|
||||
query = query.Limit(limit.Value) as IOrderedFindFluent<PumpObservation, PumpObservation>;
|
||||
|
||||
return await query.ToListAsync();
|
||||
}
|
||||
|
||||
public async Task DeleteBeforeDate(DateTime addDays)
|
||||
{
|
||||
var filter = Builders<PumpObservation>.Filter.Lt(x => x.Time, addDays);
|
||||
await Collection.DeleteManyAsync(filter);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,297 @@
|
||||
using adas_core.Application.Repositories.Interfaces;
|
||||
using adas_core.Domain.Models.AppSettings;
|
||||
using adas_core.Domain.Models.Pumps;
|
||||
using Microsoft.Extensions.Options;
|
||||
using MongoDB.Bson;
|
||||
using MongoDB.Driver;
|
||||
|
||||
namespace adas_core.Infrastructure.Repositories
|
||||
{
|
||||
public class PumpObservationRepository : MongoRepository<PumpObservation>, IPumpObservationRepository
|
||||
{
|
||||
private readonly ApiSettings _apiSettings;
|
||||
|
||||
|
||||
|
||||
public PumpObservationRepository(IOptions<ApiSettings> apiSettings, IMongoDatabase database) : base(database)
|
||||
{
|
||||
_apiSettings = apiSettings.Value;
|
||||
}
|
||||
|
||||
public override string GetCollectionName()
|
||||
{
|
||||
return _apiSettings.PumpObservations ?? "pump_observations";
|
||||
}
|
||||
|
||||
public override async Task CreateIndexes()
|
||||
{
|
||||
var indexModels = new List<CreateIndexModel<PumpObservation>>
|
||||
{
|
||||
// Timeline por bomba (consulta más frecuente)
|
||||
new CreateIndexModel<PumpObservation>(
|
||||
Builders<PumpObservation>.IndexKeys
|
||||
.Ascending(x => x.DeviceId)
|
||||
.Descending(x => x.Time),
|
||||
new CreateIndexOptions { Name = "ix_deviceId_time" }),
|
||||
|
||||
// consultas por paciente
|
||||
new CreateIndexModel<PumpObservation>(
|
||||
Builders<PumpObservation>.IndexKeys.Ascending(x => x.PatientId),
|
||||
new CreateIndexOptions { Name = "ix_patientId" }),
|
||||
|
||||
|
||||
// TTL por antigüedad (si aplica retención directa en Mongo)
|
||||
// new CreateIndexModel<PumpObservation>(
|
||||
// Builders<PumpObservation>.IndexKeys.Ascending(x => x.Time),
|
||||
// new CreateIndexOptions { Name = "ttl_time", ExpireAfter = TimeSpan.FromDays(180) })
|
||||
};
|
||||
|
||||
await Collection.Indexes.CreateManyAsync(indexModels);
|
||||
}
|
||||
|
||||
public async Task InsertAsync(PumpObservation obs)
|
||||
{
|
||||
await Collection.InsertOneAsync(obs);
|
||||
}
|
||||
|
||||
public async Task InsertManyAsync(IEnumerable<PumpObservation>? observations)
|
||||
{
|
||||
if (observations == null) return;
|
||||
|
||||
var list = observations as IList<PumpObservation> ?? observations.ToList();
|
||||
if (list.Count == 0) return;
|
||||
|
||||
await Collection.InsertManyAsync(list);
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<PumpObservation>> FindByDeviceIdAsync(
|
||||
string deviceId,
|
||||
DateTime? from = null,
|
||||
DateTime? to = null,
|
||||
int? limit = null)
|
||||
{
|
||||
var filter = Builders<PumpObservation>.Filter.Eq(x => x.DeviceId, deviceId);
|
||||
|
||||
if (from.HasValue)
|
||||
filter &= Builders<PumpObservation>.Filter.Gte(x => x.Time, from.Value);
|
||||
|
||||
if (to.HasValue)
|
||||
filter &= Builders<PumpObservation>.Filter.Lte(x => x.Time, to.Value);
|
||||
|
||||
var query = Collection.Find(filter)
|
||||
.SortByDescending(x => x.Time);
|
||||
|
||||
if (limit.HasValue)
|
||||
query = query.Limit(limit.Value) as IOrderedFindFluent<PumpObservation, PumpObservation>;
|
||||
|
||||
return await query.ToListAsync();
|
||||
}
|
||||
|
||||
// histórico por paciente
|
||||
public async Task<IEnumerable<PumpObservation>> FindByPatientAsync(
|
||||
ObjectId patientId,
|
||||
DateTime? from = null,
|
||||
DateTime? to = null,
|
||||
int? limit = null)
|
||||
{
|
||||
var filter = Builders<PumpObservation>.Filter.Eq(x => x.PatientId, patientId);
|
||||
|
||||
if (from.HasValue)
|
||||
filter &= Builders<PumpObservation>.Filter.Gte(x => x.Time, from.Value);
|
||||
|
||||
if (to.HasValue)
|
||||
filter &= Builders<PumpObservation>.Filter.Lte(x => x.Time, to.Value);
|
||||
|
||||
var query = Collection.Find(filter)
|
||||
.SortByDescending(x => x.Time);
|
||||
|
||||
if (limit.HasValue)
|
||||
query = query.Limit(limit.Value) as IOrderedFindFluent<PumpObservation, PumpObservation>;
|
||||
|
||||
return await query.ToListAsync();
|
||||
}
|
||||
|
||||
public async Task<Dictionary<ObjectId, DateTime>> FindAllLastPatientObservationTimeAsync()
|
||||
{
|
||||
// Pipeline:
|
||||
// 1) Filtrar observaciones con PatientId no nulo
|
||||
// 2) Agrupar por PatientId
|
||||
// 3) Obtener el máximo Time
|
||||
// 4) Devolver diccionario
|
||||
|
||||
var pipeline = new[]
|
||||
{
|
||||
new BsonDocument("$match", new BsonDocument
|
||||
{
|
||||
{ "patientid", new BsonDocument("$ne", BsonNull.Value) }
|
||||
}),
|
||||
new BsonDocument("$group", new BsonDocument
|
||||
{
|
||||
{ "_id", "$patientid" },
|
||||
{ "LastTime", new BsonDocument("$max", "$time") }
|
||||
})
|
||||
};
|
||||
|
||||
var docs = await Collection.Aggregate<BsonDocument>(pipeline).ToListAsync();
|
||||
|
||||
var result = new Dictionary<ObjectId, DateTime>();
|
||||
|
||||
foreach (var doc in docs.Where(doc =>
|
||||
doc["_id"].IsObjectId && doc["LastTime"].IsValidDateTime
|
||||
))
|
||||
{
|
||||
result[doc["_id"].AsObjectId] = doc["LastTime"].ToUniversalTime();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<PumpObservation?> FindLastByDeviceIdAsync(string deviceId)
|
||||
{
|
||||
return await Collection
|
||||
.Find(x => x.DeviceId == deviceId)
|
||||
.SortByDescending(x => x.Time)
|
||||
.FirstOrDefaultAsync();
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<PumpObservation>> FindByPatientId(ObjectId? patientId)
|
||||
{
|
||||
return await Collection.Find(x => x.PatientId == patientId).ToListAsync();
|
||||
}
|
||||
|
||||
|
||||
public async Task<List<PumpObservation>> AggregatedPatientLastObservations(ObjectId patientId, int num = 100)
|
||||
{
|
||||
var filterBuilder = Builders<PumpObservation>.Filter;
|
||||
var sortBuilder = Builders<PumpObservation>.Sort;
|
||||
|
||||
var filter = filterBuilder.Eq(o => o.PatientId, patientId);
|
||||
var sort = sortBuilder.Descending("time");
|
||||
var options = new FindOptions<PumpObservation> { Sort = sort, Limit = num };
|
||||
|
||||
var result = await Collection.FindAsync(filter, options);
|
||||
var observations = await result.ToListAsync();
|
||||
|
||||
var distinctObservations = observations.DistinctBy(m => new { m.Code, m.Name }).ToList();
|
||||
var sortedObservations = distinctObservations.OrderByDescending(x => x.Time).ToList();
|
||||
|
||||
return sortedObservations;
|
||||
}
|
||||
|
||||
public async Task DeleteByPatientId(ObjectId? patientId)
|
||||
{
|
||||
await Collection.DeleteManyAsync(x => x.PatientId == patientId);
|
||||
}
|
||||
public async Task<long> DeleteOlderThanDaysAsync(int days, string? name = null)
|
||||
{
|
||||
var limitDate = DateTime.UtcNow.AddDays(-days);
|
||||
|
||||
var filter = Builders<PumpObservation>.Filter.Lt(x => x.Time, limitDate);
|
||||
if(!string.IsNullOrEmpty(name))
|
||||
filter &= Builders<PumpObservation>.Filter.Eq(x=> x.Name, name);
|
||||
|
||||
return (await Collection.DeleteManyAsync(filter)).DeletedCount;
|
||||
}
|
||||
|
||||
public async Task<long> DeleteKeepLastNAsync(int maxCount)
|
||||
{
|
||||
// Para cada DeviceId:
|
||||
var deviceIds = await Collection
|
||||
.Distinct<string>("DeviceId", FilterDefinition<PumpObservation>.Empty)
|
||||
.ToListAsync();
|
||||
|
||||
long totalDeleted = 0;
|
||||
|
||||
foreach (var filter in deviceIds.Select(deviceId =>
|
||||
Builders<PumpObservation>.Filter.Eq(x => x.DeviceId, deviceId)
|
||||
))
|
||||
{
|
||||
var all = await Collection.Find(filter)
|
||||
.SortByDescending(x => x.Time)
|
||||
.ToListAsync();
|
||||
|
||||
if (all.Count <= maxCount)
|
||||
continue;
|
||||
|
||||
var toDelete = all.Skip(maxCount).Select(x => x.Id).ToList();
|
||||
|
||||
var deleteFilter = Builders<PumpObservation>.Filter.In(x => x.Id, toDelete);
|
||||
var result = await Collection.DeleteManyAsync(deleteFilter);
|
||||
|
||||
totalDeleted += result.DeletedCount;
|
||||
}
|
||||
|
||||
return totalDeleted;
|
||||
}
|
||||
|
||||
public async Task<long> UpdateManyObjectIdByFieldAsync(string fieldName, ObjectId newId, ObjectId? oldId)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(fieldName))
|
||||
throw new ArgumentException("fieldName can't be null or empty.", nameof(fieldName));
|
||||
|
||||
// Normalize casing (Mongo is case-sensitive)
|
||||
// if (fieldName.Equals("patientid", StringComparison.OrdinalIgnoreCase))
|
||||
// fieldName = nameof(PumpObservation.PatientId);
|
||||
|
||||
var filter = Builders<PumpObservation>.Filter.Eq(fieldName, oldId);
|
||||
var update = Builders<PumpObservation>.Update.Set(fieldName, newId);
|
||||
|
||||
var result = await Collection.UpdateManyAsync(filter, update);
|
||||
return result.ModifiedCount;
|
||||
}
|
||||
|
||||
|
||||
public async Task<long> DeleteOlderNumberAsync(string name, int maxCount)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(name))
|
||||
return 0;
|
||||
|
||||
// 1. Filtrar todas las observaciones con ese Name
|
||||
var filter = Builders<PumpObservation>.Filter.Eq(x => x.Name, name);
|
||||
|
||||
// 2. Obtenerlas ordenadas por Time DESC (las más recientes primero)
|
||||
var all = await Collection
|
||||
.Find(filter)
|
||||
.SortByDescending(x => x.Time)
|
||||
.ToListAsync();
|
||||
|
||||
// 3. Si hay menos o igual al número permitido → no borrar nada
|
||||
if (all.Count <= maxCount)
|
||||
return 0;
|
||||
|
||||
// 4. Seleccionar TODAS excepto las maxCount más recientes
|
||||
var toDeleteIds = all
|
||||
.Skip(maxCount)
|
||||
.Select(x => x.Id)
|
||||
.ToList();
|
||||
|
||||
if (toDeleteIds.Count == 0)
|
||||
return 0;
|
||||
|
||||
// 5. Borrar las seleccionadas
|
||||
var deleteFilter = Builders<PumpObservation>.Filter.In(x => x.Id, toDeleteIds);
|
||||
var result = await Collection.DeleteManyAsync(deleteFilter);
|
||||
|
||||
return result.DeletedCount;
|
||||
}
|
||||
|
||||
|
||||
public async Task<List<PumpObservation>> FindLastObservations(ObjectId patientId, string name)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(name))
|
||||
return [];
|
||||
|
||||
var filter = Builders<PumpObservation>.Filter.And(
|
||||
Builders<PumpObservation>.Filter.Eq(x => x.PatientId, patientId),
|
||||
Builders<PumpObservation>.Filter.Eq(x => x.Name, name)
|
||||
);
|
||||
|
||||
return await Collection
|
||||
.Find(filter)
|
||||
.SortByDescending(x => x.Time)
|
||||
.Limit(2)
|
||||
.ToListAsync();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
using adas_core.Application.Repositories.Interfaces;
|
||||
using adas_core.Domain.Models.AppSettings;
|
||||
using adas_core.Domain.Models.Pumps;
|
||||
using Microsoft.Extensions.Options;
|
||||
using MongoDB.Bson;
|
||||
using MongoDB.Driver;
|
||||
|
||||
namespace adas_core.Infrastructure.Repositories
|
||||
{
|
||||
public class PumpStateRepository : MongoRepository<PumpState>, IPumpStateRepository
|
||||
{
|
||||
private readonly ApiSettings _apiSettings;
|
||||
|
||||
public PumpStateRepository(IOptions<ApiSettings> apiSettings, IMongoDatabase database)
|
||||
: base(database)
|
||||
{
|
||||
_apiSettings = apiSettings.Value;
|
||||
}
|
||||
|
||||
|
||||
public override string GetCollectionName()
|
||||
{
|
||||
return _apiSettings.PumpStates ?? "pump_states";
|
||||
}
|
||||
|
||||
public override async Task CreateIndexes()
|
||||
{
|
||||
var indexModels = new List<CreateIndexModel<PumpState>>
|
||||
{
|
||||
// Clave única del snapshot
|
||||
new CreateIndexModel<PumpState>(
|
||||
Builders<PumpState>.IndexKeys.Ascending(x => x.DeviceId),
|
||||
new CreateIndexOptions { Unique = true, Name = "ux_deviceId" }),
|
||||
|
||||
// Consultas por DeviceId + actualización temporal
|
||||
new CreateIndexModel<PumpState>(
|
||||
Builders<PumpState>.IndexKeys
|
||||
.Ascending(x => x.DeviceId)
|
||||
.Descending(x => x.LastUpdated),
|
||||
new CreateIndexOptions { Name = "ix_deviceId_lastUpdated" }),
|
||||
|
||||
// indexado por PatientId
|
||||
new CreateIndexModel<PumpState>(
|
||||
Builders<PumpState>.IndexKeys.Ascending(x => x.PatientId),
|
||||
new CreateIndexOptions { Name = "ix_patientId" })
|
||||
};
|
||||
|
||||
await Collection.Indexes.CreateManyAsync(indexModels);
|
||||
}
|
||||
|
||||
public async Task<PumpState?> FindByDeviceIdAsync(string deviceId)
|
||||
{
|
||||
return await Collection.Find(x => x.DeviceId == deviceId).FirstOrDefaultAsync();
|
||||
}
|
||||
|
||||
public async Task UpsertAsync(PumpState state)
|
||||
{
|
||||
var existing = await Collection
|
||||
.Find(x => x.DeviceId == state.DeviceId)
|
||||
.FirstOrDefaultAsync();
|
||||
|
||||
if (existing != null)
|
||||
state.Id = existing.Id;
|
||||
else
|
||||
if (state.Id == ObjectId.Empty)
|
||||
state.Id = ObjectId.GenerateNewId();
|
||||
|
||||
await Collection.ReplaceOneAsync(
|
||||
x => x.DeviceId == state.DeviceId,
|
||||
state,
|
||||
new ReplaceOptions { IsUpsert = true });
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<PumpState>> GetAllAsync()
|
||||
{
|
||||
return await Collection.Find(Builders<PumpState>.Filter.Empty).ToListAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
using adas_core.Application.Repositories.Interfaces;
|
||||
using adas_core.Domain.Models;
|
||||
using adas_core.Domain.Models.AppSettings;
|
||||
using Microsoft.Extensions.Options;
|
||||
using MongoDB.Driver;
|
||||
|
||||
namespace adas_core.Infrastructure.Repositories;
|
||||
|
||||
public class RecordingAlertArchiveRepository : MongoRepository<PatientRecordingAlert>, IRecordingAlertArchiveRepository
|
||||
{
|
||||
private readonly ApiSettings _apiSettings;
|
||||
|
||||
public RecordingAlertArchiveRepository(IOptions<ApiSettings> apiSettings, IMongoDatabase database) : base(database)
|
||||
{
|
||||
if (apiSettings == null) throw new ArgumentNullException(nameof(apiSettings));
|
||||
_apiSettings = apiSettings.Value;
|
||||
} // To testing
|
||||
|
||||
|
||||
|
||||
|
||||
public override string GetCollectionName()
|
||||
{
|
||||
return _apiSettings.ArchivePatientsRecordingalerts ?? "archive_patients_recordingalerts";
|
||||
}
|
||||
|
||||
public override async Task InsertOneAsync(PatientRecordingAlert patientRecordingAlert)
|
||||
{
|
||||
await Collection.InsertOneAsync(patientRecordingAlert);
|
||||
}
|
||||
|
||||
public async Task DeleteBeforeDate(DateTime date)
|
||||
{
|
||||
var filter = Builders<PatientRecordingAlert>.Filter.Lt(po => po.Time, date);
|
||||
await Collection.DeleteManyAsync(filter);
|
||||
}
|
||||
|
||||
public async Task<long> InsertBatch(IEnumerable<PatientRecordingAlert> patientRecordingAlerts)
|
||||
{
|
||||
var writes = new List<WriteModel<PatientRecordingAlert>>();
|
||||
writes.AddRange(patientRecordingAlerts.Select(d => new InsertOneModel<PatientRecordingAlert>(d)));
|
||||
|
||||
var bulkInsert = await Collection.BulkWriteAsync(writes);
|
||||
|
||||
return bulkInsert.InsertedCount;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,211 @@
|
||||
using System.Diagnostics;
|
||||
using adas_core.Application.Repositories.Interfaces;
|
||||
using adas_core.Domain.Models;
|
||||
using adas_core.Domain.Models.AppSettings;
|
||||
using Microsoft.Extensions.Options;
|
||||
using MongoDB.Bson;
|
||||
using MongoDB.Bson.Serialization;
|
||||
using MongoDB.Driver;
|
||||
using MongoUtils = adas_core.Infrastructure.Utils.MongoUtils;
|
||||
|
||||
namespace adas_core.Infrastructure.Repositories;
|
||||
|
||||
public class RecordingAlertRepository : MongoRepository<PatientRecordingAlert>, IRecordingAlertRepository
|
||||
{
|
||||
private readonly ApiSettings _apiSettings;
|
||||
|
||||
public RecordingAlertRepository(IOptions<ApiSettings> apiSettings, IMongoDatabase database) : base(database)
|
||||
{
|
||||
if (apiSettings == null) throw new ArgumentNullException(nameof(apiSettings));
|
||||
_apiSettings = apiSettings.Value;
|
||||
} //For testing
|
||||
|
||||
|
||||
|
||||
public override string GetCollectionName()
|
||||
{
|
||||
return _apiSettings.PatientsRecordingAlerts ?? "patients_recordingalerts";
|
||||
}
|
||||
|
||||
public async Task<List<PatientRecordingAlert>> AggregatedPatientLastObservations(ObjectId patientId, int num)
|
||||
{
|
||||
var match = new BsonDocument
|
||||
{
|
||||
{ "patientid", patientId }
|
||||
};
|
||||
var pipeline = new BsonDocument[]
|
||||
{
|
||||
new()
|
||||
{
|
||||
{
|
||||
"$match", match
|
||||
}
|
||||
},
|
||||
new()
|
||||
{
|
||||
{
|
||||
"$sort", new BsonDocument
|
||||
{
|
||||
{ "codingSystem", 1 },
|
||||
{ "code", 1 },
|
||||
{ "time", -1 }
|
||||
}
|
||||
}
|
||||
},
|
||||
new()
|
||||
{
|
||||
{
|
||||
"$group", new BsonDocument
|
||||
{
|
||||
{
|
||||
"_id", new BsonDocument
|
||||
{
|
||||
// { "codingSystem", "$codingSystem" } ,
|
||||
// { "code", "$code" } ,
|
||||
{ "name", "$name" }
|
||||
}
|
||||
},
|
||||
{
|
||||
"results", new BsonDocument
|
||||
{
|
||||
{ "$push", "$$ROOT" }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
new()
|
||||
{
|
||||
{
|
||||
"$project", new BsonDocument
|
||||
{
|
||||
{
|
||||
"results", new BsonDocument
|
||||
{
|
||||
{ "$slice", new BsonArray { "$results", num } }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
Debug.WriteLine(pipeline.ToJson());
|
||||
var result =
|
||||
await Collection.AggregateAsync<BsonDocument>(pipeline, new AggregateOptions { AllowDiskUse = true });
|
||||
var obs = new List<PatientRecordingAlert>();
|
||||
result.ToList().ForEach(it =>
|
||||
{
|
||||
foreach (var obit in it.GetValue("results").AsBsonArray)
|
||||
{
|
||||
var obsit = obit.AsBsonDocument;
|
||||
var pobs = BsonSerializer.Deserialize<PatientRecordingAlert>(obsit);
|
||||
pobs.PatientId = patientId;
|
||||
obs.Add(pobs);
|
||||
}
|
||||
});
|
||||
return obs;
|
||||
}
|
||||
|
||||
public new async Task DeleteAsync(ObjectId id)
|
||||
{
|
||||
var filter = Builders<PatientRecordingAlert>.Filter.Eq(obs => obs.Id, id);
|
||||
await Collection.DeleteOneAsync(filter);
|
||||
}
|
||||
|
||||
|
||||
public override async Task InsertOneAsync(PatientRecordingAlert patientRecordingAlert)
|
||||
{
|
||||
await Collection.InsertOneAsync(patientRecordingAlert);
|
||||
}
|
||||
|
||||
public async Task DeleteOlderDaysAsync(string name, int retentionPolicyValue)
|
||||
{
|
||||
var filterBuilder = Builders<PatientRecordingAlert>.Filter;
|
||||
var filter = filterBuilder.And(
|
||||
filterBuilder.Eq(obs => obs.Name, name),
|
||||
filterBuilder.Lt(obs => obs.Time, DateTime.UtcNow.AddDays(-1 * retentionPolicyValue))
|
||||
);
|
||||
|
||||
await Collection.DeleteOneAsync(filter);
|
||||
}
|
||||
|
||||
|
||||
public async Task DeleteByPatientId(ObjectId patientId)
|
||||
{
|
||||
var filter = Builders<PatientRecordingAlert>.Filter.Eq(po => po.PatientId, patientId);
|
||||
await Collection.DeleteManyAsync(filter);
|
||||
}
|
||||
|
||||
|
||||
public async Task DeleteOlderNumberAsync(string name, int retentionPolicyValue)
|
||||
{
|
||||
var filterBuilder = Builders<PatientRecordingAlert>.Filter;
|
||||
var sortBuilder = Builders<PatientRecordingAlert>.Sort;
|
||||
|
||||
var filter = filterBuilder.Eq(obs => obs.Name, name);
|
||||
var projection = Builders<PatientRecordingAlert>.Projection.Include(obs => obs.Id).Include(obs => obs.Time);
|
||||
var sort = sortBuilder.Descending("time");
|
||||
var options = new FindOptions<PatientRecordingAlert>
|
||||
{
|
||||
Projection = projection,
|
||||
Sort = sort,
|
||||
Skip = retentionPolicyValue
|
||||
};
|
||||
|
||||
var result = await Collection.FindAsync(filter, options);
|
||||
|
||||
await result.ForEachAsync(async obs =>
|
||||
{
|
||||
var idFilter = filterBuilder.Eq(ob => ob.Id, obs.Id);
|
||||
await Collection.DeleteOneAsync(idFilter);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public async Task<IAsyncCursor<PatientRecordingAlert>> FindByPatientIdAsync(ObjectId patientId)
|
||||
{
|
||||
var filter = Builders<PatientRecordingAlert>.Filter.Eq(ob => ob.PatientId, patientId);
|
||||
return await Collection.FindAsync(filter);
|
||||
}
|
||||
|
||||
|
||||
public async Task<List<PatientRecordingAlert>> FindLastObservations(ObjectId patientId, string name, int num = 2)
|
||||
{
|
||||
var filterBuilder = Builders<PatientRecordingAlert>.Filter;
|
||||
var sortBuilder = Builders<PatientRecordingAlert>.Sort;
|
||||
|
||||
var filter = filterBuilder.And(
|
||||
filterBuilder.Eq(ob => ob.PatientId, patientId),
|
||||
filterBuilder.Eq(ob => ob.Name, name)
|
||||
);
|
||||
|
||||
var sort = sortBuilder.Descending("time");
|
||||
|
||||
var options = new FindOptions<PatientRecordingAlert>
|
||||
{
|
||||
Sort = sort,
|
||||
Limit = num
|
||||
};
|
||||
|
||||
var result = await Collection.FindAsync(filter, options);
|
||||
|
||||
return await result.ToListAsync();
|
||||
}
|
||||
|
||||
|
||||
public async Task UpdateManyObjectId(string nameId, ObjectId id, ObjectId oldId)
|
||||
{
|
||||
await UpdateManyObjectIdAsync(nameId, id, oldId);
|
||||
}
|
||||
|
||||
public override async Task CreateIndexes()
|
||||
{
|
||||
var options = new CreateIndexOptions { Background = true, Unique = false };
|
||||
var indexes = new List<CreateIndexModel<PatientRecordingAlert>>
|
||||
{
|
||||
new("{ patientid: 1 }", options)
|
||||
};
|
||||
|
||||
await MongoUtils.EnsureIndexes(Collection, indexes);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,140 @@
|
||||
using adas_core.Application.Repositories.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 Newtonsoft.Json;
|
||||
using Serilog;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace adas_core.Infrastructure.Repositories;
|
||||
|
||||
public class RelayRepository : MongoRepository<Relay>, IRelayRepository
|
||||
{
|
||||
private readonly ApiSettings _apiSettings;
|
||||
|
||||
|
||||
|
||||
public RelayRepository(IMongoDatabase database, IOptions<ApiSettings> apiSettings) : base(database)
|
||||
{
|
||||
_apiSettings = apiSettings.Value;
|
||||
}
|
||||
|
||||
public override string GetCollectionName()
|
||||
{
|
||||
return _apiSettings.Relays;
|
||||
}
|
||||
|
||||
public async Task<Relay?> GetById(ObjectId relayId)
|
||||
{
|
||||
try
|
||||
{
|
||||
var filter = Builders<Relay>.Filter.Eq(x => x.Id, relayId);
|
||||
var result = await Collection.FindAsync(filter, null);
|
||||
return result.FirstOrDefault();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error("Exception trying to get relay by id: {id}. Exception {e}", relayId, e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public List<Relay> GetRelayByTypeInList(List<ObjectId> configurationRelayList, RelayEnum.Type type)
|
||||
{
|
||||
var filterBuilder = Builders<Relay>.Filter;
|
||||
|
||||
var filter = filterBuilder.And(
|
||||
filterBuilder.In(r => r.Id, configurationRelayList),
|
||||
filterBuilder.Eq(r => r.Type, type)
|
||||
);
|
||||
|
||||
return Collection.Find(filter).ToList();
|
||||
}
|
||||
|
||||
public List<Relay> GetRelayInList(List<ObjectId> configurationRelayList)
|
||||
{
|
||||
var filterBuilder = Builders<Relay>.Filter;
|
||||
|
||||
var filter = filterBuilder.And(
|
||||
filterBuilder.In(r => r.Id, configurationRelayList));
|
||||
|
||||
return Collection.Find(filter).ToList();
|
||||
}
|
||||
|
||||
public IFindFluent<Relay, Relay> GetPaginatedRelays(PaginationFilter filter)
|
||||
{
|
||||
var filterBuilder = Builders<Relay>.Filter;
|
||||
var sort = Builders<Relay>.Sort.Ascending("relayName");
|
||||
var filters = new List<FilterDefinition<Relay>>();
|
||||
|
||||
if (filter.FilteredRequest == null) return CreateFindFluent(filters, sort);
|
||||
|
||||
if (!string.IsNullOrEmpty(filter.FilteredRequest?.Text))
|
||||
{
|
||||
var textFilter = filter.FilteredRequest.Text;
|
||||
var textFilterEscaped = Regex.Escape(textFilter);
|
||||
|
||||
filters.Add(
|
||||
filterBuilder.Or(
|
||||
filterBuilder.Regex(p => p.RelayName,
|
||||
new BsonRegularExpression(textFilterEscaped, "i"))
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return CreateFindFluent(filters, sort);
|
||||
}
|
||||
|
||||
public async Task<Relay?> InsertOneRelayAsync(Relay request)
|
||||
{
|
||||
try
|
||||
{
|
||||
await Collection.InsertOneAsync(request);
|
||||
return await GetById(request.Id);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error("Error inserting relay: {relay}. Exception: {ex}",
|
||||
JsonConvert.SerializeObject(request, Formatting.Indented), ex);
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<Relay?> UpdateRelayAsync(ObjectId objectId, Relay relay)
|
||||
{
|
||||
var filter = Builders<Relay>.Filter.Eq("_id", objectId);
|
||||
var update = Builders<Relay>.Update
|
||||
.Set(c => c.Mode, relay.Mode)
|
||||
.Set(c => c.RelayNumber, relay.RelayNumber)
|
||||
.Set(c => c.Username, relay.Username)
|
||||
.Set(c => c.Password, relay.Password)
|
||||
.Set(c => c.Driver, relay.Driver)
|
||||
.Set(c => c.Ip, relay.Ip)
|
||||
.Set(c => c.Port, relay.Port)
|
||||
.Set(c => c.RelayName, relay.RelayName);
|
||||
return await Collection.FindOneAndUpdateAsync(filter, update,
|
||||
new FindOneAndUpdateOptions<Relay, Relay> { ReturnDocument = ReturnDocument.After });
|
||||
}
|
||||
|
||||
public async Task<Relay?> GetByName(string? requestRelayName)
|
||||
{
|
||||
var filterBuilder = Builders<Relay>.Filter;
|
||||
|
||||
var filter = filterBuilder.Eq(r => r.RelayName, requestRelayName);
|
||||
|
||||
return await Collection.Find(filter).FirstOrDefaultAsync();
|
||||
}
|
||||
|
||||
private IFindFluent<Relay, Relay> CreateFindFluent(List<FilterDefinition<Relay>> filters, SortDefinition<Relay> sort)
|
||||
{
|
||||
var combinedFilter = filters.Any()
|
||||
? Builders<Relay>.Filter.And(filters)
|
||||
: Builders<Relay>.Filter.Empty;
|
||||
return Collection.Find(combinedFilter).Sort(sort);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
using adas_core.Application.Repositories.Interfaces;
|
||||
using adas_core.Domain.Models;
|
||||
using adas_core.Domain.Models.AppSettings;
|
||||
using adas_core.Domain.Models.MongoModels;
|
||||
using Microsoft.Extensions.Options;
|
||||
using MongoDB.Driver;
|
||||
using Newtonsoft.Json;
|
||||
using Serilog;
|
||||
|
||||
namespace adas_core.Infrastructure.Repositories;
|
||||
|
||||
public class SectionRepository : MongoRepository<Section>, ISectionRepository
|
||||
{
|
||||
private readonly ApiSettings _apiSettings;
|
||||
|
||||
public SectionRepository(IOptions<ApiSettings> apiSettings, IMongoDatabase database) : base(database)
|
||||
{
|
||||
if (apiSettings == null) throw new ArgumentNullException(nameof(apiSettings));
|
||||
_apiSettings = apiSettings.Value;
|
||||
} //For testing
|
||||
|
||||
|
||||
|
||||
|
||||
public override string GetCollectionName()
|
||||
{
|
||||
return _apiSettings.ConfigSections ?? "config_sections";
|
||||
}
|
||||
|
||||
public async Task<List<Section>> GetAll()
|
||||
{
|
||||
var result = await Collection.FindAsync(Builders<Section>.Filter.Empty);
|
||||
|
||||
return result.ToList();
|
||||
}
|
||||
|
||||
public async Task<Section?> FindBySection(string section)
|
||||
{
|
||||
var result = await Collection.FindAsync(Builders<Section>.Filter.Eq(x => x.SectionTitle, section));
|
||||
|
||||
return await result.FirstOrDefaultAsync();
|
||||
}
|
||||
|
||||
public async Task<Section?> FindByPointOfCare(string pointOfCare)
|
||||
{
|
||||
var result = await Collection.FindAsync(Builders<Section>.Filter.Eq(x => x.PointOfCare, pointOfCare));
|
||||
|
||||
return await result.FirstOrDefaultAsync();
|
||||
}
|
||||
|
||||
public async Task<Section?> FindById(string id)
|
||||
{
|
||||
var result = await Collection.FindAsync(Builders<Section>.Filter.Eq(x => x.Id, id));
|
||||
|
||||
return await result.FirstOrDefaultAsync();
|
||||
}
|
||||
|
||||
public async Task<Section?> FindById(object id)
|
||||
{
|
||||
var result = await Collection.FindAsync(Builders<Section>.Filter.Eq(x => x._id, id));
|
||||
return await result.FirstOrDefaultAsync();
|
||||
}
|
||||
|
||||
public async Task<List<Section>> FindByLocation(PatientLocation location)
|
||||
{
|
||||
//can not filter to Collection the where condition, it throws System.InvalidOperationException: '{}.pointOfCare is not supported.'
|
||||
var sections = await GetAll();
|
||||
|
||||
return sections.Where(section =>
|
||||
(section.PointOfCare == location.UnitName && section.Items.Any(item =>
|
||||
item.Boxes.Any(box => box.PointOfCare == null && box.Bed == location.Bed && box.IsActive))) ||
|
||||
section.Items.Any(item =>
|
||||
item.Boxes.Any(box =>
|
||||
box.PointOfCare == location.UnitName && box.Bed == location.Bed && box.IsActive))).ToList();
|
||||
}
|
||||
|
||||
public async Task<Section?> InsertOneSection(Section section)
|
||||
{
|
||||
try
|
||||
{
|
||||
await Collection.InsertOneAsync(section);
|
||||
return await FindById(section.Id);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error("Error inserting section: {section}. Exception: {ex}",
|
||||
JsonConvert.SerializeObject(section, Formatting.Indented), ex);
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public async Task<Section?> UpdateSection(Section section)
|
||||
{
|
||||
var filter = Builders<Section>.Filter.Eq("Id", section.Id);
|
||||
var update = Builders<Section>.Update
|
||||
.Set(c => c.Id, section.Id)
|
||||
.Set(c => c.PointOfCare, section.PointOfCare)
|
||||
.Set(c => c.SectionTitle, section.SectionTitle)
|
||||
.Set(c => c.Configuration, section.Configuration)
|
||||
.Set(c => c.Items, section.Items);
|
||||
|
||||
return await Collection.FindOneAndUpdateAsync(filter, update,
|
||||
new FindOneAndUpdateOptions<Section, Section> { ReturnDocument = ReturnDocument.After });
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
using adas_core.Application.Repositories.Interfaces;
|
||||
using adas_core.Domain.Models.AppSettings;
|
||||
using adas_core.Domain.Models.MongoModels;
|
||||
using Microsoft.Extensions.Options;
|
||||
using MongoDB.Bson;
|
||||
using MongoDB.Driver;
|
||||
|
||||
namespace adas_core.Infrastructure.Repositories;
|
||||
|
||||
public class ServiceConfigRepository : MongoRepository<ServiceConfig>, IServiceConfigRepository
|
||||
{
|
||||
private readonly ApiSettings _apiSettings;
|
||||
|
||||
public ServiceConfigRepository(IOptions<ApiSettings> apiSettings, IMongoDatabase database) : base(database)
|
||||
{
|
||||
if (apiSettings == null) throw new ArgumentNullException(nameof(apiSettings));
|
||||
_apiSettings = apiSettings.Value;
|
||||
} //For testing
|
||||
|
||||
|
||||
|
||||
public override string GetCollectionName()
|
||||
{
|
||||
return _apiSettings.ServiceConfig ?? "service_config";
|
||||
}
|
||||
|
||||
public async Task<ServiceConfig?> FindById(string id)
|
||||
{
|
||||
var result = await Collection.FindAsync(Builders<ServiceConfig>.Filter.Eq(x => x.StrId, id));
|
||||
|
||||
return await result.FirstOrDefaultAsync();
|
||||
}
|
||||
|
||||
public async Task<ServiceConfig?> FindById(ObjectId oid)
|
||||
{
|
||||
var result = await Collection.FindAsync(Builders<ServiceConfig>.Filter.Eq(x => x.Id, oid));
|
||||
|
||||
return await result.FirstOrDefaultAsync();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
using adas_core.Application.Repositories.Interfaces;
|
||||
using adas_core.Domain.Models;
|
||||
using adas_core.Domain.Models.AppSettings;
|
||||
using Microsoft.Extensions.Options;
|
||||
using MongoDB.Bson;
|
||||
using MongoDB.Driver;
|
||||
|
||||
namespace adas_core.Infrastructure.Repositories;
|
||||
|
||||
public class TreatmentArchiveRepository : MongoRepository<PatientTreatment>, ITreatmentArchiveRepository
|
||||
{
|
||||
private readonly ApiSettings _apiSettings;
|
||||
|
||||
public TreatmentArchiveRepository(IOptions<ApiSettings> apiSettings, IMongoDatabase database) : base(database)
|
||||
{
|
||||
if (apiSettings == null) throw new ArgumentNullException(nameof(apiSettings));
|
||||
_apiSettings = apiSettings.Value;
|
||||
} //For testing
|
||||
|
||||
|
||||
|
||||
public override async Task InsertOneAsync(PatientTreatment patientTreatment)
|
||||
{
|
||||
await Collection.InsertOneAsync(patientTreatment);
|
||||
}
|
||||
|
||||
public async Task DeleteBeforeDate(DateTime date)
|
||||
{
|
||||
var filter = Builders<PatientTreatment>.Filter.Lt(po => po.OrderTime, date);
|
||||
await Collection.DeleteManyAsync(filter);
|
||||
}
|
||||
|
||||
public async Task<long> InsertBatch(IEnumerable<PatientTreatment> treatments)
|
||||
{
|
||||
var writes = new List<WriteModel<PatientTreatment>>();
|
||||
writes.AddRange(treatments.Select(d => new InsertOneModel<PatientTreatment>(d)));
|
||||
|
||||
var bulkInsert = await Collection.BulkWriteAsync(writes);
|
||||
|
||||
return bulkInsert.InsertedCount;
|
||||
}
|
||||
|
||||
public async Task<List<PatientTreatment>> FindAllFromPatient(ObjectId patientId)
|
||||
{
|
||||
var filter = Builders<PatientTreatment>.Filter.Eq(t => t.PatientId, patientId);
|
||||
var result = await Collection.FindAsync(filter);
|
||||
|
||||
return await result.ToListAsync();
|
||||
}
|
||||
|
||||
public override string GetCollectionName()
|
||||
{
|
||||
return _apiSettings.ArchivePatientsTreatments ?? "archive_patients_treatments";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,246 @@
|
||||
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.Filter;
|
||||
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 TreatmentRepository : MongoRepository<PatientTreatment>, ITreatmentRepository
|
||||
{
|
||||
private readonly ApiSettings _apiSettings;
|
||||
|
||||
|
||||
public TreatmentRepository(IOptions<ApiSettings> apiSettings, IMongoDatabase database) : base(database)
|
||||
{
|
||||
if (apiSettings == null) throw new ArgumentNullException(nameof(apiSettings));
|
||||
_apiSettings = apiSettings.Value;
|
||||
} //For testing
|
||||
|
||||
|
||||
public override string GetCollectionName()
|
||||
{
|
||||
return _apiSettings.PatientsTreatments ?? "patients_treatments";
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<PatientTreatment>> GetByPatientId(ObjectId patientId)
|
||||
{
|
||||
var filter = Builders<PatientTreatment>.Filter.Eq(ob => ob.PatientId, patientId);
|
||||
var result = await Collection.FindAsync(filter);
|
||||
return result.ToEnumerable();
|
||||
}
|
||||
|
||||
public async Task<IAsyncCursor<PatientTreatment>> GetById(ObjectId id)
|
||||
{
|
||||
var filter = Builders<PatientTreatment>.Filter.Eq(ob => ob.Id, id);
|
||||
var result = await Collection.FindAsync(filter);
|
||||
return result;
|
||||
}
|
||||
|
||||
public override async Task InsertOneAsync(PatientTreatment treatment)
|
||||
{
|
||||
treatment.OrderTime ??= DateTime.UtcNow;
|
||||
await base.InsertOneAsync(treatment);
|
||||
}
|
||||
|
||||
public new async Task DeleteAsync(ObjectId id)
|
||||
{
|
||||
var filter = Builders<PatientTreatment>.Filter.Eq(ob => ob.Id, id);
|
||||
await Collection.DeleteOneAsync(filter);
|
||||
}
|
||||
|
||||
|
||||
public async Task<IAsyncCursor<PatientTreatment>> FindByPatientIdAsync(ObjectId patientId)
|
||||
{
|
||||
var filter = Builders<PatientTreatment>.Filter.Eq(ob => ob.PatientId, patientId);
|
||||
return await Collection.FindAsync(filter);
|
||||
}
|
||||
|
||||
|
||||
public async Task<bool> DeleteByPatientId(ObjectId patientId)
|
||||
{
|
||||
try
|
||||
{
|
||||
var filter = Builders<PatientTreatment>.Filter.Eq(po => po.PatientId, patientId);
|
||||
await Collection.DeleteManyAsync(filter);
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(ex.ToString());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<bool> Update(PatientTreatment treatment)
|
||||
{
|
||||
try
|
||||
{
|
||||
await UpdateOneAsync(treatment.Id, treatment);
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error(ex.ToString());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<List<PatientTreatment>> FindBolusTreatments(ObjectId patientId)
|
||||
{
|
||||
var builder = Builders<PatientTreatment>.Filter;
|
||||
var filter = builder.And(
|
||||
builder.Eq(t => t.PatientId, patientId),
|
||||
builder.Exists(t => t.RequestedGiveCodesStatus),
|
||||
builder.SizeGt(t => t.RequestedGiveCodesStatus, 0)
|
||||
);
|
||||
|
||||
var result = await Collection.FindAsync(filter);
|
||||
|
||||
return await result.ToListAsync();
|
||||
}
|
||||
|
||||
public async Task<List<PatientTreatment>> GetActiveTreatmentsByPatientIdAndOrder(ObjectId patientId, string order)
|
||||
{
|
||||
var builder = Builders<PatientTreatment>.Filter;
|
||||
var filter = builder.And(
|
||||
builder.Or(
|
||||
builder.Eq(t => t.OrderControl, OrderControlType.Nw),
|
||||
builder.Eq(t => t.OrderControl, OrderControlType.Xo)
|
||||
),
|
||||
builder.Eq(t => t.PatientId, patientId),
|
||||
builder.And(
|
||||
builder.Ne(t => t.PlacerOrder, null), // Verifica que no sea nulo
|
||||
builder.Eq(t => t.PlacerOrder!.EntityIdentifier, order)
|
||||
)
|
||||
);
|
||||
|
||||
var result = await Collection.FindAsync(filter);
|
||||
|
||||
return await result.ToListAsync();
|
||||
}
|
||||
|
||||
|
||||
public async Task UpdateManyObjectId(string nameId, ObjectId id, ObjectId oldId)
|
||||
{
|
||||
await UpdateManyObjectIdAsync(nameId, id, oldId);
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<PatientTreatment>> FindByPatientId(ObjectId patientId)
|
||||
{
|
||||
var filter = Builders<PatientTreatment>.Filter.Eq(ob => ob.PatientId, patientId);
|
||||
var result = await Collection.FindAsync(filter);
|
||||
return result.ToEnumerable();
|
||||
}
|
||||
|
||||
public IFindFluent<PatientTreatment, PatientTreatment> GetPaginatedTreatments(PaginationFilter filter)
|
||||
{
|
||||
var filterBuilder = Builders<PatientTreatment>.Filter;
|
||||
var sort = Builders<PatientTreatment>.Sort.Descending("orderTime");
|
||||
var filters = new List<FilterDefinition<PatientTreatment>>();
|
||||
|
||||
if (filter.FilteredRequest == null)
|
||||
{
|
||||
AddDefaultTimeFilters(filters, filter, filterBuilder);
|
||||
return CreateFindFluent(filters, sort);
|
||||
}
|
||||
|
||||
var requestFilter = filter.FilteredRequest;
|
||||
if (requestFilter.PatientId != null && ObjectId.TryParse(requestFilter.PatientId, out var patientObjectId))
|
||||
filters.Add(filterBuilder.Eq(t => t.PatientId, patientObjectId));
|
||||
|
||||
if (requestFilter.StartDate != null) filters.Add(filterBuilder.Gt(t => t.OrderTime, requestFilter.StartDate));
|
||||
|
||||
if (requestFilter.EndDate != null) filters.Add(filterBuilder.Lt(t => t.OrderTime, requestFilter.EndDate));
|
||||
|
||||
if (string.IsNullOrWhiteSpace(requestFilter.Text))
|
||||
{
|
||||
//TODO falta definir la búsqueda por texto
|
||||
}
|
||||
|
||||
if (requestFilter.ActiveTreatments)
|
||||
AddActiveTreatmentFilters(filters, filterBuilder);
|
||||
else
|
||||
AddDefaultTimeFilters(filters, filter, filterBuilder);
|
||||
|
||||
return CreateFindFluent(filters, sort);
|
||||
}
|
||||
|
||||
public override async Task CreateIndexes()
|
||||
{
|
||||
var options = new CreateIndexOptions { Background = true, Unique = false };
|
||||
var indexes = new List<CreateIndexModel<PatientTreatment>>
|
||||
{
|
||||
new("{ patientid: 1 }", options)
|
||||
};
|
||||
|
||||
await MongoUtils.EnsureIndexes(Collection, indexes);
|
||||
}
|
||||
|
||||
private static void AddActiveTreatmentFilters(List<FilterDefinition<PatientTreatment>> filters,
|
||||
FilterDefinitionBuilder<PatientTreatment> filterBuilder)
|
||||
{
|
||||
var currentTime = DateTime.UtcNow;
|
||||
|
||||
filters.Add(
|
||||
filterBuilder.And(
|
||||
filterBuilder.Ne(t => t.PlacerOrder, null),
|
||||
filterBuilder.Ne(t => t.PlacerOrder!.EntityIdentifier, null)
|
||||
)
|
||||
);
|
||||
|
||||
filters.Add(
|
||||
filterBuilder.Or(
|
||||
filterBuilder.Eq(t => t.StartTime, null),
|
||||
filterBuilder.Lte(t => t.StartTime, currentTime)
|
||||
)
|
||||
);
|
||||
|
||||
filters.Add(
|
||||
filterBuilder.Or(
|
||||
filterBuilder.Eq(t => t.EndTime, null),
|
||||
filterBuilder.Gte(t => t.EndTime, currentTime)
|
||||
)
|
||||
);
|
||||
|
||||
filters.Add(filterBuilder.Ne(t => t.OrderControl, OrderControlType.Dc));
|
||||
filters.Add(
|
||||
filterBuilder.Or(
|
||||
filterBuilder.Eq(t => t.OrderControl, OrderControlType.Nw),
|
||||
filterBuilder.Eq(t => t.OrderControl, OrderControlType.Xo)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
private void AddDefaultTimeFilters(List<FilterDefinition<PatientTreatment>> filters, PaginationFilter filter,
|
||||
FilterDefinitionBuilder<PatientTreatment> filterBuilder)
|
||||
{
|
||||
filters.Add(
|
||||
filterBuilder.Or(
|
||||
filterBuilder.Eq(t => t.StartTime, null),
|
||||
filterBuilder.Gt(p => p.StartTime, filter.FilteredRequest?.StartDate ?? DateTime.MinValue)
|
||||
)
|
||||
);
|
||||
|
||||
filters.Add(
|
||||
filterBuilder.Or(
|
||||
filterBuilder.Eq(t => t.EndTime, null),
|
||||
filterBuilder.Lt(p => p.EndTime, filter.FilteredRequest?.EndDate ?? DateTime.MaxValue)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
private IFindFluent<PatientTreatment, PatientTreatment> CreateFindFluent(
|
||||
List<FilterDefinition<PatientTreatment>> filters, SortDefinition<PatientTreatment> sort)
|
||||
{
|
||||
var combinedFilter = filters.Any()
|
||||
? Builders<PatientTreatment>.Filter.And(filters)
|
||||
: Builders<PatientTreatment>.Filter.Empty; // Filtra todo si no hay filtros
|
||||
return Collection.Find(combinedFilter).Sort(sort);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,402 @@
|
||||
using adas_core.Application.Repositories.Interfaces;
|
||||
using adas_core.Domain.Enums;
|
||||
using adas_core.Domain.Models.AppSettings;
|
||||
using adas_core.Domain.Models.DTO;
|
||||
using adas_core.Domain.Models.Filter;
|
||||
using adas_core.Domain.Models.MongoModels;
|
||||
using Microsoft.Extensions.Options;
|
||||
using MongoDB.Bson;
|
||||
using MongoDB.Driver;
|
||||
using Newtonsoft.Json;
|
||||
using Serilog;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace adas_core.Infrastructure.Repositories;
|
||||
|
||||
public class UnitRepository : MongoRepository<Unit>, IUnitRepository
|
||||
{
|
||||
#region Properties
|
||||
|
||||
private readonly ApiSettings _apiSettings;
|
||||
|
||||
#endregion
|
||||
|
||||
#region Constructor
|
||||
|
||||
|
||||
|
||||
public UnitRepository(IOptions<ApiSettings> apiSettings, IMongoDatabase database) : base(database)
|
||||
{
|
||||
_apiSettings = apiSettings.Value;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Methods
|
||||
|
||||
#region Create
|
||||
|
||||
public async Task<Unit?> InsertOneUnit(Unit unit)
|
||||
{
|
||||
try
|
||||
{
|
||||
await Collection.InsertOneAsync(unit);
|
||||
return await FindById(unit.Id);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error("Error inserting Unit: {unit}. Exception: {ex}",
|
||||
JsonConvert.SerializeObject(unit, Formatting.Indented), ex);
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Read
|
||||
|
||||
public override string GetCollectionName()
|
||||
{
|
||||
return _apiSettings.Units ?? "units";
|
||||
}
|
||||
|
||||
// public async Task<Unit?> FindByLocation(PatientLocation location)
|
||||
// {
|
||||
// var filter = Builders<Unit>.Filter.ElemMatch(x => x.PointOfCares, poc => poc.Bed == location.Bed && poc.UnitName == location.UnitName);
|
||||
// var result = await Collection.Find(filter).FirstOrDefaultAsync();
|
||||
//
|
||||
// return result;
|
||||
// }
|
||||
|
||||
public async Task<Unit?> FindById(object id)
|
||||
{
|
||||
var result = await Collection.FindAsync(Builders<Unit>.Filter.Eq(x => x.Id, id));
|
||||
return await result.FirstOrDefaultAsync();
|
||||
}
|
||||
|
||||
public Task<Unit?> FindById(string id)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<Unit>> FindByMasterListId(ObjectId id, MasterListType masterListType)
|
||||
{
|
||||
try
|
||||
{
|
||||
var propertyName = $"{masterListType}Id"; // nombre de la propiedad dinámicamente
|
||||
var filter = Builders<Unit>.Filter.Eq(propertyName, id);
|
||||
|
||||
|
||||
var result = await Collection.Find(filter).ToListAsync();
|
||||
|
||||
return result;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error("Error searching unit by {masterlisttype} Id {id}. Exception: {ex}", masterListType.ToString(),
|
||||
id, ex);
|
||||
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<Unit>> FindByMasterListId(ObjectId id)
|
||||
{
|
||||
try
|
||||
{
|
||||
var filterBuilder = Builders<Unit>.Filter;
|
||||
var filters = new List<FilterDefinition<Unit>>
|
||||
{
|
||||
filterBuilder.Or(
|
||||
filterBuilder.Eq(p => p.DoctorListId, id),
|
||||
filterBuilder.Eq(p => p.AllergyListId, id),
|
||||
filterBuilder.Eq(p => p.DestinationListId, id),
|
||||
filterBuilder.Eq(p => p.DiagnosisListId, id),
|
||||
filterBuilder.Eq(p => p.InsulationListId, id),
|
||||
filterBuilder.Eq(p => p.OriginListId, id),
|
||||
filterBuilder.Eq(p => p.ProcedureListId, id),
|
||||
filterBuilder.Eq(p => p.TestListId, id),
|
||||
filterBuilder.Eq(p => p.ServiceListId, id),
|
||||
filterBuilder.Eq(p => p.TreatmentListId, id),
|
||||
filterBuilder.Eq(p => p.LanguageBarrierListId, id),
|
||||
filterBuilder.Eq(p => p.AltableOptionListId, id),
|
||||
filterBuilder.Eq(p => p.DischargeStatusListId, id),
|
||||
filterBuilder.Eq(p => p.DoctorTypeListId, id),
|
||||
filterBuilder.Eq(p => p.InternalDestinationListId, id),
|
||||
filterBuilder.Eq(p => p.PassiveSittingListId, id),
|
||||
filterBuilder.Eq(p => p.GenericListId, id),
|
||||
filterBuilder.Eq(p => p.VisitOptionListId, id),
|
||||
filterBuilder.Eq(p => p.AccessControlListId, id),
|
||||
filterBuilder.Eq(p => p.TherapeuticCeilingListId, id),
|
||||
filterBuilder.Eq(p => p.MobilityOptionListId, id)
|
||||
)
|
||||
};
|
||||
|
||||
|
||||
var result = await Collection.Find(Builders<Unit>.Filter.And(filters)).ToListAsync();
|
||||
|
||||
return result;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error("Error searching unit by masterlist Id {id}. Exception: {ex}", id.ToString(), ex);
|
||||
|
||||
return new List<Unit>();
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<long> CountUnitsByMasterListId(ObjectId id, MasterListType masterListType)
|
||||
{
|
||||
var propertyName = $"{masterListType}Id";
|
||||
var filter = Builders<Unit>.Filter.Eq(propertyName, id);
|
||||
var result = await Collection.CountDocumentsAsync(filter);
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<Unit?> FindByName(string unitName)
|
||||
{
|
||||
var result = await Collection.FindAsync(Builders<Unit>.Filter.Eq(x => x.Name, unitName));
|
||||
|
||||
return await result.FirstOrDefaultAsync();
|
||||
}
|
||||
|
||||
// public async Task<List<Unit>> FindByPointOfCare(PointOfCare pointOfCare)
|
||||
// {
|
||||
// var filter = Builders<Unit>.Filter.ElemMatch(x => x.PointOfCares, poc => poc.Bed == pointOfCare.Bed && poc.Room == pointOfCare.Room && pointOfCare.unitName == poc.unitName);
|
||||
// var result = await Collection.Find(filter).ToListAsync();
|
||||
//
|
||||
// return result;
|
||||
// }
|
||||
// public async Task<Unit?> FindByPointOfCare(PointOfCare pointOfCare)
|
||||
// {
|
||||
// var filter = Builders<Unit>.Filter.ElemMatch(x => x.PointOfCares, poc => poc.Bed == pointOfCare.Bed && poc.Room == pointOfCare.Room && pointOfCare.UnitName == poc.UnitName);
|
||||
// var result = await Collection.Find(filter).FirstOrDefaultAsync();
|
||||
//
|
||||
// return result;
|
||||
// }
|
||||
// public async Task<List<Unit>> FindByUnitName(string unitName)
|
||||
// {
|
||||
// var filter = Builders<Unit>.Filter.ElemMatch(x => x.PointOfCares, poc => poc.UnitName == unitName);
|
||||
// var result = await Collection.Find(filter).ToListAsync();
|
||||
//
|
||||
// return result;
|
||||
// }
|
||||
public async Task<List<Unit>> GetAll()
|
||||
{
|
||||
var result = await Collection.FindAsync(Builders<Unit>.Filter.Empty);
|
||||
|
||||
return result.ToList();
|
||||
}
|
||||
|
||||
|
||||
public IFindFluent<Unit, Unit> GetPaginatedUnits(PaginationFilter filter)
|
||||
{
|
||||
var filterBuilder = Builders<Unit>.Filter;
|
||||
var sort = Builders<Unit>.Sort.Ascending("title");
|
||||
var filters = new List<FilterDefinition<Unit>>();
|
||||
|
||||
if (filter.FilteredRequest == null) return CreateFindFluent(filters, sort);
|
||||
|
||||
if (!string.IsNullOrEmpty(filter.FilteredRequest?.Text))
|
||||
{
|
||||
var textFilter = filter.FilteredRequest.Text;
|
||||
var textFilterEscaped = Regex.Escape(textFilter);
|
||||
|
||||
filters.Add(
|
||||
filterBuilder.Or(
|
||||
filterBuilder.Regex(p => p.Name,
|
||||
new BsonRegularExpression(textFilterEscaped, "i")), // Case-insensitive regex match for name
|
||||
filterBuilder.Regex(p => p.Title,
|
||||
new BsonRegularExpression(textFilterEscaped, "i")) // Case-insensitive regex match for title
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return CreateFindFluent(filters, sort);
|
||||
}
|
||||
|
||||
private IFindFluent<Unit, Unit> CreateFindFluent(List<FilterDefinition<Unit>> filters, SortDefinition<Unit> sort)
|
||||
{
|
||||
var combinedFilter = filters.Any()
|
||||
? Builders<Unit>.Filter.And(filters)
|
||||
: Builders<Unit>.Filter.Empty;
|
||||
return Collection.Find(combinedFilter).Sort(sort);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Update
|
||||
|
||||
public async Task<Unit?> UpdateUnit(Unit unit)
|
||||
{
|
||||
var filter = Builders<Unit>.Filter.Eq("_id", unit.Id);
|
||||
var update = Builders<Unit>.Update
|
||||
//.Set(c => c.Id, unit.Id)
|
||||
.Set(c => c.Title, unit.Title)
|
||||
.Set(c => c.Name, unit.Name)
|
||||
.Set(c => c.Configuration, unit.Configuration)
|
||||
.Set(c => c.AllergyListId, unit.AllergyListId)
|
||||
.Set(c => c.DestinationListId, unit.DestinationListId)
|
||||
.Set(c => c.InternalDestinationListId, unit.InternalDestinationListId)
|
||||
.Set(c => c.DiagnosisListId, unit.DiagnosisListId)
|
||||
.Set(c => c.DoctorListId, unit.DoctorListId)
|
||||
.Set(c => c.DoctorTypeListId, unit.DoctorTypeListId)
|
||||
.Set(c => c.InsulationListId, unit.InsulationListId)
|
||||
.Set(c => c.MobilityOptionListId, unit.MobilityOptionListId)
|
||||
.Set(c => c.OriginListId, unit.OriginListId)
|
||||
.Set(c => c.PatientStatusListId, unit.PatientStatusListId)
|
||||
.Set(c => c.ProcedureListId, unit.ProcedureListId)
|
||||
.Set(c => c.TestListId, unit.TestListId)
|
||||
.Set(c => c.ServiceListId, unit.ServiceListId)
|
||||
.Set(c => c.TherapeuticCeilingListId, unit.TherapeuticCeilingListId)
|
||||
.Set(c => c.TreatmentListId, unit.TreatmentListId)
|
||||
.Set(c => c.VisitOptionListId, unit.VisitOptionListId)
|
||||
.Set(c => c.AccessControlListId, unit.AccessControlListId)
|
||||
.Set(c => c.DischargeStatusListId, unit.DischargeStatusListId);
|
||||
|
||||
return await Collection.FindOneAndUpdateAsync(filter, update,
|
||||
new FindOneAndUpdateOptions<Unit, Unit> { ReturnDocument = ReturnDocument.After });
|
||||
}
|
||||
|
||||
public async Task<Unit?> UpdateUnitInfo(ObjectId unitId, string name, string title)
|
||||
{
|
||||
var filter = Builders<Unit>.Filter.Eq("_id", unitId);
|
||||
var update = Builders<Unit>.Update
|
||||
//.Set(c => c.Id, unit.Id)
|
||||
.Set(c => c.Title, title)
|
||||
.Set(c => c.Name, name);
|
||||
|
||||
|
||||
return await Collection.FindOneAndUpdateAsync(filter, update,
|
||||
new FindOneAndUpdateOptions<Unit, Unit> { ReturnDocument = ReturnDocument.After });
|
||||
}
|
||||
|
||||
public async Task<Unit?> UpdateUnitMasterList(UpdateUnitIdListDto updateUnitListDto)
|
||||
{
|
||||
var filter = Builders<Unit>.Filter.Eq("_id", updateUnitListDto.UnitId);
|
||||
var update = Builders<Unit>.Update;
|
||||
var updates = new List<UpdateDefinition<Unit>>();
|
||||
|
||||
foreach (var masterListData in updateUnitListDto.MasterListData)
|
||||
if (masterListData.MasterListType.HasValue)
|
||||
switch (masterListData.MasterListType.Value)
|
||||
{
|
||||
case MasterListType.AltableOptionList:
|
||||
updates.Add(update.Set(u => u.AltableOptionListId, masterListData.MasterListId));
|
||||
break;
|
||||
case MasterListType.AllergyList:
|
||||
updates.Add(update.Set(u => u.AllergyListId, masterListData.MasterListId));
|
||||
break;
|
||||
case MasterListType.DestinationList:
|
||||
updates.Add(update.Set(u => u.DestinationListId, masterListData.MasterListId));
|
||||
break;
|
||||
case MasterListType.DiagnosisList:
|
||||
updates.Add(update.Set(u => u.DiagnosisListId, masterListData.MasterListId));
|
||||
break;
|
||||
case MasterListType.DischargeStatusList:
|
||||
updates.Add(update.Set(u => u.DischargeStatusListId, masterListData.MasterListId));
|
||||
break;
|
||||
case MasterListType.DoctorList:
|
||||
updates.Add(update.Set(u => u.DoctorListId, masterListData.MasterListId));
|
||||
break;
|
||||
case MasterListType.DoctorTypeList:
|
||||
updates.Add(update.Set(u => u.DoctorTypeListId, masterListData.MasterListId));
|
||||
break;
|
||||
case MasterListType.InternalDestinationList:
|
||||
updates.Add(update.Set(u => u.InternalDestinationListId, masterListData.MasterListId));
|
||||
break;
|
||||
case MasterListType.InsulationList:
|
||||
updates.Add(update.Set(u => u.InsulationListId, masterListData.MasterListId));
|
||||
break;
|
||||
case MasterListType.LanguageBarrierList:
|
||||
updates.Add(update.Set(u => u.LanguageBarrierListId, masterListData.MasterListId));
|
||||
break;
|
||||
case MasterListType.PassiveSittingList:
|
||||
updates.Add(update.Set(u => u.PassiveSittingListId, masterListData.MasterListId));
|
||||
break;
|
||||
case MasterListType.GenericList:
|
||||
updates.Add(update.Set(u => u.GenericListId, masterListData.MasterListId));
|
||||
break;
|
||||
case MasterListType.MobilityOptionList:
|
||||
updates.Add(update.Set(u => u.MobilityOptionListId, masterListData.MasterListId));
|
||||
break;
|
||||
case MasterListType.OriginList:
|
||||
updates.Add(update.Set(u => u.OriginListId, masterListData.MasterListId));
|
||||
break;
|
||||
case MasterListType.PatientStatusList:
|
||||
updates.Add(update.Set(u => u.PatientStatusListId, masterListData.MasterListId));
|
||||
break;
|
||||
case MasterListType.ProcedureList:
|
||||
updates.Add(update.Set(u => u.ProcedureListId, masterListData.MasterListId));
|
||||
break;
|
||||
case MasterListType.TestList:
|
||||
updates.Add(update.Set(u => u.TestListId, masterListData.MasterListId));
|
||||
break;
|
||||
case MasterListType.ServiceList:
|
||||
updates.Add(update.Set(u => u.ServiceListId, masterListData.MasterListId));
|
||||
break;
|
||||
case MasterListType.TherapeuticCeilingList:
|
||||
updates.Add(update.Set(u => u.TherapeuticCeilingListId, masterListData.MasterListId));
|
||||
break;
|
||||
case MasterListType.TreatmentList:
|
||||
updates.Add(update.Set(u => u.TreatmentListId, masterListData.MasterListId));
|
||||
break;
|
||||
case MasterListType.VisitOptionList:
|
||||
updates.Add(update.Set(u => u.VisitOptionListId, masterListData.MasterListId));
|
||||
break;
|
||||
case MasterListType.AccessControlList:
|
||||
updates.Add(update.Set(u => u.AccessControlListId, masterListData.MasterListId));
|
||||
break;
|
||||
}
|
||||
|
||||
if (updates.Any())
|
||||
{
|
||||
var combinedUpdate = update.Combine(updates);
|
||||
return await Collection.FindOneAndUpdateAsync(filter, combinedUpdate,
|
||||
new FindOneAndUpdateOptions<Unit, Unit> { ReturnDocument = ReturnDocument.After });
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public async Task<bool> UpdateConfiguration(ObjectId unitIdParsed, UnitConfiguration unitConfiguration)
|
||||
{
|
||||
var filter = Builders<Unit>.Filter.Eq("_id", unitIdParsed);
|
||||
var update = Builders<Unit>.Update
|
||||
.Set(c => c.Configuration, unitConfiguration);
|
||||
try
|
||||
{
|
||||
var result = await Collection.UpdateOneAsync(filter, update);
|
||||
return result.ModifiedCount > 0;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Error("Error UpdateConfiguration from unit: {name}. Exception: {ex}", unitIdParsed, ex);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Delete
|
||||
|
||||
public new async Task<Unit?> DeleteAsync(ObjectId id)
|
||||
{
|
||||
var filter = Builders<Unit>.Filter.Eq(unit => unit.Id, id);
|
||||
|
||||
try
|
||||
{
|
||||
return await Collection.FindOneAndDeleteAsync(filter);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.Error(e.Message);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,240 @@
|
||||
using adas_core.Application.Repositories.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;
|
||||
|
||||
public class UserRepository : MongoRepository<User>, IUserRepository
|
||||
{
|
||||
private readonly ApiSettings _apiSettings;
|
||||
|
||||
public UserRepository(IOptions<ApiSettings> apiSettings, IMongoDatabase database) : base(database)
|
||||
{
|
||||
if (apiSettings == null) throw new ArgumentNullException(nameof(apiSettings));
|
||||
_apiSettings = apiSettings.Value;
|
||||
}
|
||||
|
||||
public override string GetCollectionName()
|
||||
{
|
||||
return _apiSettings.Users;
|
||||
}
|
||||
|
||||
public async Task<User?> GetUser(string username, string password)
|
||||
{
|
||||
var filter = Builders<User>
|
||||
.Filter.Eq(p => p.UserName, username) & Builders<User>
|
||||
.Filter.Eq(p => p.Password, password);
|
||||
var result = await Collection.FindAsync(filter);
|
||||
return await result.FirstOrDefaultAsync();
|
||||
}
|
||||
|
||||
public async Task<User?> GetById(ObjectId id)
|
||||
{
|
||||
var filter = Builders<User>
|
||||
.Filter.Eq(p => p.Id, id);
|
||||
var result = await Collection.FindAsync(filter);
|
||||
return await result.FirstOrDefaultAsync();
|
||||
}
|
||||
|
||||
public async Task<User?> GetByUserName(string name)
|
||||
{
|
||||
var filter = Builders<User>
|
||||
.Filter.Eq(p => p.UserName, name);
|
||||
var result = await Collection.FindAsync(filter);
|
||||
return await result.FirstOrDefaultAsync();
|
||||
}
|
||||
|
||||
public async Task<User?> GetByUserAndAuthoritesName(string name)
|
||||
{
|
||||
var matchStage = new BsonDocument("$match", new BsonDocument("userName", name));
|
||||
var lookupStage = new BsonDocument("$lookup", new BsonDocument
|
||||
{
|
||||
{ "from", "authorizations" },
|
||||
{ "localField", "_id" },
|
||||
{ "foreignField", "userId" },
|
||||
{ "as", "Authorization" }
|
||||
});
|
||||
|
||||
var projectStage = new BsonDocument("$project", new BsonDocument
|
||||
{
|
||||
{ "_id", 1 },
|
||||
{ "userName", 1 },
|
||||
{ "email", 1 },
|
||||
{ "name", 1 },
|
||||
{ "Authorization", "$Authorization" },
|
||||
{
|
||||
"rol", new BsonDocument("$cond", new BsonArray
|
||||
{
|
||||
new BsonDocument("$eq", new BsonArray { "$Authorization.rol", "Admin" }),
|
||||
"$rol",
|
||||
"Some"
|
||||
})
|
||||
}
|
||||
});
|
||||
|
||||
var pipeline = new[]
|
||||
{
|
||||
matchStage,
|
||||
lookupStage,
|
||||
projectStage
|
||||
};
|
||||
|
||||
var options = new AggregateOptions { AllowDiskUse = true };
|
||||
var result = await Collection.AggregateAsync<User>(pipeline, options);
|
||||
var bsonResult = await result.FirstOrDefaultAsync();
|
||||
|
||||
return bsonResult;
|
||||
}
|
||||
|
||||
public async Task<User?> GetByName(string name)
|
||||
{
|
||||
var filter = Builders<User>
|
||||
.Filter.Eq(p => p.Name, name);
|
||||
var result = await Collection.FindAsync(filter);
|
||||
return await result.FirstOrDefaultAsync();
|
||||
}
|
||||
|
||||
public async Task<User?> UpdateUser(User user, bool updatePass)
|
||||
{
|
||||
var filter = Builders<User>
|
||||
.Filter.Eq(p => p.Id, user.Id);
|
||||
var update = Builders<User>.Update
|
||||
.Set(u => u.UserName, user.UserName)
|
||||
.Set(u => u.Name, user.Name)
|
||||
.Set(u => u.Email, user.Email)
|
||||
.Set(u => u.LockExpirationDate, user.LockExpirationDate)
|
||||
.Set(u => u.LastLogin, user.LastLogin)
|
||||
.Set(u => u.IsEnabled, user.IsEnabled);
|
||||
|
||||
if (updatePass) update = update.Set(u => u.Password, user.Password);
|
||||
|
||||
await Collection.UpdateOneAsync(filter, update);
|
||||
var result = await Collection.Find(filter).FirstOrDefaultAsync();
|
||||
return result;
|
||||
}
|
||||
|
||||
public IFindFluent<User, User> GetPaginatedUsers(PaginationFilter filteredRequest)
|
||||
{
|
||||
// Crear variable con la clase que construye los filtros que necesitamos
|
||||
var filterBuilder = Builders<User>.Filter;
|
||||
var sort = Builders<User>.Sort.Ascending("userName");
|
||||
// Crear una lista de filtros que pueden venir de tu servicio
|
||||
var filters = new List<FilterDefinition<User>>();
|
||||
if (filteredRequest.FilteredRequest == null) return CreateFindFluent(filters, sort);
|
||||
var textFilter = filteredRequest.FilteredRequest?.Text;
|
||||
if (!string.IsNullOrEmpty(textFilter))
|
||||
{
|
||||
var textFilterEscaped = Regex.Escape(textFilter);
|
||||
var orFilters = new List<FilterDefinition<User>>
|
||||
{
|
||||
filterBuilder.Regex(p => p.Name, new BsonRegularExpression(textFilterEscaped, "i")),
|
||||
filterBuilder.Regex(p => p.Email, new BsonRegularExpression(textFilterEscaped, "i")),
|
||||
filterBuilder.Regex(p => p.UserName, new BsonRegularExpression(textFilterEscaped, "i"))
|
||||
};
|
||||
filters.Add(filterBuilder.Or(orFilters));
|
||||
}
|
||||
|
||||
var userStatus = filteredRequest.FilteredRequest?.UserStatus;
|
||||
filters.Add(filterBuilder.And(GetUserStatusFilter(userStatus)));
|
||||
|
||||
|
||||
if (Enum.TryParse(filteredRequest.FilteredRequest?.UserType, out UserEnum.Type userType))
|
||||
{
|
||||
GetUserTypeFilter(userType);
|
||||
filters.Add(filterBuilder.And(GetUserTypeFilter(userType)));
|
||||
}
|
||||
|
||||
return CreateFindFluent(filters, sort);
|
||||
}
|
||||
|
||||
|
||||
public async Task<User> GetOrCreateSystemUser()
|
||||
{
|
||||
var user = await GetByUserName("System");
|
||||
if (user == null)
|
||||
{
|
||||
var userToInsert = new User
|
||||
{
|
||||
UserName = "System",
|
||||
Name = "System",
|
||||
Password = "$2a$12$crWa3EN1izcZBXNc81RzmOlfaYW2TPr2NdDQEWI7RzLTnA0Dd68WG"
|
||||
};
|
||||
await Collection.InsertOneAsync(userToInsert);
|
||||
return userToInsert;
|
||||
}
|
||||
|
||||
return user;
|
||||
}
|
||||
|
||||
public sealed override async Task InsertInitialLoad()
|
||||
{
|
||||
await GetOrCreateSystemUser();
|
||||
}
|
||||
|
||||
private IFindFluent<User, User> CreateFindFluent(List<FilterDefinition<User>> filters, SortDefinition<User> sort)
|
||||
{
|
||||
var combinedFilter = filters.Any()
|
||||
? Builders<User>.Filter.And(filters)
|
||||
: Builders<User>.Filter.Empty; // Filtra todo si no hay filtros
|
||||
|
||||
return Collection.Find(combinedFilter).Sort(sort);
|
||||
}
|
||||
|
||||
private List<FilterDefinition<User>> GetUserTypeFilter(UserEnum.Type? type)
|
||||
{
|
||||
var filters = new List<FilterDefinition<User>>();
|
||||
var filterBuilder = Builders<User>.Filter;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case UserEnum.Type.Local:
|
||||
filters.Add(filterBuilder.Eq(u => u.Type, UserEnum.Type.Local));
|
||||
break;
|
||||
case UserEnum.Type.Ldap:
|
||||
filters.Add(filterBuilder.Eq(u => u.Type, UserEnum.Type.Ldap));
|
||||
break;
|
||||
}
|
||||
|
||||
return filters;
|
||||
}
|
||||
|
||||
private List<FilterDefinition<User>> GetUserStatusFilter(StatusEnum.User? status)
|
||||
{
|
||||
var filters = new List<FilterDefinition<User>>();
|
||||
var filterBuilder = Builders<User>.Filter;
|
||||
switch (status)
|
||||
{
|
||||
case StatusEnum.User.Enabled:
|
||||
filters.Add(filterBuilder.Or(
|
||||
filterBuilder.Eq(u => u.IsEnabled, true),
|
||||
filterBuilder.Exists(u => u.IsEnabled, false)
|
||||
));
|
||||
break;
|
||||
case StatusEnum.User.EnabledUnlocked:
|
||||
filters.Add(filterBuilder.Or(
|
||||
filterBuilder.Eq(u => u.IsEnabled, true),
|
||||
filterBuilder.Exists(u => u.IsEnabled, false)
|
||||
));
|
||||
filters.Add(filterBuilder.Ne(u => u.LockExpirationDate, null));
|
||||
break;
|
||||
case StatusEnum.User.EnabledLocked:
|
||||
filters.Add(filterBuilder.Or(
|
||||
filterBuilder.Eq(u => u.IsEnabled, true),
|
||||
filterBuilder.Exists(u => u.IsEnabled, false)
|
||||
));
|
||||
filters.Add(filterBuilder.Eq(u => u.LockExpirationDate, null));
|
||||
break;
|
||||
case StatusEnum.User.Disabled:
|
||||
filters.Add(filterBuilder.Eq(u => u.IsEnabled, false));
|
||||
break;
|
||||
}
|
||||
|
||||
return filters;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user