Compare commits
4 Commits
058fb62849
...
ddd6e01f1f
Author | SHA1 | Date |
---|---|---|
dankito | ddd6e01f1f | |
dankito | af94ff2049 | |
dankito | f6a0022b24 | |
dankito | 2cbe323e9b |
|
@ -0,0 +1,49 @@
|
||||||
|
package net.codinux.invoicing.filesystem
|
||||||
|
|
||||||
|
import net.codinux.invoicing.model.Invoice
|
||||||
|
import net.codinux.invoicing.reader.EInvoiceReader
|
||||||
|
import net.codinux.log.logger
|
||||||
|
import java.nio.file.Path
|
||||||
|
import kotlin.io.path.*
|
||||||
|
|
||||||
|
class FilesystemInvoiceReader(
|
||||||
|
private val eInvoiceReader: EInvoiceReader = EInvoiceReader()
|
||||||
|
) {
|
||||||
|
|
||||||
|
private val log by logger()
|
||||||
|
|
||||||
|
fun readAllInvoicesOfDirectory(directory: Path, recursive: Boolean = false) =
|
||||||
|
readInvoicesFromFiles(collectFiles(directory, recursive))
|
||||||
|
|
||||||
|
private fun collectFiles(directory: Path, recursive: Boolean): List<Path> = buildList {
|
||||||
|
directory.listDirectoryEntries().forEach { child ->
|
||||||
|
if (child.isRegularFile()) {
|
||||||
|
add(child)
|
||||||
|
} else if (recursive && child.isDirectory()) {
|
||||||
|
addAll(collectFiles(child, recursive))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun readInvoicesFromFiles(vararg files: Path) =
|
||||||
|
readInvoicesFromFiles(files.toList())
|
||||||
|
|
||||||
|
fun readInvoicesFromFiles(files: List<Path>): List<InvoiceOnFilesystem> =
|
||||||
|
files.mapNotNull { file -> readInvoiceFromFile(file)?.let { InvoiceOnFilesystem(file, it) } }
|
||||||
|
|
||||||
|
fun readInvoiceFromFile(file: Path): Invoice? = try {
|
||||||
|
val extension = file.extension.lowercase()
|
||||||
|
|
||||||
|
if (extension == "pdf") {
|
||||||
|
eInvoiceReader.extractFromPdf(file.inputStream())
|
||||||
|
} else if (extension == "xml") {
|
||||||
|
eInvoiceReader.readFromXml(file.inputStream())
|
||||||
|
} else {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
} catch (e: Throwable) {
|
||||||
|
log.debug(e) { "Could not extract invoices from $file" }
|
||||||
|
null
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
package net.codinux.invoicing.filesystem
|
||||||
|
|
||||||
|
import net.codinux.invoicing.model.Invoice
|
||||||
|
import java.nio.file.Path
|
||||||
|
import kotlin.io.path.name
|
||||||
|
|
||||||
|
class InvoiceOnFilesystem(
|
||||||
|
val file: Path,
|
||||||
|
val invoice: Invoice
|
||||||
|
) {
|
||||||
|
override fun toString() = "${file.name} $invoice"
|
||||||
|
}
|
|
@ -17,10 +17,6 @@ class MailReader(
|
||||||
private val eInvoiceReader: EInvoiceReader = EInvoiceReader()
|
private val eInvoiceReader: EInvoiceReader = EInvoiceReader()
|
||||||
) {
|
) {
|
||||||
|
|
||||||
private val extractionErrorMessages = mutableSetOf<String?>()
|
|
||||||
|
|
||||||
private val extractionErrors = mutableSetOf<Throwable>()
|
|
||||||
|
|
||||||
private val log by logger()
|
private val log by logger()
|
||||||
|
|
||||||
|
|
||||||
|
@ -105,23 +101,20 @@ class MailReader(
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun tryToReadEInvoice(part: BodyPart): Invoice? {
|
private fun tryToReadEInvoice(part: BodyPart): Invoice? = try {
|
||||||
val filename = part.fileName.lowercase()
|
val filename = part.fileName.lowercase()
|
||||||
val contentType = part.contentType.lowercase()
|
val contentType = part.contentType.lowercase()
|
||||||
|
|
||||||
return if (filename.endsWith(".pdf") || contentType.startsWith("application/pdf") || contentType.startsWith("application/octet-stream")) {
|
if (filename.endsWith(".pdf") || contentType.startsWith("application/pdf") || contentType.startsWith("application/octet-stream")) {
|
||||||
try {
|
eInvoiceReader.extractFromPdf(part.inputStream)
|
||||||
eInvoiceReader.extractFromPdf(part.inputStream)
|
|
||||||
} catch (e: Throwable) {
|
|
||||||
extractionErrorMessages.add(e.message)
|
|
||||||
extractionErrors.add(e)
|
|
||||||
null
|
|
||||||
}
|
|
||||||
} else if (filename.endsWith(".xml") || contentType.startsWith("application/xml") || contentType.startsWith("text/xml")) {
|
} else if (filename.endsWith(".xml") || contentType.startsWith("application/xml") || contentType.startsWith("text/xml")) {
|
||||||
eInvoiceReader.readFromXml(part.inputStream)
|
eInvoiceReader.readFromXml(part.inputStream)
|
||||||
} else {
|
} else {
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
|
} catch (e: Throwable) {
|
||||||
|
log.debug(e) { "Could not extract invoices from ${part.fileName}" }
|
||||||
|
null
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: same code as in MustangMapper
|
// TODO: same code as in MustangMapper
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
package net.codinux.invoicing.filesystem
|
||||||
|
|
||||||
|
import assertk.assertThat
|
||||||
|
import assertk.assertions.hasSize
|
||||||
|
import net.codinux.invoicing.model.Invoice
|
||||||
|
import net.codinux.invoicing.test.InvoiceAsserter
|
||||||
|
import net.codinux.invoicing.test.TestUtils
|
||||||
|
import java.nio.file.Path
|
||||||
|
import kotlin.test.Test
|
||||||
|
|
||||||
|
class FilesystemInvoiceReaderTest {
|
||||||
|
|
||||||
|
private val underTest = FilesystemInvoiceReader()
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun readAllInvoicesOfDirectory() {
|
||||||
|
val testDirectory = getTestFile("XRechnung.xml").parent
|
||||||
|
|
||||||
|
val result = underTest.readAllInvoicesOfDirectory(testDirectory)
|
||||||
|
|
||||||
|
assertThat(result).hasSize(3)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun readInvoiceFromFile() {
|
||||||
|
val xRechnung = getTestFile("XRechnung.xml")
|
||||||
|
|
||||||
|
val result = underTest.readInvoiceFromFile(xRechnung)
|
||||||
|
|
||||||
|
assertInvoice(result)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun getTestFile(filename: String): Path =
|
||||||
|
TestUtils.getTestFile(filename).toPath()
|
||||||
|
|
||||||
|
private fun assertInvoice(invoice: Invoice?) {
|
||||||
|
InvoiceAsserter.assertInvoice(invoice)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -2,7 +2,7 @@ package net.codinux.invoicing.reader
|
||||||
|
|
||||||
import net.codinux.invoicing.model.Invoice
|
import net.codinux.invoicing.model.Invoice
|
||||||
import net.codinux.invoicing.test.InvoiceAsserter
|
import net.codinux.invoicing.test.InvoiceAsserter
|
||||||
import java.io.InputStream
|
import net.codinux.invoicing.test.TestUtils
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
|
|
||||||
class EInvoiceReaderTest {
|
class EInvoiceReaderTest {
|
||||||
|
@ -32,8 +32,7 @@ class EInvoiceReaderTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun getTestFile(filename: String): InputStream =
|
private fun getTestFile(filename: String) = TestUtils.getTestFileAsStream(filename)
|
||||||
this.javaClass.classLoader.getResourceAsStream("files/$filename")!!
|
|
||||||
|
|
||||||
private fun assertInvoice(invoice: Invoice?) {
|
private fun assertInvoice(invoice: Invoice?) {
|
||||||
InvoiceAsserter.assertInvoice(invoice)
|
InvoiceAsserter.assertInvoice(invoice)
|
||||||
|
|
|
@ -0,0 +1,14 @@
|
||||||
|
package net.codinux.invoicing.test
|
||||||
|
|
||||||
|
import java.io.File
|
||||||
|
import java.io.InputStream
|
||||||
|
|
||||||
|
object TestUtils {
|
||||||
|
|
||||||
|
fun getTestFileAsStream(filename: String): InputStream =
|
||||||
|
this.javaClass.classLoader.getResourceAsStream("files/$filename")!!
|
||||||
|
|
||||||
|
fun getTestFile(filename: String): File =
|
||||||
|
File(this.javaClass.classLoader.getResource("files/$filename")!!.toURI())
|
||||||
|
|
||||||
|
}
|
|
@ -2,7 +2,7 @@ package net.codinux.invoicing.validation
|
||||||
|
|
||||||
import assertk.assertThat
|
import assertk.assertThat
|
||||||
import assertk.assertions.*
|
import assertk.assertions.*
|
||||||
import java.io.File
|
import net.codinux.invoicing.test.TestUtils
|
||||||
import kotlin.test.Test
|
import kotlin.test.Test
|
||||||
|
|
||||||
class EInvoiceValidatorTest {
|
class EInvoiceValidatorTest {
|
||||||
|
@ -54,7 +54,6 @@ class EInvoiceValidatorTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun getTestFile(filename: String): File =
|
private fun getTestFile(filename: String) = TestUtils.getTestFile(filename)
|
||||||
File(this.javaClass.classLoader.getResource("files/$filename")!!.toURI())
|
|
||||||
|
|
||||||
}
|
}
|
Loading…
Reference in New Issue