using DigitalData.Core.Abstraction.Application.Repository; using EnvelopeGenerator.Application.Common.Dto; using EnvelopeGenerator.Domain.Entities; using MediatR; using Microsoft.EntityFrameworkCore; namespace EnvelopeGenerator.Application.Documents.Queries; /// /// Represents a query to read document metadata/details without binary payload. /// /// The identifier of the envelope associated with the document. /// The unique identifier of the sending user. Optional. public record ReadDocumentDetailsQuery(int EnvelopeId, int? UserId = null) : IRequest; /// /// Handles queries for reading document details without loading BYTE_DATA. /// public class ReadDocumentDetailsQueryHandler : IRequestHandler { private readonly IRepository _repo; public ReadDocumentDetailsQueryHandler(IRepository repo) { _repo = repo; } public async Task Handle(ReadDocumentDetailsQuery query, CancellationToken cancel) { var docQuery = _repo.Query.AsNoTracking(); if (query.UserId is int userId) docQuery = docQuery.Where(doc => doc.Envelope.UserId == userId); // shortcut: manual select avoids AutoMapper ProjectTo pulling BYTE_DATA and the full navigation // graph (Envelope → History → User etc.) which caused an extremely slow query (~87s). // Annotations navigation is IEnumerable on the entity (not ICollection), so EF Core // cannot translate it in a Select projection — we skip it entirely here; sender editor only // needs element coordinates, not annotation payloads. var raw = await docQuery .Where(d => d.EnvelopeId == query.EnvelopeId) .Select(d => new { d.Id, d.EnvelopeId, d.AddedWhen, Elements = d.Elements == null ? null : d.Elements.Select(e => new { e.Id, e.DocumentId, e.ReceiverId, e.ElementType, e.X, e.Y, e.Width, e.Height, e.Page, e.Required, e.Tooltip, e.ReadOnly, e.AnnotationIndex, e.AddedWhen, e.ChangedWhen, e.FullName, e.Position, e.Place, }).ToList() }) .FirstOrDefaultAsync(cancel); if (raw is null) return null; return new DocumentDetailsDto { Id = raw.Id, EnvelopeId = raw.EnvelopeId, AddedWhen = raw.AddedWhen, Elements = raw.Elements?.Select(e => new DocReceiverElementDto { Id = e.Id, DocumentId = e.DocumentId, ReceiverId = e.ReceiverId, ElementType = e.ElementType, X = e.X, Y = e.Y, Width = e.Width, Height = e.Height, Page = e.Page, Required = e.Required, Tooltip = e.Tooltip, ReadOnly = e.ReadOnly, AnnotationIndex = e.AnnotationIndex, AddedWhen = e.AddedWhen, ChangedWhen = e.ChangedWhen, FullName = e.FullName, Position = e.Position, Place = e.Place, }) }; } }