Creado apartir del commit b888de6c92056de294456f581a56e25e734d4ab7 de develop
This commit is contained in:
@@ -0,0 +1,398 @@
|
||||
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;
|
||||
using adas_core.Domain.Models.AppSettings;
|
||||
using adas_core.Domain.Models.Filter;
|
||||
using adas_core.Domain.Models.Masters;
|
||||
using adas_core.Domain.Models.MongoModels;
|
||||
using adas_core.Domain.Models.Responses;
|
||||
using adas_core.Domain.Utils;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using MongoDB.Bson;
|
||||
using MongoDB.Driver;
|
||||
|
||||
namespace adas_core.Application.Services;
|
||||
|
||||
public class PointOfCareService(
|
||||
ILogger<PointOfCareService> logger,
|
||||
IPointOfCareRepository pointOfCareRepository,
|
||||
Lazy<IPatientService> patientService,
|
||||
Lazy<IUnitService> unitService,
|
||||
ISubscribersService subscribersService,
|
||||
Lazy<IClientMessageService> clientMessageService,
|
||||
Lazy<IAdmissionService> admissionService,
|
||||
IHttpContextAccessor httpContextAccessor,
|
||||
ILocalAuditService auditService,
|
||||
ICacheService cacheService,
|
||||
IOptions<CacheSettings> cacheSettings)
|
||||
: IPointOfCareService
|
||||
{
|
||||
private readonly CacheSettings? _cacheSettings = cacheSettings.Value ;
|
||||
|
||||
public async Task<PointOfCare?> InsertPointOfCare(PointOfCare pointOfCare)
|
||||
{
|
||||
try
|
||||
{
|
||||
var unit = await unitService.Value.FindById(pointOfCare.UnitId);
|
||||
if (unit == null)
|
||||
{
|
||||
logger.LogError("Unit id: {unitId} Not Found. PointOfCare not inserted", pointOfCare.UnitId);
|
||||
return null;
|
||||
}
|
||||
|
||||
pointOfCare.UnitId = unit.Id;
|
||||
|
||||
await pointOfCareRepository.InsertOneAsync(pointOfCare);
|
||||
await auditService.CreateAuditLogAsync(httpContextAccessor.HttpContext?.User!, null, pointOfCare);
|
||||
return await FindById(pointOfCare.Id);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.LogError("Exception inserting pointOfCare: {pointOfCare}, Exception: {ex}", pointOfCare, ex);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task Delete(ObjectId id)
|
||||
{
|
||||
var poc = await FindById(id);
|
||||
if (poc is not { AdmissionId: null }) return;
|
||||
|
||||
await pointOfCareRepository.Delete(id);
|
||||
|
||||
await cacheService.DeleteByPatternAsync(CacheKeys.PointOfCareBase(id));
|
||||
|
||||
await auditService.CreateAuditLogAsync(httpContextAccessor.HttpContext?.User!, poc, null);
|
||||
|
||||
}
|
||||
|
||||
public async Task DeletePoCsByUnitId(ObjectId unitId)
|
||||
{
|
||||
await pointOfCareRepository.DeleteManyByUnitId(unitId);
|
||||
|
||||
await cacheService.DeleteByPatternAsync(CacheKeyPatterns.ForEntity(CacheEnum.EntityType.PontOfCare));
|
||||
|
||||
}
|
||||
|
||||
public async Task<HashSet<ObjectId>> FindAllIdCamerasInUse()
|
||||
{
|
||||
return await pointOfCareRepository.FindAllIdCamerasInUse();
|
||||
}
|
||||
public async Task<HashSet<ObjectId>> FindAllIdRelaysInUse()
|
||||
{
|
||||
return await pointOfCareRepository.FindAllIdRelaysInUse();
|
||||
}
|
||||
public async Task<HashSet<ObjectId>> FindAllIdBeaconsInUse()
|
||||
{
|
||||
return await pointOfCareRepository.FindAllIdBeaconsInUse();
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<PointOfCare>?> FindAllByUnitIdWithDevices(ObjectId unitId)
|
||||
{
|
||||
var result = await pointOfCareRepository.FindAllByUnitIdWithDevices(unitId);
|
||||
|
||||
return result ?? [];
|
||||
}
|
||||
|
||||
|
||||
public async Task<PointOfCare?> Update(PointOfCare pointOfCare)
|
||||
{
|
||||
var oldPoc = await pointOfCareRepository.FindById(pointOfCare.Id);
|
||||
await pointOfCareRepository.Update(pointOfCare);
|
||||
var updatedPoc = await GetInfo(pointOfCare.Id);
|
||||
await cacheService.DeleteByPatternAsync(CacheKeys.PointOfCareBase(pointOfCare.Id));
|
||||
await auditService.CreateAuditLogAsync(httpContextAccessor.HttpContext?.User!, oldPoc, updatedPoc);
|
||||
if (updatedPoc == null) return null;
|
||||
SendPointOfCareBroadcast(updatedPoc, OperationType.UpdatedPointOfCare);
|
||||
return updatedPoc;
|
||||
|
||||
}
|
||||
|
||||
public async Task UpdateUnit(ObjectId id, Unit unit)
|
||||
{
|
||||
var poc = await FindById(id);
|
||||
if (poc == null)
|
||||
return;
|
||||
await pointOfCareRepository.UpdateUnitId(id, unit);
|
||||
|
||||
await cacheService.DeleteByPatternAsync(CacheKeys.PointOfCareBase(id));
|
||||
|
||||
var newPoc = await FindById(id);
|
||||
await auditService.CreateAuditLogAsync(httpContextAccessor.HttpContext?.User!, poc, newPoc!);
|
||||
SendPointOfCareBroadcast(poc, OperationType.UpdatedPointOfCare);
|
||||
}
|
||||
|
||||
public async Task<List<PointOfCare>> GetAll()
|
||||
{
|
||||
var c = await pointOfCareRepository.GetAll();
|
||||
return c ?? [];
|
||||
}
|
||||
|
||||
public async Task<List<PointOfCare>> GetAllConfigs()
|
||||
{
|
||||
var c = await pointOfCareRepository.GetAllConfigs();
|
||||
return c ?? [];
|
||||
}
|
||||
|
||||
public async Task<List<PointOfCare>> GetAllLocationInfo()
|
||||
{
|
||||
var c = await pointOfCareRepository.GetAllLocationInfo();
|
||||
return c ?? [];
|
||||
}
|
||||
|
||||
public async Task<PaginationResponse<PointOfCare>> GetPaginatedPoCs(PaginationFilter filter)
|
||||
{
|
||||
var result = pointOfCareRepository.GetPaginatedPoCs(filter);
|
||||
var count = await result.CountDocumentsAsync();
|
||||
var data = await result.Skip((filter.PageNumber - 1) * filter.PageSize)
|
||||
.Limit(filter.PageSize)
|
||||
.ToCursorAsync();
|
||||
|
||||
|
||||
var dataList = await data.ToListAsync();
|
||||
return new PaginationResponse<PointOfCare>(dataList, filter.PageNumber, filter.PageSize, count);
|
||||
}
|
||||
|
||||
public async Task UpdateConfiguration(ObjectId id, PointOfCareConfiguration configuration)
|
||||
{
|
||||
var old = await pointOfCareRepository.GetPoCConfiguration(id) ??
|
||||
throw new ConflictException(HttpEnum.ErrorMessage.ConflictUpdateFailed);
|
||||
await pointOfCareRepository.UpdateConfiguration(id, configuration);
|
||||
|
||||
await cacheService.DeleteByPatternAsync(CacheKeys.PointOfCareBase(id));
|
||||
|
||||
await auditService.CreateAuditLogAsync(httpContextAccessor.HttpContext?.User!, old.Configuration,
|
||||
configuration);
|
||||
}
|
||||
|
||||
public async Task<PointOfCare?> FindById(ObjectId id)
|
||||
{
|
||||
return await pointOfCareRepository.FindByIdAllConfig(id);
|
||||
}
|
||||
public async Task<PointOfCare?> FindByIdAllConfig(ObjectId id)
|
||||
{
|
||||
return await pointOfCareRepository.FindByIdAllConfig(id);
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<PointOfCare>?> FindAllByUnitId(ObjectId unit)
|
||||
{
|
||||
var result = await pointOfCareRepository.FindAllByUnitId(unit);
|
||||
|
||||
return result ?? [];
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<PointOfCare>> FindByUnitAndStatus(ObjectId unitId, StatusEnum.PointOfCare poc,
|
||||
bool excludeVirtual = false)
|
||||
{
|
||||
return await pointOfCareRepository.FindByUnitAndStatus(unitId, poc, excludeVirtual);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check nex admission when patient has exit from poc
|
||||
/// </summary>
|
||||
/// <param name="patientLocation">PoC id</param>
|
||||
public async void CheckNextAdmission(ObjectId? patientLocation)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (patientLocation == null) return;
|
||||
var pocToCheck = await GetInfo(patientLocation.Value,null);
|
||||
if (pocToCheck != null && pocToCheck.Status != StatusEnum.PointOfCare.Locked)
|
||||
{
|
||||
if (pocToCheck.AdmissionId != null)
|
||||
{
|
||||
pocToCheck.Status = StatusEnum.PointOfCare.Reserved;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Sabemos que puede ser una lista, pero limitamos directamente a 1 elemento
|
||||
var next = await admissionService.Value.GetAdmissionByPointOfCareId(pocToCheck.Id);
|
||||
var adm = next.FirstOrDefault();
|
||||
if (adm != null)
|
||||
{
|
||||
pocToCheck.Admission = adm;
|
||||
pocToCheck.AdmissionId = adm.Id;
|
||||
pocToCheck.Status = StatusEnum.PointOfCare.Reserved;
|
||||
}
|
||||
else
|
||||
{
|
||||
pocToCheck.Status = StatusEnum.PointOfCare.Available;
|
||||
}
|
||||
}
|
||||
|
||||
await Update(pocToCheck);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
logger.LogError("Error checking next admission for PointOfCare {pocId}: {message}", patientLocation,
|
||||
e.Message);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<PointOfCare?> FindByBedAndUnitId(string? bed, ObjectId? unitId)
|
||||
{
|
||||
if (unitId == null || string.IsNullOrEmpty(bed)) return null;
|
||||
return await pointOfCareRepository.FindByBedAndUnitId(bed, unitId.Value);
|
||||
}
|
||||
|
||||
public async Task UpdateRelayConfig(PointOfCare poc)
|
||||
{
|
||||
var oldPoc = await pointOfCareRepository.GetPoCConfiguration(poc.Id);
|
||||
if (poc.Configuration?.RelayIdList != null)
|
||||
{
|
||||
await pointOfCareRepository.UpdateRelayConfig(poc.Id, poc.Configuration.RelayIdList);
|
||||
await cacheService.DeleteByPatternAsync(CacheKeys.PointOfCareBase(poc.Id));
|
||||
await auditService.CreateAuditLogAsync(httpContextAccessor.HttpContext?.User!, oldPoc, poc);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<PointOfCare>?> FindByRoom(string room)
|
||||
{
|
||||
return await pointOfCareRepository.FindByRoom(room);
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<PointOfCare>?> FindByBed(string bed)
|
||||
{
|
||||
return await pointOfCareRepository.FindByBed(bed);
|
||||
}
|
||||
|
||||
public async Task<List<PointOfCare>> FindAllByUnitIds(List<ObjectId> unitIds)
|
||||
{
|
||||
var filter = Builders<PointOfCare>.Filter.In(p => p.UnitId, unitIds);
|
||||
return await pointOfCareRepository.FindByFilter(filter);
|
||||
}
|
||||
|
||||
public async Task<PointOfCare?> GetInfo(ObjectId id, bool fillPatientData = true)
|
||||
{
|
||||
var poc = await FindById(id);
|
||||
if (poc == null) return null;
|
||||
var unit = await unitService.Value.FindById(poc.UnitId);
|
||||
if (unit is { Name: not null })
|
||||
poc.UnitName = unit.Name;
|
||||
if (fillPatientData)
|
||||
{
|
||||
var patient = await patientService.Value.GetByPointOfCare(poc);
|
||||
if (patient != null)
|
||||
{
|
||||
poc.Patientid = patient.Id;
|
||||
poc.Patient = patient;
|
||||
}
|
||||
|
||||
if (poc.AdmissionId != null)
|
||||
{
|
||||
var admission = await admissionService.Value.GetAdmissionByIdAsync(poc.AdmissionId.Value);
|
||||
if (admission != null)
|
||||
poc.Admission = admission;
|
||||
}
|
||||
}
|
||||
|
||||
return poc;
|
||||
}
|
||||
|
||||
public async Task<PointOfCare?> GetInfo(ObjectId id, LocaleEnum? locale, bool fillPatientData = true,
|
||||
CancellationToken ct = default)
|
||||
{
|
||||
var (key, ttl) = CacheKeys.PointOfCareBaseKeyWithTtl(_cacheSettings, id);
|
||||
var poc = await cacheService.GetOrSetObjectAsync(key,
|
||||
() => pointOfCareRepository.FindById(id),
|
||||
ttl, ct);
|
||||
|
||||
if (poc == null || !fillPatientData)
|
||||
return poc;
|
||||
|
||||
var unit = await unitService.Value.FindById(poc.UnitId);
|
||||
if (unit?.Name != null)
|
||||
poc.UnitName = unit.Name;
|
||||
|
||||
var patient = locale != null
|
||||
? await patientService.Value.GetByPointOfCareAndLocale(poc, unit, locale)
|
||||
: await patientService.Value.GetByPointOfCare(poc);
|
||||
|
||||
if (patient != null)
|
||||
{
|
||||
poc.Patientid = patient.Id;
|
||||
poc.Patient = patient;
|
||||
}
|
||||
|
||||
if (poc.AdmissionId == null) return poc;
|
||||
|
||||
var admission = await admissionService.Value.GetAdmissionByIdAsync(poc.AdmissionId.Value);
|
||||
if (admission != null)
|
||||
poc.Admission = admission;
|
||||
return poc;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public async Task<PointOfCare?> FindPoCByPatientId(ObjectId patientId)
|
||||
{
|
||||
var patient = await patientService.Value.FindById(patientId);
|
||||
if (patient is { PointOfCareId: not null })
|
||||
return await FindById(patient.PointOfCareId.Value);
|
||||
return null;
|
||||
}
|
||||
|
||||
public async Task<PointOfCare?> FindPoCByPatientNumber(string patientNumber)
|
||||
{
|
||||
var patient = await patientService.Value.FindByPatientNumber(patientNumber);
|
||||
if (patient is { PointOfCareId: not null })
|
||||
return await FindById(patient.PointOfCareId.Value);
|
||||
return null;
|
||||
}
|
||||
|
||||
public async Task<long> CountPoCsByUnitId(ObjectId unitId)
|
||||
{
|
||||
return await pointOfCareRepository.CountByUnitId(unitId);
|
||||
}
|
||||
|
||||
public async Task<long> CountVirtualPoCsByUnitId(ObjectId unitId)
|
||||
{
|
||||
return await pointOfCareRepository.CountVirtualsByUnitId(unitId);
|
||||
}
|
||||
|
||||
public async Task SetPointOfCareStatus(ObjectId id, StatusEnum.PointOfCare status)
|
||||
{
|
||||
var pointOfCare = await GetInfo(id,null);
|
||||
|
||||
if (pointOfCare == null) return;
|
||||
|
||||
pointOfCare.Status = status;
|
||||
|
||||
await pointOfCareRepository.Update(pointOfCare);
|
||||
|
||||
await cacheService.DeleteByPatternAsync(CacheKeys.PointOfCareBase(id));
|
||||
|
||||
var oldPoc = await auditService.DeepCopyAsync(pointOfCare);
|
||||
if (oldPoc != null)
|
||||
await auditService.CreateAuditLogAsync(httpContextAccessor.HttpContext?.User!, oldPoc, pointOfCare);
|
||||
// await _patientService.Value.UpdatePatientAltable()
|
||||
SendPointOfCareBroadcast(pointOfCare, OperationType.UpdatedPointOfCare);
|
||||
}
|
||||
|
||||
public async Task<PointOfCare?> FindPoCByPatientLocation(PatientLocation patientLocation)
|
||||
{
|
||||
return await pointOfCareRepository.FindByPatientLocation(patientLocation);
|
||||
}
|
||||
|
||||
private void SendPointOfCareBroadcast(PointOfCare pointOfCare, OperationType operation)
|
||||
{
|
||||
try
|
||||
{
|
||||
var subscribers = subscribersService.GetSubscribers()
|
||||
.Where(s => s.LocationIds.Any(c => c == pointOfCare.Id)).ToList();
|
||||
|
||||
foreach (var subscriber in subscribers)
|
||||
_ = clientMessageService.Value.SendAsync(subscriber.Id, operation, pointOfCare);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.LogError("Exception sending PoC broadcast. Operation type: {op}. Exception: {ex}",
|
||||
operation.ToString(), ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user