rama creada apartir de master en j

This commit is contained in:
jrojas
2026-06-26 10:29:23 +02:00
parent 319fd3dfb0
commit c1517fda87
2810 changed files with 1927392 additions and 25392 deletions
@@ -33,8 +33,13 @@ public class AppointmentService(
: IAppointmentService
{
private readonly bool _createPatientWithSiu = apiSettings.Value.CreatePatientWithSiu;
private readonly CacheSettings? _cacheSettings = cacheSettings.Value ;
private readonly CacheSettings? _cacheSettings = cacheSettings.Value;
/// <summary>
/// Saves an API request by validating the patient, resolving or creating the patient record, processing the request, and handling associated observations and diagnoses.
/// </summary>
/// <param name="apiRequest">The API request containing the patient number, location, type, observations, diagnosis, and related data to be processed.</param>
/// <exception cref="ApiRequestException">Thrown when the <paramref name="apiRequest"/> has a null or empty patient number.</exception>
public async Task SaveRequest(ApiRequest apiRequest)
{
if (string.IsNullOrEmpty(apiRequest.PatientNumber))
@@ -73,6 +78,12 @@ public class AppointmentService(
}
}
/// <summary>
/// Processes an incoming API request for a patient, handling HL7 SIU message types to create, update, or cancel appointments.
/// Validates the patient and auto-ADT configuration, then routes the request to the appropriate handler based on message type: SIU_S12-S14 and SIU_S18-S22 (booking/rescheduling/modification), SIU_S15-S17 (cancellation), and other types (blocked slots / no-show), persisting changes, refreshing cache, creating audit logs, and emitting broadcasts.
/// </summary>
/// <param name="apiRequest">The API request containing the HL7 message type, timestamp, and appointment payload to process.</param>
/// <param name="patient">The patient associated with the request; if null, the method returns without processing.</param>
public async Task ProcessApiRequest(ApiRequest apiRequest, Patient? patient)
{
if (patient == null)
@@ -209,16 +220,29 @@ public class AppointmentService(
}
}
/// <summary>
/// Asynchronously saves the provided API request by running the save operation on a background task.
/// </summary>
/// <param name="apiRequest">The API request to be saved.</param>
/// <returns>A task that represents the asynchronous save operation.</returns>
public Task SaveRequestAsync(ApiRequest apiRequest)
{
return Task.FromResult(Task.Run(async () => { await SaveRequest(apiRequest); }));
}
/// <summary>
/// Archives the specified patient by delegating the operation to <see cref="ArchiveByPatientId"/> using the patient's identifier.
/// </summary>
/// <param name="patient">The patient to be archived.</param>
public async Task Archive(Patient patient)
{
await ArchiveByPatientId(patient.Id);
}
/// <summary>
/// Archives all appointments associated with the specified patient by copying them to the appointment archive repository and then deleting them from the source collection.
/// </summary>
/// <param name="id">The unique identifier of the patient whose appointments should be archived.</param>
public async Task ArchiveByPatientId(ObjectId id)
{
logger.LogDebug("Archive Appointments by patientId {id}", id);
@@ -232,14 +256,26 @@ public class AppointmentService(
await DeleteByPatientId(id);
}
/// <summary>
/// Retrieves a list of patient appointments associated with the specified patient identifier by delegating to the appointment repository.
/// </summary>
/// <param name="patientId">The unique identifier of the patient whose appointments are being requested.</param>
/// <returns>A task that represents the asynchronous operation, containing a list of <see cref="PatientAppointment"/> records for the given patient.</returns>
public async Task<List<PatientAppointment>> GetByPatient(ObjectId patientId)
{
return await appointmentRepository.GetByPatient(patientId);
}
/// <summary>
/// Retrieves the list of appointments scheduled for today (UTC) for the specified patient, using a cache-aside pattern to avoid repeated database queries.
/// The full list of patient appointments is fetched from cache (or loaded from the repository on a cache miss) and then filtered locally to include only those whose start time falls on the current UTC date.
/// </summary>
/// <param name="patientId">The unique identifier of the patient whose appointments are being queried.</param>
/// <param name="ct">Cancellation token used to cancel the asynchronous operation.</param>
/// <returns>A task that resolves to a list of <see cref="PatientAppointment"/> instances scheduled for today; an empty list is returned when no appointments match.</returns>
public async Task<List<PatientAppointment>> GetTodayByPatient(
ObjectId patientId,
CancellationToken ct = default)
ObjectId patientId,
CancellationToken ct = default)
{
// Obtener clave + TTL según CacheSettings
var (key, ttl) = CacheKeys.PatientAppointmentsTodayKeyWithTtl(_cacheSettings, patientId);
@@ -270,14 +306,20 @@ public class AppointmentService(
return todayAppointments;
}
/// <summary>
/// Retrieves the patient appointments scheduled for today at the specified point of care. Uses a cache to store the full appointment list for the point of care and filters it by today's date; returns an empty list if the point of care is not found.
/// </summary>
/// <param name="pocId">The identifier of the point of care whose appointments should be retrieved.</param>
/// <param name="ct">A cancellation token to cancel the asynchronous operation.</param>
/// <returns>A task that represents the asynchronous operation, containing the list of patient appointments scheduled for today at the specified point of care.</returns>
public async Task<List<PatientAppointment>> GetTodayByPoc(
ObjectId pocId,
CancellationToken ct = default)
ObjectId pocId,
CancellationToken ct = default)
{
var poc = await pointOfCareService.FindById(pocId);
if(poc == null) return [];
if (poc == null) return [];
// Obtener clave + TTL según CacheSettings
var (key, ttl) = CacheKeys.PocAppointmentsTodayKeyWithTtl(_cacheSettings, pocId);
@@ -307,34 +349,59 @@ public class AppointmentService(
return todayAppointments;
}
/// <summary>
/// Asynchronously retrieves all patient appointments associated with the specified patient identifier by delegating to the appointment repository.
/// </summary>
/// <param name="patientId">The unique identifier of the patient whose appointments are to be retrieved.</param>
/// <returns>A task that represents the asynchronous operation, containing an async cursor over the matching <see cref="PatientAppointment"/> documents.</returns>
public Task<IAsyncCursor<PatientAppointment>> FindByPatientIdAsync(ObjectId patientId)
{
return appointmentRepository.FindByPatientIdAsync(patientId);
}
/// <summary>
/// Retrieves all patient appointments associated with the specified location.
/// </summary>
/// <param name="location">The location used to filter the patient appointments.</param>
/// <returns>A task that represents the asynchronous operation, containing a list of patient appointments for the specified location.</returns>
public async Task<List<PatientAppointment>> FindByLocation(PatientLocation location)
{
return await appointmentRepository.FindByLocation(location);
}
/// <summary>
/// Deletes all appointments associated with the specified patient identifier, invalidates the appointments cache, and records the action in the audit log.
/// </summary>
/// <param name="id">The unique identifier of the patient whose appointments will be deleted.</param>
public async Task DeleteByPatientId(ObjectId id)
{
var patientApp = await FindByPatientIdAsync(id);
logger.LogDebug("Delete Appointments by Patient Id {id}", id);
await appointmentRepository.DeleteByPatientId(id);
// Invalidar CACHE (colección completa)
await cacheService.DeleteByPatternAsync(CacheKeyPatterns.ForEntity(CacheEnum.EntityType.Appointments));
await auditService.CreateAuditLogAsync(httpContextAccessor.HttpContext?.User!, patientApp, null);
}
/// <summary>
/// Updates multiple appointment records by replacing the specified <paramref name="oldId"/> with the new <paramref name="id"/>, scoped by the given <paramref name="nameId"/>. Delegates the operation to the underlying appointment repository.
/// </summary>
/// <param name="nameId">The identifier used to scope which appointment records are affected by the update.</param>
/// <param name="id">The new ObjectId that will replace the existing one in the matching records.</param>
/// <param name="oldId">The current ObjectId to be replaced in the matching records.</param>
public async Task UpdateManyObjectId(string nameId, ObjectId id, ObjectId oldId)
{
await appointmentRepository.UpdateManyObjectId(nameId, id, oldId);
}
/// <summary>
/// Broadcasts a patient appointment operation to all subscribers associated with the appointment's locations. Iterates through each resource group and location, resolving the unit and point of care, and dispatches a fire-and-forget message to every matching subscriber. Skips locations with missing unit/bed data and silently ignores unresolved unit or point-of-care lookups.
/// </summary>
/// <param name="appointment">The patient appointment whose resource groups and locations will be broadcast to subscribers.</param>
/// <param name="operationType">The optional operation type describing the change performed on the appointment; passed along to the subscriber message.</param>
private async Task SendBroadcast(PatientAppointment appointment, OperationType? operationType)
{
//RECORRE LOS DIFERENTES LOCATIONS DE LA CITA