From b3a07f13486719bf64d1dd3ec440e35422725fc5 Mon Sep 17 00:00:00 2001 From: TekH Date: Thu, 30 Jul 2026 16:59:54 +0200 Subject: [PATCH] Add interfaces and DTOs for PDF operations support Introduced multiple interfaces and DTOs to support a wide range of PDF-related operations, including attachment handling, conversion, validation, annotation, stamping, and metadata extraction. Key changes: - Added `DocumentServiceClientOptions` for HTTP client config. - Introduced `IPdfAttachmentClient` for attachment operations. - Added `IPdfConversionClient` for PDF/A conversion (marked obsolete). - Added `IPdfOperationsClient` for merge, annotate, and stamp ops. - Introduced `IPdfValidationClient` for PDF and PDF/A validation. - Added `ISwissQrCodeClient` for Swiss QR Code extraction. - Added `IZugferdClient` for ZUGFeRD detection and extraction. - Created request DTOs for Base64-encoded operations. - Added enums for annotation, stamp, and validation configurations. These changes provide a flexible and extensible foundation for interacting with PDF documents, supporting both multipart and Base64-encoded inputs, and ensuring type safety with enums and records. --- .../DocumentServiceClientOptions.cs | 29 +++ .../Interfaces/IPdfAttachmentClient.cs | 89 +++++++ .../Interfaces/IPdfConversionClient.cs | 49 ++++ .../Interfaces/IPdfOperationsClient.cs | 69 ++++++ .../Interfaces/IPdfValidationClient.cs | 75 ++++++ .../Interfaces/ISwissQrCodeClient.cs | 36 +++ .../Interfaces/IZugferdClient.cs | 79 +++++++ .../Models/Requests/PdfAttachmentRequests.cs | 66 ++++++ .../Models/Requests/PdfConversionRequests.cs | 31 +++ .../Models/Requests/PdfOperationRequests.cs | 221 ++++++++++++++++++ .../Models/Requests/PdfValidationRequests.cs | 27 +++ .../Models/Requests/SwissQrCodeRequests.cs | 13 ++ .../Models/Requests/ZugferdRequests.cs | 25 ++ .../Models/ValueObjects/AnnotationOrigin.cs | 17 ++ .../Models/ValueObjects/AnnotationType.cs | 32 +++ .../Models/ValueObjects/OnReconfigure.cs | 13 ++ .../ValueObjects/PredefinedStampType.cs | 32 +++ .../Models/ValueObjects/StampPlacement.cs | 17 ++ .../Models/ValueObjects/StampType.cs | 22 ++ .../Models/ValueObjects/TextMarkupStyle.cs | 22 ++ 20 files changed, 964 insertions(+) create mode 100644 DocumentService.Client/Configuration/DocumentServiceClientOptions.cs create mode 100644 DocumentService.Client/Interfaces/IPdfAttachmentClient.cs create mode 100644 DocumentService.Client/Interfaces/IPdfConversionClient.cs create mode 100644 DocumentService.Client/Interfaces/IPdfOperationsClient.cs create mode 100644 DocumentService.Client/Interfaces/IPdfValidationClient.cs create mode 100644 DocumentService.Client/Interfaces/ISwissQrCodeClient.cs create mode 100644 DocumentService.Client/Interfaces/IZugferdClient.cs create mode 100644 DocumentService.Client/Models/Requests/PdfAttachmentRequests.cs create mode 100644 DocumentService.Client/Models/Requests/PdfConversionRequests.cs create mode 100644 DocumentService.Client/Models/Requests/PdfOperationRequests.cs create mode 100644 DocumentService.Client/Models/Requests/PdfValidationRequests.cs create mode 100644 DocumentService.Client/Models/Requests/SwissQrCodeRequests.cs create mode 100644 DocumentService.Client/Models/Requests/ZugferdRequests.cs create mode 100644 DocumentService.Client/Models/ValueObjects/AnnotationOrigin.cs create mode 100644 DocumentService.Client/Models/ValueObjects/AnnotationType.cs create mode 100644 DocumentService.Client/Models/ValueObjects/OnReconfigure.cs create mode 100644 DocumentService.Client/Models/ValueObjects/PredefinedStampType.cs create mode 100644 DocumentService.Client/Models/ValueObjects/StampPlacement.cs create mode 100644 DocumentService.Client/Models/ValueObjects/StampType.cs create mode 100644 DocumentService.Client/Models/ValueObjects/TextMarkupStyle.cs diff --git a/DocumentService.Client/Configuration/DocumentServiceClientOptions.cs b/DocumentService.Client/Configuration/DocumentServiceClientOptions.cs new file mode 100644 index 0000000..cd5a529 --- /dev/null +++ b/DocumentService.Client/Configuration/DocumentServiceClientOptions.cs @@ -0,0 +1,29 @@ +namespace DocumentService.Client.Configuration; + +/// +/// Configuration options for DocumentService HTTP client. +/// +public class DocumentServiceClientOptions +{ + /// + /// Base URL of the DocumentService API. + /// + /// https://api.example.com + public string BaseUrl { get; set; } = "http://localhost:5000"; + + /// + /// HTTP request timeout duration. + /// + public TimeSpan Timeout { get; set; } = TimeSpan.FromMinutes(5); + + /// + /// Maximum number of retry attempts for failed requests. + /// + public int MaxRetries { get; set; } = 3; + + /// + /// Whether to throw exceptions on HTTP error responses (4xx, 5xx). + /// If false, returns null/default values instead. + /// + public bool ThrowOnError { get; set; } = true; +} diff --git a/DocumentService.Client/Interfaces/IPdfAttachmentClient.cs b/DocumentService.Client/Interfaces/IPdfAttachmentClient.cs new file mode 100644 index 0000000..aeecee6 --- /dev/null +++ b/DocumentService.Client/Interfaces/IPdfAttachmentClient.cs @@ -0,0 +1,89 @@ +using DocumentService.Client.Models.Requests; + +namespace DocumentService.Client.Interfaces; + +/// +/// Client for PDF attachment operations (check, extract, add). +/// +public interface IPdfAttachmentClient +{ + /// + /// Checks if PDF contains attachments (multipart). + /// + /// PDF file stream + /// Cancellation token + /// Attachment check result with metadata + Task CheckAttachmentsAsync(Stream pdfStream, CancellationToken cancellationToken = default); + + /// + /// Checks if PDF contains attachments (Base64). + /// + /// PDF file as byte array + /// Cancellation token + /// Attachment check result with metadata + Task CheckAttachmentsAsync(byte[] pdfBytes, CancellationToken cancellationToken = default); + + /// + /// Extracts all embedded attachments from a PDF (multipart). + /// The returned dictionary maps each file name to its decompressed content stream. + /// + /// PDF file stream + /// Cancellation token + /// Dictionary of file name ? content stream for each extracted attachment + Task> ExtractAttachmentsAsync(Stream pdfStream, CancellationToken cancellationToken = default); + + /// + /// Extracts all embedded attachments from a PDF (Base64). + /// The returned dictionary maps each file name to its decompressed content stream. + /// + /// PDF file as byte array + /// Cancellation token + /// Dictionary of file name ? content stream for each extracted attachment + Task> ExtractAttachmentsAsync(byte[] pdfBytes, CancellationToken cancellationToken = default); + + /// + /// Adds attachments to PDF (multipart). ?? Not implemented yet in API. + /// + /// PDF file stream + /// Attachments to add + /// Cancellation token + /// Modified PDF as stream + [Obsolete("API endpoint not implemented yet")] + Task AddAttachmentsAsync(Stream pdfStream, List attachments, CancellationToken cancellationToken = default); + + /// + /// Adds attachments to PDF (Base64). ?? Not implemented yet in API. + /// + /// PDF file as byte array + /// Attachments to add + /// Cancellation token + /// Modified PDF as stream + [Obsolete("API endpoint not implemented yet")] + Task AddAttachmentsAsync(byte[] pdfBytes, List attachments, CancellationToken cancellationToken = default); +} + +/// +/// DTO for attachment check result +/// +public record AttachmentCheckResult +{ + /// Whether the document contains any embedded file attachments. + public bool HasAttachments { get; init; } + /// Number of embedded file attachments found. + public int AttachmentCount { get; init; } + /// Metadata for each attachment found in the document. + public List Attachments { get; init; } = new(); +} + +/// +/// DTO for attachment metadata +/// +public record AttachmentMetadata +{ + /// Name of the embedded file. + public string FileName { get; init; } = string.Empty; + /// MIME type of the embedded file (e.g. "application/xml"), or null if unknown. + public string? MimeType { get; init; } + /// Size of the embedded file in bytes. + public long Size { get; init; } +} diff --git a/DocumentService.Client/Interfaces/IPdfConversionClient.cs b/DocumentService.Client/Interfaces/IPdfConversionClient.cs new file mode 100644 index 0000000..c94f482 --- /dev/null +++ b/DocumentService.Client/Interfaces/IPdfConversionClient.cs @@ -0,0 +1,49 @@ +namespace DocumentService.Client.Interfaces; + +/// +/// Client for PDF conversion operations (PDF ? PDF/A). +/// +/// +/// All methods on this interface are marked obsolete because the corresponding +/// API endpoints are not yet implemented. +/// +public interface IPdfConversionClient +{ + /// + /// Converts a standard PDF to PDF/A format (multipart). + /// + /// Source PDF stream + /// Target PDF/A level (e.g., "PDF/A-3b") + /// Cancellation token + /// PDF/A document as stream + [Obsolete("API endpoint not implemented yet")] + Task ConvertToPdfAAsync(Stream pdfStream, string pdfALevel = "PDF/A-3b", CancellationToken cancellationToken = default); + + /// + /// Converts a standard PDF to PDF/A format (Base64). + /// + /// Source PDF as byte array + /// Target PDF/A level (e.g., "PDF/A-3b") + /// Cancellation token + /// PDF/A document as stream + [Obsolete("API endpoint not implemented yet")] + Task ConvertToPdfAAsync(byte[] pdfBytes, string pdfALevel = "PDF/A-3b", CancellationToken cancellationToken = default); + + /// + /// Converts a PDF/A document to standard PDF (multipart). + /// + /// Source PDF/A stream + /// Cancellation token + /// Standard PDF as stream + [Obsolete("API endpoint not implemented yet")] + Task ConvertFromPdfAAsync(Stream pdfStream, CancellationToken cancellationToken = default); + + /// + /// Converts a PDF/A document to standard PDF (Base64). + /// + /// Source PDF/A as byte array + /// Cancellation token + /// Standard PDF as stream + [Obsolete("API endpoint not implemented yet")] + Task ConvertFromPdfAAsync(byte[] pdfBytes, CancellationToken cancellationToken = default); +} diff --git a/DocumentService.Client/Interfaces/IPdfOperationsClient.cs b/DocumentService.Client/Interfaces/IPdfOperationsClient.cs new file mode 100644 index 0000000..bdde83e --- /dev/null +++ b/DocumentService.Client/Interfaces/IPdfOperationsClient.cs @@ -0,0 +1,69 @@ +using DocumentService.Client.Models.Requests; + +namespace DocumentService.Client.Interfaces; + +/// +/// Client for PDF operations (merge, annotate, stamp). +/// +public interface IPdfOperationsClient +{ + // ==================== MERGE OPERATIONS ==================== + + /// + /// Merges multiple PDFs (multipart). + /// + /// PDF file streams to merge + /// Optional page ranges per PDF (e.g., "1-3,5") + /// Cancellation token + /// Merged PDF as stream + Task MergeAsync(IEnumerable pdfStreams, List? pageRanges = null, CancellationToken cancellationToken = default); + + /// + /// Merges multiple PDFs (Base64). + /// + /// PDF files as byte arrays + /// Optional page ranges per PDF (e.g., "1-3,5") + /// Cancellation token + /// Merged PDF as stream + Task MergeAsync(IEnumerable pdfByteArrays, List? pageRanges = null, CancellationToken cancellationToken = default); + + // ==================== ANNOTATION OPERATIONS ==================== + + /// + /// Adds annotation to PDF (multipart). + /// + /// PDF file stream + /// Annotation request with coordinates and style + /// Cancellation token + /// Annotated PDF as stream + Task AnnotateAsync(Stream pdfStream, AddAnnotationBase64Request request, CancellationToken cancellationToken = default); + + /// + /// Adds annotation to PDF (Base64). + /// + /// PDF file as byte array + /// Annotation request with coordinates and style + /// Cancellation token + /// Annotated PDF as stream + Task AnnotateAsync(byte[] pdfBytes, AddAnnotationBase64Request request, CancellationToken cancellationToken = default); + + // ==================== STAMP OPERATIONS ==================== + + /// + /// Adds stamp to PDF (multipart). + /// + /// PDF file stream + /// Stamp request with position and style + /// Cancellation token + /// Stamped PDF as stream + Task StampAsync(Stream pdfStream, AddStampBase64Request request, CancellationToken cancellationToken = default); + + /// + /// Adds stamp to PDF (Base64). + /// + /// PDF file as byte array + /// Stamp request with position and style + /// Cancellation token + /// Stamped PDF as stream + Task StampAsync(byte[] pdfBytes, AddStampBase64Request request, CancellationToken cancellationToken = default); +} diff --git a/DocumentService.Client/Interfaces/IPdfValidationClient.cs b/DocumentService.Client/Interfaces/IPdfValidationClient.cs new file mode 100644 index 0000000..fa1cd98 --- /dev/null +++ b/DocumentService.Client/Interfaces/IPdfValidationClient.cs @@ -0,0 +1,75 @@ +namespace DocumentService.Client.Interfaces; + +/// +/// Client for PDF validation operations (validate, validate PDF/A). +/// +public interface IPdfValidationClient +{ + /// + /// Validates a PDF from stream (multipart upload). + /// + /// PDF file stream + /// Cancellation token + /// Validation result with metadata + Task ValidatePdfAsync(Stream pdfStream, CancellationToken cancellationToken = default); + + /// + /// Validates a PDF from byte array (Base64 JSON). + /// + /// PDF file as byte array + /// Cancellation token + /// Validation result with metadata + Task ValidatePdfAsync(byte[] pdfBytes, CancellationToken cancellationToken = default); + + /// + /// Validates a PDF/A from stream (multipart upload). + /// + /// PDF/A file stream + /// Cancellation token + /// PDF/A validation result with conformance level and errors + Task ValidatePdfAAsync(Stream pdfStream, CancellationToken cancellationToken = default); + + /// + /// Validates a PDF/A from byte array (Base64 JSON). + /// + /// PDF/A file as byte array + /// Cancellation token + /// PDF/A validation result with conformance level and errors + Task ValidatePdfAAsync(byte[] pdfBytes, CancellationToken cancellationToken = default); +} + +/// +/// DTO for PDF validation result +/// +public record PdfValidationResult +{ + /// Total number of pages in the document. + public int PageCount { get; init; } + /// File size in bytes. + public long FileSizeBytes { get; init; } + /// PDF specification version (e.g. "1.7"). + public string PdfVersion { get; init; } = string.Empty; + /// Whether the document is password-protected. + public bool IsEncrypted { get; init; } + /// Whether the document contains embedded file attachments. + public bool HasAttachments { get; init; } + /// Number of embedded file attachments. + public int AttachmentCount { get; init; } +} + +/// +/// DTO for PDF/A validation result +/// +public record PdfAValidationResult +{ + /// Whether the document is fully PDF/A conformant. + public bool IsValid { get; init; } + /// Detected PDF/A conformance level (e.g. "PDF/A-3b"), or null if not a PDF/A document. + public string? PdfAVersion { get; init; } + /// Total number of pages in the document. + public int PageCount { get; init; } + /// List of conformance errors found during validation. + public List Errors { get; init; } = new(); + /// List of conformance warnings found during validation. + public List Warnings { get; init; } = new(); +} diff --git a/DocumentService.Client/Interfaces/ISwissQrCodeClient.cs b/DocumentService.Client/Interfaces/ISwissQrCodeClient.cs new file mode 100644 index 0000000..28bcfaf --- /dev/null +++ b/DocumentService.Client/Interfaces/ISwissQrCodeClient.cs @@ -0,0 +1,36 @@ +namespace DocumentService.Client.Interfaces; + +/// +/// Client for Swiss QR Code extraction operations. +/// +public interface ISwissQrCodeClient +{ + /// + /// Extracts Swiss QR Code from PDF (multipart). + /// + /// PDF file stream + /// If true, returns raw QR text lines instead of parsed Bill object + /// Cancellation token + /// Swiss QR Code extraction result + Task ExtractSwissQrCodeAsync(Stream pdfStream, bool raw = false, CancellationToken cancellationToken = default); + + /// + /// Extracts Swiss QR Code from PDF (Base64). + /// + /// PDF file as byte array + /// If true, returns raw QR text lines instead of parsed Bill object + /// Cancellation token + /// Swiss QR Code extraction result + Task ExtractSwissQrCodeAsync(byte[] pdfBytes, bool raw = false, CancellationToken cancellationToken = default); +} + +/// +/// DTO for Swiss QR Code extraction result +/// +public record SwissQrCodeExtractionResult +{ + /// Parsed Swiss QR bill object. null when raw=true was requested. + public object? Bill { get; init; } + /// Raw QR code text lines. Populated when raw=true was requested. + public List RawLines { get; init; } = new(); +} diff --git a/DocumentService.Client/Interfaces/IZugferdClient.cs b/DocumentService.Client/Interfaces/IZugferdClient.cs new file mode 100644 index 0000000..bbc827d --- /dev/null +++ b/DocumentService.Client/Interfaces/IZugferdClient.cs @@ -0,0 +1,79 @@ +namespace DocumentService.Client.Interfaces; + +/// +/// Client for ZUGFeRD operations (detection, extraction). +/// +public interface IZugferdClient +{ + /// + /// Checks whether a PDF contains a ZUGFeRD XML attachment (multipart). + /// + /// PDF file stream + /// Cancellation token + /// ZUGFeRD check result + Task HasZugferdAsync(Stream pdfStream, CancellationToken cancellationToken = default); + + /// + /// Checks whether a PDF contains a ZUGFeRD XML attachment (Base64). + /// + /// PDF file as byte array + /// Cancellation token + /// ZUGFeRD check result + Task HasZugferdAsync(byte[] pdfBytes, CancellationToken cancellationToken = default); + + /// + /// Extracts the ZUGFeRD XML from a PDF and returns the raw XML stream (multipart). + /// + /// PDF file stream + /// Cancellation token + /// ZUGFeRD XML content as stream + Task ExtractZugferdAsync(Stream pdfStream, CancellationToken cancellationToken = default); + + /// + /// Extracts the ZUGFeRD XML from a PDF and returns the raw XML stream (Base64). + /// + /// PDF file as byte array + /// Cancellation token + /// ZUGFeRD XML content as stream + Task ExtractZugferdAsync(byte[] pdfBytes, CancellationToken cancellationToken = default); + + /// + /// Extracts ZUGFeRD metadata and XML content as a structured result (multipart). + /// + /// PDF file stream + /// Cancellation token + /// Structured ZUGFeRD extraction result + Task ExtractZugferdAsResultAsync(Stream pdfStream, CancellationToken cancellationToken = default); + + /// + /// Extracts ZUGFeRD metadata and XML content as a structured result (Base64). + /// + /// PDF file as byte array + /// Cancellation token + /// Structured ZUGFeRD extraction result + Task ExtractZugferdAsResultAsync(byte[] pdfBytes, CancellationToken cancellationToken = default); +} + +/// DTO for ZUGFeRD detection result +public record ZugferdCheckResult +{ + /// Whether the document contains a ZUGFeRD XML attachment. + public bool HasZugferd { get; init; } + /// Detected ZUGFeRD version (e.g. "2.1"), or null if not present. + public string? Version { get; init; } + /// ZUGFeRD profile name (e.g. "EN 16931"), or null if not present. + public string? Profile { get; init; } +} + +/// DTO for ZUGFeRD extraction result +public record ZugferdExtractionResult +{ + /// File name of the extracted XML attachment (e.g. "factur-x.xml"). + public string FileName { get; init; } = string.Empty; + /// Full XML content of the ZUGFeRD attachment. + public string XmlContent { get; init; } = string.Empty; + /// ZUGFeRD version (e.g. "2.1"), or null if not detected. + public string? Version { get; init; } + /// ZUGFeRD profile name (e.g. "EN 16931"), or null if not detected. + public string? Profile { get; init; } +} diff --git a/DocumentService.Client/Models/Requests/PdfAttachmentRequests.cs b/DocumentService.Client/Models/Requests/PdfAttachmentRequests.cs new file mode 100644 index 0000000..81b46ab --- /dev/null +++ b/DocumentService.Client/Models/Requests/PdfAttachmentRequests.cs @@ -0,0 +1,66 @@ +namespace DocumentService.Client.Models.Requests; + +/// +/// Request DTO for Base64-encoded PDF attachment check +/// +public record CheckPdfAttachmentsRequest +{ + /// + /// PDF document encoded as Base64 string + /// + /// JVBERi0xLjQKJeLjz9MKMSAwIG9iago8PC9UeXBlL0NhdGFsb2c... + public required string Base64Pdf { get; init; } +} + +/// +/// Request DTO for Base64-encoded PDF attachment extraction +/// +public record ExtractPdfAttachmentsRequest +{ + /// + /// PDF document encoded as Base64 string + /// + /// JVBERi0xLjQKJeLjz9MKMSAwIG9iago8PC9UeXBlL0NhdGFsb2c... + public required string Base64Pdf { get; init; } +} + +/// +/// Request DTO for Base64-encoded PDF with attachments to add +/// +public record AddAttachmentsRequest +{ + /// + /// PDF document encoded as Base64 string + /// + /// JVBERi0xLjQKJeLjz9MKMSAwIG9iago8PC9UeXBlL0NhdGFsb2c... + public required string Base64Pdf { get; init; } + + /// + /// List of attachments to embed + /// + public required List Attachments { get; init; } +} + +/// +/// DTO for attachment file in request +/// +public record AttachmentRequestDto +{ + /// + /// File name (e.g., "invoice.xml", "document.pdf") + /// + /// factur-x.xml + public required string FileName { get; init; } + + /// + /// File content encoded as Base64 string + /// + /// PD94bWwgdmVyc2lvbj0iMS4wIj8+... + public required string Base64Content { get; init; } + + /// + /// MIME type (optional, e.g., "application/xml") + /// + /// application/xml + public string? MimeType { get; init; } +} diff --git a/DocumentService.Client/Models/Requests/PdfConversionRequests.cs b/DocumentService.Client/Models/Requests/PdfConversionRequests.cs new file mode 100644 index 0000000..825228a --- /dev/null +++ b/DocumentService.Client/Models/Requests/PdfConversionRequests.cs @@ -0,0 +1,31 @@ +namespace DocumentService.Client.Models.Requests; + +/// +/// Request DTO for converting a standard PDF to PDF/A format (Base64 JSON) +/// +public record ConvertToPdfARequest +{ + /// + /// PDF document encoded as Base64 string + /// + /// JVBERi0xLjQKJeLjz9MKMSAwIG9iago8PC9UeXBlL0NhdGFsb2c... + public required string Base64Pdf { get; init; } + + /// + /// Target PDF/A conformance level. Defaults to "PDF/A-3b". + /// + /// PDF/A-3b + public string? PdfALevel { get; init; } +} + +/// +/// Request DTO for converting a PDF/A document back to standard PDF (Base64 JSON) +/// +public record ConvertFromPdfARequest +{ + /// + /// PDF/A document encoded as Base64 string + /// + /// JVBERi0xLjQKJeLjz9MKMSAwIG9iago8PC9UeXBlL0NhdGFsb2c... + public required string Base64Pdf { get; init; } +} diff --git a/DocumentService.Client/Models/Requests/PdfOperationRequests.cs b/DocumentService.Client/Models/Requests/PdfOperationRequests.cs new file mode 100644 index 0000000..3246772 --- /dev/null +++ b/DocumentService.Client/Models/Requests/PdfOperationRequests.cs @@ -0,0 +1,221 @@ +using DocumentService.Client.Models.ValueObjects; + +namespace DocumentService.Client.Models.Requests; + +/// +/// Request DTO for Base64-encoded PDF merge operation +/// +public record MergePdfsBase64Request +{ + /// + /// Array of Base64-encoded PDF files (minimum 2 required) + /// + /// ["JVBERi0xLjQK...", "JVBERi0xLjQK..."] + public required List Base64Pdfs { get; init; } + + /// + /// Optional page ranges per PDF (null = all pages). + /// Format: "1-3,5" means pages 1, 2, 3, and 5. + /// If provided, array length must match Base64Pdfs length. + /// + /// ["1-2", "1,3,5", null] + public List? PageRanges { get; init; } +} + +/// +/// Request DTO for Base64-encoded PDF annotation +/// +public record AddAnnotationBase64Request +{ + /// + /// Base64-encoded PDF file + /// + /// "JVBERi0xLjQK..." + public required string Base64Pdf { get; init; } + + /// + /// Type of annotation to add + /// + /// TextMarkup + public required AnnotationType AnnotationType { get; init; } + + /// + /// Target page number (1-indexed) + /// + /// 1 + public required int PageNumber { get; init; } + + /// + /// Rectangle X1 coordinate (left) + /// + /// 100.0 + public required double X1 { get; init; } + + /// + /// Rectangle Y1 coordinate (top or bottom depending on Origin) + /// + /// 100.0 + public required double Y1 { get; init; } + + /// + /// Rectangle X2 coordinate (right). Optional if Width is provided. + /// + /// 200.0 + public double? X2 { get; init; } + + /// + /// Rectangle Y2 coordinate (bottom or top depending on Origin). Optional if Height is provided. + /// + /// 120.0 + public double? Y2 { get; init; } + + /// + /// Rectangle width. Alternative to X2 (X2 = X1 + Width). Optional if X2 is provided. + /// + /// 100.0 + public double? Width { get; init; } + + /// + /// Rectangle height. Alternative to Y2 (Y2 = Y1 + Height). Optional if Y2 is provided. + /// + /// 20.0 + public double? Height { get; init; } + + /// + /// Annotation content (required for FreeText and StickyNote) + /// + /// "Important text to highlight" + public string? Content { get; init; } + + /// + /// Author name (optional) + /// + /// "John Doe" + public string? Author { get; init; } + + /// + /// Hex color (6 digits, e.g., "FF0000" for red). Optional - defaults vary by annotation type. + /// + /// "FFFF00" + public string? Color { get; init; } + + /// + /// Text markup style (Highlight, Underline, or Strikeout). Required for TextMarkup annotations. + /// + /// Highlight + public TextMarkupStyle? TextMarkupStyle { get; init; } + + /// + /// Coordinate origin (BottomLeft = PDF native, TopLeft = UI-friendly). Default: BottomLeft + /// + /// BottomLeft + public AnnotationOrigin Origin { get; init; } = AnnotationOrigin.BottomLeft; +} + +/// +/// Request DTO for Base64-encoded PDF stamp operation +/// +public record AddStampBase64Request +{ + /// + /// Base64-encoded PDF file + /// + /// "JVBERi0xLjQK..." + public required string Base64Pdf { get; init; } + + /// + /// Type of stamp (Text, Image, or Predefined) + /// + /// Text + public required StampType StampType { get; init; } + + /// + /// Target page numbers (1-indexed). Null or empty = all pages. + /// + /// [1, 3, 5] + public int[]? PageNumbers { get; init; } + + /// + /// Stamp position X coordinate + /// + /// 100.0 + public required double X { get; init; } + + /// + /// Stamp position Y coordinate + /// + /// 100.0 + public required double Y { get; init; } + + /// + /// Stamp width (optional, auto-size for images if not specified) + /// + /// 200.0 + public double? Width { get; init; } + + /// + /// Stamp height (optional, auto-size for images if not specified) + /// + /// 50.0 + public double? Height { get; init; } + + /// + /// Coordinate origin (BottomLeft = PDF native, TopLeft = UI-friendly). Default: BottomLeft + /// + /// BottomLeft + public AnnotationOrigin Origin { get; init; } = AnnotationOrigin.BottomLeft; + + /// + /// Text content (required for Text stamps) + /// + /// "CONFIDENTIAL" + public string? Text { get; init; } + + /// + /// Font name (default: Arial) + /// + /// "Arial" + public string? FontName { get; init; } + + /// + /// Font size in points (default: 12) + /// + /// 24.0 + public double? FontSize { get; init; } + + /// + /// Hex color (6 digits, e.g., "FF0000" for red, default: "000000") + /// + /// "FF0000" + public string? Color { get; init; } + + /// + /// Opacity (0.0 = transparent, 1.0 = opaque, default: 0.5) + /// + /// 0.5 + public double? Opacity { get; init; } + + /// + /// Rotation angle in degrees (0-360, default: 0) + /// + /// 45.0 + public double? Rotation { get; init; } + + /// + /// Stamp placement (Foreground = on top, Background = watermark effect, default: Foreground) + /// + /// Foreground + public StampPlacement Placement { get; init; } = StampPlacement.Foreground; + + /// + /// Base64-encoded image (required for Image stamps, PNG/JPEG) + /// + /// "iVBORw0KGgoAAAANSUhEUgAA..." + public string? Base64Image { get; init; } + + /// + /// Predefined stamp type (required for Predefined stamps) + /// + /// Confidential + public PredefinedStampType? PredefinedType { get; init; } +} diff --git a/DocumentService.Client/Models/Requests/PdfValidationRequests.cs b/DocumentService.Client/Models/Requests/PdfValidationRequests.cs new file mode 100644 index 0000000..b6d4ff4 --- /dev/null +++ b/DocumentService.Client/Models/Requests/PdfValidationRequests.cs @@ -0,0 +1,27 @@ +using DocumentService.Client.Models.ValueObjects; + +namespace DocumentService.Client.Models.Requests; + +/// +/// Request DTO for Base64-encoded PDF validation +/// +public record ValidatePdfBase64Request +{ + /// + /// PDF document encoded as Base64 string + /// + /// JVBERi0xLjQKJeLjz9MKMSAwIG9iago8PC9UeXBlL0NhdGFsb2c... + public required string Base64Pdf { get; init; } +} + +/// +/// Request DTO for Base64-encoded PDF/A validation +/// +public record ValidatePdfABase64Request +{ + /// + /// PDF document encoded as Base64 string + /// + /// JVBERi0xLjQKJeLjz9MKMSAwIG9iago8PC9UeXBlL0NhdGFsb2c... + public required string Base64Pdf { get; init; } +} diff --git a/DocumentService.Client/Models/Requests/SwissQrCodeRequests.cs b/DocumentService.Client/Models/Requests/SwissQrCodeRequests.cs new file mode 100644 index 0000000..775199c --- /dev/null +++ b/DocumentService.Client/Models/Requests/SwissQrCodeRequests.cs @@ -0,0 +1,13 @@ +namespace DocumentService.Client.Models.Requests; + +/// +/// Request DTO for Base64-encoded Swiss QR Code extraction +/// +public record ExtractSwissQrCodeBase64Request +{ + /// + /// PDF document encoded as Base64 string + /// + /// JVBERi0xLjQKJeLjz9MKMSAwIG9iago8PC9UeXBlL0NhdGFsb2c... + public required string Base64Pdf { get; init; } +} diff --git a/DocumentService.Client/Models/Requests/ZugferdRequests.cs b/DocumentService.Client/Models/Requests/ZugferdRequests.cs new file mode 100644 index 0000000..a6adca4 --- /dev/null +++ b/DocumentService.Client/Models/Requests/ZugferdRequests.cs @@ -0,0 +1,25 @@ +namespace DocumentService.Client.Models.Requests; + +/// +/// Request DTO for Base64-encoded PDF ZUGFeRD check +/// +public record HasZugferdRequest +{ + /// + /// PDF document encoded as Base64 string + /// + /// JVBERi0xLjQKJeLjz9MKMSAwIG9iago8PC9UeXBlL0NhdGFsb2c... + public required string Base64Pdf { get; init; } +} + +/// +/// Request DTO for Base64-encoded PDF ZUGFeRD extraction +/// +public record ExtractZugferdRequest +{ + /// + /// PDF document encoded as Base64 string + /// + /// JVBERi0xLjQKJeLjz9MKMSAwIG9iago8PC9UeXBlL0NhdGFsb2c... + public required string Base64Pdf { get; init; } +} diff --git a/DocumentService.Client/Models/ValueObjects/AnnotationOrigin.cs b/DocumentService.Client/Models/ValueObjects/AnnotationOrigin.cs new file mode 100644 index 0000000..87643c0 --- /dev/null +++ b/DocumentService.Client/Models/ValueObjects/AnnotationOrigin.cs @@ -0,0 +1,17 @@ +namespace DocumentService.Client.Models.ValueObjects; + +/// +/// Coordinate origin point for PDF annotations. +/// +public enum AnnotationOrigin +{ + /// + /// Bottom-left corner (PDF native coordinate system, default) + /// + BottomLeft, + + /// + /// Top-left corner (common in UI frameworks) + /// + TopLeft +} diff --git a/DocumentService.Client/Models/ValueObjects/AnnotationType.cs b/DocumentService.Client/Models/ValueObjects/AnnotationType.cs new file mode 100644 index 0000000..6b5a6e3 --- /dev/null +++ b/DocumentService.Client/Models/ValueObjects/AnnotationType.cs @@ -0,0 +1,32 @@ +namespace DocumentService.Client.Models.ValueObjects; + +/// +/// Supported PDF annotation types +/// +public enum AnnotationType +{ + /// + /// Text markup annotation (highlight, underline, strikeout) + /// + TextMarkup, + + /// + /// Free text annotation (text box with visible text) + /// + FreeText, + + /// + /// Sticky note annotation (popup comment icon) + /// + StickyNote, + + /// + /// Circle shape annotation + /// + Circle, + + /// + /// Square shape annotation + /// + Square +} diff --git a/DocumentService.Client/Models/ValueObjects/OnReconfigure.cs b/DocumentService.Client/Models/ValueObjects/OnReconfigure.cs new file mode 100644 index 0000000..ec17225 --- /dev/null +++ b/DocumentService.Client/Models/ValueObjects/OnReconfigure.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace DocumentService.Client.Models.ValueObjects; + +public enum OnReconfigure +{ + ThrowException = 0, + Ignore = 1, +} diff --git a/DocumentService.Client/Models/ValueObjects/PredefinedStampType.cs b/DocumentService.Client/Models/ValueObjects/PredefinedStampType.cs new file mode 100644 index 0000000..ec43464 --- /dev/null +++ b/DocumentService.Client/Models/ValueObjects/PredefinedStampType.cs @@ -0,0 +1,32 @@ +namespace DocumentService.Client.Models.ValueObjects; + +/// +/// Predefined stamp types with standard text and styling. +/// +public enum PredefinedStampType +{ + /// + /// CONFIDENTIAL stamp (red, bold). + /// + Confidential, + + /// + /// APPROVED stamp (green, bold). + /// + Approved, + + /// + /// DRAFT stamp (gray, italic). + /// + Draft, + + /// + /// VOID stamp (red, strikethrough effect). + /// + Void, + + /// + /// FOR REVIEW stamp (orange, bold). + /// + ForReview +} diff --git a/DocumentService.Client/Models/ValueObjects/StampPlacement.cs b/DocumentService.Client/Models/ValueObjects/StampPlacement.cs new file mode 100644 index 0000000..b0b8147 --- /dev/null +++ b/DocumentService.Client/Models/ValueObjects/StampPlacement.cs @@ -0,0 +1,17 @@ +namespace DocumentService.Client.Models.ValueObjects; + +/// +/// Specifies whether the stamp should appear in the foreground or background. +/// +public enum StampPlacement +{ + /// + /// Stamp appears on top of existing page content. + /// + Foreground, + + /// + /// Stamp appears behind existing page content (watermark effect). + /// + Background +} diff --git a/DocumentService.Client/Models/ValueObjects/StampType.cs b/DocumentService.Client/Models/ValueObjects/StampType.cs new file mode 100644 index 0000000..7ccb18c --- /dev/null +++ b/DocumentService.Client/Models/ValueObjects/StampType.cs @@ -0,0 +1,22 @@ +namespace DocumentService.Client.Models.ValueObjects; + +/// +/// Specifies the type of stamp to add to a PDF document. +/// +public enum StampType +{ + /// + /// Text-based stamp with custom text, font, and color. + /// + Text, + + /// + /// Image-based stamp (PNG/JPEG overlay). + /// + Image, + + /// + /// Predefined stamp with standard text (e.g., CONFIDENTIAL, APPROVED). + /// + Predefined +} diff --git a/DocumentService.Client/Models/ValueObjects/TextMarkupStyle.cs b/DocumentService.Client/Models/ValueObjects/TextMarkupStyle.cs new file mode 100644 index 0000000..95b19f4 --- /dev/null +++ b/DocumentService.Client/Models/ValueObjects/TextMarkupStyle.cs @@ -0,0 +1,22 @@ +namespace DocumentService.Client.Models.ValueObjects; + +/// +/// Text markup annotation style (highlight, underline, strikeout) +/// +public enum TextMarkupStyle +{ + /// + /// Highlight text with background color + /// + Highlight, + + /// + /// Underline text + /// + Underline, + + /// + /// Strikeout text (strikethrough) + /// + Strikeout +}