Persisting AccountTransactions in db
This commit is contained in:
parent
7495cb89c2
commit
6d35b9c64f
|
@ -22,4 +22,4 @@ xcuserdata
|
|||
!*.xcworkspace/contents.xcworkspacedata
|
||||
**/xcshareddata/WorkspaceSettings.xcsettings
|
||||
|
||||
composeApp/data/logs
|
||||
composeApp/data/
|
||||
|
|
|
@ -11,6 +11,8 @@ plugins {
|
|||
alias(libs.plugins.compose.compiler)
|
||||
|
||||
alias(libs.plugins.kotlinxSerialization)
|
||||
|
||||
alias(libs.plugins.sqldelight)
|
||||
}
|
||||
|
||||
|
||||
|
@ -63,6 +65,10 @@ kotlin {
|
|||
implementation(libs.klf)
|
||||
implementation(libs.kotlinx.serializable)
|
||||
|
||||
implementation(libs.sqldelight.runtime)
|
||||
implementation(libs.sqldelight.coroutines.extensions)
|
||||
implementation(libs.sqldelight.paging.extensions)
|
||||
|
||||
// UI
|
||||
implementation(compose.runtime)
|
||||
implementation(compose.foundation)
|
||||
|
@ -75,20 +81,50 @@ kotlin {
|
|||
implementation(libs.androidx.lifecycle.runtime.compose)
|
||||
}
|
||||
|
||||
commonTest.dependencies {
|
||||
implementation(libs.kotlin.test)
|
||||
}
|
||||
|
||||
androidMain.dependencies {
|
||||
implementation(compose.preview)
|
||||
implementation(libs.androidx.activity.compose)
|
||||
|
||||
implementation(libs.sqldelight.android.driver)
|
||||
}
|
||||
|
||||
nativeMain.dependencies {
|
||||
implementation(libs.sqldelight.native.driver)
|
||||
}
|
||||
|
||||
jvmMain.dependencies {
|
||||
implementation(libs.sqldelight.sqlite.driver)
|
||||
}
|
||||
jvmTest.dependencies {
|
||||
implementation(libs.kotlin.test.junit)
|
||||
}
|
||||
|
||||
desktopMain.dependencies {
|
||||
implementation(compose.desktop.currentOs)
|
||||
implementation(libs.kotlinx.coroutines.swing)
|
||||
|
||||
implementation(libs.sqldelight.sqlite.driver)
|
||||
|
||||
implementation(libs.logback)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
sqldelight {
|
||||
databases {
|
||||
create("BankmeisterDb") {
|
||||
packageName.set("net.codinux.banking.dataaccess")
|
||||
generateAsync.set(true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
android {
|
||||
namespace = "net.codinux.banking.ui"
|
||||
compileSdk = libs.versions.android.compileSdk.get().toInt()
|
||||
|
|
|
@ -5,11 +5,17 @@ import androidx.activity.ComponentActivity
|
|||
import androidx.activity.compose.setContent
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.tooling.preview.Preview
|
||||
import app.cash.sqldelight.async.coroutines.synchronous
|
||||
import app.cash.sqldelight.driver.android.AndroidSqliteDriver
|
||||
import net.codinux.banking.dataaccess.BankmeisterDb
|
||||
import net.codinux.banking.ui.config.DI
|
||||
|
||||
class MainActivity : ComponentActivity() {
|
||||
override fun onCreate(savedInstanceState: Bundle?) {
|
||||
super.onCreate(savedInstanceState)
|
||||
|
||||
DI.setRepository(AndroidSqliteDriver(BankmeisterDb.Schema.synchronous(), this, "Bankmeister.db"))
|
||||
|
||||
setContent {
|
||||
App()
|
||||
}
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
package net.codinux.banking.dataaccess
|
||||
|
||||
import net.codinux.banking.client.model.AccountTransaction
|
||||
import net.codinux.banking.dataaccess.entities.AccountTransactionEntity
|
||||
|
||||
interface BankingRepository {
|
||||
|
||||
fun getAllAccountTransactions(): List<AccountTransactionEntity>
|
||||
|
||||
suspend fun persistAccountTransactions(transactions: Collection<AccountTransaction>)
|
||||
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
package net.codinux.banking.dataaccess
|
||||
|
||||
import net.codinux.banking.client.model.AccountTransaction
|
||||
import net.codinux.banking.dataaccess.entities.AccountTransactionEntity
|
||||
|
||||
class InMemoryBankingRepository(
|
||||
transactions: Collection<AccountTransaction>
|
||||
) : BankingRepository {
|
||||
|
||||
private var nextId = 0L // TODO: make thread-safe
|
||||
|
||||
private val transactions = transactions.map { map(it) }.toMutableList()
|
||||
|
||||
|
||||
override fun getAllAccountTransactions(): List<AccountTransactionEntity> = transactions.toList()
|
||||
|
||||
override suspend fun persistAccountTransactions(transactions: Collection<AccountTransaction>) {
|
||||
this.transactions.addAll(transactions.map { map(it) })
|
||||
}
|
||||
|
||||
|
||||
private fun map(transaction: AccountTransaction) = AccountTransactionEntity(
|
||||
nextId++,
|
||||
transaction.amount, transaction.currency, transaction.reference,
|
||||
transaction.bookingDate, transaction.valueDate,
|
||||
transaction.otherPartyName, transaction.otherPartyBankCode, transaction.otherPartyAccountId,
|
||||
transaction.bookingText
|
||||
)
|
||||
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
package net.codinux.banking.dataaccess
|
||||
|
||||
import app.cash.sqldelight.db.SqlDriver
|
||||
import kotlinx.datetime.LocalDate
|
||||
import net.codinux.banking.client.model.AccountTransaction
|
||||
import net.codinux.banking.client.model.Amount
|
||||
import net.codinux.banking.dataaccess.entities.AccountTransactionEntity
|
||||
|
||||
class SqliteBankingRepository(
|
||||
sqlDriver: SqlDriver
|
||||
) : BankingRepository {
|
||||
|
||||
private val database = BankmeisterDb(sqlDriver)
|
||||
|
||||
private val accountTransactionQueries = database.accountTransactionQueries
|
||||
|
||||
|
||||
override fun getAllAccountTransactions(): List<AccountTransactionEntity> {
|
||||
return accountTransactionQueries.selectAllTransactions { id, amount, currency, reference, bookingDate, valueDate, otherPartyName, otherPartyBankCode, otherPartyAccountId, bookingText, userSetDisplayName, notes, information, statementNumber, sequenceNumber, openingBalance, closingBalance, endToEndReference, customerReference, mandateReference, creditorIdentifier, originatorsIdentificationCode, compensationAmount, originalAmount, sepaReference, deviantOriginator, deviantRecipient, referenceWithNoSpecialType, primaNotaNumber, textKeySupplement, currencyType, bookingKey, referenceForTheAccountOwner, referenceOfTheAccountServicingInstitution, supplementaryDetails, transactionReferenceNumber, relatedReferenceNumber ->
|
||||
AccountTransactionEntity(
|
||||
id,
|
||||
Amount(amount), currency, reference,
|
||||
mapToDate(bookingDate), mapToDate(valueDate),
|
||||
otherPartyName, otherPartyBankCode, otherPartyAccountId,
|
||||
bookingText,
|
||||
|
||||
userSetDisplayName, notes,
|
||||
|
||||
information,
|
||||
statementNumber?.toInt(), sequenceNumber?.toInt(),
|
||||
|
||||
mapToAmount(openingBalance), mapToAmount(closingBalance),
|
||||
|
||||
endToEndReference, customerReference, mandateReference,
|
||||
creditorIdentifier, originatorsIdentificationCode,
|
||||
compensationAmount, originalAmount,
|
||||
sepaReference,
|
||||
deviantOriginator, deviantRecipient,
|
||||
referenceWithNoSpecialType, primaNotaNumber,
|
||||
textKeySupplement,
|
||||
|
||||
currencyType, bookingKey,
|
||||
referenceForTheAccountOwner, referenceOfTheAccountServicingInstitution,
|
||||
supplementaryDetails,
|
||||
|
||||
transactionReferenceNumber, relatedReferenceNumber
|
||||
)
|
||||
}.executeAsList()
|
||||
}
|
||||
|
||||
override suspend fun persistAccountTransactions(transactions: Collection<AccountTransaction>) {
|
||||
transactions.forEach {
|
||||
saveAccountTransaction(it)
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun saveAccountTransaction(transaction: AccountTransaction) {
|
||||
accountTransactionQueries.insertTransaction(
|
||||
transaction.amount.amount, transaction.currency, transaction.reference,
|
||||
mapDate(transaction.bookingDate), mapDate(transaction.valueDate),
|
||||
transaction.otherPartyName, transaction.otherPartyBankCode, transaction.otherPartyAccountId,
|
||||
transaction.bookingText,
|
||||
|
||||
transaction.userSetDisplayName, transaction.notes,
|
||||
|
||||
transaction.information,
|
||||
transaction.statementNumber?.toLong(), transaction.sequenceNumber?.toLong(),
|
||||
transaction.openingBalance?.amount, transaction.closingBalance?.amount,
|
||||
|
||||
transaction.endToEndReference, transaction.customerReference, transaction.mandateReference,
|
||||
transaction.creditorIdentifier, transaction.originatorsIdentificationCode,
|
||||
transaction.compensationAmount, transaction.originalAmount,
|
||||
transaction.sepaReference,
|
||||
transaction.deviantOriginator, transaction.deviantRecipient,
|
||||
transaction.referenceWithNoSpecialType, transaction.primaNotaNumber, transaction.textKeySupplement,
|
||||
|
||||
transaction.currencyType, transaction.bookingKey,
|
||||
transaction.referenceForTheAccountOwner, transaction.referenceOfTheAccountServicingInstitution,
|
||||
transaction.supplementaryDetails,
|
||||
|
||||
transaction.transactionReferenceNumber, transaction.relatedReferenceNumber
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
private fun mapToAmount(serializedAmount: String?): Amount? = serializedAmount?.let { Amount(it) }
|
||||
|
||||
private fun mapDate(date: LocalDate): String = date.toString()
|
||||
|
||||
private fun mapToDate(serializedDate: String): LocalDate = LocalDate.parse(serializedDate)
|
||||
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
package net.codinux.banking.dataaccess.entities
|
||||
|
||||
import kotlinx.datetime.LocalDate
|
||||
import net.codinux.banking.client.model.AccountTransaction
|
||||
import net.codinux.banking.client.model.Amount
|
||||
|
||||
class AccountTransactionEntity(
|
||||
val id: Long,
|
||||
|
||||
amount: Amount,
|
||||
currency: String,
|
||||
reference: String,
|
||||
|
||||
bookingDate: LocalDate,
|
||||
valueDate: LocalDate,
|
||||
|
||||
otherPartyName: String? = null,
|
||||
otherPartyBankCode: String? = null,
|
||||
otherPartyAccountId: String? = null,
|
||||
|
||||
bookingText: String? = null,
|
||||
|
||||
userSetDisplayName: String? = null,
|
||||
notes: String? = null,
|
||||
information: String? = null,
|
||||
|
||||
statementNumber: Int? = null,
|
||||
sequenceNumber: Int? = null,
|
||||
|
||||
openingBalance: Amount? = null,
|
||||
closingBalance: Amount? = null,
|
||||
|
||||
endToEndReference: String? = null,
|
||||
customerReference: String? = null,
|
||||
mandateReference: String? = null,
|
||||
creditorIdentifier: String? = null,
|
||||
originatorsIdentificationCode: String? = null,
|
||||
compensationAmount: String? = null,
|
||||
originalAmount: String? = null,
|
||||
sepaReference: String? = null,
|
||||
deviantOriginator: String? = null,
|
||||
deviantRecipient: String? = null,
|
||||
referenceWithNoSpecialType: String? = null,
|
||||
primaNotaNumber: String? = null,
|
||||
textKeySupplement: String? = null,
|
||||
|
||||
currencyType: String? = null,
|
||||
bookingKey: String? = null,
|
||||
referenceForTheAccountOwner: String? = null,
|
||||
referenceOfTheAccountServicingInstitution: String? = null,
|
||||
supplementaryDetails: String? = null,
|
||||
|
||||
transactionReferenceNumber: String? = null,
|
||||
relatedReferenceNumber: String? = null
|
||||
) : AccountTransaction(
|
||||
amount, currency, reference,
|
||||
bookingDate, valueDate,
|
||||
otherPartyName, otherPartyBankCode, otherPartyAccountId,
|
||||
bookingText,
|
||||
|
||||
information,
|
||||
statementNumber, sequenceNumber,
|
||||
openingBalance, closingBalance,
|
||||
|
||||
endToEndReference, customerReference, mandateReference,
|
||||
creditorIdentifier, originatorsIdentificationCode,
|
||||
compensationAmount, originalAmount,
|
||||
sepaReference,
|
||||
deviantOriginator, deviantRecipient,
|
||||
referenceWithNoSpecialType, primaNotaNumber,
|
||||
textKeySupplement,
|
||||
|
||||
currencyType, bookingKey,
|
||||
referenceForTheAccountOwner, referenceOfTheAccountServicingInstitution,
|
||||
supplementaryDetails,
|
||||
|
||||
transactionReferenceNumber, relatedReferenceNumber,
|
||||
|
||||
userSetDisplayName, notes
|
||||
)
|
|
@ -14,7 +14,6 @@ import androidx.compose.ui.text.TextStyle
|
|||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import kotlinx.coroutines.launch
|
||||
import net.codinux.banking.client.model.AccountTransaction
|
||||
import net.codinux.banking.ui.composables.StateHandler
|
||||
import net.codinux.banking.ui.composables.TransactionsList
|
||||
import net.codinux.banking.ui.dialogs.AddAccountDialog
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
package net.codinux.banking.ui.config
|
||||
|
||||
import app.cash.sqldelight.db.SqlDriver
|
||||
import net.codinux.banking.dataaccess.BankingRepository
|
||||
import net.codinux.banking.dataaccess.InMemoryBankingRepository
|
||||
import net.codinux.banking.dataaccess.SqliteBankingRepository
|
||||
import net.codinux.banking.ui.Platform
|
||||
import net.codinux.banking.ui.getPlatform
|
||||
import net.codinux.banking.ui.service.BankFinder
|
||||
import net.codinux.banking.ui.service.BankingService
|
||||
import net.codinux.banking.ui.service.FormatUtil
|
||||
import net.codinux.banking.ui.service.*
|
||||
import net.codinux.banking.ui.state.UiState
|
||||
|
||||
object DI {
|
||||
|
@ -13,12 +15,24 @@ object DI {
|
|||
|
||||
val platform: Platform = getPlatform()
|
||||
|
||||
val bankFinder = BankFinder()
|
||||
|
||||
val bankingService = BankingService(uiState, bankFinder)
|
||||
|
||||
val formatUtil = FormatUtil()
|
||||
|
||||
val bankFinder = BankFinder()
|
||||
|
||||
|
||||
var bankingRepository: BankingRepository = InMemoryBankingRepository(emptyList())
|
||||
|
||||
val bankingService by lazy {
|
||||
BankingService(uiState, bankingRepository, bankFinder) }
|
||||
|
||||
|
||||
fun setRepository(sqlDriver: SqlDriver) = setRepository(SqliteBankingRepository(sqlDriver))
|
||||
|
||||
fun setRepository(repository: BankingRepository) {
|
||||
this.bankingRepository = repository
|
||||
}
|
||||
|
||||
|
||||
suspend fun init() {
|
||||
bankingService.init()
|
||||
|
|
|
@ -10,6 +10,7 @@ import net.codinux.banking.client.model.options.GetAccountDataOptions
|
|||
import net.codinux.banking.client.model.options.RetrieveTransactions
|
||||
import net.codinux.banking.client.model.request.GetAccountDataRequest
|
||||
import net.codinux.banking.client.model.response.*
|
||||
import net.codinux.banking.dataaccess.BankingRepository
|
||||
import net.codinux.banking.fints.config.FinTsClientConfiguration
|
||||
import net.codinux.banking.fints.config.FinTsClientOptions
|
||||
import net.codinux.banking.ui.model.BankInfo
|
||||
|
@ -25,6 +26,7 @@ import org.jetbrains.compose.resources.ExperimentalResourceApi
|
|||
@OptIn(ExperimentalResourceApi::class)
|
||||
class BankingService(
|
||||
private val uiState: UiState,
|
||||
private val bankingRepository: BankingRepository,
|
||||
private val bankFinder: BankFinder
|
||||
) {
|
||||
|
||||
|
@ -36,9 +38,11 @@ class BankingService(
|
|||
|
||||
|
||||
suspend fun init() {
|
||||
val transactions = readTransactionsFromCsv()
|
||||
|
||||
uiState.transactions.value = transactions
|
||||
try {
|
||||
uiState.transactions.value = bankingRepository.getAllAccountTransactions()
|
||||
} catch (e: Throwable) {
|
||||
log.error(e) { "Could not read all account transactions from repository" }
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun findBanks(query: String): List<BankInfo> =
|
||||
|
@ -64,13 +68,21 @@ class BankingService(
|
|||
}
|
||||
}
|
||||
|
||||
private fun handleSuccessfulGetAccountDataResponse(response: GetAccountDataResponse) {
|
||||
private suspend fun handleSuccessfulGetAccountDataResponse(response: GetAccountDataResponse) {
|
||||
// TODO: save customer
|
||||
|
||||
val transactions = uiState.transactions.value.toMutableList()
|
||||
transactions.addAll(response.bookedTransactions)
|
||||
|
||||
uiState.transactions.value = transactions.sortedByDescending { it.valueDate }
|
||||
|
||||
try {
|
||||
bankingRepository.persistAccountTransactions(response.bookedTransactions)
|
||||
|
||||
log.info { "Saved ${response.bookedTransactions.size} transactions" }
|
||||
} catch (e: Throwable) {
|
||||
log.error(e) { "Could not save account transactions ${response.bookedTransactions}" }
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleUnsuccessfulBankingClientResponse(action: BankingClientAction, response: Response<*>) {
|
||||
|
|
|
@ -0,0 +1,110 @@
|
|||
CREATE TABLE IF NOT EXISTS AccountTransaction (
|
||||
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||
|
||||
amount TEXT NOT NULL,
|
||||
currency TEXT NOT NULL,
|
||||
reference TEXT NOT NULL,
|
||||
|
||||
bookingDate TEXT NOT NULL,
|
||||
valueDate TEXT NOT NULL,
|
||||
|
||||
otherPartyName TEXT,
|
||||
otherPartyBankCode TEXT,
|
||||
otherPartyAccountId TEXT,
|
||||
|
||||
bookingText TEXT,
|
||||
|
||||
userSetDisplayName TEXT,
|
||||
notes TEXT,
|
||||
|
||||
information TEXT,
|
||||
|
||||
statementNumber INTEGER,
|
||||
sequenceNumber INTEGER,
|
||||
|
||||
openingBalance TEXT,
|
||||
closingBalance TEXT,
|
||||
|
||||
endToEndReference TEXT,
|
||||
customerReference TEXT,
|
||||
mandateReference TEXT,
|
||||
creditorIdentifier TEXT,
|
||||
originatorsIdentificationCode TEXT,
|
||||
compensationAmount TEXT,
|
||||
originalAmount TEXT,
|
||||
sepaReference TEXT,
|
||||
deviantOriginator TEXT,
|
||||
deviantRecipient TEXT,
|
||||
referenceWithNoSpecialType TEXT,
|
||||
primaNotaNumber TEXT,
|
||||
textKeySupplement TEXT,
|
||||
|
||||
currencyType TEXT,
|
||||
bookingKey TEXT,
|
||||
referenceForTheAccountOwner TEXT,
|
||||
referenceOfTheAccountServicingInstitution TEXT,
|
||||
supplementaryDetails TEXT,
|
||||
|
||||
transactionReferenceNumber TEXT,
|
||||
relatedReferenceNumber TEXT
|
||||
);
|
||||
|
||||
|
||||
insertTransaction:
|
||||
INSERT INTO AccountTransaction(
|
||||
amount, currency, reference,
|
||||
bookingDate, valueDate,
|
||||
otherPartyName, otherPartyBankCode, otherPartyAccountId,
|
||||
bookingText,
|
||||
|
||||
userSetDisplayName, notes,
|
||||
|
||||
information,
|
||||
statementNumber, sequenceNumber,
|
||||
openingBalance, closingBalance,
|
||||
|
||||
endToEndReference, customerReference, mandateReference,
|
||||
creditorIdentifier, originatorsIdentificationCode,
|
||||
compensationAmount, originalAmount,
|
||||
sepaReference,
|
||||
deviantOriginator, deviantRecipient,
|
||||
referenceWithNoSpecialType,
|
||||
primaNotaNumber, textKeySupplement,
|
||||
|
||||
currencyType, bookingKey,
|
||||
referenceForTheAccountOwner, referenceOfTheAccountServicingInstitution,
|
||||
supplementaryDetails,
|
||||
|
||||
transactionReferenceNumber, relatedReferenceNumber
|
||||
)
|
||||
VALUES(
|
||||
?, ?, ?,
|
||||
?, ?,
|
||||
?, ?, ?,
|
||||
?,
|
||||
|
||||
?, ?,
|
||||
|
||||
?,
|
||||
?, ?,
|
||||
?, ?,
|
||||
|
||||
?, ?, ?,
|
||||
?, ?,
|
||||
?, ?,
|
||||
?,
|
||||
?, ?,
|
||||
?,
|
||||
?, ?,
|
||||
|
||||
?, ?,
|
||||
?, ?,
|
||||
?,
|
||||
|
||||
?, ?
|
||||
);
|
||||
|
||||
|
||||
selectAllTransactions:
|
||||
SELECT AccountTransaction.*
|
||||
FROM AccountTransaction;
|
|
@ -4,9 +4,15 @@ import androidx.compose.ui.Alignment
|
|||
import androidx.compose.ui.unit.DpSize
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.window.*
|
||||
import app.cash.sqldelight.async.coroutines.synchronous
|
||||
import app.cash.sqldelight.driver.jdbc.sqlite.JdbcSqliteDriver
|
||||
import bankmeister.composeapp.generated.resources.AppIcon_svg
|
||||
import bankmeister.composeapp.generated.resources.Res
|
||||
import net.codinux.banking.dataaccess.BankmeisterDb
|
||||
import net.codinux.banking.ui.config.DI
|
||||
import net.codinux.log.Log
|
||||
import org.jetbrains.compose.resources.painterResource
|
||||
import java.io.File
|
||||
|
||||
fun main() = application {
|
||||
Window(
|
||||
|
@ -15,6 +21,11 @@ fun main() = application {
|
|||
icon = painterResource(Res.drawable.AppIcon_svg),
|
||||
state = WindowState(position = WindowPosition(Alignment.Center), size = DpSize(900.dp, 800.dp)),
|
||||
) {
|
||||
File("data/db").mkdirs()
|
||||
DI.setRepository(JdbcSqliteDriver("jdbc:sqlite:data/db/Bankmeister.db").apply {
|
||||
val schema = BankmeisterDb.Schema.synchronous().create(this)
|
||||
})
|
||||
|
||||
App()
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
package net.codinux.banking.dataaccess
|
||||
|
||||
import app.cash.sqldelight.async.coroutines.synchronous
|
||||
import app.cash.sqldelight.driver.jdbc.sqlite.JdbcSqliteDriver
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import kotlinx.datetime.LocalDate
|
||||
import net.codinux.banking.client.model.AccountTransaction
|
||||
import net.codinux.banking.client.model.Amount
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertNotNull
|
||||
|
||||
class SqliteBankingRepositoryTest {
|
||||
|
||||
private val sqlDriver = JdbcSqliteDriver(JdbcSqliteDriver.IN_MEMORY).apply {
|
||||
BankmeisterDb.Schema.synchronous().create(this)
|
||||
}
|
||||
|
||||
private val underTest = SqliteBankingRepository(sqlDriver)
|
||||
|
||||
|
||||
@Test
|
||||
fun saveTransaction() = runBlocking {
|
||||
val transaction = AccountTransaction(Amount("12.45"), "EUR", "Lohn", LocalDate(2024, 5, 7), LocalDate(2024, 6, 15), "Dein Boss")
|
||||
|
||||
underTest.persistAccountTransactions(listOf(transaction))
|
||||
|
||||
val result = underTest.getAllAccountTransactions()
|
||||
|
||||
assertEquals(1, result.size)
|
||||
|
||||
val persisted = result.first()
|
||||
assertNotNull(persisted.id)
|
||||
|
||||
assertEquals(transaction.amount, persisted.amount)
|
||||
assertEquals(transaction.currency, persisted.currency)
|
||||
assertEquals(transaction.reference, persisted.reference)
|
||||
assertEquals(transaction.bookingDate, persisted.bookingDate)
|
||||
assertEquals(transaction.valueDate, persisted.valueDate)
|
||||
assertEquals(transaction.otherPartyName, persisted.otherPartyName)
|
||||
}
|
||||
|
||||
}
|
|
@ -1,5 +1,13 @@
|
|||
package net.codinux.banking.ui
|
||||
|
||||
import androidx.compose.ui.window.ComposeUIViewController
|
||||
import app.cash.sqldelight.async.coroutines.synchronous
|
||||
import app.cash.sqldelight.driver.native.NativeSqliteDriver
|
||||
import net.codinux.banking.dataaccess.BankmeisterDb
|
||||
import net.codinux.banking.ui.config.DI
|
||||
|
||||
fun MainViewController() = ComposeUIViewController { App() }
|
||||
fun MainViewController() = ComposeUIViewController {
|
||||
DI.setRepository(NativeSqliteDriver(Database.Schema.synchronous(), "Bankmeister.db"))
|
||||
|
||||
App()
|
||||
}
|
|
@ -10,6 +10,8 @@ kotlinx-serializable = "1.7.1"
|
|||
klf = "1.6.0"
|
||||
logback = "1.5.7"
|
||||
|
||||
sqlDelight = "2.0.2"
|
||||
|
||||
agp = "8.2.2"
|
||||
android-compileSdk = "34"
|
||||
android-minSdk = "24"
|
||||
|
@ -36,6 +38,13 @@ kotlinx-serializable = { group = "org.jetbrains.kotlinx", name = "kotlinx-serial
|
|||
klf = { group = "net.codinux.log", name = "klf", version.ref = "klf" }
|
||||
logback = { group = "ch.qos.logback", name = "logback-classic", version.ref = "logback" }
|
||||
|
||||
sqldelight-runtime = { module = "app.cash.sqldelight:runtime", version.ref = "sqlDelight" }
|
||||
sqldelight-coroutines-extensions = { module = "app.cash.sqldelight:coroutines-extensions", version.ref = "sqlDelight" }
|
||||
sqldelight-paging-extensions = { module = "app.cash.sqldelight:androidx-paging3-extensions", version.ref = "sqlDelight" }
|
||||
sqldelight-sqlite-driver = { module = "app.cash.sqldelight:sqlite-driver", version.ref = "sqlDelight" }
|
||||
sqldelight-android-driver = { module = "app.cash.sqldelight:android-driver", version.ref = "sqlDelight" }
|
||||
sqldelight-native-driver = { module = "app.cash.sqldelight:native-driver", version.ref = "sqlDelight" }
|
||||
|
||||
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "androidx-core-ktx" }
|
||||
androidx-test-junit = { group = "androidx.test.ext", name = "junit", version.ref = "androidx-test-junit" }
|
||||
androidx-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "androidx-espresso-core" }
|
||||
|
@ -57,4 +66,6 @@ kotlinxSerialization = { id = "org.jetbrains.kotlin.plugin.serialization", versi
|
|||
jetbrainsCompose = { id = "org.jetbrains.compose", version.ref = "compose-plugin" }
|
||||
compose-compiler = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
|
||||
androidLibrary = { id = "com.android.library", version.ref = "agp" }
|
||||
androidApplication = { id = "com.android.application", version.ref = "agp" }
|
||||
androidApplication = { id = "com.android.application", version.ref = "agp" }
|
||||
|
||||
sqldelight = { id = "app.cash.sqldelight", version.ref = "sqlDelight" }
|
Loading…
Reference in New Issue