Implemented storing and displaying for which period account transactions have been fetched
This commit is contained in:
parent
700e3e6da9
commit
13d95f4bda
|
@ -47,7 +47,8 @@ open class FinTsClient(
|
|||
val FindAccountTransactionsStartRegex = Regex("^HIKAZ:\\d:\\d:\\d\\+@\\d+@", RegexOption.MULTILINE)
|
||||
val FindAccountTransactionsEndRegex = Regex("^-'", RegexOption.MULTILINE)
|
||||
|
||||
const val NinetyDaysMillis = 90 * 24 * 60 * 60 * 1000L
|
||||
const val OneDayMillis = 24 * 60 * 60 * 1000L
|
||||
const val NinetyDaysMillis = 90 * OneDayMillis
|
||||
|
||||
|
||||
private val log = LoggerFactory.getLogger(FinTsClient::class)
|
||||
|
@ -404,8 +405,12 @@ open class FinTsClient(
|
|||
closeDialog(dialogContext)
|
||||
|
||||
val successful = response.successful && (parameter.alsoRetrieveBalance == false || balance != null)
|
||||
val fromDate = parameter.fromDate
|
||||
?: dialogContext.bank.countDaysForWhichTransactionsAreKept?.let { Date(Date.today.millisSinceEpoch - it * OneDayMillis) }
|
||||
?: bookedTransactions.map { it.valueDate }.sortedBy { it.millisSinceEpoch }.firstOrNull()
|
||||
val retrievedData = RetrievedAccountData(parameter.account, successful, balance, bookedTransactions, unbookedTransactions, fromDate, parameter.toDate ?: Date.today)
|
||||
|
||||
callback(GetTransactionsResponse(response, listOf(RetrievedAccountData(parameter.account, successful, balance, bookedTransactions, unbookedTransactions)),
|
||||
callback(GetTransactionsResponse(response, listOf(retrievedData),
|
||||
if (parameter.maxCountEntries != null) parameter.isSettingMaxCountEntriesAllowedByBank else null
|
||||
))
|
||||
}
|
||||
|
|
|
@ -1,18 +1,22 @@
|
|||
package net.dankito.banking.fints.model
|
||||
|
||||
import net.dankito.utils.multiplatform.Date
|
||||
|
||||
|
||||
open class RetrievedAccountData(
|
||||
open val accountData: AccountData,
|
||||
open val successfullyRetrievedData: Boolean,
|
||||
open val balance: Money?,
|
||||
open var bookedTransactions: Collection<AccountTransaction>,
|
||||
open var unbookedTransactions: Collection<Any>
|
||||
open var unbookedTransactions: Collection<Any>,
|
||||
open val retrievedTransactionsFrom: Date?,
|
||||
open val retrievedTransactionsTo: Date?
|
||||
) {
|
||||
|
||||
companion object {
|
||||
|
||||
fun unsuccessful(account: AccountData): RetrievedAccountData {
|
||||
return RetrievedAccountData(account, false, null, listOf(), listOf())
|
||||
return RetrievedAccountData(account, false, null, listOf(), listOf(), null, null)
|
||||
}
|
||||
|
||||
fun unsuccessfulList(account: AccountData): List<RetrievedAccountData> {
|
||||
|
|
|
@ -24,7 +24,8 @@ open class BankAccount(
|
|||
override var type: BankAccountType = BankAccountType.Girokonto,
|
||||
override var productName: String? = null,
|
||||
override var accountLimit: String? = null,
|
||||
override var lastRetrievedTransactionsTimestamp: Date? = null,
|
||||
override var retrievedTransactionsFromOn: Date? = null,
|
||||
override var retrievedTransactionsUpTo: Date? = null,
|
||||
|
||||
override var supportsRetrievingAccountTransactions: Boolean = false,
|
||||
override var supportsRetrievingBalance: Boolean = false,
|
||||
|
|
|
@ -22,7 +22,8 @@ open class BankAccountEntity(
|
|||
override var type: BankAccountType = BankAccountType.Girokonto,
|
||||
override var productName: String? = null,
|
||||
override var accountLimit: String? = null,
|
||||
override var lastRetrievedTransactionsTimestamp: Date? = null,
|
||||
override var retrievedTransactionsFromOn: Date? = null,
|
||||
override var retrievedTransactionsUpTo: Date? = null,
|
||||
override var supportsRetrievingAccountTransactions: Boolean = false,
|
||||
override var supportsRetrievingBalance: Boolean = false,
|
||||
override var supportsTransferringMoney: Boolean = false,
|
||||
|
|
|
@ -27,6 +27,7 @@ import net.dankito.banking.ui.presenter.BankingPresenter
|
|||
import net.dankito.utils.android.extensions.asActivity
|
||||
import net.dankito.utils.android.extensions.getDimension
|
||||
import net.dankito.utils.multiplatform.sum
|
||||
import java.text.DateFormat
|
||||
import javax.inject.Inject
|
||||
|
||||
|
||||
|
@ -36,6 +37,8 @@ class HomeFragment : Fragment() {
|
|||
|
||||
val TransactionsCannotBeRetrievedStates = listOf(TransactionsRetrievalState.AccountTypeNotSupported, TransactionsRetrievalState.AccountDoesNotSupportFetchingTransactions)
|
||||
|
||||
val RetrievedTransactionsPeriodDateFormat = DateFormat.getDateInstance(DateFormat.MEDIUM)
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -272,14 +275,20 @@ class HomeFragment : Fragment() {
|
|||
btnRetrieveTransactions.visibility = if (TransactionsCannotBeRetrievedStates.contains(transactionsRetrievalState)) View.GONE else View.VISIBLE
|
||||
btnAddAccount.visibility = if (noAccountsAddedYet) View.VISIBLE else View.GONE
|
||||
|
||||
var messageArgs = mutableListOf<String>()
|
||||
val transactionsRetrievalStateMessageId = when (transactionsRetrievalState) {
|
||||
TransactionsRetrievalState.AccountTypeNotSupported -> R.string.fragment_home_transactions_retrieval_state_account_type_not_supported
|
||||
TransactionsRetrievalState.AccountDoesNotSupportFetchingTransactions -> R.string.fragment_home_transactions_retrieval_state_account_does_not_support_retrieving_transactions
|
||||
TransactionsRetrievalState.NoTransactionsInRetrievedPeriod -> R.string.fragment_home_transactions_retrieval_state_no_transactions_in_retrieved_period
|
||||
TransactionsRetrievalState.NoTransactionsInRetrievedPeriod -> {
|
||||
val account = presenter.selectedBankAccounts.first()
|
||||
account.retrievedTransactionsFromOn?.let { messageArgs.add(RetrievedTransactionsPeriodDateFormat.format(it)) }
|
||||
account.retrievedTransactionsUpTo?.let { messageArgs.add(RetrievedTransactionsPeriodDateFormat.format(it)) }
|
||||
R.string.fragment_home_transactions_retrieval_state_no_transactions_in_retrieved_period
|
||||
}
|
||||
TransactionsRetrievalState.NeverRetrievedTransactions -> R.string.fragment_home_transactions_retrieval_state_never_retrieved_transactions
|
||||
else -> null
|
||||
}
|
||||
txtNoTransactionsFetchedMessage.text = transactionsRetrievalStateMessageId?.let { requireContext().getString(transactionsRetrievalStateMessageId) } ?: ""
|
||||
txtNoTransactionsFetchedMessage.text = transactionsRetrievalStateMessageId?.let { requireContext().getString(transactionsRetrievalStateMessageId, *messageArgs.toTypedArray()) } ?: ""
|
||||
}
|
||||
|
||||
private fun setFetchAllTransactionsView() {
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
<string name="fragment_home_transactions_retrieval_state_account_type_not_supported">Kontotyp wird von App nicht unterstützt</string>
|
||||
<string name="fragment_home_transactions_retrieval_state_account_does_not_support_retrieving_transactions">Konto unterstützt Abrufen von Umsätzen nicht</string>
|
||||
<string name="fragment_home_transactions_retrieval_state_never_retrieved_transactions">Noch keine Umsätze abgerufen</string>
|
||||
<string name="fragment_home_transactions_retrieval_state_no_transactions_in_retrieved_period">Empfangener Zeitraum enthielt keine Umsätze</string>
|
||||
<string name="fragment_home_transactions_retrieval_state_no_transactions_in_retrieved_period">Empfangener Zeitraum vom %1$s - %2$s enthält keine Umsätze</string>
|
||||
<string name="fragment_home_transfer_money_to">Neue Überweisung an %s</string>
|
||||
<string name="fragment_home_transfer_money_with_same_data">Neue Überweisung mit gleichen Daten</string>
|
||||
<string name="fragment_home_fetch_all_account_transactions">Ältere Umsätze abrufen (erfordert TAN)</string>
|
||||
|
|
|
@ -42,7 +42,7 @@
|
|||
<string name="fragment_home_transactions_retrieval_state_account_type_not_supported">Account type not supported by app</string>
|
||||
<string name="fragment_home_transactions_retrieval_state_account_does_not_support_retrieving_transactions">Account does not support retrieving transactions</string>
|
||||
<string name="fragment_home_transactions_retrieval_state_never_retrieved_transactions">No transactions fetched yet</string>
|
||||
<string name="fragment_home_transactions_retrieval_state_no_transactions_in_retrieved_period">There haven\'t been any transactions in retrieved period</string>
|
||||
<string name="fragment_home_transactions_retrieval_state_no_transactions_in_retrieved_period">There haven\'t been any transactions in retrieved period from %1$s - %2$s</string>
|
||||
<string name="fragment_home_transfer_money_to">Transfer money to %s</string>
|
||||
<string name="fragment_home_transfer_money_with_same_data">New transfer with same data</string>
|
||||
<string name="fragment_home_fetch_all_account_transactions">Fetch earlier transactions (requires TAN)</string>
|
||||
|
|
|
@ -18,7 +18,8 @@ open class BankAccount @JvmOverloads constructor(
|
|||
override var type: BankAccountType = BankAccountType.Girokonto,
|
||||
override var productName: String? = null,
|
||||
override var accountLimit: String? = null,
|
||||
override var lastRetrievedTransactionsTimestamp: Date? = null,
|
||||
override var retrievedTransactionsFromOn: Date? = null,
|
||||
override var retrievedTransactionsUpTo: Date? = null,
|
||||
override var supportsRetrievingAccountTransactions: Boolean = false,
|
||||
override var supportsRetrievingBalance: Boolean = false,
|
||||
override var supportsTransferringMoney: Boolean = false,
|
||||
|
|
|
@ -19,7 +19,8 @@ interface IBankAccount<TTransaction: IAccountTransaction> : OrderedDisplayable {
|
|||
var type: BankAccountType
|
||||
var productName: String?
|
||||
var accountLimit: String?
|
||||
var lastRetrievedTransactionsTimestamp: Date?
|
||||
var retrievedTransactionsFromOn: Date?
|
||||
var retrievedTransactionsUpTo: Date?
|
||||
var supportsRetrievingAccountTransactions: Boolean
|
||||
var supportsRetrievingBalance: Boolean
|
||||
var supportsTransferringMoney: Boolean
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package net.dankito.banking.ui.model
|
||||
|
||||
import net.dankito.utils.multiplatform.BigDecimal
|
||||
import net.dankito.utils.multiplatform.Date
|
||||
|
||||
|
||||
open class RetrievedAccountData(
|
||||
|
@ -8,5 +9,7 @@ open class RetrievedAccountData(
|
|||
open val successfullyRetrievedData: Boolean,
|
||||
open val balance: BigDecimal?,
|
||||
open val bookedTransactions: Collection<IAccountTransaction>,
|
||||
open val unbookedTransactions: List<Any>
|
||||
open val unbookedTransactions: List<Any>,
|
||||
open val retrievedTransactionsFrom: Date?,
|
||||
open val retrievedTransactionsTo: Date?
|
||||
)
|
|
@ -11,7 +11,7 @@ open class GetTransactionsResponse(
|
|||
open val tanRequiredButWeWereToldToAbortIfSo: Boolean = false
|
||||
) : BankingClientResponse(true /* any value */, errorToShowToUser, userCancelledAction) {
|
||||
|
||||
constructor(account: TypedBankAccount, errorToShowToUser: String) : this(listOf(RetrievedAccountData(account, false, null, listOf(), listOf())), errorToShowToUser)
|
||||
constructor(account: TypedBankAccount, errorToShowToUser: String) : this(listOf(RetrievedAccountData(account, false, null, listOf(), listOf(), null, null)), errorToShowToUser)
|
||||
|
||||
constructor(retrievedData: RetrievedAccountData) : this(listOf(retrievedData))
|
||||
|
||||
|
|
|
@ -327,7 +327,7 @@ open class BankingPresenter(
|
|||
}
|
||||
|
||||
open fun updateBankAccountTransactionsAsync(bankAccount: TypedBankAccount, abortIfTanIsRequired: Boolean = false, callback: ((GetTransactionsResponse) -> Unit)? = null) {
|
||||
val fromDate = bankAccount.lastRetrievedTransactionsTimestamp?.let { Date(it.millisSinceEpoch - OneDayMillis) } // one day before last received transactions
|
||||
val fromDate = bankAccount.retrievedTransactionsUpTo?.let { Date(it.millisSinceEpoch - OneDayMillis) } // one day before last received transactions
|
||||
|
||||
fetchAccountTransactionsAsync(bankAccount, fromDate, abortIfTanIsRequired, callback)
|
||||
}
|
||||
|
@ -336,7 +336,10 @@ open class BankingPresenter(
|
|||
if (response.successful) {
|
||||
response.retrievedData.forEach { retrievedData ->
|
||||
val account = retrievedData.account
|
||||
account.lastRetrievedTransactionsTimestamp = startDate
|
||||
account.retrievedTransactionsUpTo = startDate
|
||||
if (account.retrievedTransactionsFromOn == null || retrievedData.retrievedTransactionsFrom?.isBefore(account.retrievedTransactionsFromOn!!) == true) {
|
||||
account.retrievedTransactionsFromOn = retrievedData.retrievedTransactionsFrom
|
||||
}
|
||||
|
||||
if (didFetchAllTransactions || didFetchAllTransactionsStoredOnBankServer(account, retrievedData.bookedTransactions)) {
|
||||
account.haveAllTransactionsBeenFetched = true
|
||||
|
@ -368,7 +371,7 @@ open class BankingPresenter(
|
|||
asyncRunner.runAsync { // don't block retrieving next chunk by blocked saving to db / json
|
||||
updateAccountTransactions(bankAccount, accountTransactionsChunk)
|
||||
|
||||
callRetrievedAccountTransactionsResponseListener(GetTransactionsResponse(RetrievedAccountData(bankAccount, true, null, accountTransactionsChunk, listOf())))
|
||||
callRetrievedAccountTransactionsResponseListener(GetTransactionsResponse(RetrievedAccountData(bankAccount, true, null, accountTransactionsChunk, listOf(), null, null)))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -770,7 +773,7 @@ open class BankingPresenter(
|
|||
return TransactionsRetrievalState.RetrievedTransactions
|
||||
}
|
||||
|
||||
if (account.lastRetrievedTransactionsTimestamp != null) {
|
||||
if (account.retrievedTransactionsUpTo != null) {
|
||||
return TransactionsRetrievalState.NoTransactionsInRetrievedPeriod
|
||||
}
|
||||
|
||||
|
|
|
@ -79,7 +79,7 @@
|
|||
"Account type not supported by app" = "Account type not supported by app";
|
||||
"Account does not support retrieving transactions" = "Account does not support retrieving transactions";
|
||||
"No transactions fetched yet" = "No transactions fetched yet";
|
||||
"There haven't been any transactions in retrieved period" = "There haven't been any transactions in retrieved period";
|
||||
"There haven't been any transactions in retrieved period from %@ - %@" = "There haven't been any transactions in retrieved period from %@ - %@";
|
||||
|
||||
"Transfer money to %@" = "Transfer money to %@";
|
||||
"New transfer with same data" = "New transfer with same data";
|
||||
|
|
|
@ -79,7 +79,7 @@
|
|||
"Account type not supported by app" = "Kontotyp wird von App nicht unterstützt";
|
||||
"Account does not support retrieving transactions" = "Konto unterstützt Abrufen von Umsätzen nicht";
|
||||
"No transactions fetched yet" = "Noch keine Umsätze abgerufen";
|
||||
"There haven't been any transactions in retrieved period" = "Empfangener Zeitraum enthielt keine Umsätze";
|
||||
"There haven't been any transactions in retrieved period from %@ - %@" = "Empfangener Zeitraum vom %@ - %@ enthält keine Umsätze";
|
||||
|
||||
"Transfer money to %@" = "Neue Überweisung an %@";
|
||||
"New transfer with same data" = "Neue Überweisung mit gleichen Daten";
|
||||
|
|
|
@ -58,7 +58,7 @@ class Mapper {
|
|||
}
|
||||
|
||||
func map(_ customer: ICustomer, _ account: PersistedBankAccount) -> IBankAccount {
|
||||
let mapped = BankAccount(customer: customer, identifier: map(account.identifier), accountHolderName: map(account.accountHolderName), iban: account.iban, subAccountNumber: account.subAccountNumber, customerId: map(account.customerId), balance: map(account.balance), currency: map(account.currency), type: map(account.type), productName: account.productName, accountLimit: account.accountLimit, lastRetrievedTransactionsTimestamp: map(account.lastRetrievedTransactionsTimestamp), supportsRetrievingAccountTransactions: account.supportsRetrievingAccountTransactions, supportsRetrievingBalance: account.supportsRetrievingBalance, supportsTransferringMoney: account.supportsTransferringMoney, supportsInstantPaymentMoneyTransfer: account.supportsInstantPaymentMoneyTransfer, bookedTransactions: [], unbookedTransactions: [])
|
||||
let mapped = BankAccount(customer: customer, identifier: map(account.identifier), accountHolderName: map(account.accountHolderName), iban: account.iban, subAccountNumber: account.subAccountNumber, customerId: map(account.customerId), balance: map(account.balance), currency: map(account.currency), type: map(account.type), productName: account.productName, accountLimit: account.accountLimit, retrievedTransactionsFromOn: map(account.retrievedTransactionsFromOn), retrievedTransactionsUpTo: map(account.retrievedTransactionsUpTo), supportsRetrievingAccountTransactions: account.supportsRetrievingAccountTransactions, supportsRetrievingBalance: account.supportsRetrievingBalance, supportsTransferringMoney: account.supportsTransferringMoney, supportsInstantPaymentMoneyTransfer: account.supportsInstantPaymentMoneyTransfer, bookedTransactions: [], unbookedTransactions: [])
|
||||
|
||||
mapped.haveAllTransactionsBeenFetched = account.haveAllTransactionsBeenFetched
|
||||
mapped.isAccountTypeSupported = account.isAccountTypeSupported
|
||||
|
@ -92,7 +92,8 @@ class Mapper {
|
|||
mapped.isAccountTypeSupported = account.isAccountTypeSupported
|
||||
mapped.productName = account.productName
|
||||
mapped.accountLimit = account.accountLimit
|
||||
mapped.lastRetrievedTransactionsTimestamp = account.lastRetrievedTransactionsTimestamp?.date
|
||||
mapped.retrievedTransactionsFromOn = account.retrievedTransactionsFromOn?.date
|
||||
mapped.retrievedTransactionsUpTo = account.retrievedTransactionsUpTo?.date
|
||||
mapped.supportsRetrievingAccountTransactions = account.supportsRetrievingAccountTransactions
|
||||
mapped.supportsRetrievingBalance = account.supportsRetrievingBalance
|
||||
mapped.supportsTransferringMoney = account.supportsTransferringMoney
|
||||
|
|
|
@ -6,6 +6,8 @@ struct AccountTransactionsDialog: View {
|
|||
|
||||
static private let DoNotShowFetchAllTransactionsOverlayForUserDefaultsKeyPrefix = "DoNotShowFetchAllTransactionsOverlayFor_"
|
||||
|
||||
static private let RetrievedTransactionsPeriodDateFormat = DateFormatter()
|
||||
|
||||
|
||||
private let title: String
|
||||
|
||||
|
@ -73,6 +75,8 @@ struct AccountTransactionsDialog: View {
|
|||
self.title = title
|
||||
|
||||
self.showBankIcons = showBankIcons
|
||||
|
||||
Self.RetrievedTransactionsPeriodDateFormat.dateStyle = .medium
|
||||
}
|
||||
|
||||
|
||||
|
@ -246,7 +250,8 @@ struct AccountTransactionsDialog: View {
|
|||
return "No transactions fetched yet"
|
||||
}
|
||||
else if state == .notransactionsinretrievedperiod {
|
||||
return "There haven't been any transactions in retrieved period"
|
||||
let account = presenter.selectedBankAccounts.first!
|
||||
return "There haven't been any transactions in retrieved period from \(mapDate(account.retrievedTransactionsFromOn)) - \(mapDate(account.retrievedTransactionsUpTo))"
|
||||
}
|
||||
else if state == .accountdoesnotsupportfetchingtransactions {
|
||||
return "Account does not support retrieving transactions"
|
||||
|
|
|
@ -56,7 +56,9 @@ open class fints4kModelMapper(protected val modelCreator: IModelCreator) {
|
|||
retrievedData.successfullyRetrievedData,
|
||||
retrievedData.balance?.toBigDecimal(),
|
||||
mapTransactions(account, retrievedData.bookedTransactions),
|
||||
listOf() // TODO: map unbooked transactions
|
||||
listOf(), // TODO: map unbooked transactions
|
||||
retrievedData.retrievedTransactionsFrom,
|
||||
retrievedData.retrievedTransactionsTo
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -102,7 +102,7 @@ open class hbci4jBankingClient(
|
|||
response.retrievedData.first()
|
||||
}
|
||||
else {
|
||||
RetrievedAccountData(account, false, null, listOf(), listOf())
|
||||
RetrievedAccountData(account, false, null, listOf(), listOf(), null)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -180,7 +180,7 @@ open class hbci4jBankingClient(
|
|||
}
|
||||
|
||||
return GetTransactionsResponse(RetrievedAccountData(account, true, balance.toBigDecimal(),
|
||||
accountTransactionMapper.mapAccountTransactions(account, result), listOf()))
|
||||
accountTransactionMapper.mapAccountTransactions(account, result), listOf(), parameter.fromDate, parameter.toDate))
|
||||
}
|
||||
catch(e: Exception) {
|
||||
log.error("Could not get accounting details for bank ${credentials.bankCode}", e)
|
||||
|
|
Loading…
Reference in New Issue