363 lines
13 KiB
C#
363 lines
13 KiB
C#
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.AppSettings;
|
|
using adas_core.Domain.Models.MongoModels;
|
|
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 DiagnosisService : IDiagnosisService
|
|
{
|
|
private readonly ILocalAuditService _auditService;
|
|
private readonly Lazy<ICalculatedObservationsService> _calculatedObservations;
|
|
private readonly IClientMessageService _clientMessageService;
|
|
private readonly IDiagnosisArchiveRepository _diagnosisArchiveRepository;
|
|
|
|
private readonly List<string> _diagnosisCode = [];
|
|
private readonly IDiagnosisRepository _diagnosisRepository;
|
|
|
|
private readonly string _diagnosisSystem;
|
|
private readonly IHttpContextAccessor _httpContextAccessor;
|
|
private readonly ILogger<DiagnosisService> _logger;
|
|
private readonly Lazy<IPatientService> _patientService;
|
|
private readonly ISubscribersService _subscribersService;
|
|
private readonly IUnitService _unitService;
|
|
|
|
|
|
public DiagnosisService(
|
|
Lazy<IPatientService> patientService,
|
|
IOptions<ApiSettings> apiSettings,
|
|
IDiagnosisRepository diagnosisRepository,
|
|
IDiagnosisArchiveRepository diagnosisArchiveRepository,
|
|
ILogger<DiagnosisService> logger,
|
|
IClientMessageService clientMessageService,
|
|
ISubscribersService subscribersService,
|
|
Lazy<ICalculatedObservationsService> calculatedObservations,
|
|
IHttpContextAccessor httpContextAccessor,
|
|
ILocalAuditService auditService,
|
|
IUnitService unitService)
|
|
{
|
|
_patientService = patientService;
|
|
_diagnosisRepository = diagnosisRepository;
|
|
_diagnosisArchiveRepository = diagnosisArchiveRepository;
|
|
_logger = logger;
|
|
_clientMessageService = clientMessageService;
|
|
_subscribersService = subscribersService;
|
|
_calculatedObservations = calculatedObservations;
|
|
_unitService = unitService;
|
|
_httpContextAccessor = httpContextAccessor;
|
|
_auditService = auditService;
|
|
|
|
|
|
_diagnosisSystem = apiSettings.Value.DiagnosisSystem ?? "CUSTOM";
|
|
|
|
if (apiSettings.Value.DiagnosisCode.Any())
|
|
_diagnosisCode = apiSettings.Value.DiagnosisCode;
|
|
}
|
|
|
|
// private async Task SendBroadcast(PatientDiagnosis diagnosis)
|
|
// {
|
|
// var patient = await _patientService.Value.FindById(diagnosis.PatientId);
|
|
// if (patient == null) return;
|
|
//
|
|
//
|
|
// var subscribers = _subscribersService.GetSubscribers().Where(s =>
|
|
// (s.SubscriptionType == SubscriptionType.Box && s.Box == patient.Bed &&
|
|
// s.Section == patient.UnitString) ||
|
|
// (s.SubscriptionType == SubscriptionType.Section && s.Section == patient.UnitString)).ToList();
|
|
// subscribers.ForEach(Action);
|
|
// return;
|
|
//
|
|
// async void Action(WsSubscriber subscriber) =>
|
|
// await _clientMessageService.SendAsync(subscriber.Id, OperationType.Diagnosis, diagnosis);
|
|
// }
|
|
|
|
public async Task Archive(Patient patient)
|
|
{
|
|
await ArchiveByPatientId(patient.Id);
|
|
}
|
|
|
|
public async Task ArchiveByPatientId(ObjectId id)
|
|
{
|
|
_logger.LogDebug("Archive Diagnoses by Patient Id {id}", id);
|
|
using (var cursor = await FindByPatientIdAsync(id))
|
|
{
|
|
while (await cursor.MoveNextAsync())
|
|
foreach (var current in cursor.Current)
|
|
await _diagnosisArchiveRepository.InsertOneAsync(current);
|
|
}
|
|
|
|
await DeleteByPatientId(id);
|
|
}
|
|
|
|
public async Task DeleteByPatientId(ObjectId id)
|
|
{
|
|
_logger.LogDebug("Delete Diagnoses by Patient Id {id}", id);
|
|
var oldPatient = await _diagnosisRepository.GetByPatient(id);
|
|
await _diagnosisRepository.DeleteByPatientId(id);
|
|
await _auditService.CreateAuditLogAsync(_httpContextAccessor.HttpContext?.User!, oldPatient, null);
|
|
}
|
|
|
|
public async Task<List<PatientDiagnosis>> GetByPatientId(ObjectId patientId)
|
|
{
|
|
var diagnosis = await _diagnosisRepository.GetByPatient(patientId);
|
|
|
|
return diagnosis;
|
|
}
|
|
|
|
|
|
public Task SaveRequest(ApiRequest apiRequest)
|
|
{
|
|
return Task.FromResult(Task.Run(async () => { await SaveRequest(apiRequest, null); }));
|
|
}
|
|
|
|
public Task SaveRequestAsync(ApiRequest apiRequest)
|
|
{
|
|
return Task.FromResult(Task.Run(async () => { await SaveRequest(apiRequest, null); }));
|
|
}
|
|
|
|
public async Task ProcessDiagnosisObservation(ApiRequest apiRequest, Patient patient)
|
|
{
|
|
_logger.LogDebug("INSERT DiagnosisObservation from obsservation");
|
|
|
|
var time = apiRequest.ObservationData?.Time;
|
|
if (time == null)
|
|
_logger.LogWarning("Processing diagnosis without time. Set Datetime now {DateTimeNow}. ", DateTime.Now);
|
|
|
|
var obs = new PatientDiagnosis
|
|
{
|
|
CodingSystem = _diagnosisSystem,
|
|
Time = time ?? DateTime.Now,
|
|
PatientId = patient.Id,
|
|
MessageTime = apiRequest.MessageTime
|
|
};
|
|
|
|
if (apiRequest.Observations == null)
|
|
{
|
|
_logger.LogError("ApiRequest Observations null. ");
|
|
return;
|
|
}
|
|
|
|
for (var i = 0; i <= apiRequest.Observations.Count - 1; i++)
|
|
{
|
|
var value = apiRequest.Observations[i].Value;
|
|
|
|
var strValue = value.ToString() ?? "null";
|
|
|
|
switch (apiRequest.Observations[i].Code)
|
|
{
|
|
case "272099008":
|
|
obs.Description = strValue;
|
|
break;
|
|
|
|
case "1000000013":
|
|
obs.Label = strValue;
|
|
break;
|
|
|
|
case "1000000014":
|
|
obs.Code = strValue;
|
|
break;
|
|
|
|
case "394731006":
|
|
obs.State = strValue;
|
|
break;
|
|
|
|
case "272125009":
|
|
obs.Category = strValue;
|
|
break;
|
|
|
|
case "398201009":
|
|
if (DateTime.TryParse(apiRequest.Observations[i].Value.ToString(), out var startTime))
|
|
obs.StartTime = startTime;
|
|
break;
|
|
|
|
case "397898000":
|
|
if (DateTime.TryParse(apiRequest.Observations[i].Value.ToString(), out var endTime))
|
|
obs.EndTime = endTime;
|
|
break;
|
|
}
|
|
}
|
|
|
|
await InsertDiagnosis(obs);
|
|
}
|
|
|
|
public async Task SaveRequest(ApiRequest apiRequest, Patient? patient)
|
|
{
|
|
if (patient == null)
|
|
{
|
|
_logger.LogDebug("message:ApiRequest Diagnosis");
|
|
if (string.IsNullOrEmpty(apiRequest.PatientNumber) &&
|
|
string.IsNullOrEmpty(apiRequest.Location?.UnitName))
|
|
{
|
|
_logger.LogDebug("person and PointOfCare are nulls");
|
|
throw new ApiRequestException("person and PointOfCare are nulls");
|
|
}
|
|
|
|
_logger.LogDebug("patientNumber: {apiRequestpatientNumber} location: {apiRequestlocation}",
|
|
apiRequest.PatientNumber, apiRequest.Location);
|
|
_logger.LogDebug("RequestType: {apiRequesttype}", apiRequest.Type);
|
|
|
|
patient = await _patientService.Value.FindPatientByApiRequest(apiRequest);
|
|
}
|
|
|
|
if (patient == null)
|
|
{
|
|
// NO PATIENTS OR LOCATIONS WERE FOUND
|
|
_logger.LogWarning(
|
|
"Observation for patient: {apiRequestpatientNumber} with location: {apiRequestlocation} not found, ignoring",
|
|
apiRequest.PatientNumber, apiRequest.Location);
|
|
return;
|
|
}
|
|
|
|
var unitConfig = await _unitService.FindById(patient.UnitId);
|
|
if (!Hl7Utils.ManageAutoAdt(unitConfig, null, _logger, "ORU Diagnosis")) return;
|
|
|
|
switch (apiRequest.Type)
|
|
{
|
|
//* ORU_R01 - Unsolicited transmission of an observation message
|
|
//* ORU_R40 - Unsolicited transmission of an alert observation message
|
|
|
|
case "ORU_R01":
|
|
case "ORU_R40":
|
|
|
|
// OBSERVATIONS
|
|
if (apiRequest.Observation != null && apiRequest.Observations?.FirstOrDefault() == null)
|
|
apiRequest.Observations = [apiRequest.Observation];
|
|
|
|
if (apiRequest.Observations != null)
|
|
{
|
|
var obrcode = apiRequest.ObservationData?.Code;
|
|
|
|
if (apiRequest.ObservationData?.Value != null)
|
|
apiRequest.Observations.Add(new PatientObservation
|
|
{ Value = apiRequest.ObservationData.Value });
|
|
|
|
if (obrcode != null && _diagnosisCode.Contains(obrcode))
|
|
_ = ProcessDiagnosisObservation(apiRequest, patient);
|
|
}
|
|
|
|
|
|
break;
|
|
default:
|
|
_logger.LogWarning("ApiRequest type {apiRequesttype} sis not valid for Diagnosis",
|
|
apiRequest.Type);
|
|
throw new ApiRequestException("ApiRequest type " + apiRequest.Type +
|
|
" is not valid for Diagnosis");
|
|
}
|
|
}
|
|
|
|
public async Task ProcessDiagnosis(List<PatientDiagnosis> diagnosis, Patient patient, DateTime messageTime)
|
|
{
|
|
_logger.LogDebug("INSERT DiagnosisObservation from diagnosis");
|
|
|
|
foreach (var d in diagnosis)
|
|
{
|
|
d.PatientId = patient.Id;
|
|
d.Time = messageTime;
|
|
await InsertDiagnosis(d);
|
|
}
|
|
}
|
|
|
|
public async Task UpdateManyObjectId(string nameId, ObjectId id, ObjectId oldId)
|
|
{
|
|
await _diagnosisRepository.UpdateManyObjectId(nameId, id, oldId);
|
|
}
|
|
|
|
public async Task<List<PatientDiagnosis>> GetByPatient(ObjectId id)
|
|
{
|
|
return await _diagnosisRepository.GetByPatient(id);
|
|
}
|
|
|
|
public async Task Insert(PatientDiagnosis diagnosis)
|
|
{
|
|
_logger.LogDebug("Insert {diagnosis}", diagnosis);
|
|
var diag = await MapDiagnosis(diagnosis);
|
|
if (diag != null)
|
|
{
|
|
await _diagnosisRepository.InsertOneAsync(diag);
|
|
await SendBroadcast(diag);
|
|
}
|
|
}
|
|
|
|
private async Task<PatientDiagnosis?> MapDiagnosis(PatientDiagnosis diagnosis)
|
|
{
|
|
var diagnosis2 = await _calculatedObservations.Value.Map(diagnosis);
|
|
if (diagnosis2 == null) _logger.LogDebug("Mapping {diagnosis}: Ignored", diagnosis2);
|
|
|
|
return diagnosis2;
|
|
}
|
|
|
|
private async Task SendBroadcast(PatientDiagnosis diagnosis)
|
|
{
|
|
var patient = await _patientService.Value.FindById(diagnosis.PatientId);
|
|
if (patient == null) return;
|
|
|
|
var displaySubscribers = _subscribersService.GetSubscribers().Where(s =>
|
|
!s.Locations.IsNullOrEmpty() && s.Locations.Any(c =>
|
|
c.UnitName == patient.Location.UnitName &&
|
|
c.Bed == patient.Location.Bed &&
|
|
c.Room == patient.Location.Room
|
|
)).ToList();
|
|
|
|
displaySubscribers.ForEach(Action);
|
|
return;
|
|
|
|
void Action(WsSubscriber subscriber)
|
|
{
|
|
_clientMessageService.SendAsync(subscriber.Id, OperationType.Diagnosis, diagnosis);
|
|
}
|
|
}
|
|
|
|
public Task<IAsyncCursor<PatientDiagnosis>> FindByPatientIdAsync(ObjectId patientId)
|
|
{
|
|
return _diagnosisRepository.FindByPatientIdAsync(patientId);
|
|
}
|
|
|
|
public async Task InsertDiagnosis(PatientDiagnosis diagnosis)
|
|
{
|
|
try
|
|
{
|
|
_logger.LogDebug("Insert {diagnosis}", diagnosis);
|
|
var diag = await MapDiagnosis(diagnosis);
|
|
if (diag == null)
|
|
{
|
|
_logger.LogError("Mepped diagnosis is null. Diagnosis: {diagnosis}", diagnosis);
|
|
}
|
|
else
|
|
{
|
|
var dgdb = await _diagnosisRepository.FindByPatientIdAndCode(diag.PatientId, diag.Code,
|
|
diag.CodingSystem);
|
|
|
|
if (dgdb != null)
|
|
{
|
|
var auxDgdb = dgdb;
|
|
diag.Id = dgdb.Id;
|
|
diag.Time = dgdb.Time;
|
|
diag.UpdateDate = diagnosis.Time;
|
|
await _diagnosisRepository.UpdateOneAsync(diag.Id, diag);
|
|
await _auditService.CreateAuditLogAsync(_httpContextAccessor.HttpContext?.User!, auxDgdb, dgdb);
|
|
}
|
|
else
|
|
{
|
|
await _diagnosisRepository.InsertOneAsync(diagnosis);
|
|
await _auditService.CreateAuditLogAsync(_httpContextAccessor.HttpContext?.User!, null, diagnosis);
|
|
}
|
|
|
|
_ = SendBroadcast(diagnosis);
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
_logger.LogError("Error inserting diagnosis. Diagnosis: {diagnosis}. Exception:{ex}", diagnosis, ex);
|
|
}
|
|
}
|
|
} |