diff --git a/DocumentOperator.Application/Common/DTOs/SwissQrCodeExtractionResult.cs b/DocumentOperator.Application/Common/DTOs/SwissQrCodeExtractionResult.cs
index 4db1e7a..c0f9738 100644
--- a/DocumentOperator.Application/Common/DTOs/SwissQrCodeExtractionResult.cs
+++ b/DocumentOperator.Application/Common/DTOs/SwissQrCodeExtractionResult.cs
@@ -1,116 +1,37 @@
namespace DocumentOperator.Application.Common.DTOs;
///
-/// Response containing extracted Swiss QR Code data and passed-through references.
+/// Response containing extracted Swiss QR Code in dual format.
///
-/// Reference strings passed through from the request
-/// Parsed Swiss QR Code data from the last page of the PDF
+/// Parsed Swiss QR Bill (structured format)
+/// Raw Swiss QR Code lines (original newline-separated format)
///
/// {
-/// "references": ["REF-001", "REF-002"],
-/// "qrCodeData": {
-/// "qrType": "SPC",
-/// "version": "0200",
-/// "codingType": "1",
-/// "iban": "CH4431999123000889012",
-/// "creditor": {
-/// "addressType": "S",
-/// "name": "Robert Schneider AG",
-/// "street": "Rue du Lac",
-/// "buildingNumber": "1268",
-/// "postalCode": "2501",
-/// "city": "Biel",
-/// "country": "CH"
-/// },
-/// "amount": 1949.75,
+/// "bill": {
+/// "version": "V2_0",
+/// "amount": 630.20,
/// "currency": "CHF",
+/// "account": "CH953000520280564701R",
+/// "creditor": {
+/// "type": "Structured",
+/// "name": "ALMAT AG",
+/// "town": "Tagelswangen"
+/// },
/// "referenceType": "QRR",
-/// "reference": "210000000003139471430009017"
-/// }
+/// "reference": "000000000000000000252080824"
+/// },
+/// "rawLines": [
+/// "SPC",
+/// "0200",
+/// "1",
+/// "CH953000520280564701R",
+/// "S",
+/// "ALMAT AG",
+/// "..."
+/// ]
/// }
///
public record SwissQrCodeExtractionResult(
- IReadOnlyList References,
- SwissQrCodeDataDto QrCodeData
-);
-
-///
-/// Swiss QR Code data according to Swiss QR Bill Standard 2.0.
-/// Contains all fields defined in the Swiss Payment Standards.
-///
-public record SwissQrCodeDataDto(
- /// QR type - always "SPC" for Swiss Payment Code
- string QrType,
-
- /// Version of the Swiss QR Code standard (e.g., "0200" for version 2.0)
- string Version,
-
- /// Character set code (always "1" for UTF-8)
- string CodingType,
-
- /// IBAN of the creditor (payee)
- string Iban,
-
- /// Creditor (payee) information
- AddressDataDto Creditor,
-
- /// Ultimate creditor information (optional)
- AddressDataDto? UltimateCreditor,
-
- /// Payment amount (null if not specified)
- decimal? Amount,
-
- /// Currency code (CHF or EUR)
- string Currency,
-
- /// Ultimate debtor (payer) information (optional)
- AddressDataDto? UltimateDebtor,
-
- /// Reference type: "QRR" (QR Reference), "SCOR" (Creditor Reference ISO 11649), or "NON" (No Reference)
- string ReferenceType,
-
- /// Payment reference (format depends on ReferenceType)
- string? Reference,
-
- /// Unstructured message (max 140 characters)
- string? UnstructuredMessage,
-
- /// Bill information (structured data for automated processing)
- string? BillInformation,
-
- /// Alternative procedure parameters (up to 2 entries)
- IReadOnlyList? AlternativeProcedureParameters
-);
-
-///
-/// Address data in Swiss QR Code (creditor or debtor).
-/// Can be either structured (S) or combined (K) format.
-///
-public record AddressDataDto(
- /// Address type: "S" for structured, "K" for combined
- string AddressType,
-
- /// Name of person or company
- string Name,
-
- /// Street name (structured address only)
- string? Street,
-
- /// Building number (structured address only)
- string? BuildingNumber,
-
- /// Address line 1 (combined address only)
- string? AddressLine1,
-
- /// Address line 2 (combined address only)
- string? AddressLine2,
-
- /// Postal code
- string PostalCode,
-
- /// City/town name
- string City,
-
- /// Two-letter country code (ISO 3166-1 alpha-2)
- string Country
+ SwissQrBillDto Bill,
+ IReadOnlyList RawLines
);
diff --git a/DocumentOperator.Application/Common/Interfaces/ISwissQrCodeProcessor.cs b/DocumentOperator.Application/Common/Interfaces/ISwissQrCodeProcessor.cs
index c832fe8..baa746a 100644
--- a/DocumentOperator.Application/Common/Interfaces/ISwissQrCodeProcessor.cs
+++ b/DocumentOperator.Application/Common/Interfaces/ISwissQrCodeProcessor.cs
@@ -1,4 +1,4 @@
-using DocumentOperator.Domain.ValueObjects;
+using Codecrete.SwissQRBill.Generator;
namespace DocumentOperator.Application.Common.Interfaces;
@@ -9,16 +9,21 @@ namespace DocumentOperator.Application.Common.Interfaces;
public interface ISwissQrCodeProcessor
{
///
- /// Extracts and parses Swiss QR Code from the last page of a PDF document.
+ /// Extracts and parses Swiss QR Code from a PDF document.
+ /// Returns both parsed Bill object and raw QR text lines.
///
/// PDF document as byte array
+ /// Optional: Specific page numbers to scan (1-indexed). If null, scans all pages starting with last page.
/// Cancellation token
- /// Parsed Swiss QR Code data
+ /// Tuple: (Parsed Codecrete Bill, Raw QR lines as string array)
///
- /// Thrown when no Swiss QR Code is found on the last page
+ /// Thrown when no Swiss QR Code is found in the specified pages
///
///
/// Thrown when PDF processing fails
///
- Task ExtractSwissQrCodeAsync(byte[] pdfBytes, CancellationToken cancellationToken = default);
+ Task<(Bill Bill, string[] RawLines)> ExtractSwissQrCodeAsync(
+ byte[] pdfBytes,
+ int[]? pageNumbers = null,
+ CancellationToken cancellationToken = default);
}
diff --git a/DocumentOperator.Application/DocumentOperator.Application.csproj b/DocumentOperator.Application/DocumentOperator.Application.csproj
index b86574b..d8bc74e 100644
--- a/DocumentOperator.Application/DocumentOperator.Application.csproj
+++ b/DocumentOperator.Application/DocumentOperator.Application.csproj
@@ -6,8 +6,18 @@
enable
+
+
+
+
+
+
+
+
+
+
@@ -19,11 +29,6 @@
-
-
-
-
-
diff --git a/DocumentOperator.Application/SwissQrCode/Queries/ExtractSwissQrCodeQuery.cs b/DocumentOperator.Application/SwissQrCode/Queries/ExtractSwissQrCodeQuery.cs
index c1f3447..8c093fa 100644
--- a/DocumentOperator.Application/SwissQrCode/Queries/ExtractSwissQrCodeQuery.cs
+++ b/DocumentOperator.Application/SwissQrCode/Queries/ExtractSwissQrCodeQuery.cs
@@ -19,11 +19,6 @@ public record ExtractSwissQrCodeQuery : IRequest
/// PDF as Base64 string (API clients)
///
public string? Base64Pdf { get; init; }
-
- ///
- /// Optional reference strings (passed through to response for external tracking)
- ///
- public IReadOnlyList? References { get; init; }
}
///
@@ -34,23 +29,24 @@ public class ExtractSwissQrCodeQueryHandler(ISwissQrCodeProcessor qrCodeProcesso
: IRequestHandler
{
///
- /// Extracts and parses Swiss QR Code from the last page of the PDF
+ /// Extracts and parses Swiss QR Code from the PDF (default: scans all pages starting with last)
+ /// Returns both parsed Bill DTO and raw QR text lines
///
public async Task Handle(ExtractSwissQrCodeQuery request, CancellationToken cancellationToken)
{
// Use byte[] if available, otherwise convert Base64
byte[] pdfBytes = request.PdfBytes ?? Convert.FromBase64String(request.Base64Pdf!);
- // Extract and parse Swiss QR Code from last page (can throw PdfProcessingException or QrCodeNotFoundException)
- var qrCodeData = await qrCodeProcessor.ExtractSwissQrCodeAsync(pdfBytes, cancellationToken);
+ // Extract: returns (Bill, RawLines)
+ var (bill, rawLines) = await qrCodeProcessor.ExtractSwissQrCodeAsync(pdfBytes, pageNumbers: null, cancellationToken);
- // Map domain value object to DTO using AutoMapper
- var qrCodeDto = mapper.Map(qrCodeData);
+ // Map Codecrete Bill to DTO using AutoMapper
+ var billDto = mapper.Map(bill);
- // Return references (passed through) + QR code data
+ // Return references (passed through) + Bill DTO + raw lines
return new SwissQrCodeExtractionResult(
- References: request.References ?? [],
- QrCodeData: qrCodeDto
+ Bill: billDto,
+ RawLines: rawLines
);
}
}