Compare commits
10 Commits
c564750832
...
952fa9c13a
Author | SHA1 | Date |
---|---|---|
dankito | 952fa9c13a | |
dankito | b47fcabc1c | |
dankito | 878d32ea16 | |
dankito | 5f7b07a601 | |
dankito | 7e8d005fcb | |
dankito | 21215300b3 | |
dankito | b826ee3c8f | |
dankito | 32defa20f7 | |
dankito | c5432883ef | |
dankito | dae6084ebb |
|
@ -1,6 +1,6 @@
|
||||||
// TODO: move to versions.gradle
|
// TODO: move to versions.gradle
|
||||||
ext {
|
ext {
|
||||||
appVersionName = '1.0.0-Alpha-12-SNAPSHOT'
|
appVersionName = '1.0.0-Alpha-13-SNAPSHOT'
|
||||||
|
|
||||||
|
|
||||||
/* Test */
|
/* Test */
|
||||||
|
|
|
@ -8,7 +8,7 @@ plugins {
|
||||||
|
|
||||||
|
|
||||||
kotlin {
|
kotlin {
|
||||||
jvmToolchain(8)
|
jvmToolchain(11)
|
||||||
|
|
||||||
compilerOptions {
|
compilerOptions {
|
||||||
// suppresses compiler warning: [EXPECT_ACTUAL_CLASSIFIERS_ARE_IN_BETA_WARNING] 'expect'/'actual' classes (including interfaces, objects, annotations, enums, and 'actual' typealiases) are in Beta.
|
// suppresses compiler warning: [EXPECT_ACTUAL_CLASSIFIERS_ARE_IN_BETA_WARNING] 'expect'/'actual' classes (including interfaces, objects, annotations, enums, and 'actual' typealiases) are in Beta.
|
||||||
|
@ -73,7 +73,7 @@ kotlin {
|
||||||
|
|
||||||
implementation("org.jetbrains.kotlinx:kotlinx-serialization-core:$kotlinxSerializationVersion")
|
implementation("org.jetbrains.kotlinx:kotlinx-serialization-core:$kotlinxSerializationVersion")
|
||||||
|
|
||||||
implementation("net.codinux.log:kmp-log:$klfVersion")
|
implementation("net.codinux.log:klf:$klfVersion")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -307,6 +307,7 @@ open class FinTsJobExecutor(
|
||||||
|
|
||||||
bank.selectedTanMedium = preferredTanMedium?.let { bank.tanMedia.firstOrNull { it.mediumName == preferredTanMedium } }
|
bank.selectedTanMedium = preferredTanMedium?.let { bank.tanMedia.firstOrNull { it.mediumName == preferredTanMedium } }
|
||||||
?: bank.selectedTanMedium?.let { selected -> bank.tanMedia.firstOrNull { it.mediumName == selected.mediumName } } // try to find selectedTanMedium in new TanMedia instances
|
?: bank.selectedTanMedium?.let { selected -> bank.tanMedia.firstOrNull { it.mediumName == selected.mediumName } } // try to find selectedTanMedium in new TanMedia instances
|
||||||
|
?: bank.tanMedia.firstOrNull { it.status == TanMediumStatus.Aktiv && it.mediumName != null }
|
||||||
?: bank.tanMedia.firstOrNull { it.mediumName != null }
|
?: bank.tanMedia.firstOrNull { it.mediumName != null }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,15 @@ open class BankParameters(
|
||||||
*
|
*
|
||||||
* Maximale Anzahl aller Geschäftsvorfallsarten pro Nachricht: „Anzahl Geschäftsvorfallsarten“ (BPA, also dieser Wert hier).
|
* Maximale Anzahl aller Geschäftsvorfallsarten pro Nachricht: „Anzahl Geschäftsvorfallsarten“ (BPA, also dieser Wert hier).
|
||||||
* Maximale Anzahl eines bestimmten Segments pro Nachricht: „Maximale Anzahl Aufträge“ (JobParameter des jeweiligen Segments).
|
* Maximale Anzahl eines bestimmten Segments pro Nachricht: „Maximale Anzahl Aufträge“ (JobParameter des jeweiligen Segments).
|
||||||
|
*
|
||||||
|
* Jedoch, 07 PINTAN, S. 60:
|
||||||
|
* "Desweiteren ist vom Kundenprodukt sicherzustellen, dass eine Nachricht entweder nur einen einzelnen Geschäftsvorfall enthält,
|
||||||
|
* für den eine TAN erforderlich ist, oder nur solche Geschäftsvorfälle, für die keine TAN erforderlich ist. Andernfalls ist
|
||||||
|
* die eindeutige Zuordnung der übergebenen TAN zu den Geschäftsvorfällen nicht sichergestellt.
|
||||||
|
* Eine Mischung von Geschäftsvorfällen, die eine TAN erfordern, mit solchen, die keine erfordern, ist generell nicht zulässig."
|
||||||
|
*
|
||||||
|
* -> ist praktisch nutzlos, da allenfalls nur mehr als ein nicht-TAN pflichtiger Geschäftsvorall pro Nachricht
|
||||||
|
* gesendent werden kann, jedoch nicht mehrere TAN-pflichtige und damit 99 % aller Geschäftsvorfälle.
|
||||||
*/
|
*/
|
||||||
val countMaxJobsPerMessage: Int,
|
val countMaxJobsPerMessage: Int,
|
||||||
|
|
||||||
|
|
|
@ -53,7 +53,7 @@ open class Mt940Parser(
|
||||||
|
|
||||||
val DateFormatter = DateFormatter("yyMMdd") // TODO: replace with LocalDate.Format { }
|
val DateFormatter = DateFormatter("yyMMdd") // TODO: replace with LocalDate.Format { }
|
||||||
|
|
||||||
val CurrentYearTwoDigit = LocalDate.todayAtEuropeBerlin().year - 2000
|
val CurrentYearTwoDigit = LocalDate.todayAtEuropeBerlin().year
|
||||||
|
|
||||||
val CreditDebitCancellationRegex = Regex("C|D|RC|RD")
|
val CreditDebitCancellationRegex = Regex("C|D|RC|RD")
|
||||||
|
|
||||||
|
@ -455,7 +455,7 @@ open class Mt940Parser(
|
||||||
// this really simple date format on my own
|
// this really simple date format on my own
|
||||||
if (dateString.length == 6) {
|
if (dateString.length == 6) {
|
||||||
try {
|
try {
|
||||||
var year = dateString.substring(0, 2).toInt()
|
var year = dateString.substring(0, 2).toInt() + 2000
|
||||||
val month = dateString.substring(2, 4).toInt()
|
val month = dateString.substring(2, 4).toInt()
|
||||||
val day = dateString.substring(4, 6).toInt()
|
val day = dateString.substring(4, 6).toInt()
|
||||||
|
|
||||||
|
@ -463,7 +463,14 @@ open class Mt940Parser(
|
||||||
year -= 100
|
year -= 100
|
||||||
}
|
}
|
||||||
|
|
||||||
return LocalDate(year + 2000, month, day) // java.util.Date years start at 1900 at month at 0 not at 1
|
// ah, here we go, banks (in Germany) calculate with 30 days each month, so yes, it can happen that dates
|
||||||
|
// like 30th of February or 29th of February in non-leap years occur, see:
|
||||||
|
// https://de.m.wikipedia.org/wiki/30._Februar#30._Februar_in_der_Zinsberechnung
|
||||||
|
if (month == 2 && (day > 29 || (day > 28 && year % 4 != 0))) { // fix that for banks each month has 30 days
|
||||||
|
return LocalDate(year, 3, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
return LocalDate(year , month, day)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
logError("Could not parse dateString '$dateString'", e)
|
logError("Could not parse dateString '$dateString'", e)
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ open class KtorWebClient(
|
||||||
private val log by logger()
|
private val log by logger()
|
||||||
|
|
||||||
|
|
||||||
protected val client = HttpClient {
|
protected open val client = HttpClient {
|
||||||
install(HttpTimeout) {
|
install(HttpTimeout) {
|
||||||
this.connectTimeoutMillis = connectTimeoutMillis
|
this.connectTimeoutMillis = connectTimeoutMillis
|
||||||
this.requestTimeoutMillis = requestTimeoutMillis
|
this.requestTimeoutMillis = requestTimeoutMillis
|
||||||
|
@ -37,7 +37,7 @@ open class KtorWebClient(
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
suspend fun get(url: String): WebClientResponse {
|
open suspend fun get(url: String): WebClientResponse {
|
||||||
val clientResponse = client.get(url)
|
val clientResponse = client.get(url)
|
||||||
|
|
||||||
val responseBody = clientResponse.bodyAsText()
|
val responseBody = clientResponse.bodyAsText()
|
||||||
|
|
|
@ -38,7 +38,11 @@ class Mt940ParserTest : FinTsTestBase() {
|
||||||
val AccountStatement1With2TransactionsClosingBalanceAmount = Amount("13148,13")
|
val AccountStatement1With2TransactionsClosingBalanceAmount = Amount("13148,13")
|
||||||
}
|
}
|
||||||
|
|
||||||
private val underTest = Mt940Parser()
|
private val underTest = object : Mt940Parser() {
|
||||||
|
public override fun parseMt940Date(dateString: String): LocalDate {
|
||||||
|
return super.parseMt940Date(dateString)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -312,6 +316,35 @@ class Mt940ParserTest : FinTsTestBase() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun parseDate() {
|
||||||
|
val result = underTest.parseMt940Date("240507")
|
||||||
|
|
||||||
|
assertEquals(LocalDate(2024, 5, 7), result)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun parseDateBeforeYear2000() {
|
||||||
|
val result = underTest.parseMt940Date("990507")
|
||||||
|
|
||||||
|
assertEquals(LocalDate(1999, 5, 7), result)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun parseDate_FixSparkasse29thOFFebruaryInNonLeapYearBug() {
|
||||||
|
val result = underTest.parseMt940Date("230229")
|
||||||
|
|
||||||
|
assertEquals(LocalDate(2023, 3, 1), result)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun parseDate_FixSparkasse30thOfFebruaryBug() {
|
||||||
|
val result = underTest.parseMt940Date("230229")
|
||||||
|
|
||||||
|
assertEquals(LocalDate(2023, 3, 1), result)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun assertBalance(balance: Balance, isCredit: Boolean, bookingDate: LocalDate, amount: Amount) {
|
private fun assertBalance(balance: Balance, isCredit: Boolean, bookingDate: LocalDate, amount: Amount) {
|
||||||
assertEquals(isCredit, balance.isCredit)
|
assertEquals(isCredit, balance.isCredit)
|
||||||
assertEquals(bookingDate, balance.bookingDate)
|
assertEquals(bookingDate, balance.bookingDate)
|
||||||
|
|
|
@ -15,7 +15,7 @@ kotlinxDateTimeVersion=0.5.0
|
||||||
kotlinxSerializationVersion=1.7.1
|
kotlinxSerializationVersion=1.7.1
|
||||||
atomicfuVersion=0.25.0
|
atomicfuVersion=0.25.0
|
||||||
|
|
||||||
klfVersion=1.5.1
|
klfVersion=1.6.0
|
||||||
|
|
||||||
android.useAndroidX=true
|
android.useAndroidX=true
|
||||||
android.enableJetifier=true
|
android.enableJetifier=true
|
Loading…
Reference in New Issue