This commit implements a complete rebranding of the project: - Updated all namespaces from `DocumentOperator` to `DocumentService`. - Renamed file paths, embedded resources, and test data references. - Updated configuration keys, logging paths, and Redis instance names. - Revised documentation to reflect the new project name. - Modified project and solution files to align with the new structure. - Updated class names, DTOs, commands, queries, and handlers. - Adjusted middleware, controllers, and API endpoints. - Updated Swagger metadata and API titles to `DocumentService API`. - Refactored test namespaces, resource paths, and embedded resources. - Updated build and deployment configurations for the new name. - Replaced all references to `DocumentOperator` in comments and literals. These changes ensure consistency across the codebase and documentation.
91 lines
2.7 KiB
C#
91 lines
2.7 KiB
C#
using DocumentService.Application.Common.Interfaces;
|
|
using FluentValidation;
|
|
using MediatR;
|
|
|
|
namespace DocumentService.Application.AddAttachments;
|
|
|
|
/// <summary>
|
|
/// Command to add one or more attachments to a PDF document (supports PDF/A-3)
|
|
/// </summary>
|
|
public record AddAttachmentsCommand : IRequest<byte[]>
|
|
{
|
|
/// <summary>
|
|
/// PDF document stream. Must be positioned at the beginning (Position = 0).
|
|
/// </summary>
|
|
public required Stream PdfStream { get; init; }
|
|
|
|
/// <summary>
|
|
/// List of attachments to embed (filename, content, optional MIME type)
|
|
/// </summary>
|
|
public required IReadOnlyList<AttachmentFile> Attachments { get; init; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Represents a file to be attached to a PDF
|
|
/// </summary>
|
|
public record AttachmentFile
|
|
{
|
|
/// <summary>
|
|
/// File name (e.g., "invoice.xml", "document.pdf")
|
|
/// </summary>
|
|
public required string FileName { get; init; }
|
|
|
|
/// <summary>
|
|
/// File content as byte array
|
|
/// </summary>
|
|
public required byte[] Content { get; init; }
|
|
|
|
/// <summary>
|
|
/// MIME type (optional, e.g., "application/xml", "application/pdf")
|
|
/// If not provided, will be inferred from file extension
|
|
/// </summary>
|
|
public string? MimeType { get; init; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Handler for AddAttachmentsCommand
|
|
/// </summary>
|
|
public class AddAttachmentsCommandHandler(IPdfProcessor pdfProcessor)
|
|
: IRequestHandler<AddAttachmentsCommand, byte[]>
|
|
{
|
|
public async Task<byte[]> Handle(AddAttachmentsCommand request, CancellationToken cancellationToken)
|
|
{
|
|
// Convert to tuple list for IPdfProcessor
|
|
var attachmentTuples = request.Attachments
|
|
.Select(a => (a.FileName, a.Content, a.MimeType))
|
|
.ToList();
|
|
|
|
return await pdfProcessor.AddAttachmentsAsync(request.PdfStream, attachmentTuples);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Validator for AddAttachmentsCommand
|
|
/// </summary>
|
|
public class AddAttachmentsCommandValidator : AbstractValidator<AddAttachmentsCommand>
|
|
{
|
|
public AddAttachmentsCommandValidator()
|
|
{
|
|
RuleFor(x => x.PdfStream)
|
|
.NotNull()
|
|
.WithMessage("PDF stream is required");
|
|
|
|
RuleFor(x => x.Attachments)
|
|
.NotNull()
|
|
.NotEmpty()
|
|
.WithMessage("At least one attachment is required");
|
|
|
|
RuleForEach(x => x.Attachments).ChildRules(attachment =>
|
|
{
|
|
attachment.RuleFor(a => a.FileName)
|
|
.NotEmpty()
|
|
.WithMessage("Attachment file name is required");
|
|
|
|
attachment.RuleFor(a => a.Content)
|
|
.NotNull()
|
|
.NotEmpty()
|
|
.WithMessage("Attachment content is required");
|
|
});
|
|
}
|
|
}
|