diff --git a/README.md b/README.md index dc1a198..0e81229 100644 --- a/README.md +++ b/README.md @@ -29,6 +29,18 @@ val mailsWithEInvoices = mailReader.listAllMessagesWithEInvoice(MailAccount( )) ``` +### Validate eInvoice + +```kotlin +val validator = EInvoiceValidator() +val invoiceFile = File("ZUGFeRD.pdf") // or XRechnung,xml, ... + +val result = validator.validate(invoiceFile) + +println("Is valid? ${result.isValid}") +println(result.report) +``` + ## Create eInvoice ```kotlin diff --git a/e-invoicing-domain/build.gradle.kts b/e-invoicing-domain/build.gradle.kts index 73ad53c..3a15f99 100644 --- a/e-invoicing-domain/build.gradle.kts +++ b/e-invoicing-domain/build.gradle.kts @@ -20,6 +20,7 @@ val logbackVersion: String by project dependencies { implementation("org.mustangproject:library:$mustangVersion") + implementation("org.mustangproject:validator:$mustangVersion") implementation("org.eclipse.angus:angus-mail:$angusMailVersion") diff --git a/e-invoicing-domain/src/main/kotlin/net/codinux/invoicing/validation/EInvoiceValidator.kt b/e-invoicing-domain/src/main/kotlin/net/codinux/invoicing/validation/EInvoiceValidator.kt new file mode 100644 index 0000000..c29cda1 --- /dev/null +++ b/e-invoicing-domain/src/main/kotlin/net/codinux/invoicing/validation/EInvoiceValidator.kt @@ -0,0 +1,20 @@ +package net.codinux.invoicing.validation + +import org.mustangproject.validator.ZUGFeRDValidator +import java.io.File + +class EInvoiceValidator { + + fun validate(fileToValidate: File, disableNotices: Boolean = false): InvoiceValidationResult { + val validator = ZUGFeRDValidator() + if (disableNotices) { + validator.disableNotices() + } + + // TODO: this is far from ideal to have to report only as string and not the single failures as objects + val report = validator.validate(fileToValidate.absolutePath) + + return InvoiceValidationResult(validator.wasCompletelyValid(), report) + } + +} \ No newline at end of file diff --git a/e-invoicing-domain/src/main/kotlin/net/codinux/invoicing/validation/InvoiceValidationResult.kt b/e-invoicing-domain/src/main/kotlin/net/codinux/invoicing/validation/InvoiceValidationResult.kt new file mode 100644 index 0000000..44061a8 --- /dev/null +++ b/e-invoicing-domain/src/main/kotlin/net/codinux/invoicing/validation/InvoiceValidationResult.kt @@ -0,0 +1,11 @@ +package net.codinux.invoicing.validation + +class InvoiceValidationResult( + val isValid: Boolean, + val report: String +) { + override fun toString() = when (isValid) { + true -> "Valid: $report" + false -> "Invalid: $report" + } +} \ No newline at end of file diff --git a/e-invoicing-domain/src/test/kotlin/net/codinux/invoicing/Demonstration.kt b/e-invoicing-domain/src/test/kotlin/net/codinux/invoicing/Demonstration.kt index 50c6225..218030c 100644 --- a/e-invoicing-domain/src/test/kotlin/net/codinux/invoicing/Demonstration.kt +++ b/e-invoicing-domain/src/test/kotlin/net/codinux/invoicing/Demonstration.kt @@ -7,6 +7,7 @@ import net.codinux.invoicing.model.Invoice import net.codinux.invoicing.model.LineItem import net.codinux.invoicing.model.Party import net.codinux.invoicing.reader.EInvoiceReader +import net.codinux.invoicing.validation.EInvoiceValidator import java.io.File import java.math.BigDecimal import java.time.LocalDate @@ -34,6 +35,17 @@ class Demonstration { )) } + fun validate() { + val validator = EInvoiceValidator() + val invoiceFile = File("ZUGFeRD.pdf") // or XRechnung,xml, ... + + val result = validator.validate(invoiceFile) + + println("Is valid? ${result.isValid}") + println(result.report) + } + + fun create() { val invoice = createInvoice() val pdfResultFile = File.createTempFile("Zugferd", ".pdf") diff --git a/e-invoicing-domain/src/test/kotlin/net/codinux/invoicing/validation/EInvoiceValidatorTest.kt b/e-invoicing-domain/src/test/kotlin/net/codinux/invoicing/validation/EInvoiceValidatorTest.kt new file mode 100644 index 0000000..618712d --- /dev/null +++ b/e-invoicing-domain/src/test/kotlin/net/codinux/invoicing/validation/EInvoiceValidatorTest.kt @@ -0,0 +1,49 @@ +package net.codinux.invoicing.validation + +import assertk.assertThat +import assertk.assertions.isFalse +import assertk.assertions.isNotEmpty +import assertk.assertions.isTrue +import java.io.File +import kotlin.test.Test + +class EInvoiceValidatorTest { + + private val underTest = EInvoiceValidator() + + + @Test + fun validateXRechnung() { + val testFile = getTestFile("XRechnung.xml") + + val result = underTest.validate(testFile) + + assertThat(result.isValid).isFalse() // TODO: add required properties to XRechnung.xml + assertThat(result.report).isNotEmpty() + } + + @Test + fun validateZugferdPdf() { + val testFile = getTestFile("ZUGFeRD.pdf") + + val result = underTest.validate(testFile) + + assertThat(result.isValid).isTrue() + assertThat(result.report).isNotEmpty() + } + + @Test + fun validateZugferdXml() { + val testFile = getTestFile("ZUGFeRD.xml") + + val result = underTest.validate(testFile) + + assertThat(result.isValid).isTrue() + assertThat(result.report).isNotEmpty() + } + + + private fun getTestFile(filename: String): File = + File(this.javaClass.classLoader.getResource("files/$filename")!!.toURI()) + +} \ No newline at end of file