6 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
ljrojas91 609c601fe1 chore: ignore n8n local workflow artifacts 2026-07-02 10:56:12 +02:00
n8n IEC 62304 Bot 052918f601 docs: apply curated AI doc review updates for 1.0.2
Documentation branch: docs/rc-1.0.2
Technical branch: release/rc-1.0.2

Scope:
- Technical changed files: 13
- Technical changed C# files: 2
- Curated review markers: 33
- Kept review markers before apply: 32
- Removed false positives during curation: 1

Applied review files:
- adas-core.Infrastructure/Repositories/MasterListRepository.cs

Generated by n8n IEC 62304 documentation workflow.
2026-06-28 22:59:38 +02:00
n8n IEC 62304 Bot d51271effd merge: bring documentation baseline from docs/master into docs/rc-1.0.2 2026-06-28 22:22:56 +02:00
jrojas e6a350a426 aqui copie los archivos de la rama de guitea fix/CR-1.0.1-alineación-actualizacion-de-dependencias 2026-06-28 14:11:07 +02:00
14 changed files with 232 additions and 159 deletions
+4
View File
@@ -381,3 +381,7 @@ FodyWeavers.xsd
.idea .idea
/.ollamassist/conversations /.ollamassist/conversations
/write_readme.py /write_readme.py
# n8n local workflow artifacts
.n8n-docs-rc-flow/
logs/
@@ -21,17 +21,24 @@
<PackageReference Include="AutoMapper" Version="16.1.1" /> <PackageReference Include="AutoMapper" Version="16.1.1" />
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="5.3.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Scripting" Version="5.3.0" /> <PackageReference Include="Microsoft.CodeAnalysis.CSharp.Scripting" Version="5.3.0" />
<PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="10.0.8" /> <PackageReference Include="Microsoft.Extensions.Caching.Memory" Version="10.0.9" />
<PackageReference Include="Microsoft.Extensions.Http" Version="10.0.8" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="10.0.8" /> <PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="10.0.9" />
<PackageReference Include="Microsoft.Extensions.Options" Version="10.0.8" /> <PackageReference Include="Microsoft.Extensions.Http" Version="10.0.9" />
<PackageReference Include="Microsoft.IdentityModel.JsonWebTokens" Version="8.18.0" /> <PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="10.0.9" />
<PackageReference Include="Microsoft.Extensions.Options" Version="10.0.9" />
<PackageReference Include="Microsoft.IdentityModel.JsonWebTokens" Version="8.19.1" />
<PackageReference Include="MongoDB.Driver" Version="3.9.0" /> <PackageReference Include="MongoDB.Driver" Version="3.9.0" />
<PackageReference Include="Quartz" Version="3.18.1" /> <PackageReference Include="Quartz" Version="3.18.1" />
<PackageReference Include="StackExchange.Redis" Version="2.13.17" /> <PackageReference Include="StackExchange.Redis" Version="3.0.0" />
<PackageReference Include="System.Text.Json" Version="10.0.8" /> <PackageReference Include="System.Text.Json" Version="10.0.9" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
@@ -9,12 +9,17 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="AuditLogs" Version="1.0.59" /> <PackageReference Include="AuditLogs" Version="1.0.59" />
<PackageReference Include="Microsoft.AspNetCore.Http" Version="2.3.10" /> <PackageReference Include="Microsoft.AspNetCore.Http" Version="2.3.11" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="8.0.27" /> <PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="8.0.28" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="10.0.8" /> <PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="5.3.0">
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="10.0.8" /> <PrivateAssets>all</PrivateAssets>
<PackageReference Include="Microsoft.IdentityModel.Tokens" Version="8.18.0" /> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.18.0" /> </PackageReference>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Scripting" Version="5.3.0" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="10.0.9" />
<PackageReference Include="Microsoft.Extensions.Options.ConfigurationExtensions" Version="10.0.9" />
<PackageReference Include="Microsoft.IdentityModel.Tokens" Version="8.19.1" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.19.1" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
+6 -6
View File
@@ -10,17 +10,17 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="AuditLogs" Version="1.0.59" /> <PackageReference Include="AuditLogs" Version="1.0.59" />
<PackageReference Include="BCrypt.Net-Next" Version="4.2.0" /> <PackageReference Include="BCrypt.Net-Next" Version="4.2.0" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Abstractions" Version="2.3.10" /> <PackageReference Include="Microsoft.AspNetCore.Mvc.Abstractions" Version="2.3.11" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="2.3.10" /> <PackageReference Include="Microsoft.AspNetCore.Mvc.Core" Version="2.3.11" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.27" /> <PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.28" />
<PackageReference Include="MongoDB.Bson" Version="3.9.0" /> <PackageReference Include="MongoDB.Bson" Version="3.9.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
<PackageReference Include="Newtonsoft.Json.Bson" Version="1.0.3" /> <PackageReference Include="Newtonsoft.Json.Bson" Version="1.0.3" />
<PackageReference Include="Serilog" Version="4.3.1" /> <PackageReference Include="Serilog" Version="4.3.1" />
<PackageReference Include="SharpCompress" Version="0.49.0" /> <PackageReference Include="SharpCompress" Version="0.49.1" />
<PackageReference Include="Snappier" Version="1.3.1" /> <PackageReference Include="Snappier" Version="1.3.1" />
<PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.18.0" /> <PackageReference Include="System.IdentityModel.Tokens.Jwt" Version="8.19.1" />
<PackageReference Include="System.Text.Json" Version="10.0.8" /> <PackageReference Include="System.Text.Json" Version="10.0.9" />
<PackageReference Include="TagLibSharp" Version="2.3.0" /> <PackageReference Include="TagLibSharp" Version="2.3.0" />
</ItemGroup> </ItemGroup>
@@ -20,6 +20,7 @@ namespace adas_core.Infrastructure.Repositories;
/// options lists, diagnoses, allergies, procedures, treatments, and other reference data. /// options lists, diagnoses, allergies, procedures, treatments, and other reference data.
/// </summary> /// </summary>
/// <typeparam name="T">The type of MasterList entity to manage.</typeparam> /// <typeparam name="T">The type of MasterList entity to manage.</typeparam>
/// <!-- aidoc:v1 sig=f958de2 -->
public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository<T> where T : MasterList public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository<T> where T : MasterList
{ {
private readonly ApiSettings _apiSettings; private readonly ApiSettings _apiSettings;
@@ -30,6 +31,7 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
/// <param name="apiSettings">API settings containing collection names configuration.</param> /// <param name="apiSettings">API settings containing collection names configuration.</param>
/// <param name="database">The MongoDB database instance.</param> /// <param name="database">The MongoDB database instance.</param>
/// <exception cref="ArgumentNullException">Thrown when apiSettings is null.</exception> /// <exception cref="ArgumentNullException">Thrown when apiSettings is null.</exception>
/// <!-- aidoc:v1 sig=800d538 body=d2b18a3 -->
public MasterListRepository(IOptions<ApiSettings> apiSettings, IMongoDatabase database) : base(database) public MasterListRepository(IOptions<ApiSettings> apiSettings, IMongoDatabase database) : base(database)
{ {
if (apiSettings == null) throw new ArgumentNullException(nameof(apiSettings)); if (apiSettings == null) throw new ArgumentNullException(nameof(apiSettings));
@@ -41,6 +43,7 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
/// Maps different MasterList subtypes to their corresponding MongoDB collection names. /// Maps different MasterList subtypes to their corresponding MongoDB collection names.
/// </summary> /// </summary>
/// <returns>The collection name for the current MasterList type.</returns> /// <returns>The collection name for the current MasterList type.</returns>
/// <!-- aidoc:v1 sig=94e22ff body=64e6c55 -->
public override string GetCollectionName() public override string GetCollectionName()
{ {
return typeof(T) switch return typeof(T) switch
@@ -76,6 +79,7 @@ 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
@@ -94,6 +98,7 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
/// </summary> /// </summary>
/// <param name="id">The ObjectId of the entity to delete.</param> /// <param name="id">The ObjectId of the entity to delete.</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=3de1ad6 body=fe0ba8c -->
public async Task Delete(ObjectId id) public async Task Delete(ObjectId id)
{ {
try try
@@ -109,10 +114,10 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
} }
/// <summary> /// <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> /// </summary>
/// <param name="entity">The entity with updated values.</param> /// <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>
/// <exception cref="Exception">Throws and re-throws exceptions after logging.</exception> /// <!-- aidoc:v1 sig=019b691 body=863650a -->
public async Task Update(T entity) public async Task Update(T entity)
{ {
try try
@@ -133,6 +138,7 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
/// <param name="id">The ObjectId of the master list.</param> /// <param name="id">The ObjectId of the master list.</param>
/// <param name="newOpt">The OptionList with updated values.</param> /// <param name="newOpt">The OptionList with updated values.</param>
/// <returns>The updated OptionList if found; otherwise, null.</returns> /// <returns>The updated OptionList if found; otherwise, null.</returns>
/// <!-- aidoc:v1 sig=64ca4dd body=a7714e6 -->
public async Task<OptionList?> UpdateFullMasterListOption(ObjectId id, OptionList newOpt) public async Task<OptionList?> UpdateFullMasterListOption(ObjectId id, OptionList newOpt)
{ {
var filter = Builders<T>.Filter.Where(o => o.Id == id && o.Options.Any(opt => opt.Id == newOpt.Id) var filter = Builders<T>.Filter.Where(o => o.Id == id && o.Options.Any(opt => opt.Id == newOpt.Id)
@@ -161,11 +167,11 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
} }
/// <summary> /// <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> /// </summary>
/// <param name="id">The ObjectId of the entity to retrieve.</param> /// <param name="id">The <see cref="ObjectId"/> identifier of the entity to look up.</param>
/// <returns>The MasterList entity if found; otherwise, null.</returns> /// <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>
/// <exception cref="Exception">Logs errors and returns null on failure.</exception> /// <!-- aidoc:v1 sig=81ac96a body=1519944 -->
public async Task<T?> FindById(ObjectId id) public async Task<T?> FindById(ObjectId id)
{ {
try try
@@ -189,14 +195,13 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
} }
/// <summary> /// <summary>
/// Finds a specific option within a master list by master and option IDs with locale translation. /// 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.
/// Uses MongoDB aggregation to apply translations and return the translated option.
/// </summary> /// </summary>
/// <param name="masterId">The ObjectId of the master list.</param> /// <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 ObjectId of the option to retrieve.</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 locale for translation.</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>The OptionList with translated fields if found; otherwise, null.</returns> /// <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>
/// <exception cref="Exception">Logs errors and returns null on failure.</exception> /// <!-- 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)
{ {
try try
@@ -336,12 +341,12 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
} }
/// <summary> /// <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> /// </summary>
/// <param name="masterId">The ObjectId of the master list.</param> /// <param name="masterId">The identifier of the master document that owns the options array.</param>
/// <param name="optionId">The ObjectId of the option to retrieve.</param> /// <param name="optionId">The identifier of the specific option to locate within that array.</param>
/// <returns>The OptionList if found; otherwise, null.</returns> /// <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>
/// <exception cref="Exception">Logs errors and returns null on failure.</exception> /// <!-- aidoc:v1 sig=ccc34cb body=71837cc -->
public async Task<OptionList?> FindOptionItemById(ObjectId masterId, ObjectId optionId) public async Task<OptionList?> FindOptionItemById(ObjectId masterId, ObjectId optionId)
{ {
try try
@@ -367,13 +372,12 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
} }
/// <summary> /// <summary>
/// Finds a master list entity by its ID with optional locale translation for options. /// 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.
/// Uses MongoDB aggregation to unwind options and apply translations.
/// </summary> /// </summary>
/// <param name="id">The ObjectId of the entity to retrieve.</param> /// <param name="id">The <see cref="ObjectId"/> of the document to retrieve.</param>
/// <param name="locale">Optional locale for translated option names.</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>The MasterList entity with translated options if found; otherwise, null.</returns> /// <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>
/// <exception cref="Exception">Logs errors and returns null on failure.</exception> /// <!-- aidoc:v1 sig=cb4a658 body=f2e88d8 -->
public async Task<T?> FindById(ObjectId id, LocaleEnum? locale) public async Task<T?> FindById(ObjectId id, LocaleEnum? locale)
{ {
try try
@@ -551,11 +555,13 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
} }
/// <summary> /// <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> /// </summary>
/// <param name="name">The name of the master list to retrieve.</param> /// <param name="name">The value compared against the entity's <c>Name</c> field to locate the document.</param>
/// <returns>The MasterList entity if found; otherwise, null.</returns> /// <returns>A task that yields the first matching entity of type T, or null if no match is found or the operation fails.</returns>
/// <exception cref="Exception">Logs errors and returns null on failure.</exception> /// <!-- aidoc:v1 sig=80a1541 body=8b5b558 -->
public async Task<T?> FindByName(string name) public async Task<T?> FindByName(string name)
{ {
try try
@@ -584,16 +590,19 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
/// <param name="id">The ObjectId of the master list.</param> /// <param name="id">The ObjectId of the master list.</param>
/// <param name="textSearch">Optional text to search within options.</param> /// <param name="textSearch">Optional text to search within options.</param>
/// <returns>A list of matching OptionList items.</returns> /// <returns>A list of matching OptionList items.</returns>
/// <!-- aidoc:v1 sig=569d223 body=bb7f2c6 -->
public async Task<List<OptionList>> GetMasterListByIdAndTextSearchContaining(ObjectId id, string? textSearch) public async Task<List<OptionList>> GetMasterListByIdAndTextSearchContaining(ObjectId id, string? textSearch)
{ {
return await GetOptionsByTextSearch(textSearch, id); return await GetOptionsByTextSearch(textSearch, id);
} }
/// <summary> /// <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> /// </summary>
/// <param name="filter">The pagination and filtering parameters.</param> /// <param name="filter">The <see cref="PaginationFilter"/> providing pagination settings and the optional search text.</param>
/// <returns>A fluent queryable for MasterList results.</returns> /// <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) public IFindFluent<T, T> GetPaginatedMasterList(PaginationFilter filter)
{ {
var filterBuilder = Builders<T>.Filter; var filterBuilder = Builders<T>.Filter;
@@ -616,11 +625,12 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
} }
/// <summary> /// <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> /// </summary>
/// <param name="filter">The pagination and filtering parameters.</param> /// <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 ObjectId of the master list.</param> /// <param name="listId">The identifier of the master <see cref="OptionList"/> whose options are returned.</param>
/// <returns>A list of filtered OptionList items.</returns> /// <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) public async Task<List<OptionList>> GetPaginatedOptions(PaginationFilter filter, ObjectId listId)
{ {
//TODO: LOCALE //TODO: LOCALE
@@ -640,12 +650,14 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
} }
/// <summary> /// <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> /// </summary>
/// <param name="id">The ObjectId of the master list.</param> /// <param name="id">The identifier of the master list to which the option will be appended.</param>
/// <param name="opt">The option element to add.</param> /// <param name="opt">The option payload, including name, type, visual properties, and locale items used to seed translations.</param>
/// <returns>The newly created OptionList if successful; otherwise, null if duplicate exists.</returns> /// <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>
/// <exception cref="Exception">Logs errors and returns null on failure.</exception> /// <!-- aidoc:v1 sig=1602f0d body=e7fd138 -->
public async Task<OptionList?> AddOptionToMasterList(ObjectId id, FilterOptionListElement opt) public async Task<OptionList?> AddOptionToMasterList(ObjectId id, FilterOptionListElement opt)
{ {
var exist = await GetMasterListByIdAndSearchOptions(id, opt); var exist = await GetMasterListByIdAndSearchOptions(id, opt);
@@ -685,10 +697,11 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
} }
/// <summary> /// <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> /// </summary>
/// <returns>An enumerable of all MasterList entities.</returns> /// <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>
/// <exception cref="Exception">Logs errors and returns empty list on failure.</exception> /// <!-- aidoc:v1 sig=3a61c61 body=40d7129 -->
public async Task<IEnumerable<T>> GetAll() public async Task<IEnumerable<T>> GetAll()
{ {
try try
@@ -704,10 +717,11 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
} }
/// <summary> /// <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> /// </summary>
/// <returns>An enumerable of MasterListDto containing id, name, description, listType, and options count.</returns> /// <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>
/// <exception cref="Exception">Logs errors and returns empty list on failure.</exception> /// <!-- aidoc:v1 sig=e493435 body=1c299ba -->
public async Task<IEnumerable<MasterListDto>> GetAllWithoutOptions() public async Task<IEnumerable<MasterListDto>> GetAllWithoutOptions()
{ {
try try
@@ -732,10 +746,10 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
} }
/// <summary> /// <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> /// </summary>
/// <returns>The total count of entities.</returns> /// <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>
/// <exception cref="Exception">Logs errors and returns 0 on failure.</exception> /// <!-- aidoc:v1 sig=f1f0a98 body=01cd3d1 -->
public async Task<int> Count() public async Task<int> Count()
{ {
try try
@@ -751,13 +765,14 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
} }
/// <summary> /// <summary>
/// Searches for options within a master list using multiple filter criteria. /// Retrieves the master list of <see cref="OptionList"/> entries associated with the supplied <paramref name="id"/>, applying the optional search and locale filters.
/// Uses MongoDB aggregation pipeline to apply filters and locale translations. /// 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> /// </summary>
/// <param name="id">The ObjectId of the master list.</param> /// <param name="id">The <see cref="ObjectId"/> of the master list document to match in the aggregation pipeline.</param>
/// <param name="filters">The filter criteria including text, name, description, and optionType.</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 list of matching OptionList items ordered by name.</returns> /// <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>
/// <exception cref="Exception">Logs errors and returns empty list on failure.</exception> /// <!-- 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)
{ {
try try
@@ -966,13 +981,13 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
} }
/// <summary> /// <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> /// </summary>
/// <param name="id">The ObjectId of the master list.</param> /// <param name="id">The <see cref="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"/> carrying the new values to be applied to the matching option.</param>
/// <param name="locale">The locale for translation updates.</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>The updated OptionList if successful; otherwise, null.</returns> /// <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>
/// <exception cref="Exception">Logs errors and returns null on failure.</exception> /// <!-- 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)
{ {
// 1. Evitar duplicados // 1. Evitar duplicados
@@ -1067,12 +1082,13 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
} }
/// <summary> /// <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> /// </summary>
/// <param name="id">The ObjectId of the master list.</param> /// <param name="id">The identifier of the master list that contains the option to update.</param>
/// <param name="newOpt">The OptionList with updated values.</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 OptionList if successful; otherwise, null.</returns> /// <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>
/// <exception cref="Exception">Logs errors and returns null on failure.</exception> /// <!-- aidoc:v1 sig=6def54c body=9554543 -->
public async Task<OptionList?> UpdateMasterListOption(ObjectId id, OptionList newOpt) public async Task<OptionList?> UpdateMasterListOption(ObjectId id, OptionList newOpt)
{ {
var master = await FindById(id); var master = await FindById(id);
@@ -1108,6 +1124,7 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
/// <param name="id">The ObjectId of the master list.</param> /// <param name="id">The ObjectId of the master list.</param>
/// <param name="deleteOptId">The ObjectId of the option to delete.</param> /// <param name="deleteOptId">The ObjectId of the option to delete.</param>
/// <returns>True if the option was deleted; otherwise, false.</returns> /// <returns>True if the option was deleted; otherwise, false.</returns>
/// <!-- aidoc:v1 sig=e663f16 body=75627bc -->
public async Task<bool> DeleteMasterListOption(ObjectId id, ObjectId deleteOptId) public async Task<bool> DeleteMasterListOption(ObjectId id, ObjectId deleteOptId)
{ {
// Define el filtro para encontrar el documento por su _id // Define el filtro para encontrar el documento por su _id
@@ -1126,12 +1143,14 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
} }
/// <summary> /// <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> /// </summary>
/// <param name="id">The ObjectId of the master list.</param> /// <param name="id">The <see cref="ObjectId"/> identifying the master list document to update.</param>
/// <param name="opt">The UpdateMasterListDetailsDto with updated values.</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>The updated UpdateMasterListDetailsDto if successful; otherwise, null.</returns> /// <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>
/// <exception cref="Exception">Logs errors and returns null on failure.</exception> /// <!-- aidoc:v1 sig=53d4179 body=49f50ca -->
public async Task<UpdateMasterListDetailsDto?> UpdateOptionDetailsToMasterList(ObjectId id, public async Task<UpdateMasterListDetailsDto?> UpdateOptionDetailsToMasterList(ObjectId id,
UpdateMasterListDetailsDto opt) UpdateMasterListDetailsDto opt)
{ {
@@ -1161,12 +1180,13 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
} }
/// <summary> /// <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> /// </summary>
/// <param name="id">The ObjectId of the master list.</param> /// <param name="id">The <see cref="ObjectId"/> of the document to update.</param>
/// <param name="name">The new name.</param> /// <param name="name">The new name to assign to the document.</param>
/// <returns>True if the update was successful; otherwise, false.</returns> /// <returns><c>true</c> if the update modified a document; otherwise, <c>false</c>.</returns>
/// <exception cref="Exception">Logs errors and returns false on failure.</exception> /// <!-- aidoc:v1 sig=5b79a51 body=36dfe99 -->
public async Task<bool> UpdateMasterListName(ObjectId id, string name) public async Task<bool> UpdateMasterListName(ObjectId id, string name)
{ {
var filter = Builders<T>.Filter.And( var filter = Builders<T>.Filter.And(
@@ -1187,12 +1207,12 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
} }
/// <summary> /// <summary>
/// Updates the description of a master list. /// Updates the description of the master list entry identified by <paramref name="id"/>.
/// </summary> /// </summary>
/// <param name="id">The ObjectId of the master list.</param> /// <param name="id">The <see cref="ObjectId"/> of the master list entry to update.</param>
/// <param name="description">The new description.</param> /// <param name="description">The new description to apply to the entry.</param>
/// <returns>True if the update was successful; otherwise, false.</returns> /// <returns><see langword="true"/> when the document was modified; <see langword="false"/> when no document matched the filter or the update operation failed.</returns>
/// <exception cref="Exception">Logs errors and returns false on failure.</exception> /// <!-- aidoc:v1 sig=5a27a55 body=3552f46 -->
public async Task<bool> UpdateMasterListDescription(ObjectId id, string description) public async Task<bool> UpdateMasterListDescription(ObjectId id, string description)
{ {
var filter = Builders<T>.Filter.And( var filter = Builders<T>.Filter.And(
@@ -1213,12 +1233,12 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
} }
/// <summary> /// <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> /// </summary>
/// <param name="id">The ObjectId of the master list.</param> /// <param name="id">The <see cref="MongoDB.Bson.ObjectId"/> of the master list document to update.</param>
/// <param name="oldOpt">The OptionList to remove.</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>True if the option was removed; otherwise, false.</returns> /// <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>
/// <exception cref="Exception">Logs errors and returns false on failure.</exception> /// <!-- aidoc:v1 sig=8de50cd body=d974b9b -->
public async Task<bool> RemoveMasterListOption(ObjectId id, OptionList oldOpt) public async Task<bool> RemoveMasterListOption(ObjectId id, OptionList oldOpt)
{ {
var filter = Builders<T>.Filter.Eq("_id", id); var filter = Builders<T>.Filter.Eq("_id", id);
@@ -1247,9 +1267,9 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
} }
/// <summary> /// <summary>
/// Creates necessary indexes for the MasterList collection. /// 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.
/// Currently creates text indexes for DiagnosisList on options.name, options.description, and options._id.
/// </summary> /// </summary>
/// <!-- aidoc:v1 sig=4955da2 body=2c8d1f7 -->
public override async Task CreateIndexes() public override async Task CreateIndexes()
{ {
if (typeof(T) == typeof(DiagnosisList)) if (typeof(T) == typeof(DiagnosisList))
@@ -1275,18 +1295,19 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
/// </summary> /// </summary>
/// <param name="textSearch">Optional text to search within options.</param> /// <param name="textSearch">Optional text to search within options.</param>
/// <returns>A list of matching OptionList items.</returns> /// <returns>A list of matching OptionList items.</returns>
/// <!-- aidoc:v1 sig=484b092 body=48e3496 -->
public async Task<List<OptionList>> GetMasterListByTextSearch(string? textSearch) public async Task<List<OptionList>> GetMasterListByTextSearch(string? textSearch)
{ {
return await GetOptionsByTextSearch(textSearch); return await GetOptionsByTextSearch(textSearch);
} }
/// <summary> /// <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> /// </summary>
/// <param name="textSearch">Optional text to search within options.</param> /// <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">Optional master list ObjectId to filter 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 list of matching OptionList items ordered by name.</returns> /// <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>
/// <exception cref="Exception">Logs errors and returns empty list on failure.</exception> /// <!-- aidoc:v1 sig=6ebeac8 body=1d7bbb7 -->
private async Task<List<OptionList>> GetOptionsByTextSearch(string? textSearch, ObjectId? id = null) private async Task<List<OptionList>> GetOptionsByTextSearch(string? textSearch, ObjectId? id = null)
{ {
try try
@@ -1296,7 +1317,6 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
// Normaliza el texto de búsqueda a minúsculas // Normaliza el texto de búsqueda a minúsculas
var normalizedTextSearch = textSearch.ToLowerInvariant(); var normalizedTextSearch = textSearch.ToLowerInvariant();
// Construye la expresión regular dinámica para tener en cuenta la acentuación en las vocales
var regexPattern = BuildRegexPattern(normalizedTextSearch); var regexPattern = BuildRegexPattern(normalizedTextSearch);
// foreach (var c in normalizedTextSearch) // foreach (var c in normalizedTextSearch)
// { // {
@@ -1360,11 +1380,12 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
} }
/// <summary> /// <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> /// </summary>
/// <param name="filters">List of filter definitions to apply.</param> /// <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">Sort definition for the query results.</param> /// <param name="sort">The <see cref="SortDefinition{T}"/> to apply to the resulting query.</param>
/// <returns>A fluent queryable for T results.</returns> /// <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) private IFindFluent<T, T> CreateFindFluent(List<FilterDefinition<T>> filters, SortDefinition<T> sort)
{ {
var combinedFilter = filters.Any() var combinedFilter = filters.Any()
@@ -1374,12 +1395,12 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
} }
/// <summary> /// <summary>
/// Generates new locale items for a master list option based on a default locale. /// 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"/>.
/// Creates LocaleItem entries for all locales except the specified default.
/// </summary> /// </summary>
/// <param name="localeList">The default locale to exclude from translations.</param> /// <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 option name to use as default translation.</param> /// <param name="opt">The name assigned to each created <see cref="LocaleItem"/>.</param>
/// <returns>A Locale object with translations for all other locales.</returns> /// <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) private Locale GetNewItemLocale(LocaleEnum localeList, string opt)
{ {
var newLocale = new Locale(); var newLocale = new Locale();
@@ -1414,11 +1435,12 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
// Método auxiliar para construir patrones regex con soporte de acentos // Método auxiliar para construir patrones regex con soporte de acentos
/// Builds a regex pattern that matches accented and non-accented versions of vowels. /// <summary>
/// Supports Spanish accent handling (á, é, í, ó, ú) and digits. /// 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> /// </summary>
/// <param name="input">The input string to build the pattern from.</param> /// <param name="input">The source text whose characters are translated into the resulting regex pattern.</param>
/// <returns>A regex-compatible pattern string.</returns> /// <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) private static string BuildRegexPattern(string input)
{ {
var regexPattern = new StringBuilder(); var regexPattern = new StringBuilder();
@@ -1452,14 +1474,17 @@ public class MasterListRepository<T> : MongoRepository<T>, IMasterListRepository
} }
/// <summary> /// <summary>
/// Searches for options within a master list by name with locale translation. /// Retrieves the options of a master list document identified by <paramref name="id"/>, rebuilding each option's
/// Uses MongoDB aggregation pipeline to apply locale-aware filtering. /// <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> /// </summary>
/// <param name="id">The ObjectId of the master list.</param> /// <param name="id">MongoDB <see cref="ObjectId"/> of the master list document to search.</param>
/// <param name="newOptName">The option name to search for.</param> /// <param name="newOptName">Option name (already resolved against the requested locale) used to filter the options.</param>
/// <param name="locale">The locale for translation.</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 list of matching OptionList items ordered by name.</returns> /// <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>
/// <exception cref="Exception">Logs errors and returns empty list on failure.</exception> /// <!-- 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)
{ {
@@ -9,11 +9,16 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="AuditLogs" Version="1.0.59" /> <PackageReference Include="AuditLogs" Version="1.0.59" />
<PackageReference Include="EasyNetQ" Version="8.1.4" /> <PackageReference Include="EasyNetQ" Version="8.1.5" />
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="10.0.8" /> <PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="5.3.0">
<PackageReference Include="Microsoft.Extensions.Options" Version="10.0.8" /> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Scripting" Version="5.3.0" />
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="10.0.9" />
<PackageReference Include="Microsoft.Extensions.Options" Version="10.0.9" />
<PackageReference Include="MongoMigrations.Core" Version="4.0.15" /> <PackageReference Include="MongoMigrations.Core" Version="4.0.15" />
<PackageReference Include="StackExchange.Redis" Version="2.13.17" /> <PackageReference Include="StackExchange.Redis" Version="3.0.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
@@ -14,6 +14,11 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="AuditLogs" Version="1.0.59" /> <PackageReference Include="AuditLogs" Version="1.0.59" />
<PackageReference Include="FluentValidation" Version="12.1.1" /> <PackageReference Include="FluentValidation" Version="12.1.1" />
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="5.3.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Scripting" Version="5.3.0" />
<PackageReference Include="Novell.Directory.Ldap.NETStandard" Version="4.0.0" /> <PackageReference Include="Novell.Directory.Ldap.NETStandard" Version="4.0.0" />
</ItemGroup> </ItemGroup>
@@ -8,13 +8,18 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\adas-core.Authentication\adas-core.Authentication.csproj"/> <ProjectReference Include="..\adas-core.Authentication\adas-core.Authentication.csproj" />
<ProjectReference Include="..\adas-core.Infrastructure\adas-core.Infrastructure.csproj"/> <ProjectReference Include="..\adas-core.Infrastructure\adas-core.Infrastructure.csproj" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="AuditLogs" Version="1.0.59" /> <PackageReference Include="AuditLogs" Version="1.0.59" />
<PackageReference Include="Portable.BouncyCastle" Version="1.9.0"/> <PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="5.3.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Scripting" Version="5.3.0" />
<PackageReference Include="Portable.BouncyCastle" Version="1.9.0" />
</ItemGroup> </ItemGroup>
</Project> </Project>
+6 -1
View File
@@ -21,6 +21,11 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="AuditLogs" Version="1.0.59" /> <PackageReference Include="AuditLogs" Version="1.0.59" />
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="5.3.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.Analyzers" Version="10.0.9" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.6.0" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.6.0" />
<PackageReference Include="Microsoft.QualityTools.Testing.Fakes" Version="18.1.1" /> <PackageReference Include="Microsoft.QualityTools.Testing.Fakes" Version="18.1.1" />
<PackageReference Include="Mongo2Go" Version="4.1.0" /> <PackageReference Include="Mongo2Go" Version="4.1.0" />
@@ -28,7 +33,7 @@
<PackageReference Include="Moq" Version="4.20.72" /> <PackageReference Include="Moq" Version="4.20.72" />
<PackageReference Include="NUnit" Version="4.6.1" /> <PackageReference Include="NUnit" Version="4.6.1" />
<PackageReference Include="NUnit3TestAdapter" Version="6.2.0" /> <PackageReference Include="NUnit3TestAdapter" Version="6.2.0" />
<PackageReference Include="NUnit.Analyzers" Version="4.13.0"> <PackageReference Include="NUnit.Analyzers" Version="4.14.0">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference> </PackageReference>
@@ -14,6 +14,11 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="AuditLogs" Version="1.0.59" /> <PackageReference Include="AuditLogs" Version="1.0.59" />
<PackageReference Include="HtmlAgilityPack" Version="1.12.4" /> <PackageReference Include="HtmlAgilityPack" Version="1.12.4" />
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="5.3.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Scripting" Version="5.3.0" />
</ItemGroup> </ItemGroup>
</Project> </Project>
@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>net8.0</TargetFramework> <TargetFramework>net8.0</TargetFramework>
@@ -15,10 +15,10 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="AuditLogs" Version="1.0.59" /> <PackageReference Include="AuditLogs" Version="1.0.59" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="10.0.8" /> <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="10.0.9" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="10.0.8" /> <PackageReference Include="Microsoft.Extensions.Hosting" Version="10.0.9" />
<PackageReference Include="Serilog" Version="4.3.1" /> <PackageReference Include="Serilog" Version="4.3.1" />
<PackageReference Include="SharpCompress" Version="0.49.0" /> <PackageReference Include="SharpCompress" Version="0.49.1" />
<PackageReference Include="Snappier" Version="1.3.1" /> <PackageReference Include="Snappier" Version="1.3.1" />
</ItemGroup> </ItemGroup>
@@ -9,7 +9,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="AuditLogs" Version="1.0.59" /> <PackageReference Include="AuditLogs" Version="1.0.59" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="10.0.8" /> <PackageReference Include="Microsoft.Extensions.Hosting" Version="10.0.9" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
+2 -2
View File
@@ -21,7 +21,7 @@ using adas_core.WebSocket;
using adas_core.WebSocket.Hubs; using adas_core.WebSocket.Hubs;
using audit_logs.Extensions; using audit_logs.Extensions;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Microsoft.OpenApi.Models; using Microsoft.OpenApi;
using MongoDB.Bson; using MongoDB.Bson;
using MongoDB.Driver; using MongoDB.Driver;
using Newtonsoft.Json; using Newtonsoft.Json;
@@ -120,7 +120,7 @@ builder.Services.AddSwaggerGen(c =>
c.MapType<ObjectId>(() => new OpenApiSchema c.MapType<ObjectId>(() => new OpenApiSchema
{ {
Type = "string", Type = JsonSchemaType.String,
Format = "objectid" Format = "objectid"
}); });
}); });
+16 -9
View File
@@ -24,11 +24,17 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="AuditLogs" Version="1.0.59" /> <PackageReference Include="AuditLogs" Version="1.0.59" />
<PackageReference Include="EasyNetQ" Version="8.1.4" /> <PackageReference Include="EasyNetQ" Version="8.1.5" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.8" /> <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.28" />
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="5.3.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Scripting" Version="5.3.0" /> <PackageReference Include="Microsoft.CodeAnalysis.CSharp.Scripting" Version="5.3.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.27" /> <PackageReference Include="Microsoft.EntityFrameworkCore" Version="8.0.28" />
<PackageReference Include="Microsoft.IdentityModel.Protocols" Version="8.18.0" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Analyzers" Version="10.0.9" />
<PackageReference Include="Microsoft.IdentityModel.Protocols" Version="8.19.1" />
<PackageReference Include="Microsoft.OpenApi" Version="3.7.0" />
<PackageReference Include="MongoDB.Driver" Version="3.9.0" /> <PackageReference Include="MongoDB.Driver" Version="3.9.0" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" /> <PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
<PackageReference Include="prometheus-net.AspNetCore" Version="8.2.1" /> <PackageReference Include="prometheus-net.AspNetCore" Version="8.2.1" />
@@ -43,17 +49,18 @@
<PackageReference Include="Serilog.Sinks.Console" Version="6.1.1" /> <PackageReference Include="Serilog.Sinks.Console" Version="6.1.1" />
<PackageReference Include="Serilog.Sinks.File" Version="7.0.0" /> <PackageReference Include="Serilog.Sinks.File" Version="7.0.0" />
<PackageReference Include="System.Diagnostics.PerformanceCounter" Version="10.0.8" /> <PackageReference Include="System.Diagnostics.PerformanceCounter" Version="10.0.9" />
<PackageReference Include="System.Management" Version="10.0.8" /> <PackageReference Include="System.Management" Version="10.0.9" />
<PackageReference Include="System.Net.Http" Version="4.3.4" /> <PackageReference Include="System.Net.Http" Version="4.3.4" />
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="6.1.2" />
<PackageReference Include="System.Text.RegularExpressions" Version="4.3.1" /> <PackageReference Include="System.Text.RegularExpressions" Version="4.3.1" />
<PackageReference Include="WebPush" Version="1.0.13" /> <PackageReference Include="WebPush" Version="1.0.13" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" /> <PackageReference Include="Swashbuckle.AspNetCore" Version="10.2.1" />
<PackageReference Include="Swashbuckle.AspNetCore.Newtonsoft" Version="6.5.0" /> <PackageReference Include="Swashbuckle.AspNetCore.Newtonsoft" Version="10.2.1" />
<PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="8.0.27" /> <PackageReference Include="Microsoft.AspNetCore.Mvc.NewtonsoftJson" Version="8.0.28" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>