Creado apartir del commit b888de6c92056de294456f581a56e25e734d4ab7 de develop
This commit is contained in:
@@ -0,0 +1,400 @@
|
||||
using System.Reflection;
|
||||
using adas_core.Application.Exceptions;
|
||||
using adas_core.Application.Repositories.Interfaces;
|
||||
using adas_core.Application.Services.Interfaces;
|
||||
using adas_core.Application.Subscriptions;
|
||||
using adas_core.Domain.Enums;
|
||||
using adas_core.Domain.Models;
|
||||
using adas_core.Domain.Models.DTO;
|
||||
using adas_core.Domain.Models.Masters;
|
||||
using adas_core.Domain.Models.MongoModels;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using MongoDB.Bson;
|
||||
|
||||
namespace adas_core.Application.Services;
|
||||
|
||||
public class DischargeService : IDischargeService
|
||||
{
|
||||
private readonly ILocalAuditService _auditService;
|
||||
private readonly IClientMessageService _clientMessageService;
|
||||
private readonly IDischargeRepository _dischargeRepository;
|
||||
private readonly IHttpContextAccessor _httpContextAccessor;
|
||||
private readonly ILogger<DischargeService> _logger;
|
||||
private readonly IMasterListServiceFactory _masterListServiceFactory;
|
||||
private readonly Lazy<IPatientService> _patientServiceLazy;
|
||||
private readonly IPointOfCareService _pointOfCareService;
|
||||
private readonly ISubscribersService _subscribersService;
|
||||
private readonly IUnitService _unitService;
|
||||
|
||||
public DischargeService(ILogger<DischargeService> logger,
|
||||
ISubscribersService subscribersService,
|
||||
IDischargeRepository dischargeRepository,
|
||||
Lazy<IPatientService> patientServiceLazy,
|
||||
IClientMessageService clientMessageService,
|
||||
IPointOfCareService pointOfCareService,
|
||||
IHttpContextAccessor httpContextAccessor,
|
||||
ILocalAuditService auditService,
|
||||
IUnitService unitService,
|
||||
IMasterListServiceFactory masterListServiceFactory)
|
||||
{
|
||||
_logger = logger;
|
||||
_subscribersService = subscribersService;
|
||||
_dischargeRepository = dischargeRepository;
|
||||
_patientServiceLazy = patientServiceLazy;
|
||||
_clientMessageService = clientMessageService;
|
||||
_pointOfCareService = pointOfCareService;
|
||||
_pointOfCareService = pointOfCareService;
|
||||
_httpContextAccessor = httpContextAccessor;
|
||||
_auditService = auditService;
|
||||
_unitService = unitService;
|
||||
_masterListServiceFactory = masterListServiceFactory;
|
||||
}
|
||||
|
||||
|
||||
public async Task DeleteDischargeAsync(Discharge discharge)
|
||||
{
|
||||
//var patient = await _patientServiceLazy.Value.FindById(discharge.PatientId);
|
||||
//if (!discharge.MedicalDischarge.HasValue || !discharge.AdminDischarge.HasValue
|
||||
// // || DischargeStatusType.NoAltable.ToString().Equals(patient?.DischargeStatus?.OptionType)
|
||||
// )
|
||||
//{
|
||||
// _logger.LogError("The patient cannot be discharged");
|
||||
// return;
|
||||
//}
|
||||
await DeleteDischargeByIdAsync(discharge.Id);
|
||||
}
|
||||
|
||||
public async Task DeleteDischargeByIdAsync(ObjectId dischargeId)
|
||||
{
|
||||
try
|
||||
{
|
||||
var dischargeAux = await _dischargeRepository.FindById(dischargeId);
|
||||
if (dischargeAux == null)
|
||||
{
|
||||
_logger.LogError("Error Discharge not found, id: {discharge} ", dischargeId);
|
||||
return;
|
||||
}
|
||||
|
||||
await _dischargeRepository.Delete(dischargeId);
|
||||
|
||||
_logger.LogInformation("Discharge id: {dischargeId} DELETED ", dischargeId);
|
||||
|
||||
//var patient = await _patientServiceLazy.Value.FindById(dischargeAux.PatientId);
|
||||
// if (patient != null)
|
||||
// await _patientServiceLazy.Value.ArchivePatient(patient);
|
||||
// else
|
||||
// _logger.LogError("Patient not found on Discharge id: {discharge} ", dischargeId);
|
||||
|
||||
await _auditService.CreateAuditLogAsync(_httpContextAccessor.HttpContext?.User!, dischargeAux, null);
|
||||
SendDischargeBroadcast(dischargeAux, OperationType.DeleteDischarge);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError("Exception deleting discharge id:{admission} . Exception: {ex}", dischargeId, ex);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<long> CountDischargesByUnitId(ObjectId unitId)
|
||||
{
|
||||
return await _dischargeRepository.CountByUnitId(unitId);
|
||||
}
|
||||
|
||||
public async Task<Discharge?> GetDischargeByIdAsync(ObjectId dischargeId)
|
||||
{
|
||||
var result = await _dischargeRepository.FindById(dischargeId) ??
|
||||
throw new NotFoundException(HttpEnum.ErrorMessage.NotFoundResourceMissing);
|
||||
if (result.PointOfCareId == null)
|
||||
return result;
|
||||
|
||||
var poc = await _pointOfCareService.GetInfo(result.PointOfCareId.Value, null,false);
|
||||
result.PatientLocation = new PatientLocation(poc?.UnitName, poc?.Bed, poc?.Room);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public async Task<IEnumerable<Discharge>> GetDischargesAsync()
|
||||
{
|
||||
return await _dischargeRepository.FindAll();
|
||||
}
|
||||
|
||||
public async Task<Discharge?> GetDischargeByPatientId(ObjectId patientId)
|
||||
{
|
||||
try
|
||||
{
|
||||
var discharge = await _dischargeRepository.GetByPatientId(patientId);
|
||||
if (discharge == null)
|
||||
_logger.LogError("Discharge not found by patient Id {id}", patientId);
|
||||
if (discharge is { PointOfCareId: not null })
|
||||
{
|
||||
var poc = await _pointOfCareService.GetInfo(discharge.PointOfCareId.Value, null,false);
|
||||
discharge.PatientLocation = new PatientLocation(poc?.UnitName, poc?.Bed, poc?.Room);
|
||||
}
|
||||
|
||||
return discharge;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError("Exception getting discharge by patient id: {id} . Exception: {ex}", patientId, ex);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<Discharge?> InsertDischarge(Discharge discharge)
|
||||
{
|
||||
await _dischargeRepository.InsertOneAsync(discharge);
|
||||
|
||||
var dischargeAux = await _dischargeRepository.FindById(discharge.Id) ??
|
||||
throw new ConflictException(HttpEnum.ErrorMessage.ConflictCreationFailed);
|
||||
_logger.LogInformation("Discharge: {discharge} INSERTED", discharge);
|
||||
await _auditService.CreateAuditLogAsync(_httpContextAccessor.HttpContext?.User!, null, dischargeAux);
|
||||
SendDischargeBroadcast(discharge, OperationType.NewDischarge);
|
||||
return dischargeAux;
|
||||
}
|
||||
|
||||
public async Task<Discharge?> GetDischargeByLocation(PatientLocation location)
|
||||
{
|
||||
try
|
||||
{
|
||||
return await _dischargeRepository.GetDischargeByLocation(location);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.LogError($"Unable to get discharge by location on service Exception: {e}");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<Discharge?> GetDischargeByPointOfCareId(ObjectId poc)
|
||||
{
|
||||
try
|
||||
{
|
||||
var discharge = await _dischargeRepository.GetDischargeByPointOfCareId(poc);
|
||||
if (discharge == null)
|
||||
_logger.LogInformation("Discharge not found by PointOfCareId {id}", poc);
|
||||
if (discharge is { PointOfCareId: not null })
|
||||
{
|
||||
var pocInfo = await _pointOfCareService.GetInfo(discharge.PointOfCareId.Value, null,false);
|
||||
discharge.PatientLocation = new PatientLocation(pocInfo?.UnitName, pocInfo?.Bed, pocInfo?.Room);
|
||||
}
|
||||
|
||||
return discharge;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
_logger.LogError($"Unable to get discharge by location on service Exception: {e}");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<Discharge?> GetDischargeByPointOfCareIdWithLocale(ObjectId location, LocaleEnum dataLocale)
|
||||
{
|
||||
var discharge = await GetDischargeByPointOfCareId(location);
|
||||
if (discharge == null) return null;
|
||||
var unit = await _unitService.FindById(discharge.UnitId);
|
||||
if (unit == null) return discharge;
|
||||
var dischargeWithLocale = await GetDischargeWithLocale(unit, discharge, dataLocale);
|
||||
return dischargeWithLocale;
|
||||
}
|
||||
|
||||
public async Task UpdateDischargeAsync(Discharge discharge)
|
||||
{
|
||||
var oldDischarge = await GetDischargeByIdAsync(discharge.Id) ??
|
||||
throw new ConflictException(HttpEnum.ErrorMessage.ConflictUpdateFailed);
|
||||
await _dischargeRepository.Update(discharge);
|
||||
await _auditService.CreateAuditLogAsync(_httpContextAccessor.HttpContext?.User!, oldDischarge, discharge);
|
||||
SendDischargeBroadcast(discharge, OperationType.UpdateDischarge);
|
||||
_logger.LogInformation("Discharge: {discharge} UPDATED", discharge);
|
||||
}
|
||||
|
||||
|
||||
public async Task SaveRequest(ApiRequest apiRequest)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (apiRequest.Discharge?.Patient == null) return;
|
||||
|
||||
var patientId = apiRequest.Discharge.Patient.Id;
|
||||
|
||||
var patient = await _patientServiceLazy.Value.FindById(patientId);
|
||||
if (patient == null)
|
||||
{
|
||||
_logger.LogError("Error discharging patient id: {id} NOT FOUND", patientId);
|
||||
return;
|
||||
}
|
||||
|
||||
await _patientServiceLazy.Value.Update(apiRequest.Discharge.Patient);
|
||||
|
||||
switch (apiRequest.Type)
|
||||
{
|
||||
case "NewDischarge":
|
||||
{
|
||||
//TODO: ver qué tipos llegan
|
||||
if (!"Altable".Equals(apiRequest.Discharge.Patient.DischargeStatus?.OptionType))
|
||||
{
|
||||
_logger.LogError("Error discharging. Patient not altable: {patient}", patient);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
await _dischargeRepository.InsertOneAsync(apiRequest.Discharge);
|
||||
await _auditService.CreateAuditLogAsync(_httpContextAccessor.HttpContext?.User!, null,
|
||||
apiRequest.Discharge);
|
||||
SendDischargeBroadcast(apiRequest.Discharge, OperationType.NewDischarge);
|
||||
|
||||
break;
|
||||
}
|
||||
case "UpdateDischarge":
|
||||
{
|
||||
await GetDischargeByIdAsync(apiRequest.Discharge.Id);
|
||||
await UpdateDischargeAsync(apiRequest.Discharge);
|
||||
break;
|
||||
}
|
||||
case "DeleteDischarge":
|
||||
{
|
||||
if (StatusEnum.Discharge.NoAltable.ToString().Equals(patient.DischargeStatus?.OptionType))
|
||||
{
|
||||
_logger.LogError("Error deleting discharge. Patient altable: {patient}", patient);
|
||||
return;
|
||||
}
|
||||
|
||||
await DeleteDischargeAsync(apiRequest.Discharge);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError("Exception processing discharge api request {discharge} . Exception: {ex}",
|
||||
apiRequest.Discharge, ex);
|
||||
}
|
||||
}
|
||||
|
||||
public Task SaveRequestAsync(ApiRequest apiRequest)
|
||||
{
|
||||
return Task.FromResult(Task.Run(async () => { await SaveRequest(apiRequest); }));
|
||||
}
|
||||
|
||||
// Revisar
|
||||
public async void SendDischargeBroadcast(Discharge discharge, OperationType operation)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (discharge.PointOfCareId == null)
|
||||
{
|
||||
_logger.LogError("Error sending discharge broadcast. Unit name is null or empty {discharge} .",
|
||||
discharge);
|
||||
return;
|
||||
}
|
||||
|
||||
var subscribersGroup = _subscribersService.GetSubscribers()
|
||||
.Where(s => s.LocationIds.Any(c => c == discharge.PointOfCareId)).GroupBy(h => h.Locale)
|
||||
.ToList();
|
||||
|
||||
var unit = await _unitService.FindById(discharge.UnitId);
|
||||
foreach (var group in subscribersGroup)
|
||||
{
|
||||
var locale = group.Key ?? LocaleEnum.Default;
|
||||
IEnumerable<WsSubscriber> subscribers = group;
|
||||
|
||||
foreach (var subscriber in subscribers)
|
||||
{
|
||||
var dischargeWithLocale = await GetDischargeWithLocale(unit, discharge, locale);
|
||||
_ = _clientMessageService.SendAsync(subscriber.Id, operation, dischargeWithLocale);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError("Exception sending discharge broadcast. Operation type: {op}. Exception: {ex}",
|
||||
operation.ToString(), ex);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task UpdatePatientMasterListItemChange(UpdateOptionMasterListDto opt, IEnumerable<Unit> unitList,
|
||||
string typeName)
|
||||
{
|
||||
var unitIds = unitList.Select(x => x.Id).ToList();
|
||||
await _dischargeRepository.GetDischargesByUnitIds(unitIds);
|
||||
var dischargeUpdatedList = await _dischargeRepository.UpdateMasterListOption(unitIds, opt, typeName);
|
||||
var updatedList = dischargeUpdatedList as Discharge[] ?? dischargeUpdatedList.ToArray();
|
||||
foreach (var discharge in updatedList)
|
||||
{
|
||||
var oldDischarge = updatedList.FirstOrDefault(dis => dis.Id == discharge.Id);
|
||||
await _auditService.CreateAuditLogAsync(_httpContextAccessor.HttpContext?.User!, oldDischarge!, discharge);
|
||||
SendDischargeBroadcast(discharge, OperationType.UpdateDischarge);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task DeletePatientMasterListItem(OptionList opt, IEnumerable<Unit> unitList, string typeName)
|
||||
{
|
||||
var unitIds = unitList.Select(x => x.Id).ToList();
|
||||
var patientUpdatedList = await _dischargeRepository.DeleteMasterListOption(unitIds, opt, typeName);
|
||||
foreach (var discharge in patientUpdatedList)
|
||||
{
|
||||
var dischargeUpdated = await GetDischargeByIdAsync(discharge.Id);
|
||||
await _auditService.CreateAuditLogAsync(_httpContextAccessor.HttpContext?.User!, discharge, null);
|
||||
if (dischargeUpdated != null)
|
||||
SendDischargeBroadcast(discharge, OperationType.UpdateDischarge);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task DeleteDischargesByUnitId(ObjectId unitId)
|
||||
{
|
||||
await _dischargeRepository.DeleteByUnitId(unitId);
|
||||
}
|
||||
|
||||
private async Task<Discharge> GetDischargeWithLocale(Unit? unit, Discharge discharge, LocaleEnum locale)
|
||||
{
|
||||
if (unit == null)
|
||||
return discharge;
|
||||
|
||||
if (locale == LocaleEnum.Default)
|
||||
return discharge;
|
||||
|
||||
// Campos del discharge que deben traducirse
|
||||
var listMap = new List<(string field, ObjectId? listId, MasterListType type)>
|
||||
{
|
||||
("serviceOption", unit.ServiceListId, MasterListType.ServiceList),
|
||||
("destinationOption", unit.DestinationListId, MasterListType.DestinationList)
|
||||
};
|
||||
|
||||
foreach (var (field, listId, masterListType) in listMap)
|
||||
{
|
||||
if (listId == null)
|
||||
continue;
|
||||
|
||||
// Obtener propiedad desde DISCHARGE, no Patient
|
||||
var prop = typeof(Discharge).GetProperty(
|
||||
field,
|
||||
BindingFlags.Public | BindingFlags.Instance | BindingFlags.IgnoreCase);
|
||||
|
||||
if (prop == null)
|
||||
continue;
|
||||
|
||||
var propValue = prop.GetValue(discharge);
|
||||
if (propValue == null)
|
||||
continue;
|
||||
|
||||
// Cargar master list traducida según locale
|
||||
var listObj = await _masterListServiceFactory
|
||||
.GetMasterListById(masterListType, listId.Value, locale);
|
||||
|
||||
if (listObj == null)
|
||||
continue;
|
||||
|
||||
var master = listObj as dynamic;
|
||||
|
||||
IEnumerable<OptionList> masterOptions = master.Options;
|
||||
|
||||
// El campo puede ser OptionList simple
|
||||
if (propValue is OptionList { Id: not null } option)
|
||||
{
|
||||
var translated = masterOptions.FirstOrDefault(o => o.Id == option.Id);
|
||||
if (translated != null) option.Name = translated.Name; // Solo traducimos el nombre
|
||||
}
|
||||
}
|
||||
|
||||
return discharge;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user