Creado apartir del commit b888de6c92056de294456f581a56e25e734d4ab7 de develop

This commit is contained in:
jrojas
2026-06-26 09:52:35 +02:00
commit 319fd3dfb0
746 changed files with 106610 additions and 0 deletions
@@ -0,0 +1,496 @@
using MongoDB.Bson;
using MongoDB.Driver;
using MongoMigrations.Core;
namespace adas_core.Infrastructure.Migrations.MongoMigrations;
// ReSharper disable once InconsistentNaming
public class U_0_1_0_UpdateDataPatien : Migration
{
public U_0_1_0_UpdateDataPatien() : base(10)
{
Description =
"Transforma person.historicalIds y historicalLocations en arrays con fechas y realiza merge sobre patients.";
}
public override void Update()
{
var collectionPatient = Database.GetCollection<BsonDocument>("patients");
var pipelinePatient = new[]
{
new BsonDocument("$addFields", new BsonDocument
{
{
"person.historicalIds", new BsonDocument("$cond", new BsonDocument
{
// si ya es array → no tocar
{ "if", new BsonDocument("$isArray", "$person.historicalIds") },
{ "then", "$person.historicalIds" },
// si es document → migrar
{
"else", new BsonDocument("$map", new BsonDocument
{
{ "input", new BsonDocument("$objectToArray", "$person.historicalIds") },
{ "as", "id" },
{
"in", new BsonDocument
{
{
"time",
new BsonDocument("$dateFromString",
new BsonDocument("dateString", "$$id.k"))
},
{ "patientIds", "$$id.v" }
}
}
})
}
})
},
{
"historicalLocations", new BsonDocument("$cond", new BsonDocument
{
{ "if", new BsonDocument("$isArray", "$historicalLocations") },
{ "then", "$historicalLocations" },
{
"else", new BsonDocument("$map", new BsonDocument
{
{ "input", new BsonDocument("$objectToArray", "$historicalLocations") },
{ "as", "location" },
{
"in", new BsonDocument
{
{
"admTime",
new BsonDocument("$dateFromString",
new BsonDocument("dateString", "$$location.k"))
},
{ "patientLocation", "$$location.v" }
}
}
})
}
})
}
}),
new BsonDocument("$merge", new BsonDocument
{
{ "into", "patients" },
{ "whenMatched", "replace" }, // aquí SÍ es seguro (no hay _t)
{ "whenNotMatched", "discard" }
})
};
collectionPatient.Aggregate<BsonDocument>(pipelinePatient).ToList();
var collectionAdmission = Database.GetCollection<BsonDocument>("admissions");
var pipelineAdmission = new[]
{
new BsonDocument("$addFields", new BsonDocument
{
{
"person.historicalIds", new BsonDocument("$cond", new BsonDocument
{
// si ya es array → no tocar
{ "if", new BsonDocument("$isArray", "$person.historicalIds") },
{ "then", "$person.historicalIds" },
// si es document → migrar
{
"else", new BsonDocument("$map", new BsonDocument
{
{ "input", new BsonDocument("$objectToArray", "$person.historicalIds") },
{ "as", "id" },
{
"in", new BsonDocument
{
{
"time",
new BsonDocument("$dateFromString",
new BsonDocument("dateString", "$$id.k"))
},
{ "patientIds", "$$id.v" }
}
}
})
}
})
},
{
"historicalLocations", new BsonDocument("$cond", new BsonDocument
{
{ "if", new BsonDocument("$isArray", "$historicalLocations") },
{ "then", "$historicalLocations" },
{
"else", new BsonDocument("$map", new BsonDocument
{
{ "input", new BsonDocument("$objectToArray", "$historicalLocations") },
{ "as", "location" },
{
"in", new BsonDocument
{
{
"admTime",
new BsonDocument("$dateFromString",
new BsonDocument("dateString", "$$location.k"))
},
{ "patientLocation", "$$location.v" }
}
}
})
}
})
}
}),
new BsonDocument("$merge", new BsonDocument
{
{ "into", "admissions" },
{ "whenMatched", "replace" }, // aquí SÍ es seguro (no hay _t)
{ "whenNotMatched", "discard" }
})
};
collectionAdmission.Aggregate<BsonDocument>(pipelineAdmission).ToList();
var collectionArchivePatient = Database.GetCollection<BsonDocument>("archive_patient");
var pipelineArchivePatient = new[]
{
new BsonDocument("$addFields", new BsonDocument
{
{
"person.historicalIds", new BsonDocument("$cond", new BsonDocument
{
// si ya es array → no tocar
{ "if", new BsonDocument("$isArray", "$person.historicalIds") },
{ "then", "$person.historicalIds" },
// si es document → migrar
{
"else", new BsonDocument("$map", new BsonDocument
{
{ "input", new BsonDocument("$objectToArray", "$person.historicalIds") },
{ "as", "id" },
{
"in", new BsonDocument
{
{
"time",
new BsonDocument("$dateFromString",
new BsonDocument("dateString", "$$id.k"))
},
{ "patientIds", "$$id.v" }
}
}
})
}
})
},
{
"historicalLocations", new BsonDocument("$cond", new BsonDocument
{
{ "if", new BsonDocument("$isArray", "$historicalLocations") },
{ "then", "$historicalLocations" },
{
"else", new BsonDocument("$map", new BsonDocument
{
{ "input", new BsonDocument("$objectToArray", "$historicalLocations") },
{ "as", "location" },
{
"in", new BsonDocument
{
{
"admTime",
new BsonDocument("$dateFromString",
new BsonDocument("dateString", "$$location.k"))
},
{ "patientLocation", "$$location.v" }
}
}
})
}
})
}
}),
new BsonDocument("$merge", new BsonDocument
{
{ "into", "archive_patient" },
{ "whenMatched", "replace" }, // aquí SÍ es seguro (no hay _t)
{ "whenNotMatched", "discard" }
})
};
collectionArchivePatient.Aggregate<BsonDocument>(pipelineArchivePatient).ToList();
}
// NO usado por MongoMigrations.Core
// Solo para ejecución manual si hiciera falta
public void Down()
{
var collectionPatient = Database.GetCollection<BsonDocument>("patients");
var pipelinePatient = new[]
{
new BsonDocument("$addFields", new BsonDocument
{
{
"person.historicalIds", new BsonDocument("$cond", new BsonDocument
{
// si ya es document → no tocar
{ "if", new BsonDocument("$not", new BsonArray { new BsonDocument("$isArray", "$person.historicalIds") }) },
{ "then", "$person.historicalIds" },
// si es array → revertir
{
"else", new BsonDocument("$arrayToObject", new BsonArray
{
new BsonDocument
{
{
"$map", new BsonDocument
{
{ "input", "$person.historicalIds" },
{ "as", "id" },
{
"in", new BsonDocument
{
{
"k", new BsonDocument("$dateToString", new BsonDocument
{
{ "format", "%Y-%m-%dT%H:%M:%S.%LZ" },
{ "date", "$$id.time" }
})
},
{ "v", "$$id.patientIds" }
}
}
}
}
}
})
}
})
},
{
"historicalLocations", new BsonDocument("$cond", new BsonDocument
{
{ "if", new BsonDocument("$not", new BsonArray { new BsonDocument("$isArray", "$historicalLocations") }) },
{ "then", "$historicalLocations" },
{
"else", new BsonDocument("$arrayToObject", new BsonArray
{
new BsonDocument
{
{
"$map", new BsonDocument
{
{ "input", "$historicalLocations" },
{ "as", "location" },
{
"in", new BsonDocument
{
{
"k", new BsonDocument("$dateToString", new BsonDocument
{
{ "format", "%Y-%m-%dT%H:%M:%S.%LZ" },
{ "date", "$$location.admTime" }
})
},
{ "v", "$$location.patientLocation" }
}
}
}
}
}
})
}
})
}
}),
new BsonDocument("$merge", new BsonDocument
{
{ "into", "patients" },
{ "whenMatched", "replace" },
{ "whenNotMatched", "discard" }
})
};
collectionPatient.Aggregate<BsonDocument>(pipelinePatient).ToList();
var collectionAdm = Database.GetCollection<BsonDocument>("admissions");
var pipelineAdm = new[]
{
new BsonDocument("$addFields", new BsonDocument
{
{
"person.historicalIds", new BsonDocument("$cond", new BsonDocument
{
// si ya es document → no tocar
{ "if", new BsonDocument("$not", new BsonArray { new BsonDocument("$isArray", "$person.historicalIds") }) },
{ "then", "$person.historicalIds" },
// si es array → revertir
{
"else", new BsonDocument("$arrayToObject", new BsonArray
{
new BsonDocument
{
{
"$map", new BsonDocument
{
{ "input", "$person.historicalIds" },
{ "as", "id" },
{
"in", new BsonDocument
{
{
"k", new BsonDocument("$dateToString", new BsonDocument
{
{ "format", "%Y-%m-%dT%H:%M:%S.%LZ" },
{ "date", "$$id.time" }
})
},
{ "v", "$$id.patientIds" }
}
}
}
}
}
})
}
})
},
{
"historicalLocations", new BsonDocument("$cond", new BsonDocument
{
{ "if", new BsonDocument("$not", new BsonArray { new BsonDocument("$isArray", "$historicalLocations") }) },
{ "then", "$historicalLocations" },
{
"else", new BsonDocument("$arrayToObject", new BsonArray
{
new BsonDocument
{
{
"$map", new BsonDocument
{
{ "input", "$historicalLocations" },
{ "as", "location" },
{
"in", new BsonDocument
{
{
"k", new BsonDocument("$dateToString", new BsonDocument
{
{ "format", "%Y-%m-%dT%H:%M:%S.%LZ" },
{ "date", "$$location.admTime" }
})
},
{ "v", "$$location.patientLocation" }
}
}
}
}
}
})
}
})
}
}),
new BsonDocument("$merge", new BsonDocument
{
{ "into", "admissions" },
{ "whenMatched", "replace" },
{ "whenNotMatched", "discard" }
})
};
collectionAdm.Aggregate<BsonDocument>(pipelineAdm).ToList();
var collectionArcP = Database.GetCollection<BsonDocument>("archive_patient");
var pipelineArcP = new[]
{
new BsonDocument("$addFields", new BsonDocument
{
{
"person.historicalIds", new BsonDocument("$cond", new BsonDocument
{
// si ya es document → no tocar
{ "if", new BsonDocument("$not", new BsonArray { new BsonDocument("$isArray", "$person.historicalIds") }) },
{ "then", "$person.historicalIds" },
// si es array → revertir
{
"else", new BsonDocument("$arrayToObject", new BsonArray
{
new BsonDocument
{
{
"$map", new BsonDocument
{
{ "input", "$person.historicalIds" },
{ "as", "id" },
{
"in", new BsonDocument
{
{
"k", new BsonDocument("$dateToString", new BsonDocument
{
{ "format", "%Y-%m-%dT%H:%M:%S.%LZ" },
{ "date", "$$id.time" }
})
},
{ "v", "$$id.patientIds" }
}
}
}
}
}
})
}
})
},
{
"historicalLocations", new BsonDocument("$cond", new BsonDocument
{
{ "if", new BsonDocument("$not", new BsonArray { new BsonDocument("$isArray", "$historicalLocations") }) },
{ "then", "$historicalLocations" },
{
"else", new BsonDocument("$arrayToObject", new BsonArray
{
new BsonDocument
{
{
"$map", new BsonDocument
{
{ "input", "$historicalLocations" },
{ "as", "location" },
{
"in", new BsonDocument
{
{
"k", new BsonDocument("$dateToString", new BsonDocument
{
{ "format", "%Y-%m-%dT%H:%M:%S.%LZ" },
{ "date", "$$location.admTime" }
})
},
{ "v", "$$location.patientLocation" }
}
}
}
}
}
})
}
})
}
}),
new BsonDocument("$merge", new BsonDocument
{
{ "into", "archive_patient" },
{ "whenMatched", "replace" },
{ "whenNotMatched", "discard" }
})
};
collectionArcP.Aggregate<BsonDocument>(pipelineArcP).ToList();
}
}
@@ -0,0 +1,66 @@
using MongoDB.Bson;
using MongoDB.Driver;
using MongoMigrations.Core;
namespace adas_core.Infrastructure.Migrations.MongoMigrations;
public class U_0_1_1_UpdateDisplayConfigDriver : Migration
{
public U_0_1_1_UpdateDisplayConfigDriver() : base(11)
{
Description =
"Genera el campo Type en todos los documentos de la coleccion DisplayConfig por que el nuevo driver no expone _t para polimorfia";
}
public override void Update()
{
var collection = Database.GetCollection<BsonDocument>("config_displays");
var pipeline = new[]
{
new BsonDocument("$set", new BsonDocument
{
{
"type", new BsonDocument("$switch", new BsonDocument
{
{
"branches", new BsonArray
{
new BsonDocument
{
{ "case", new BsonDocument("$eq", new BsonArray { "$_t", "DisplayNurse" }) },
{ "then", "DisplayNurse" }
},
new BsonDocument
{
{ "case", new BsonDocument("$eq", new BsonArray { "$_t", "StandarDisplay" }) },
{ "then", "StandarDisplay" }
},
new BsonDocument
{
{ "case", new BsonDocument("$eq", new BsonArray { "$_t", "SmartDisplay" }) },
{ "then", "SmartDisplay" }
}
}
},
{ "default", "Unknown" }
})
}
}),
new BsonDocument("$unset", "_t"),
new BsonDocument("$merge", new BsonDocument
{
{ "into", "config_displays" },
{ "whenMatched", "merge" },
{ "whenNotMatched", "discard" }
})
};
collection.AggregateToCollection<BsonDocument>(pipeline);
// collection.AggregateToCollection<BsonDocument>(pipeline, "config_displays");
}
}
@@ -0,0 +1,59 @@
using MongoDB.Bson;
using MongoDB.Driver;
using MongoMigrations.Core;
namespace adas_core.Infrastructure.Migrations.MongoMigrations;
public class U_0_1_2_UpdatePointOfCareConfig : Migration
{
public U_0_1_2_UpdatePointOfCareConfig() : base(12)
{
Description =
"Borra los elementos de configuracion de poc, relay, camera y beacon y deja el place holder del nuevo modelo";
}
public override void Update()
{
var collection = Database.GetCollection<BsonDocument>("pointOfCares");
var filter = Builders<BsonDocument>.Filter.Exists("configuration");
var documents = collection.Find(filter).ToList();
foreach (var doc in documents)
{
var configuration = doc["configuration"].AsBsonDocument;
// Listas nuevas de IDs
var beaconIdList = new BsonArray();
var cameraIdList = new BsonArray();
var relayIdList = new BsonArray();
// 1. Procesar Beacons (si existen)
if (configuration.Contains("beacons") && configuration["beacons"].IsBsonArray)
{
configuration.Remove("beacons");
}
configuration["beaconIdList"] = beaconIdList;
// 2. Procesar Cameras (si existen)
if (configuration.Contains("cameras") && configuration["cameras"].IsBsonArray)
{
configuration.Remove("cameras");
}
configuration["cameraIdList"] = cameraIdList;
// 3. Procesar RelayList (si existen)
if (configuration.Contains("relayList") && configuration["relayList"].IsBsonArray)
{
configuration.Remove("relayList");
}
configuration["relayIdList"] = relayIdList;
// Actualizar el documento en la base de datos
collection.ReplaceOne(Builders<BsonDocument>.Filter.Eq("_id", doc["_id"]), doc);
}
}
}
@@ -0,0 +1,50 @@
using MongoDB.Bson;
using MongoDB.Driver;
using MongoMigrations.Core;
namespace adas_core.Infrastructure.Migrations.MongoMigrations;
public class U_0_1_3_UpdateLanguageBarrier : Migration
{
public U_0_1_3_UpdateLanguageBarrier() : base(13)
{
Description =
"Borra los elementos de configuracion de poc, relay, camera y beacon y deja el place holder del nuevo modelo";
}
public override void Update()
{
string[] collectionsToUpdate = { "patients", "admissions" };
foreach (var collectionName in collectionsToUpdate)
{
var collection = Database.GetCollection<BsonDocument>(collectionName);
// Filtramos documentos donde languageBarrier existe y NO es ya un array
var filter = Builders<BsonDocument>.Filter.And(
Builders<BsonDocument>.Filter.Exists("languageBarrier"),
Builders<BsonDocument>.Filter.Not(Builders<BsonDocument>.Filter.Type("languageBarrier", BsonType.Array))
);
var documents = collection.Find(filter).ToList();
foreach (var doc in documents)
{
var currentValue = doc["languageBarrier"];
BsonArray newArray = new BsonArray();
// Si el valor actual no es nulo, lo añadimos como primer elemento del array
if (!currentValue.IsBsonNull)
{
newArray.Add(currentValue);
}
// Actualizamos el campo en el documento Bson
doc["languageBarrier"] = newArray;
// Guardamos los cambios en la base de datos
collection.ReplaceOne(Builders<BsonDocument>.Filter.Eq("_id", doc["_id"]), doc);
}
}
}
}
@@ -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;
}
}
@@ -0,0 +1,126 @@
using adas_core.Application.Services.Interfaces;
using adas_core.Domain.Models.AppSettings;
using EasyNetQ;
using EasyNetQ.SystemMessages;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
namespace adas_core.Infrastructure.Services;
public class PublisherService : IPublisherService
{
private readonly ILogger<PublisherService> _logger;
private readonly HashSet<string> _queues = new();
private readonly IBus? _bus;
public PublisherService(
IOptions<RabbitMqSettings> rabbitMqSettings,
ILogger<PublisherService> logger)
{
_logger = logger;
try
{
var connection = rabbitMqSettings.Value.ConnectionString;
if (string.IsNullOrWhiteSpace(connection))
{
_logger.LogError("Missing RabbitMQ connection string");
return;
}
var services = new ServiceCollection();
services.AddEasyNetQ(connection);
var provider = services.BuildServiceProvider();
_bus = provider.GetRequiredService<IBus>();
_logger.LogInformation("PublisherService initialized");
}
catch (Exception ex)
{
_logger.LogError(ex, "Error initializing PublisherService");
}
}
public Task<bool> CreateQueue(string queueName)
{
if (string.IsNullOrWhiteSpace(queueName))
return Task.FromResult(false);
if (_queues.Contains(queueName))
{
_logger.LogDebug("Queue {queueName} already registered", queueName);
return Task.FromResult(true);
}
_queues.Add(queueName);
_logger.LogInformation("Queue registered: {queueName}", queueName);
// EasyNetQ crea colas automáticamente
return Task.FromResult(true);
}
public async Task<bool> SendMessage(string msg, string queueName)
{
try
{
if (_bus == null)
{
_logger.LogError("Bus is null");
return false;
}
await CreateQueue(queueName);
_logger.LogDebug("Sending message to {queueName}", queueName);
await _bus.SendReceive.SendAsync(queueName, msg);
return true;
}
catch (Exception ex)
{
_logger.LogError(ex, "Error sending message to {queueName}", queueName);
return false;
}
}
public async Task<bool> SendMessage(object obj, string queueName)
{
var json = JsonConvert.SerializeObject(obj);
return await SendMessage(json, queueName);
}
public async Task<bool> SendMessageError(object obj, string queueName)
{
try
{
if (_bus == null)
{
_logger.LogError("Bus is null - cannot send error message");
return false;
}
if (obj is not Message<Error> errorMessage)
return false;
await CreateQueue(queueName);
_logger.LogDebug("Sending error message to {queueName}", queueName);
// enviamos solo el Error (no Message<Error>)
await _bus.SendReceive.SendAsync(queueName, errorMessage.Body);
return true;
}
catch (Exception ex)
{
_logger.LogError(ex, "Error sending error message");
return false;
}
}
}
@@ -0,0 +1,239 @@
using adas_core.Application.Services.Interfaces;
using adas_core.Domain.Models;
using adas_core.Domain.Models.AppSettings;
using EasyNetQ;
using EasyNetQ.SystemMessages;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
namespace adas_core.Infrastructure.Services;
public class ReceiverService
{
private readonly ILogger<ReceiverService> _logger;
private readonly RabbitMqSettings _settings;
private readonly IObservationService _observationService;
private readonly ITreatmentService _treatmentService;
private readonly IPatientService _patientsService;
private readonly IPumpService _pumpService;
private readonly IRecordingAlertService _recordingAlertService;
private readonly IRecordingService _recordingService;
private readonly IAppointmentService _appointmentService;
private readonly IAlarmService _alarmService;
private readonly List<string> _queues = [];
private IBus? _bus;
public ReceiverService(
IObservationService observationService,
ITreatmentService treatmentService,
IPatientService patientsService,
IPumpService pumpService,
IRecordingAlertService recordingAlertService,
IRecordingService recordingService,
IAppointmentService appointmentService,
IAlarmService alarmService,
IOptions<RabbitMqSettings> settings,
ILogger<ReceiverService> logger)
{
_logger = logger;
_settings = settings.Value;
_observationService = observationService;
_treatmentService = treatmentService;
_patientsService = patientsService;
_pumpService = pumpService;
_recordingAlertService = recordingAlertService;
_recordingService = recordingService;
_appointmentService = appointmentService;
_alarmService = alarmService;
if (!string.IsNullOrWhiteSpace(_settings.ConnectionString))
{
SetQueues();
TryToConnect();
}
else
{
_logger.LogError("RabbitMQ connection string NOT configured");
}
}
private void SetQueues()
{
AddQueue(_settings.ObservationsQueue);
AddQueue(_settings.TreatmentsQueue);
AddQueue(_settings.PatientsQueue);
AddQueue(_settings.PumpsQueue);
AddQueue(_settings.AppointmentsQueue);
AddQueue(_settings.RecordingQueue);
AddQueue(_settings.RecordingAlertQueue);
AddQueue(_settings.AlarmObservationQueue);
}
private void AddQueue(string? queue)
{
if (!string.IsNullOrWhiteSpace(queue))
_queues.Add(queue!);
}
private void TryToConnect()
{
try
{
DisposeBus();
var services = new ServiceCollection();
services.AddEasyNetQ(_settings.ConnectionString);
var provider = services.BuildServiceProvider();
_bus = provider.GetRequiredService<IBus>();
foreach (var queue in _queues)
{
RegisterConsumer(queue);
}
_logger.LogInformation("RabbitMQ connected. Registered {Count} queues", _queues.Count);
}
catch (Exception ex)
{
_logger.LogError(ex, "RabbitMQ connection failed. Retrying in 5 seconds...");
var timer = new System.Timers.Timer(5000);
timer.Elapsed += (_, _) =>
{
timer.Stop();
TryToConnect();
};
timer.Start();
}
}
private void DisposeBus()
{
if (_bus is IDisposable disposable)
{
disposable.Dispose();
}
}
private void RegisterConsumer(string queue)
{
_bus!.SendReceive.ReceiveAsync<string>(queue, async payload =>
{
try
{
_logger.LogDebug("Message received from {queue}", queue);
var service = ResolveService(queue);
if (service == null)
{
_logger.LogWarning("No service mapped for queue {queue}", queue);
return;
}
var message = new Message<string>(
payload,
new MessageProperties()
);
await Task.Run(() => TryToParseAndSend(message, service));
}
catch (Exception ex)
{
_logger.LogError(ex, "Error processing message from {queue}", queue);
throw; // 🔴 importante: activa retry
}
});
}
private IApiRequestService? ResolveService(string queue)
{
return queue switch
{
var q when q == _settings.ObservationsQueue => _observationService,
var q when q == _settings.TreatmentsQueue => _treatmentService,
var q when q == _settings.PatientsQueue => _patientsService,
var q when q == _settings.PumpsQueue => _pumpService,
var q when q == _settings.RecordingQueue => _recordingService,
var q when q == _settings.RecordingAlertQueue => _recordingAlertService,
var q when q == _settings.AlarmObservationQueue => _alarmService,
var q when q == _settings.AppointmentsQueue => _appointmentService,
_ => null
};
}
public async Task ProcessErrorQueue(string errorQueueName)
{
if (_bus == null)
{
_logger.LogError("Cannot process error queue - bus is null");
return;
}
await _bus.SendReceive.ReceiveAsync<Error>(errorQueueName, async err =>
{
try
{
var queue = err.RoutingKey?.Replace("Key", "");
if (string.IsNullOrEmpty(queue))
return;
var service = ResolveService(queue);
if (service == null)
return;
var message = new Message<string>(
err.Message,
new MessageProperties()
);
await Task.Run(() => TryToParseAndSend(message, service));
}
catch (Exception ex)
{
_logger.LogError(ex, "Error reprocessing message from {queue}", errorQueueName);
throw;
}
});
}
/// <summary>
/// Sends EasyNetQ messages to a service implementing IApiRequestService
/// Throws exception to trigger retry on failure
/// </summary>
private void TryToParseAndSend(IMessage<string> msg, IApiRequestService service)
{
try
{
_logger.LogDebug("Processing message: {msg}", msg.Body);
var apiRequest = JsonConvert.DeserializeObject<ApiRequest>(msg.Body);
if (apiRequest == null)
{
_logger.LogError("Invalid ApiRequest JSON: {msg}", msg.Body);
return;
}
if (apiRequest.PatientNumber == "\"\"")
apiRequest.PatientNumber = string.Empty;
service.SaveRequest(apiRequest);
}
catch (Exception ex)
{
_logger.LogError(ex, "Error processing request");
throw;
}
}
}
@@ -0,0 +1,459 @@
using System.Collections.Concurrent;
using System.Net;
using System.Text;
using System.Web;
using adas_core.Application.Repositories.Interfaces;
using adas_core.Application.Services.Interfaces;
using adas_core.Domain.Enums;
using adas_core.Domain.Exceptions;
using adas_core.Domain.Models.Filter;
using adas_core.Domain.Models.MongoModels;
using adas_core.Domain.Models.Responses;
using adas_core.Infrastructure.Utils;
using adas_core.module.Relays.Devices;
using adas_core.module.Relays.Models;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using MongoDB.Bson;
using MongoDB.Driver;
using Quartz.Util;
namespace adas_core.Infrastructure.Services;
public class RelayService : IRelayService
{
private readonly List<RelayDevice> _devices = [];
private readonly IHttpClientFactory _httpClientFactory;
private readonly ILogger<RelayService> _logger;
private readonly IPointOfCareService _pointOfCareService;
private readonly RelaySettings _relaySettings;
private readonly IRelayRepository _relayRepository;
private readonly ConcurrentDictionary<Tuple<string, int, int>, RelayEnum.Status> _relayWithStatus = new();
private readonly string _url;
private UriBuilder? _builder;
public RelayService(
ILogger<RelayService> logger,
IHttpClientFactory httpClientFactory,
IOptions<RelaySettings> relaySettings,
IPointOfCareService pointOfCareService,
IRelayRepository relayRepository)
{
_httpClientFactory = httpClientFactory;
_pointOfCareService = pointOfCareService;
_relayRepository = relayRepository;
_logger = logger;
_relaySettings = relaySettings.Value;
_url = _relaySettings.RecordingOrApiUrl ?? string.Empty;
Task.Run(async () => await InitRelayWithStatus());
}
public async Task<RelayEnum.Status> CheckRelayStatus(Relay relay)
{
var cacheKey = Tuple.Create(relay.Ip, relay.Port, relay.RelayNumber);
try
{
if (_relaySettings.Cache && relay.Cache)
lock (_relayWithStatus)
{
if (_relayWithStatus.TryGetValue(cacheKey, out var status) &&
status != RelayEnum.Status.NotInitialized)
return status;
_logger.LogDebug("Relay status not found in cache: {Dct}",
DictionaryToString(_relayWithStatus));
}
RelayDevice? relayDevice = null;
try
{
relayDevice = GetRelayDevice(relay);
}
catch (Exception e)
{
_logger.LogWarning("Error getting relay device: {EMessage} {EStackTrace}", e.Message, e.StackTrace);
}
if (relayDevice == null && !string.IsNullOrEmpty(_url)) return await GetRelayStatusByOr(relay);
if (relayDevice != null) return relayDevice.GetStatusRelay(relay.RelayNumber);
}
catch (Exception e)
{
_logger.LogError("Error CheckRelayStatus relay {Relay}: {EMessage} {EStackTrace}", relay, e.Message,
e.StackTrace);
lock (_relayWithStatus)
{
_relayWithStatus[cacheKey] = RelayEnum.Status.Unknown;
}
}
return RelayEnum.Status.Unknown;
}
public async Task<RelayEnum.Status> CheckRelayStatus(ObjectId relayId)
{
var relay = await _relayRepository.GetById(relayId);
if(relay == null) return RelayEnum.Status.Unknown;
return await CheckRelayStatus(relay);
}
public async Task PowerOff(Relay relay)
{
var cacheKey = Tuple.Create(relay.Ip, relay.Port, relay.RelayNumber);
if (_relaySettings.Cache && relay.Cache)
lock (_relayWithStatus)
{
if (_relayWithStatus.Any() &&
_relayWithStatus[cacheKey] == RelayEnum.Status.Off)
return;
}
RelayDevice? relayDevice = null;
try
{
relayDevice = GetRelayDevice(relay);
}
catch (Exception e)
{
_logger.LogWarning("Error getting relay device: {EMessage} {EStackTrace}", e.Message, e.StackTrace);
}
if (relayDevice == null && !string.IsNullOrEmpty(_url))
{
_builder = new UriBuilder(_url)
{
Path = $"Relay/{relay.RelayNumber}/powerOff"
};
_logger.LogDebug("Send PowerOff relay {Relay}", relay);
await PowerRelay(relay, _builder);
}
relayDevice?.PowerOffRelay(relay.RelayNumber);
if (_relaySettings.Cache && relay.Cache)
lock (_relayWithStatus)
{
_relayWithStatus[cacheKey] = RelayEnum.Status.Off;
_logger.LogDebug("Relay status cached: {Dct}", DictionaryToString(_relayWithStatus));
}
}
public async Task PowerOn(Relay relay)
{
if (string.IsNullOrEmpty(relay.Driver) || string.IsNullOrEmpty(relay.Ip)) return;
var cacheKey = Tuple.Create(relay.Ip, relay.Port, relay.RelayNumber);
if (_relaySettings.Cache && relay.Cache)
if (_relaySettings.Cache && relay.Cache)
lock (_relayWithStatus)
{
if (_relayWithStatus.Any() &&
_relayWithStatus[cacheKey] == RelayEnum.Status.On)
return;
}
RelayDevice? relayDevice = null;
try
{
relayDevice = GetRelayDevice(relay);
}
catch (Exception e)
{
_logger.LogWarning("Error getting relay device: {EMessage} {EStackTrace}", e.Message, e.StackTrace);
}
if (relayDevice == null && !string.IsNullOrEmpty(_url))
{
_builder = new UriBuilder(_url)
{
Path = $"Relay/{relay.RelayNumber}/powerOn"
};
_logger.LogDebug("Send PowerOn relay {Relay}", relay);
await PowerRelay(relay, _builder);
}
relayDevice?.PowerOnRelay(relay.RelayNumber);
if (_relaySettings.Cache && relay.Cache)
lock (_relayWithStatus)
{
_relayWithStatus[cacheKey] = RelayEnum.Status.On;
_logger.LogDebug("Relay status cached: {Dct}", DictionaryToString(_relayWithStatus));
}
}
public async Task SetManualRelay(RelayEnum.Status status, ObjectId pocId, RelayEnum.Type type)
{
try
{
var poc = await _pointOfCareService.FindById(pocId);
if (poc is { Configuration.RelayIdList: not null })
{
var relay = _relayRepository.GetRelayByTypeInList(poc.Configuration.RelayIdList, type).FirstOrDefault();
if (relay != null) relay.ManualRelayStatus = status;
await _pointOfCareService.UpdateRelayConfig(poc);
_logger.LogDebug("SetManualRelay: {Status}, pocId: {Location}, bed: {Bed}", status, poc.Id, poc.Bed);
}
}
catch (Exception ex)
{
_logger.LogError("Error settings manual relay. Exception: {ex}", ex);
throw;
}
}
public Task<Relay?> GetById(ObjectId relay)
{
return _relayRepository.GetById(relay);
}
public List<Relay> GetRelayInList(List<ObjectId>? relayList)
{
if(relayList == null) return new List<Relay>();
return _relayRepository.GetRelayInList(relayList);
}
public List<Relay> GetRelayByTypeInList(List<ObjectId>? configurationRelayList, RelayEnum.Type type)
{
if(configurationRelayList == null) return new List<Relay>();
return _relayRepository.GetRelayByTypeInList(configurationRelayList, type);
}
public async Task<PaginationResponse<Relay>> GetPaginatedRelays(PaginationFilter filter)
{
var usedRelayIds = await _pointOfCareService.FindAllIdRelaysInUse();
var fluentQuery = _relayRepository.GetPaginatedRelays(filter);
if (filter.FilteredRequest?.InUse != null)
{
bool filterInUse = filter.FilteredRequest.InUse.Value;
var filterBuilder = Builders<Relay>.Filter;
var idFilter = filterInUse
? filterBuilder.In(c => c.Id, usedRelayIds)
: filterBuilder.Not(filterBuilder.In(c => c.Id, usedRelayIds));
fluentQuery.Filter = filterBuilder.And(fluentQuery.Filter, idFilter);
}
var count = await fluentQuery.CountDocumentsAsync();
var data = await fluentQuery
.Skip((filter.PageNumber - 1) * filter.PageSize)
.Limit(filter.PageSize)
.ToListAsync();
if (data == null) return new PaginationResponse<Relay>([], filter.PageNumber, filter.PageSize, count);
foreach (var camera in data)
{
if (camera == null) continue;
bool isInUse = usedRelayIds.Contains(camera.Id);
// Asignación mediante reflexión para el private set
camera.GetType().GetProperty(nameof(Relay.InUse))
?.SetValue(camera, isInUse);
}
return new PaginationResponse<Relay>(data, filter.PageNumber, filter.PageSize, count);
}
public async Task<Relay?> InsertRelay(Relay request)
{
var relayExist = await _relayRepository.GetByName(request.RelayName);
if(relayExist != null) throw new Exception($"Relay with name {request.RelayName} already exists");
return await _relayRepository.InsertOneRelayAsync(request);
}
public Task<Relay?> UpdateRelayById(ObjectId objectId, Relay relay)
{
return _relayRepository.UpdateRelayAsync(objectId, relay);
}
public event EventHandler<Tuple<RelayDevice, int>>? RelayStatusChanged;
private async Task InitRelayWithStatus()
{
try
{
var pocConfigList = await _pointOfCareService.GetAllConfigs();
var relayTasks = new List<Task>();
pocConfigList.ForEach(poc =>
{
if (poc.Configuration?.RelayList == null) return;
relayTasks.AddRange(from relayConf in poc.Configuration.RelayList
let statusTask = CheckRelayStatus(relayConf)
select statusTask.ContinueWith(task =>
{
if (task.IsCompletedSuccessfully)
{
var cackeKey = Tuple.Create(relayConf.Ip, relayConf.Port, relayConf.RelayNumber);
if (!relayConf.Cache || !relayConf.Cache) return;
lock (_relayWithStatus)
{
_relayWithStatus[cackeKey] = task.Result;
}
}
else if (task.IsFaulted)
{
// Manejar la excepción si la llamada asincrónica falla
_logger.LogError("Error al obtener el estado del relé {RelayParsedIp}: {TaskException}",
relayConf.Ip, task.Exception.Message);
}
}));
});
await Task.WhenAll(relayTasks);
lock (_relayWithStatus)
{
_logger.LogDebug("Relay status cached: {Dct}", DictionaryToString(_relayWithStatus));
}
}
catch (Exception ex)
{
Console.WriteLine("Exception setting relay with status: " + ex.Message);
}
}
private RelayDevice? GetRelayDevice(Relay relay)
{
if(relay.Ip.IsNullOrWhiteSpace() || relay.Port == 0) return null;
var device = _devices.FirstOrDefault(d => d.Relay.Ip == relay.Ip && d.Relay.Port == relay.Port);
if (device != null) return device;
var type = TypesUtils.GetDriver("Relay", relay.Driver ?? string.Empty);
var constructor = type.GetConstructor([typeof(Relay), typeof(RelaySettings)]);
if (constructor == null) throw new AdasException("Constructor not found for relay device");
var relayDevice = (RelayDevice)constructor.Invoke([relay, _relaySettings]);
if (relayDevice == null) throw new AdasException("Relay device not found");
relayDevice.RelayStatusChanged += (_, outletId) =>
{
var cacheKey = Tuple.Create(relay.Ip, relay.Port, outletId);
var value = relayDevice.GetStatusRelay(outletId);
lock (_relayWithStatus)
{
_relayWithStatus[cacheKey] = value;
}
_logger.LogDebug("Relay status changed for {Key} with value {Value}", cacheKey, value);
RelayStatusChanged?.Invoke(this, Tuple.Create(relayDevice, outletId));
};
_devices.Add(relayDevice);
return relayDevice;
}
private async Task PowerRelay(Relay relay, UriBuilder builder)
{
var query = HttpUtility.ParseQueryString(builder.Query);
query["driver"] = relay.Driver;
query["host"] = relay.Ip;
query["port"] = relay.Port.ToString();
query["relayName"] = relay.RelayName;
query["relays"] = relay.Total.ToString();
query["username"] = relay.Username;
query["password"] = relay.Password;
builder.Query = query.ToString();
HttpRequestMessage request = new()
{
RequestUri = builder.Uri,
Method = HttpMethod.Post
};
try
{
using var client = _httpClientFactory.CreateClient();
var httpResponse = await client.SendAsync(request);
if (!httpResponse.StatusCode.Equals(HttpStatusCode.OK))
_logger.LogDebug("Send PowerRelay relay {Relay}", relay);
}
catch (Exception e)
{
_logger.LogError("Error PowerRelay relay {Relay}: {EMessage} {EStackTrace}", relay, e.Message,
e.StackTrace);
}
}
private static string DictionaryToString(ConcurrentDictionary<Tuple<string, int, int>, RelayEnum.Status> dictionary)
{
var builder = new StringBuilder();
foreach (var pair in dictionary)
builder.AppendLine($"Device ID: {pair.Key.Item1}, Port: {pair.Key.Item2}, Status: {pair.Value}");
return builder.ToString();
}
private async Task<RelayEnum.Status> GetRelayStatusByOr(Relay relay)
{
var cacheKey = Tuple.Create(relay.Ip, relay.Port, relay.RelayNumber);
_builder = new UriBuilder(_url)
{
Path = $"Relay/{relay.RelayNumber}/status"
};
var query = HttpUtility.ParseQueryString(_builder.Query);
query["driver"] = relay.Driver;
query["host"] = relay.Ip;
query["port"] = relay.Port.ToString();
query["relayName"] = relay.RelayName;
query["relays"] = relay.Total.ToString();
query["username"] = relay.Username;
query["password"] = relay.Password;
query["mode"] = relay.Mode.ToString();
query["refreshTime"] = "0";
_builder.Query = query.ToString();
HttpRequestMessage request = new()
{
RequestUri = _builder.Uri,
Method = HttpMethod.Get
};
using var client = _httpClientFactory.CreateClient();
client.Timeout = new TimeSpan(0, 0, 3);
var httpResponse = await client.SendAsync(request);
if (httpResponse.StatusCode.Equals(HttpStatusCode.OK))
{
var responseContent = httpResponse.Content;
var response = await responseContent.ReadAsStringAsync();
response = response.Replace("\"", "");
var relayStatusParsed = (RelayEnum.Status)Enum.Parse(typeof(RelayEnum.Status), response);
if (_relaySettings.Cache && relay.Cache)
lock (_relayWithStatus)
{
_relayWithStatus[cacheKey] = relayStatusParsed;
_logger.LogDebug("Relay status cached: {Dct}", DictionaryToString(_relayWithStatus));
}
return relayStatusParsed;
}
if (_relaySettings.Cache && relay.Cache)
lock (_relayWithStatus)
{
_relayWithStatus[cacheKey] = RelayEnum.Status.Unknown;
_logger.LogDebug("Relay status cached: {Dct}", DictionaryToString(_relayWithStatus));
}
return RelayEnum.Status.Unknown;
}
}
@@ -0,0 +1,282 @@
using adas_core.Application.Services.Interfaces;
using adas_core.Domain.Models.AppSettings;
using adas_core.Domain.Models.SystemAlerts;
using EasyNetQ;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using System.Diagnostics;
namespace adas_core.Infrastructure.Services;
public class SendAlertService(
IOptions<RabbitMqSettings> rabbitMqSettings,
ILogger<SendAlertService> logger)
: ISendAlertService
{
private readonly string _errorObservationsQueue = $"Error{rabbitMqSettings.Value.ObservationsQueue}";
private readonly string _errorPatientsQueue = $"Error{rabbitMqSettings.Value.PatientsQueue}";
private readonly string _errorPumpsQueue = $"Error{rabbitMqSettings.Value.PumpsQueue}";
private readonly string _errorRecordingQueue = $"Error{rabbitMqSettings.Value.RecordingQueue}";
private readonly string _errorTreatmetsQueue = $"Error{rabbitMqSettings.Value.TreatmentsQueue}";
private readonly string? _rabbitConnectionString = rabbitMqSettings.Value.ConnectionString;
//readonly PlatformID[] _windowsPlatforms;
////TODO new ws private static DefaultWebSocketHandler defaultWebSocketHandler = new ();
//_windowsPlatforms = new[]
//{
// PlatformID.Win32NT,
// PlatformID.Win32S,
// PlatformID.Win32Windows,
// PlatformID.WinCE
//};
public async Task<List<Queue>> GetQueues()
{
if (_rabbitConnectionString != null) return await GetQueuesAsync();
logger.LogError("Rabbit connection string not defined in web config");
return [];
}
public List<Performance> GetPerformance()
{
logger.LogDebug("Starting check performance data from hospitals");
var list = new List<Performance>();
try
{
list.Add(GetConsumedCpu());
list.Add(GetConsumedRam());
list.AddRange(GetConsumedStorages());
}
catch (Exception e)
{
logger.LogError("Error check error performance data from hospitals: {eMessage} {eStackTrace}",
e.Message, e.StackTrace);
}
return list;
}
public async Task<List<ApiClients>> GetApiClients()
{
return await GetApiClientsAsync();
}
private async Task<List<Queue>> GetQueuesAsync()
{
logger.LogDebug("Starting check rabbitMQ data from hospitals");
var errorQueues = new List<Queue>();
var errorQueuesNames = new List<string>();
try
{
var services = new ServiceCollection();
services.AddEasyNetQ(_rabbitConnectionString);
var provider = services.BuildServiceProvider();
var bus = provider.GetRequiredService<IBus>();
var advanced = bus.Advanced;
if (!string.IsNullOrEmpty(_errorRecordingQueue))
errorQueuesNames.Add(_errorRecordingQueue);
if (!string.IsNullOrEmpty(_errorPatientsQueue))
errorQueuesNames.Add(_errorPatientsQueue);
if (!string.IsNullOrEmpty(_errorTreatmetsQueue))
errorQueuesNames.Add(_errorTreatmetsQueue);
if (!string.IsNullOrEmpty(_errorObservationsQueue))
errorQueuesNames.Add(_errorObservationsQueue);
if (!string.IsNullOrEmpty(_errorPumpsQueue))
errorQueuesNames.Add(_errorPumpsQueue);
foreach (var errorQueueName in errorQueuesNames.Distinct())
{
var stats = await advanced.GetQueueStatsAsync(errorQueueName);
errorQueues.Add(new Queue
{
Name = errorQueueName,
Messages = stats.MessagesCount,
Consumers = stats.ConsumersCount
});
}
}
catch (Exception e)
{
logger.LogError("Error checking RabbitMQ queues: {msg} {stack}",
e.Message, e.StackTrace);
}
return errorQueues;
}
public Performance GetConsumedCpu()
{
Performance performance = new();
try
{
var currentProcess = Process.GetCurrentProcess();
var percentage = currentProcess.TotalProcessorTime.TotalMilliseconds / Environment.ProcessorCount / 10;
performance = new Performance
{
Name = "CPU",
PercentageConsumed = percentage,
ValueTotal = 100,
Unit = "%"
};
}
catch (Exception e)
{
logger.LogError("Error check CPU performance: {eMessage} {eStackTrace}", e.Message, e.StackTrace);
}
return performance;
}
public Performance GetConsumedRam()
{
Performance performance = new();
try
{
var totalMemoryBytes = GC.GetTotalMemory(false);
var totalMemoryGb = Math.Round((double)totalMemoryBytes / 1024 / 1024 / 1024, 2);
performance = new Performance
{
Name = "RAM",
ValueTotal = totalMemoryGb,
ValueConsumed = totalMemoryGb,
PercentageConsumed = 100,
Unit = "GB"
};
}
catch (Exception e)
{
logger.LogError("Error check RAM performance: {eMessage} {eStackTrace}", e.Message, e.StackTrace);
}
return performance;
}
public Performance GetConsumedStorage(DriveInfo drive)
{
Performance performance = new();
try
{
double percentage = 0;
//Total storage
double valueTotal = drive.TotalSize;
//Consumed storage
var value = valueTotal - drive.AvailableFreeSpace;
if (valueTotal != 0)
{
percentage = Math.Round(value * 100 / valueTotal, 2); //%
valueTotal = Math.Round(valueTotal / 1024 / 1024 / 1024, 2); //Bytes -> GB
}
value = Math.Round(value / 1024 / 1024 / 1024, 2); //Bytes -> GB
performance = new Performance
{
Name = "STORAGE " + drive.Name,
ValueConsumed = value,
ValueTotal = valueTotal,
PercentageConsumed = percentage,
Unit = "GB"
};
}
catch (Exception e)
{
logger.LogError("Error check Storage performance: {eMessage} {eStackTrace}", e.Message, e.StackTrace);
}
return performance;
}
private List<Performance> GetConsumedStorages()
{
var list = new List<Performance>();
try
{
foreach (var drive in DriveInfo.GetDrives())
{
if (!drive.IsReady) continue;
try
{
var performance = GetConsumedStorage(drive);
list.Add(performance);
}
catch (Exception e)
{
logger.LogError("Error check Storage drive {drive} in performance: {eMessage}", drive.Name,
e.Message);
}
}
}
catch (Exception e)
{
logger.LogError("Error check Storages performance: {eMessage}", e.Message);
}
return list;
}
private async Task<List<ApiClients>> GetApiClientsAsync()
{
logger.LogDebug("Starting check conected clients from hospitals");
var clientsList = new List<ApiClients>();
try
{
var clients = await GetWebSocketClients();
if (clients != null)
clientsList.Add(clients);
}
catch (Exception e)
{
logger.LogError("Error check error conected clients from hospitals: {eMessage} {eStackTrace}",
e.Message, e.StackTrace);
}
return clientsList;
}
private Task<ApiClients?> GetWebSocketClients()
{
ApiClients apiClients = new();
try
{
//TODO new ws apiClients = defaultWebSocketHandler.GetSubscribersConected();
//apiClients = webSocketHandler.GetSubscribersConected();
}
catch (Exception e)
{
logger.LogError("Error check WebSocket Clients: {eMessage} {eStackTrace}", e.Message, e.StackTrace);
}
return Task.FromResult<ApiClients?>(apiClients);
}
}
@@ -0,0 +1,50 @@
using adas_core.Application.Services.Caching;
using adas_core.Application.Services.Interfaces;
using adas_core.Domain.Models.AppSettings;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
namespace adas_core.Infrastructure.Utils
{
public static class CacheHostBuilderExtension
{
public static IHostBuilder UseCache(this IHostBuilder hostBuilder)
{
return hostBuilder.ConfigureServices((context, services) =>
{
services.Configure<CacheSettings>(context.Configuration.GetSection("CacheSettings"));
services.AddSingleton(sp => sp.GetRequiredService<IOptions<CacheSettings>>().Value);
services.AddSingleton<InMemoryLockProvider>();
services.AddSingleton<NoCacheService>();
// RedisLockProvider obtiene IDatabase de forma lazy a través de una clausura,
// ya que la conexión se establece de forma asíncrona dentro de RedisService.
services.AddSingleton<RedisService>(sp => {
RedisService? svcRef = null;
var lockProvider = new RedisLockProvider(() => svcRef?.Database);
var lockMgr = new LockManagerService(
sp.GetRequiredService<ILogger<LockManagerService>>(),
lockProvider);
svcRef = new RedisService(
sp.GetRequiredService<IOptions<CacheSettings>>(),
sp.GetRequiredService<ILogger<RedisService>>(),
lockMgr);
return svcRef;
});
// Inyectamos LockManager con InMemoryLockProvider
services.AddSingleton<CacheService>(sp => {
var lockMgr = new LockManagerService(
sp.GetRequiredService<ILogger<LockManagerService>>(),
sp.GetRequiredService<InMemoryLockProvider>());
return new CacheService(lockMgr);
});
services.AddSingleton<ICacheService, CacheDispatcher>();
});
}
}
}
@@ -0,0 +1,43 @@
using adas_core.Domain.Models.MongoModels;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace adas_core.Infrastructure.Utils;
public class CustomPointOfCareConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(PointOfCare);
}
public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer)
{
if (value == null)
{
writer.WriteNull();
return;
}
var jo = JObject.FromObject(value);
// Aquí modificas específicamente las propiedades que necesitas
// Por ejemplo, aplicar StringEnumConverter solo a ciertas propiedades enumeradas
// Esto es un ejemplo, ajusta según tus necesidades
foreach (var prop in value.GetType().GetProperties())
if (prop.PropertyType.IsEnum)
{
var enumValue = prop.GetValue(value);
if (enumValue != null) jo[prop.Name] = JToken.FromObject(enumValue.ToString() ?? string.Empty);
}
jo.WriteTo(writer);
}
public override object ReadJson(JsonReader reader, Type objectType, object? existingValue,
JsonSerializer serializer)
{
// Implementa la lógica de deserialización si es necesario
throw new NotImplementedException();
}
}
@@ -0,0 +1,104 @@
using System.Reflection;
using adas_core.Domain.Models.AppSettings;
using adas_core.Infrastructure.Utils.MongoMaps.Interfaz;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options;
using MongoDB.Bson.Serialization.Conventions;
using MongoDB.Driver;
using MongoMigrations.Core;
using MongoClient = MongoDB.Driver.MongoClient;
namespace adas_core.Infrastructure.Utils;
public static class MongoDbHostBuilderExtension
{
public static IHostBuilder UseMongo(this IHostBuilder hostBuilder)
{
ConfigureMongoDbConventions();
ConfigureRegisterMapClass();
return hostBuilder;
}
public static IHost RunMongoMigrations(this IHost host)
{
using var scope = host.Services.CreateScope();
var database = scope.ServiceProvider.GetRequiredService<IMongoDatabase>();
var locator = new MigrationLocator();
locator.LookForMigrationsInAssembly(
typeof(adas_core.Infrastructure.Migrations.MongoMigrations.U_0_1_0_UpdateDataPatien).Assembly
);
var runner = new MigrationRunner(
database,
collectionName: "migrations",
migrationLocator: locator
);
runner.UpdateToLatest();
return host;
}
private static IMongoDatabase ConfigureMongoDbConnection(IOptions<DatabaseSettings> dbSettings)
{
var connectionString = dbSettings.Value.ConnectionString;
var databaseName = dbSettings.Value.DatabaseName;
if (string.IsNullOrEmpty(connectionString) || string.IsNullOrEmpty(databaseName))
throw new Exception("DataBase connection string and name is requiered");
_mongoClient = new MongoClient(connectionString);
var mongoDb = _mongoClient.GetDatabase(databaseName);
if (mongoDb == null) throw new Exception("DataBase doesn't exist");
return mongoDb;
}
public static void ConfigureRegisterMapClass()
{
var assembly = Assembly.GetExecutingAssembly();
// Busca todos los tipos que implementan la interfaz
var contributors = assembly.GetTypes()
.Where(t => typeof(IEntityMapContributor).IsAssignableFrom(t) &&
t is { IsInterface: false, IsAbstract: false });
// Crea una instancia de cada contribuidor y ejecuta su método
foreach (var contributorType in contributors)
{
var contributorInstance = (IEntityMapContributor)Activator.CreateInstance(contributorType)!;
contributorInstance.RegisterMaps();
}
}
public static void ConfigureMongoDbConventions()
{
var pack = new ConventionPack
{
new IgnoreExtraElementsConvention(true),
new CamelCaseElementNameConvention()
};
ConventionRegistry.Register(
"Ignore Extra Elements Convention",
pack,
_ => true);
ConventionRegistry.Register(
"Camel Case Convention",
pack,
_ => true);
}
#region MongoDB
private static MongoClient? _mongoClient;
#endregion
}
@@ -0,0 +1,133 @@
using adas_core.Domain.Enums;
using adas_core.Domain.Models;
using adas_core.Domain.Models.MongoModels;
using adas_core.Domain.Models.SystemAlerts;
using adas_core.Infrastructure.Utils.MongoMaps.Interfaz;
using MongoDB.Bson;
using MongoDB.Bson.Serialization;
using MongoDB.Bson.Serialization.Serializers;
namespace adas_core.Infrastructure.Utils.MongoMaps;
public class AlarmMapContributor : IEntityMapContributor
{
public void RegisterMaps()
{
if (!BsonClassMap.IsClassMapRegistered(typeof(AlarmConfig)))
BsonClassMap.RegisterClassMap<AlarmConfig>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.Name).SetIgnoreIfNull(true);
cm.MapMember(c => c.Enabled).SetDefaultValue(false);
cm.MapMember(c => c.EndAfter).SetIgnoreIfNull(true);
cm.MapMember(c => c.Recording).SetIgnoreIfNull(true);
cm.MapMember(c => c.Beacon).SetIgnoreIfNull(true);
cm.MapMember(c => c.OpenDoor).SetIgnoreIfNull(true);
cm.MapMember(c => c.Priority).SetIgnoreIfNull(true);
cm.MapMember(c => c.Color).SetIgnoreIfNull(true);
cm.MapMember(c => c.AudioConfig).SetIgnoreIfNull(true);
});
if (!BsonClassMap.IsClassMapRegistered(typeof(AudioConfig)))
BsonClassMap.RegisterClassMap<AudioConfig>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.Type)
.SetDefaultValue(AlarmEnum.AudioAlarmType.Off)
.SetSerializer(new EnumSerializer<AlarmEnum.AudioAlarmType>(BsonType.String));
cm.MapMember(c => c.Path).SetIgnoreIfNull(true);
cm.MapMember(c => c.EndAfter).SetIgnoreIfNull(true);
});
if (!BsonClassMap.IsClassMapRegistered(typeof(AlarmItem)))
BsonClassMap.RegisterClassMap<AlarmItem>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.Enabled).SetDefaultValue(false);
cm.MapMember(c => c.StartBefore).SetIgnoreIfNull(true);
cm.MapMember(c => c.EndAfter).SetIgnoreIfNull(true);
cm.MapMember(c => c.Color).SetIgnoreIfNull(true);
cm.MapMember(c => c.Severity)
.SetDefaultValue(AlarmEnum.Severity.None)
.SetSerializer(new EnumSerializer<AlarmEnum.Severity>(BsonType.String));
cm.MapMember(c => c.BeaconColor)
.SetDefaultValue(AlarmEnum.BeaconColor.None)
.SetSerializer(new EnumSerializer<AlarmEnum.BeaconColor>(BsonType.String));
});
if (!BsonClassMap.IsClassMapRegistered(typeof(PatientObservationAlarm)))
{
BsonClassMap.RegisterClassMap<PatientObservationAlarm>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.InactivationState).SetIgnoreIfNull(true);
cm.MapMember(c => c.EventPhase)
.SetDefaultValue(AlarmEnum.EventPhase.Continue)
.SetSerializer(new EnumSerializer<AlarmEnum.EventPhase>(BsonType.String));
cm.MapMember(c => c.Event).SetIgnoreIfNull(true);
cm.MapMember(c => c.EventId).SetIgnoreIfNull(true);
cm.MapMember(c => c.State)
.SetIgnoreIfNull(true)
.SetSerializer(new NullableSerializer<AlarmEnum.ObservationAlarmState>(
new EnumSerializer<AlarmEnum.ObservationAlarmState>(BsonType.String)));
cm.MapMember(c => c.Priority)
.SetIgnoreIfNull(true)
.SetSerializer(new NullableSerializer<AlarmEnum.ObservationAlarmPriority>(
new EnumSerializer<AlarmEnum.ObservationAlarmPriority>(BsonType.String)));
cm.MapMember(c => c.PriorityLevel)
.SetIgnoreIfNull(true)
.SetSerializer(new NullableSerializer<int>(new Int32Serializer()));
cm.UnmapMember(c => c.AlarmConfig);
cm.MapMember(c => c.Type)
.SetIgnoreIfNull(true)
.SetSerializer(
new NullableSerializer<AlarmEnum.ObservationAlarmType>(
new EnumSerializer<AlarmEnum.ObservationAlarmType>(BsonType.String)));
cm.MapMember(c => c.AlertColor).SetIgnoreIfNull(true)
.SetSerializer(new StringSerializer(BsonType.String));
cm.UnmapMember(c => c.MessageTime);
cm.MapMember(c => c.Persist).SetIgnoreIfNull(true);
cm.UnmapMember(c => c.Expired);
cm.MapMember(c => c.Expires).SetIgnoreIfNull(true);
cm.MapMember(c => c.Sources).SetIgnoreIfNull(true);
});
BsonClassMap.RegisterClassMap<InactivationState>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.Audio)
.SetIgnoreIfNull(true)
.SetSerializer(
new NullableSerializer<AlarmEnum.AudioVideoState>(
new EnumSerializer<AlarmEnum.AudioVideoState>(BsonType.String)));
cm.MapMember(c => c.Visual)
.SetIgnoreIfNull(true)
.SetSerializer(
new NullableSerializer<AlarmEnum.AudioVideoState>(
new EnumSerializer<AlarmEnum.AudioVideoState>(BsonType.String)));
cm.MapMember(c => c.Acknowledge).SetIgnoreIfNull(true);
});
BsonClassMap.RegisterClassMap<Source>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.Code).SetIgnoreIfNull(true);
cm.MapMember(c => c.OriginalName).SetIgnoreIfNull(true);
cm.MapMember(c => c.CodeSystem).SetIgnoreIfNull(true);
cm.MapMember(c => c.Units).SetIgnoreIfNull(true);
cm.MapMember(c => c.Value).SetIgnoreIfNull(true);
cm.MapMember(c => c.Result).SetIgnoreIfNull(true);
});
}
if (!BsonClassMap.IsClassMapRegistered(typeof(PatientRecordingAlert)))
BsonClassMap.RegisterClassMap<PatientRecordingAlert>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.IsRecording);
});
if (!BsonClassMap.IsClassMapRegistered(typeof(Performance)))
BsonClassMap.RegisterClassMap<Performance>(cm => { cm.AutoMap(); });
}
}
@@ -0,0 +1,72 @@
using adas_core.Domain.Enums;
using adas_core.Domain.Models;
using adas_core.Infrastructure.Utils.MongoMaps.Interfaz;
using MongoDB.Bson;
using MongoDB.Bson.Serialization;
using MongoDB.Bson.Serialization.Serializers;
namespace adas_core.Infrastructure.Utils.MongoMaps;
public class AppointmentMapContributor : IEntityMapContributor
{
public void RegisterMaps()
{
if (!BsonClassMap.IsClassMapRegistered(typeof(PatientAppointment)))
BsonClassMap.RegisterClassMap<PatientAppointment>(cm =>
{
cm.AutoMap();
cm.MapIdMember(c => c.Id).SetElementName("_id");
cm.MapMember(c => c.PatientId).SetSerializer(new ObjectIdSerializer(BsonType.String));
cm.MapMember(c => c.Patient).SetIgnoreIfNull(true);
cm.MapMember(c => c.Timings).SetDefaultValue(new List<Timing>());
cm.MapMember(c => c.CreateTime).SetIgnoreIfNull(true);
cm.MapMember(c => c.UpdateTime).SetIgnoreIfNull(true);
cm.MapMember(c => c.PlacerOrder).SetIgnoreIfNull(true);
cm.MapMember(c => c.FillerOrder).SetIgnoreIfNull(true);
cm.MapMember(c => c.EventReason).SetIgnoreIfNull(true);
cm.MapMember(c => c.AppointmentReason).SetIgnoreIfNull(true);
cm.MapMember(c => c.AppointmentType).SetIgnoreIfNull(true);
cm.MapMember(c => c.AppointmentOperationType)
.SetIgnoreIfNull(true)
.SetSerializer(
new NullableSerializer<OperationType>(new EnumSerializer<OperationType>(BsonType.String)));
cm.MapMember(c => c.AppointmentStatus)
.SetIgnoreIfNull(true)
.SetSerializer(
new NullableSerializer<OperationType>(new EnumSerializer<OperationType>(BsonType.String)));
cm.MapMember(c => c.Duration).SetIgnoreIfNull(true);
cm.MapMember(c => c.VisitNumber).SetIgnoreIfNull(true);
cm.MapMember(c => c.PatientClass).SetIgnoreIfNull(true);
cm.MapMember(c => c.EpisodeActivation).SetDefaultValue(true);
cm.MapMember(c => c.PlacerContact).SetIgnoreIfNull(true);
cm.MapMember(c => c.FillerContact).SetIgnoreIfNull(true);
cm.MapMember(c => c.ResourceGroups).SetDefaultValue(new List<PatientAppointmentResourceGroup>());
cm.MapMember(c => c.Allergies).SetDefaultValue(new List<Allergies>());
});
if (!BsonClassMap.IsClassMapRegistered(typeof(PatientAppointmentResourceGroup)))
BsonClassMap.RegisterClassMap<PatientAppointmentResourceGroup>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.Services).SetIgnoreIfNull(true);
cm.MapMember(c => c.Resources).SetIgnoreIfNull(true);
cm.MapMember(c => c.Locations).SetIgnoreIfNull(true);
cm.MapMember(c => c.Personnel).SetIgnoreIfNull(true);
cm.UnmapMember(c => c.ServicesActions);
cm.UnmapMember(c => c.ResourcesActions);
cm.UnmapMember(c => c.LocationsActions);
cm.UnmapMember(c => c.PersonnelActions);
});
if (!BsonClassMap.IsClassMapRegistered(typeof(Allergies)))
BsonClassMap.RegisterClassMap<Allergies>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.AllergenType).SetIgnoreIfNull(true);
cm.MapMember(c => c.Allergen).SetIgnoreIfNull(true);
});
}
}
@@ -0,0 +1,37 @@
using adas_core.Domain.Models.MongoModels;
using adas_core.Infrastructure.Utils.MongoMaps.Interfaz;
using MongoDB.Bson.Serialization;
namespace adas_core.Infrastructure.Utils.MongoMaps;
public class AuthMapContributor : IEntityMapContributor
{
public void RegisterMaps()
{
if (!BsonClassMap.IsClassMapRegistered(typeof(User)))
BsonClassMap.RegisterClassMap<User>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.Password)
.SetIgnoreIfNull(true)
.SetShouldSerializeMethod(obj => !string.IsNullOrEmpty(((User)obj).Password));
cm.MapIdMember(c => c.Id).SetElementName("_id");
cm.MapMember(c => c.LockExpirationDate)
.SetIgnoreIfNull(true);
cm.MapMember(c => c.Authorization).SetElementName("Authorization")
.SetShouldSerializeMethod(_ => false);
});
if (!BsonClassMap.IsClassMapRegistered(typeof(Authorization)))
BsonClassMap.RegisterClassMap<Authorization>(cm =>
{
cm.AutoMap();
cm.MapIdMember(c => c.Id).SetElementName("_id");
cm.MapMember(c => c.UnitId).SetIgnoreIfNull(true);
cm.UnmapProperty(c => c.User);
cm.UnmapProperty(c => c.Display);
cm.UnmapProperty(c => c.Unit);
});
}
}
@@ -0,0 +1,62 @@
using adas_core.Domain.Enums;
using adas_core.Domain.Models.MongoModels;
using adas_core.Infrastructure.Utils.MongoMaps.Interfaz;
using MongoDB.Bson;
using MongoDB.Bson.Serialization;
using MongoDB.Bson.Serialization.Serializers;
namespace adas_core.Infrastructure.Utils.MongoMaps;
public class BannerConfigMapContributor : IEntityMapContributor
{
public void RegisterMaps()
{
if (!BsonClassMap.IsClassMapRegistered(typeof(BannerItem)))
BsonClassMap.RegisterClassMap<BannerItem>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.Type)
.SetIgnoreIfNull(true)
.SetSerializer(
new NullableSerializer<DisplayConfigEnums.BannerType>(
new EnumSerializer<DisplayConfigEnums.BannerType>(BsonType.String)));
cm.MapMember(c => c.GrowPriority).SetDefaultValue(1);
cm.MapMember(c => c.Config).SetIgnoreIfNull(true);
});
if (!BsonClassMap.IsClassMapRegistered(typeof(BannerItemConfig)))
BsonClassMap.RegisterClassMap<BannerItemConfig>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.BannerItemDialogTableConfig).SetIgnoreIfNull(true);
cm.MapMember(c => c.BannerItemTableConfig).SetIgnoreIfNull(true);
cm.MapMember(c => c.MedicalStaffConfig).SetIgnoreIfNull(true);
});
if (!BsonClassMap.IsClassMapRegistered(typeof(BannerItemTableConfig)))
BsonClassMap.RegisterClassMap<BannerItemTableConfig>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.Config).SetIgnoreIfNull(true);
cm.MapMember(c => c.BgColor).SetIgnoreIfNull(true);
cm.MapMember(c => c.TextColor).SetIgnoreIfNull(true);
});
if (!BsonClassMap.IsClassMapRegistered(typeof(HeaderBannerItemTableConfig)))
BsonClassMap.RegisterClassMap<HeaderBannerItemTableConfig>(cm =>
{
cm.MapMember(c => c.Type)
.SetIgnoreIfNull(true)
.SetSerializer(
new NullableSerializer<DisplayConfigEnums.CellType>(
new EnumSerializer<DisplayConfigEnums.CellType>(BsonType.String)));
cm.MapMember(c => c.SubType).SetIgnoreIfNull(true);
cm.MapMember(c => c.Field).SetIgnoreIfNull(true);
cm.MapMember(c => c.GrowPriority).SetIgnoreIfNull(true);
cm.MapMember(c => c.Icon).SetIgnoreIfNull(true);
cm.MapMember(c => c.BgColor).SetIgnoreIfNull(true);
cm.MapMember(c => c.TextColor).SetIgnoreIfNull(true);
cm.MapMember(c => c.Title).SetIgnoreIfNull(true);
});
}
}
@@ -0,0 +1,42 @@
using adas_core.Domain.Models.MongoModels;
using adas_core.Infrastructure.Utils.MongoMaps.Interfaz;
using adas_core.module.LightBeacons.Devices;
using MongoDB.Bson.Serialization;
using LightBeacon = adas_core.Domain.Models.MongoModels.LightBeacon;
namespace adas_core.Infrastructure.Utils.MongoMaps;
public class BeaconMapContributor : IEntityMapContributor
{
public void RegisterMaps()
{
if (!BsonClassMap.IsClassMapRegistered(typeof(LightBeacon)))
BsonClassMap.RegisterClassMap<LightBeacon>(cm =>
{
cm.AutoMap();
cm.MapIdMember(c => c.Id).SetElementName("_id");
cm.MapMember(c => c.Type).SetDefaultValue(string.Empty);
cm.MapMember(c => c.Name).SetDefaultValue(string.Empty);
cm.MapMember(c => c.Options).SetDefaultValue(new Options());
cm.MapMember(c => c.InUse).SetIgnoreIfNull(true).SetIsRequired(false);
});
if (!BsonClassMap.IsClassMapRegistered(typeof(Options)))
BsonClassMap.RegisterClassMap<Options>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.Url).SetIgnoreIfNull(true);
cm.MapMember(c => c.Port).SetIgnoreIfNull(true);
cm.MapMember(c => c.Password).SetIgnoreIfNull(true);
cm.MapMember(c => c.Emulate).SetDefaultValue(false);
});
if (!BsonClassMap.IsClassMapRegistered(typeof(LightBeaconAbstract)))
BsonClassMap.RegisterClassMap<LightBeaconAbstract>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.Host);
cm.MapMember(c => c.Password);
});
}
}
@@ -0,0 +1,48 @@
using adas_core.Domain.Enums;
using adas_core.Domain.Models.BsonConverters;
using adas_core.Domain.Models.MongoModels;
using adas_core.Infrastructure.Utils.MongoMaps.Interfaz;
using MongoDB.Bson;
using MongoDB.Bson.Serialization;
using MongoDB.Bson.Serialization.Serializers;
using Stream = adas_core.Domain.Models.MongoModels.Stream;
namespace adas_core.Infrastructure.Utils.MongoMaps;
public class BoxConfigMapContributor : IEntityMapContributor
{
public void RegisterMaps()
{
if (!BsonClassMap.IsClassMapRegistered(typeof(Box)))
BsonClassMap.RegisterClassMap<Box>(cm =>
{
cm.AutoMap();
cm.UnmapMember(c => c.PointOfCare); //Esto hace que ignora la propiedad en la serialización del Bson
cm.MapMember(c => c.Bed).SetElementName("name");
cm.UnmapMember(c => c.IsActive);
cm.UnmapMember(c => c.IsVisible);
cm.MapMember(c => c.Configuration)
.SetSerializer(new DictionaryBsonConverter())
.SetIgnoreIfNull(true);
cm.UnmapMember(c => c.Location);
cm.UnmapMember(c => c.HasPatient);
cm.UnmapMember(c => c.Patientid);
cm.UnmapMember(c => c.Patient);
cm.UnmapMember(c => c.AttendingDoctor);
cm.UnmapMember(c => c.Type);
cm.UnmapMember(c => c.Observations);
cm.UnmapMember(c => c.Medication);
});
if (!BsonClassMap.IsClassMapRegistered(typeof(Sensor)))
BsonClassMap.RegisterClassMap<Sensor>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.Name).SetIgnoreIfNull(true);
cm.MapMember(c => c.Title).SetIgnoreIfNull(true);
cm.MapMember(c => c.OnlyNumbers).SetDefaultValue(true);
cm.MapMember(c => c.IsGeneral).SetDefaultValue(true);
});
}
}
@@ -0,0 +1,39 @@
using adas_core.Domain.Models.MongoModels;
using adas_core.Infrastructure.Utils.MongoMaps.Interfaz;
using MongoDB.Bson.Serialization;
using Stream = System.IO.Stream;
namespace adas_core.Infrastructure.Utils.MongoMaps;
public class CameraContributor : IEntityMapContributor
{
public void RegisterMaps()
{
if (!BsonClassMap.IsClassMapRegistered(typeof(Camera)))
{
BsonClassMap.RegisterClassMap<Camera>(cm =>
{
cm.AutoMap();
cm.MapIdMember(c => c.Id).SetElementName("_id");
cm.MapMember(c => c.Streams).SetIgnoreIfNull(true);
cm.MapMember(c => c.Name).SetDefaultValue(string.Empty);
cm.MapMember(c => c.Ptz).SetDefaultValue(false);
cm.MapMember(c => c.Driver).SetIgnoreIfNull(true);
cm.MapMember(c => c.Ip).SetIgnoreIfNull(true);
cm.MapMember(c => c.Username).SetIgnoreIfNull(true);
cm.MapMember(c => c.Password).SetIgnoreIfNull(true);
cm.MapMember(c => c.InUse).SetIgnoreIfNull(true).SetIsRequired(false);
});
BsonClassMap.RegisterClassMap<Domain.Models.MongoModels.Stream>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.Rtsp).SetIgnoreIfNull(true);
cm.MapMember(c => c.Jpeg).SetIgnoreIfNull(true);
cm.MapMember(c => c.WebRtc).SetIgnoreIfNull(true);
cm.MapMember(c => c.Hls).SetIgnoreIfNull(true);
cm.MapMember(c => c.Mp4).SetIgnoreIfNull(true);
});
}
}
}
@@ -0,0 +1,93 @@
using adas_core.Domain.Enums;
using adas_core.Domain.Models.MongoModels;
using adas_core.Infrastructure.Utils.MongoMaps.Interfaz;
using MongoDB.Bson;
using MongoDB.Bson.Serialization;
using MongoDB.Bson.Serialization.Serializers;
namespace adas_core.Infrastructure.Utils.MongoMaps;
public class CardMapContributor : IEntityMapContributor
{
public void RegisterMaps()
{
if (!BsonClassMap.IsClassMapRegistered(typeof(SectionBoxLayout)))
BsonClassMap.RegisterClassMap<SectionBoxLayout>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.Type).SetDefaultValue(DisplayConfigEnums.RowType.Simple)
.SetSerializer(new EnumSerializer<DisplayConfigEnums.RowType>(BsonType.String));
cm.MapMember(c => c.Name).SetIgnoreIfNull(true);
cm.MapMember(c => c.Subtitle).SetIgnoreIfNull(true);
cm.MapMember(c => c.Icon).SetIgnoreIfNull(true);
cm.MapMember(c => c.GridColumn).SetIgnoreIfNull(true);
cm.MapMember(c => c.PaddingTop).SetIgnoreIfNull(true);
cm.MapMember(c => c.PaddingBottom).SetIgnoreIfNull(true);
cm.MapMember(c => c.PaddingLeft).SetIgnoreIfNull(true);
cm.MapMember(c => c.PaddingRight).SetIgnoreIfNull(true);
cm.MapMember(c => c.BorderColor).SetIgnoreIfNull(true);
cm.MapMember(c => c.BorderWidth).SetIgnoreIfNull(true);
cm.MapMember(c => c.BorderStyle).SetIgnoreIfNull(true);
cm.MapMember(c => c.BorderRadius).SetIgnoreIfNull(true);
cm.MapMember(c => c.HProportion).SetIgnoreIfNull(true);
cm.MapMember(c => c.BgColor).SetIgnoreIfNull(true);
cm.MapMember(c => c.SectionUrl).SetIgnoreIfNull(true);
cm.MapMember(c => c.MinHeight).SetIgnoreIfNull(true);
cm.MapMember(c => c.Subtitle).SetIgnoreIfNull(true);
cm.MapMember(c => c.Conditions).SetIgnoreIfNull(true);
cm.MapMember(c => c.Direction).SetDefaultValue(DisplayConfigEnums.DirectionEnum.Row)
.SetSerializer(new EnumSerializer<DisplayConfigEnums.DirectionEnum>(BsonType.String));
cm.MapMember(c => c.Rows).SetDefaultValue(new List<RowBoxLayout>());
});
if (!BsonClassMap.IsClassMapRegistered(typeof(CardDetailsConfig)))
BsonClassMap.RegisterClassMap<CardDetailsConfig>(cm =>
{
cm.AutoMap();
cm.MapIdMember(c => c.Id).SetElementName("_id");
cm.MapMember(c => c.Header).SetIgnoreIfNull(true);
cm.MapMember(c => c.SmartSections).SetDefaultValue(new List<SectionBoxLayout>());
cm.MapMember(c => c.NurseRows).SetDefaultValue(new List<RowDetailsConfig>());
});
if (!BsonClassMap.IsClassMapRegistered(typeof(CardRotatingLayout)))
BsonClassMap.RegisterClassMap<CardRotatingLayout>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.MillisecondsBeforeRotating).SetDefaultValue(3000);
cm.MapMember(c => c.Order).SetIgnoreIfNull(true);
cm.MapMember(c => c.Name).SetIgnoreIfNull(true);
cm.MapMember(c => c.Title).SetIgnoreIfNull(true);
cm.MapMember(c => c.Data)
.SetIgnoreIfNull(true)
.SetIsRequired(false);
cm.MapMember(c => c.Type).SetDefaultValue(DisplayConfigEnums.RotatingLayoutType.HomeSection)
.SetSerializer(new EnumSerializer<DisplayConfigEnums.RotatingLayoutType>(BsonType.String));
cm.MapMember(c => c.Mode).SetDefaultValue(DisplayConfigEnums.RotatingLayoutMode.Default)
.SetSerializer(new EnumSerializer<DisplayConfigEnums.RotatingLayoutMode>(BsonType.String));
});
//standard card rotating layout
if (!BsonClassMap.IsClassMapRegistered(typeof(Step)))
BsonClassMap.RegisterClassMap<Step>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.Type)
.SetIgnoreIfNull(true)
.SetSerializer(
new NullableSerializer<DisplayConfigEnums.StepType>(
new EnumSerializer<DisplayConfigEnums.StepType>(BsonType.String)));
});
if (!BsonClassMap.IsClassMapRegistered(typeof(HomeConfig)))
BsonClassMap.RegisterClassMap<HomeConfig>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.MinColumnSize).SetDefaultValue("250");
cm.MapMember(c => c.ColumnsPerBreakpoint).SetDefaultValue(1);
cm.MapMember(c => c.BreakpointSize).SetDefaultValue("2000");
cm.MapMember(c => c.CardAspectRatioHeight).SetDefaultValue("700");
cm.MapMember(c => c.CardAspectRatioWidth).SetDefaultValue("500");
});
}
}
@@ -0,0 +1,129 @@
using adas_core.Domain.Enums;
using adas_core.Domain.Models.MongoModels;
using adas_core.Infrastructure.Utils.MongoMaps.Interfaz;
using MongoDB.Bson;
using MongoDB.Bson.Serialization;
using MongoDB.Bson.Serialization.Serializers;
namespace adas_core.Infrastructure.Utils.MongoMaps;
public class CellMapContributor : IEntityMapContributor
{
public void RegisterMaps()
{
if (!BsonClassMap.IsClassMapRegistered(typeof(Cell)))
BsonClassMap.RegisterClassMap<Cell>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.Type)
.SetDefaultValue(DisplayConfigEnums.CellType.Default)
.SetSerializer(new EnumSerializer<DisplayConfigEnums.CellType>(BsonType.String));
cm.MapMember(c => c.ChartSettings).SetIgnoreIfNull(true);
cm.MapMember(c => c.GrowPriority).SetDefaultValue(1.0);
cm.MapMember(c => c.Name).SetIgnoreIfNull(true);
cm.MapMember(c => c.IconValueList)
.SetIgnoreIfNull(true);
cm.MapMember(c => c.Border).SetIgnoreIfNull(true);
cm.MapMember(c => c.BorderRadius).SetIgnoreIfNull(true);
cm.MapMember(c => c.Direction)
.SetIgnoreIfNull(true)
.SetSerializer(new NullableSerializer<DisplayConfigEnums.DirectionEnum>(
new EnumSerializer<DisplayConfigEnums.DirectionEnum>(BsonType.String)));
cm.MapMember(c => c.SubType).SetIgnoreIfNull(true);
cm.MapMember(c => c.Size).SetIgnoreIfNull(true);
cm.MapMember(c => c.HideName).SetIgnoreIfNull(true);
cm.MapMember(c => c.IsVisible).SetDefaultValue(true);
cm.MapMember(c => c.IsColumn).SetIgnoreIfNull(true);
cm.MapMember(c => c.BgColor).SetIgnoreIfNull(true);
cm.MapMember(c => c.Title).SetIgnoreIfNull(true);
cm.MapMember(c => c.ValuePathKey).SetIgnoreIfNull(true);
cm.MapMember(c => c.PaddingTop).SetIgnoreIfNull(true);
cm.MapMember(c => c.PaddingBottom).SetIgnoreIfNull(true);
cm.MapMember(c => c.PaddingLeft).SetIgnoreIfNull(true);
cm.MapMember(c => c.PaddingRight).SetIgnoreIfNull(true);
cm.MapMember(c => c.Color).SetIgnoreIfNull(true);
cm.MapMember(c => c.BackgroundColor).SetIgnoreIfNull(true);
cm.MapMember(c => c.ShowIcon).SetIgnoreIfNull(true);
cm.MapMember(c => c.FlexBasis).SetIgnoreIfNull(true);
cm.MapMember(c => c.Grow).SetIgnoreIfNull(true);
cm.MapMember(c => c.Shrink).SetIgnoreIfNull(true);
cm.MapMember(c => c.ShowTitle).SetIgnoreIfNull(true);
cm.MapMember(c => c.IndicatorHorizontal).SetIgnoreIfNull(true);
cm.MapMember(c => c.DialogConfig).SetIgnoreIfNull(true);
cm.MapMember(c => c.ShowIndicator).SetIgnoreIfNull(true);
cm.MapMember(c => c.OnlyNumber).SetIgnoreIfNull(true);
cm.MapMember(c => c.ShowArrow).SetIgnoreIfNull(true);
cm.MapMember(c => c.GraphConf).SetIgnoreIfNull(true);
cm.MapMember(c => c.Names).SetIgnoreIfNull(true);
cm.MapMember(c => c.ObservationName).SetIgnoreIfNull(true);
cm.MapMember(c => c.ObservationTitle).SetIgnoreIfNull(true);
cm.MapMember(c => c.GraphConf).SetIgnoreIfNull(true);
cm.MapMember(c => c.ValuePathNested).SetIgnoreIfNull(true);
cm.MapMember(c => c.SubObs).SetIgnoreIfNull(true);
cm.MapMember(c => c.TextRules).SetIgnoreIfNull(true);
cm.MapMember(c => c.IsStatic).SetIgnoreIfNull(true);
});
if (!BsonClassMap.IsClassMapRegistered(typeof(CellDetails)))
BsonClassMap.RegisterClassMap<CellDetails>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.TextRules).SetIgnoreIfNull(true);
cm.MapMember(c => c.Type)
.SetSerializer(new EnumSerializer<DisplayConfigEnums.CellType>(BsonType.String))
.SetDefaultValue(DisplayConfigEnums.CellType.Default);
cm.MapMember(c => c.ChartSettings).SetIgnoreIfNull(true);
cm.MapMember(c => c.SubType).SetDefaultValue(string.Empty);
cm.MapMember(c => c.GrowPriority).SetDefaultValue(1.0);
cm.MapMember(c => c.Cells).SetDefaultValue(new List<CellDetails>());
cm.MapMember(c => c.Name).SetIgnoreIfNull(true);
cm.MapMember(c => c.Title).SetIgnoreIfNull(true);
cm.MapMember(c => c.IsVisible).SetDefaultValue(true);
cm.MapMember(c => c.ValuePathNested).SetIgnoreIfNull(true);
cm.MapMember(c => c.ValuePathKey).SetIgnoreIfNull(true);
cm.MapMember(c => c.IconValueList).SetIgnoreIfNull(true);
cm.MapMember(c => c.ObservationName).SetIgnoreIfNull(true);
cm.MapMember(c => c.PaddingTop).SetIgnoreIfNull(true);
cm.MapMember(c => c.PaddingBottom).SetIgnoreIfNull(true);
cm.MapMember(c => c.PaddingLeft).SetIgnoreIfNull(true);
cm.MapMember(c => c.PaddingRight).SetIgnoreIfNull(true);
cm.MapMember(c => c.Color).SetIgnoreIfNull(true);
cm.MapMember(c => c.BackgroundColor).SetIgnoreIfNull(true);
cm.MapMember(c => c.ShowIcon).SetIgnoreIfNull(true);
cm.MapMember(c => c.FlexBasis).SetIgnoreIfNull(true);
cm.MapMember(c => c.FlexDirection).SetIgnoreIfNull(true);
cm.MapMember(c => c.Grow).SetIgnoreIfNull(true);
cm.MapMember(c => c.Shrink).SetIgnoreIfNull(true);
cm.MapMember(c => c.ShowTitle).SetIgnoreIfNull(true);
cm.MapMember(c => c.DialogConfig).SetIgnoreIfNull(true);
cm.MapMember(c => c.IsStatic).SetIgnoreIfNull(true);
});
if (!BsonClassMap.IsClassMapRegistered(typeof(IconValueList)))
BsonClassMap.RegisterClassMap<IconValueList>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.MinValue).SetIgnoreIfNull(true);
cm.MapMember(c => c.MaxValue).SetIgnoreIfNull(true);
cm.MapMember(c => c.Width).SetIgnoreIfNull(true);
cm.MapMember(c => c.Height).SetIgnoreIfNull(true);
cm.MapMember(c => c.IconList).SetIgnoreIfNull(true);
});
if (!BsonClassMap.IsClassMapRegistered(typeof(DialogConfig)))
BsonClassMap.RegisterClassMap<DialogConfig>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.IsDraggable).SetDefaultValue(false);
cm.MapMember(c => c.MedicalConfig).SetIgnoreIfNull(true);
});
if (!BsonClassMap.IsClassMapRegistered(typeof(MedicalConfig)))
BsonClassMap.RegisterClassMap<MedicalConfig>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.HasFinalizeTime).SetDefaultValue(true);
cm.MapMember(c => c.HasStartTime).SetDefaultValue(true);
});
}
}
@@ -0,0 +1,334 @@
using adas_core.Domain.Models.MongoModels;
using adas_core.Infrastructure.Utils.MongoMaps.Interfaz;
using MongoDB.Bson.Serialization;
namespace adas_core.Infrastructure.Utils.MongoMaps;
public class ColorConfigMapContributor : IEntityMapContributor
{
public void RegisterMaps()
{
if (!BsonClassMap.IsClassMapRegistered(typeof(ColorConfig)))
BsonClassMap.RegisterClassMap<ColorConfig>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.Level).SetDefaultValue(new ColorConfig.LevelColors
{
Level1 = "#FFFFFF",
Level2 = "#FAFF41",
Level3 = "#F5A623",
Level4 = "#C2510F",
Level5 = "#FF5D6A"
}).SetIgnoreIfNull(true);
cm.MapMember(c => c.Text).SetDefaultValue(new ColorConfig.TextColors
{
Normal = "#FFFFFF",
Warning = "#FFAD26",
Alert = "#FF5D6A",
Improve = "#60D61D",
Expired = "#333333"
}).SetIgnoreIfNull(true);
cm.MapMember(c => c.Arrow).SetDefaultValue(new ColorConfig.ArrowColors
{
Normal = "#FFFFFF",
Warning = "#F5A623",
Alert = "#FF5D6A",
Improve = "#60D61D"
}).SetIgnoreIfNull(true);
cm.MapMember(c => c.Indicator).SetDefaultValue(new ColorConfig.IndicatorColors
{
Empty = "#CCCCCC",
Warning = "#FFAD26",
Normal = "#60D61D",
Alert = "#FF5D6A",
Background = "#000000",
EmptyBackground = "#CCCCCC"
}).SetIgnoreIfNull(true);
cm.MapMember(c => c.Graph).SetDefaultValue(new ColorConfig.GraphColors
{
Alert = "#FF5D6A",
Warning = "#FFAD26",
Normal = "#60D61D"
}).SetIgnoreIfNull(true);
cm.MapMember(c => c.BoxNumber).SetDefaultValue(new ColorConfig.StatusBoxNumberColors
{
Reserved =
new ColorConfig.AppearanceSettings { BackgroundColor = "#FFF84C", TextColor = "#000000" },
InUse = new ColorConfig.AppearanceSettings { BackgroundColor = "#FFF84C", TextColor = "#000000" },
Available = new ColorConfig.AppearanceSettings
{ BackgroundColor = "#FFF84C", TextColor = "#000000" },
Locked = new ColorConfig.AppearanceSettings { BackgroundColor = "#FFF84C", TextColor = "#000000" },
Transferable = new ColorConfig.AppearanceSettings
{ BackgroundColor = "#FFF84C", TextColor = "#000000" },
Exitus = new ColorConfig.AppearanceSettings { BackgroundColor = "#FFF84C", TextColor = "#000000" },
Altable = new ColorConfig.AppearanceSettings { BackgroundColor = "#FFF84C", TextColor = "#000000" }
}).SetIgnoreIfNull(true);
cm.MapMember(c => c.BoxStatusColor).SetDefaultValue(new ColorConfig.StatusBoxNumberColors
{
Reserved =
new ColorConfig.AppearanceSettings { BackgroundColor = "#FFF84C", TextColor = "#000000" },
InUse = new ColorConfig.AppearanceSettings { BackgroundColor = "#FFF84C", TextColor = "#000000" },
Available = new ColorConfig.AppearanceSettings
{ BackgroundColor = "#FFF84C", TextColor = "#000000" },
Locked = new ColorConfig.AppearanceSettings { BackgroundColor = "#FFF84C", TextColor = "#000000" },
Transferable = new ColorConfig.AppearanceSettings
{ BackgroundColor = "#FFF84C", TextColor = "#000000" },
Exitus = new ColorConfig.AppearanceSettings { BackgroundColor = "#FFF84C", TextColor = "#000000" },
Altable = new ColorConfig.AppearanceSettings { BackgroundColor = "#FFF84C", TextColor = "#000000" }
}).SetIgnoreIfNull(true);
cm.MapMember(c => c.Therapy).SetDefaultValue(new ColorConfig.TherapyColors
{
Default = new ColorConfig.AppearanceSettings(),
Finished = new ColorConfig.AppearanceSettings(),
Initialized = new ColorConfig.AppearanceSettings(),
InProgress = new ColorConfig.AppearanceSettings()
}).SetIgnoreIfNull(true);
cm.MapMember(c => c.Test).SetDefaultValue(new ColorConfig.TestColors
{
Default = new ColorConfig.AppearanceSettings
{
BackgroundColor = "#00A4E1",
TextColor = "#FFF"
},
Finished = new ColorConfig.AppearanceSettings
{
BackgroundColor = "#00C49B",
TextColor = "#FFF",
Icon = "assets/icon/light-theme/ic-tick.svg",
IconDefault = "icTick"
},
Initialized = new ColorConfig.AppearanceSettings
{
BackgroundColor = "#ED4965",
TextColor = "#FFF"
},
Expired = new ColorConfig.AppearanceSettings
{
BackgroundColor = "#ED4965",
TextColor = "#FFF",
Icon = "assets/icon/light-theme/ic-clock.svg",
IconDefault = "icClock"
}
}).SetIgnoreIfNull(true);
cm.MapMember(c => c.Procedure).SetDefaultValue(new ColorConfig.ProcedureColors
{
Default = new ColorConfig.AppearanceSettings
{
BackgroundColor = "#00A4E1",
TextColor = "#FFF"
},
Finished = new ColorConfig.AppearanceSettings
{
BackgroundColor = "#00C49B",
TextColor = "#FFF",
Icon = "assets/icon/light-theme/ic-tick.svg",
IconDefault = "icTick"
},
Initialized = new ColorConfig.AppearanceSettings
{
BackgroundColor = "#ED4965",
TextColor = "#FFF"
},
Expired = new ColorConfig.AppearanceSettings
{
BackgroundColor = "#ED4965",
TextColor = "#FFF",
Icon = "assets/icon/light-theme/ic-clock.svg",
IconDefault = "icClock"
}
}).SetIgnoreIfNull(true);
});
if (!BsonClassMap.IsClassMapRegistered(typeof(ColorConfig.StatusBoxNumberColors)))
BsonClassMap.RegisterClassMap<ColorConfig.StatusBoxNumberColors>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.Reserved).SetDefaultValue(new ColorConfig.AppearanceSettings
{
BackgroundColor = "#FFF84C",
TextColor = "#000000"
});
cm.MapMember(c => c.InUse).SetDefaultValue(new ColorConfig.AppearanceSettings());
cm.MapMember(c => c.Available).SetDefaultValue(new ColorConfig.AppearanceSettings
{
BackgroundColor = "#57B812",
TextColor = "#000000"
});
cm.MapMember(c => c.Locked).SetDefaultValue(new ColorConfig.AppearanceSettings
{
BackgroundColor = "#ED4965",
TextColor = "#000000"
});
cm.MapMember(c => c.Transferable).SetDefaultValue(new ColorConfig.AppearanceSettings
{
BackgroundColor = "#57B812",
TextColor = "#000000"
});
cm.MapMember(c => c.Exitus).SetDefaultValue(new ColorConfig.AppearanceSettings
{
BackgroundColor = "#24BFF9",
TextColor = "#000000"
});
cm.MapMember(c => c.Altable).SetDefaultValue(new ColorConfig.AppearanceSettings
{
BackgroundColor = "#24BFF9",
TextColor = "#000000"
});
});
if (!BsonClassMap.IsClassMapRegistered(typeof(ColorConfig.TherapyColors)))
BsonClassMap.RegisterClassMap<ColorConfig.TherapyColors>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.Default).SetDefaultValue(new ColorConfig.AppearanceSettings
{
BackgroundColor = "#00A4E1",
TextColor = "#FFF",
IconInvertColor = 1
});
cm.MapMember(c => c.Initialized).SetDefaultValue(new ColorConfig.AppearanceSettings
{
BackgroundColor = "#FFF",
TextColor = "#000"
});
cm.MapMember(c => c.Finished).SetDefaultValue(new ColorConfig.AppearanceSettings
{
BackgroundColor = "#FFF",
TextColor = "#000",
Icon = "assets/icon/light-theme/ic-tick.svg",
IconDefault = "icTick"
});
cm.MapMember(c => c.InProgress).SetDefaultValue(new ColorConfig.AppearanceSettings
{
BackgroundColor = "#FFF",
TextColor = "#000"
});
});
if (!BsonClassMap.IsClassMapRegistered(typeof(ColorConfig.AppearanceSettings)))
BsonClassMap.RegisterClassMap<ColorConfig.AppearanceSettings>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.TextColor).SetDefaultValue("#000000");
cm.MapMember(c => c.BackgroundColor).SetDefaultValue("#FFFFFF");
cm.MapMember(c => c.Icon).SetIgnoreIfNull(true);
cm.MapMember(c => c.IconDefault).SetIgnoreIfNull(true);
cm.MapMember(c => c.IconColor).SetIgnoreIfNull(true);
cm.MapMember(c => c.IconCategory).SetIgnoreIfNull(true);
cm.MapMember(c => c.IconInvertColor).SetDefaultValue(0.0);
});
if (!BsonClassMap.IsClassMapRegistered(typeof(ColorConfig.TestColors)))
BsonClassMap.RegisterClassMap<ColorConfig.TestColors>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.Default).SetDefaultValue(new ColorConfig.AppearanceSettings
{
BackgroundColor = "#00A4E1",
TextColor = "#FFF"
});
cm.MapMember(c => c.Initialized).SetDefaultValue(new ColorConfig.AppearanceSettings
{
BackgroundColor = "#ED4965",
TextColor = "#FFF"
});
cm.MapMember(c => c.Finished).SetDefaultValue(new ColorConfig.AppearanceSettings
{
BackgroundColor = "#00C49B",
TextColor = "#FFF",
Icon = "assets/icon/light-theme/ic-tick.svg",
IconDefault = "icTick"
});
cm.MapMember(c => c.Expired).SetDefaultValue(new ColorConfig.AppearanceSettings
{
BackgroundColor = "#ED4965",
TextColor = "#FFF",
Icon = "assets/icon/light-theme/ic-clock.svg",
IconDefault = "icClock"
});
});
if (!BsonClassMap.IsClassMapRegistered(typeof(ColorConfig.ProcedureColors)))
BsonClassMap.RegisterClassMap<ColorConfig.ProcedureColors>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.Default).SetDefaultValue(new ColorConfig.AppearanceSettings
{
BackgroundColor = "#00A4E1",
TextColor = "#FFF"
});
cm.MapMember(c => c.Initialized).SetDefaultValue(new ColorConfig.AppearanceSettings
{
BackgroundColor = "#ED4965",
TextColor = "#FFF"
});
cm.MapMember(c => c.Finished).SetDefaultValue(new ColorConfig.AppearanceSettings
{
BackgroundColor = "#00C49B",
TextColor = "#FFF",
Icon = "assets/icon/light-theme/ic-tick.svg",
IconDefault = "icTick"
});
cm.MapMember(c => c.Expired).SetDefaultValue(new ColorConfig.AppearanceSettings
{
BackgroundColor = "#ED4965",
TextColor = "#FFF",
Icon = "assets/icon/light-theme/ic-clock.svg",
IconDefault = "icClock"
});
});
if (!BsonClassMap.IsClassMapRegistered(typeof(ColorConfig.LevelColors)))
BsonClassMap.RegisterClassMap<ColorConfig.LevelColors>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.Level1).SetDefaultValue("#FFFFFF");
cm.MapMember(c => c.Level2).SetDefaultValue("#FAFF41");
cm.MapMember(c => c.Level3).SetDefaultValue("#F5A623");
cm.MapMember(c => c.Level4).SetDefaultValue("#C2510F");
cm.MapMember(c => c.Level5).SetDefaultValue("#FF5D6A");
});
if (!BsonClassMap.IsClassMapRegistered(typeof(ColorConfig.TextColors)))
BsonClassMap.RegisterClassMap<ColorConfig.TextColors>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.Normal).SetDefaultValue("#FFFFFF");
cm.MapMember(c => c.Warning).SetDefaultValue("#FFAD26");
cm.MapMember(c => c.Alert).SetDefaultValue("#FF5D6A");
cm.MapMember(c => c.Improve).SetDefaultValue("#60D61D");
cm.MapMember(c => c.Expired).SetDefaultValue("#333333");
});
if (!BsonClassMap.IsClassMapRegistered(typeof(ColorConfig.ArrowColors)))
BsonClassMap.RegisterClassMap<ColorConfig.ArrowColors>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.Normal).SetDefaultValue("#FFFFFF");
cm.MapMember(c => c.Warning).SetDefaultValue("#F5A623");
cm.MapMember(c => c.Alert).SetDefaultValue("#FF5D6A");
cm.MapMember(c => c.Improve).SetDefaultValue("#60D61D");
});
if (!BsonClassMap.IsClassMapRegistered(typeof(ColorConfig.IndicatorColors)))
BsonClassMap.RegisterClassMap<ColorConfig.IndicatorColors>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.Empty).SetDefaultValue("#CCCCCC");
cm.MapMember(c => c.Warning).SetDefaultValue("#FFAD26");
cm.MapMember(c => c.Normal).SetDefaultValue("#60D61D");
cm.MapMember(c => c.Alert).SetDefaultValue("#FF5D6A");
cm.MapMember(c => c.Background).SetDefaultValue("#000000");
cm.MapMember(c => c.EmptyBackground).SetDefaultValue("#CCCCCC");
});
if (!BsonClassMap.IsClassMapRegistered(typeof(ColorConfig.GraphColors)))
BsonClassMap.RegisterClassMap<ColorConfig.GraphColors>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.Normal).SetDefaultValue("#60D61D");
cm.MapMember(c => c.Warning).SetDefaultValue("#FFAD26");
cm.MapMember(c => c.Alert).SetDefaultValue("#FF5D6A");
});
}
}
@@ -0,0 +1,40 @@
using adas_core.Domain.Models;
using adas_core.Domain.Models.Recording;
using adas_core.Domain.Models.SignalR;
using adas_core.Domain.Models.SystemAlerts;
using adas_core.Infrastructure.Utils.MongoMaps.Interfaz;
using MongoDB.Bson.Serialization;
namespace adas_core.Infrastructure.Utils.MongoMaps;
public class ComunicationFlowMapContributor : IEntityMapContributor
{
public void RegisterMaps()
{
if (!BsonClassMap.IsClassMapRegistered(typeof(Message)))
BsonClassMap.RegisterClassMap<Message>(cm =>
{
cm.AutoMap();
cm.UnmapMember(c => c.Operation);
});
if (!BsonClassMap.IsClassMapRegistered(typeof(Queue)))
BsonClassMap.RegisterClassMap<Queue>(cm => { cm.AutoMap(); });
if (!BsonClassMap.IsClassMapRegistered(typeof(ApiRequest)))
BsonClassMap.RegisterClassMap<ApiRequest>(cm => { cm.AutoMap(); });
if (!BsonClassMap.IsClassMapRegistered(typeof(AdmPanelRequest)))
BsonClassMap.RegisterClassMap<AdmPanelRequest>(cm =>
{
cm.AutoMap();
cm.GetMemberMap(c => c.ObsertationData).SetIgnoreIfNull(true);
});
if (!BsonClassMap.IsClassMapRegistered(typeof(ApiClients)))
BsonClassMap.RegisterClassMap<ApiClients>(cm => { cm.AutoMap(); });
if (!BsonClassMap.IsClassMapRegistered(typeof(VideoDto)))
BsonClassMap.RegisterClassMap<VideoDto>(cm => { cm.AutoMap(); });
}
}
@@ -0,0 +1,81 @@
using adas_core.Domain.Enums;
using adas_core.Domain.Models.MongoModels;
using adas_core.Domain.Utils;
using adas_core.Infrastructure.Utils.MongoMaps.Interfaz;
using MongoDB.Bson;
using MongoDB.Bson.Serialization;
using MongoDB.Bson.Serialization.Serializers;
namespace adas_core.Infrastructure.Utils.MongoMaps;
public class DeviceMapContributor : IEntityMapContributor
{
public void RegisterMaps()
{
if (!BsonClassMap.IsClassMapRegistered(typeof(DeviceActionType)))
{
BsonClassMap.RegisterClassMap<DeviceActionType>(cm => cm.AutoMap() );
}
if (!BsonClassMap.IsClassMapRegistered(typeof(DeviceAction)))
{
BsonClassMap.RegisterClassMap<DeviceAction>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.Type)
.SetDefaultValue(DeviceActionType.Unknown)
.SetSerializer(new EnumSerializer<DeviceActionType>(BsonType.String));
cm.MapMember(c => c.ConfigObservationId).SetIgnoreIfNull(true);
cm.MapMember(c => c.AlarmName).SetIgnoreIfNull(true);
cm.MapMember(c => c.ValueOnSingleClick)
.SetDefaultValue(new object())
.SetSerializer(new ComplexObjectValueTypeSerializer());
cm.MapMember(c => c.ValueOnDoubleClick)
.SetDefaultValue(new object())
.SetSerializer(new ComplexObjectValueTypeSerializer());
cm.MapMember(c => c.ValueOnHoldClick)
.SetDefaultValue(new object())
.SetSerializer(new ComplexObjectValueTypeSerializer());
}
);
}
if (!BsonClassMap.IsClassMapRegistered(typeof(DeviceSettings)))
{
BsonClassMap.RegisterClassMap<DeviceSettings>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.Action).SetDefaultValue(new DeviceAction());
}
);
}
if (!BsonClassMap.IsClassMapRegistered(typeof(Device)))
{
BsonClassMap.RegisterClassMap<Device>(cm =>
{
cm.AutoMap();
cm.MapIdMember(c => c.Id).SetElementName("_id");
cm.MapMember(c => c.DeviceType)
.SetDefaultValue(DeviceType.Unknown)
.SetSerializer(new EnumSerializer<DeviceType>(BsonType.String));
cm.MapMember(c => c.Uuid).SetIgnoreIfNull(true);
cm.MapMember(c => c.MacAddr).SetIgnoreIfNull(true);
cm.MapMember(c => c.CreatedAt).SetDefaultValue(DateTime.UtcNow);
cm.MapMember(c => c.UpdatedAt).SetDefaultValue(DateTime.UtcNow);
cm.MapMember(c => c.Key).SetIgnoreIfNull(true);
cm.MapMember(c => c.Color).SetIgnoreIfNull(true);
cm.MapMember(c => c.Battery).SetIgnoreIfNull(true);
cm.MapMember(c => c.Name).SetIgnoreIfNull(true);
cm.MapMember(c => c.SerialNumber).SetIgnoreIfNull(true);
cm.MapMember(c => c.PointOfCareIds).SetDefaultValue(new List<ObjectId>());
cm.MapMember(c => c.Connected).SetDefaultValue(false).SetIgnoreIfNull(true);
cm.MapMember(c => c.Ready).SetDefaultValue(false).SetIgnoreIfNull(true);
cm.MapMember(c => c.DeviceType)
.SetSerializer(new EnumSerializer<DeviceType>(BsonType.String));
cm.MapMember(c => c.Settings).SetDefaultValue(new DeviceSettings());
}
);
}
}
}
@@ -0,0 +1,46 @@
using adas_core.Domain.Enums;
using adas_core.Domain.Models.MongoModels;
using adas_core.Infrastructure.Utils.MongoMaps.Interfaz;
using MongoDB.Bson;
using MongoDB.Bson.Serialization;
using MongoDB.Bson.Serialization.Serializers;
namespace adas_core.Infrastructure.Utils.MongoMaps;
public class DisplayHomeConfigContributor : IEntityMapContributor
{
public void RegisterMaps()
{
if (!BsonClassMap.IsClassMapRegistered(typeof(CardConfig)))
BsonClassMap.RegisterClassMap<CardConfig>(cm =>
{
cm.AutoMap();
cm.MapIdMember(c => c.Id).SetElementName("_id");
cm.MapMember(c => c.Rows).SetDefaultValue(new List<RowCardConfig>());
});
if (!BsonClassMap.IsClassMapRegistered(typeof(RowCardConfig)))
BsonClassMap.RegisterClassMap<RowCardConfig>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.Cells).SetDefaultValue(new List<Cell>());
cm.MapMember(c => c.GrowPriority).SetDefaultValue(1);
cm.MapMember(c => c.Border).SetIgnoreIfNull(true);
cm.MapMember(c => c.BorderRadius).SetIgnoreIfNull(true);
cm.MapMember(c => c.Title).SetIgnoreIfNull(true);
cm.MapMember(c => c.Size).SetIgnoreIfNull(true);
cm.MapMember(c => c.MarginTop).SetIgnoreIfNull(true);
cm.MapMember(c => c.MarginBottom).SetIgnoreIfNull(true);
cm.MapMember(c => c.MarginLeft).SetIgnoreIfNull(true);
cm.MapMember(c => c.MarginRight).SetIgnoreIfNull(true);
cm.MapMember(c => c.BgColor).SetIgnoreIfNull(true);
cm.MapMember(c => c.PaddingTop).SetIgnoreIfNull(true);
cm.MapMember(c => c.PaddingBottom).SetIgnoreIfNull(true);
cm.MapMember(c => c.PaddingLeft).SetIgnoreIfNull(true);
cm.MapMember(c => c.PaddingRight).SetIgnoreIfNull(true);
cm.MapMember(c => c.Type)
.SetDefaultValue(DisplayConfigEnums.CellType.Default)
.SetSerializer(new EnumSerializer<DisplayConfigEnums.CellType>(BsonType.String));
});
}
}
@@ -0,0 +1,134 @@
using adas_core.Domain.Enums;
using adas_core.Domain.Models.GroupedObservations;
using adas_core.Domain.Models.MongoModels;
using adas_core.Infrastructure.Utils.MongoMaps.Interfaz;
using MongoDB.Bson;
using MongoDB.Bson.Serialization;
using MongoDB.Bson.Serialization.Serializers;
namespace adas_core.Infrastructure.Utils.MongoMaps;
public class DisplayMapContributor : IEntityMapContributor
{
public void RegisterMaps()
{
if (!BsonClassMap.IsClassMapRegistered(typeof(Display)))
BsonClassMap.RegisterClassMap<Display>(cm =>
{
cm.AutoMap();
cm.MapIdMember(c => c.Id).SetElementName("_id");
cm.UnmapProperty(c => c.Unit);
cm.UnmapProperty(c => c.PointOfCares);
cm.UnmapProperty(c => c.DisplayConfig);
cm.MapMember(c => c.Type)
.SetDefaultValue(DisplayConfigEnums.DisplayType.Unknown)
.SetSerializer(new EnumSerializer<DisplayConfigEnums.DisplayType>(BsonType.String));
});
if (!BsonClassMap.IsClassMapRegistered(typeof(DisplayNurse)))
BsonClassMap.RegisterClassMap<DisplayNurse>(cm =>
{
cm.AutoMap();
});
if (!BsonClassMap.IsClassMapRegistered(typeof(StandarDisplay)))
BsonClassMap.RegisterClassMap<StandarDisplay>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.SectionConfig).SetIgnoreIfNull(true);
});
if (!BsonClassMap.IsClassMapRegistered(typeof(SmartDisplay)))
BsonClassMap.RegisterClassMap<SmartDisplay>(cm =>
{
cm.AutoMap();
});
if (!BsonClassMap.IsClassMapRegistered(typeof(PumpDisplay)))
BsonClassMap.RegisterClassMap<PumpDisplay>(cm =>
{
cm.AutoMap();
});
if (!BsonClassMap.IsClassMapRegistered(typeof(DisplayConfig)))
{
BsonClassMap.RegisterClassMap<DisplayConfig>(cm =>
{
cm.AutoMap();
cm.AddKnownType(typeof(DisplayNurse));
cm.AddKnownType(typeof(StandarDisplay));
cm.AddKnownType(typeof(SmartDisplay));
cm.AddKnownType(typeof(PumpDisplay));
cm.MapIdMember(c => c.Id).SetElementName("_id");
cm.MapMember(c => c.Type)
.SetDefaultValue(DisplayConfigEnums.DisplayType.Unknown)
.SetSerializer(new EnumSerializer<DisplayConfigEnums.DisplayType>(BsonType.String));
cm.MapMember(c => c.MediaFolder).SetIgnoreIfNull(true);
cm.MapMember(c => c.CardConfigId).SetIgnoreIfNull(true);
cm.MapMember(c => c.CardConfig)
.SetIgnoreIfNull(true)
.SetIsRequired(false);
cm.MapMember(c => c.DetailConfigId).SetIgnoreIfNull(true);
cm.MapMember(c => c.DetailConfig)
.SetIgnoreIfNull(true)
.SetIsRequired(false);
cm.MapMember(c => c.HomeBanner).SetIgnoreIfNull(true);
cm.MapMember(c => c.FormConfig)
.SetDefaultValue(new FormConfig
{
Admission = new FormItemOverview { Nhc = true },
Demographic = new FormItemOverview { Nhc = true },
Discharge = new FormItemOverview { Nhc = true },
IncomeInfo = new FormItemOverview { Nhc = true }
});
cm.MapMember(c => c.HasCameras).SetIgnoreIfNull(true);
cm.MapMember(c => c.HasSound).SetIgnoreIfNull(true);
cm.MapMember(c => c.IsRotationEnabled).SetIgnoreIfNull(true);
cm.MapMember(c => c.CanChangeCameraMode).SetIgnoreIfNull(true);
cm.MapMember(c => c.CamerasAreActive).SetIgnoreIfNull(true);
cm.MapMember(c => c.CameraStreamType).SetIgnoreIfNull(true);
cm.MapMember(c => c.SensorList).SetIgnoreIfNull(true);
cm.MapMember(c => c.ObservationForIndicator).SetIgnoreIfNull(true);
cm.MapMember(c => c.AlarmFieldList).SetIgnoreIfNull(true);
cm.MapMember(c => c.RequestGroupedFieldList).SetIgnoreIfNull(true);
cm.MapMember(c => c.Pumps).SetIgnoreIfNull(true);
cm.MapMember(c => c.ChartConfig).SetIgnoreIfNull(true);
cm.MapMember(c => c.GraphLayout).SetIgnoreIfNull(true);
cm.MapMember(c => c.CardRotatingLayout).SetIgnoreIfNull(true);
cm.MapMember(c => c.ChartConfigIdList).SetIgnoreIfNull(true);
cm.MapMember(c => c.HomeConfig).SetIgnoreIfNull(true);
cm.MapMember(c => c.HeaderConfig).SetIgnoreIfNull(true);
cm.MapMember(c => c.DisplaySectionIdList).SetDefaultValue(new List<ObjectId>());
cm.MapMember(c => c.Hospital).SetIgnoreIfNull(true);
cm.MapMember(c => c.ColorConfig).SetDefaultValue(new ColorConfig());
cm.MapMember(c => c.FieldList).SetDefaultValue(new List<Field>());
cm.MapMember(c => c.GroupedFieldList).SetDefaultValue(new List<GroupedField>());
cm.UnmapProperty(c => c.DisplaySectionList);
// cm.UnmapProperty(c => c.CardConfig);
});
BsonClassMap.RegisterClassMap<GroupedField>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.Name).SetIgnoreIfNull(true);
cm.MapMember(c => c.Names).SetIgnoreIfNull(true);
cm.MapMember(c => c.Group).SetIgnoreIfNull(true);
cm.MapMember(c => c.StartTimeShift).SetIgnoreIfNull(true);
cm.MapMember(c => c.Max);
cm.MapMember(c => c.Regularity)
.SetIgnoreIfNull(true)
.SetSerializer(new NullableSerializer<GroupedObservationEnum.Regularity>(
new EnumSerializer<GroupedObservationEnum.Regularity>(BsonType.String)));
cm.MapMember(c => c.Since)
.SetDefaultValue(GroupedObservationEnum.Since.Last)
.SetSerializer(new EnumSerializer<GroupedObservationEnum.Since>(BsonType.String));
cm.MapMember(c => c.Result)
.SetIgnoreIfNull(true);
//.SetSerializer(new EnumSerializer<GroupedObservationEnum.Result>(BsonType.Array));
cm.MapMember(c => c.LabelList).SetIgnoreIfNull(true);
});
}
}
}
@@ -0,0 +1,49 @@
using adas_core.Domain.Models.MongoModels;
using adas_core.Infrastructure.Utils.MongoMaps.Interfaz;
using MongoDB.Bson.Serialization;
namespace adas_core.Infrastructure.Utils.MongoMaps;
public class FormMapContributor : IEntityMapContributor
{
public void RegisterMaps()
{
if (!BsonClassMap.IsClassMapRegistered(typeof(FormConfig)))
BsonClassMap.RegisterClassMap<FormConfig>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.Admission).SetDefaultValue(new FormItemOverview());
cm.MapMember(c => c.Demographic).SetIgnoreIfNull(true);
cm.MapMember(c => c.Discharge).SetIgnoreIfNull(true);
cm.MapMember(c => c.IncomeInfo).SetIgnoreIfNull(true);
});
if (!BsonClassMap.IsClassMapRegistered(typeof(FormItemOverview)))
BsonClassMap.RegisterClassMap<FormItemOverview>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.Nhc).SetDefaultValue(true);
cm.MapMember(c => c.Bed).SetIgnoreIfNull(true);
cm.MapMember(c => c.Name).SetIgnoreIfNull(true);
cm.MapMember(c => c.LastName).SetIgnoreIfNull(true);
cm.MapMember(c => c.SecondName).SetIgnoreIfNull(true);
cm.MapMember(c => c.Genre).SetIgnoreIfNull(true);
cm.MapMember(c => c.Birthday).SetIgnoreIfNull(true);
cm.MapMember(c => c.Origin).SetIgnoreIfNull(true);
cm.MapMember(c => c.OriginAux).SetIgnoreIfNull(true);
cm.MapMember(c => c.Diagnostic).SetIgnoreIfNull(true);
cm.MapMember(c => c.DiagnosticAux).SetIgnoreIfNull(true);
cm.MapMember(c => c.Allergy).SetIgnoreIfNull(true);
cm.MapMember(c => c.Language).SetIgnoreIfNull(true);
cm.MapMember(c => c.Insulation).SetIgnoreIfNull(true);
cm.MapMember(c => c.Service).SetIgnoreIfNull(true);
cm.MapMember(c => c.Destination).SetIgnoreIfNull(true);
cm.MapMember(c => c.DestinationAux).SetIgnoreIfNull(true);
cm.MapMember(c => c.AdmDischarge).SetIgnoreIfNull(true);
cm.MapMember(c => c.NurseDischarge).SetIgnoreIfNull(true);
cm.MapMember(c => c.MedicalDischarge).SetIgnoreIfNull(true);
cm.MapMember(c => c.IncomingDate).SetIgnoreIfNull(true);
cm.MapMember(c => c.UciDays).SetIgnoreIfNull(true);
});
}
}
@@ -0,0 +1,265 @@
using adas_core.Domain.Enums;
using adas_core.Domain.Models.MongoModels;
using adas_core.Infrastructure.Utils.MongoMaps.Interfaz;
using MongoDB.Bson;
using MongoDB.Bson.Serialization;
using MongoDB.Bson.Serialization.Serializers;
namespace adas_core.Infrastructure.Utils.MongoMaps;
public class GraphMapContributor : IEntityMapContributor
{
public void RegisterMaps()
{
if (!BsonClassMap.IsClassMapRegistered(typeof(GraphLayout)))
BsonClassMap.RegisterClassMap<GraphLayout>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.Layout).SetIgnoreIfNull(true);
cm.MapMember(c => c.ObservationTitle).SetIgnoreIfNull(true);
cm.MapMember(c => c.Name).SetIgnoreIfNull(true);
cm.MapMember(c => c.GraphConf).SetIgnoreIfNull(true);
cm.MapMember(c => c.ObservationName).SetIgnoreIfNull(true);
});
if (!BsonClassMap.IsClassMapRegistered(typeof(ChartSettings)))
BsonClassMap.RegisterClassMap<ChartSettings>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.LegendLayoutConfig).SetIgnoreIfNull(true);
cm.MapMember(c => c.LegendGrowPriority).SetIgnoreIfNull(true);
cm.MapMember(c => c.ChartGrowPriority).SetIgnoreIfNull(true);
});
if (!BsonClassMap.IsClassMapRegistered(typeof(ChartConfig)))
{
BsonClassMap.RegisterClassMap<ChartConfig>(cm =>
{
cm.AutoMap();
cm.MapIdMember(c => c.Id).SetElementName("_id");
cm.MapMember(c => c.BaseConfig).SetDefaultValue(new ChartBaseConfig());
cm.MapMember(c => c.AxesConfig).SetDefaultValue(new List<AxisConfig>());
cm.MapMember(c => c.SeriesConfig).SetDefaultValue(new List<SeriesConfigBase>());
});
BsonClassMap.RegisterClassMap<ChartBaseConfig>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.Title).SetDefaultValue(string.Empty);
cm.MapMember(c => c.Top).SetDefaultValue("7%");
cm.MapMember(c => c.Right).SetDefaultValue("7%");
cm.MapMember(c => c.Bottom).SetDefaultValue("7%");
cm.MapMember(c => c.Left).SetDefaultValue("7%");
cm.MapMember(c => c.Group).SetDefaultValue(string.Empty);
cm.MapMember(c => c.Name).SetDefaultValue(string.Empty);
cm.MapMember(c => c.BorderWidth).SetDefaultValue(1);
cm.MapMember(c => c.BorderColor).SetDefaultValue(string.Empty);
cm.MapMember(c => c.ShowLegend).SetDefaultValue(false);
cm.MapMember(c => c.ShowGrid).SetDefaultValue(false);
cm.MapMember(c => c.NumValues).SetIgnoreIfNull(true);
cm.MapMember(c => c.BaselineOffset).SetIgnoreIfNull(true);
});
BsonClassMap.RegisterClassMap<AxisConfig>(cm =>
{
cm.AutoMap();
cm.MapMember(a => a.Type)
.SetSerializer(new EnumSerializer<DisplayConfigEnums.AxisType>(BsonType.String))
.SetDefaultValue(DisplayConfigEnums.AxisType.Value);
cm.MapMember(a => a.KeyName).SetIgnoreIfNull(true);
cm.MapMember(a => a.Position)
.SetSerializer(new EnumSerializer<DisplayConfigEnums.AxisPosition>(BsonType.String))
.SetDefaultValue(DisplayConfigEnums.AxisPosition.Left);
cm.MapMember(a => a.Min).SetIgnoreIfNull(true);
cm.MapMember(a => a.Max).SetIgnoreIfNull(true);
cm.MapMember(a => a.AxisLine).SetIgnoreIfNull(true);
cm.MapMember(a => a.AxisTick).SetIgnoreIfNull(true);
cm.MapMember(a => a.AxisLabel).SetIgnoreIfNull(true);
cm.MapMember(a => a.Silent).SetDefaultValue(true);
cm.MapMember(a => a.LabelFormat)
.SetSerializer(new EnumSerializer<DisplayConfigEnums.LabelFormat>(BsonType.String))
.SetDefaultValue(DisplayConfigEnums.LabelFormat.Hour);
cm.MapMember(a => a.Offset).SetDefaultValue(0.0);
cm.MapMember(a => a.CustomLabels).SetDefaultValue(new List<string>());
cm.MapMember(a => a.SortLabels).SetDefaultValue(false);
cm.MapMember(a => a.Show).SetDefaultValue(true);
cm.MapMember(a => a.Regularity)
.SetSerializer(new EnumSerializer<GroupedObservationEnum.Regularity>(BsonType.String))
.SetDefaultValue(GroupedObservationEnum.Regularity.Hour);
});
BsonClassMap.RegisterClassMap<AxisTick>(cm =>
{
cm.AutoMap();
cm.MapMember(a => a.Show).SetIgnoreIfNull(true);
cm.MapMember(a => a.Interval).SetIgnoreIfNull(true);
cm.MapMember(a => a.Length).SetIgnoreIfNull(true);
});
BsonClassMap.RegisterClassMap<AxisLabel>(cm =>
{
cm.AutoMap();
cm.MapMember(a => a.Show).SetIgnoreIfNull(true);
cm.MapMember(a => a.Color).SetIgnoreIfNull(true);
cm.MapMember(a => a.Margin).SetIgnoreIfNull(true);
cm.MapMember(a => a.FontSize).SetIgnoreIfNull(true);
cm.MapMember(a => a.Silent).SetIgnoreIfNull(true);
});
BsonClassMap.RegisterClassMap<AxisLineStyle>(cm =>
{
cm.AutoMap();
cm.MapMember(a => a.Color).SetIgnoreIfNull(true);
});
BsonClassMap.RegisterClassMap<AxisLine>(cm =>
{
cm.AutoMap();
cm.MapMember(a => a.Show).SetIgnoreIfNull(true);
cm.MapMember(a => a.LineStyle).SetIgnoreIfNull(true);
});
BsonClassMap.RegisterClassMap<SeriesConfigBase>(cm =>
{
cm.AutoMap();
// cm.SetIsRootClass(true);
// cm.AddKnownType(typeof(CandlestickSeriesConfig));
cm.MapMember(s => s.Key).SetElementName("key");
cm.MapMember(s => s.Color).SetElementName("color");
cm.MapMember(s => s.Type)
.SetDefaultValue(DisplayConfigEnums.SeriesType.Line)
.SetSerializer(new EnumSerializer<DisplayConfigEnums.SeriesType>(BsonType.String));
cm.MapMember(s => s.SourceType)
.SetDefaultValue(DisplayConfigEnums.SourceType.Obs)
.SetSerializer(new EnumSerializer<DisplayConfigEnums.SourceType>(BsonType.String));
cm.MapMember(s => s.AxesNames)
.SetDefaultValue(new List<string>());
cm.MapMember(s => s.ShowSymbol).SetDefaultValue(false);
cm.MapMember(s => s.ShowColorOnLegend).SetDefaultValue(false);
cm.MapMember(s => s.ShowOnLegend).SetDefaultValue(true);
cm.MapMember(s => s.Values)
.SetDefaultValue(GroupedObservationEnum.Result.Last)
.SetSerializer(new EnumSerializer<GroupedObservationEnum.Result>(BsonType.String));
cm.MapMember(s => s.MarkerIcon)
.SetDefaultValue(DisplayConfigEnums.MarkerIcon.None)
.SetSerializer(new EnumSerializer<DisplayConfigEnums.MarkerIcon>(BsonType.String));
cm.MapMember(s => s.VisualMap).SetIgnoreIfNull(true);
cm.MapMember(l => l.LineWidth).SetDefaultValue(2);
cm.MapMember(l => l.LineStyle).SetDefaultValue("solid");
cm.MapMember(v => v.Marker)
.SetDefaultValue(DisplayConfigEnums.MarkerIcon.Kangaroo)
.SetSerializer(new EnumSerializer<DisplayConfigEnums.MarkerIcon>(BsonType.String));
cm.MapMember(a => a.AboveBaselineColor).SetIgnoreIfDefault(true);
cm.MapMember(a => a.BelowBaselineColor).SetIgnoreIfDefault(true);
cm.MapMember(a => a.CandleKeyList).SetIgnoreIfDefault(true);
cm.MapMember(p => p.LineType).SetIgnoreIfNull(true);
});
// BsonClassMap.RegisterClassMap<LineSeriesConfig>(cm =>
// {
// cm.AutoMap();
// cm.MapMember(l => l.LineWidth).SetDefaultValue(2);
// cm.MapMember(l => l.LineStyle).SetDefaultValue("solid");
// });
// BsonClassMap.RegisterClassMap<VerticalMarkerSeriesConfig>(cm =>
// {
// cm.AutoMap();
// cm.MapMember(v => v.Marker)
// .SetDefaultValue(DisplayConfigEnums.MarkerIcon.Kangaroo)
// .SetSerializer(new EnumSerializer<DisplayConfigEnums.MarkerIcon>(BsonType.String));
// });
// BsonClassMap.RegisterClassMap<AreaSeriesConfig>(cm =>
// {
// cm.AutoMap();
// cm.MapMember(a => a.AboveBaselineColor).SetIgnoreIfDefault(true);
// cm.MapMember(a => a.BelowBaselineColor).SetIgnoreIfDefault(true);
// });
// BsonClassMap.RegisterClassMap<CandlestickSeriesConfig>(cm =>
// {
// cm.AutoMap();
// cm.MapMember(a => a.CandleKeyList).SetIgnoreIfDefault(true);
// });
// if (!BsonClassMap.IsClassMapRegistered(typeof(LineSeriesConfig)))
// {
// BsonClassMap.RegisterClassMap<LineSeriesConfig>(cm =>
// {
// cm.AutoMap();
// cm.MapMember(p => p.LineStyle).SetDefaultValue("solid");
// cm.MapMember(p => p.LineWidth).SetDefaultValue(2);
// cm.MapMember(p => p.LineType).SetIgnoreIfNull(true);
// });
// }
BsonClassMap.RegisterClassMap<Candle>(cm =>
{
cm.AutoMap();
cm.MapMember(a => a.Key).SetIgnoreIfDefault(true);
cm.MapMember(a => a.CandleValueType)
.SetSerializer(
new NullableSerializer<CandleValueType>(new EnumSerializer<CandleValueType>(BsonType.String)));
});
BsonClassMap.RegisterClassMap<VisualMap>(cm =>
{
cm.AutoMap();
cm.MapMember(v => v.Show).SetDefaultValue(false);
cm.MapMember(v => v.Dimension).SetDefaultValue(0);
cm.MapMember(v => v.SerieKey).SetIgnoreIfNull(true);
cm.MapMember(v => v.Pieces).SetDefaultValue(new List<Piece>());
});
}
if (!BsonClassMap.IsClassMapRegistered(typeof(LegendLayoutConfig)))
BsonClassMap.RegisterClassMap<LegendLayoutConfig>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.Rows).SetIgnoreIfNull(true);
});
if (!BsonClassMap.IsClassMapRegistered(typeof(LegendLayoutRow)))
BsonClassMap.RegisterClassMap<LegendLayoutRow>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.GrowPriority).SetIgnoreIfNull(true);
cm.MapMember(c => c.Columns).SetIgnoreIfNull(true);
});
if (!BsonClassMap.IsClassMapRegistered(typeof(LegendLayoutColumn)))
BsonClassMap.RegisterClassMap<LegendLayoutColumn>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.Key).SetIgnoreIfNull(true);
cm.MapMember(c => c.GrowPriority).SetIgnoreIfNull(true);
cm.MapMember(c => c.Label).SetIgnoreIfNull(true);
});
if (!BsonClassMap.IsClassMapRegistered(typeof(LegendLabel)))
BsonClassMap.RegisterClassMap<LegendLabel>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.Name).SetIgnoreIfNull(true);
cm.MapMember(c => c.ColorLabel).SetIgnoreIfNull(true);
cm.MapMember(c => c.ColorIcon).SetIgnoreIfNull(true);
cm.MapMember(c => c.ShowSymbol).SetIgnoreIfNull(true);
cm.MapMember(c => c.IconType).SetIgnoreIfNull(true)
.SetSerializer(new NullableSerializer<DisplayConfigEnums.ELegendIconType>(
new EnumSerializer<DisplayConfigEnums.ELegendIconType>(BsonType.String)));
});
if (!BsonClassMap.IsClassMapRegistered(typeof(Piece)))
BsonClassMap.RegisterClassMap<Piece>(cm =>
{
cm.AutoMap();
cm.MapMember(p => p.Opacity).SetIgnoreIfNull(true);
cm.MapMember(p => p.LineType)
.SetDefaultValue(DisplayConfigEnums.LineType.Solid)
.SetSerializer(new EnumSerializer<DisplayConfigEnums.LineType>(BsonType.String));
cm.MapMember(p => p.Color).SetIgnoreIfNull(true);
cm.MapMember(p => p.Symbol).SetIgnoreIfNull(true);
cm.MapMember(p => p.SymbolSize).SetIgnoreIfNull(true);
cm.MapMember(p => p.Eq).SetIgnoreIfNull(true);
cm.MapMember(p => p.Neq).SetIgnoreIfNull(true);
cm.MapMember(p => p.Gt).SetIgnoreIfNull(true);
cm.MapMember(p => p.Lt).SetIgnoreIfNull(true);
cm.MapMember(p => p.Gte).SetIgnoreIfNull(true);
cm.MapMember(p => p.Lte).SetIgnoreIfNull(true);
});
}
}
@@ -0,0 +1,39 @@
using adas_core.Domain.Models.MongoModels;
using adas_core.Infrastructure.Utils.MongoMaps.Interfaz;
using MongoDB.Bson.Serialization;
namespace adas_core.Infrastructure.Utils.MongoMaps;
public class HeaderMapContributor : IEntityMapContributor
{
public void RegisterMaps()
{
if (!BsonClassMap.IsClassMapRegistered(typeof(HeaderConfig)))
BsonClassMap.RegisterClassMap<HeaderConfig>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.PartnerLogo).SetDefaultValue(new HeaderConfig.HeaderItem()).SetIgnoreIfNull(true);
cm.MapMember(c => c.CompanyLogo).SetDefaultValue(new HeaderConfig.HeaderItem()).SetIgnoreIfNull(true);
cm.MapMember(c => c.CenterLogo).SetDefaultValue(new HeaderConfig.HeaderItem()).SetIgnoreIfNull(true);
cm.MapMember(c => c.MeddisLogo).SetDefaultValue(new HeaderConfig.HeaderItem()).SetIgnoreIfNull(true);
cm.MapMember(c => c.UnitName).SetDefaultValue(new HeaderConfig.HeaderItem()).SetIgnoreIfNull(true);
cm.MapMember(c => c.Cameras).SetDefaultValue(new HeaderConfig.HeaderItem()).SetIgnoreIfNull(true);
cm.MapMember(c => c.Sensors).SetDefaultValue(new HeaderConfig.HeaderItem()).SetIgnoreIfNull(true);
cm.MapMember(c => c.Fullscreen).SetDefaultValue(new HeaderConfig.HeaderItem()).SetIgnoreIfNull(true);
cm.MapMember(c => c.Sounds).SetDefaultValue(new HeaderConfig.HeaderItem()).SetIgnoreIfNull(true);
cm.MapMember(c => c.Sidebar).SetDefaultValue(new HeaderConfig.HeaderItem()).SetIgnoreIfNull(true);
cm.MapMember(c => c.CurrentDateTime).SetDefaultValue(new HeaderConfig.HeaderItem())
.SetIgnoreIfNull(true);
cm.MapMember(c => c.SectionTitle).SetDefaultValue(new HeaderConfig.HeaderItem()).SetIgnoreIfNull(true);
});
if (!BsonClassMap.IsClassMapRegistered(typeof(HeaderConfig.HeaderItem)))
BsonClassMap.RegisterClassMap<HeaderConfig.HeaderItem>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.LogoUrl).SetDefaultValue(() => null)
.SetIgnoreIfNull(true);
cm.MapMember(c => c.IsVisible).SetDefaultValue(true);
});
}
}
@@ -0,0 +1,9 @@
namespace adas_core.Infrastructure.Utils.MongoMaps.Interfaz;
/// <summary>
/// Interfaz para clases que contribuyen al registro de mapas de BSON.
/// </summary>
public interface IEntityMapContributor
{
void RegisterMaps();
}
@@ -0,0 +1,158 @@
using adas_core.Domain.Enums;
using adas_core.Domain.Models.Masters;
using adas_core.Infrastructure.Utils.MongoMaps.Interfaz;
using MongoDB.Bson;
using MongoDB.Bson.Serialization;
using MongoDB.Bson.Serialization.Serializers;
namespace adas_core.Infrastructure.Utils.MongoMaps;
public class MasterListMapContributor : IEntityMapContributor
{
public void RegisterMaps()
{
if (!BsonClassMap.IsClassMapRegistered(typeof(Element)))
BsonClassMap.RegisterClassMap<Element>(cm =>
{
cm.AutoMap();
cm.GetMemberMap(c => c.Title).SetDefaultValue(string.Empty);
cm.GetMemberMap(c => c.IsRequired).SetDefaultValue(false);
cm.GetMemberMap(c => c.IsList).SetDefaultValue(false);
cm.GetMemberMap(c => c.ListName).SetDefaultValue(string.Empty);
});
if (!BsonClassMap.IsClassMapRegistered(typeof(OptionListDetails)))
BsonClassMap.RegisterClassMap<OptionListDetails>(cm =>
{
cm.AutoMap();
cm.GetMemberMap(c => c.OptionType).SetIgnoreIfNull(true);
cm.GetMemberMap(c => c.Name).SetIgnoreIfNull(true);
cm.GetMemberMap(c => c.IconDefault).SetIgnoreIfNull(true);
cm.GetMemberMap(c => c.IconCategory).SetIgnoreIfNull(true);
cm.GetMemberMap(c => c.IconColor).SetIgnoreIfNull(true);
cm.GetMemberMap(c => c.Color).SetIgnoreIfNull(true);
cm.GetMemberMap(c => c.BgColor).SetIgnoreIfNull(true);
cm.GetMemberMap(c => c.Description).SetIgnoreIfNull(true);
});
if (!BsonClassMap.IsClassMapRegistered(typeof(MasterList)))
BsonClassMap.RegisterClassMap<MasterList>(cm =>
{
cm.AutoMap();
cm.UnmapMember(c => c.ManualObservationName);
cm.UnmapMember(c => c.AutoObservationName);
cm.MapIdMember(c => c.Id).SetElementName("_id");
cm.GetMemberMap(c => c.DefaultLocale).SetIgnoreIfNull(true).SetSerializer(
new NullableSerializer<LocaleEnum>(new EnumSerializer<LocaleEnum>(BsonType.String))
);
cm.GetMemberMap(c => c.Name).SetDefaultValue(string.Empty);
cm.GetMemberMap(c => c.Description).SetDefaultValue(string.Empty);
cm.GetMemberMap(c => c.OptionListDetails).SetIgnoreIfNull(true);
cm.GetMemberMap(c => c.CanAddElement).SetDefaultValue(false);
cm.MapMember(c => c.ListType)
.SetSerializer(new EnumSerializer<MasterListType>(BsonType.String));
cm.MapMember(c => c.Options).SetDefaultValue(new List<OptionList>());
});
if (!BsonClassMap.IsClassMapRegistered(typeof(LocaleItem)))
BsonClassMap.RegisterClassMap<LocaleItem>(cm =>
{
cm.AutoMap();
cm.GetMemberMap(c => c.Name).SetIgnoreIfNull(true);
});
if (!BsonClassMap.IsClassMapRegistered(typeof(Locale)))
BsonClassMap.RegisterClassMap<Locale>(cm =>
{
cm.AutoMap();
cm.GetMemberMap(c => c.Es).SetIgnoreIfNull(true);
cm.GetMemberMap(c => c.Pt).SetIgnoreIfNull(true);
cm.GetMemberMap(c => c.Eng).SetIgnoreIfNull(true);
cm.GetMemberMap(c => c.Ca).SetIgnoreIfNull(true);
cm.GetMemberMap(c => c.Zh).SetIgnoreIfNull(true);
});
if (!BsonClassMap.IsClassMapRegistered(typeof(OptionList)))
BsonClassMap.RegisterClassMap<OptionList>(cm =>
{
cm.AutoMap();
cm.MapIdMember(c => c.Id).SetElementName("_id").SetSerializer(new NullableSerializer<ObjectId>(new ObjectIdSerializer(BsonType.ObjectId)));;
cm.GetMemberMap(c => c.OptionType).SetIgnoreIfNull(true);
cm.GetMemberMap(c => c.Name).SetIgnoreIfNull(true);
cm.GetMemberMap(c => c.LocaleItems).SetIgnoreIfNull(true);
cm.GetMemberMap(c => c.IconDefault).SetIgnoreIfNull(true);
cm.GetMemberMap(c => c.IconCategory).SetIgnoreIfNull(true);
cm.GetMemberMap(c => c.IconColor).SetIgnoreIfNull(true);
cm.GetMemberMap(c => c.Color).SetIgnoreIfNull(true);
cm.GetMemberMap(c => c.BgColor).SetIgnoreIfNull(true);
cm.GetMemberMap(c => c.Description).SetIgnoreIfNull(true);
cm.GetMemberMap(c => c.InitDate).SetIgnoreIfNull(true);
cm.GetMemberMap(c => c.EndDate).SetIgnoreIfNull(true);
cm.GetMemberMap(c => c.IsDefault).SetIgnoreIfNull(true);
cm.SetDiscriminator(nameof(OptionList));
});
if (!BsonClassMap.IsClassMapRegistered(typeof(AltableOptionList)))
BsonClassMap.RegisterClassMap<AltableOptionList>(cm => { cm.AutoMap(); });
if (!BsonClassMap.IsClassMapRegistered(typeof(VisitOptionList)))
BsonClassMap.RegisterClassMap<VisitOptionList>(cm => { cm.AutoMap(); });
if (!BsonClassMap.IsClassMapRegistered(typeof(AccessControlList)))
BsonClassMap.RegisterClassMap<AccessControlList>(cm => { cm.AutoMap(); });
if (!BsonClassMap.IsClassMapRegistered(typeof(MobilityOptionList)))
BsonClassMap.RegisterClassMap<MobilityOptionList>(cm => { cm.AutoMap(); });
if (!BsonClassMap.IsClassMapRegistered(typeof(TherapeuticCeilingList)))
BsonClassMap.RegisterClassMap<TherapeuticCeilingList>(cm => { cm.AutoMap(); });
if (!BsonClassMap.IsClassMapRegistered(typeof(PassiveSittingList)))
BsonClassMap.RegisterClassMap<PassiveSittingList>(cm => { cm.AutoMap(); });
if (!BsonClassMap.IsClassMapRegistered(typeof(GenericList)))
BsonClassMap.RegisterClassMap<GenericList>(cm => { cm.AutoMap(); });
if (!BsonClassMap.IsClassMapRegistered(typeof(ProcedureList)))
BsonClassMap.RegisterClassMap<ProcedureList>(cm => { cm.AutoMap(); });
if (!BsonClassMap.IsClassMapRegistered(typeof(TestList)))
BsonClassMap.RegisterClassMap<TestList>(cm => { cm.AutoMap(); });
if (!BsonClassMap.IsClassMapRegistered(typeof(DiagnosisList)))
BsonClassMap.RegisterClassMap<DiagnosisList>(cm => { cm.AutoMap(); });
if (!BsonClassMap.IsClassMapRegistered(typeof(OriginList)))
BsonClassMap.RegisterClassMap<OriginList>(cm => { cm.AutoMap(); });
if (!BsonClassMap.IsClassMapRegistered(typeof(DestinationList)))
BsonClassMap.RegisterClassMap<DestinationList>(cm => { cm.AutoMap(); });
if (!BsonClassMap.IsClassMapRegistered(typeof(InternalDestinationList)))
BsonClassMap.RegisterClassMap<InternalDestinationList>(cm => { cm.AutoMap(); });
if (!BsonClassMap.IsClassMapRegistered(typeof(TreatmentList)))
BsonClassMap.RegisterClassMap<TreatmentList>(cm => { cm.AutoMap(); });
if (!BsonClassMap.IsClassMapRegistered(typeof(PatientStatusList)))
BsonClassMap.RegisterClassMap<PatientStatusList>(cm => { cm.AutoMap(); });
if (!BsonClassMap.IsClassMapRegistered(typeof(ServiceList)))
BsonClassMap.RegisterClassMap<ServiceList>(cm => { cm.AutoMap(); });
if (!BsonClassMap.IsClassMapRegistered(typeof(AllergyList)))
BsonClassMap.RegisterClassMap<AllergyList>(cm => { cm.AutoMap(); });
if (!BsonClassMap.IsClassMapRegistered(typeof(DoctorTypeList)))
BsonClassMap.RegisterClassMap<DoctorTypeList>(cm => { cm.AutoMap(); });
if (!BsonClassMap.IsClassMapRegistered(typeof(DoctorList)))
BsonClassMap.RegisterClassMap<DoctorList>(cm => { cm.AutoMap(); });
if (!BsonClassMap.IsClassMapRegistered(typeof(InsulationList)))
BsonClassMap.RegisterClassMap<InsulationList>(cm => { cm.AutoMap(); });
if (!BsonClassMap.IsClassMapRegistered(typeof(DischargeStatusList)))
BsonClassMap.RegisterClassMap<DischargeStatusList>(cm => { cm.AutoMap(); });
if (!BsonClassMap.IsClassMapRegistered(typeof(LanguageBarrierList)))
BsonClassMap.RegisterClassMap<LanguageBarrierList>(cm => { cm.AutoMap(); });
}
}
@@ -0,0 +1,28 @@
using adas_core.Domain.Models.MongoModels;
using adas_core.Infrastructure.Utils.MongoMaps.Interfaz;
using MongoDB.Bson.Serialization;
namespace adas_core.Infrastructure.Utils.MongoMaps;
public class NoticeControlMapContributor : IEntityMapContributor
{
public void RegisterMaps()
{
if (!BsonClassMap.IsClassMapRegistered(typeof(Notice)))
BsonClassMap.RegisterClassMap<Notice>(cm =>
{
cm.AutoMap();
cm.MapIdMember(c => c.Id).SetElementName("_id");
});
if (!BsonClassMap.IsClassMapRegistered(typeof(StaffInfo)))
BsonClassMap.RegisterClassMap<StaffInfo>(cm => { cm.AutoMap(); });
if (!BsonClassMap.IsClassMapRegistered(typeof(MedicalStaffConfig)))
BsonClassMap.RegisterClassMap<MedicalStaffConfig>(cm =>
{
cm.MapMember(c => c.HasTeams).SetIgnoreIfNull(true);
cm.MapMember(c => c.StaffAmount).SetIgnoreIfNull(true);
});
}
}
@@ -0,0 +1,27 @@
using adas_core.Domain.Models.MongoModels;
using adas_core.Infrastructure.Utils.MongoMaps.Interfaz;
using MongoDB.Bson.Serialization;
namespace adas_core.Infrastructure.Utils.MongoMaps;
public class ObsUnitMapContributor : IEntityMapContributor
{
public void RegisterMaps()
{
if (!BsonClassMap.IsClassMapRegistered(typeof(ConfigUnits)))
BsonClassMap.RegisterClassMap<ConfigUnits>(cm =>
{
cm.AutoMap();
cm.MapIdMember(c => c.Id).SetElementName("_id").SetDefaultValue(string.Empty);
cm.MapMember(c => c.Items).SetIgnoreIfNull(true);
});
if (!BsonClassMap.IsClassMapRegistered(typeof(ConfigUnitItem)))
BsonClassMap.RegisterClassMap<ConfigUnitItem>(cm =>
{
cm.AutoMap();
cm.GetMemberMap(c => c.Code).SetIgnoreIfNull(true);
cm.GetMemberMap(c => c.Value).SetIgnoreIfNull(true);
});
}
}
@@ -0,0 +1,289 @@
using adas_core.Domain.Enums;
using adas_core.Domain.Models;
using adas_core.Domain.Models.MongoModels;
using adas_core.Domain.Models.Observations;
using adas_core.Domain.Utils;
using adas_core.Infrastructure.Utils.MongoMaps.Interfaz;
using MongoDB.Bson;
using MongoDB.Bson.Serialization;
using MongoDB.Bson.Serialization.Serializers;
using static adas_core.Domain.Models.GroupedObservation;
namespace adas_core.Infrastructure.Utils.MongoMaps;
public class ObservationMapContributor : IEntityMapContributor
{
public void RegisterMaps()
{
if (!BsonClassMap.IsClassMapRegistered(typeof(BasePatientObservation)))
BsonClassMap.RegisterClassMap<BasePatientObservation>(cm =>
{
cm.AutoMap();
cm.MapIdMember(c => c.Id).SetElementName("_id");
cm.MapMember(c => c.PatientId).SetElementName("patientid");
cm.MapMember(c => c.UserId).SetIgnoreIfNull(true);
cm.MapMember(c => c.ClinicalEpisode).SetIgnoreIfNull(true);
cm.UnmapMember(c => c.Patient);
cm.MapMember(c => c.SystemId).SetIgnoreIfNull(true);
cm.MapMember(c => c.Code).SetIgnoreIfNull(true);
cm.MapMember(c => c.CodingSystem).SetIgnoreIfNull(true);
cm.MapMember(c => c.ParentData).SetIgnoreIfNull(true);
cm.MapMember(c => c.Time);
cm.MapMember(c => c.EndTime).SetIgnoreIfNull(true);
cm.MapMember(c => c.Name).SetIgnoreIfNull(true);
cm.MapMember(c => c.Units).SetIgnoreIfNull(true);
cm.UnmapMember(c => c.CheckObservations);
cm.UnmapMember(c => c.CreateObservation);
cm.MapMember(c => c.PatientId).SetElementName("patientid");
cm.MapMember(c => c.EndTime).SetIgnoreIfNull(true);
});
if (!BsonClassMap.IsClassMapRegistered(typeof(BasePatientObservationValue)))
BsonClassMap.RegisterClassMap<BasePatientObservationValue>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.Value)
.SetDefaultValue(new object())
.SetSerializer(new ComplexObjectValueTypeSerializer());
});
if (!BsonClassMap.IsClassMapRegistered(typeof(PatientObservation)))
BsonClassMap.RegisterClassMap<PatientObservation>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.Max).SetIgnoreIfNull(true);
cm.MapMember(c => c.Min).SetIgnoreIfNull(true);
cm.MapMember(c => c.MaxWarn).SetIgnoreIfNull(true);
cm.MapMember(c => c.MinWarn).SetIgnoreIfNull(true);
cm.MapMember(c => c.WarnColor).SetIgnoreIfNull(true);
cm.MapMember(c => c.AlertColor).SetIgnoreIfNull(true);
cm.UnmapMember(c => c.ShowOnExpired);
cm.MapMember(c => c.InsertMode)
.SetDefaultValue(ObservationEnum.InsertMode.Auto)
.SetSerializer(new EnumSerializer<ObservationEnum.InsertMode>(BsonType.String));
cm.UnmapMember(c => c.Persist);
cm.MapMember(c => c.ColorOnExpired).SetIgnoreIfNull(true);
cm.UnmapMember(c => c.MessageTime);
cm.MapMember(c => c.Result).SetIgnoreIfNull(true);
cm.MapMember(c => c.Status)
.SetDefaultValue(StatusEnum.Type.Ok)
.SetSerializer(new EnumSerializer<StatusEnum.Type>(BsonType.String));
cm.UnmapMember(c => c.Level);
cm.UnmapMember(c => c.Expires);
cm.MapMember(c => c.Expired).SetDefaultValue(false);
cm.UnmapMember(c => c.UiConfiguration);
cm.UnmapMember(c => c.Alarm);
});
if (!BsonClassMap.IsClassMapRegistered(typeof(ParentDataClass)))
BsonClassMap.RegisterClassMap<ParentDataClass>(cm =>
{
cm.AutoMap();
cm.GetMemberMap(c => c.Code).SetIgnoreIfNull(true);
cm.GetMemberMap(c => c.CodingSystem).SetIgnoreIfNull(true);
cm.GetMemberMap(c => c.Name).SetIgnoreIfNull(true);
});
if (!BsonClassMap.IsClassMapRegistered(typeof(ObservationData)))
BsonClassMap.RegisterClassMap<ObservationData>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.CodingSystem).SetIgnoreIfNull(true);
cm.MapMember(c => c.Code).SetIgnoreIfNull(true);
cm.MapMember(c => c.Text).SetIgnoreIfNull(true);
cm.MapMember(c => c.Time).SetIgnoreIfNull(true);
cm.MapMember(c => c.Value).SetIgnoreIfNull(true);
});
if (!BsonClassMap.IsClassMapRegistered(typeof(ObservationsRequest)))
BsonClassMap.RegisterClassMap<ObservationsRequest>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.PatientNumber).SetIgnoreIfNull(true);
cm.MapMember(c => c.ObservationNames).SetIgnoreIfNull(true);
cm.MapMember(c => c.StartTime).SetIgnoreIfNull(true);
cm.MapMember(c => c.EndTime).SetIgnoreIfNull(true);
cm.MapMember(c => c.PageNumber).SetDefaultValue(1);
cm.MapMember(c => c.PageSize).SetDefaultValue(10);
});
if (!BsonClassMap.IsClassMapRegistered(typeof(DemoConfig)))
BsonClassMap.RegisterClassMap<DemoConfig>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.ValueOption)
.SetIgnoreIfNull(true);
});
if (!BsonClassMap.IsClassMapRegistered(typeof(ConfigObservation)))
BsonClassMap.RegisterClassMap<ConfigObservation>(cm =>
{
cm.AutoMap();
cm.MapIdMember(c => c.Id).SetElementName("_id");
cm.MapMember(c => c.DemoConfig).SetIgnoreIfNull(true);
});
if (!BsonClassMap.IsClassMapRegistered(typeof(ConfigObservation)))
BsonClassMap.RegisterClassMap<ConfigObservation>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.Code).SetIgnoreIfNull(true);
cm.MapMember(c => c.CodingSystem).SetIgnoreIfNull(true);
cm.MapMember(c => c.OriginalName).SetIgnoreIfNull(true);
cm.MapMember(c => c.ParentCode).SetIgnoreIfNull(true);
cm.MapMember(c => c.ParentCodingSystem).SetIgnoreIfNull(true);
cm.MapMember(c => c.ParentName).SetIgnoreIfNull(true);
cm.MapMember(c => c.Name).SetIgnoreIfNull(true);
cm.MapMember(c => c.Units).SetIgnoreIfNull(true);
cm.MapMember(c => c.ArrowType)
.SetSerializer(new EnumSerializer<ObservationEnum.ArrowType>(BsonType.String))
.SetDefaultValue(ObservationEnum.ArrowType.Default);
cm.MapMember(c => c.ShowArrow).SetDefaultValue(true);
cm.MapMember(c => c.ShowValue).SetDefaultValue(true);
cm.MapMember(c => c.ForceUnits).SetDefaultValue(false);
cm.MapMember(c => c.MinAlert).SetIgnoreIfNull(true);
cm.MapMember(c => c.MaxAlert).SetIgnoreIfNull(true);
cm.MapMember(c => c.MaxWarn).SetIgnoreIfNull(true);
cm.MapMember(c => c.MinWarn).SetIgnoreIfNull(true);
cm.MapMember(c => c.WarnColor).SetIgnoreIfNull(true);
cm.MapMember(c => c.AlertColor).SetIgnoreIfNull(true);
cm.MapMember(c => c.AlertValues).SetIgnoreIfNull(true);
cm.MapMember(c => c.WarningValues).SetIgnoreIfNull(true);
cm.MapMember(c => c.ForceWarn).SetDefaultValue(false);
cm.MapMember(c => c.ForceAlert).SetDefaultValue(false);
cm.MapMember(c => c.Alert).SetIgnoreIfNull(true);
cm.MapMember(c => c.Expires).SetIgnoreIfNull(true);
cm.MapMember(c => c.ShowOnExpired).SetIgnoreIfDefault(true);
cm.MapMember(c => c.Persist).SetIgnoreIfNull(true);
cm.MapMember(c => c.ColorOnExpired).SetIgnoreIfNull(true);
cm.MapMember(c => c.RetentionPolicy)
.SetIgnoreIfNull(true)
.SetSerializer(
new NullableSerializer<RetentionPolicy>(new EnumSerializer<RetentionPolicy>(BsonType.String)));
cm.MapMember(c => c.RetentionPolicyValue).SetIgnoreIfNull(true);
cm.MapMember(c => c.LevelCondition).SetIgnoreIfNull(true);
cm.MapMember(c => c.Grouped).SetIgnoreIfNull(true);
cm.MapMember(c => c.UiConfiguration).SetIgnoreIfNull(true);
cm.MapMember(c => c.Alarm).SetIgnoreIfNull(true);
cm.MapMember(c => c.Description).SetIgnoreIfNull(true);
cm.MapMember(c => c.RequiredValue).SetIgnoreIfNull(true);
cm.MapMember(c => c.Preconditions).SetIgnoreIfNull(true);
cm.MapMember(c => c.CheckObservations).SetDefaultValue(false);
cm.MapMember(c => c.CreateObservation).SetIgnoreIfNull(true);
cm.MapMember(c => c.InsertMode)
.SetDefaultValue(ObservationEnum.InsertMode.Auto)
.SetSerializer(new EnumSerializer<ObservationEnum.InsertMode>(BsonType.String));
cm.MapMember(c => c.TimeFromMessageTime).SetIgnoreIfDefault(true);
cm.MapMember(c => c.ColorRanges).SetIgnoreIfNull(true);
});
if (!BsonClassMap.IsClassMapRegistered(typeof(ConfigObservation.ColorRange)))
BsonClassMap.RegisterClassMap<ConfigObservation.ColorRange>(cm =>
{
cm.AutoMap();
cm.MapMember(s => s.ValueType)
.SetIgnoreIfNull(true)
.SetSerializer(
new NullableSerializer<ObservationEnum.ValueType>(
new EnumSerializer<ObservationEnum.ValueType>(BsonType.String)));
cm.MapMember(s => s.Min).SetIgnoreIfNull(true);
cm.MapMember(s => s.Max).SetIgnoreIfNull(true);
cm.MapMember(s => s.MatchText).SetIgnoreIfNull(true);
cm.MapMember(s => s.MatchBoolean).SetIgnoreIfNull(true);
cm.MapMember(s => s.MinDate).SetIgnoreIfNull(true);
cm.MapMember(s => s.MaxDate).SetIgnoreIfNull(true);
cm.MapMember(s => s.Color).SetIgnoreIfNull(true);
cm.MapMember(s => s.Label).SetIgnoreIfNull(true);
});
if (!BsonClassMap.IsClassMapRegistered(typeof(GroupedObservation)))
BsonClassMap.RegisterClassMap<GroupedObservation>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.PatientId);
cm.MapMember(c => c.Name).SetDefaultValue(string.Empty);
cm.MapMember(c => c.Group).SetDefaultValue(string.Empty);
cm.MapMember(c => c.Observations).SetDefaultValue(new List<GroupedObservationObs>());
});
if (!BsonClassMap.IsClassMapRegistered(typeof(GroupedObservationObs)))
BsonClassMap.RegisterClassMap<GroupedObservationObs>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.Name).SetDefaultValue(string.Empty);
cm.MapMember(c => c.First).SetIgnoreIfNull(true);
cm.MapMember(c => c.Last).SetIgnoreIfNull(true);
cm.MapMember(c => c.Min).SetIgnoreIfNull(true);
cm.MapMember(c => c.Max).SetIgnoreIfNull(true);
cm.MapMember(c => c.MinAlert).SetIgnoreIfNull(true);
cm.MapMember(c => c.MaxAlert).SetIgnoreIfNull(true);
cm.MapMember(c => c.Average).SetIgnoreIfNull(true);
cm.MapMember(c => c.Sum).SetIgnoreIfNull(true);
cm.MapMember(c => c.Count).SetIgnoreIfNull(true);
cm.MapMember(c => c.HalfHour).SetIgnoreIfNull(true);
cm.MapMember(c => c.LastFilled).SetIgnoreIfNull(true);
cm.MapMember(c => c.Time);
cm.MapMember(c => c.Shift).SetIgnoreIfNull(true);
cm.MapMember(c => c.ShiftDate);
cm.MapMember(c => c.IsFilled);
});
if (!BsonClassMap.IsClassMapRegistered(typeof(GroupedObservationObsValue)))
BsonClassMap.RegisterClassMap<GroupedObservationObsValue>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.Type)
.SetDefaultValue(StatusEnum.Type.Ok)
.SetSerializer(new EnumSerializer<StatusEnum.Type>(BsonType.String));
cm.MapMember(c => c.Value);
cm.MapMember(c => c.Time).SetIgnoreIfNull(true);
});
if (!BsonClassMap.IsClassMapRegistered(typeof(PredictMedicationObservation)))
BsonClassMap.RegisterClassMap<PredictMedicationObservation>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.MedicineText).SetDefaultValue(string.Empty);
cm.MapMember(c => c.DegreeSimilarity);
});
if (!BsonClassMap.IsClassMapRegistered(typeof(ObservationTextRule)))
BsonClassMap.RegisterClassMap<ObservationTextRule>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.ValueType)
.SetDefaultValue(ObservationEnum.ValueType.String)
.SetSerializer(new EnumSerializer<ObservationEnum.ValueType>(BsonType.String));
cm.MapMember(c => c.Value).SetIgnoreIfNull(true);
cm.MapMember(c => c.MatchText).SetIgnoreIfNull(true);
cm.MapMember(c => c.MatchBoolean).SetIgnoreIfNull(true);
cm.MapMember(c => c.MatchNumber).SetIgnoreIfNull(true);
cm.MapMember(c => c.MatchDate).SetIgnoreIfNull(true);
cm.MapMember(c => c.Label).SetIgnoreIfNull(true);
cm.MapMember(c => c.MinDate).SetIgnoreIfNull(true);
cm.MapMember(c => c.MaxDate).SetIgnoreIfNull(true);
cm.MapMember(c => c.MinNum).SetIgnoreIfNull(true);
cm.MapMember(c => c.MaxNum).SetIgnoreIfNull(true);
});
if (!BsonClassMap.IsClassMapRegistered(typeof(ConditionsConfig)))
BsonClassMap.RegisterClassMap<ConditionsConfig>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.Condition).SetIgnoreIfNull(true);
cm.MapMember(c => c.FieldCondition).SetIgnoreIfNull(true);
});
}
}
@@ -0,0 +1,245 @@
using adas_core.Domain.Enums;
using adas_core.Domain.Models;
using adas_core.Domain.Models.MongoModels;
using adas_core.Infrastructure.Utils.MongoMaps.Interfaz;
using MongoDB.Bson;
using MongoDB.Bson.Serialization;
using MongoDB.Bson.Serialization.Options;
using MongoDB.Bson.Serialization.Serializers;
namespace adas_core.Infrastructure.Utils.MongoMaps;
public class PatientMapContributor : IEntityMapContributor
{
public void RegisterMaps()
{
if (!BsonClassMap.IsClassMapRegistered(typeof(HistoricalLocation)))
{
BsonClassMap.RegisterClassMap<HistoricalLocation>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.AdmTime);
cm.MapMember(c => c.PatientLocation);
});
}
if (!BsonClassMap.IsClassMapRegistered(typeof(Patient)))
BsonClassMap.RegisterClassMap<Patient>(cm =>
{
cm.AutoMap();
cm.MapIdMember(c => c.Id).SetElementName("_id");
cm.GetMemberMap(c => c.PatientNumber).SetIgnoreIfNull(true);
cm.GetMemberMap(c => c.PatientId).SetIgnoreIfNull(true);
cm.GetMemberMap(c => c.AdmTime).SetIgnoreIfNull(true);
cm.GetMemberMap(c => c.DischargeStatus).SetIgnoreIfNull(true);
cm.GetMemberMap(c => c.Altable).SetIgnoreIfNull(true);
cm.GetMemberMap(c => c.Origin).SetIgnoreIfNull(true);
cm.GetMemberMap(c => c.OriginAux).SetIgnoreIfNull(true);
cm.GetMemberMap(c => c.Diagnosis).SetIgnoreIfNull(true);
cm.GetMemberMap(c => c.DiagnosisAux).SetIgnoreIfNull(true);
cm.GetMemberMap(c => c.Visits).SetIgnoreIfNull(true);
cm.GetMemberMap(c => c.AccessControl).SetIgnoreIfNull(true);
cm.GetMemberMap(c => c.Insulation).SetIgnoreIfNull(true);
cm.GetMemberMap(c => c.PatientStatus).SetIgnoreIfNull(true);
cm.GetMemberMap(c => c.Mobility).SetIgnoreIfNull(true);
cm.GetMemberMap(c => c.TherapeuticCeiling).SetIgnoreIfNull(true);
cm.GetMemberMap(c => c.Procedures).SetIgnoreIfNull(true);
cm.GetMemberMap(c => c.Tests).SetIgnoreIfNull(true);
cm.GetMemberMap(c => c.Treatment).SetIgnoreIfNull(true);
cm.GetMemberMap(c => c.Doctors).SetIgnoreIfNull(true);
cm.GetMemberMap(c => c.Allergies).SetIgnoreIfNull(true);
cm.GetMemberMap(c => c.LanguageBarrier).SetIgnoreIfNull(true);
cm.GetMemberMap(c => c.PassiveSitting).SetIgnoreIfNull(true);
cm.GetMemberMap(c => c.DisTime).SetIgnoreIfNull(true);
cm.GetMemberMap(c => c.Person).SetIgnoreIfNull(true);
cm.GetMemberMap(c => c.AttendingDoctor).SetIgnoreIfNull(true);
cm.GetMemberMap(c => c.LastObservationDate).SetIgnoreIfNull(true);
cm.GetMemberMap(c => c.CreationDate).SetIgnoreIfNull(true);
cm.GetMemberMap(c => c.UpdateDate).SetIgnoreIfNull(true);
cm.GetMemberMap(c => c.ArchiveDate).SetIgnoreIfNull(true);
cm.GetMemberMap(c => c.PointOfCareId).SetIgnoreIfNull(true);
cm.GetMemberMap(c => c.UnitId).SetIgnoreIfNull(true);
cm.GetMemberMap(c => c.HistoricalLocations).SetIgnoreIfNull(true);
// No mapear estos campos
cm.UnmapMember(c => c.Bed);
cm.UnmapMember(c => c.UnitString);
cm.UnmapMember(c => c.Room);
cm.UnmapMember(c => c.PointOfCare);
cm.UnmapMember(c => c.Location);
});
if (!BsonClassMap.IsClassMapRegistered(typeof(Person)))
{
BsonClassMap.RegisterClassMap<Person>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.LastName).SetIgnoreIfNull(true);
cm.MapMember(c => c.FirstName).SetIgnoreIfNull(true);
cm.MapMember(c => c.SecondName).SetIgnoreIfNull(true);
cm.MapMember(c => c.BirthDate).SetIgnoreIfNull(true);
cm.MapMember(c => c.Language).SetIgnoreIfNull(true);
cm.MapMember(c => c.Gender)
.SetDefaultValue(PatientEnum.Gender.Unknown)
.SetSerializer(new EnumSerializer<PatientEnum.Gender>(BsonType.String));
cm.MapMember(c => c.Ids).SetIgnoreIfNull(true);
cm.MapMember(c => c.HistoricalIds)
.SetIgnoreIfNull(true);
});
BsonClassMap.RegisterClassMap<HistoricalId>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.Time).SetIgnoreIfNull(true);
cm.MapMember(c => c.PatientIds)
.SetSerializer(
new DictionaryInterfaceImplementerSerializer<Dictionary<string, string>, string, string>(
DictionaryRepresentation.Document))
.SetIgnoreIfNull(true);
});
}
if (!BsonClassMap.IsClassMapRegistered(typeof(PatientLocation)))
BsonClassMap.RegisterClassMap<PatientLocation>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.UnitName).SetIgnoreIfNull(true);
cm.MapMember(c => c.Bed).SetIgnoreIfNull(true);
cm.MapMember(c => c.Room).SetIgnoreIfNull(true);
});
if (!BsonClassMap.IsClassMapRegistered(typeof(PatientLocationAction)))
BsonClassMap.RegisterClassMap<PatientLocationAction>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.Location).SetIgnoreIfNull(true);
cm.MapMember(c => c.Action)
.SetIgnoreIfNull(true)
.SetSerializer(
new NullableSerializer<ActionsEnum.ResourceAction>(
new EnumSerializer<ActionsEnum.ResourceAction>(BsonType.String)));
});
if (!BsonClassMap.IsClassMapRegistered(typeof(PatientIncomeData)))
BsonClassMap.RegisterClassMap<PatientIncomeData>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.Diagnosis).SetIgnoreIfNull(true);
cm.MapMember(c => c.DiagnosisAux).SetIgnoreIfNull(true);
cm.MapMember(c => c.Origin).SetIgnoreIfNull(true);
cm.MapMember(c => c.OriginAux).SetIgnoreIfNull(true);
cm.MapMember(c => c.AdmTime).SetIgnoreIfNull(true);
});
if (!BsonClassMap.IsClassMapRegistered(typeof(PatientIcca)))
BsonClassMap.RegisterClassMap<PatientIcca>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.Location).SetDefaultValue(new PatientLocation(string.Empty, string.Empty));
cm.MapMember(c => c.PatientNumber).SetIgnoreIfNull(true);
cm.MapMember(c => c.PatientId).SetIgnoreIfNull(true);
cm.MapMember(c => c.AdmitTime).SetIgnoreIfNull(true);
});
if (!BsonClassMap.IsClassMapRegistered(typeof(PatientAllergiesValue)))
BsonClassMap.RegisterClassMap<PatientAllergiesValue>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.Notes).SetIgnoreIfNull(true);
cm.MapMember(c => c.Type).SetIgnoreIfNull(true);
cm.MapMember(c => c.Value).SetIgnoreIfNull(true);
});
if (!BsonClassMap.IsClassMapRegistered(typeof(PatientIntravenousLinesValue)))
BsonClassMap.RegisterClassMap<PatientIntravenousLinesValue>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.Type).SetIgnoreIfNull(true);
cm.MapMember(c => c.Duration).SetIgnoreIfNull(true);
cm.MapMember(c => c.Action).SetIgnoreIfNull(true);
cm.MapMember(c => c.Location).SetIgnoreIfNull(true);
cm.MapMember(c => c.InsertTime).SetIgnoreIfNull(true);
cm.MapMember(c => c.RemoveTime).SetIgnoreIfNull(true);
});
if (!BsonClassMap.IsClassMapRegistered(typeof(PatientDiagnosis)))
BsonClassMap.RegisterClassMap<PatientDiagnosis>(cm =>
{
cm.AutoMap();
cm.SetIgnoreExtraElements(true);
cm.MapIdMember(c => c.Id).SetElementName("_id");
cm.MapMember(c => c.PatientId);
cm.MapMember(c => c.Time);
cm.MapMember(c => c.UpdateDate).SetIgnoreIfNull(true);
cm.UnmapMember(c => c.MessageTime);
cm.MapMember(c => c.CodingSystem).SetIgnoreIfNull(true);
cm.MapMember(c => c.Description).SetIgnoreIfNull(true);
cm.MapMember(c => c.Label).SetIgnoreIfNull(true);
cm.MapMember(c => c.Code).SetIgnoreIfNull(true);
cm.MapMember(c => c.State).SetIgnoreIfNull(true);
cm.MapMember(c => c.Category).SetIgnoreIfNull(true);
cm.MapMember(c => c.StartTime).SetIgnoreIfNull(true);
cm.MapMember(c => c.EndTime).SetIgnoreIfNull(true);
cm.UnmapMember(c => c.DiagnosisCode);
cm.UnmapMember(c => c.DiagnosisSystem);
});
if (!BsonClassMap.IsClassMapRegistered(typeof(PatientDrainagesValue)))
BsonClassMap.RegisterClassMap<PatientDrainagesValue>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.Type).SetIgnoreIfNull(true);
cm.MapMember(c => c.Location).SetIgnoreIfNull(true);
cm.MapMember(c => c.Volume).SetIgnoreIfNull(true);
cm.MapMember(c => c.Height).SetIgnoreIfNull(true);
});
if (!BsonClassMap.IsClassMapRegistered(typeof(PatientCarePlan)))
BsonClassMap.RegisterClassMap<PatientCarePlan>(cm =>
{
cm.AutoMap();
cm.MapIdMember(c => c.Id).SetElementName("_id");
cm.MapMember(c => c.PatientId);
cm.MapMember(c => c.PointOfCareId).SetIgnoreIfNull(true);
cm.MapMember(c => c.PatientNumber).SetIgnoreIfNull(true);
cm.MapMember(c => c.UserId).SetIgnoreIfNull(true);
cm.MapMember(c => c.CarePlan).SetIgnoreIfNull(true);
cm.MapMember(c => c.Description).SetIgnoreIfNull(true);
cm.MapMember(c => c.Time).SetIgnoreIfNull(true);
cm.MapMember(c => c.Action)
.SetIgnoreIfNull(true)
.SetSerializer(
new NullableSerializer<ActionsEnum.CrudAction>(
new EnumSerializer<ActionsEnum.CrudAction>(BsonType.String)));
});
if (!BsonClassMap.IsClassMapRegistered(typeof(Admission)))
BsonClassMap.RegisterClassMap<Admission>(cm =>
{
cm.AutoMap();
cm.MapIdMember(c => c.Id).SetElementName("_id");
cm.UnmapMember(c => c.PatientLocation);
});
if (!BsonClassMap.IsClassMapRegistered(typeof(Discharge)))
BsonClassMap.RegisterClassMap<Discharge>(cm =>
{
cm.AutoMap();
cm.MapIdMember(c => c.Id).SetElementName("_id");
cm.UnmapMember(c => c.Patient);
cm.UnmapMember(c => c.PatientLocation);
cm.MapMember(c => c.MedicalDischarge).SetIgnoreIfNull(true);
cm.MapMember(c => c.AdminDischarge).SetIgnoreIfNull(true);
cm.MapMember(c => c.NurseDischarge).SetIgnoreIfNull(true);
});
}
}
@@ -0,0 +1,96 @@
using adas_core.Domain.Enums;
using adas_core.Domain.Models;
using adas_core.Domain.Models.MongoModels;
using adas_core.Infrastructure.Utils.MongoMaps.Interfaz;
using MongoDB.Bson;
using MongoDB.Bson.Serialization;
using MongoDB.Bson.Serialization.Serializers;
using LightBeacon = adas_core.Domain.Models.MongoModels.LightBeacon;
namespace adas_core.Infrastructure.Utils.MongoMaps;
public class PoCMapContributor : IEntityMapContributor
{
public void RegisterMaps()
{
if (!BsonClassMap.IsClassMapRegistered(typeof(PointOfCare)))
BsonClassMap.RegisterClassMap<PointOfCare>(cm =>
{
cm.AutoMap();
cm.MapIdMember(c => c.Id).SetElementName("_id");
cm.MapMember(c => c.Room).SetDefaultValue(string.Empty);
cm.MapMember(c => c.Bed).SetDefaultValue(string.Empty);
cm.MapMember(c => c.Hall).SetIgnoreIfNull(true);
cm.MapMember(c => c.UnitId);
cm.MapMember(c => c.Configuration).SetIgnoreIfNull(true);
cm.MapMember(c => c.Status)
.SetSerializer(new EnumSerializer<StatusEnum.PointOfCare>(BsonType.String));
cm.MapMember(c => c.AdmissionId).SetIgnoreIfNull(true);
cm.MapMember(c => c.IsActive).SetIgnoreIfNull(true);
cm.MapMember(c => c.IsVisible).SetIgnoreIfNull(true);
cm.UnmapMember(c => c.UnitName);
cm.UnmapMember(c => c.Unit);
cm.UnmapMember(c => c.Location);
cm.UnmapMember(c => c.Observations);
cm.UnmapMember(c => c.HasPatient);
cm.UnmapMember(c => c.Patientid);
cm.UnmapMember(c => c.Patient);
cm.UnmapMember(c => c.Admission);
});
if (!BsonClassMap.IsClassMapRegistered(typeof(PointOfCareConfiguration)))
BsonClassMap.RegisterClassMap<PointOfCareConfiguration>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.BeaconIdList)
.SetDefaultValue(new List<ObjectId>());
cm.MapMember(c => c.CameraIdList)
.SetDefaultValue(new List<ObjectId>());
cm.MapMember(c => c.RelayIdList).SetIgnoreIfNull(true);
cm.MapMember(c => c.Type).SetIgnoreIfNull(true);
cm.MapMember(c => c.Id).SetIgnoreIfNull(true);
cm.MapMember(c => c.BeaconList)
.SetIgnoreIfNull(true)
.SetIsRequired(false);
cm.MapMember(c => c.CameraList)
.SetIgnoreIfNull(true)
.SetIsRequired(false);
cm.MapMember(c => c.RelayList)
.SetIgnoreIfNull(true)
.SetIsRequired(false);
});
if (!BsonClassMap.IsClassMapRegistered(typeof(PoCMapping)))
BsonClassMap.RegisterClassMap<PoCMapping>(cm =>
{
cm.AutoMap();
cm.MapIdMember(c => c.Id).SetElementName("_id");
cm.MapMember(c => c.PointOfCares).SetDefaultValue(new List<PoCMappingItem>());
});
if (!BsonClassMap.IsClassMapRegistered(typeof(PoCMappingItem)))
BsonClassMap.RegisterClassMap<PoCMappingItem>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.NewPoC).SetElementName("new");
cm.MapMember(c => c.OriginalPoC).SetElementName("original");
cm.MapMember(c => c.Beds).SetDefaultValue(new List<List<string>>());
});
if (!BsonClassMap.IsClassMapRegistered(typeof(PoCSettings)))
BsonClassMap.RegisterClassMap<PoCSettings>(cm =>
{
cm.AutoMap();
cm.MapIdMember(c => c.Id).SetElementName("_id");
cm.MapMember(c => c.PatientLocation).SetIgnoreIfNull(true);
cm.MapMember(c => c.ManualRelayStatus)
.SetIgnoreIfNull(true)
.SetSerializer(
new NullableSerializer<RelayEnum.Status>(
new EnumSerializer<RelayEnum.Status>(BsonType.String)));
});
}
}
@@ -0,0 +1,380 @@
using adas_core.Domain.Enums;
using adas_core.Domain.Models.MongoModels;
using adas_core.Domain.Models.Pumps;
using adas_core.Infrastructure.Utils.MongoMaps.Interfaz;
using MongoDB.Bson;
using MongoDB.Bson.Serialization;
using MongoDB.Bson.Serialization.Serializers;
namespace adas_core.Infrastructure.Utils.MongoMaps
{
public class PumpMapContributor : IEntityMapContributor
{
public void RegisterMaps()
{
// ============================================================
// CommonPumpTypes: PumpValue
// ============================================================
if (!BsonClassMap.IsClassMapRegistered(typeof(CommonPumpTypes.PumpValue)))
{
BsonClassMap.RegisterClassMap<CommonPumpTypes.PumpValue>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.Value).SetIgnoreIfNull(true);
cm.MapMember(c => c.Units).SetIgnoreIfNull(true);
});
}
// ============================================================
// CommonPumpTypes: SyringeDetails
// ============================================================
if (!BsonClassMap.IsClassMapRegistered(typeof(CommonPumpTypes.SyringeDetails)))
{
BsonClassMap.RegisterClassMap<CommonPumpTypes.SyringeDetails>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.Type).SetIgnoreIfNull(true);
cm.MapMember(c => c.Manufacturer).SetIgnoreIfNull(true);
cm.MapMember(c => c.Volume).SetIgnoreIfNull(true);
});
}
// ============================================================
// PatientPumpObservation (nuevo modelo simplificado)
// ============================================================
if (!BsonClassMap.IsClassMapRegistered(typeof(PumpObservation)))
{
BsonClassMap.RegisterClassMap<PumpObservation>(cm =>
{
cm.AutoMap();
cm.MapIdMember(c => c.Id).SetElementName("_id");
// Identificadores
cm.MapMember(c => c.DeviceId).SetIgnoreIfNull(true);
cm.MapMember(c => c.RackId).SetIgnoreIfNull(true);
cm.MapMember(c => c.DeviceTypeMdc).SetIgnoreIfNull(true);
cm.MapMember(c => c.InfusionId).SetIgnoreIfNull(true);
cm.MapMember(c => c.PatientId).SetIgnoreIfNull(true).SetElementName("patientid");
//campos para Alaris
cm.MapMember(c => c.Pressure).SetIgnoreIfNull(true);
cm.MapMember(c => c.DiluentVolume).SetIgnoreIfNull(true);
cm.MapMember(c => c.PatientHeight).SetIgnoreIfNull(true);
cm.MapMember(c => c.BasalRate).SetIgnoreIfNull(true);
cm.MapMember(c => c.TotalAux).SetIgnoreIfNull(true);
cm.MapMember(c => c.GatewayNumber).SetIgnoreIfNull(true);
cm.MapMember(c => c.Number).SetIgnoreIfNull(true);
cm.MapMember(c => c.Total).SetIgnoreIfNull(true);
cm.MapMember(c => c.IsAux).SetIgnoreIfNull(true);
cm.MapMember(c => c.Code).SetIgnoreIfNull(true);
cm.MapMember(c => c.Name).SetIgnoreIfNull(true);
cm.UnmapMember(c => c.UiConfiguration);
cm.MapMember(c => c.AlarmMode)
.SetIgnoreIfNull(true)
.SetSerializer(new NullableSerializer<PumpEnum.AlarmMode>(
new EnumSerializer<PumpEnum.AlarmMode>(BsonType.String)));
// Tiempo
cm.MapMember(c => c.Time).SetIgnoreIfNull(true);
cm.MapMember(c => c.MessageType)
.SetIgnoreIfNull(true)
.SetSerializer(new EnumSerializer<PumpEnum.PumpMessageType>(BsonType.String));
// Estado de infusión
cm.MapMember(c => c.IsInfusing).SetIgnoreIfNull(true);
cm.MapMember(c => c.InfusingStatus)
.SetIgnoreIfNull(true)
.SetSerializer(new NullableSerializer<PumpEnum.InfusingStatus>(
new EnumSerializer<PumpEnum.InfusingStatus>(BsonType.String)));
cm.MapMember(c => c.Status)
.SetIgnoreIfNull(true)
.SetSerializer(new NullableSerializer<PumpEnum.Status>(
new EnumSerializer<PumpEnum.Status>(BsonType.String)));
cm.MapMember(c => c.PumpMode)
.SetIgnoreIfNull(true)
.SetSerializer(new NullableSerializer<PumpEnum.Mode>(
new EnumSerializer<PumpEnum.Mode>(BsonType.String)));
cm.MapMember(c => c.ActiveSourceInfo).SetIgnoreIfNull(true);
cm.MapMember(c => c.InfusionModeDetail).SetIgnoreIfNull(true);
cm.MapMember(c => c.NotDeliveringReason).SetIgnoreIfNull(true);
cm.MapMember(c => c.Source).SetIgnoreIfNull(true);
// Métricas
cm.MapMember(c => c.FlowFluid).SetIgnoreIfNull(true);
cm.MapMember(c => c.Rate).SetIgnoreIfNull(true);
cm.MapMember(c => c.VolumeInfused).SetIgnoreIfNull(true);
cm.MapMember(c => c.FluidDelivTotal).SetIgnoreIfNull(true);
cm.MapMember(c => c.FluidDelivTotalSet).SetIgnoreIfNull(true);
cm.MapMember(c => c.VolumeRemaining).SetIgnoreIfNull(true);
cm.MapMember(c => c.Vtbi).SetIgnoreIfNull(true);
cm.MapMember(c => c.TimeRemaining).SetIgnoreIfNull(true);
cm.MapMember(c => c.TimeProgrammed).SetIgnoreIfNull(true);
// Medicación
cm.MapMember(c => c.DrugName).SetIgnoreIfNull(true);
cm.MapMember(c => c.DrugId).SetIgnoreIfNull(true);
cm.MapMember(c => c.Concentration).SetIgnoreIfNull(true);
cm.MapMember(c => c.DoseRate).SetIgnoreIfNull(true);
cm.MapMember(c => c.DrugAmount).SetIgnoreIfNull(true);
cm.MapMember(c => c.DrugDoseDelivered).SetIgnoreIfNull(true);
// Paciente
cm.MapMember(c => c.PatientWeight).SetIgnoreIfNull(true);
cm.MapMember(c => c.Syringe).SetIgnoreIfNull(true);
// Ubicación
cm.MapMember(c => c.DeviceIp).SetIgnoreIfNull(true);
cm.MapMember(c => c.PillarAssembly).SetIgnoreIfNull(true);
cm.MapMember(c => c.PillarRackSlot).SetIgnoreIfNull(true);
// ALARMAS
cm.MapMember(c => c.AlarmType)
.SetIgnoreIfNull(true)
.SetSerializer(new NullableSerializer<PumpEnum.AlarmType>(
new EnumSerializer<PumpEnum.AlarmType>(BsonType.String)));
cm.MapMember(c => c.AlarmDescription).SetIgnoreIfNull(true);
cm.MapMember(c => c.AlarmState).SetIgnoreIfNull(true);
cm.MapMember(c => c.AlarmInactivationState).SetIgnoreIfNull(true);
cm.MapMember(c => c.AlarmPriority).SetIgnoreIfNull(true);
cm.MapMember(c => c.AlarmTypeMdc).SetIgnoreIfNull(true);
cm.MapMember(c => c.EventPhase)
.SetIgnoreIfNull(true)
.SetSerializer(new NullableSerializer<PumpEnum.EventPhase>(
new EnumSerializer<PumpEnum.EventPhase>(BsonType.String)));
cm.MapMember(c => c.AlertSourceMdc).SetIgnoreIfNull(true);
// EVENTOS (PCD-10)
cm.MapMember(c => c.Event)
.SetIgnoreIfNull(true)
.SetSerializer(new NullableSerializer<PumpEnum.Event>(
new EnumSerializer<PumpEnum.Event>(BsonType.String)));
});
}
// ============================================================
// PumpState
// ============================================================
if (!BsonClassMap.IsClassMapRegistered(typeof(PumpState)))
{
BsonClassMap.RegisterClassMap<PumpState>(cm =>
{
cm.AutoMap();
cm.MapIdMember(c => c.Id).SetElementName("_id");
cm.MapMember(c => c.DeviceId).SetIgnoreIfNull(true);
cm.MapMember(c => c.RackId).SetIgnoreIfNull(true);
cm.MapMember(c => c.DeviceTypeMdc).SetIgnoreIfNull(true);
cm.MapMember(c => c.DeviceIp).SetIgnoreIfNull(true);
cm.MapMember(c => c.PillarAssembly).SetIgnoreIfNull(true);
cm.MapMember(c => c.PillarRackSlot).SetIgnoreIfNull(true);
cm.MapMember(c => c.InfusionId).SetIgnoreIfNull(true);
cm.MapMember(c => c.PatientId).SetIgnoreIfNull(true);
cm.MapMember(c => c.LastUpdated).SetIgnoreIfNull(true);
// Estado
cm.MapMember(c => c.IsInfusing).SetIgnoreIfNull(true);
cm.MapMember(c => c.InfusingStatus)
.SetIgnoreIfNull(true)
.SetSerializer(new NullableSerializer<PumpEnum.InfusingStatus>(
new EnumSerializer<PumpEnum.InfusingStatus>(BsonType.String)));
cm.MapMember(c => c.Status)
.SetIgnoreIfNull(true)
.SetSerializer(new NullableSerializer<PumpEnum.Status>(
new EnumSerializer<PumpEnum.Status>(BsonType.String)));
cm.MapMember(c => c.PumpMode)
.SetIgnoreIfNull(true)
.SetSerializer(new NullableSerializer<PumpEnum.Mode>(
new EnumSerializer<PumpEnum.Mode>(BsonType.String)));
cm.MapMember(c => c.InfusionModeDetail).SetIgnoreIfNull(true);
cm.MapMember(c => c.ActiveSourceInfo).SetIgnoreIfNull(true);
cm.MapMember(c => c.NotDeliveringReason).SetIgnoreIfNull(true);
cm.MapMember(c => c.Source).SetIgnoreIfNull(true);
// Métricas
cm.MapMember(c => c.FlowFluid).SetIgnoreIfNull(true);
cm.MapMember(c => c.Rate).SetIgnoreIfNull(true);
cm.MapMember(c => c.VolumeInfused).SetIgnoreIfNull(true);
cm.MapMember(c => c.FluidDelivTotal).SetIgnoreIfNull(true);
cm.MapMember(c => c.FluidDelivTotalSet).SetIgnoreIfNull(true);
cm.MapMember(c => c.VolumeRemaining).SetIgnoreIfNull(true);
cm.MapMember(c => c.Vtbi).SetIgnoreIfNull(true);
cm.MapMember(c => c.TimeRemaining).SetIgnoreIfNull(true);
cm.MapMember(c => c.TimeProgrammed).SetIgnoreIfNull(true);
// Medicación
cm.MapMember(c => c.DrugName).SetIgnoreIfNull(true);
cm.MapMember(c => c.DrugId).SetIgnoreIfNull(true);
cm.MapMember(c => c.Concentration).SetIgnoreIfNull(true);
cm.MapMember(c => c.DoseRate).SetIgnoreIfNull(true);
cm.MapMember(c => c.DrugAmount).SetIgnoreIfNull(true);
cm.MapMember(c => c.DrugDoseDelivered).SetIgnoreIfNull(true);
cm.MapMember(c => c.PatientWeight).SetIgnoreIfNull(true);
cm.MapMember(c => c.Syringe).SetIgnoreIfNull(true);
// Última alarma resumen
cm.MapMember(c => c.AlarmType)
.SetIgnoreIfNull(true)
.SetSerializer(new NullableSerializer<PumpEnum.AlarmType>(
new EnumSerializer<PumpEnum.AlarmType>(BsonType.String)));
cm.MapMember(c => c.AlarmDescription).SetIgnoreIfNull(true);
cm.MapMember(c => c.AlarmState).SetIgnoreIfNull(true);
cm.MapMember(c => c.AlarmInactivationState).SetIgnoreIfNull(true);
cm.MapMember(c => c.AlarmPriority).SetIgnoreIfNull(true);
cm.MapMember(c => c.AlarmCodeMdc).SetIgnoreIfNull(true);
cm.MapMember(c => c.Event)
.SetIgnoreIfNull(true)
.SetSerializer(new NullableSerializer<PumpEnum.Event>(
new EnumSerializer<PumpEnum.Event>(BsonType.String)));
cm.MapMember(c => c.EventPhase)
.SetIgnoreIfNull(true)
.SetSerializer(new NullableSerializer<PumpEnum.EventPhase>(
new EnumSerializer<PumpEnum.EventPhase>(BsonType.String)));
// Relay / Comm
cm.MapMember(c => c.CommStatus).SetIgnoreIfNull(true);
cm.MapMember(c => c.RelayState).SetIgnoreIfNull(true);
cm.MapMember(c => c.RelayGuid).SetIgnoreIfNull(true);
});
}
// ============================================================
// PumpAlarmEvent
// ============================================================
if (!BsonClassMap.IsClassMapRegistered(typeof(PumpAlarmEvent)))
{
BsonClassMap.RegisterClassMap<PumpAlarmEvent>(cm =>
{
cm.AutoMap();
cm.MapIdMember(c => c.Id).SetElementName("_id");
cm.MapMember(c => c.DeviceId).SetIgnoreIfNull(true);
cm.MapMember(c => c.RackId).SetIgnoreIfNull(true);
cm.MapMember(c => c.DeviceTypeMdc).SetIgnoreIfNull(true);
cm.MapMember(c => c.InfusionId).SetIgnoreIfNull(true);
cm.MapMember(c => c.PatientId).SetIgnoreIfNull(true);
cm.MapMember(c => c.Time).SetIgnoreIfNull(true);
cm.MapMember(c => c.AlarmType)
.SetIgnoreIfNull(true)
.SetSerializer(new NullableSerializer<PumpEnum.AlarmType>(
new EnumSerializer<PumpEnum.AlarmType>(BsonType.String)));
cm.MapMember(c => c.AlarmDescription).SetIgnoreIfNull(true);
cm.MapMember(c => c.AlarmState).SetIgnoreIfNull(true);
cm.MapMember(c => c.AlarmInactivationState).SetIgnoreIfNull(true);
cm.MapMember(c => c.AlarmPriority).SetIgnoreIfNull(true);
cm.MapMember(c => c.AlarmTypeMdc).SetIgnoreIfNull(true);
cm.MapMember(c => c.EventPhase)
.SetIgnoreIfNull(true)
.SetSerializer(new NullableSerializer<PumpEnum.EventPhase>(
new EnumSerializer<PumpEnum.EventPhase>(BsonType.String)));
cm.MapMember(c => c.AlertSourceMdc).SetIgnoreIfNull(true);
cm.MapMember(c => c.DeviceIp).SetIgnoreIfNull(true);
cm.MapMember(c => c.PillarAssembly).SetIgnoreIfNull(true);
cm.MapMember(c => c.PillarRackSlot).SetIgnoreIfNull(true);
});
}
// ============================================================
// PumpAlarmState
// ============================================================
if (!BsonClassMap.IsClassMapRegistered(typeof(PumpAlarmState)))
{
BsonClassMap.RegisterClassMap<PumpAlarmState>(cm =>
{
cm.AutoMap();
cm.MapIdMember(c => c.Id).SetElementName("_id");
cm.MapMember(c => c.DeviceId).SetIgnoreIfNull(true);
cm.MapMember(c => c.PatientId).SetIgnoreIfNull(true);
cm.MapMember(c => c.AlarmType)
.SetIgnoreIfNull(true)
.SetSerializer(new NullableSerializer<PumpEnum.AlarmType>(
new EnumSerializer<PumpEnum.AlarmType>(BsonType.String)));
cm.MapMember(c => c.AlarmCodeMdc).SetIgnoreIfNull(true);
cm.MapMember(c => c.AlarmDescription).SetIgnoreIfNull(true);
cm.MapMember(c => c.AlarmPriority).SetIgnoreIfNull(true);
cm.MapMember(c => c.AlarmState).SetIgnoreIfNull(true);
cm.MapMember(c => c.LastPhase)
.SetIgnoreIfNull(true)
.SetSerializer(new NullableSerializer<PumpEnum.EventPhase>(
new EnumSerializer<PumpEnum.EventPhase>(BsonType.String)));
cm.MapMember(c => c.FirstSeen).SetIgnoreIfNull(true);
cm.MapMember(c => c.LastUpdated).SetIgnoreIfNull(true);
cm.MapMember(c => c.AlertSourceMdc).SetIgnoreIfNull(true);
cm.MapMember(c => c.InfusionId).SetIgnoreIfNull(true);
});
}
// ============================================================
// ConfigPumps
// ============================================================
if (!BsonClassMap.IsClassMapRegistered(typeof(ConfigPumps)))
{
BsonClassMap.RegisterClassMap<ConfigPumps>(cm =>
{
cm.AutoMap();
cm.MapIdMember(c => c.Id).SetElementName("_id");
cm.MapMember(c => c.Items).SetIgnoreIfNull(true);
});
}
// ============================================================
// ConfigPumpItem
// ============================================================
if (!BsonClassMap.IsClassMapRegistered(typeof(ConfigPumpItem)))
{
BsonClassMap.RegisterClassMap<ConfigPumpItem>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.AlarmType)
.SetIgnoreIfNull(true)
.SetSerializer(new NullableSerializer<PumpEnum.AlarmType>(
new EnumSerializer<PumpEnum.AlarmType>(BsonType.String)));
cm.MapMember(c => c.UiConfiguration).SetIgnoreIfNull(true);
cm.MapMember(c => c.Type)
.SetIgnoreIfNull(true)
.SetSerializer(new NullableSerializer<PumpEnum.PumpMessageType>(
new EnumSerializer<PumpEnum.PumpMessageType>(BsonType.String)));
cm.MapMember(c => c.RetentionPolicy).SetIgnoreIfNull(true);
cm.MapMember(c => c.RetentionPolicyValue).SetIgnoreIfNull(true);
});
}
}
}
}
@@ -0,0 +1,48 @@
using adas_core.Domain.Enums;
using adas_core.Domain.Models.MongoModels;
using adas_core.Infrastructure.Utils.MongoMaps.Interfaz;
using MongoDB.Bson;
using MongoDB.Bson.Serialization;
using MongoDB.Bson.Serialization.Serializers;
namespace adas_core.Infrastructure.Utils.MongoMaps;
public class RelayContributor : IEntityMapContributor
{
public void RegisterMaps()
{
if (!BsonClassMap.IsClassMapRegistered(typeof(Relay)))
BsonClassMap.RegisterClassMap<Relay>(cm =>
{
cm.AutoMap();
cm.MapIdMember(c => c.Id).SetElementName("_id");
cm.MapMember(c => c.Type)
.SetDefaultValue(RelayEnum.Type.Door)
.SetSerializer(new EnumSerializer<RelayEnum.Type>(BsonType.String));
cm.MapMember(c => c.Driver).SetIgnoreIfNull(true);
cm.MapMember(c => c.Ip).SetIgnoreIfNull(true);
cm.MapMember(c => c.Port).SetDefaultValue(0);
cm.MapMember(c => c.RelayNumber).SetDefaultValue(1);
cm.MapMember(c => c.RelayName).SetIgnoreIfNull(true);
cm.MapMember(c => c.Total).SetDefaultValue(1);
cm.MapMember(c => c.RefreshTime).SetDefaultValue(60);
cm.MapMember(c => c.Open).SetDefaultValue(false);
cm.MapMember(c => c.Status)
.SetDefaultValue(RelayEnum.Status.NotInitialized)
.SetSerializer(new EnumSerializer<RelayEnum.Status>(BsonType.String));
cm.MapMember(c => c.Username).SetIgnoreIfNull(true);
cm.MapMember(c => c.Password).SetIgnoreIfNull(true);
cm.MapMember(c => c.Mode)
.SetDefaultValue(RelayEnum.Mode.OpenedOnClosedOff)
.SetSerializer(new EnumSerializer<RelayEnum.Mode>(BsonType.String));
cm.MapMember(c => c.RebootDelay).SetIgnoreIfNull(true);
cm.MapMember(c => c.Cache).SetDefaultValue(true);
cm.MapMember(c => c.InUse).SetIgnoreIfNull(true).SetIsRequired(false);
cm.MapMember(c => c.ManualRelayStatus)
.SetIgnoreIfNull(true)
.SetSerializer(
new NullableSerializer<RelayEnum.Status>(
new EnumSerializer<RelayEnum.Status>(BsonType.String)));
});
}
}
@@ -0,0 +1,91 @@
using adas_core.Domain.Enums;
using adas_core.Domain.Models.MongoModels;
using adas_core.Infrastructure.Utils.MongoMaps.Interfaz;
using MongoDB.Bson;
using MongoDB.Bson.Serialization;
using MongoDB.Bson.Serialization.Serializers;
namespace adas_core.Infrastructure.Utils.MongoMaps;
public class RowMapContributor : IEntityMapContributor
{
public void RegisterMaps()
{
if (!BsonClassMap.IsClassMapRegistered(typeof(RowBoxLayout)))
BsonClassMap.RegisterClassMap<RowBoxLayout>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.GrowPriority).SetDefaultValue(1D);
cm.MapMember(c => c.Type)
.SetDefaultValue(DisplayConfigEnums.CellType.Default)
.SetSerializer(new EnumSerializer<DisplayConfigEnums.CellType>(BsonType.String));
cm.MapMember(c => c.SubType)
.SetDefaultValue(DisplayConfigEnums.WebDisplayCellSubtype.Default)
.SetSerializer(new EnumSerializer<DisplayConfigEnums.WebDisplayCellSubtype>(BsonType.String));
cm.MapMember(c => c.BgColor).SetIgnoreIfNull(true);
cm.MapMember(c => c.PaddingTop).SetIgnoreIfNull(true);
cm.MapMember(c => c.PaddingBottom).SetIgnoreIfNull(true);
cm.MapMember(c => c.PaddingLeft).SetIgnoreIfNull(true);
cm.MapMember(c => c.PaddingRight).SetIgnoreIfNull(true);
cm.MapMember(c => c.Observations)
.SetDefaultValue(new List<ObservationRowBoxLayout>());
cm.MapMember(c => c.Direction)
.SetDefaultValue(DisplayConfigEnums.DirectionEnum.Row)
.SetSerializer(new EnumSerializer<DisplayConfigEnums.DirectionEnum>(BsonType.String));
});
if (!BsonClassMap.IsClassMapRegistered(typeof(RowDetailsConfig)))
BsonClassMap.RegisterClassMap<RowDetailsConfig>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.Cells).SetDefaultValue(new List<CellDetails>());
cm.MapMember(c => c.Rows).SetDefaultValue(new List<RowDetailsConfig>());
cm.MapMember(c => c.GrowPriority).SetDefaultValue(1.0);
cm.MapMember(c => c.Title).SetIgnoreIfNull(true);
cm.MapMember(c => c.DialogConfig).SetIgnoreIfNull(true);
cm.MapMember(c => c.Type).SetDefaultValue(DisplayConfigEnums.RowType.Demographic)
.SetSerializer(new EnumSerializer<DisplayConfigEnums.RowType>(BsonType.String));
});
if (!BsonClassMap.IsClassMapRegistered(typeof(ObservationRowBoxLayout)))
BsonClassMap.RegisterClassMap<ObservationRowBoxLayout>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.TextRules).SetIgnoreIfNull(true);
cm.MapMember(c => c.ChartSettings).SetIgnoreIfNull(true);
cm.MapMember(c => c.ShowTitle).SetIgnoreIfNull(true);
cm.MapMember(c => c.GrowPriority).SetDefaultValue(1D);
cm.MapMember(c => c.Type)
.SetDefaultValue(DisplayConfigEnums.CellType.Default)
.SetSerializer(new EnumSerializer<DisplayConfigEnums.CellType>(BsonType.String));
cm.MapMember(c => c.SubType).SetIgnoreIfNull(true);
cm.MapMember(c => c.Name).SetIgnoreIfNull(true);
cm.MapMember(c => c.Icon).SetIgnoreIfNull(true);
cm.MapMember(c => c.Title).SetIgnoreIfNull(true);
cm.MapMember(c => c.GridColumn).SetDefaultValue(1);
cm.MapMember(c => c.IsColumn).SetIgnoreIfNull(true);
cm.MapMember(c => c.IsStatic).SetIgnoreIfNull(true);
cm.MapMember(c => c.GraphConf).SetIgnoreIfNull(true);
cm.MapMember(c => c.Names).SetIgnoreIfNull(true);
cm.MapMember(c => c.ObservationName).SetIgnoreIfNull(true);
cm.MapMember(c => c.ObservationTitle).SetIgnoreIfNull(true);
cm.MapMember(c => c.Observations).SetIgnoreIfNull(true);
cm.MapMember(c => c.BgColor).SetIgnoreIfNull(true);
cm.MapMember(c => c.PaddingTop).SetIgnoreIfNull(true);
cm.MapMember(c => c.PaddingBottom).SetIgnoreIfNull(true);
cm.MapMember(c => c.PaddingLeft).SetIgnoreIfNull(true);
cm.MapMember(c => c.PaddingRight).SetIgnoreIfNull(true);
cm.MapMember(c => c.Border).SetIgnoreIfNull(true);
cm.MapMember(c => c.BorderRadius).SetIgnoreIfNull(true);
cm.MapMember(c => c.ValuePathKey).SetIgnoreIfNull(true);
cm.MapMember(c => c.ValuePathNested).SetIgnoreIfNull(true);
cm.MapMember(c => c.Size).SetDefaultValue(15.0);
cm.MapMember(c => c.Format).SetIgnoreIfNull(true);
cm.MapMember(c => c.Length).SetIgnoreIfNull(true);
cm.MapMember(c => c.Direction)
.SetIgnoreIfNull(true)
.SetSerializer(new NullableSerializer<DisplayConfigEnums.DirectionEnum>(
new EnumSerializer<DisplayConfigEnums.DirectionEnum>(BsonType.String)));
});
}
}
@@ -0,0 +1,69 @@
using adas_core.Domain.Enums;
using adas_core.Domain.Models.BsonConverters;
using adas_core.Domain.Models.MongoModels;
using adas_core.Infrastructure.Utils.MongoMaps.Interfaz;
using MongoDB.Bson;
using MongoDB.Bson.Serialization;
using MongoDB.Bson.Serialization.Serializers;
namespace adas_core.Infrastructure.Utils.MongoMaps;
public class SectionMapContributor : IEntityMapContributor
{
public void RegisterMaps()
{
if (!BsonClassMap.IsClassMapRegistered(typeof(Section)))
BsonClassMap.RegisterClassMap<Section>(cm =>
{
cm.AutoMap();
cm.MapIdMember(c => c._id);
cm.MapMember(c => c.Id)
.SetIsRequired(true)
.SetDefaultValue(string.Empty);
cm.MapMember(c => c.SectionTitle).SetIgnoreIfNull(true);
cm.MapMember(c => c.PointOfCare).SetIgnoreIfNull(true);
cm.MapMember(c => c.LastUpdate).SetIgnoreIfNull(true);
cm.MapMember(c => c.Configuration)
.SetSerializer(new DictionaryBsonConverter());
cm.MapMember(c => c.SectionConfig).SetIgnoreIfNull(true);
cm.MapMember(c => c.DesignProperties).SetIgnoreIfNull(true);
cm.MapMember(c => c.PointOfCareList)
.SetDefaultValue(new Dictionary<string, List<PointOfCare>>());
cm.MapMember(c => c.Items).SetDefaultValue(new List<Section.SectionItem>());
cm.MapMember(c => c.Status)
.SetIgnoreIfNull(true)
.SetSerializer(
new NullableSerializer<StatusEnum.Type>(new EnumSerializer<StatusEnum.Type>(BsonType.String)));
});
if (!BsonClassMap.IsClassMapRegistered(typeof(Section.SectionItem)))
BsonClassMap.RegisterClassMap<Section.SectionItem>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.Group).SetIgnoreIfNull(true);
cm.MapMember(c => c.Boxes).SetDefaultValue(new List<Box>());
});
if (!BsonClassMap.IsClassMapRegistered(typeof(SectionConfig)))
BsonClassMap.RegisterClassMap<SectionConfig>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.Columns).SetIgnoreIfNull(true);
cm.MapMember(c => c.Rows).SetIgnoreIfNull(true);
cm.MapMember(c => c.RefreshValues).SetIgnoreIfNull(true);
cm.MapMember(c => c.RefreshConfig).SetIgnoreIfNull(true);
cm.MapMember(c => c.Steps).SetIgnoreIfNull(true);
cm.MapMember(c => c.DesignProperties).SetIgnoreIfNull(true);
});
if (!BsonClassMap.IsClassMapRegistered(typeof(MinimalDisplaySection)))
BsonClassMap.RegisterClassMap<MinimalDisplaySection>(cm =>
{
cm.AutoMap();
cm.MapIdMember(c => c.Id).SetDefaultValue(ObjectId.GenerateNewId());
cm.MapMember(c => c.Name).SetDefaultValue(string.Empty);
cm.MapMember(c => c.IsSelected).SetDefaultValue(false);
});
}
}
@@ -0,0 +1,60 @@
using adas_core.Domain.Models.MongoModels;
using adas_core.Infrastructure.Utils.MongoMaps.Interfaz;
using MongoDB.Bson.Serialization;
namespace adas_core.Infrastructure.Utils.MongoMaps;
public class ServiceConfigMapContributor : IEntityMapContributor
{
public void RegisterMaps()
{
if (!BsonClassMap.IsClassMapRegistered(typeof(ServiceConfig)))
BsonClassMap.RegisterClassMap<ServiceConfig>(cm =>
{
cm.AutoMap();
cm.MapIdMember(c => c.Id).SetElementName("_id");
cm.MapMember(c => c.StrId).SetElementName("id")
.SetDefaultValue(string.Empty);
cm.MapMember(c => c.Service).SetDefaultValue(new List<ServiceConfigService>());
cm.MapMember(c => c.Theme).SetIgnoreIfNull(true);
cm.MapMember(c => c.BoxObservations).SetIgnoreIfNull(true);
cm.MapMember(c => c.Score).SetDefaultValue(string.Empty);
});
if (!BsonClassMap.IsClassMapRegistered(typeof(ServiceConfigService)))
BsonClassMap.RegisterClassMap<ServiceConfigService>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.Screen).SetDefaultValue(string.Empty);
cm.MapMember(c => c.Sections).SetDefaultValue(new List<ServiceConfigServiceSection>());
});
if (!BsonClassMap.IsClassMapRegistered(typeof(ServiceConfigServiceSection)))
BsonClassMap.RegisterClassMap<ServiceConfigServiceSection>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.BoxId).SetDefaultValue(string.Empty);
cm.MapMember(c => c.Box).SetDefaultValue(string.Empty);
});
if (!BsonClassMap.IsClassMapRegistered(typeof(ServiceConfigTheme)))
BsonClassMap.RegisterClassMap<ServiceConfigTheme>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.DefaultTheme).SetElementName("default")
.SetDefaultValue(string.Empty);
cm.MapMember(c => c.Timetables).SetDefaultValue(new List<ServiceConfigThemeTimetable>());
});
if (!BsonClassMap.IsClassMapRegistered(typeof(ServiceConfigThemeTimetable)))
BsonClassMap.RegisterClassMap<ServiceConfigThemeTimetable>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.Theme).SetDefaultValue(string.Empty);
cm.MapMember(c => c.StartDay).SetDefaultValue(string.Empty);
cm.MapMember(c => c.EndDay).SetDefaultValue(string.Empty);
cm.MapMember(c => c.StartHour).SetDefaultValue(string.Empty);
cm.MapMember(c => c.EndHour).SetDefaultValue(string.Empty);
});
}
}
@@ -0,0 +1,45 @@
using adas_core.Domain.Models.MongoModels;
using adas_core.Infrastructure.Utils.MongoMaps.Interfaz;
using MongoDB.Bson.Serialization;
namespace adas_core.Infrastructure.Utils.MongoMaps;
public class StandardMapContributor : IEntityMapContributor
{
public void RegisterMaps()
{
if (!BsonClassMap.IsClassMapRegistered(typeof(HistoricalConfigChanges)))
BsonClassMap.RegisterClassMap<HistoricalConfigChanges>(cm =>
{
cm.AutoMap();
//cm.MapMember(c => c.Id)
// .SetSerializer(new ObjectIdSerializer(BsonType.String));
//cm.GetMemberMap(c => c.ConfigType)
// .SetSerializer(new NullableSerializer<ConfigTypes>(new EnumSerializer<ConfigTypes>(BsonType.String)));
});
if (!BsonClassMap.IsClassMapRegistered(typeof(UiFontData)))
BsonClassMap.RegisterClassMap<UiFontData>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.WidthStepBed).SetIgnoreIfNull(true);
cm.MapMember(c => c.HeightStepBed).SetIgnoreIfNull(true);
cm.MapMember(c => c.FontSizeValue).SetIgnoreIfNull(true);
cm.MapMember(c => c.FontSizeMediumValue).SetIgnoreIfNull(true);
cm.MapMember(c => c.FontSizeHeaderValue).SetIgnoreIfNull(true);
cm.MapMember(c => c.FontSizeLittleValue).SetIgnoreIfNull(true);
cm.MapMember(c => c.FontSizeMicroValue).SetIgnoreIfNull(true);
cm.MapMember(c => c.FontSizeNanoValue).SetIgnoreIfNull(true);
cm.MapMember(c => c.FontSizeLittleTextValue).SetIgnoreIfNull(true);
cm.MapMember(c => c.FontSizeName).SetIgnoreIfNull(true);
cm.MapMember(c => c.FontSizeLittleName).SetIgnoreIfNull(true);
cm.MapMember(c => c.FontSizeUnit).SetIgnoreIfNull(true);
cm.MapMember(c => c.BorderColor).SetIgnoreIfNull(true);
cm.MapMember(c => c.BackGroundColor).SetIgnoreIfNull(true);
cm.MapMember(c => c.BoxMarginTop).SetIgnoreIfNull(true);
cm.MapMember(c => c.BoxMarginBot).SetIgnoreIfNull(true);
cm.MapMember(c => c.BoxMarginLeft).SetIgnoreIfNull(true);
cm.MapMember(c => c.BoxMarginRight).SetIgnoreIfNull(true);
});
}
}
@@ -0,0 +1,116 @@
using adas_core.Domain.Enums;
using adas_core.Domain.Models;
using adas_core.Domain.Models.Observations;
using adas_core.Infrastructure.Utils.MongoMaps.Interfaz;
using MongoDB.Bson;
using MongoDB.Bson.Serialization;
using MongoDB.Bson.Serialization.Serializers;
namespace adas_core.Infrastructure.Utils.MongoMaps;
public class TreatmentMapContributor : IEntityMapContributor
{
public void RegisterMaps()
{
if (!BsonClassMap.IsClassMapRegistered(typeof(PatientTreatment)))
BsonClassMap.RegisterClassMap<PatientTreatment>(cm =>
{
cm.AutoMap();
cm.MapIdMember(c => c.Id).SetElementName("_id");
cm.MapMember(c => c.PatientId)
.SetSerializer(new ObjectIdSerializer(BsonType.String))
.SetIgnoreIfNull(true);
cm.MapMember(c => c.OrderControl)
.SetSerializer(new EnumSerializer<OrderControlType>(BsonType.String));
cm.MapMember(c => c.PlacerOrder).SetIgnoreIfNull(true);
cm.MapMember(c => c.FillerOrder).SetIgnoreIfNull(true);
cm.MapMember(c => c.OrderStatus).SetDefaultValue(string.Empty);
cm.MapMember(c => c.OrderTime).SetIgnoreIfNull(true);
cm.MapMember(c => c.StartTime).SetIgnoreIfNull(true);
cm.MapMember(c => c.EndTime).SetIgnoreIfNull(true);
cm.MapMember(c => c.RequestedGiveCodes).SetDefaultValue(new List<Code>());
cm.MapMember(c => c.RequestedGiveTreatment).SetDefaultValue(string.Empty);
cm.MapMember(c => c.RequestedGiveCodesStatus).SetDefaultValue(new List<CodeStatus>());
cm.MapMember(c => c.RequestedGiveAmountMinimum).SetIgnoreIfNull(true);
cm.MapMember(c => c.RequestedGiveAmountMaximum).SetIgnoreIfNull(true);
cm.MapMember(c => c.RequestedGiveUnits).SetIgnoreIfNull(true);
cm.MapMember(c => c.RequestedDosageForm).SetIgnoreIfNull(true);
cm.MapMember(c => c.Notes).SetDefaultValue(new List<Note>());
cm.MapMember(c => c.Routes).SetDefaultValue(new List<TreatmentRoute>());
cm.MapMember(c => c.SingleDose).SetDefaultValue(false);
cm.MapMember(c => c.BoloPom).SetDefaultValue(false);
cm.MapMember(c => c.MessageTime);
cm.MapMember(c => c.SystemId).SetIgnoreIfNull(true);
});
if (!BsonClassMap.IsClassMapRegistered(typeof(Entity)))
BsonClassMap.RegisterClassMap<Entity>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.EntityIdentifier).SetIgnoreIfNull(true);
cm.MapMember(c => c.NamespaceId).SetIgnoreIfNull(true);
cm.MapMember(c => c.UniversalId).SetIgnoreIfNull(true);
cm.MapMember(c => c.UniversalIdType).SetIgnoreIfNull(true);
});
if (!BsonClassMap.IsClassMapRegistered(typeof(Code)))
BsonClassMap.RegisterClassMap<Code>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.Identifier).SetDefaultValue(string.Empty);
cm.MapMember(c => c.Text).SetDefaultValue(string.Empty);
cm.MapMember(c => c.CodingSystem).SetDefaultValue(string.Empty);
});
if (!BsonClassMap.IsClassMapRegistered(typeof(CodeStatus)))
BsonClassMap.RegisterClassMap<CodeStatus>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.Code).SetIgnoreIfNull(true);
cm.MapMember(c => c.Status).SetIgnoreIfNull(true);
cm.MapMember(c => c.AdministrationTime).SetIgnoreIfNull(true);
cm.MapMember(c => c.EndAdministrationTime).SetIgnoreIfNull(true);
});
if (!BsonClassMap.IsClassMapRegistered(typeof(Note)))
BsonClassMap.RegisterClassMap<Note>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.CommentType).SetDefaultValue(string.Empty);
cm.MapMember(c => c.Comment).SetDefaultValue(string.Empty);
cm.MapMember(c => c.EnteredTime).SetIgnoreIfNull(true);
});
if (!BsonClassMap.IsClassMapRegistered(typeof(TreatmentRoute)))
BsonClassMap.RegisterClassMap<TreatmentRoute>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.Route).SetIgnoreIfNull(true);
});
if (!BsonClassMap.IsClassMapRegistered(typeof(Medicine)))
BsonClassMap.RegisterClassMap<Medicine>(cm =>
{
cm.AutoMap();
cm.MapIdMember(c => c.Id).SetElementName("_id");
cm.MapMember(c => c.Name).SetIgnoreIfNull(true);
cm.MapMember(c => c.Codes).SetIgnoreIfNull(true);
cm.MapMember(c => c.Notes).SetIgnoreIfNull(true);
cm.MapMember(c => c.Type).SetIgnoreIfNull(true);
cm.MapMember(c => c.Group).SetIgnoreIfNull(true);
});
if (!BsonClassMap.IsClassMapRegistered(typeof(CodeAction)))
BsonClassMap.RegisterClassMap<CodeAction>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.Code).SetIsRequired(true);
cm.MapMember(c => c.Action)
.SetSerializer(new EnumSerializer<ActionsEnum.ResourceAction>(BsonType.String));
});
if (!BsonClassMap.IsClassMapRegistered(typeof(PredictMedicationObservation)))
BsonClassMap.RegisterClassMap<PredictMedicationObservation>(cm => { cm.AutoMap(); });
}
}
@@ -0,0 +1,94 @@
using adas_core.Domain.Enums;
using adas_core.Domain.Models.MongoModels;
using adas_core.Infrastructure.Utils.MongoMaps.Interfaz;
using MongoDB.Bson;
using MongoDB.Bson.Serialization;
using MongoDB.Bson.Serialization.Serializers;
namespace adas_core.Infrastructure.Utils.MongoMaps;
public class UnitMapContributor : IEntityMapContributor
{
public void RegisterMaps()
{
if (!BsonClassMap.IsClassMapRegistered(typeof(Unit)))
BsonClassMap.RegisterClassMap<Unit>(cm =>
{
cm.AutoMap();
cm.MapIdMember(c => c.Id).SetElementName("_id").SetIsRequired(true);
cm.GetMemberMap(c => c.Title).SetIgnoreIfNull(true);
cm.GetMemberMap(c => c.Name).SetIgnoreIfNull(true);
cm.GetMemberMap(c => c.LastUpdate).SetIgnoreIfNull(true);
cm.GetMemberMap(c => c.PointOfCareIds).SetIgnoreIfNull(true);
cm.UnmapMember(c => c.PocCount);
cm.MapMember(c => c.Status)
.SetDefaultValue(StatusEnum.Type.Ok)
.SetSerializer(
new NullableSerializer<StatusEnum.Type>(new EnumSerializer<StatusEnum.Type>(BsonType.String)));
cm.MapMember(c => c.Configuration).SetDefaultValue(new UnitConfiguration());
cm.GetMemberMap(c => c.AltableOptionListId).SetIgnoreIfNull(true);
cm.GetMemberMap(c => c.AllergyListId).SetIgnoreIfNull(true);
cm.GetMemberMap(c => c.DestinationListId).SetIgnoreIfNull(true);
cm.GetMemberMap(c => c.InternalDestinationListId).SetIgnoreIfNull(true);
cm.GetMemberMap(c => c.DiagnosisListId).SetIgnoreIfNull(true);
cm.GetMemberMap(c => c.DoctorListId).SetIgnoreIfNull(true);
cm.GetMemberMap(c => c.DoctorTypeListId).SetIgnoreIfNull(true);
cm.GetMemberMap(c => c.InsulationListId).SetIgnoreIfNull(true);
cm.GetMemberMap(c => c.MobilityOptionListId).SetIgnoreIfNull(true);
cm.GetMemberMap(c => c.OriginListId).SetIgnoreIfNull(true);
cm.GetMemberMap(c => c.PatientStatusListId).SetIgnoreIfNull(true);
cm.GetMemberMap(c => c.ProcedureListId).SetIgnoreIfNull(true);
cm.GetMemberMap(c => c.TestListId).SetIgnoreIfNull(true);
cm.GetMemberMap(c => c.ServiceListId).SetIgnoreIfNull(true);
cm.GetMemberMap(c => c.TherapeuticCeilingListId).SetIgnoreIfNull(true);
cm.GetMemberMap(c => c.TreatmentListId).SetIgnoreIfNull(true);
cm.GetMemberMap(c => c.VisitOptionListId).SetIgnoreIfNull(true);
cm.GetMemberMap(c => c.AccessControlListId).SetIgnoreIfNull(true);
cm.GetMemberMap(c => c.LanguageBarrierListId).SetIgnoreIfNull(true);
cm.GetMemberMap(c => c.DischargeStatusListId).SetIgnoreIfNull(true);
cm.GetMemberMap(c => c.PassiveSittingListId).SetIgnoreIfNull(true);
cm.GetMemberMap(c => c.GenericListId).SetIgnoreIfNull(true);
// No mapear estos campos
cm.UnmapProperty(c => c.AllergyList);
cm.UnmapProperty(c => c.DestinationList);
cm.UnmapProperty(c => c.DiagnosisList);
cm.UnmapProperty(c => c.DoctorList);
cm.UnmapProperty(c => c.DoctorTypeList);
cm.UnmapProperty(c => c.InsulationList);
cm.UnmapProperty(c => c.MobilityOptionList);
cm.UnmapProperty(c => c.OriginList);
cm.UnmapProperty(c => c.PatientStatusList);
cm.UnmapProperty(c => c.ProcedureList);
cm.UnmapProperty(c => c.TestList);
cm.UnmapProperty(c => c.AltableOptionList);
cm.UnmapProperty(c => c.DischargeStatusList);
cm.UnmapProperty(c => c.ServiceList);
cm.UnmapProperty(c => c.TherapeuticCeilingList);
cm.UnmapProperty(c => c.TreatmentList);
cm.UnmapProperty(c => c.VisitOptionList);
cm.UnmapProperty(c => c.PassiveSittingList);
cm.UnmapProperty(c => c.GenericList);
cm.UnmapProperty(c => c.LanguageBarrierList);
cm.UnmapProperty(c => c.PointOfCares);
cm.UnmapProperty(c => c.InternalDestinationList);
});
if (!BsonClassMap.IsClassMapRegistered(typeof(UnitConfiguration)))
BsonClassMap.RegisterClassMap<UnitConfiguration>(cm =>
{
cm.AutoMap();
cm.MapMember(c => c.AutoAdt).SetDefaultValue(false);
cm.MapMember(c => c.ManualDischarge).SetDefaultValue(true);
cm.MapMember(c => c.ManualAdmit).SetDefaultValue(true);
cm.MapMember(c => c.ManualMove).SetDefaultValue(true);
cm.MapMember(c => c.ManualEdit).SetDefaultValue(true);
cm.MapMember(c => c.PlanDisplayConfiguration).SetIgnoreIfNull(true);
cm.MapMember(c => c.SmartDisplayConfiguration).SetIgnoreIfNull(true);
cm.MapMember(c => c.StandarDisplayConfiguration).SetIgnoreIfNull(true);
});
}
}
@@ -0,0 +1,90 @@
using MongoDB.Bson;
using MongoDB.Bson.Serialization;
using MongoDB.Driver;
namespace adas_core.Infrastructure.Utils;
public class MongoUtils
{
public static async Task EnsureIndexes<TDocument>(IMongoCollection<TDocument> collection,
List<CreateIndexModel<TDocument>> expectedIndexes)
{
var existingIndexes = await (await collection.Indexes.ListAsync()).ToListAsync();
var documentSerializer = BsonSerializer.SerializerRegistry.GetSerializer<TDocument>();
var serializerRegistry = BsonSerializer.SerializerRegistry;
var renderArgs = new RenderArgs<TDocument>(documentSerializer, serializerRegistry);
foreach (var expectedIndexModel in expectedIndexes)
{
var expectedIndexKeys = expectedIndexModel.Keys
.Render(renderArgs).ToString();
var existingIndexWithSameKeys = existingIndexes.FirstOrDefault(index =>
{
var keys = index.Elements.FirstOrDefault(e => e.Name == "key").Value?.ToString();
return keys == expectedIndexKeys;
});
if (existingIndexWithSameKeys != null)
{
// Existe un índice con las mismas claves, verificar las opciones
if (!IndexOptionsMatch(expectedIndexModel, existingIndexWithSameKeys, renderArgs))
{
// Las opciones no coinciden, eliminar el índice existente y crear el nuevo
var indexName = existingIndexWithSameKeys.Elements.FirstOrDefault(e => e.Name == "name").Value
?.AsString;
if (!string.IsNullOrEmpty(indexName) && indexName != "_id_")
try
{
await collection.Indexes.DropOneAsync(indexName);
await collection.Indexes.CreateOneAsync(expectedIndexModel);
Console.WriteLine($"Info: Índice con claves '{expectedIndexKeys}' actualizado.");
}
catch (MongoCommandException ex) when (ex.Code == 85)
{
Console.WriteLine(
$"Warning: No se pudo actualizar el índice con claves '{expectedIndexKeys}'. Error: {ex.Message}");
}
else
try
{
await collection.Indexes.CreateOneAsync(expectedIndexModel);
}
catch (MongoCommandException ex) when (ex.Code == 85)
{
Console.WriteLine(
$"Warning: El índice con claves '{expectedIndexKeys}' ya existe con diferentes opciones y no se pudo actualizar automáticamente.");
}
}
// Si las opciones coinciden, no se hace nada
}
else
{
// No existe un índice con estas claves, crear el nuevo
try
{
await collection.Indexes.CreateOneAsync(expectedIndexModel);
}
catch (MongoCommandException ex) when (ex.Code == 85)
{
Console.WriteLine($"Warning: El índice con claves '{expectedIndexKeys}' ya existe.");
}
}
}
}
private static bool IndexOptionsMatch<TDocument>(CreateIndexModel<TDocument> expectedIndexModel,
BsonDocument existingIndex, RenderArgs<TDocument> renderArgs)
{
var expectedIndexOptions = expectedIndexModel.Options;
var unique = existingIndex.Elements.FirstOrDefault(e => e.Name == "unique").Value?.AsBoolean ?? false;
var background = existingIndex.Elements.FirstOrDefault(e => e.Name == "background").Value?.AsBoolean ?? false;
var partialFilter = existingIndex.Elements.FirstOrDefault(e => e.Name == "partialFilterExpression").Value
?.ToString();
var expectedPartialFilter = expectedIndexOptions.PartialFilterExpression
?.Render(renderArgs).ToString();
return unique == expectedIndexOptions.Unique &&
background == expectedIndexOptions.Background &&
partialFilter == expectedPartialFilter;
}
}
@@ -0,0 +1,100 @@
using System.Reflection;
using adas_core.Domain.Models;
using MongoDB.Bson.Serialization;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;
namespace adas_core.Infrastructure.Utils;
public class PatientObservationAlarmConverter : JsonConverter<PatientObservationAlarm>, IBsonSerializer
{
public object Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
{
throw new NotImplementedException();
}
public void Serialize(BsonSerializationContext context, BsonSerializationArgs args, object value)
{
throw new NotImplementedException();
}
public Type ValueType => typeof(PatientObservationAlarm);
public override PatientObservationAlarm? ReadJson(JsonReader reader, Type objectType,
PatientObservationAlarm? existingValue,
bool hasExistingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null)
return null;
// Implement your custom deserialization logic here
var jsonObject = JObject.Load(reader);
// Deserialize properties from jsonObject to PatientObservationAlarm object
// Example: Deserialize 'Value' property
var value = jsonObject.GetValue("value")?.ToObject<object>();
return new PatientObservationAlarm
{
Value = value ?? new object()
// Other property assignments...
};
}
public new void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer)
{
if (value != null)
{
var jo = JObject.FromObject(value);
// Add [JsonConverter(typeof(StringEnumConverter))] attribute to specified properties
AddStringEnumConverterAttribute(value, "eventPhase");
AddStringEnumConverterAttribute(value, "state");
AddStringEnumConverterAttribute(value, "priority");
AddStringEnumConverterAttribute(value, "type");
jo.Property("messageTime")?.Remove();
jo.Property("expired")?.Remove();
jo.WriteTo(writer);
}
}
private static void AddStringEnumConverterAttribute(object value, string propertyName)
{
var prop = value.GetType().GetProperty(propertyName);
var attr = new JsonConverterAttribute(typeof(StringEnumConverter));
if (prop != null)
{
var attrs = prop.GetCustomAttributes(false);
// Check if the attribute is not already applied
if (Array.Find(attrs, a => a is JsonConverterAttribute) == null)
{
// Create a new array that includes the existing attributes and the new one
var newAttrs = new object[attrs.Length + 1];
Array.Copy(attrs, newAttrs, attrs.Length);
newAttrs[attrs.Length] = attr;
// Use reflection to set the new attributes array
var field = typeof(PropertyInfo).GetField("m_customAttributes",
BindingFlags.Instance | BindingFlags.NonPublic);
field?.SetValue(prop, newAttrs);
}
}
}
public override void WriteJson(JsonWriter writer, PatientObservationAlarm? value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
/*How to use it:
BsonSerializer.RegisterSerializer(new PatientObservationAlarmConverter());
JsonConvert.DefaultSettings = () => new JsonSerializerSettings
{
Converters = { new PatientObservationAlarmConverter() }
};
*/
@@ -0,0 +1,68 @@
using System.Reflection;
using adas_core.Domain.Models;
using MongoDB.Bson.Serialization;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;
namespace adas_core.Infrastructure.Utils;
public class PatientObservationConverter(Type? valueType) : JsonConverter<PatientObservation>, IBsonSerializer
{
public object Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
{
throw new NotImplementedException();
}
public void Serialize(BsonSerializationContext context, BsonSerializationArgs args, object value)
{
throw new NotImplementedException();
}
public Type? ValueType { get; } = valueType;
public override void WriteJson(JsonWriter writer, PatientObservation? value, JsonSerializer serializer)
{
if (value != null)
{
var jo = JObject.FromObject(value);
// Add [JsonConverter(typeof(StringEnumConverter))] attribute to specified properties
AddStringEnumConverterAttribute(value, "Status");
jo.Property("MessageTime")?.Remove();
jo.WriteTo(writer);
}
}
private static void AddStringEnumConverterAttribute(object value, string propertyName)
{
var prop = value.GetType().GetProperty(propertyName);
var attr = new JsonConverterAttribute(typeof(StringEnumConverter));
if (prop != null)
{
var attrs = prop.GetCustomAttributes(false);
// Check if the attribute is not already applied
if (Array.Find(attrs, a => a is JsonConverterAttribute) == null)
{
// Create a new array that includes the existing attributes and the new one
var newAttrs = new object[attrs.Length + 1];
Array.Copy(attrs, newAttrs, attrs.Length);
newAttrs[attrs.Length] = attr;
// Use reflection to set the new attributes array
var field = typeof(PropertyInfo).GetField("m_customAttributes",
BindingFlags.Instance | BindingFlags.NonPublic);
field?.SetValue(prop, newAttrs);
}
}
}
public override PatientObservation ReadJson(JsonReader reader, Type objectType, PatientObservation? existingValue,
bool hasExistingValue, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
@@ -0,0 +1,87 @@
using System.Reflection;
using adas_core.Domain.Models;
using adas_core.Domain.Models.Pumps;
using MongoDB.Bson.Serialization;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;
using JsonConverterAttribute = Newtonsoft.Json.JsonConverterAttribute;
namespace adas_core.Infrastructure.Utils;
public class PatientPumpObservationConverter : JsonConverter<PumpObservation>, IBsonSerializer
{
public object Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
{
throw new NotImplementedException();
}
public void Serialize(BsonSerializationContext context, BsonSerializationArgs args, object value)
{
throw new NotImplementedException();
}
public Type ValueType => typeof(PatientObservationAlarm);
public override PumpObservation ReadJson(JsonReader reader, Type objectType,
PumpObservation? existingValue,
bool hasExistingValue, JsonSerializer serializer)
{
throw new NotImplementedException();
}
public new void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer)
{
if (value != null)
{
var jo = JObject.FromObject(value);
// Add [JsonConverter(typeof(StringEnumConverter))] attribute to specified properties
AddStringEnumConverterAttribute(value, "Event");
AddStringEnumConverterAttribute(value, "Status");
AddStringEnumConverterAttribute(value, "PumpMode");
AddStringEnumConverterAttribute(value, "InfusingStatus");
AddStringEnumConverterAttribute(value, "AlarmMode");
jo.WriteTo(writer);
}
}
public override void WriteJson(JsonWriter writer, PumpObservation? value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
private static void AddStringEnumConverterAttribute(object value, string propertyName)
{
var prop = value.GetType().GetProperty(propertyName);
var attr = new JsonConverterAttribute(typeof(StringEnumConverter));
if (prop != null)
{
var attrs = prop.GetCustomAttributes(false);
// Check if the attribute is not already applied
if (Array.Find(attrs, a => a is JsonConverterAttribute) == null)
{
// Create a new array that includes the existing attributes and the new one
var newAttrs = new object[attrs.Length + 1];
Array.Copy(attrs, newAttrs, attrs.Length);
newAttrs[attrs.Length] = attr;
// Use reflection to set the new attributes array
var field = typeof(PropertyInfo).GetField("m_customAttributes",
BindingFlags.Instance | BindingFlags.NonPublic);
field?.SetValue(prop, newAttrs);
}
}
}
}
/*How to use it:
BsonSerializer.RegisterSerializer(new PatientObservationAlarmConverter());
JsonConvert.DefaultSettings = () => new JsonSerializerSettings
{
Converters = { new PatientObservationAlarmConverter() }
};
*/
@@ -0,0 +1,63 @@
using System.Reflection;
using adas_core.Domain.Models;
using MongoDB.Bson.Serialization;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;
namespace adas_core.Infrastructure.Utils;
public class PersonConverter(Type valueType) : JsonConverter<Person>, IBsonSerializer
{
public object Deserialize(BsonDeserializationContext context, BsonDeserializationArgs args)
{
throw new NotImplementedException();
}
public void Serialize(BsonSerializationContext context, BsonSerializationArgs args, object value)
{
throw new NotImplementedException();
}
public Type ValueType { get; } = valueType;
public override void WriteJson(JsonWriter writer, Person? value, JsonSerializer serializer)
{
if (value == null) return;
var jo = JObject.FromObject(value);
// Add [JsonConverter(typeof(StringEnumConverter))] attribute to specified properties
AddStringEnumConverterAttribute(value, "Gender");
jo.WriteTo(writer);
}
private static void AddStringEnumConverterAttribute(object value, string propertyName)
{
var prop = value.GetType().GetProperty(propertyName);
var attr = new JsonConverterAttribute(typeof(StringEnumConverter));
if (prop == null) return;
var attrs = prop.GetCustomAttributes(false);
// Check if the attribute is not already applied
if (Array.Find(attrs, a => a is JsonConverterAttribute) != null) return;
// Create a new array that includes the existing attributes and the new one
var newAttrs = new object[attrs.Length + 1];
Array.Copy(attrs, newAttrs, attrs.Length);
newAttrs[attrs.Length] = attr;
// Use reflection to set the new attributes array
var field = typeof(PropertyInfo).GetField("m_customAttributes",
BindingFlags.Instance | BindingFlags.NonPublic);
field?.SetValue(prop, newAttrs);
}
public override Person ReadJson(JsonReader reader, Type objectType, Person? existingValue, bool hasExistingValue,
JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
@@ -0,0 +1,145 @@
using adas_core.Application.Services.Interfaces;
using EasyNetQ;
using EasyNetQ.SystemMessages;
using Newtonsoft.Json;
using Serilog;
using System.Text;
using ILogger = Serilog.ILogger;
namespace adas_core.Infrastructure.Utils;
public class RabbitConsumerErrorHandler(IPublisherService publisherService)
{
private const int MaxRetries = 2;
private static readonly ILogger Logger = Log.ForContext<RabbitConsumerErrorHandler>();
public async Task HandleAsync<T>(
Message<T> message,
MessageReceivedInfo receivedInfo,
Func<Task> next)
{
try
{
await next();
}
catch (Exception exception)
{
Logger.Error(exception, "Consumer error {Message}", exception.Message);
var properties = message.Properties;
var body = Encoding.UTF8.GetString(
message.Body is byte[] bytes
? bytes
: Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(message.Body)));
HandleRetries(receivedInfo, properties, body, exception);
}
}
private void HandleRetries(
MessageReceivedInfo receivedInfo,
MessageProperties properties,
string body,
Exception exception)
{
try
{
var headers = properties.Headers != null
? new Dictionary<string, object>(properties.Headers)
: [];
var retries = GetRetries(properties);
// MAX RETRIES → ERROR QUEUE
if (retries > MaxRetries)
{
if (!receivedInfo.Queue.StartsWith("Error"))
{
headers["retries"] = BitConverter.GetBytes(MaxRetries + 1);
var errorMsg = CreateErrorMessage(
receivedInfo,
properties,
body,
exception,
headers
);
_ = publisherService.SendMessageError(
errorMsg,
$"Error{receivedInfo.Queue}");
}
return;
}
// RETRY NORMAL
headers["retries"] = BitConverter.GetBytes(retries + 1);
var newProps = new MessageProperties
{
DeliveryMode = 2,
Headers = headers,
ContentType = properties.ContentType,
CorrelationId = properties.CorrelationId,
MessageId = properties.MessageId
};
var message = new Message<string>(body, newProps);
var result = publisherService
.SendMessage(message, receivedInfo.Queue)
.GetAwaiter()
.GetResult();
if (!result)
throw new Exception("Requeue failed");
}
catch (Exception e)
{
Logger.Error(e, "Exception processing rabbit message");
}
}
private int GetRetries(MessageProperties properties)
{
if (properties.Headers != null &&
properties.Headers.TryGetValue("retries", out var retriesObj) &&
retriesObj is byte[] bytes)
{
return BitConverter.ToInt32(bytes, 0);
}
return 0;
}
private static Message<Error> CreateErrorMessage(
MessageReceivedInfo receivedInfo,
MessageProperties originalProperties,
string body,
Exception exception,
Dictionary<string, object> headers)
{
var props = new MessageProperties
{
Headers = headers,
DeliveryMode = originalProperties.DeliveryMode,
ContentType = originalProperties.ContentType,
CorrelationId = originalProperties.CorrelationId,
MessageId = originalProperties.MessageId
};
var error = new Error(
body,
exception.Message,
receivedInfo.Exchange,
receivedInfo.RoutingKey,
receivedInfo.Queue,
DateTime.UtcNow,
props
);
return new Message<Error>(error, props);
}
}
@@ -0,0 +1,29 @@
using System.Text;
using EasyNetQ.Consumer;
using Newtonsoft.Json;
namespace adas_core.Infrastructure.Utils;
public class RabbitIErrorMessageSerializer : IErrorMessageSerializer
{
public byte[]? Deserialize(string messageBody)
{
var unescapedJsonString = JsonConvert.DeserializeObject<string>(messageBody);
return unescapedJsonString != null ? Encoding.UTF8.GetBytes(unescapedJsonString) : null;
}
public string? Serialize(byte[] messageBody)
{
var stringifiedMsgBody = Encoding.UTF8.GetString(messageBody);
try
{
return JsonConvert.DeserializeObject<string>(stringifiedMsgBody);
}
catch (Exception)
{
return stringifiedMsgBody;
}
}
}
@@ -0,0 +1,40 @@
using adas_core.Domain.Exceptions;
namespace adas_core.Infrastructure.Utils;
public static class TypesUtils
{
public static Type GetDriver(string deviceType, string device)
{
return deviceType switch
{
"Relay" => GetType("adas-core.module.Relays", device, deviceType),
"LightBeacon" => GetType("adas-core.module.LightBeacons", device, deviceType),
_ => throw new AdasException($"Device type {deviceType} not found")
};
}
private static Type GetType(string typeName, string device, string deviceType)
{
var loadedAssemblies = AppDomain.CurrentDomain.GetAssemblies();
var assembly = loadedAssemblies.FirstOrDefault(a =>
{
var name = a.GetName().Name;
return name != null && name.Contains(typeName);
});
if (assembly == null)
// El ensamblado no está cargado. Lanzar excepción o manejar el fallo.
throw new AdasException($"Assembly '{typeName}' not loaded.");
var fullClassName = $"{typeName.Replace('-', '_')}.Devices.{device}{deviceType}";
var type = assembly.GetType(fullClassName,
true,
true);
if (type != null) return type;
throw new AdasException($"{typeName} driver not found");
}
}
@@ -0,0 +1,25 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<RootNamespace>adas_core.Infrastructure</RootNamespace>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="AuditLogs" Version="1.0.59" />
<PackageReference Include="EasyNetQ" Version="8.1.4" />
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="10.0.8" />
<PackageReference Include="Microsoft.Extensions.Options" Version="10.0.8" />
<PackageReference Include="MongoMigrations.Core" Version="4.0.15" />
<PackageReference Include="StackExchange.Redis" Version="2.13.17" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\adas-core.Application\adas-core.Application.csproj" />
<ProjectReference Include="..\adas-core.module.LightBeacons\adas-core.module.LightBeacons.csproj" />
<ProjectReference Include="..\adas-core.module.Relays\adas-core.module.Relays.csproj" />
</ItemGroup>
</Project>