using adas_core.Application.Repositories.Interfaces; using adas_core.Domain.Models; using adas_core.Domain.Models.AppSettings; using adas_core.Domain.Models.MongoModels; using Microsoft.Extensions.Options; using MongoDB.Driver; using Newtonsoft.Json; using Serilog; namespace adas_core.Infrastructure.Repositories; /// /// Represents a MongoDB repository for entities, /// implementing the contract defined by . /// /// The type of the section entity managed by this repository. public class SectionRepository : MongoRepository
, ISectionRepository { private readonly ApiSettings _apiSettings; public SectionRepository(IOptions apiSettings, IMongoDatabase database) : base(database) { if (apiSettings == null) throw new ArgumentNullException(nameof(apiSettings)); _apiSettings = apiSettings.Value; } //For testing /// /// Gets the configuration sections collection name from the API settings, falling back to a default value when not configured. /// /// The configured collection name, or "config_sections" if _apiSettings.ConfigSections is null. public override string GetCollectionName() { return _apiSettings.ConfigSections ?? "config_sections"; } /// /// Retrieves all documents from the underlying collection by querying with an empty filter. /// /// A task that represents the asynchronous operation, containing a list of all documents found in the collection. public async Task> GetAll() { var result = await Collection.FindAsync(Builders
.Filter.Empty); return result.ToList(); } /// /// Finds and returns the first whose SectionTitle matches the specified section value. /// /// The section title used to look up the matching . /// The first matching , or null if no section with the given title is found. public async Task FindBySection(string section) { var result = await Collection.FindAsync(Builders
.Filter.Eq(x => x.SectionTitle, section)); return await result.FirstOrDefaultAsync(); } /// /// Asynchronously retrieves the first whose PointOfCare matches the specified value. /// /// The point of care identifier used to filter the sections. /// The first matching , or null if no section is found. public async Task FindByPointOfCare(string pointOfCare) { var result = await Collection.FindAsync(Builders
.Filter.Eq(x => x.PointOfCare, pointOfCare)); return await result.FirstOrDefaultAsync(); } /// /// Finds a by its unique identifier in the underlying collection. /// Returns null when no matching section exists. /// /// The unique identifier of the section to retrieve. /// A task containing the matching if found; otherwise, null. public async Task FindById(string id) { var result = await Collection.FindAsync(Builders
.Filter.Eq(x => x.Id, id)); return await result.FirstOrDefaultAsync(); } /// /// Asynchronously retrieves a by its identifier from the collection, returning null when no matching document is found. /// /// The identifier of the section to locate. /// A instance if a document with the given identifier exists; otherwise, null. public async Task FindById(object id) { var result = await Collection.FindAsync(Builders
.Filter.Eq(x => x._id, id)); return await result.FirstOrDefaultAsync(); } /// /// Retrieves the active sections associated with the specified patient location by matching the unit name and bed against the section hierarchy. /// Filtering is performed in memory after retrieving all sections because the underlying query does not support direct filtering on the collection's point of care field. /// A section is considered matching when its point of care equals the unit name and contains a box with a null point of care for the requested bed, or when it contains a box whose point of care equals the unit name for the requested bed. /// /// The patient location containing the unit name and bed used to locate the corresponding sections. /// A task that represents the asynchronous operation. The task result contains a list of sections matching the provided patient location; an empty list is returned when no matching sections are found. public async Task> FindByLocation(PatientLocation location) { //can not filter to Collection the where condition, it throws System.InvalidOperationException: '{}.pointOfCare is not supported.' var sections = await GetAll(); return sections.Where(section => (section.PointOfCare == location.UnitName && section.Items.Any(item => item.Boxes.Any(box => box.PointOfCare == null && box.Bed == location.Bed && box.IsActive))) || section.Items.Any(item => item.Boxes.Any(box => box.PointOfCare == location.UnitName && box.Bed == location.Bed && box.IsActive))).ToList(); } /// /// Asynchronously inserts a single into the collection and returns the persisted entity retrieved by its identifier. /// If the insertion fails, the error is logged and the method returns null instead of propagating the exception. /// /// The section to insert into the collection. /// The inserted on success, or null if the operation fails. public async Task InsertOneSection(Section section) { try { await Collection.InsertOneAsync(section); return await FindById(section.Id); } catch (Exception ex) { Log.Error("Error inserting section: {section}. Exception: {ex}", JsonConvert.SerializeObject(section, Formatting.Indented), ex); return null; } } /// /// Updates an existing in the data store and returns the updated document. /// If no section with the specified identifier is found, the method returns . /// /// The section containing the identifier of the record to update and the new field values to persist. /// The updated as it appears after the update, or if no matching record was found. public async Task UpdateSection(Section section) { var filter = Builders
.Filter.Eq("Id", section.Id); var update = Builders
.Update .Set(c => c.Id, section.Id) .Set(c => c.PointOfCare, section.PointOfCare) .Set(c => c.SectionTitle, section.SectionTitle) .Set(c => c.Configuration, section.Configuration) .Set(c => c.Items, section.Items); return await Collection.FindOneAndUpdateAsync(filter, update, new FindOneAndUpdateOptions { ReturnDocument = ReturnDocument.After }); } }