Implemented attaching invoice XML to a PDF via API

This commit is contained in:
dankito 2024-11-21 01:52:14 +01:00
parent 5395880429
commit 2d42e58d0f
2 changed files with 47 additions and 16 deletions

View File

@ -6,37 +6,51 @@ import jakarta.ws.rs.core.Response
import net.codinux.invoicing.model.Invoice import net.codinux.invoicing.model.Invoice
import net.codinux.invoicing.service.InvoicingService import net.codinux.invoicing.service.InvoicingService
import org.eclipse.microprofile.openapi.annotations.Operation import org.eclipse.microprofile.openapi.annotations.Operation
import org.jboss.resteasy.reactive.PartType
import org.jboss.resteasy.reactive.RestForm
import org.jboss.resteasy.reactive.multipart.FileUpload
@Path("") @Path("")
@Consumes(MediaType.APPLICATION_JSON) @Consumes(MediaType.APPLICATION_JSON)
@Produces(MediaType.APPLICATION_OCTET_STREAM) @Produces(MediaType.APPLICATION_XML)
class InvoicingResource( class InvoicingResource(
private val service: InvoicingService private val service: InvoicingService
) { ) {
@Path("xrechnung") @Path("xrechnung")
@POST @POST
@Produces(MediaType.APPLICATION_XML)
@Operation(summary = "Create a XRechnung XML") @Operation(summary = "Create a XRechnung XML")
fun createXRechnung(invoice: Invoice) = fun createXRechnung(invoice: Invoice) =
service.createXRechnung(invoice) service.createXRechnung(invoice)
@Path("facturx/xml") @Path("facturx/xml")
@POST @POST
@Produces(MediaType.APPLICATION_XML)
@Operation(summary = "Create a Factur-X / ZUGFeRD XML (ZUGFeRD is a synonym for Factur-X)") @Operation(summary = "Create a Factur-X / ZUGFeRD XML (ZUGFeRD is a synonym for Factur-X)")
fun createFacturXXml(invoice: Invoice) = fun createFacturXXml(invoice: Invoice) =
service.createFacturXXml(invoice) service.createFacturXXml(invoice)
@Path("facturx/pdf") @Path("facturx/pdf")
@POST @POST
@Produces(MediaType.APPLICATION_OCTET_STREAM)
@Operation(summary = "Create a Factur-X / ZUGFeRD XML, transforms it to PDF and attaches before created XML to it") @Operation(summary = "Create a Factur-X / ZUGFeRD XML, transforms it to PDF and attaches before created XML to it")
fun createFacturXPdf(invoice: Invoice): Response { fun createFacturXPdf(invoice: Invoice): Response {
val pdfFile = service.createFacturXPdf(invoice) val pdfFile = service.createFacturXPdf(invoice)
return Response.ok(pdfFile) return createPdfFileResponse(pdfFile)
.header("Content-Disposition", "attachment;filename=\"Invoice.pdf\"") }
.build()
@Path("attach")
@POST
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Produces(MediaType.APPLICATION_OCTET_STREAM)
@Operation(summary = "Attaches the invoice data as EN 16931 XML to a PDF file, combining them to a Factur-X / ZUGFeRD hybrid PDF with XML invoice file")
fun attachInvoiceXmlToPdf(
@RestForm @PartType(MediaType.APPLICATION_JSON) invoice: Invoice,
@RestForm("pdf") pdf: FileUpload
): Response {
val pdfFile = service.attachInvoiceXmlToPdf(invoice, pdf.uploadedFile())
return createPdfFileResponse(pdfFile)
} }
@ -46,15 +60,20 @@ class InvoicingResource(
@Consumes(MediaType.APPLICATION_OCTET_STREAM) @Consumes(MediaType.APPLICATION_OCTET_STREAM)
@Produces(MediaType.APPLICATION_JSON) @Produces(MediaType.APPLICATION_JSON)
@Operation(summary = "Extract invoice data from a Factur-x / ZUGFeRD or XRechnung file") @Operation(summary = "Extract invoice data from a Factur-x / ZUGFeRD or XRechnung file")
fun extractInvoiceData(invoice: java.nio.file.Path) = fun extractInvoiceData(invoice: FileUpload) =
service.extractInvoiceData(invoice) service.extractInvoiceData(invoice.uploadedFile())
@Path("validate") @Path("validate")
@POST @POST
@Consumes(MediaType.APPLICATION_OCTET_STREAM) @Consumes(MediaType.APPLICATION_OCTET_STREAM)
@Produces(MediaType.APPLICATION_XML)
@Operation(summary = "Validate a Factur-x / ZUGFeRD or XRechnung file") @Operation(summary = "Validate a Factur-x / ZUGFeRD or XRechnung file")
fun validateInvoiceXml(invoice: java.nio.file.Path) = fun validateInvoiceXml(invoice: FileUpload) =
service.validateInvoice(invoice).reportAsXml service.validateInvoice(invoice.uploadedFile()).reportAsXml
private fun createPdfFileResponse(pdfFile: java.nio.file.Path): Response =
Response.ok(pdfFile)
.header("Content-Disposition", "attachment;filename=\"Invoice.pdf\"")
.build()
} }

View File

@ -25,12 +25,18 @@ class InvoicingService {
fun createFacturXXml(invoice: Invoice): String = fun createFacturXXml(invoice: Invoice): String =
creator.createZugferdXml(invoice) creator.createZugferdXml(invoice)
fun createFacturXPdf(invoice: Invoice): File { fun createFacturXPdf(invoice: Invoice): Path {
val resultFile = File.createTempFile("factur-x", ".pdf").also { val resultFile = createTempPdfFile()
it.deleteOnExit()
}
creator.createZugferdPdf(invoice, resultFile) creator.createZugferdPdf(invoice, resultFile.toFile())
return resultFile
}
fun attachInvoiceXmlToPdf(invoice: Invoice, pdf: Path): Path {
val resultFile = createTempPdfFile()
creator.combinePdfAndInvoiceXml(invoice, pdf.toFile(), resultFile.toFile())
return resultFile return resultFile
} }
@ -46,4 +52,10 @@ class InvoicingService {
fun validateInvoice(invoice: Path) = fun validateInvoice(invoice: Path) =
validator.validate(invoice.toFile()) validator.validate(invoice.toFile())
private fun createTempPdfFile(): Path =
File.createTempFile("factur-x", ".pdf")
.also { it.deleteOnExit() }
.toPath()
} }