2 Commits

Author SHA1 Message Date
n8n IEC 62304 Bot 49def4ee2d docs(iec62304): [REL-1.0.2] apply curated XML doc review updates 2026-07-02 12:27:30 +02:00
n8n IEC 62304 Bot 7de114a95a docs(iec62304): [REL-1.0.2] validate and curate XML doc review markers 2026-07-02 12:21:44 +02:00
@@ -114,12 +114,10 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
}
/// <summary>
/// Updates an existing master list entity with full replacement.
/// Upserts the specified <paramref name="entity"/> in the collection, replacing the document matched by its identifier or inserting it when no match is found. Exceptions are logged and rethrown to the caller.
/// </summary>
/// <param name="entity">The entity with updated values.</param>
/// <exception cref="Exception">Throws and re-throws exceptions after logging.</exception>
/// <!-- aidoc-review:v1 severity=medium kind=wrong_summary
/// "Summary states 'Updates an existing' entity, but the ReplaceOptions { IsUpsert = true } means the entity will be inserted if it does not already exist, so the 'existing' qualifier is contradicted by the code's actual behavior." -->
/// <param name="entity">The entity to persist; its identifier is used as the filter and its state replaces the existing document or creates a new one when absent.</param>
/// <!-- aidoc:v1 sig=019b691 body=863650a -->
public async Task Update(T entity)
{
try
@@ -169,17 +167,11 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
}
/// <summary>
/// Finds a master list entity by its ID with options projection limited to 100 items.
/// Asynchronously retrieves an entity of type <typeparamref name="T"/> from the collection using its <see cref="ObjectId"/>, applying a projection that truncates the "options" field to a maximum of 100 elements. Returns <c>null</c> when no document matches the identifier or when an exception is thrown, in which case the exception is logged and swallowed.
/// </summary>
/// <param name="id">The ObjectId of the entity to retrieve.</param>
/// <returns>The MasterList entity if found; otherwise, null.</returns>
/// <exception cref="Exception">Logs errors and returns null on failure.</exception>
/// <!-- aidoc-review:v1 severity=high kind=wrong_summary
/// "Method is generic (returns Task<T?>) and works on any entity type T, not specifically a 'master list entity'." -->
/// <!-- aidoc-review:v1 severity=high kind=wrong_returns
/// "Documentation says it returns 'The MasterList entity' but the method actually returns Task<T?>, a generic type." -->
/// <!-- aidoc-review:v1 severity=high kind=wrong_exception
/// "Documents <exception cref=\"Exception\"> but the catch block swallows all exceptions and never rethrows, so the method never throws." -->
/// <param name="id">The <see cref="ObjectId"/> identifier of the entity to look up.</param>
/// <returns>A <see cref="Task{T}"/> that resolves to the matching entity of type <typeparamref name="T"/>, or <c>null</c> if the entity is not found or an error occurs during retrieval.</returns>
/// <!-- aidoc:v1 sig=81ac96a body=1519944 -->
public async Task<T?> FindById(ObjectId id)
{
try
@@ -203,16 +195,13 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
}
/// <summary>
/// Finds a specific option within a master list by master and option IDs with locale translation.
/// Uses MongoDB aggregation to apply translations and return the translated option.
/// Retrieves a single <see cref="OptionList"/> item by its parent master identifier and option identifier, resolving the display name according to the requested <paramref name="locale"/> using the aggregation translation logic embedded in the pipeline.
/// </summary>
/// <param name="masterId">The ObjectId of the master list.</param>
/// <param name="optionId">The ObjectId of the option to retrieve.</param>
/// <param name="locale">The locale for translation.</param>
/// <returns>The OptionList with translated fields if found; otherwise, null.</returns>
/// <exception cref="Exception">Logs errors and returns null on failure.</exception>
/// <!-- aidoc-review:v1 severity=medium kind=extra_exception
/// "The method catches all exceptions internally (try/catch) and never throws; documenting <exception cref=\"Exception\"> is misleading. Callers will not receive any exception to handle." -->
/// <param name="masterId">The <see cref="MongoDB.Bson.ObjectId"/> of the master document whose embedded options collection will be searched.</param>
/// <param name="optionId">The <see cref="MongoDB.Bson.ObjectId"/> of the specific <see cref="OptionList"/> to retrieve from the unwound options array.</param>
/// <param name="locale">The <see cref="LocaleEnum"/> used to select the localized name; when equal to <see cref="LocaleEnum.Default"/> or matching the document's default locale, the base name is returned, otherwise the matching <c>localeItems</c> entry is used with a fallback to the base name.</param>
/// <returns>A <see cref="Task"/> that yields the matching <see cref="OptionList"/> deserialized from the aggregation result, or <c>null</c> if no document is found or the operation fails.</returns>
/// <!-- aidoc:v1 sig=fdb2628 body=0e4983e -->
public async Task<OptionList?> FindOptionItemById(ObjectId masterId, ObjectId optionId, LocaleEnum locale)
{
try
@@ -352,14 +341,12 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
}
/// <summary>
/// Finds a specific option within a master list by master and option IDs without locale translation.
/// Asynchronously retrieves the <see cref="OptionList"/> option that matches the supplied <paramref name="masterId"/> and <paramref name="optionId"/> from the parent document's options array, returning the first match or <see langword="null"/> when no option is found or when an error is logged.
/// </summary>
/// <param name="masterId">The ObjectId of the master list.</param>
/// <param name="optionId">The ObjectId of the option to retrieve.</param>
/// <returns>The OptionList if found; otherwise, null.</returns>
/// <exception cref="Exception">Logs errors and returns null on failure.</exception>
/// <!-- aidoc-review:v1 severity=medium kind=extra_exception
/// "The method contains a catch-all for Exception and never lets it propagate to callers, so documenting <exception cref=\"Exception\"> is misleading; the tag should be removed since no exception escapes this method." -->
/// <param name="masterId">The identifier of the master document that owns the options array.</param>
/// <param name="optionId">The identifier of the specific option to locate within that array.</param>
/// <returns>A <see cref="Task{T}"/> that yields the matching <see cref="OptionList"/>, or <see langword="null"/> if the lookup yields no result or the operation fails.</returns>
/// <!-- aidoc:v1 sig=ccc34cb body=71837cc -->
public async Task<OptionList?> FindOptionItemById(ObjectId masterId, ObjectId optionId)
{
try
@@ -385,17 +372,12 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
}
/// <summary>
/// Finds a master list entity by its ID with optional locale translation for options.
/// Uses MongoDB aggregation to unwind options and apply translations.
/// Retrieves an entity by its <see cref="ObjectId"/>, applying locale-aware name resolution to the nested options. When <paramref name="locale"/> is <see cref="LocaleEnum.Default"/> or matches the document's default locale, the original option name is used; otherwise the translated name is looked up in <c>localeItems</c> with a fallback to the original name. Returns <c>null</c> when the entity is not found or an error occurs.
/// </summary>
/// <param name="id">The ObjectId of the entity to retrieve.</param>
/// <param name="locale">Optional locale for translated option names.</param>
/// <returns>The MasterList entity with translated options if found; otherwise, null.</returns>
/// <exception cref="Exception">Logs errors and returns null on failure.</exception>
/// <!-- aidoc-review:v1 severity=high kind=extra_exception
/// "The <exception cref=\"Exception\"> tag is misleading: the catch block handles all exceptions internally and the method returns null, so no Exception is ever thrown to callers. Listing Exception implies callers must handle it, which they cannot." -->
/// <!-- aidoc-review:v1 severity=high kind=wrong_returns
/// "Documentation says 'The MasterList entity' but the method signature is generic Task<T?>, so the returned type is T, not necessarily a MasterList." -->
/// <param name="id">The <see cref="ObjectId"/> of the document to retrieve.</param>
/// <param name="locale">The optional <see cref="LocaleEnum"/> used to resolve translated option names. When <c>null</c> or <see cref="LocaleEnum.Default"/>, the default locale is applied.</param>
/// <returns>A <see cref="Task{T}"/> containing the localized entity, or <c>null</c> when the entity cannot be found or the aggregation fails.</returns>
/// <!-- aidoc:v1 sig=cb4a658 body=f2e88d8 -->
public async Task<T?> FindById(ObjectId id, LocaleEnum? locale)
{
try
@@ -573,17 +555,13 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
}
/// <summary>
/// Finds a master list entity by its name.
/// Asynchronously finds the first entity matching the specified <paramref name="name"/> in the underlying collection,
/// applying a projection that limits the <c>options</c> array to 100 elements. Returns null when no matching document is found,
/// and logs the error and returns null if the lookup throws an exception.
/// </summary>
/// <param name="name">The name of the master list to retrieve.</param>
/// <returns>The MasterList entity if found; otherwise, null.</returns>
/// <exception cref="Exception">Logs errors and returns null on failure.</exception>
/// <!-- aidoc-review:v1 severity=high kind=wrong_exception
/// "The <exception> tag documents Exception being thrown, but the method catches all exceptions internally and returns null instead of letting any exception propagate to the caller." -->
/// <!-- aidoc-review:v1 severity=high kind=wrong_summary
/// "The summary specifies a 'master list entity', but the method is generic (T) and could operate on any type with a Name property; the documentation should not assume a specific type." -->
/// <!-- aidoc-review:v1 severity=high kind=wrong_returns
/// "The <returns> tag describes a MasterList entity, but the method returns Task<T?> where T is a generic type parameter, not necessarily MasterList." -->
/// <param name="name">The value compared against the entity's <c>Name</c> field to locate the document.</param>
/// <returns>A task that yields the first matching entity of type T, or null if no match is found or the operation fails.</returns>
/// <!-- aidoc:v1 sig=80a1541 body=8b5b558 -->
public async Task<T?> FindByName(string name)
{
try
@@ -619,14 +597,12 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
}
/// <summary>
/// Retrieves paginated master lists with optional text filtering.
/// Builds a query for the master list of <typeparamref name="T"/> documents, sorted ascending by the name field.
/// When <paramref name="filter"/> carries non-empty search text, a case-insensitive regex match is applied to the Name property; otherwise the query is returned without additional filtering.
/// </summary>
/// <param name="filter">The pagination and filtering parameters.</param>
/// <returns>A fluent queryable for MasterList results.</returns>
/// <!-- aidoc-review:v1 severity=high kind=wrong_summary
/// "Summary claims the method 'retrieves paginated master lists', but the code only builds filters/sort and returns an IFindFluent without any pagination logic (no Skip/Limit)." -->
/// <!-- aidoc-review:v1 severity=high kind=wrong_returns
/// "Returns tag specifies 'MasterList results', but the method is generic and returns IFindFluent<T, T>, not specifically MasterList." -->
/// <param name="filter">The <see cref="PaginationFilter"/> providing pagination settings and the optional search text.</param>
/// <returns>An <see cref="IFindFluent{T,T}"/> representing the prepared query, ready for further pagination and execution.</returns>
/// <!-- aidoc:v1 sig=bbb39c7 body=f42ebaa -->
public IFindFluent<T, T> GetPaginatedMasterList(PaginationFilter filter)
{
var filterBuilder = Builders<T>.Filter;
@@ -649,13 +625,12 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
}
/// <summary>
/// Retrieves paginated options within a master list with optional text filtering.
/// Retrieves the options belonging to the master list identified by <paramref name="listId"/>, optionally applying a case-insensitive text filter on the option name, description, or type. Returns an empty list when the master list cannot be found.
/// </summary>
/// <param name="filter">The pagination and filtering parameters.</param>
/// <param name="listId">The ObjectId of the master list.</param>
/// <returns>A list of filtered OptionList items.</returns>
/// <!-- aidoc-review:v1 severity=high kind=wrong_summary
/// "Summary and method name claim 'paginated' results, but the code applies only text filtering with no skip/take/page logic — the PaginationFilter's pagination fields are unused." -->
/// <param name="filter">A <see cref="PaginationFilter"/> whose <c>FilteredRequest.Text</c> is used to match option fields when provided.</param>
/// <param name="listId">The identifier of the master <see cref="OptionList"/> whose options are returned.</param>
/// <returns>A task that yields a <see cref="List{OptionList}"/> of options matching the filter, or an empty list if the master list does not exist.</returns>
/// <!-- aidoc:v1 sig=2ac8d75 body=b25fb18 -->
public async Task<List<OptionList>> GetPaginatedOptions(PaginationFilter filter, ObjectId listId)
{
//TODO: LOCALE
@@ -675,14 +650,14 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
}
/// <summary>
/// Adds a new option to a master list.
/// Adds a new <see cref="OptionList"/> entry to the master list identified by <paramref name="id"/>, rejecting duplicates that match the search criteria in <paramref name="opt"/>.
/// When <see cref="FilterOptionListElement.IsFromAdmPanel"/> is set, the provided locale items are reused; otherwise new locale entries are derived from the current default locale (falling back to <see cref="LocaleEnum.Es"/>) through <c>GetNewItemLocale</c>.
/// Returns <see langword="null"/> when the option already exists, the update modifies no documents, or an exception is caught and logged.
/// </summary>
/// <param name="id">The ObjectId of the master list.</param>
/// <param name="opt">The option element to add.</param>
/// <returns>The newly created OptionList if successful; otherwise, null if duplicate exists.</returns>
/// <exception cref="Exception">Logs errors and returns null on failure.</exception>
/// <!-- aidoc-review:v1 severity=medium kind=extra_exception
/// "The method catches all exceptions internally and returns null; it never throws an Exception to the caller, so documenting <exception cref=\"Exception\"> is misleading." -->
/// <param name="id">The identifier of the master list to which the option will be appended.</param>
/// <param name="opt">The option payload, including name, type, visual properties, and locale items used to seed translations.</param>
/// <returns>The persisted <see cref="OptionList"/> on success; otherwise, <see langword="null"/> if a duplicate is found, no document is modified, or an error occurs.</returns>
/// <!-- aidoc:v1 sig=1602f0d body=e7fd138 -->
public async Task<OptionList?> AddOptionToMasterList(ObjectId id, FilterOptionListElement opt)
{
var exist = await GetMasterListByIdAndSearchOptions(id, opt);
@@ -722,16 +697,11 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
}
/// <summary>
/// Retrieves all master list entities.
/// Asynchronously retrieves all entities from the underlying collection by matching every document.
/// If the retrieval fails, the exception is logged and an empty collection is returned as a fallback.
/// </summary>
/// <returns>An enumerable of all MasterList entities.</returns>
/// <exception cref="Exception">Logs errors and returns empty list on failure.</exception>
/// <!-- aidoc-review:v1 severity=high kind=wrong_summary
/// "Summary says 'Retrieves all master list entities' but the method is generic over T and operates on the configured Collection, not specifically MasterList entities." -->
/// <!-- aidoc-review:v1 severity=high kind=wrong_returns
/// "Returns tag says 'An enumerable of all MasterList entities' but the method returns Task<IEnumerable<T>>, where T is a generic type parameter." -->
/// <!-- aidoc-review:v1 severity=high kind=extra_exception
/// "<exception cref=\"Exception\"> implies the method may throw Exception, but the catch block swallows all exceptions and returns an empty list; the method does not throw Exception." -->
/// <returns>A task that yields an <see cref="System.Collections.Generic.IEnumerable{T}"/> of all entities, or an empty collection when an error occurs.</returns>
/// <!-- aidoc:v1 sig=3a61c61 body=40d7129 -->
public async Task<IEnumerable<T>> GetAll()
{
try
@@ -747,12 +717,11 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
}
/// <summary>
/// Retrieves all master list entities without options, returning only metadata.
/// Asynchronously retrieves all <see cref="MasterListDto"/> entries from the collection, mapping each result to include its identifier, name, description, list type, and the count of associated options.
/// If an error occurs while accessing the underlying store, the exception is logged and an empty collection is returned.
/// </summary>
/// <returns>An enumerable of MasterListDto containing id, name, description, listType, and options count.</returns>
/// <exception cref="Exception">Logs errors and returns empty list on failure.</exception>
/// <!-- aidoc-review:v1 severity=medium kind=extra_exception
/// "The method catches all exceptions internally (try/catch around the entire body) and returns an empty list; it never throws Exception to the caller, so the <exception cref=\"Exception\"> tag is misleading." -->
/// <returns>A <see cref="Task{TResult}"/> that yields an <see cref="IEnumerable{MasterListDto}"/> containing the projected master list entries, or an empty collection when the operation fails.</returns>
/// <!-- aidoc:v1 sig=e493435 body=1c299ba -->
public async Task<IEnumerable<MasterListDto>> GetAllWithoutOptions()
{
try
@@ -777,12 +746,10 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
}
/// <summary>
/// Counts the total number of master list entities in the collection.
/// Asynchronously counts all entities in the underlying collection by invoking CountDocumentsAsync with a filter that matches every document. If an exception occurs during the count operation, the error is logged and the method returns <c>0</c> as a safe fallback.
/// </summary>
/// <returns>The total count of entities.</returns>
/// <exception cref="Exception">Logs errors and returns 0 on failure.</exception>
/// <!-- aidoc-review:v1 severity=medium kind=wrong_exception
/// "The method catches all Exception internally and returns 0, so it never throws Exception to callers. The <exception cref=\"Exception\"> tag misleads readers into expecting exceptions to propagate." -->
/// <returns>A <see cref="Task{Int32}"/> that resolves to the total number of entities in the collection, or <c>0</c> if the operation fails.</returns>
/// <!-- aidoc:v1 sig=f1f0a98 body=01cd3d1 -->
public async Task<int> Count()
{
try
@@ -798,15 +765,14 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
}
/// <summary>
/// Searches for options within a master list using multiple filter criteria.
/// Uses MongoDB aggregation pipeline to apply filters and locale translations.
/// Retrieves the master list of <see cref="OptionList"/> entries associated with the supplied <paramref name="id"/>, applying the optional search and locale filters.
/// When <paramref name="filters"/> is <c>null</c> the method short-circuits and returns an empty list; if the <see cref="FilterOptionListElement.Text"/> is provided it takes precedence over <see cref="FilterOptionListElement.Name"/> and <see cref="FilterOptionListElement.Description"/> and is matched as a case-insensitive regex across name and description.
/// The pipeline resolves per-option translations for the requested locale, falling back to the original values when no translation exists, then filters, sorts by name, and returns the result — or an empty list if an exception is encountered.
/// </summary>
/// <param name="id">The ObjectId of the master list.</param>
/// <param name="filters">The filter criteria including text, name, description, and optionType.</param>
/// <returns>A list of matching OptionList items ordered by name.</returns>
/// <exception cref="Exception">Logs errors and returns empty list on failure.</exception>
/// <!-- aidoc-review:v1 severity=medium kind=extra_exception
/// "The method catches all Exception instances and logs them without rethrowing, so no Exception is propagated to the caller; documenting <exception cref=\"Exception\"> is misleading." -->
/// <param name="id">The <see cref="ObjectId"/> of the master list document to match in the aggregation pipeline.</param>
/// <param name="filters">The optional <see cref="FilterOptionListElement"/> carrying the search criteria and locale to apply; when <c>null</c> no lookup is performed.</param>
/// <returns>A <see cref="Task{List{OptionList}}"/> containing the filtered and locale-resolved options ordered by name, or an empty list when <paramref name="filters"/> is <c>null</c> or the aggregation fails.</returns>
/// <!-- aidoc:v1 sig=f6ee5be body=17d6a96 -->
public async Task<List<OptionList>> GetMasterListByIdAndSearchOptions(ObjectId id, FilterOptionListElement? filters)
{
try
@@ -1015,15 +981,13 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
}
/// <summary>
/// Updates a specific option within a master list with locale-aware field updates.
/// Updates an existing option within a master list identified by <paramref name="id"/>, applying the changes from <paramref name="newOpt"/> in the specified <paramref name="locale"/>. Prevents duplicates by short-circuiting when an option with the same name already exists, routes name changes to either the main field or the locale-specific translation entry depending on whether the supplied locale matches the master's default locale, and respects the per-field required flags defined on the master.
/// </summary>
/// <param name="id">The ObjectId of the master list.</param>
/// <param name="newOpt">The OptionList with updated values.</param>
/// <param name="locale">The locale for translation updates.</param>
/// <returns>The updated OptionList if successful; otherwise, null.</returns>
/// <exception cref="Exception">Logs errors and returns null on failure.</exception>
/// <!-- aidoc-review:v1 severity=medium kind=extra_exception
/// "The method catches all exceptions internally and returns null; it does not propagate any exception to callers, so the <exception cref=\"Exception\"/> tag is misleading." -->
/// <param name="id">The <see cref="ObjectId"/> of the master list that contains the option to update.</param>
/// <param name="newOpt">The <see cref="OptionList"/> carrying the new values to be applied to the matching option.</param>
/// <param name="locale">The <see cref="LocaleEnum"/> that determines whether the name is written to the main field or stored as a translation under <c>localeItems</c>.</param>
/// <returns>A <see cref="Task{T}"/> that yields the updated <see cref="OptionList"/> when the operation succeeds, an existing duplicate when one is detected, or <see langword="null"/> when there is nothing to update, no document was modified, or an error is logged and swallowed.</returns>
/// <!-- aidoc:v1 sig=e771f23 body=5520a4a -->
public async Task<OptionList?> UpdateMasterListOption(ObjectId id, OptionList newOpt, LocaleEnum locale)
{
// 1. Evitar duplicados
@@ -1118,14 +1082,13 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
}
/// <summary>
/// Updates a specific option within a master list with full replacement.
/// Updates an existing option within the master list identified by <paramref name="id"/> with the values supplied in <paramref name="newOpt"/>.
/// Returns <see langword="null"/> when the master list cannot be found, when no document is modified, or when the operation fails.
/// </summary>
/// <param name="id">The ObjectId of the master list.</param>
/// <param name="newOpt">The OptionList with updated values.</param>
/// <returns>The updated OptionList if successful; otherwise, null.</returns>
/// <exception cref="Exception">Logs errors and returns null on failure.</exception>
/// <!-- aidoc-review:v1 severity=medium kind=extra_exception
/// "The <exception cref=\"Exception\"> tag is misleading because the method catches Exception rather than throwing it. The described behavior (log and return null) matches the catch block, but this is not an exception thrown by the method." -->
/// <param name="id">The identifier of the master list that contains the option to update.</param>
/// <param name="newOpt">The new option values to persist; its <see cref="OptionList.Id"/> is used to match the existing element.</param>
/// <returns>The updated <see cref="OptionList"/> item, or <see langword="null"/> if the master list is not found, the option was not updated, or an error occurred.</returns>
/// <!-- aidoc:v1 sig=6def54c body=9554543 -->
public async Task<OptionList?> UpdateMasterListOption(ObjectId id, OptionList newOpt)
{
var master = await FindById(id);
@@ -1180,16 +1143,14 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
}
/// <summary>
/// Updates the metadata details for a master list.
/// Asynchronously updates the option details of a master list document identified by <paramref name="id"/>,
/// applying only the non-null fields supplied in <paramref name="opt"/> (such as <see cref="UpdateMasterListDetailsDto.CanAddElement"/> and <see cref="UpdateMasterListDetailsDto.OptionListDetails"/>).
/// Returns the updated <see cref="UpdateMasterListDetailsDto"/> when the document is modified, or <see langword="null"/> when no document matches the identifier, no fields were changed, or an error occurs while updating.
/// </summary>
/// <param name="id">The ObjectId of the master list.</param>
/// <param name="opt">The UpdateMasterListDetailsDto with updated values.</param>
/// <returns>The updated UpdateMasterListDetailsDto if successful; otherwise, null.</returns>
/// <exception cref="Exception">Logs errors and returns null on failure.</exception>
/// <!-- aidoc-review:v1 severity=medium kind=extra_exception
/// "The method catches all exceptions internally and never throws them, so documenting <exception cref=\"Exception\"> is misleading" -->
/// <!-- aidoc-review:v1 severity=medium kind=wrong_summary
/// "Summary says 'metadata details' but the method updates option details (CanAddElement, OptionListDetails)" -->
/// <param name="id">The <see cref="ObjectId"/> identifying the master list document to update.</param>
/// <param name="opt">The <see cref="UpdateMasterListDetailsDto"/> containing the new values to apply; only non-null properties are included in the update.</param>
/// <returns>A <see cref="Task{T}"/> that resolves to the updated <see cref="UpdateMasterListDetailsDto"/> on success, or <see langword="null"/> when the document is not found, not modified, or the operation fails.</returns>
/// <!-- aidoc:v1 sig=53d4179 body=49f50ca -->
public async Task<UpdateMasterListDetailsDto?> UpdateOptionDetailsToMasterList(ObjectId id,
UpdateMasterListDetailsDto opt)
{
@@ -1219,14 +1180,13 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
}
/// <summary>
/// Updates the name of a master list.
/// Updates the name of a master list entry identified by <paramref name="id"/>.
/// Returns <c>true</c> when a document was modified, or <c>false</c> when no document matched the filter or an exception is caught and logged.
/// </summary>
/// <param name="id">The ObjectId of the master list.</param>
/// <param name="name">The new name.</param>
/// <returns>True if the update was successful; otherwise, false.</returns>
/// <exception cref="Exception">Logs errors and returns false on failure.</exception>
/// <!-- aidoc-review:v1 severity=medium kind=extra_exception
/// "The method catches all exceptions internally and never rethrows them, so <exception cref=\"Exception\"> is misleading; callers cannot actually receive an exception from this method." -->
/// <param name="id">The <see cref="ObjectId"/> of the document to update.</param>
/// <param name="name">The new name to assign to the document.</param>
/// <returns><c>true</c> if the update modified a document; otherwise, <c>false</c>.</returns>
/// <!-- aidoc:v1 sig=5b79a51 body=36dfe99 -->
public async Task<bool> UpdateMasterListName(ObjectId id, string name)
{
var filter = Builders<T>.Filter.And(
@@ -1247,14 +1207,12 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
}
/// <summary>
/// Updates the description of a master list.
/// Updates the description of the master list entry identified by <paramref name="id"/>.
/// </summary>
/// <param name="id">The ObjectId of the master list.</param>
/// <param name="description">The new description.</param>
/// <returns>True if the update was successful; otherwise, false.</returns>
/// <exception cref="Exception">Logs errors and returns false on failure.</exception>
/// <!-- aidoc-review:v1 severity=high kind=extra_exception
/// "The method catches all exceptions internally and returns false; it never throws an Exception, so the <exception cref=\"Exception\"> tag is incorrect." -->
/// <param name="id">The <see cref="ObjectId"/> of the master list entry to update.</param>
/// <param name="description">The new description to apply to the entry.</param>
/// <returns><see langword="true"/> when the document was modified; <see langword="false"/> when no document matched the filter or the update operation failed.</returns>
/// <!-- aidoc:v1 sig=5a27a55 body=3552f46 -->
public async Task<bool> UpdateMasterListDescription(ObjectId id, string description)
{
var filter = Builders<T>.Filter.And(
@@ -1275,14 +1233,12 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
}
/// <summary>
/// Removes an option from a master list by matching all its properties.
/// Removes the specified <paramref name="oldOpt"/> entry from the <c>options</c> array of a master list document identified by <paramref name="id"/>. The option is matched by all of its defining properties (name, optionType, iconDefault, iconCategory, iconColor, color, bgColor, isDefault, and description) using a pull filter, and the method returns <see langword="true"/> only when at least one document was modified; if no matching document is found, or if an exception is caught, it is logged and the method returns <see langword="false"/>.
/// </summary>
/// <param name="id">The ObjectId of the master list.</param>
/// <param name="oldOpt">The OptionList to remove.</param>
/// <returns>True if the option was removed; otherwise, false.</returns>
/// <exception cref="Exception">Logs errors and returns false on failure.</exception>
/// <!-- aidoc-review:v1 severity=high kind=extra_exception
/// "The method catches all exceptions in a try/catch and returns false; it does not throw Exception, so the <exception> tag is misleading." -->
/// <param name="id">The <see cref="MongoDB.Bson.ObjectId"/> of the master list document to update.</param>
/// <param name="oldOpt">The <see cref="OptionList"/> whose properties are used to identify which element to pull from the <c>options</c> array.</param>
/// <returns>A <see cref="Task{Boolean}"/> that resolves to <see langword="true"/> if the document was modified (i.e., the option was removed), or <see langword="false"/> if no document was updated or an error occurred.</returns>
/// <!-- aidoc:v1 sig=8de50cd body=d974b9b -->
public async Task<bool> RemoveMasterListOption(ObjectId id, OptionList oldOpt)
{
var filter = Builders<T>.Filter.Eq("_id", id);
@@ -1311,11 +1267,9 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
}
/// <summary>
/// Creates necessary indexes for the MasterList collection.
/// Currently creates text indexes for DiagnosisList on options.name, options.description, and options._id.
/// Creates MongoDB indexes for the <see cref="DiagnosisList"/> entity type, adding non-unique background indexes on the <c>options.name</c>, <c>options.description</c>, and <c>options._id</c> fields with Spanish configured as both the default and override language. If the generic type is not <see cref="DiagnosisList"/>, no indexes are created.
/// </summary>
/// <!-- aidoc-review:v1 severity=high kind=wrong_summary
/// "Documentation claims 'text indexes' are created, but the code uses Builders<T>.IndexKeys.Ascending(), which creates ascending (non-text) indexes." -->
/// <!-- aidoc:v1 sig=4955da2 body=2c8d1f7 -->
public override async Task CreateIndexes()
{
if (typeof(T) == typeof(DiagnosisList))
@@ -1348,14 +1302,12 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
}
/// <summary>
/// Searches for options within a master list using text search with accent-aware regex.
/// Retrieves the options of a referenced entity whose <c>name</c> or <c>description</c> match the supplied <paramref name="textSearch"/>, building a case-insensitive regex pattern (via <c>BuildRegexPattern</c>) and filtering through a MongoDB aggregation pipeline against <see cref="Collection"/>. Returns an empty list when <paramref name="textSearch"/> is null, empty, or whitespace, when the entity identified by <paramref name="id"/> cannot be found, or when no options match; any error is logged and an empty list is returned.
/// </summary>
/// <param name="textSearch">Optional text to search within options.</param>
/// <param name="id">Optional master list ObjectId to filter results.</param>
/// <returns>A list of matching OptionList items ordered by name.</returns>
/// <exception cref="Exception">Logs errors and returns empty list on failure.</exception>
/// <!-- aidoc-review:v1 severity=medium kind=extra_exception
/// "The method catches all exceptions internally (catch (Exception ex)) and never throws to the caller; the <exception cref=\"Exception\"> tag is misleading and should be removed. The catch-block description belongs in the summary or remarks instead." -->
/// <param name="textSearch">The free-text query used to match option names and descriptions. A null, empty, or whitespace value short-circuits the search and yields no results.</param>
/// <param name="id">The <see cref="ObjectId"/> of the parent entity whose options will be searched. When <c>null</c>, the aggregation matches a literal <c>null</c> identifier.</param>
/// <returns>A <see cref="Task{List}"/> containing the matching <see cref="OptionList"/> entries ordered by name, or an empty list when nothing matches or the operation fails.</returns>
/// <!-- aidoc:v1 sig=6ebeac8 body=1d7bbb7 -->
private async Task<List<OptionList>> GetOptionsByTextSearch(string? textSearch, ObjectId? id = null)
{
try
@@ -1428,11 +1380,11 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
}
/// <summary>
/// Creates a fluent query for paginated results with combined filters.
/// Creates an <see cref="IFindFluent{T,T}"/> query by combining the provided <paramref name="filters"/> with a logical AND and applying the given <paramref name="sort"/>. When <paramref name="filters"/> is empty, <see cref="MongoDB.Driver.Builders{TDocument}.Filter.Empty"/> is used so that all documents are matched.
/// </summary>
/// <param name="filters">List of filter definitions to apply.</param>
/// <param name="sort">Sort definition for the query results.</param>
/// <returns>A fluent queryable for T results.</returns>
/// <param name="filters">The list of <see cref="FilterDefinition{T}"/> instances to combine. When the list is empty, no filtering is applied.</param>
/// <param name="sort">The <see cref="SortDefinition{T}"/> to apply to the resulting query.</param>
/// <returns>An <see cref="IFindFluent{T,T}"/> configured with the combined filter and sort.</returns>
/// <!-- aidoc:v1 sig=704d715 body=2a35652 -->
private IFindFluent<T, T> CreateFindFluent(List<FilterDefinition<T>> filters, SortDefinition<T> sort)
{
@@ -1443,14 +1395,12 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
}
/// <summary>
/// Generates new locale items for a master list option based on a default locale.
/// Creates LocaleItem entries for all locales except the specified default.
/// Builds a new <see cref="Locale"/> by assigning a fresh <see cref="LocaleItem"/> (with <see cref="LocaleItem.Name"/> set to <paramref name="opt"/>) to every property of <see cref="Locale"/> whose name matches a <see cref="LocaleEnum"/> value, skipping <see cref="LocaleEnum.Default"/> and the value supplied through <paramref name="localeList"/>.
/// </summary>
/// <param name="localeList">The default locale to exclude from translations.</param>
/// <param name="opt">The option name to use as default translation.</param>
/// <returns>A Locale object with translations for all other locales.</returns>
/// <!-- aidoc-review:v1 severity=medium kind=stale_summary
/// "Summary says items are created for all locales except 'the specified default', but the code also always skips LocaleEnum.Default in addition to the localeList parameter; only one exclusion is documented when two occur." -->
/// <param name="localeList">The <see cref="LocaleEnum"/> value identifying the locale to omit when populating the resulting <see cref="Locale"/>.</param>
/// <param name="opt">The name assigned to each created <see cref="LocaleItem"/>.</param>
/// <returns>A <see cref="Locale"/> with a new <see cref="LocaleItem"/> for every locale other than <see cref="LocaleEnum.Default"/> and <paramref name="localeList"/>; properties without a matching enum name are left unset.</returns>
/// <!-- aidoc:v1 sig=147db59 body=9b63847 -->
private Locale GetNewItemLocale(LocaleEnum localeList, string opt)
{
var newLocale = new Locale();
@@ -1485,11 +1435,11 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
// Método auxiliar para construir patrones regex con soporte de acentos
/// Builds a regex pattern that matches accented and non-accented versions of vowels.
/// Supports Spanish accent handling (á, é, í, ó, ú) and digits.
/// <summary>
/// Builds a case-insensitive regex pattern from <paramref name="input"/>, expanding each vowel into a character class that includes its common accented variants (e.g. <c>a</c> → <c>[aáàäâ]</c>). Digits are wrapped in a character class as literal matches, and any other character is appended as-is to be treated literally by the regex engine.
/// </summary>
/// <param name="input">The input string to build the pattern from.</param>
/// <returns>A regex-compatible pattern string.</returns>
/// <param name="input">The source text whose characters are translated into the resulting regex pattern.</param>
/// <returns>A <see cref="System.String"/> containing the constructed regular expression pattern.</returns>
/// <!-- aidoc:v1 sig=2992c00 body=ae88daf -->
private static string BuildRegexPattern(string input)
{
@@ -1524,16 +1474,17 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
}
/// <summary>
/// Searches for options within a master list by name with locale translation.
/// Uses MongoDB aggregation pipeline to apply locale-aware filtering.
/// Retrieves the options of a master list document identified by <paramref name="id"/>, rebuilding each option's
/// <c>Name</c> by selecting the translation matching <paramref name="locale"/> (or falling back to the original name
/// when the locale is the default or no translation exists), and filters the resulting options by exact match against
/// <paramref name="newOptName"/>. Returns the matched options ordered by name, or an empty list if no document is
/// found, no option matches, or an error occurs.
/// </summary>
/// <param name="id">The ObjectId of the master list.</param>
/// <param name="newOptName">The option name to search for.</param>
/// <param name="locale">The locale for translation.</param>
/// <returns>A list of matching OptionList items ordered by name.</returns>
/// <exception cref="Exception">Logs errors and returns empty list on failure.</exception>
/// <!-- aidoc-review:v1 severity=medium kind=extra_exception
/// "The <exception cref=\"Exception\"> tag documents an exception that is never thrown to the caller: the method catches all exceptions internally, logs them, and returns an empty list. The descriptive text 'Logs errors and returns empty list on failure' is accurate but should not be tagged as an exception." -->
/// <param name="id">MongoDB <see cref="ObjectId"/> of the master list document to search.</param>
/// <param name="newOptName">Option name (already resolved against the requested locale) used to filter the options.</param>
/// <param name="locale">Target <see cref="LocaleEnum"/> used to pick the translated name; the lowercased enum value is matched against the stored locale code.</param>
/// <returns>A <see cref="Task{T}"/> of <see cref="List{T}"/> of <see cref="OptionList"/> containing the matching options sorted by name, or an empty list when there is no match or an error is logged.</returns>
/// <!-- aidoc:v1 sig=342dc63 body=21f31fc -->
private async Task<List<OptionList>> GetMasterListByIdAndTextSearch(
ObjectId id, string newOptName, LocaleEnum locale)
{