Implemented extracting cash transfer data from PDF files and setting them as preselected values in TransferMoneyDialog
This commit is contained in:
parent
80680a16b6
commit
996204f54f
|
@ -27,6 +27,11 @@ ext {
|
|||
luceneUtilsVersion = "0.5.1-SNAPSHOT"
|
||||
|
||||
|
||||
textExtractorVersion = "0.5.1-SNAPSHOT"
|
||||
|
||||
textInfoExtractorVersion = "1.0.1-SNAPSHOT"
|
||||
|
||||
|
||||
hbci4jVersion = '3.1.37'
|
||||
|
||||
|
||||
|
@ -41,6 +46,8 @@ ext {
|
|||
androidTargetSdkVersion = 28
|
||||
|
||||
|
||||
fileChooserDialogVersion = "1.2.0-androidx"
|
||||
|
||||
androidUtilsVersion = '1.1.1-SNAPSHOT'
|
||||
|
||||
materialDrawerVersion = "8.0.1"
|
||||
|
|
|
@ -1,3 +1,7 @@
|
|||
android.enableJetifier=true
|
||||
android.useAndroidX=true
|
||||
kotlin.code.style=official
|
||||
kotlin.code.style=official
|
||||
|
||||
# Specifies the JVM arguments used for the daemon process.
|
||||
# The setting is particularly useful for tweaking memory settings.
|
||||
org.gradle.jvmargs=-Xmx3072m
|
|
@ -83,6 +83,10 @@ dependencies {
|
|||
implementation project(':BankingPersistenceJson')
|
||||
implementation project(':LuceneBankingPersistence')
|
||||
|
||||
|
||||
implementation "net.dankito.text.extraction:itext2-text-extractor:$textExtractorVersion"
|
||||
implementation "net.dankito.text.extraction:pdfbox-android-text-extractor:$textExtractorVersion"
|
||||
|
||||
implementation "com.github.clans:fab:$clansFloatingActionButtonVersion"
|
||||
|
||||
implementation "com.otaliastudios:autocomplete:$autocompleteVersion"
|
||||
|
@ -90,6 +94,14 @@ dependencies {
|
|||
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion"
|
||||
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlinCoroutinesVersion"
|
||||
|
||||
implementation "net.dankito.filechooserdialog:filechooserdialog-android:$fileChooserDialogVersion", {
|
||||
exclude group: 'org.jetbrains.kotlin', module: 'kotlin-stdlib'
|
||||
exclude group: 'com.android.support', module: 'appcompat-v7'
|
||||
exclude group: 'com.android.support', module: 'design'
|
||||
exclude group: 'com.android.support.constraint', module: 'constraint-layout'
|
||||
exclude module: 'recyclerview-v7'
|
||||
}
|
||||
|
||||
implementation "net.dankito.utils:android-utils:$androidUtilsVersion", {
|
||||
exclude group: 'org.jetbrains.kotlin', module: 'kotlin-stdlib-jdk7'
|
||||
exclude group: 'com.android.support', module: 'appcompat-v7'
|
||||
|
|
|
@ -14,6 +14,8 @@ import net.dankito.banking.ui.android.activities.BaseActivity
|
|||
import net.dankito.banking.ui.android.views.DrawerView
|
||||
import net.dankito.banking.ui.android.views.MainActivityFloatingActionMenuButton
|
||||
import net.dankito.banking.ui.presenter.BankingPresenter
|
||||
import net.dankito.utils.android.permissions.IPermissionsService
|
||||
import net.dankito.utils.android.permissions.PermissionsService
|
||||
import javax.inject.Inject
|
||||
|
||||
|
||||
|
@ -27,6 +29,8 @@ class MainActivity : BaseActivity() {
|
|||
|
||||
private lateinit var floatingActionMenuButton: MainActivityFloatingActionMenuButton
|
||||
|
||||
private val permissionsService: IPermissionsService = PermissionsService(this)
|
||||
|
||||
|
||||
@Inject
|
||||
protected lateinit var presenter: BankingPresenter
|
||||
|
@ -73,7 +77,7 @@ class MainActivity : BaseActivity() {
|
|||
}
|
||||
|
||||
val floatingActionMenu = findViewById<FloatingActionMenu>(R.id.floatingActionMenu)
|
||||
floatingActionMenuButton = MainActivityFloatingActionMenuButton(floatingActionMenu, presenter)
|
||||
floatingActionMenuButton = MainActivityFloatingActionMenuButton(floatingActionMenu, permissionsService, presenter)
|
||||
}
|
||||
|
||||
override fun onCreateOptionsMenu(menu: Menu): Boolean {
|
||||
|
|
|
@ -19,6 +19,12 @@ import net.dankito.banking.util.BankIconFinder
|
|||
import net.dankito.banking.util.IBankIconFinder
|
||||
import net.dankito.banking.bankfinder.IBankFinder
|
||||
import net.dankito.banking.bankfinder.LuceneBankFinder
|
||||
import net.dankito.text.extraction.ITextExtractorRegistry
|
||||
import net.dankito.text.extraction.TextExtractorRegistry
|
||||
import net.dankito.text.extraction.info.invoice.IInvoiceDataExtractor
|
||||
import net.dankito.text.extraction.info.invoice.InvoiceDataExtractor
|
||||
import net.dankito.text.extraction.pdf.PdfBoxAndroidPdfTextExtractor
|
||||
import net.dankito.text.extraction.pdf.iText2PdfTextExtractor
|
||||
import net.dankito.utils.IThreadPool
|
||||
import net.dankito.utils.ThreadPool
|
||||
import net.dankito.utils.serialization.ISerializer
|
||||
|
@ -78,10 +84,11 @@ class BankingModule(private val applicationContext: Context) {
|
|||
@Singleton
|
||||
fun provideBankingPresenter(bankingClientCreator: IBankingClientCreator, bankFinder: IBankFinder,
|
||||
@Named(DatabaseFolderKey) databaseFolder: File, @Named(DataFolderKey) dataFolder: File,
|
||||
persister: IBankingPersistence, bankIconFinder: IBankIconFinder, remitteeSearcher: IRemitteeSearcher,
|
||||
router: IRouter, serializer: ISerializer, threadPool: IThreadPool) : BankingPresenter {
|
||||
persister: IBankingPersistence, remitteeSearcher: IRemitteeSearcher, bankIconFinder: IBankIconFinder,
|
||||
textExtractorRegistry: ITextExtractorRegistry, router: IRouter, invoiceDataExtractor: IInvoiceDataExtractor,
|
||||
serializer: ISerializer, threadPool: IThreadPool) : BankingPresenter {
|
||||
return BankingPresenter(bankingClientCreator, bankFinder, databaseFolder, dataFolder, persister,
|
||||
remitteeSearcher, bankIconFinder, router, serializer, threadPool)
|
||||
remitteeSearcher, bankIconFinder, textExtractorRegistry, router, invoiceDataExtractor, serializer, threadPool)
|
||||
}
|
||||
|
||||
@Provides
|
||||
|
@ -127,6 +134,22 @@ class BankingModule(private val applicationContext: Context) {
|
|||
}
|
||||
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideTextExtractorRegistry(applicationContext: Context) : ITextExtractorRegistry {
|
||||
// TODO: add PdfTypeDetector
|
||||
return TextExtractorRegistry(listOf(
|
||||
iText2PdfTextExtractor(), PdfBoxAndroidPdfTextExtractor(applicationContext)
|
||||
))
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideInvoiceDataExtractor() : IInvoiceDataExtractor {
|
||||
return InvoiceDataExtractor()
|
||||
}
|
||||
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
fun provideWebClient() : IWebClient {
|
||||
|
|
|
@ -1,18 +1,36 @@
|
|||
package net.dankito.banking.ui.android.views
|
||||
|
||||
import android.content.Context
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.fragment.app.FragmentActivity
|
||||
import com.github.clans.fab.FloatingActionButton
|
||||
import com.github.clans.fab.FloatingActionMenu
|
||||
import kotlinx.android.synthetic.main.view_floating_action_button_main.view.*
|
||||
import net.dankito.banking.ui.android.R
|
||||
import net.dankito.banking.ui.model.moneytransfer.ExtractTransferMoneyDataFromPdfResult
|
||||
import net.dankito.banking.ui.model.moneytransfer.ExtractTransferMoneyDataFromPdfResultType
|
||||
import net.dankito.banking.ui.presenter.BankingPresenter
|
||||
import net.dankito.filechooserdialog.FileChooserDialog
|
||||
import net.dankito.filechooserdialog.model.FileChooserDialogConfig
|
||||
import net.dankito.utils.android.extensions.asActivity
|
||||
import net.dankito.utils.android.permissions.IPermissionsService
|
||||
import java.io.File
|
||||
|
||||
|
||||
open class MainActivityFloatingActionMenuButton(floatingActionMenu: FloatingActionMenu, protected val presenter: BankingPresenter)
|
||||
: FloatingActionMenuButton(floatingActionMenu) {
|
||||
open class MainActivityFloatingActionMenuButton(
|
||||
floatingActionMenu: FloatingActionMenu,
|
||||
protected val permissionsService: IPermissionsService,
|
||||
protected val presenter: BankingPresenter
|
||||
) : FloatingActionMenuButton(floatingActionMenu) {
|
||||
|
||||
protected lateinit var fabTransferMoney: FloatingActionButton
|
||||
|
||||
protected lateinit var fabTransferMoneyFromPdf: FloatingActionButton
|
||||
|
||||
protected var lastSelectedFolder: File? = null
|
||||
|
||||
|
||||
init {
|
||||
setupButtons(floatingActionMenu)
|
||||
|
||||
|
@ -32,16 +50,59 @@ open class MainActivityFloatingActionMenuButton(floatingActionMenu: FloatingActi
|
|||
}
|
||||
|
||||
fabTransferMoney = floatingActionMenu.fabTransferMoney
|
||||
fabTransferMoneyFromPdf = floatingActionMenu.fabTransferMoneyFromPdf
|
||||
|
||||
fabTransferMoney.setOnClickListener {
|
||||
executeAndCloseMenu { presenter.showTransferMoneyDialog() }
|
||||
}
|
||||
|
||||
fabTransferMoneyFromPdf.setOnClickListener {
|
||||
executeAndCloseMenu { transferMoneyWithDataFromPdf() }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected open fun checkIfThereAreAccountsThatCanTransferMoney() {
|
||||
fabTransferMoney.isEnabled = presenter.hasBankAccountsSupportTransferringMoney
|
||||
|
||||
fabTransferMoneyFromPdf.isEnabled = presenter.hasBankAccountsSupportTransferringMoney
|
||||
}
|
||||
|
||||
|
||||
protected open fun transferMoneyWithDataFromPdf() {
|
||||
(floatingActionMenu.context.asActivity() as? FragmentActivity)?.let { activity ->
|
||||
val config = FileChooserDialogConfig(listOf("*.pdf"), lastSelectedFolder)
|
||||
|
||||
FileChooserDialog().showOpenSingleFileDialog(activity, permissionsService, config) { _, selectedFile ->
|
||||
selectedFile?.let {
|
||||
lastSelectedFolder = selectedFile.parentFile
|
||||
|
||||
val result = presenter.transferMoneyWithDataFromPdf(selectedFile)
|
||||
|
||||
if (result.type != ExtractTransferMoneyDataFromPdfResultType.Success) {
|
||||
showTransferMoneyWithDataFromPdfError(activity, selectedFile, result)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected open fun showTransferMoneyWithDataFromPdfError(context: Context, pdfFile: File, result: ExtractTransferMoneyDataFromPdfResult) {
|
||||
val errorMessage = when (result.type) {
|
||||
ExtractTransferMoneyDataFromPdfResultType.NotASearchablePdf ->
|
||||
context.getString(R.string.transfer_money_from_pdf_error_message_not_a_searchable_pdf, pdfFile.absolutePath)
|
||||
ExtractTransferMoneyDataFromPdfResultType.CouldNotExtractText ->
|
||||
context.getString(R.string.transfer_money_from_pdf_error_message_could_not_extract_text, pdfFile.absolutePath, result.error)
|
||||
ExtractTransferMoneyDataFromPdfResultType.CouldNotExtractInvoiceDataFromExtractedText ->
|
||||
context.getString(R.string.transfer_money_from_pdf_error_message_could_not_extract_invoice_data, pdfFile.absolutePath, result.error)
|
||||
ExtractTransferMoneyDataFromPdfResultType.Success -> "" // will never come to this
|
||||
}
|
||||
|
||||
AlertDialog.Builder(context)
|
||||
.setMessage(errorMessage)
|
||||
.setPositiveButton(android.R.string.ok) { dialog, _ -> dialog.dismiss() }
|
||||
.show()
|
||||
}
|
||||
|
||||
}
|
|
@ -17,6 +17,14 @@
|
|||
fab:menu_animationDelayPerItem="50">
|
||||
|
||||
|
||||
<com.github.clans.fab.FloatingActionButton
|
||||
android:id="@+id/fabTransferMoneyFromPdf"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
style="@style/MenuButtonsStyle"
|
||||
fab:fab_label="@string/floating_action_menu_transfer_money_from_pdf"
|
||||
/>
|
||||
|
||||
<com.github.clans.fab.FloatingActionButton
|
||||
android:id="@+id/fabTransferMoney"
|
||||
android:layout_width="wrap_content"
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
<string name="floating_action_menu_add_account">Konto</string>
|
||||
<string name="floating_action_menu_transfer_money">Überweisung</string>
|
||||
<string name="floating_action_menu_transfer_money_from_pdf">Überweisung aus PDF</string>
|
||||
|
||||
<string name="menu_home">Umsätze</string>
|
||||
|
||||
|
@ -60,6 +61,10 @@
|
|||
<string name="dialog_transfer_money_message_transfer_successful">%1$s %2$s wurden erfolgreich an %3$s überwiesen.</string>
|
||||
<string name="dialog_transfer_money_message_transfer_failed">Konnte nicht %1$s %2$s an %3$s überweisen.\n\nFehlermeldung Ihrer Bank:\n\n%4$s</string>
|
||||
|
||||
<string name="transfer_money_from_pdf_error_message_not_a_searchable_pdf">Konnte Text nicht aus Datei "%1$s" extrahieren. Enthält sie auch Text oder nur Bilder?</string>
|
||||
<string name="transfer_money_from_pdf_error_message_could_not_extract_text">Text konnte nicht aus Datei "%1$s" extrahiert werden:\n\n%2$s</string>
|
||||
<string name="transfer_money_from_pdf_error_message_could_not_extract_invoice_data">Überweisungsdaten konnten aus der Datei "%1$s" nicht ausgelesen werden:\n\n%2$s</string>
|
||||
|
||||
<string name="view_tan_image_size_controls_size">Größe:</string>
|
||||
<string name="view_tan_image_size_controls_decrease_size">-</string>
|
||||
<string name="view_tan_image_size_controls_increase_size">+</string>
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
|
||||
<string name="floating_action_menu_add_account">Account</string>
|
||||
<string name="floating_action_menu_transfer_money">Transfer money</string>
|
||||
<string name="floating_action_menu_transfer_money_from_pdf">Transfer money from PDF</string>
|
||||
|
||||
<string name="menu_home">Home</string>
|
||||
|
||||
|
@ -60,6 +61,10 @@
|
|||
<string name="dialog_transfer_money_message_transfer_successful">Successfully transferred %1$s %2$s to %3$s.</string>
|
||||
<string name="dialog_transfer_money_message_transfer_failed">Could not transfer %1$s %2$s to %3$s.\n\nError message from your bank:\n\n%4$s</string>
|
||||
|
||||
<string name="transfer_money_from_pdf_error_message_not_a_searchable_pdf">File "%1$s" is not a searchable PDF. Could therefore not extract text from it.</string>
|
||||
<string name="transfer_money_from_pdf_error_message_could_not_extract_text">Could not extract text from file "%1$s":\n\n%2$s</string>
|
||||
<string name="transfer_money_from_pdf_error_message_could_not_extract_invoice_data">Could not extract cash transfer data from file "%1$s":\n\n%2$s</string>
|
||||
|
||||
<string name="view_tan_image_size_controls_size">Size:</string>
|
||||
<string name="view_tan_image_size_controls_decrease_size">-</string>
|
||||
<string name="view_tan_image_size_controls_increase_size">+</string>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<resources>
|
||||
|
||||
<!-- Base application theme. -->
|
||||
<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar">
|
||||
<style name="AppTheme" parent="FileChooserDialogAppThemeLight">
|
||||
<!-- Customize your theme here. -->
|
||||
<item name="colorPrimary">@color/colorPrimary</item>
|
||||
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
|
||||
|
|
|
@ -24,8 +24,18 @@ dependencies {
|
|||
implementation project(':fints4kBankingClient')
|
||||
implementation project(':hbci4jBankingClient')
|
||||
|
||||
implementation project(':fints4k')
|
||||
implementation project(':fints4k-jvm')
|
||||
|
||||
implementation project(':LuceneBankingPersistence')
|
||||
|
||||
|
||||
implementation "net.dankito.text.extraction:poppler-text-extractor:$textExtractorVersion"
|
||||
implementation "net.dankito.text.extraction:pdfbox-text-extractor:$textExtractorVersion"
|
||||
implementation "net.dankito.text.extraction:itext2-text-extractor:$textExtractorVersion"
|
||||
implementation "net.dankito.text.extraction:tesseract4-commandline-text-extractor:$textExtractorVersion"
|
||||
implementation "net.dankito.text.extraction:tika-text-extractor:$textExtractorVersion"
|
||||
|
||||
implementation "ch.qos.logback:logback-classic:$logbackVersion"
|
||||
}
|
||||
|
||||
|
|
|
@ -12,6 +12,12 @@ import net.dankito.banking.util.BankIconFinder
|
|||
import net.dankito.banking.bankfinder.LuceneBankFinder
|
||||
import net.dankito.banking.persistence.LuceneBankingPersistence
|
||||
import net.dankito.banking.search.LuceneRemitteeSearcher
|
||||
import net.dankito.text.extraction.TextExtractorRegistry
|
||||
import net.dankito.text.extraction.TikaTextExtractor
|
||||
import net.dankito.text.extraction.image.Tesseract4CommandlineImageTextExtractor
|
||||
import net.dankito.text.extraction.image.model.OcrLanguage
|
||||
import net.dankito.text.extraction.image.model.TesseractConfig
|
||||
import net.dankito.text.extraction.pdf.*
|
||||
import net.dankito.utils.web.client.OkHttpWebClient
|
||||
import tornadofx.*
|
||||
import tornadofx.FX.Companion.messages
|
||||
|
@ -26,11 +32,20 @@ class MainWindow : View(messages["application.title"]) {
|
|||
|
||||
private val indexFolder = File(dataFolder, "index")
|
||||
|
||||
private val tesseractTextExtractor = Tesseract4CommandlineImageTextExtractor(TesseractConfig(listOf(OcrLanguage.English, OcrLanguage.German)))
|
||||
|
||||
private val textExtractorRegistry = TextExtractorRegistry(pdffontsPdfTypeDetector(), listOf(
|
||||
pdfToTextPdfTextExtractor(), PdfBoxPdfTextExtractor(), iText2PdfTextExtractor(),
|
||||
ImageOnlyPdfTextExtractor(tesseractTextExtractor, pdfimagesImagesFromPdfExtractor()),
|
||||
tesseractTextExtractor, TikaTextExtractor()
|
||||
))
|
||||
|
||||
private val presenter = BankingPresenter(fints4kBankingClientCreator(OkHttpWebClient(), Base64ServiceJava8()),
|
||||
LuceneBankFinder(indexFolder), databaseFolder, dataFolder, LuceneBankingPersistence(indexFolder, databaseFolder),
|
||||
LuceneRemitteeSearcher(indexFolder), BankIconFinder(), RouterJavaFx())
|
||||
LuceneRemitteeSearcher(indexFolder), BankIconFinder(), textExtractorRegistry, RouterJavaFx())
|
||||
// private val presenter = BankingPresenter(hbci4jBankingClientCreator(), LuceneBankFinder(indexFolder), databaseFolder,
|
||||
// dataFolder, LuceneBankingPersistence(indexFolder, databaseFolder), LuceneRemitteeSearcher(indexFolder), BankIconFinder(), RouterJavaFx())
|
||||
// dataFolder, LuceneBankingPersistence(indexFolder, databaseFolder), LuceneRemitteeSearcher(indexFolder),
|
||||
// BankIconFinder(), textExtractorRegistry, RouterJavaFx())
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -4,15 +4,22 @@ import javafx.beans.property.SimpleBooleanProperty
|
|||
import javafx.scene.input.KeyCode
|
||||
import javafx.scene.input.KeyCodeCombination
|
||||
import javafx.scene.input.KeyCombination
|
||||
import javafx.stage.FileChooser
|
||||
import net.dankito.banking.ui.model.moneytransfer.ExtractTransferMoneyDataFromPdfResult
|
||||
import net.dankito.banking.ui.model.moneytransfer.ExtractTransferMoneyDataFromPdfResultType
|
||||
import net.dankito.banking.ui.presenter.BankingPresenter
|
||||
import net.dankito.utils.javafx.ui.dialogs.JavaFXDialogService
|
||||
import net.dankito.utils.javafx.ui.extensions.fixedHeight
|
||||
import tornadofx.*
|
||||
import java.io.File
|
||||
|
||||
|
||||
open class MainMenuBar(protected val presenter: BankingPresenter) : View() {
|
||||
|
||||
protected val areAccountsThatCanTransferMoneyAdded = SimpleBooleanProperty()
|
||||
|
||||
protected var lastSelectedFolder: File? = null
|
||||
|
||||
|
||||
init {
|
||||
presenter.addAccountsChangedListener {
|
||||
|
@ -35,11 +42,19 @@ open class MainMenuBar(protected val presenter: BankingPresenter) : View() {
|
|||
action { presenter.showAddAccountDialog() }
|
||||
}
|
||||
|
||||
separator()
|
||||
|
||||
item(messages["main.window.menu.file.new.cash.transfer"], KeyCodeCombination(KeyCode.W, KeyCombination.SHORTCUT_DOWN)) {
|
||||
enableWhen(areAccountsThatCanTransferMoneyAdded)
|
||||
|
||||
action { presenter.showTransferMoneyDialog() }
|
||||
}
|
||||
|
||||
item(messages["main.window.menu.file.new.cash.transfer.from.pdf"], KeyCodeCombination(KeyCode.W, KeyCombination.SHORTCUT_DOWN, KeyCodeCombination.SHIFT_DOWN)) {
|
||||
enableWhen(areAccountsThatCanTransferMoneyAdded)
|
||||
|
||||
action { transferMoneyWithDataFromPdf() }
|
||||
}
|
||||
}
|
||||
|
||||
separator()
|
||||
|
@ -55,4 +70,34 @@ open class MainMenuBar(protected val presenter: BankingPresenter) : View() {
|
|||
areAccountsThatCanTransferMoneyAdded.value = presenter.hasBankAccountsSupportTransferringMoney
|
||||
}
|
||||
|
||||
protected open fun transferMoneyWithDataFromPdf() {
|
||||
val fileChooser = FileChooser()
|
||||
|
||||
fileChooser.initialDirectory = lastSelectedFolder
|
||||
fileChooser.extensionFilters.add(FileChooser.ExtensionFilter("PDFs (*.pdf)", "*.pdf"))
|
||||
|
||||
fileChooser.showOpenDialog(currentStage)?.let { pdfFile ->
|
||||
lastSelectedFolder = pdfFile.parentFile
|
||||
|
||||
val result = presenter.transferMoneyWithDataFromPdf(pdfFile)
|
||||
|
||||
if (result.type != ExtractTransferMoneyDataFromPdfResultType.Success) {
|
||||
showTransferMoneyWithDataFromPdfError(pdfFile, result)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected open fun showTransferMoneyWithDataFromPdfError(pdfFile: File, result: ExtractTransferMoneyDataFromPdfResult) {
|
||||
val errorMessageKey = when (result.type) {
|
||||
ExtractTransferMoneyDataFromPdfResultType.NotASearchablePdf -> "transfer.money.from.pdf.error.message.not.a.searchable.pdf"
|
||||
ExtractTransferMoneyDataFromPdfResultType.CouldNotExtractText -> "transfer.money.from.pdf.error.message.could.not.extract.text"
|
||||
ExtractTransferMoneyDataFromPdfResultType.CouldNotExtractInvoiceDataFromExtractedText -> "transfer.money.from.pdf.error.message.could.not.extract.invoice.data"
|
||||
ExtractTransferMoneyDataFromPdfResultType.Success -> "" // will never come to this
|
||||
}
|
||||
|
||||
val errorMessage = String.format(messages[errorMessageKey], pdfFile.absolutePath)
|
||||
|
||||
JavaFXDialogService().showErrorMessage(errorMessage, exception = result.error)
|
||||
}
|
||||
|
||||
}
|
|
@ -13,6 +13,7 @@ main.window.menu.file=File
|
|||
main.window.menu.file.new=New...
|
||||
main.window.menu.file.new.account=Account
|
||||
main.window.menu.file.new.cash.transfer=Cash transfer
|
||||
main.window.menu.file.new.cash.transfer.from.pdf=Cash transfer from PDF
|
||||
main.window.menu.file.quit=Quit
|
||||
|
||||
|
||||
|
@ -71,4 +72,8 @@ transfer.money.dialog.transfer.money.label=Transfer
|
|||
transfer.money.dialog.bank.name.will.be.entered.automatically=Will be entered automatically
|
||||
transfer.money.dialog.bank.not.found.for.iban=No bank found for this IBAN
|
||||
transfer.money.dialog.message.transfer.cash.success=Successfully transferred %.02f %s to %s
|
||||
transfer.money.dialog.message.transfer.cash.error=Could not transfer %.02f %s to %s.\r\n\r\nError message from your bank:\r\n\r\n%s
|
||||
transfer.money.dialog.message.transfer.cash.error=Could not transfer %.02f %s to %s.\r\n\r\nError message from your bank:\r\n\r\n%s
|
||||
|
||||
transfer.money.from.pdf.error.message.not.a.searchable.pdf=File "%1$s" is not a searchable PDF. Could therefore not extract text from it.
|
||||
transfer.money.from.pdf.error.message.could.not.extract.text=Could not extract text from file "%1$s".
|
||||
transfer.money.from.pdf.error.message.could.not.extract.invoice.data=Could not extract cash transfer data from file "%1$s".
|
|
@ -13,6 +13,7 @@ main.window.menu.file=Datei
|
|||
main.window.menu.file.new=Neu...
|
||||
main.window.menu.file.new.account=Konto
|
||||
main.window.menu.file.new.cash.transfer=Überweisung
|
||||
main.window.menu.file.new.cash.transfer.from.pdf=Überweisung aus PDF
|
||||
main.window.menu.file.quit=Beenden
|
||||
|
||||
|
||||
|
@ -71,4 +72,8 @@ transfer.money.dialog.transfer.money.label=Überweisen
|
|||
transfer.money.dialog.bank.name.will.be.entered.automatically=Wird automatisch eingetragen
|
||||
transfer.money.dialog.bank.not.found.for.iban=Für diese IBAN wurde keine Bank gefunden
|
||||
transfer.money.dialog.message.transfer.cash.success=%.02f %s erfolgreich an %s überwiesen.
|
||||
transfer.money.dialog.message.transfer.cash.error=%.02f %s konnten nicht an %s überwiesen werden.\r\n\r\nFehlermeldung Ihrer Bank:\r\n\r\n%s
|
||||
transfer.money.dialog.message.transfer.cash.error=%.02f %s konnten nicht an %s überwiesen werden.\r\n\r\nFehlermeldung Ihrer Bank:\r\n\r\n%s
|
||||
|
||||
transfer.money.from.pdf.error.message.not.a.searchable.pdf=Konnte Text nicht aus Datei "%1$s" extrahieren. Enthält sie auch Text oder nur Bilder?
|
||||
transfer.money.from.pdf.error.message.could.not.extract.text=Text konnte nicht aus Datei "%1$s" extrahiert werden.
|
||||
transfer.money.from.pdf.error.message.could.not.extract.invoice.data=Überweisungsdaten konnten aus der Datei "%1$s" nicht ausgelesen werden.
|
|
@ -13,11 +13,22 @@ compileTestKotlin {
|
|||
}
|
||||
|
||||
|
||||
repositories {
|
||||
// for security issues fixed version of iText 2 from JasperReports
|
||||
maven {
|
||||
url "http://jaspersoft.jfrog.io/jaspersoft/third-party-ce-artifacts"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
dependencies {
|
||||
api "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion"
|
||||
|
||||
api "net.dankito.utils:java-utils:$javaUtilsVersion"
|
||||
|
||||
api "net.dankito.text.extraction:text-extractor-common:$textExtractorVersion"
|
||||
api "net.dankito.text.extraction:text-info-extractor:$textInfoExtractorVersion"
|
||||
|
||||
implementation "net.dankito.utils:favicon-finder:1.0.0-SNAPSHOT"
|
||||
|
||||
implementation "org.jsoup:jsoup:1.13.1"
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
package net.dankito.banking.ui.model.moneytransfer
|
||||
|
||||
|
||||
open class ExtractTransferMoneyDataFromPdfResult(
|
||||
val type: ExtractTransferMoneyDataFromPdfResultType,
|
||||
val error: Exception? = null
|
||||
) {
|
||||
|
||||
override fun toString(): String {
|
||||
return type.toString()
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
package net.dankito.banking.ui.model.moneytransfer
|
||||
|
||||
|
||||
enum class ExtractTransferMoneyDataFromPdfResultType {
|
||||
|
||||
Success,
|
||||
|
||||
NotASearchablePdf,
|
||||
|
||||
CouldNotExtractText,
|
||||
|
||||
CouldNotExtractInvoiceDataFromExtractedText
|
||||
|
||||
}
|
|
@ -19,8 +19,14 @@ import net.dankito.banking.bankfinder.IBankFinder
|
|||
import net.dankito.banking.bankfinder.BankInfo
|
||||
import net.dankito.banking.search.IRemitteeSearcher
|
||||
import net.dankito.banking.search.Remittee
|
||||
import net.dankito.banking.ui.model.moneytransfer.ExtractTransferMoneyDataFromPdfResult
|
||||
import net.dankito.banking.ui.model.moneytransfer.ExtractTransferMoneyDataFromPdfResultType
|
||||
import net.dankito.banking.ui.model.parameters.GetTransactionsParameter
|
||||
import net.dankito.banking.ui.model.settings.AppSettings
|
||||
import net.dankito.text.extraction.ITextExtractorRegistry
|
||||
import net.dankito.text.extraction.info.invoice.IInvoiceDataExtractor
|
||||
import net.dankito.text.extraction.info.invoice.InvoiceDataExtractor
|
||||
import net.dankito.text.extraction.model.ErrorType
|
||||
import net.dankito.utils.IThreadPool
|
||||
import net.dankito.utils.ThreadPool
|
||||
import net.dankito.utils.extensions.containsExactly
|
||||
|
@ -45,7 +51,9 @@ open class BankingPresenter(
|
|||
protected val persister: IBankingPersistence,
|
||||
protected val remitteeSearcher: IRemitteeSearcher,
|
||||
protected val bankIconFinder: IBankIconFinder,
|
||||
protected val textExtractorRegistry: ITextExtractorRegistry,
|
||||
protected val router: IRouter,
|
||||
protected val invoiceDataExtractor: IInvoiceDataExtractor = InvoiceDataExtractor(),
|
||||
protected val serializer: ISerializer = JacksonJsonSerializer(),
|
||||
protected val threadPool: IThreadPool = ThreadPool()
|
||||
) {
|
||||
|
@ -380,6 +388,35 @@ open class BankingPresenter(
|
|||
}
|
||||
}
|
||||
|
||||
open fun transferMoneyWithDataFromPdf(pdf: File): ExtractTransferMoneyDataFromPdfResult {
|
||||
val extractionResult = textExtractorRegistry.extractTextWithBestExtractorForFile(pdf)
|
||||
|
||||
if (extractionResult.couldExtractText == false || extractionResult.text == null) {
|
||||
val resultType = if (extractionResult.error?.type == ErrorType.NoExtractorFoundForFileType) ExtractTransferMoneyDataFromPdfResultType.NotASearchablePdf
|
||||
else ExtractTransferMoneyDataFromPdfResultType.CouldNotExtractText
|
||||
return ExtractTransferMoneyDataFromPdfResult(resultType, extractionResult.error?.exception)
|
||||
}
|
||||
else {
|
||||
extractionResult.text?.let { extractedText ->
|
||||
val invoiceData = invoiceDataExtractor.extractInvoiceData(extractedText)
|
||||
|
||||
if (invoiceData.potentialTotalAmount != null || invoiceData.potentialIban != null) { // if at least an amount or IBAN could get extracted
|
||||
val transferMoneyData = TransferMoneyData("",
|
||||
invoiceData.potentialIban ?: "",
|
||||
invoiceData.potentialBic ?: "",
|
||||
invoiceData.potentialTotalAmount?.amount ?: BigDecimal.ZERO, "")
|
||||
showTransferMoneyDialog(null, transferMoneyData)
|
||||
}
|
||||
else {
|
||||
return ExtractTransferMoneyDataFromPdfResult(
|
||||
ExtractTransferMoneyDataFromPdfResultType.CouldNotExtractInvoiceDataFromExtractedText, invoiceData.error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ExtractTransferMoneyDataFromPdfResult(ExtractTransferMoneyDataFromPdfResultType.Success)
|
||||
}
|
||||
|
||||
|
||||
open fun findUniqueBankForIbanAsync(iban: String, callback: (BankInfo?) -> Unit) {
|
||||
threadPool.runAsync {
|
||||
|
|
|
@ -15,5 +15,5 @@ compileTestKotlin {
|
|||
|
||||
dependencies {
|
||||
api project(':BankingUiCommon')
|
||||
implementation project(':fints4k')
|
||||
api project(':fints4k')
|
||||
}
|
Loading…
Reference in New Issue