Creado apartir del commit b888de6c92056de294456f581a56e25e734d4ab7 de develop
This commit is contained in:
@@ -0,0 +1,224 @@
|
||||
using adas_core.Application.Services.Interfaces;
|
||||
using adas_core.Domain.Enums;
|
||||
using adas_core.Domain.Models;
|
||||
using adas_core.Domain.Models.GroupedObservations;
|
||||
using adas_core.Domain.Utils;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using MongoDB.Bson;
|
||||
|
||||
namespace adas_core.Application.Subscriptions;
|
||||
|
||||
public class SubscriberGroupedService(
|
||||
ICacheService? cacheService,
|
||||
IGroupedObservationService groupedObservationService,
|
||||
ILogger<SubscriberGroupedService> logger,
|
||||
Lazy<IClientMessageService> clientMessageService)
|
||||
: ISubscriberGroupedService
|
||||
{
|
||||
private List<WsSubscriberGrouped> _subscriberGrouped = [];
|
||||
|
||||
|
||||
//private static readonly ILogger _logger = Log.ForContext<SubscriberGrouped>();
|
||||
|
||||
public List<WsSubscriberGrouped> SubscriberGroupedList
|
||||
{
|
||||
get
|
||||
{
|
||||
lock (_subscriberGrouped)
|
||||
{
|
||||
return _subscriberGrouped;
|
||||
}
|
||||
}
|
||||
set
|
||||
{
|
||||
lock (_subscriberGrouped)
|
||||
{
|
||||
_subscriberGrouped = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public List<WsSubscriberGrouped> GetGrouped()
|
||||
{
|
||||
lock (_subscriberGrouped)
|
||||
{
|
||||
return _subscriberGrouped.ToList();
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveGroupedObsByPatientId(string patientId)
|
||||
{
|
||||
lock (_subscriberGrouped)
|
||||
{
|
||||
var itemToRemove = _subscriberGrouped.Where(c => c.PatientId.ToString() == patientId).ToList();
|
||||
itemToRemove.ForEach(item => _subscriberGrouped.Remove(item));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if what clients dont need to get updated with new grouped observations and remove them
|
||||
/// diference between section and box if location is updated doesn't matter if is section or box
|
||||
/// BoxSubscribers don't need to get updated otherwise SectionSubscribers may still need to get updated
|
||||
/// </summary>
|
||||
/// <param name="patientId">objectId on db for Patient</param>
|
||||
/// <param name="newLocation"></param>
|
||||
public void RemoveWsSubscriberByLocation(string patientId, PatientLocation? newLocation)
|
||||
{
|
||||
lock (_subscriberGrouped)
|
||||
{
|
||||
var itemToRemove = _subscriberGrouped.Where(c => c.PatientId.ToString() == patientId).ToList();
|
||||
foreach (var wsSubscriberGrouped in itemToRemove)
|
||||
{
|
||||
// Make a separate list for wsClients to be removed
|
||||
var wsClientsToRemove = new List<string>();
|
||||
foreach (var wsClient in wsSubscriberGrouped.WsSubscriber) wsClientsToRemove.Add(wsClient);
|
||||
|
||||
// Remove the wsClients
|
||||
foreach (var wsClient in wsClientsToRemove) wsSubscriberGrouped.WsSubscriber.Remove(wsClient);
|
||||
|
||||
CheckEmptySubscriberGroup(wsSubscriberGrouped);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveWsSubscriberPatientIdAndWsId(string patientId, string wsIdToRemove)
|
||||
{
|
||||
lock (_subscriberGrouped)
|
||||
{
|
||||
var itemToRemove = _subscriberGrouped
|
||||
.Where(c => c.PatientId.ToString() == patientId && c.WsSubscriber.Contains(wsIdToRemove)).ToList();
|
||||
foreach (var wsSubscriberGrouped in itemToRemove)
|
||||
{
|
||||
// // Make a separate list for wsClients to be removed
|
||||
// var wsClientsToRemove = new List<string>();
|
||||
// foreach (var wsClient in wsSubscriberGrouped.WsSubscriber)
|
||||
// {
|
||||
// if(wsClient == wsIdToRemove)
|
||||
// wsClientsToRemove.Add(wsClient);
|
||||
// }
|
||||
//
|
||||
// // Remove the wsClients
|
||||
// foreach (var wsClient in wsClientsToRemove)
|
||||
// {
|
||||
// wsSubscriberGrouped.WsSubscriber.Remove(wsClient);
|
||||
// wsSubscriberGrouped.Group.Remove(wsClient);
|
||||
// }
|
||||
wsSubscriberGrouped.WsSubscriber.Remove(wsIdToRemove);
|
||||
wsSubscriberGrouped.Group.Remove(wsIdToRemove);
|
||||
|
||||
CheckEmptySubscriberGroup(wsSubscriberGrouped);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check clients using generated grouped observations on disconections
|
||||
/// removing the wole object in case of 0 or
|
||||
/// only the group if any other client is using it
|
||||
/// </summary>
|
||||
/// <param name="wsSubscriberGrouped">
|
||||
/// Object with properties to generate new grouped observations, clients using those
|
||||
/// grouped obsercations and the generated list of grouped observations
|
||||
/// </param>
|
||||
public List<string> CheckEmptySubscriberGroup(WsSubscriberGrouped? wsSubscriberGrouped)
|
||||
{
|
||||
lock (_subscriberGrouped)
|
||||
{
|
||||
var removed = new List<string>();
|
||||
if (wsSubscriberGrouped == null) return [];
|
||||
|
||||
if (wsSubscriberGrouped.WsSubscriber.Count == 0)
|
||||
{
|
||||
//_logger.Debug($"Removing wsSubscriberGrouped from list because client subscriber are empty");
|
||||
wsSubscriberGrouped.Timer.Stop();
|
||||
wsSubscriberGrouped.Timer.Dispose();
|
||||
_subscriberGrouped.Remove(wsSubscriberGrouped);
|
||||
removed.Add(
|
||||
$"ws:{wsSubscriberGrouped.PatientId}-{string.Join(";", wsSubscriberGrouped.Names)}-{wsSubscriberGrouped.Regularity}-{wsSubscriberGrouped.Group.Count}");
|
||||
cacheService?.DeleteObjectAsync(wsSubscriberGrouped.HashCode);
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (var kvp in wsSubscriberGrouped.Group.ToList())
|
||||
if (!wsSubscriberGrouped.WsSubscriber.Any(subscriber =>
|
||||
subscriber.Contains(kvp.Key)))
|
||||
{
|
||||
//_logger.Debug($"Removing group {kvp.Key}:{kvp.Value} from list because client subscriber got disconnected but wsSubscriberGrouped still in use with {wsSubscriberGrouped.WsSubscriber.Count()} clients");
|
||||
wsSubscriberGrouped.Group.Remove(kvp.Key);
|
||||
wsSubscriberGrouped.WsSubscriber.Remove(kvp.Key);
|
||||
removed.Add($"group:{kvp.Key}");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return removed;
|
||||
}
|
||||
}
|
||||
|
||||
public void AddSubscriberGrouped(WsSubscriberGrouped wsSubscriberGrouped)
|
||||
{
|
||||
lock (_subscriberGrouped)
|
||||
{
|
||||
_subscriberGrouped.Add(wsSubscriberGrouped);
|
||||
}
|
||||
}
|
||||
|
||||
public void CheckOnSubscriptionGroup(GroupedField groupedField, ObjectId patientId, string? timeZoneId,
|
||||
string connectionId, GroupedObservation lastObsInGroup)
|
||||
{
|
||||
var wsSubscriberGrouped = GetGrouped().FirstOrDefault(s => s.Compare(groupedField, patientId));
|
||||
if (wsSubscriberGrouped != null)
|
||||
{
|
||||
wsSubscriberGrouped.WsSubscriber.Add(connectionId);
|
||||
|
||||
// Verifica si el diccionario contiene la clave y el valor deseado
|
||||
if (!wsSubscriberGrouped.Group.ContainsKey(connectionId) ||
|
||||
wsSubscriberGrouped.Group[connectionId] != connectionId)
|
||||
// Añade el par clave-valor al diccionario
|
||||
wsSubscriberGrouped.Group[connectionId] = groupedField.Group ?? string.Empty;
|
||||
}
|
||||
else
|
||||
{
|
||||
AddSubscriberGrouped(
|
||||
// ReSharper disable once AsyncVoidLambda
|
||||
new WsSubscriberGrouped(patientId, connectionId, timeZoneId, groupedField, lastObsInGroup,
|
||||
async delegate(object? sender, string _)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (sender is WsSubscriberGrouped ws) await AddEmptyObs(ws);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.LogError(ex, "Ocurrió un error al procesar el evento del suscriptor.");
|
||||
throw;
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateLastGroupedObsInGroup(string wsgHashCode, GroupedObservation newGroupedObservation)
|
||||
{
|
||||
lock (_subscriberGrouped)
|
||||
{
|
||||
_subscriberGrouped.FirstOrDefault(c => c.HashCode == wsgHashCode)?.UpdateLastGo(newGroupedObservation);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task AddEmptyObs(WsSubscriberGrouped ws)
|
||||
{
|
||||
var gobs = await groupedObservationService.CreateNextEmptyObs(ws);
|
||||
|
||||
UpdateLastGroupedObsInGroup(ws.HashCode, gobs);
|
||||
lock (_subscriberGrouped)
|
||||
{
|
||||
foreach (var sub in ws.WsSubscriber)
|
||||
{
|
||||
gobs.Group = ws.Group.GetValue(sub)!;
|
||||
logger.LogInformation("Sending empty obs on gruped for: {Sub}, with group: {Group}", sub, gobs.Group);
|
||||
|
||||
_ = clientMessageService.Value.SendAsync(sub, OperationType.GroupedObservation, gobs);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,299 @@
|
||||
using System.Timers;
|
||||
using adas_core.Domain.Enums;
|
||||
using adas_core.Domain.Models;
|
||||
using adas_core.Domain.Models.GroupedObservations;
|
||||
using adas_core.Domain.Utils;
|
||||
using MongoDB.Bson;
|
||||
using Serilog;
|
||||
using static adas_core.Domain.Models.GroupedObservation;
|
||||
using Timer = System.Timers.Timer;
|
||||
|
||||
namespace adas_core.Application.Subscriptions;
|
||||
|
||||
/**
|
||||
* This class is used to group the subscribers by the same group
|
||||
*/
|
||||
public class WsSubscriberGrouped
|
||||
{
|
||||
private readonly EventHandler<string> _sendEvent;
|
||||
|
||||
public WsSubscriberGrouped(ObjectId patientId, string wsId, string? timeZoneId,
|
||||
GroupedField gf, GroupedObservation lastGroupedObservationObs, EventHandler<string> sendEvent)
|
||||
{
|
||||
_sendEvent = sendEvent;
|
||||
if (WsSubscriber.ToList().FirstOrDefault(s => s == wsId) == null) WsSubscriber.Add(wsId);
|
||||
|
||||
TimeZoneId = timeZoneId ?? "Romance Standard Time";
|
||||
PatientId = patientId;
|
||||
Names = CollectionsUtils.IfEmptyOrNull(gf.Names, [gf.Name ?? string.Empty]);
|
||||
Max = gf.Max;
|
||||
Since = gf.Since;
|
||||
StartTimeShift = gf.StartTimeShift;
|
||||
Regularity = gf.Regularity;
|
||||
Result = gf.Result;
|
||||
Group.Add(wsId, gf.Group ?? string.Empty);
|
||||
UpdateLastGo(lastGroupedObservationObs);
|
||||
HashCode = CryptoAdas.CreateMd5GroupedObs(gf, patientId);
|
||||
|
||||
Timer = new Timer
|
||||
{
|
||||
Interval = SetUpTimerInterval()
|
||||
};
|
||||
Timer.Elapsed += Timer_Elapsed;
|
||||
if (Regularity != GroupedObservationEnum.Regularity.Times) Timer.Start();
|
||||
}
|
||||
|
||||
public List<string> WsSubscriber { get; set; } = [];
|
||||
public ObjectId PatientId { get; set; }
|
||||
public List<string> Names { get; set; }
|
||||
public int Max { get; set; }
|
||||
public GroupedObservationEnum.Regularity? Regularity { get; set; }
|
||||
public List<GroupedObservationEnum.Result> Result { get; set; }
|
||||
public GroupedObservationEnum.Since Since { get; set; }
|
||||
public List<string> StartTimeShift { get; set; }
|
||||
public string HashCode { get; set; }
|
||||
public string TimeZoneId { get; set; }
|
||||
public List<GroupedObservationObs> LastGroupedObservationObs { get; set; } = [];
|
||||
public Dictionary<string, string> Group { get; set; } = new();
|
||||
public Timer Timer { get; set; }
|
||||
|
||||
public void UpdateLastGo(GroupedObservation lastGroupedObservationObs)
|
||||
{
|
||||
LastGroupedObservationObs.Clear();
|
||||
foreach (var name in Names)
|
||||
{
|
||||
var lastObs = lastGroupedObservationObs.Observations.LastOrDefault(c => c.Name == name);
|
||||
if (lastObs != null)
|
||||
{
|
||||
LastGroupedObservationObs.Add(lastObs);
|
||||
}
|
||||
else
|
||||
{
|
||||
lastObs = lastGroupedObservationObs.Observations.LastOrDefault();
|
||||
if (lastObs != null) LastGroupedObservationObs.Add(lastObs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void Timer_Elapsed(object? sender, ElapsedEventArgs e)
|
||||
{
|
||||
var currentDateTime = DateTime.Now;
|
||||
Timer.Stop();
|
||||
try
|
||||
{
|
||||
bool hasCurrentObs;
|
||||
|
||||
switch (Regularity)
|
||||
{
|
||||
case GroupedObservationEnum.Regularity.Second:
|
||||
// Filtra observaciones con el mismo segundo actual
|
||||
hasCurrentObs = LastGroupedObservationObs.Any(obs => obs.Time.Second == currentDateTime.Second
|
||||
&& obs.Time.Minute == currentDateTime.Minute
|
||||
&& obs.Time.Hour == currentDateTime.Hour
|
||||
&& obs.Time.Date == currentDateTime.Date);
|
||||
break;
|
||||
|
||||
case GroupedObservationEnum.Regularity.Minute:
|
||||
// Filtra observaciones con el mismo minuto actual
|
||||
hasCurrentObs = LastGroupedObservationObs.Any(obs => obs.Time.Minute == currentDateTime.Minute
|
||||
&& obs.Time.Hour == currentDateTime.Hour
|
||||
&& obs.Time.Date == currentDateTime.Date);
|
||||
break;
|
||||
|
||||
case GroupedObservationEnum.Regularity.Day:
|
||||
// Filtra observaciones con la misma fecha actual (día completo)
|
||||
hasCurrentObs = LastGroupedObservationObs.Any(obs => obs.Time.Date == currentDateTime.Date);
|
||||
break;
|
||||
|
||||
default:
|
||||
// Filtra observaciones con la misma hora actual
|
||||
hasCurrentObs = LastGroupedObservationObs.Any(obs => obs.Time.Hour == currentDateTime.Hour
|
||||
&& obs.Time.Date == currentDateTime.Date);
|
||||
break;
|
||||
}
|
||||
|
||||
// Si no hay al menos una observación que coincide, invoca el evento
|
||||
if (!hasCurrentObs) _sendEvent(this, HashCode);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Warning(
|
||||
$"Exception on WsSubsciptor for patient: {PatientId} message: {ex.Message} exception: {ex}");
|
||||
}
|
||||
|
||||
TimerReestart();
|
||||
}
|
||||
|
||||
private void TimerReestart()
|
||||
{
|
||||
Timer.Interval = SetUpTimerInterval();
|
||||
Timer.Start();
|
||||
}
|
||||
|
||||
private int SetUpTimerInterval()
|
||||
{
|
||||
var currentDateTime = DateTime.Now;
|
||||
int graceTime;
|
||||
DateTime nextIntervalTime;
|
||||
|
||||
switch (Regularity)
|
||||
{
|
||||
case GroupedObservationEnum.Regularity.Second:
|
||||
nextIntervalTime = new DateTime(
|
||||
currentDateTime.Year,
|
||||
currentDateTime.Month,
|
||||
currentDateTime.Day,
|
||||
currentDateTime.Hour,
|
||||
currentDateTime.Minute,
|
||||
currentDateTime.Second
|
||||
).AddSeconds(1);
|
||||
graceTime = 500;
|
||||
break;
|
||||
|
||||
case GroupedObservationEnum.Regularity.Minute:
|
||||
nextIntervalTime = new DateTime(
|
||||
currentDateTime.Year,
|
||||
currentDateTime.Month,
|
||||
currentDateTime.Day,
|
||||
currentDateTime.Hour,
|
||||
currentDateTime.Minute,
|
||||
0
|
||||
).AddMinutes(1);
|
||||
graceTime = 30000;
|
||||
break;
|
||||
|
||||
case GroupedObservationEnum.Regularity.Day:
|
||||
nextIntervalTime = new DateTime(
|
||||
currentDateTime.Year,
|
||||
currentDateTime.Month,
|
||||
currentDateTime.Day,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
).AddDays(1);
|
||||
graceTime = 60000;
|
||||
break;
|
||||
|
||||
default:
|
||||
nextIntervalTime = new DateTime(
|
||||
currentDateTime.Year,
|
||||
currentDateTime.Month,
|
||||
currentDateTime.Day,
|
||||
currentDateTime.Hour,
|
||||
0,
|
||||
0
|
||||
).AddHours(1);
|
||||
graceTime = 30000;
|
||||
break;
|
||||
}
|
||||
|
||||
var timeSpanToNextInterval = nextIntervalTime - currentDateTime;
|
||||
Log.Information(
|
||||
"Obs {Obs}, currentDateTime: {CurrentDateTime}, nextIntervalTime: {NextIntervalTime}, timeSpanToNextInterval: {TimeSpanToNextInterval}, timeSpanToNextInterval.TotalMilliseconds+graceTime: {Tt}",
|
||||
Group, currentDateTime, nextIntervalTime, timeSpanToNextInterval,
|
||||
(int)timeSpanToNextInterval.TotalMilliseconds + graceTime);
|
||||
|
||||
return (int)timeSpanToNextInterval.TotalMilliseconds + graceTime;
|
||||
}
|
||||
}
|
||||
|
||||
public static class WsSubscriberExtension
|
||||
{
|
||||
public static bool Compare(this WsSubscriberGrouped source, GroupedField r, ObjectId patientId)
|
||||
{
|
||||
return r.Regularity == source.Regularity &&
|
||||
r.Since == source.Since &&
|
||||
CompareStringShiftList(r.StartTimeShift, source.StartTimeShift) &&
|
||||
r.Max == source.Max &&
|
||||
r.Result.SequenceEqual(source.Result) &&
|
||||
patientId.ToString() == source.PatientId.ToString() &&
|
||||
CompareNamesStringList(r.Names, [r.Name ?? string.Empty], source.Names);
|
||||
}
|
||||
|
||||
private static bool CompareStringShiftList(List<string>? shift, List<string>? sourceShift)
|
||||
{
|
||||
if (shift != null && sourceShift != null) return sourceShift.SequenceEqual(shift);
|
||||
if (shift == null && sourceShift == null) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
private static bool CompareNamesStringList(List<string> names, List<string> name, List<string> sourceNames)
|
||||
{
|
||||
if (!CollectionsUtils.IsEmptyOrNull(names) && sourceNames.SequenceEqual(names)) return true;
|
||||
return !CollectionsUtils.IsEmptyOrNull(name) && sourceNames.SequenceEqual(name);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check if the incoming observation affect to the group and is new info or is irrelevant
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public static bool IsNewObservationRelevantForGroup(this WsSubscriberGrouped group, PatientObservation obs)
|
||||
{
|
||||
double.TryParse(obs.Value.ToString(), out var pobsValue);
|
||||
switch (group.Regularity)
|
||||
{
|
||||
case GroupedObservationEnum.Regularity.Shift:
|
||||
case GroupedObservationEnum.Regularity.Hour:
|
||||
var obsInThisHour = group.LastGroupedObservationObs.Where(c =>
|
||||
new DateTime(c.Time.Year, c.Time.Month, c.Time.Day, c.Time.Hour, 0, 0) ==
|
||||
new DateTime(obs.Time.Year, obs.Time.Month, obs.Time.Day, obs.Time.Hour, 0, 0) && !c.IsFilled);
|
||||
//Obs is in grouped time, don't generate group for observation outside of range
|
||||
|
||||
|
||||
//Change to don't cut is obs time is a future
|
||||
var obsInTime = DateTime.UtcNow.AddHours(group.Max) > obs.Time &&
|
||||
DateTime.UtcNow.AddHours(group.Max * -1) < obs.Time;
|
||||
//future data is relevant because maybe nothing is inserted in the same hour after it and we cant lose it
|
||||
/* if (DateTime.UtcNow.AddHours(group.Max) > obs.time)
|
||||
{
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
if (!obsInTime) return false;
|
||||
var groupedObservationObsEnumerable = obsInThisHour.ToList();
|
||||
if (!groupedObservationObsEnumerable.Any() && obsInTime) return true;
|
||||
|
||||
//If obs in this hour check if is relevant by Result
|
||||
if (groupedObservationObsEnumerable.Any())
|
||||
foreach (var result in group.Result)
|
||||
switch (result)
|
||||
{
|
||||
case GroupedObservationEnum.Result.Max:
|
||||
var value = groupedObservationObsEnumerable.Max(s => s.Max?.Value);
|
||||
var parsed = double.TryParse(value?.ToString(), out var valueParsed);
|
||||
//actual value is higher, is relevant
|
||||
if (parsed && pobsValue > valueParsed) return true;
|
||||
break;
|
||||
case GroupedObservationEnum.Result.Min:
|
||||
var minValue = groupedObservationObsEnumerable.Min(s => s.Min?.Value);
|
||||
var isParsed = double.TryParse(minValue?.ToString(), out var minValueParsed);
|
||||
//actual value is higher, is relevant
|
||||
if (isParsed && pobsValue < minValueParsed) return true;
|
||||
break;
|
||||
case GroupedObservationEnum.Result.Last:
|
||||
var lastObsInTime = groupedObservationObsEnumerable.OrderBy(t => t.Last?.Time).First();
|
||||
//is the new latest in the hour, relevant
|
||||
if (lastObsInTime.Time < obs.Time) return true;
|
||||
break;
|
||||
case GroupedObservationEnum.Result.LastFilled:
|
||||
var lastFilledObsInTime = groupedObservationObsEnumerable
|
||||
.OrderBy(t => t.LastFilled?.Time).First();
|
||||
//is the new latest in the hour, relevant
|
||||
if (lastFilledObsInTime.Time < obs.Time) return true;
|
||||
break;
|
||||
//always is relevant because SUM everything in the hour
|
||||
//TODO halfHour should check if any obs already in the halfHour
|
||||
case GroupedObservationEnum.Result.Sum:
|
||||
case GroupedObservationEnum.Result.Average:
|
||||
case GroupedObservationEnum.Result.HalfHour:
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
default:
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
using adas_core.Domain.Enums;
|
||||
using adas_core.Domain.Models;
|
||||
using adas_core.Domain.Models.GroupedObservations;
|
||||
using adas_core.Domain.Models.Masters;
|
||||
using MongoDB.Bson;
|
||||
|
||||
namespace adas_core.Application.Subscriptions;
|
||||
|
||||
public class WsSubscriber(string id)
|
||||
{
|
||||
public string? UserName;
|
||||
public string Id { get; set; } = id;
|
||||
public ObjectId? DisplayId { get; set; }
|
||||
public List<PatientLocation> Locations { get; set; } = [];
|
||||
public List<ObjectId> LocationIds { get; set; } = [];
|
||||
public string? Box { get; set; }
|
||||
public string? Section { get; set; }
|
||||
public string? Version { get; set; }
|
||||
public List<GroupedField>? GroupedFields { get; set; }
|
||||
public LocaleEnum? Locale { get; set; }
|
||||
public SubscriptionEnum.WsType? SubscriptionType { get; set; }
|
||||
}
|
||||
Reference in New Issue
Block a user