diff --git a/EnvelopeGenerator.Application/ThirdPartyModules/Queries/ReadThirdPartyModuleLicenseQuery.cs b/EnvelopeGenerator.Application/ThirdPartyModules/Queries/ReadThirdPartyModuleLicenseQuery.cs new file mode 100644 index 00000000..08661654 --- /dev/null +++ b/EnvelopeGenerator.Application/ThirdPartyModules/Queries/ReadThirdPartyModuleLicenseQuery.cs @@ -0,0 +1,92 @@ +using DigitalData.Core.Abstraction.Application.Repository; +using DigitalData.Core.Exceptions; +using EnvelopeGenerator.Domain.Entities; +using MediatR; +using Microsoft.EntityFrameworkCore; + +namespace EnvelopeGenerator.Application.ThirdPartyModules.Queries; + +/// +/// Query to read the license text of a third-party module. +/// Either or must be provided, but not both. +/// +public record ReadThirdPartyModuleLicenseQuery : IRequest +{ + /// + /// The unique identifier of the third-party module (optional). + /// + public int? Id { get; init; } + + /// + /// The name of the third-party module (optional). + /// + public string? Name { get; init; } + + /// + /// Whether to filter only active modules. Defaults to true. + /// + public bool Active { get; init; } = true; +} + +/// +/// Handles and returns the license text of a third-party module. +/// +public class ReadThirdPartyModuleLicenseQueryHandler : IRequestHandler +{ + private readonly IRepository _repository; + + /// + /// Initializes a new instance of the class. + /// + /// The repository for accessing third-party modules. + public ReadThirdPartyModuleLicenseQueryHandler(IRepository repository) + { + _repository = repository; + } + + /// + /// Handles the query by filtering on Id or Name and returning the license text. + /// + /// The query parameters. + /// A cancellation token. + /// The license text of the matching third-party module. + /// + /// Thrown when neither Id nor Name is provided, or when both are provided. + /// + /// + /// Thrown when multiple modules match the given criteria, indicating a data integrity issue. + /// + /// + /// Thrown when no module matches the given criteria. + /// + public async Task Handle(ReadThirdPartyModuleLicenseQuery request, CancellationToken cancel) + { + if (request.Id is null && request.Name is null) + throw new BadRequestException("Either Id or Name must be provided."); + + if (request.Id is not null && request.Name is not null) + throw new BadRequestException("Only one of Id or Name must be provided, not both."); + + var query = _repository.Query + .Where(m => m.Active == request.Active); + + if (request.Id is int id) + query = query.Where(m => m.Id == id); + + if (request.Name is string name) + query = query.Where(m => m.Name == name); + + var modules = await query + .Take(2) + .ToListAsync(cancel); + + if (modules.Count > 1) + throw new InvalidOperationException( + $"Data integrity violation: multiple third-party modules found for the given criteria (Id={request.Id}, Name={request.Name}, Active={request.Active})."); + + return modules.SingleOrDefault() is ThirdPartyModule module + ? module.License + : throw new NotFoundException( + $"Third-party module not found for the given criteria (Id={request.Id}, Name={request.Name}, Active={request.Active})."); + } +}