4 Commits

Author SHA1 Message Date
n8n IEC 62304 Bot ad518abd07 docs(iec62304): [REL-1.0.2] apply curated XML doc review updates 2026-07-06 21:21:05 +02:00
n8n IEC 62304 Bot 64da453152 docs(iec62304): [REL-1.0.2] validate and curate XML doc review markers 2026-07-06 21:15:15 +02:00
jrojas 8e6bc709f3 Conflicto de fusión en adas-core.LdapLogin/LdapLoginService.cs 2026-07-06 19:33:59 +02:00
jrojas 9e2246a459 se agrego rc102 2026-07-06 19:30:28 +02:00
2 changed files with 111 additions and 125 deletions
@@ -79,7 +79,6 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
/// </summary> /// </summary>
/// <param name="entity">The entity to insert.</param> /// <param name="entity">The entity to insert.</param>
/// <exception cref="Exception">Throws and re-throws exceptions after logging.</exception> /// <exception cref="Exception">Throws and re-throws exceptions after logging.</exception>
/// <!-- aidoc:v1 sig=c7a7ad8 body=26b3581 -->
public override async Task InsertOneAsync(T entity) public override async Task InsertOneAsync(T entity)
{ {
try try
@@ -114,10 +113,10 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
} }
/// <summary> /// <summary>
/// Replaces the document matching <paramref name="entity"/>'s identifier, or inserts it as a new document when no match is found (upsert). /// Persists the supplied <typeparamref name="T"/> entity in the collection by replacing the document identified by <see cref="T.Id"/>, or inserting a new document when no match is found (upsert). Logs and rethrows any exception raised during the operation.
/// Any exception raised during the operation is logged and rethrown to the caller.
/// </summary> /// </summary>
/// <param name="entity">The entity to persist; its <c>Id</c> property is used to locate the existing document to replace.</param> /// <typeparam name="T">The document type stored in the collection.</typeparam>
/// <param name="entity">The entity whose <see cref="T.Id"/> locates the target document and whose state is written to the collection.</param>
/// <!-- aidoc:v1 sig=019b691 body=863650a --> /// <!-- aidoc:v1 sig=019b691 body=863650a -->
public async Task Update(T entity) public async Task Update(T entity)
{ {
@@ -168,10 +167,11 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
} }
/// <summary> /// <summary>
/// Asynchronously finds an entity by its <paramref name="id"/>, returning the first matching document with its "options" array limited to 100 elements via projection. If no document matches or an exception is thrown, the error is logged and <c>null</c> is returned. /// Asynchronously retrieves an entity of type <typeparamref name="T"/> from the collection by its <see cref="ObjectId"/>, applying a projection that truncates the <c>options</c> field to 100 elements. Returns <see langword="null"/> when no matching document is found, or when an exception is caught and logged by <see cref="Log"/>.
/// </summary> /// </summary>
/// <param name="id">The <see cref="ObjectId"/> used to build the equality filter against the entity's identifier.</param> /// <typeparam name="T">The document type stored in the collection, expected to expose an <see cref="ObjectId"/> identifier.</typeparam>
/// <returns>A <see cref="Task{T}"/> that yields the matching entity, or <c>null</c> when no document is found or the operation fails.</returns> /// <param name="id">The <see cref="ObjectId"/> of the entity to locate.</param>
/// <returns>A <see cref="Task{T}"/> that resolves to the matching entity, or <see langword="null"/> if the document is not found or the operation fails.</returns>
/// <!-- aidoc:v1 sig=81ac96a body=1519944 --> /// <!-- aidoc:v1 sig=81ac96a body=1519944 -->
public async Task<T?> FindById(ObjectId id) public async Task<T?> FindById(ObjectId id)
{ {
@@ -196,12 +196,12 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
} }
/// <summary> /// <summary>
/// Retrieves a single <see cref="OptionList"/> item identified by <paramref name="masterId"/> and <paramref name="optionId"/>, applying locale-based translation. When <paramref name="locale"/> is <see cref="LocaleEnum.Default"/> or matches the document's default locale, the base option name is used; otherwise the method looks up a translation in the option's locale items and falls back to the base name when no translation exists. Returns <c>null</c> when no matching option is found or when an error is encountered. /// Retrieves a single <see cref="OptionList"/> item from a master document identified by <paramref name="masterId"/> and <paramref name="optionId"/>, applying locale-aware name resolution. When <paramref name="locale"/> is <see cref="LocaleEnum.Default"/> or matches the document's default locale, the base name is returned; otherwise, the matching entry from the <c>localeItems</c> map is used, falling back to the base name when no translation is found. Returns <see langword="null"/> when the option is not found or if an error occurs during aggregation.
/// </summary> /// </summary>
/// <param name="masterId">The identifier of the master document that owns the options collection.</param> /// <param name="masterId">The <see cref="ObjectId"/> of the master document that contains the option collection to search.</param>
/// <param name="optionId">The identifier of the specific option to retrieve.</param> /// <param name="optionId">The <see cref="ObjectId"/> of the specific option within the master document's options array.</param>
/// <param name="locale">The desired locale used to select translated content.</param> /// <param name="locale">The <see cref="LocaleEnum"/> value that drives translation selection; <see cref="LocaleEnum.Default"/> resolves to the document's default locale, while any other value attempts a locale-specific lookup.</param>
/// <returns>A <see cref="Task"/> that yields the matching <see cref="OptionList"/>, or <c>null</c> if the option does not exist or the lookup fails.</returns> /// <returns>A <see cref="Task{TResult}"/> that yields the matched <see cref="OptionList"/>, or <see langword="null"/> if no document/option is found or the operation fails.</returns>
/// <!-- aidoc:v1 sig=fdb2628 body=0e4983e --> /// <!-- aidoc:v1 sig=fdb2628 body=0e4983e -->
public async Task<OptionList?> FindOptionItemById(ObjectId masterId, ObjectId optionId, LocaleEnum locale) public async Task<OptionList?> FindOptionItemById(ObjectId masterId, ObjectId optionId, LocaleEnum locale)
{ {
@@ -374,11 +374,11 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
} }
/// <summary> /// <summary>
/// Retrieves an entity of type <c>T</c> by its <see cref="ObjectId"/> identifier, applying locale-aware resolution of option names through a MongoDB aggregation pipeline. When <paramref name="locale"/> is <see langword="null"/>, equals <see cref="LocaleEnum.Default"/>, or matches the document's <c>defaultLocale</c>, the original option name is returned; otherwise, the translated name from <c>localeItems</c> is used with a fallback to the original name when no translation exists. Any exception is logged and swallowed, returning <see langword="null"/>. /// Asynchronously finds an entity of type <typeparamref name="T"/> by its MongoDB <see cref="ObjectId"/>, executing an aggregation pipeline that unwinds the <c>options</c> array and resolves localized option names. When <paramref name="locale"/> is <c>null</c> or <see cref="LocaleEnum.Default"/>, the original option name is returned; otherwise, the option name is translated using the supplied locale, falling back to the original name when no matching <c>localeItems</c> entry exists. Returns <c>null</c> when no document is found or when an exception is caught and logged.
/// </summary> /// </summary>
/// <param name="id">The <see cref="ObjectId"/> of the document to retrieve.</param> /// <param name="id">The MongoDB <see cref="ObjectId"/> that uniquely identifies the document to retrieve.</param>
/// <param name="locale">The optional <see cref="LocaleEnum"/> used to resolve translated option names. When omitted or set to <see cref="LocaleEnum.Default"/>, the original names are used.</param> /// <param name="locale">The optional <see cref="LocaleEnum"/> used to resolve translated option names; pass <c>null</c> or <see cref="LocaleEnum.Default"/> to use the default (non-translated) names.</param>
/// <returns>A <see cref="Task{T}"/> that yields the matching entity, or <see langword="null"/> when no document is found or an error is logged.</returns> /// <returns>A <see cref="Task{T}"/> that yields the matched entity of type <typeparamref name="T"/>, or <c>null</c> if no document matches <paramref name="id"/> or if an error occurs during aggregation.</returns>
/// <!-- aidoc:v1 sig=cb4a658 body=f2e88d8 --> /// <!-- aidoc:v1 sig=cb4a658 body=f2e88d8 -->
public async Task<T?> FindById(ObjectId id, LocaleEnum? locale) public async Task<T?> FindById(ObjectId id, LocaleEnum? locale)
{ {
@@ -557,12 +557,10 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
} }
/// <summary> /// <summary>
/// Asynchronously searches the underlying collection for an entity matching the specified <paramref name="name"/>, /// Asynchronously finds a single <typeparamref name="T"/> entity by its <see cref="T.Name"/> using a MongoDB query, projecting only the first 100 elements of the <c>options</c> field to limit payload size. Returns <c>null</c> if no matching document is found or if an error occurs during the search.
/// projecting the <c>options</c> field to a maximum of 100 elements to limit the payload size.
/// Returns <see langword="null"/> if no entity is found or if an error occurs while querying the collection.
/// </summary> /// </summary>
/// <param name="name">The name of the entity to search for. Used to build an equality filter against the <c>Name</c> field.</param> /// <param name="name">The name value used to build the equality filter against the entity's <c>Name</c> field.</param>
/// <returns>A <see cref="Task{T}"/> that yields the matching entity of type <c>T</c>, or <see langword="null"/> when no match is found or an error is logged.</returns> /// <returns>A <see cref="Task{T}"/> that yields the matching <typeparamref name="T"/> instance, or <c>null</c> when no document matches or the operation fails.</returns>
/// <!-- aidoc:v1 sig=80a1541 body=8b5b558 --> /// <!-- aidoc:v1 sig=80a1541 body=8b5b558 -->
public async Task<T?> FindByName(string name) public async Task<T?> FindByName(string name)
{ {
@@ -599,11 +597,10 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
} }
/// <summary> /// <summary>
/// Builds a sorted master-list query for documents of type <typeparamref name="T"/>, returning all documents ordered ascending by the <c>name</c> field, or only those whose <c>Name</c> matches <paramref name="filter"/>'s search text via a case-insensitive regex (with special characters escaped) when provided. /// Retrieves paginated master lists with optional text filtering.
/// If <paramref name="filter"/> is null, its <c>FilteredRequest</c> is null, or <c>FilteredRequest.Text</c> is null or empty, no additional filter is applied and the unfiltered, sorted result is returned.
/// </summary> /// </summary>
/// <param name="filter">The <see cref="PaginationFilter"/> containing the optional <c>FilteredRequest.Text</c> used to match the <c>Name</c> field.</param> /// <param name="filter">The pagination and filtering parameters.</param>
/// <returns>An <see cref="IFindFluent{TDocument, TProjection}"/> representing the sorted, filtered query against the collection of <typeparamref name="T"/>.</returns> /// <returns>A fluent queryable for MasterList results.</returns>
/// <!-- aidoc:v1 sig=bbb39c7 body=f42ebaa --> /// <!-- aidoc:v1 sig=bbb39c7 body=f42ebaa -->
public IFindFluent<T, T> GetPaginatedMasterList(PaginationFilter filter) public IFindFluent<T, T> GetPaginatedMasterList(PaginationFilter filter)
{ {
@@ -627,12 +624,11 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
} }
/// <summary> /// <summary>
/// Asynchronously retrieves options from the master list identified by <paramref name="listId"/>, optionally applying a case-insensitive text filter against each option's name, description, and option type. /// Retrieves the options belonging to the master list identified by <paramref name="listId"/>, optionally narrowed down by the text contained in <paramref name="filter"/>. Returns an empty collection when no master list exists for the given identifier, and when a non-empty filter text is supplied, applies a case-insensitive match against each option's name, description, or option type.
/// Returns an empty list when no master list matches the supplied identifier.
/// </summary> /// </summary>
/// <param name="filter">A <see cref="PaginationFilter"/> whose <c>FilteredRequest.Text</c>, when provided, is used to narrow the options by matching against the name, description, or option type.</param> /// <param name="filter">The <see cref="PaginationFilter"/> that provides the optional text used to filter the returned options.</param>
/// <param name="listId">The identifier of the master list whose options should be returned.</param> /// <param name="listId">The <see cref="ObjectId"/> of the master list whose options should be retrieved.</param>
/// <returns>A task that resolves to a <see cref="List{OptionList}"/> containing the matching options, or an empty list if the master list is not found.</returns> /// <returns>A <see cref="Task"/> that resolves to a <see cref="List{OptionList}"/> of options matching the filter, or an empty list when the master list cannot be found.</returns>
/// <!-- aidoc:v1 sig=2ac8d75 body=b25fb18 --> /// <!-- aidoc:v1 sig=2ac8d75 body=b25fb18 -->
public async Task<List<OptionList>> GetPaginatedOptions(PaginationFilter filter, ObjectId listId) public async Task<List<OptionList>> GetPaginatedOptions(PaginationFilter filter, ObjectId listId)
{ {
@@ -653,13 +649,11 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
} }
/// <summary> /// <summary>
/// Adds a new <see cref="OptionList"/> to the master list identified by <paramref name="id"/>. /// Adds a new <see cref="OptionList"/> entry to the master list identified by <paramref name="id"/>. Returns the created option on success, or <c>null</c> if a matching option already exists, the master list cannot be retrieved, the update does not modify any document, or the operation throws an exception that is logged.
/// Returns null if a matching option already exists, if the update modifies no documents, or if an exception is thrown.
/// When the request comes from the admin panel, the locale items from <paramref name="opt"/> are reused; otherwise, a new locale entry is generated based on the current default locale of the list.
/// </summary> /// </summary>
/// <param name="id">The <see cref="ObjectId"/> of the master list to update.</param> /// <param name="id">The <see cref="ObjectId"/> of the master list to update.</param>
/// <param name="opt">The <see cref="FilterOptionListElement"/> describing the option to add.</param> /// <param name="opt">The <see cref="FilterOptionListElement"/> describing the option to add; its locale items are reused when <see cref="FilterOptionListElement.IsFromAdmPanel"/> is <c>true</c>, otherwise new locale entries are generated from the master list's <see cref="LocaleEnum"/> default.</param>
/// <returns>A <see cref="Task{T}"/> containing the created <see cref="OptionList"/> on success, or null if the operation does not persist any change.</returns> /// <returns>A <see cref="Task{OptionList}"/> that resolves to the newly created <see cref="OptionList"/> when the push update succeeds, or <c>null</c> when the operation is skipped, no document is modified, or the update fails.</returns>
/// <!-- aidoc:v1 sig=1602f0d body=e7fd138 --> /// <!-- aidoc:v1 sig=1602f0d body=e7fd138 -->
public async Task<OptionList?> AddOptionToMasterList(ObjectId id, FilterOptionListElement opt) public async Task<OptionList?> AddOptionToMasterList(ObjectId id, FilterOptionListElement opt)
{ {
@@ -700,10 +694,10 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
} }
/// <summary> /// <summary>
/// Retrieves all entities of type <typeparamref name="T"/> from the data store asynchronously. /// Asynchronously retrieves all entities from the underlying collection.
/// If an error occurs during retrieval, it is logged and an empty collection is returned instead of propagating the exception. /// If an exception occurs during retrieval, the error is logged and an empty collection is returned rather than propagating the failure.
/// </summary> /// </summary>
/// <returns>A task that yields an <see cref="IEnumerable{T}"/> containing all entities, or an empty collection when an error is encountered.</returns> /// <returns>A <see cref="Task"/> that yields an <see cref="IEnumerable{T}"/> containing all retrieved entities, or an empty collection if the operation fails.</returns>
/// <!-- aidoc:v1 sig=3a61c61 body=40d7129 --> /// <!-- aidoc:v1 sig=3a61c61 body=40d7129 -->
public async Task<IEnumerable<T>> GetAll() public async Task<IEnumerable<T>> GetAll()
{ {
@@ -720,9 +714,9 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
} }
/// <summary> /// <summary>
/// Retrieves every entry from the master list collection and projects each into a <see cref="MasterListDto"/>, where <see cref="MasterListDto.Options"/> contains the total count of options. If the underlying query fails, the exception is logged and an empty collection is returned. /// Retrieves all master list entries from the underlying collection without applying any filter and projects each result into a <see cref="MasterListDto"/>, where the <see cref="MasterListDto.Options"/> property is set to the count of associated options rather than the option list itself.
/// </summary> /// </summary>
/// <returns>A task that resolves to an <see cref="IEnumerable{MasterListDto}"/> containing all master list entries, or an empty collection when an error occurs.</returns> /// <returns>A <see cref="Task"/> that resolves to an <see cref="IEnumerable{T}"/> containing the projected <see cref="MasterListDto"/> instances, or an empty collection if an error is encountered while querying the data store.</returns>
/// <!-- aidoc:v1 sig=e493435 body=1c299ba --> /// <!-- aidoc:v1 sig=e493435 body=1c299ba -->
public async Task<IEnumerable<MasterListDto>> GetAllWithoutOptions() public async Task<IEnumerable<MasterListDto>> GetAllWithoutOptions()
{ {
@@ -748,10 +742,12 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
} }
/// <summary> /// <summary>
/// Asynchronously counts the total number of documents in the underlying collection. /// Asynchronously counts all entities in the underlying <see cref="Collection"/> by invoking
/// If the operation fails, the exception is logged and the method returns 0 as a fallback value. /// <c>CountDocumentsAsync</c> with a filter that matches every document. If the operation fails,
/// the exception is logged via <c>Log.Error</c> and the method returns <c>0</c> as a safe fallback.
/// </summary> /// </summary>
/// <returns>A <see cref="Task{Int32}"/> representing the asynchronous operation, containing the total document count, or 0 if an error occurred.</returns> /// <returns>A <see cref="Task{Int32}"/> that represents the asynchronous count operation. The result
/// is the total number of entities, or <c>0</c> if an error occurred while querying the collection.</returns>
/// <!-- aidoc:v1 sig=f1f0a98 body=01cd3d1 --> /// <!-- aidoc:v1 sig=f1f0a98 body=01cd3d1 -->
public async Task<int> Count() public async Task<int> Count()
{ {
@@ -768,13 +764,11 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
} }
/// <summary> /// <summary>
/// Searches for options within a master list using multiple filter criteria. /// Retrieves the options of a master list identified by <paramref name="id"/>, applying the optional <paramref name="filters"/> to restrict the results by option type, text, name, or description, and resolving the localized <c>name</c> and <c>description</c> fields for each option based on the requested locale. When <paramref name="filters"/> is <c>null</c>, no options are returned. Text searches are performed case-insensitively against both the name and description of each option using a normalized pattern, and the final result is ordered alphabetically by name. Any exception during execution is logged and an empty list is returned.
/// Uses MongoDB aggregation pipeline to apply filters and locale translations.
/// </summary> /// </summary>
/// <param name="id">The ObjectId of the master list.</param> /// <param name="id">The <see cref="ObjectId"/> of the master list whose options will be queried.</param>
/// <param name="filters">The filter criteria including text, name, description, and optionType.</param> /// <param name="filters">Optional <see cref="FilterOptionListElement"/> containing the search criteria (option type, text, name, description, and locale). When <c>null</c>, the method returns an empty list.</param>
/// <returns>A list of matching OptionList items ordered by name.</returns> /// <returns>A <see cref="Task{List{OptionList}}"/> containing the filtered, localized, and alphabetically ordered options; an empty list is returned when no filters are provided, no options match, or an error occurs.</returns>
/// <exception cref="Exception">Logs errors and returns empty list on failure.</exception>
/// <!-- aidoc:v1 sig=f6ee5be body=17d6a96 --> /// <!-- aidoc:v1 sig=f6ee5be body=17d6a96 -->
public async Task<List<OptionList>> GetMasterListByIdAndSearchOptions(ObjectId id, FilterOptionListElement? filters) public async Task<List<OptionList>> GetMasterListByIdAndSearchOptions(ObjectId id, FilterOptionListElement? filters)
{ {
@@ -984,13 +978,12 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
} }
/// <summary> /// <summary>
/// Updates a specific option within a master list with locale-aware field updates. /// Updates an option within a master list, handling duplicate detection, locale-specific translations, and conditional field updates based on the master list's required field rules.
/// </summary> /// </summary>
/// <param name="id">The ObjectId of the master list.</param> /// <param name="id">The <see cref="MongoDB.Bson.ObjectId"/> of the master list that contains the option to update.</param>
/// <param name="newOpt">The OptionList with updated values.</param> /// <param name="newOpt">The <see cref="OptionList"/> containing the new values to apply to the existing option.</param>
/// <param name="locale">The locale for translation updates.</param> /// <param name="locale">The <see cref="LocaleEnum"/> indicating which locale the <paramref name="newOpt"/> applies to; when it matches the master's default locale, the main field is updated, otherwise the translation stored in <c>localeItems</c> is updated.</param>
/// <returns>The updated OptionList if successful; otherwise, null.</returns> /// <returns>A <see cref="Task{T}"/> containing the updated <see cref="OptionList"/>, the existing option when a duplicate is detected, or <c>null</c> when the option is not found, no fields qualify for update, or the update operation fails.</returns>
/// <exception cref="Exception">Logs errors and returns null on failure.</exception>
/// <!-- aidoc:v1 sig=e771f23 body=5520a4a --> /// <!-- aidoc:v1 sig=e771f23 body=5520a4a -->
public async Task<OptionList?> UpdateMasterListOption(ObjectId id, OptionList newOpt, LocaleEnum locale) public async Task<OptionList?> UpdateMasterListOption(ObjectId id, OptionList newOpt, LocaleEnum locale)
{ {
@@ -1086,12 +1079,11 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
} }
/// <summary> /// <summary>
/// Updates a specific option within a master list with full replacement. /// Updates an existing option inside the master list identified by <paramref name="id"/> with the data from <paramref name="newOpt"/>. Returns <see langword="null"/> when the master list is not found, when no document is modified, or when an exception is caught and logged.
/// </summary> /// </summary>
/// <param name="id">The ObjectId of the master list.</param> /// <param name="id">The <see cref="ObjectId"/> of the master list that owns the option to update.</param>
/// <param name="newOpt">The OptionList with updated values.</param> /// <param name="newOpt">The <see cref="OptionList"/> whose <see cref="ObjectId"/> targets the option to replace and whose values are persisted to the document.</param>
/// <returns>The updated OptionList if successful; otherwise, null.</returns> /// <returns>A task containing the updated <see cref="OptionList"/> when the update succeeds, or <see langword="null"/> when the master list is missing, nothing was modified, or the update failed.</returns>
/// <exception cref="Exception">Logs errors and returns null on failure.</exception>
/// <!-- aidoc:v1 sig=6def54c body=9554543 --> /// <!-- aidoc:v1 sig=6def54c body=9554543 -->
public async Task<OptionList?> UpdateMasterListOption(ObjectId id, OptionList newOpt) public async Task<OptionList?> UpdateMasterListOption(ObjectId id, OptionList newOpt)
{ {
@@ -1147,14 +1139,11 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
} }
/// <summary> /// <summary>
/// Updates the option details of an existing master list document identified by <paramref name="id"/>, applying only the /// Updates the option details of a master list document identified by <paramref name="id"/>, persisting only the non-null fields supplied in <paramref name="opt"/>.
/// fields that are provided in <paramref name="opt"/> (<c>CanAddElement</c> and <c>OptionListDetails</c>) using a partial
/// <c>$set</c> update. Returns the supplied <see cref="UpdateMasterListDetailsDto"/> when the document is found and modified,
/// or <see langword="null"/> when no document matches the filter, no fields are modified, or the operation fails.
/// </summary> /// </summary>
/// <param name="id">The <see cref="MongoDB.Bson.ObjectId"/> identifier of the master list document to update.</param> /// <param name="id">The <see cref="ObjectId"/> of the master list entry to update.</param>
/// <param name="opt">The <see cref="UpdateMasterListDetailsDto"/> containing the new values; only non-null properties are applied to the document.</param> /// <param name="opt">The <see cref="UpdateMasterListDetailsDto"/> whose non-null <see cref="UpdateMasterListDetailsDto.CanAddElement"/> and <see cref="UpdateMasterListDetailsDto.OptionListDetails"/> values are written to the document.</param>
/// <returns>A <see cref="Task{UpdateMasterListDetailsDto}"/> that resolves to the updated DTO on success, or <see langword="null"/> if the document was not found, was not modified, or an error was logged.</returns> /// <returns>The supplied <see cref="UpdateMasterListDetailsDto"/> when at least one field is modified, or <see langword="null"/> when the document is not found, no changes are applied, or the operation fails.</returns>
/// <!-- aidoc:v1 sig=53d4179 body=49f50ca --> /// <!-- aidoc:v1 sig=53d4179 body=49f50ca -->
public async Task<UpdateMasterListDetailsDto?> UpdateOptionDetailsToMasterList(ObjectId id, public async Task<UpdateMasterListDetailsDto?> UpdateOptionDetailsToMasterList(ObjectId id,
UpdateMasterListDetailsDto opt) UpdateMasterListDetailsDto opt)
@@ -1185,11 +1174,12 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
} }
/// <summary> /// <summary>
/// Updates the <see cref="Name"/> of the master list entry identified by <paramref name="id"/>. /// Updates the name of the master list document identified by <paramref name="id"/>.
/// Returns <c>true</c> if a document was modified, <c>false</c> if no document matched the id or if an exception was caught and logged.
/// </summary> /// </summary>
/// <param name="id">The identifier of the master list entry to update.</param> /// <param name="id">The <see cref="MongoDB.Bson.ObjectId"/> of the master list entry to update.</param>
/// <param name="name">The new name to assign to the master list entry.</param> /// <param name="name">The new name to assign to the entry.</param>
/// <returns><see langword="true"/> if the document was modified; otherwise, <see langword="false"/>, including when the update fails due to an exception.</returns> /// <returns>A <see cref="Task{Boolean}"/> that resolves to <c>true</c> when the update modified a document; otherwise, <c>false</c>.</returns>
/// <!-- aidoc:v1 sig=5b79a51 body=36dfe99 --> /// <!-- aidoc:v1 sig=5b79a51 body=36dfe99 -->
public async Task<bool> UpdateMasterListName(ObjectId id, string name) public async Task<bool> UpdateMasterListName(ObjectId id, string name)
{ {
@@ -1211,12 +1201,12 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
} }
/// <summary> /// <summary>
/// Updates the <c>Description</c> field of the document identified by <paramref name="id"/> in the master list collection. /// Updates the <see cref="T.Description"/> field of the master list entry identified by <paramref name="id"/>.
/// Returns <see langword="true"/> when the update modified at least one document, and <see langword="false"/> when no document was modified or when an error is caught and logged. /// Returns <c>true</c> when the matched document is modified, and <c>false</c> when no document matches the filter or the underlying update operation throws, in which case the exception is logged and the call resolves to <c>false</c>.
/// </summary> /// </summary>
/// <param name="id">The <see cref="ObjectId"/> of the document whose description should be updated.</param> /// <param name="id">The <see cref="ObjectId"/> of the master list entry to update.</param>
/// <param name="description">The new description value to set on the document.</param> /// <param name="description">The new description value to set on the entry.</param>
/// <returns>A <see cref="Task{Boolean}"/> that resolves to <see langword="true"/> if the document was modified, otherwise <see langword="false"/>.</returns> /// <returns>A <see cref="Task{Boolean}"/> that yields <c>true</c> if the update modified a document; otherwise, <c>false</c>.</returns>
/// <!-- aidoc:v1 sig=5a27a55 body=3552f46 --> /// <!-- aidoc:v1 sig=5a27a55 body=3552f46 -->
public async Task<bool> UpdateMasterListDescription(ObjectId id, string description) public async Task<bool> UpdateMasterListDescription(ObjectId id, string description)
{ {
@@ -1238,11 +1228,12 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
} }
/// <summary> /// <summary>
/// Removes the specified <paramref name="oldOpt"/> entry from the "options" array of the MasterList document identified by <paramref name="id"/>, matching on all of the option's properties (name, option type, icons, colors, default flag, and description). Returns <see langword="true"/> when the document was modified (the option was found and pulled), and <see langword="false"/> when no document was modified or when the update fails and the exception is logged. /// Removes an option from a master list by matching all its properties.
/// </summary> /// </summary>
/// <param name="id">The <see cref="ObjectId"/> of the MasterList document to update.</param> /// <param name="id">The ObjectId of the master list.</param>
/// <param name="oldOpt">The <see cref="OptionList"/> instance whose properties define the filter used to pull the matching entry from the "options" array.</param> /// <param name="oldOpt">The OptionList to remove.</param>
/// <returns>A <see cref="Task{Boolean}"/> that resolves to <see langword="true"/> if an option was successfully removed, otherwise <see langword="false"/>.</returns> /// <returns>True if the option was removed; otherwise, false.</returns>
/// <exception cref="Exception">Logs errors and returns false on failure.</exception>
/// <!-- aidoc:v1 sig=8de50cd body=d974b9b --> /// <!-- aidoc:v1 sig=8de50cd body=d974b9b -->
public async Task<bool> RemoveMasterListOption(ObjectId id, OptionList oldOpt) public async Task<bool> RemoveMasterListOption(ObjectId id, OptionList oldOpt)
{ {
@@ -1272,11 +1263,11 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
} }
/// <summary> /// <summary>
/// Creates MongoDB indexes on the underlying collection when the document type is <see cref="DiagnosisList"/>. /// Creates background MongoDB indexes on the <see cref="DiagnosisList"/> collection to optimize queries against the nested <c>options</c> document fields, configuring the indexes with <c>spanish</c> as both the default and override language for text indexing.
/// Three ascending indexes are created on the <c>options.name</c>, <c>options.description</c>, and <c>options._id</c> fields,
/// configured with <c>Background = true</c>, <c>Unique = false</c>, and Spanish text indexing via <c>LanguageOverride</c> and <c>DefaultLanguage</c>.
/// For any other type <typeparamref name="T"/>, no indexes are created.
/// </summary> /// </summary>
/// <remarks>
/// When the generic type parameter is not <see cref="DiagnosisList"/>, the method performs no actions and returns without creating any indexes.
/// </remarks>
/// <!-- aidoc:v1 sig=4955da2 body=2c8d1f7 --> /// <!-- aidoc:v1 sig=4955da2 body=2c8d1f7 -->
public override async Task CreateIndexes() public override async Task CreateIndexes()
{ {
@@ -1389,11 +1380,11 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
} }
/// <summary> /// <summary>
/// Builds a fluent MongoDB find query against the collection, combining the supplied <paramref name="filters"/> with a logical AND when any are present, or using an empty filter that matches every document when the list is empty. The returned query is pre-configured with the given <paramref name="sort"/> ordering. /// Creates a find query against the underlying collection by combining the provided <paramref name="filters"/> with a logical AND and applying the specified <paramref name="sort"/>. When the filter list is empty, an empty filter is used so that the query matches every document.
/// </summary> /// </summary>
/// <param name="filters">List of <see cref="FilterDefinition{T}"/> predicates to apply; an empty list results in no filtering.</param> /// <param name="filters">The list of <see cref="FilterDefinition{T}"/> predicates to combine; an empty list causes no filtering to be applied.</param>
/// <param name="sort">The <see cref="SortDefinition{T}"/> ordering applied to the results.</param> /// <param name="sort">The <see cref="SortDefinition{T}"/> used to order the returned documents.</param>
/// <returns>An <see cref="IFindFluent{T, T}"/> representing the configured find operation.</returns> /// <returns>An <see cref="IFindFluent{T,T}"/> configured with the combined filter and sort, ready for further chaining.</returns>
/// <!-- aidoc:v1 sig=704d715 body=2a35652 --> /// <!-- aidoc:v1 sig=704d715 body=2a35652 -->
private IFindFluent<T, T> CreateFindFluent(List<FilterDefinition<T>> filters, SortDefinition<T> sort) private IFindFluent<T, T> CreateFindFluent(List<FilterDefinition<T>> filters, SortDefinition<T> sort)
{ {
@@ -1404,11 +1395,12 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
} }
/// <summary> /// <summary>
/// Creates a new <see cref="Locale"/> instance and populates each property whose name matches a <see cref="LocaleEnum"/> value, excluding <see cref="LocaleEnum.Default"/> and the value supplied in <paramref name="localeList"/>, with a new <see cref="LocaleItem"/> whose <see cref="LocaleItem.Name"/> is set to <paramref name="opt"/>. /// Generates new locale items for a master list option based on a default locale.
/// Creates LocaleItem entries for all locales except the specified default.
/// </summary> /// </summary>
/// <param name="localeList">The <see cref="LocaleEnum"/> value to skip when populating the new <see cref="Locale"/>.</param> /// <param name="localeList">The default locale to exclude from translations.</param>
/// <param name="opt">The name assigned to each created <see cref="LocaleItem"/> entry.</param> /// <param name="opt">The option name to use as default translation.</param>
/// <returns>A <see cref="Locale"/> with its matching <see cref="LocaleItem"/> properties initialized, except for the omitted locale.</returns> /// <returns>A Locale object with translations for all other locales.</returns>
/// <!-- aidoc:v1 sig=147db59 body=9b63847 --> /// <!-- aidoc:v1 sig=147db59 body=9b63847 -->
private Locale GetNewItemLocale(LocaleEnum localeList, string opt) private Locale GetNewItemLocale(LocaleEnum localeList, string opt)
{ {
@@ -1483,17 +1475,12 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
} }
/// <summary> /// <summary>
/// Retrieves the options of a master list document identified by <paramref name="id"/>, applying locale-aware /// Asynchronously retrieves a filtered list of <see cref="OptionList"/> entries from the master collection by matching the document with the specified <paramref name="id"/> and filtering options whose resolved name equals <paramref name="newOptName"/> for the given <paramref name="locale"/>. When the requested locale differs from the document's default, the pipeline uses the translated name from <c>localeItems</c>, falling back to the original name if no translation is available. Returns an empty list if no matching options are found or if an exception is logged during execution.
/// translation of the option name and filtering the results to those whose translated name matches
/// <paramref name="newOptName"/>. When the requested <paramref name="locale"/> matches the document's default
/// locale the original name is used; otherwise the translated name is preferred and falls back to the original
/// when no translation exists. Returns the matching options ordered by name, or an empty list when the
/// document is not found, no option matches, or an error is logged.
/// </summary> /// </summary>
/// <param name="id">The <see cref="MongoDB.Bson.ObjectId"/> of the master list document to query.</param> /// <param name="id">The <see cref="ObjectId"/> identifying the master document to aggregate.</param>
/// <param name="newOptName">The option name to match against the locale-resolved name of each option.</param> /// <param name="newOptName">The option name used to filter the options after locale-based name resolution.</param>
/// <param name="locale">The <see cref="LocaleEnum"/> value used to select the translated name for each option.</param> /// <param name="locale">The <see cref="LocaleEnum"/> value used to select the translated name for each option.</param>
/// <returns>A <see cref="Task"/> containing a <see cref="List{Object}"/> of matching options ordered by name, or an empty list when no options match or an error occurs.</returns> /// <returns>A <see cref="Task"/> containing a <see cref="List{T}"/> of <see cref="OptionList"/> entries ordered by name, or an empty list when no match exists or an error is caught.</returns>
/// <!-- aidoc:v1 sig=342dc63 body=21f31fc --> /// <!-- aidoc:v1 sig=342dc63 body=21f31fc -->
private async Task<List<OptionList>> GetMasterListByIdAndTextSearch( private async Task<List<OptionList>> GetMasterListByIdAndTextSearch(
ObjectId id, string newOptName, LocaleEnum locale) ObjectId id, string newOptName, LocaleEnum locale)
+23 -24
View File
@@ -157,22 +157,22 @@ public class LdapLoginService : ILoginService
} }
/// <summary> /// <summary>
/// Authenticates a user using the provided HTTP context. The implementation is not yet provided and the method always throws a <see cref="LoginServicesException"/>. /// This method is not implemented in the LdapLoginService, as the login process is handled through the Login(string username, string password) method.
/// </summary> /// </summary>
/// <param name="context">The current <see cref="HttpContext"/> carrying the request data used for authentication.</param> /// <param name="context">The HTTP context of the request.</param>
/// <returns>A <see cref="Task{User}"/> that will resolve to the authenticated user once the method is implemented.</returns> /// <returns>A task representing the asynchronous operation.</returns>
/// <exception cref="LoginServicesException">Thrown because the login operation has not been implemented.</exception> /// <exception cref="LoginServicesException">Thrown when the method is not implemented.</exception>
/// <!-- aidoc:v1 sig=851dc90 --> /// <!-- aidoc:v1 sig=851dc90 -->
public Task<User> Login(HttpContext context) public Task<User> Login(HttpContext context)
=> throw new LoginServicesException("Not implemented"); => throw new LoginServicesException("Not implemented");
/// <summary> /// <summary>
/// Authenticates a user with the provided <paramref name="username"/> and <paramref name="password"/>. /// This method is not implemented in the LdapLoginService, as the authentication process is handled through the Login(string username, string password) method.
/// </summary> /// </summary>
/// <param name="username">The username of the user attempting to authenticate.</param> /// <param name="username">The username of the user to authenticate.</param>
/// <param name="password">The password of the user attempting to authenticate.</param> /// <param name="password">The password of the user to authenticate.</param>
/// <returns>A <see cref="Task{User}"/> that represents the asynchronous authentication operation, yielding the authenticated <see cref="User"/> on success.</returns> /// <returns>A task representing the asynchronous operation.</returns>
/// <exception cref="LoginServicesException">Thrown because the authentication operation is not yet implemented.</exception> /// <exception cref="LoginServicesException">Thrown when the method is not implemented.</exception>
/// <!-- aidoc:v1 sig=a0b1f46 --> /// <!-- aidoc:v1 sig=a0b1f46 -->
public Task<User> Authenticate(string username, string password) public Task<User> Authenticate(string username, string password)
=> throw new LoginServicesException("Not implemented"); => throw new LoginServicesException("Not implemented");
@@ -188,31 +188,30 @@ public class LdapLoginService : ILoginService
=> throw new LoginServicesException("Not implemented"); => throw new LoginServicesException("Not implemented");
/// <summary> /// <summary>
/// Retrieves a <see cref="User"/> matching the supplied email address, or <see langword="null"/> when no user is found. /// This method is not implemented in the LdapLoginService, as the user retrieval process is handled through the Login(string username, string password) method and the GetOrCreateUser(User userEntryLdap, LdapEntry entry) method.
/// </summary> /// </summary>
/// <param name="email">The email address used to look up the <see cref="User"/>.</param> /// <param name="email">The email of the user to retrieve.</param>
/// <returns>A <see cref="Task{T}"/> that resolves to the matching <see cref="User"/>, or <see langword="null"/> if no user exists for the given <paramref name="email"/>.</returns> /// <returns>A task representing the asynchronous operation.</returns>
/// <exception cref="LoginServicesException">Thrown because the operation is not implemented.</exception> /// <exception cref="LoginServicesException">Thrown when the method is not implemented.</exception>
/// <!-- aidoc:v1 sig=ba92b09 --> /// <!-- aidoc:v1 sig=ba92b09 -->
public Task<User?> GetByEmail(string email) public Task<User?> GetByEmail(string email)
=> throw new LoginServicesException("Not implemented"); => throw new LoginServicesException("Not implemented");
/// <summary> /// <summary>
/// Asynchronously retrieves a <see cref="User"/> by the supplied <paramref name="username"/>. /// Retrieves a <see cref="User"/> matching the specified <paramref name="username"/>.
/// The current implementation always throws <see cref="LoginServicesException"/> because the operation is not implemented.
/// </summary> /// </summary>
/// <param name="username">The username used to look up the <see cref="User"/>.</param> /// <param name="username">The username to look up.</param>
/// <returns>A <see cref="Task{TResult}"/> that resolves to the matching <see cref="User"/>, or <see langword="null"/> if no user is found.</returns> /// <returns>A <see cref="Task{TResult}"/> that resolves to the <see cref="User"/> if found, or <see langword="null"/> when no matching user exists.</returns>
/// <exception cref="LoginServicesException">Thrown for every invocation because the operation is not implemented.</exception> /// <exception cref="LoginServicesException">Thrown because the operation is not yet implemented.</exception>
/// <!-- aidoc:v1 sig=5184c30 --> /// <!-- aidoc:v1 sig=5184c30 -->
public Task<User?> GetByUsername(string username) public Task<User?> GetByUsername(string username)
=> throw new LoginServicesException("Not implemented"); => throw new LoginServicesException("Not implemented");
/// <summary> /// <summary>
/// This method is not implemented in the LdapLoginService, as the user retrieval process is handled through the Login(string username, string password) method and the GetOrCreateUser(User userEntryLdap, LdapEntry entry) method. /// Retrieves all <see cref="User"/> entities from the system. This method is not yet implemented and currently throws a <see cref="LoginServicesException"/> when invoked.
/// </summary> /// </summary>
/// <returns>A task representing the asynchronous operation.</returns> /// <returns>A <see cref="Task{List{User}}"/> that represents the asynchronous operation, intended to contain the full collection of <see cref="User"/> entries.</returns>
/// <exception cref="LoginServicesException">Thrown when the method is not implemented.</exception> /// <exception cref="LoginServicesException">Thrown unconditionally because the method has not been implemented.</exception>
/// <!-- aidoc:v1 sig=aa066d6 --> /// <!-- aidoc:v1 sig=aa066d6 -->
public Task<List<User>> GetAllUsers() public Task<List<User>> GetAllUsers()
=> throw new LoginServicesException("Not implemented"); => throw new LoginServicesException("Not implemented");
@@ -340,10 +339,10 @@ public class LdapLoginService : ILoginService
/// <summary> /// <summary>
/// Constructs a <see cref="User"/> from the attributes of the supplied <paramref name="ldapEntry"/>, mapping the LDAP username, first name, and last name properties according to the current configuration. The username falls back to an empty string when the configured attribute is missing, and first/last name values are only applied when their corresponding configuration entries are set and the LDAP entry exposes those attributes, with the last name appended to the first name when both are available. /// Maps an <see cref="LdapEntry"/> to a <see cref="User"/> object, populating the username from the configured attribute and, when the corresponding properties are configured, composing the user's name from the first and last name attributes.
/// </summary> /// </summary>
/// <param name="ldapEntry">The <see cref="LdapEntry"/> whose attributes are read to populate the <see cref="User"/>.</param> /// <param name="ldapEntry">The <see cref="LdapEntry"/> from which the <see cref="User"/> properties are read.</param>
/// <returns>A <see cref="User"/> populated from the <paramref name="ldapEntry"/> attributes.</returns> /// <returns>A <see cref="User"/> instance populated from the LDAP entry attributes.</returns>
/// <!-- aidoc:v1 sig=947181a body=33ffec8 --> /// <!-- aidoc:v1 sig=947181a body=33ffec8 -->
private User GetUser(LdapEntry ldapEntry) private User GetUser(LdapEntry ldapEntry)