Files
Nexus.Reader/src/.documentation/cache/summaries/NexusReader.Application__Queries__User__GetUserProfileQueryHandler.cs.json
T
2026-05-25 14:02:56 +02:00

1 line
10 KiB
JSON

{"path":"NexusReader.Application/Queries/User/GetUserProfileQueryHandler.cs","purpose":"MediatR query handler that reads user profile data from the application's EF Core DbContext, projects it into UserProfileDto and returns it wrapped in a FluentResults Result.","classification":{"role":"handler","layer":"application","confidence":0.9,"evidence":["Class implements MediatR IRequestHandler<GetUserProfileQuery, Result<UserProfileDto>>","Creates an AppDbContext via IDbContextFactory and performs read/projection queries"]},"className":"GetUserProfileQueryHandler","methods":[{"name":"GetUserProfileQueryHandler","line":13,"endLine":16,"signature":"(dbContextFactory: IDbContextFactory<AppDbContext>) -> GetUserProfileQueryHandler","purpose":"Constructor that captures the IDbContextFactory dependency.","calls":[],"actions":[{"id":"assignment_15","kind":"mapping","label":"Stores dbContextFactory","line":15,"detail":"_dbContextFactory = dbContextFactory","visibility":"detail-only","confidence":0.7}]},{"name":"Handle","line":18,"endLine":66,"signature":"(request: GetUserProfileQuery, cancellationToken: CancellationToken) -> Task<Result<UserProfileDto>>","purpose":"Loads a single user's profile from the database, maps nested DTOs (plan, last read book, roles, quiz score) and returns Result.Ok(profile) or Result.Fail when not found.","calls":[{"targetFile":"NexusReader.Data.Persistence","targetMethod":"AppDbContext.Users (DbSet)","callLine":21,"paramSummary":"LINQ: filter u.Id == request.UserId; projection into UserProfileDto"},{"targetFile":"NexusReader.Data.Persistence","targetMethod":"AppDbContext.UserRoles (DbSet)","callLine":53,"paramSummary":"Used to filter roles by ur.UserId == u.Id and join with Roles"},{"targetFile":"NexusReader.Data.Persistence","targetMethod":"AppDbContext.Roles (DbSet)","callLine":55,"paramSummary":"Joined with UserRoles to select role names"}],"actions":[{"id":"resource-acquisition_20","kind":"mapping","label":"Create DbContext","line":20,"detail":"using var dbContext = await _dbContextFactory.CreateDbContextAsync(cancellationToken)","visibility":"detail-only","confidence":0.7},{"id":"handle_await_20_0","kind":"await","label":"Waits for async work","line":20,"detail":"using var dbContext = await _dbContextFactory.CreateDbContextAsync(cancellationToken);","visibility":"secondary-visible","confidence":0.81},{"id":"db-read_21","kind":"mapping","label":"Query Users and project into UserProfileDto","line":21,"detail":"Single query with Select projection mapping many nested properties and navigation collections","visibility":"detail-only","confidence":0.7},{"id":"handle_await_21_1","kind":"await","label":"Waits for async work","line":21,"detail":"var profile = await dbContext.Users","visibility":"secondary-visible","confidence":0.81},{"id":"handle_repository-read_22_2","kind":"repository-read","label":"Reads repository or persistence state","line":22,"detail":".Where(u => u.Id == request.UserId)","visibility":"secondary-visible","confidence":0.86},{"id":"projection_23","kind":"mapping","label":"Map primitive fields and nested DTOs","line":23,"detail":"Maps Email, AITokensUsed, Plan (SubscriptionPlanDto), LastReadBook (LastReadBookDto), Roles array, AverageQuizScore","visibility":"detail-only","confidence":0.7},{"id":"handle_mapping_23_3","kind":"mapping","label":"Maps data or transforms shape","line":23,"detail":".Select(u => new UserProfileDto","visibility":"detail-only","confidence":0.74},{"id":"branch-fallback_27","kind":"mapping","label":"TenantId parse with fallback","line":27,"detail":"Parses TenantId string to Guid when length==36, otherwise Guid.Empty","conditionSummary":"u.TenantId != null && u.TenantId.Length == 36","outcomeLabels":["parsed Guid","Guid.Empty"],"visibility":"detail-only","confidence":0.7},{"id":"branch-fallback_28","kind":"mapping","label":"Subscription plan projection with fallback","line":28,"detail":"Maps SubscriptionPlan when present, otherwise returns empty DTO","conditionSummary":"u.SubscriptionPlan != null","outcomeLabels":["map plan","new SubscriptionPlanDto()"],"visibility":"detail-only","confidence":0.7},{"id":"conditional-computation_35","kind":"mapping","label":"Average quiz score calculation with guard on total questions","line":35,"detail":"Computes average percentage across quiz results that have TotalQuestions>0, otherwise 0","conditionSummary":"u.QuizResults.Any(q => q.TotalQuestions > 0)","outcomeLabels":["compute average percentage","0"],"visibility":"detail-only","confidence":0.7},{"id":"handle_repository-read_36_4","kind":"repository-read","label":"Reads repository or persistence state","line":36,"detail":"? (int)u.QuizResults.Where(q => q.TotalQuestions > 0).Average(q => (double)q.Score / q.TotalQuestions * 100)","visibility":"secondary-visible","confidence":0.86},{"id":"handle_mapping_38_5","kind":"mapping","label":"Maps data or transforms shape","line":38,"detail":"LastReadBook = u.Ebooks.OrderByDescending(e => e.LastReadDate).Select(e => new LastReadBookDto","visibility":"detail-only","confidence":0.74},{"id":"collection-selection_38","kind":"mapping","label":"Select last read book or null","line":38,"detail":"Orders Ebooks by LastReadDate descending, projects LastReadBookDto and takes FirstOrDefault","visibility":"detail-only","confidence":0.7},{"id":"handle_repository-read_52_6","kind":"repository-read","label":"Reads repository or persistence state","line":52,"detail":"}).FirstOrDefault(),","visibility":"secondary-visible","confidence":0.86},{"id":"join_53","kind":"mapping","label":"Build roles array via join","line":53,"detail":"Filters UserRoles by user id, joins with Roles to select role names and converts to array","visibility":"detail-only","confidence":0.7},{"id":"handle_repository-read_54_7","kind":"repository-read","label":"Reads repository or persistence state","line":54,"detail":".Where(ur => ur.UserId == u.Id)","visibility":"secondary-visible","confidence":0.86},{"id":"handle_branch_60_8","kind":"branch","label":"Evaluates branch condition","line":60,"detail":"if (profile == null)","conditionSummary":"profile == null","outcomeLabels":["true","false"],"visibility":"secondary-visible","confidence":0.78},{"id":"guard-clause_60","kind":"guard-clause","label":"Return failure when profile not found","line":60,"detail":"If query yields null, returns a failing FluentResults Result","conditionSummary":"profile == null","outcomeLabels":["Result.Fail(\"Profile not found.\")","continue"],"visibility":"detail-only","confidence":0.7},{"id":"handle_return_62_9","kind":"return","label":"Returns result","line":62,"detail":"return Result.Fail(\"Profile not found.\");","visibility":"detail-only","confidence":0.7},{"id":"return_65","kind":"return","label":"Return successful result","line":65,"detail":"Result.Ok(profile)","visibility":"detail-only","confidence":0.7},{"id":"handle_return_65_10","kind":"return","label":"Returns result","line":65,"detail":"return Result.Ok(profile);","visibility":"detail-only","confidence":0.7}]}],"types":[],"serviceRegistrations":[],"startupActions":[],"dependencies":["NexusReader.Data.Persistence","NexusReader.Application.DTOs.User","FluentResults","MediatR"],"patterns":["CQRS Handler","Repository/EF Core DbContext read","Projection (DTO mapping)"],"domainConcepts":["User","SubscriptionPlan","Ebook / LastReadBook","QuizResult","Role"],"keyDetails":"Single MediatR query handler that performs a single EF Core projection query to build a rich UserProfileDto with multiple fallback paths (tenant parsing, subscription plan, last read book fallback), computes an average quiz score, and materializes role names via a join.","orchestrationMethods":[{"name":"Handle","line":18,"confidence":0.98,"reason":"Coordinates 3 downstream calls with 5 architectural actions.","actionKinds":["mapping","await","repository-read","branch","guard-clause","return"],"evidencePaths":["NexusReader.Application/Queries/User/GetUserProfileQueryHandler.cs","NexusReader.Data.Persistence","NexusReader.Data.Persistence","NexusReader.Data.Persistence"]}],"typedContracts":[],"persistenceInteractions":[{"methodName":"Handle","line":22,"kind":"persistence-read","detail":".Where(u => u.Id == request.UserId)","evidencePaths":["NexusReader.Application/Queries/User/GetUserProfileQueryHandler.cs"]},{"methodName":"Handle","line":36,"kind":"persistence-read","detail":"? (int)u.QuizResults.Where(q => q.TotalQuestions > 0).Average(q => (double)q.Score / q.TotalQuestions * 100)","evidencePaths":["NexusReader.Application/Queries/User/GetUserProfileQueryHandler.cs"]},{"methodName":"Handle","line":52,"kind":"persistence-read","detail":"}).FirstOrDefault(),","evidencePaths":["NexusReader.Application/Queries/User/GetUserProfileQueryHandler.cs"]},{"methodName":"Handle","line":54,"kind":"persistence-read","detail":".Where(ur => ur.UserId == u.Id)","evidencePaths":["NexusReader.Application/Queries/User/GetUserProfileQueryHandler.cs"]}],"externalInteractions":[],"evidenceAnchors":[{"kind":"orchestration-method","label":"Handle","line":18,"summary":"Coordinates 3 downstream calls with 5 architectural actions.","confidence":0.98,"evidencePaths":["NexusReader.Application/Queries/User/GetUserProfileQueryHandler.cs","NexusReader.Data.Persistence","NexusReader.Data.Persistence","NexusReader.Data.Persistence"]},{"kind":"persistence","label":"Handle","line":22,"summary":".Where(u => u.Id == request.UserId)","confidence":0.82,"evidencePaths":["NexusReader.Application/Queries/User/GetUserProfileQueryHandler.cs"]},{"kind":"persistence","label":"Handle","line":36,"summary":"? (int)u.QuizResults.Where(q => q.TotalQuestions > 0).Average(q => (double)q.Score / q.TotalQuestions * 100)","confidence":0.82,"evidencePaths":["NexusReader.Application/Queries/User/GetUserProfileQueryHandler.cs"]},{"kind":"persistence","label":"Handle","line":52,"summary":"}).FirstOrDefault(),","confidence":0.82,"evidencePaths":["NexusReader.Application/Queries/User/GetUserProfileQueryHandler.cs"]}],"cacheMetadata":{"schemaVersion":2,"analysisVersion":"2026-05-23.cache-v1","contentChecksum":"726216fa0ee1a4b132823b3f8715d8be31f569dd684009570f517335f9e6ce0b","sourceByteSize":2895,"analyzedAt":"2026-05-23T16:18:22.824Z","technology":"dotnet"}}