From b39f9063129dc0d5e34db7fc99de2f1b6e4c1b66 Mon Sep 17 00:00:00 2001 From: Hekmatullah Date: Sun, 19 Jan 2025 17:46:26 +0000 Subject: [PATCH] feat(core:database): Migrate database module to KMP --- .../demoDebugRuntimeClasspath.txt | 15 +- .../demoReleaseRuntimeClasspath.txt | 15 +- .../prodDebugRuntimeClasspath.txt | 15 +- .../prodReleaseRuntimeClasspath.txt | 15 +- core/database/build.gradle.kts | 76 ++++++++- .../1.json | 160 ++++++++++++++++++ .../mobile/core/database/AppDatabase.kt} | 14 +- .../database/AppDatabaseFactory.android.kt | 28 +++ .../mobile/core/database/Room.android.kt | 34 ++++ .../core/database/TypeConverter.android.kt | 14 ++ .../database/di/DatabaseModule.android.kt | 25 +++ .../mifos/mobile/core/database/AppDatabase.kt | 24 +++ .../org/mifos/mobile/core/database/Room.kt | 71 ++++++++ .../mobile/core/database/TypeConverter.kt | 14 ++ .../mobile/core/database/dao/ChargeDao.kt | 11 +- .../core/database/dao/MifosNotificationDao.kt | 9 +- .../mobile/core/database/di/DatabaseModule.kt | 21 +++ .../entity/ChargeCalculationTypeEntity.kt | 0 .../core/database/entity/ChargeEntity.kt | 17 +- .../database/entity/ChargeListResponse.kt | 0 .../database/entity/ChargeTimeTypeEntity.kt | 0 .../core/database/entity/CurrencyEntity.kt | 0 .../entity/MifosNotificationEntity.kt | 20 ++- .../database/utils/ChargeTypeConverters.kt | 2 +- .../mifos/mobile/core/database/AppDatabase.kt | 48 ++++++ .../database/AppDatabaseFactory.desktop.kt | 35 ++++ .../mobile/core/database/Room.desktop.kt | 34 ++++ .../core/database/TypeConverter.desktop.kt | 14 ++ .../database/di/DatabaseModule.desktop.kt | 23 +++ .../mobile/core/database/AppDatabase.js.kt | 18 ++ .../mobile/core/database/TypeConverter.js.kt | 14 ++ .../core/database/di/DatabaseModule.js.kt | 15 ++ core/database/src/main/AndroidManifest.xml | 13 -- .../mobile/core/database/di/DaoModule.kt | 32 ---- .../mobile/core/database/di/DatabaseModule.kt | 35 ---- .../mifos/mobile/core/database/AppDatabase.kt | 47 +++++ .../database/AppDatabaseFactory.native.kt | 38 +++++ .../mifos/mobile/core/database/Room.native.kt | 34 ++++ .../core/database/TypeConverter.native.kt | 14 ++ .../core/database/di/DatabaseModule.native.kt | 23 +++ .../core/database/AppDatabase.wasmJs.kt | 18 ++ .../core/database/TypeConverter.wasmJs.kt | 14 ++ .../core/database/di/DatabaseModule.wasmJs.kt | 15 ++ gradle/libs.versions.toml | 15 +- 44 files changed, 955 insertions(+), 144 deletions(-) create mode 100644 core/database/schemas/org.mifos.mobile.core.database.AppDatabase/1.json rename core/database/src/{main/kotlin/org/mifos/mobile/core/database/SelfServiceDatabase.kt => androidMain/kotlin/org/mifos/mobile/core/database/AppDatabase.kt} (76%) create mode 100644 core/database/src/androidMain/kotlin/org/mifos/mobile/core/database/AppDatabaseFactory.android.kt create mode 100644 core/database/src/androidMain/kotlin/org/mifos/mobile/core/database/Room.android.kt create mode 100644 core/database/src/androidMain/kotlin/org/mifos/mobile/core/database/TypeConverter.android.kt create mode 100644 core/database/src/androidMain/kotlin/org/mifos/mobile/core/database/di/DatabaseModule.android.kt create mode 100644 core/database/src/commonMain/kotlin/org/mifos/mobile/core/database/AppDatabase.kt create mode 100644 core/database/src/commonMain/kotlin/org/mifos/mobile/core/database/Room.kt create mode 100644 core/database/src/commonMain/kotlin/org/mifos/mobile/core/database/TypeConverter.kt rename core/database/src/{main => commonMain}/kotlin/org/mifos/mobile/core/database/dao/ChargeDao.kt (73%) rename core/database/src/{main => commonMain}/kotlin/org/mifos/mobile/core/database/dao/MifosNotificationDao.kt (84%) create mode 100644 core/database/src/commonMain/kotlin/org/mifos/mobile/core/database/di/DatabaseModule.kt rename core/database/src/{main => commonMain}/kotlin/org/mifos/mobile/core/database/entity/ChargeCalculationTypeEntity.kt (100%) rename core/database/src/{main => commonMain}/kotlin/org/mifos/mobile/core/database/entity/ChargeEntity.kt (75%) rename core/database/src/{main => commonMain}/kotlin/org/mifos/mobile/core/database/entity/ChargeListResponse.kt (100%) rename core/database/src/{main => commonMain}/kotlin/org/mifos/mobile/core/database/entity/ChargeTimeTypeEntity.kt (100%) rename core/database/src/{main => commonMain}/kotlin/org/mifos/mobile/core/database/entity/CurrencyEntity.kt (100%) rename core/database/src/{main => commonMain}/kotlin/org/mifos/mobile/core/database/entity/MifosNotificationEntity.kt (52%) rename core/database/src/{main => commonMain}/kotlin/org/mifos/mobile/core/database/utils/ChargeTypeConverters.kt (97%) create mode 100644 core/database/src/desktopMain/kotlin/org/mifos/mobile/core/database/AppDatabase.kt create mode 100644 core/database/src/desktopMain/kotlin/org/mifos/mobile/core/database/AppDatabaseFactory.desktop.kt create mode 100644 core/database/src/desktopMain/kotlin/org/mifos/mobile/core/database/Room.desktop.kt create mode 100644 core/database/src/desktopMain/kotlin/org/mifos/mobile/core/database/TypeConverter.desktop.kt create mode 100644 core/database/src/desktopMain/kotlin/org/mifos/mobile/core/database/di/DatabaseModule.desktop.kt create mode 100644 core/database/src/jsMain/kotlin/org/mifos/mobile/core/database/AppDatabase.js.kt create mode 100644 core/database/src/jsMain/kotlin/org/mifos/mobile/core/database/TypeConverter.js.kt create mode 100644 core/database/src/jsMain/kotlin/org/mifos/mobile/core/database/di/DatabaseModule.js.kt delete mode 100644 core/database/src/main/AndroidManifest.xml delete mode 100644 core/database/src/main/kotlin/org/mifos/mobile/core/database/di/DaoModule.kt delete mode 100644 core/database/src/main/kotlin/org/mifos/mobile/core/database/di/DatabaseModule.kt create mode 100644 core/database/src/nativeMain/kotlin/org/mifos/mobile/core/database/AppDatabase.kt create mode 100644 core/database/src/nativeMain/kotlin/org/mifos/mobile/core/database/AppDatabaseFactory.native.kt create mode 100644 core/database/src/nativeMain/kotlin/org/mifos/mobile/core/database/Room.native.kt create mode 100644 core/database/src/nativeMain/kotlin/org/mifos/mobile/core/database/TypeConverter.native.kt create mode 100644 core/database/src/nativeMain/kotlin/org/mifos/mobile/core/database/di/DatabaseModule.native.kt create mode 100644 core/database/src/wasmJsMain/kotlin/org/mifos/mobile/core/database/AppDatabase.wasmJs.kt create mode 100644 core/database/src/wasmJsMain/kotlin/org/mifos/mobile/core/database/TypeConverter.wasmJs.kt create mode 100644 core/database/src/wasmJsMain/kotlin/org/mifos/mobile/core/database/di/DatabaseModule.wasmJs.kt diff --git a/androidApp/dependencies/demoDebugRuntimeClasspath.txt b/androidApp/dependencies/demoDebugRuntimeClasspath.txt index 9cba9db29..164c52595 100644 --- a/androidApp/dependencies/demoDebugRuntimeClasspath.txt +++ b/androidApp/dependencies/demoDebugRuntimeClasspath.txt @@ -113,13 +113,18 @@ androidx.privacysandbox.ads:ads-adservices-java:1.0.0-beta05 androidx.privacysandbox.ads:ads-adservices:1.0.0-beta05 androidx.profileinstaller:profileinstaller:1.4.1 androidx.resourceinspection:resourceinspection-annotation:1.0.1 -androidx.room:room-common:2.6.1 -androidx.room:room-ktx:2.6.1 -androidx.room:room-runtime:2.6.1 +androidx.room:room-common-jvm:2.7.0-alpha12 +androidx.room:room-common:2.7.0-alpha12 +androidx.room:room-runtime-android:2.7.0-alpha12 +androidx.room:room-runtime:2.7.0-alpha12 androidx.savedstate:savedstate-ktx:1.2.1 androidx.savedstate:savedstate:1.2.1 -androidx.sqlite:sqlite-framework:2.4.0 -androidx.sqlite:sqlite:2.4.0 +androidx.sqlite:sqlite-android:2.5.0-alpha12 +androidx.sqlite:sqlite-bundled-android:2.5.0-alpha12 +androidx.sqlite:sqlite-bundled:2.5.0-alpha12 +androidx.sqlite:sqlite-framework-android:2.5.0-alpha12 +androidx.sqlite:sqlite-framework:2.5.0-alpha12 +androidx.sqlite:sqlite:2.5.0-alpha12 androidx.startup:startup-runtime:1.1.1 androidx.tracing:tracing-ktx:1.2.0 androidx.tracing:tracing:1.2.0 diff --git a/androidApp/dependencies/demoReleaseRuntimeClasspath.txt b/androidApp/dependencies/demoReleaseRuntimeClasspath.txt index e793251a4..4b31106fc 100644 --- a/androidApp/dependencies/demoReleaseRuntimeClasspath.txt +++ b/androidApp/dependencies/demoReleaseRuntimeClasspath.txt @@ -108,13 +108,18 @@ androidx.privacysandbox.ads:ads-adservices-java:1.0.0-beta05 androidx.privacysandbox.ads:ads-adservices:1.0.0-beta05 androidx.profileinstaller:profileinstaller:1.4.1 androidx.resourceinspection:resourceinspection-annotation:1.0.1 -androidx.room:room-common:2.6.1 -androidx.room:room-ktx:2.6.1 -androidx.room:room-runtime:2.6.1 +androidx.room:room-common-jvm:2.7.0-alpha12 +androidx.room:room-common:2.7.0-alpha12 +androidx.room:room-runtime-android:2.7.0-alpha12 +androidx.room:room-runtime:2.7.0-alpha12 androidx.savedstate:savedstate-ktx:1.2.1 androidx.savedstate:savedstate:1.2.1 -androidx.sqlite:sqlite-framework:2.4.0 -androidx.sqlite:sqlite:2.4.0 +androidx.sqlite:sqlite-android:2.5.0-alpha12 +androidx.sqlite:sqlite-bundled-android:2.5.0-alpha12 +androidx.sqlite:sqlite-bundled:2.5.0-alpha12 +androidx.sqlite:sqlite-framework-android:2.5.0-alpha12 +androidx.sqlite:sqlite-framework:2.5.0-alpha12 +androidx.sqlite:sqlite:2.5.0-alpha12 androidx.startup:startup-runtime:1.1.1 androidx.tracing:tracing-ktx:1.2.0 androidx.tracing:tracing:1.2.0 diff --git a/androidApp/dependencies/prodDebugRuntimeClasspath.txt b/androidApp/dependencies/prodDebugRuntimeClasspath.txt index 9cba9db29..164c52595 100644 --- a/androidApp/dependencies/prodDebugRuntimeClasspath.txt +++ b/androidApp/dependencies/prodDebugRuntimeClasspath.txt @@ -113,13 +113,18 @@ androidx.privacysandbox.ads:ads-adservices-java:1.0.0-beta05 androidx.privacysandbox.ads:ads-adservices:1.0.0-beta05 androidx.profileinstaller:profileinstaller:1.4.1 androidx.resourceinspection:resourceinspection-annotation:1.0.1 -androidx.room:room-common:2.6.1 -androidx.room:room-ktx:2.6.1 -androidx.room:room-runtime:2.6.1 +androidx.room:room-common-jvm:2.7.0-alpha12 +androidx.room:room-common:2.7.0-alpha12 +androidx.room:room-runtime-android:2.7.0-alpha12 +androidx.room:room-runtime:2.7.0-alpha12 androidx.savedstate:savedstate-ktx:1.2.1 androidx.savedstate:savedstate:1.2.1 -androidx.sqlite:sqlite-framework:2.4.0 -androidx.sqlite:sqlite:2.4.0 +androidx.sqlite:sqlite-android:2.5.0-alpha12 +androidx.sqlite:sqlite-bundled-android:2.5.0-alpha12 +androidx.sqlite:sqlite-bundled:2.5.0-alpha12 +androidx.sqlite:sqlite-framework-android:2.5.0-alpha12 +androidx.sqlite:sqlite-framework:2.5.0-alpha12 +androidx.sqlite:sqlite:2.5.0-alpha12 androidx.startup:startup-runtime:1.1.1 androidx.tracing:tracing-ktx:1.2.0 androidx.tracing:tracing:1.2.0 diff --git a/androidApp/dependencies/prodReleaseRuntimeClasspath.txt b/androidApp/dependencies/prodReleaseRuntimeClasspath.txt index e793251a4..4b31106fc 100644 --- a/androidApp/dependencies/prodReleaseRuntimeClasspath.txt +++ b/androidApp/dependencies/prodReleaseRuntimeClasspath.txt @@ -108,13 +108,18 @@ androidx.privacysandbox.ads:ads-adservices-java:1.0.0-beta05 androidx.privacysandbox.ads:ads-adservices:1.0.0-beta05 androidx.profileinstaller:profileinstaller:1.4.1 androidx.resourceinspection:resourceinspection-annotation:1.0.1 -androidx.room:room-common:2.6.1 -androidx.room:room-ktx:2.6.1 -androidx.room:room-runtime:2.6.1 +androidx.room:room-common-jvm:2.7.0-alpha12 +androidx.room:room-common:2.7.0-alpha12 +androidx.room:room-runtime-android:2.7.0-alpha12 +androidx.room:room-runtime:2.7.0-alpha12 androidx.savedstate:savedstate-ktx:1.2.1 androidx.savedstate:savedstate:1.2.1 -androidx.sqlite:sqlite-framework:2.4.0 -androidx.sqlite:sqlite:2.4.0 +androidx.sqlite:sqlite-android:2.5.0-alpha12 +androidx.sqlite:sqlite-bundled-android:2.5.0-alpha12 +androidx.sqlite:sqlite-bundled:2.5.0-alpha12 +androidx.sqlite:sqlite-framework-android:2.5.0-alpha12 +androidx.sqlite:sqlite-framework:2.5.0-alpha12 +androidx.sqlite:sqlite:2.5.0-alpha12 androidx.startup:startup-runtime:1.1.1 androidx.tracing:tracing-ktx:1.2.0 androidx.tracing:tracing:1.2.0 diff --git a/core/database/build.gradle.kts b/core/database/build.gradle.kts index 54518e929..c885f978b 100644 --- a/core/database/build.gradle.kts +++ b/core/database/build.gradle.kts @@ -1,3 +1,18 @@ +/* + * Copyright 2024 Mifos Initiative + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * See https://github.com/openMF/mobile-mobile/blob/master/LICENSE.md + */ + +import org.jetbrains.kotlin.gradle.ExperimentalKotlinGradlePluginApi +import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl +import org.jetbrains.kotlin.gradle.dsl.JvmTarget +import org.jetbrains.kotlin.gradle.plugin.mpp.apple.XCFramework + /* * Copyright 2024 Mifos Initiative * @@ -8,22 +23,71 @@ * See https://github.com/openMF/mobile-mobile/blob/master/LICENSE.md */ plugins { - alias(libs.plugins.mifos.android.library) - alias(libs.plugins.mifos.android.room) - alias(libs.plugins.mifos.android.hilt) + alias(libs.plugins.mifos.kmp.library) alias(libs.plugins.kotlin.serialization) + alias(libs.plugins.room) + alias(libs.plugins.ksp) } android { namespace = "org.mifos.mobile.core.database" + compileSdk = 35 defaultConfig { consumerProguardFiles("consumer-rules.pro") } + buildTypes { + getByName("release") { + isMinifyEnabled = false + } + } + compileOptions { + sourceCompatibility = JavaVersion.VERSION_17 + targetCompatibility = JavaVersion.VERSION_17 + } } -dependencies { - implementation(libs.kotlinx.coroutines.core) - implementation(libs.kotlinx.serialization.json) +kotlin { + + room { + schemaDirectory("$projectDir/schemas") + } + + sourceSets { + val desktopMain by getting + + androidMain.dependencies { + implementation(libs.koin.android) + implementation(libs.androidx.room.runtime) + implementation(libs.androidx.sqlite.bundled) + } + + nativeMain.dependencies { + implementation(libs.androidx.room.runtime) + implementation(libs.androidx.sqlite.bundled) + } + + desktopMain.dependencies { + implementation(libs.androidx.room.runtime) + implementation(libs.androidx.sqlite.bundled) + } + + commonMain.dependencies { + implementation(libs.kotlinx.coroutines.core) + implementation(libs.kotlinx.serialization.json) + } + + dependencies { + listOf( + "kspAndroid", + "kspIosArm64", + "kspIosX64", + "kspIosSimulatorArm64", + // Add any other platform you may support + ).forEach { + add(it, libs.androidx.room.compiler) + } + } + } } \ No newline at end of file diff --git a/core/database/schemas/org.mifos.mobile.core.database.AppDatabase/1.json b/core/database/schemas/org.mifos.mobile.core.database.AppDatabase/1.json new file mode 100644 index 000000000..ce9897648 --- /dev/null +++ b/core/database/schemas/org.mifos.mobile.core.database.AppDatabase/1.json @@ -0,0 +1,160 @@ +{ + "formatVersion": 1, + "database": { + "version": 1, + "identityHash": "534bff4d0668aa4c7b843d255397b445", + "entities": [ + { + "tableName": "charges", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER, `clientId` INTEGER, `chargeId` INTEGER, `name` TEXT, `dueDate` TEXT NOT NULL, `chargeTimeType` TEXT, `chargeCalculationType` TEXT, `currency` TEXT, `amount` REAL NOT NULL, `amountPaid` REAL NOT NULL, `amountWaived` REAL NOT NULL, `amountWrittenOff` REAL NOT NULL, `amountOutstanding` REAL NOT NULL, `penalty` INTEGER NOT NULL, `isActive` INTEGER NOT NULL, `isChargePaid` INTEGER NOT NULL, `isChargeWaived` INTEGER NOT NULL, `paid` INTEGER NOT NULL, `waived` INTEGER NOT NULL, PRIMARY KEY(`id`))", + "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER" + }, + { + "fieldPath": "clientId", + "columnName": "clientId", + "affinity": "INTEGER" + }, + { + "fieldPath": "chargeId", + "columnName": "chargeId", + "affinity": "INTEGER" + }, + { + "fieldPath": "name", + "columnName": "name", + "affinity": "TEXT" + }, + { + "fieldPath": "dueDate", + "columnName": "dueDate", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "chargeTimeType", + "columnName": "chargeTimeType", + "affinity": "TEXT" + }, + { + "fieldPath": "chargeCalculationType", + "columnName": "chargeCalculationType", + "affinity": "TEXT" + }, + { + "fieldPath": "currency", + "columnName": "currency", + "affinity": "TEXT" + }, + { + "fieldPath": "amount", + "columnName": "amount", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "amountPaid", + "columnName": "amountPaid", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "amountWaived", + "columnName": "amountWaived", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "amountWrittenOff", + "columnName": "amountWrittenOff", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "amountOutstanding", + "columnName": "amountOutstanding", + "affinity": "REAL", + "notNull": true + }, + { + "fieldPath": "penalty", + "columnName": "penalty", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isActive", + "columnName": "isActive", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isChargePaid", + "columnName": "isChargePaid", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "isChargeWaived", + "columnName": "isChargeWaived", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "paid", + "columnName": "paid", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "waived", + "columnName": "waived", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "id" + ] + } + }, + { + "tableName": "mifos_notification", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`timeStamp` INTEGER NOT NULL, `msg` TEXT, `read` INTEGER, PRIMARY KEY(`timeStamp`))", + "fields": [ + { + "fieldPath": "timeStamp", + "columnName": "timeStamp", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "msg", + "columnName": "msg", + "affinity": "TEXT" + }, + { + "fieldPath": "read", + "columnName": "read", + "affinity": "INTEGER" + } + ], + "primaryKey": { + "autoGenerate": false, + "columnNames": [ + "timeStamp" + ] + } + } + ], + "setupQueries": [ + "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '534bff4d0668aa4c7b843d255397b445')" + ] + } +} \ No newline at end of file diff --git a/core/database/src/main/kotlin/org/mifos/mobile/core/database/SelfServiceDatabase.kt b/core/database/src/androidMain/kotlin/org/mifos/mobile/core/database/AppDatabase.kt similarity index 76% rename from core/database/src/main/kotlin/org/mifos/mobile/core/database/SelfServiceDatabase.kt rename to core/database/src/androidMain/kotlin/org/mifos/mobile/core/database/AppDatabase.kt index 9aa1ed6c3..6eedd2d47 100644 --- a/core/database/src/main/kotlin/org/mifos/mobile/core/database/SelfServiceDatabase.kt +++ b/core/database/src/androidMain/kotlin/org/mifos/mobile/core/database/AppDatabase.kt @@ -1,5 +1,5 @@ /* - * Copyright 2024 Mifos Initiative + * Copyright 2025 Mifos Initiative * * This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this @@ -23,19 +23,17 @@ import org.mifos.mobile.core.database.utils.ChargeTypeConverters ChargeEntity::class, MifosNotificationEntity::class, ], - version = SelfServiceDatabase.VERSION, + version = AppDatabase.VERSION, exportSchema = true, autoMigrations = [], ) @TypeConverters(ChargeTypeConverters::class) -abstract class SelfServiceDatabase : RoomDatabase() { - - abstract fun mifosNotificationDao(): MifosNotificationDao - - abstract fun chargeDao(): ChargeDao +actual abstract class AppDatabase : RoomDatabase() { + actual abstract val mifosNotificationDao: MifosNotificationDao + actual abstract val chargeDao: ChargeDao companion object { - // Update the version number if you change the schema const val VERSION = 1 + const val DATABASE_NAME = "mifos_database.db" } } diff --git a/core/database/src/androidMain/kotlin/org/mifos/mobile/core/database/AppDatabaseFactory.android.kt b/core/database/src/androidMain/kotlin/org/mifos/mobile/core/database/AppDatabaseFactory.android.kt new file mode 100644 index 000000000..a098e2dc0 --- /dev/null +++ b/core/database/src/androidMain/kotlin/org/mifos/mobile/core/database/AppDatabaseFactory.android.kt @@ -0,0 +1,28 @@ +/* + * Copyright 2025 Mifos Initiative + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * See https://github.com/openMF/mobile-mobile/blob/master/LICENSE.md + */ +package org.mifos.mobile.core.database + +import android.content.Context +import androidx.room.Room +import androidx.room.RoomDatabase + +class AppDatabaseFactory( + private val context: Context, +) { + fun createDatabase(): RoomDatabase.Builder { + val appContext = context.applicationContext + val dbFile = appContext.getDatabasePath(AppDatabase.DATABASE_NAME) + + return Room.databaseBuilder( + context = appContext, + name = dbFile.absolutePath, + ) + } +} diff --git a/core/database/src/androidMain/kotlin/org/mifos/mobile/core/database/Room.android.kt b/core/database/src/androidMain/kotlin/org/mifos/mobile/core/database/Room.android.kt new file mode 100644 index 000000000..d89e08245 --- /dev/null +++ b/core/database/src/androidMain/kotlin/org/mifos/mobile/core/database/Room.android.kt @@ -0,0 +1,34 @@ +/* + * Copyright 2025 Mifos Initiative + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * See https://github.com/openMF/mobile-mobile/blob/master/LICENSE.md + */ +package org.mifos.mobile.core.database + +import androidx.room.Dao +import androidx.room.Entity +import androidx.room.ForeignKey +import androidx.room.Index +import androidx.room.Insert +import androidx.room.PrimaryKey +import androidx.room.Query + +actual typealias Dao = Dao + +actual typealias Query = Query + +actual typealias Insert = Insert + +actual typealias PrimaryKey = PrimaryKey + +actual typealias ForeignKey = ForeignKey + +actual typealias Index = Index + +actual typealias Entity = Entity + +// actual typealias OnConflictStrategy = OnConflictStrategy diff --git a/core/database/src/androidMain/kotlin/org/mifos/mobile/core/database/TypeConverter.android.kt b/core/database/src/androidMain/kotlin/org/mifos/mobile/core/database/TypeConverter.android.kt new file mode 100644 index 000000000..1571791a8 --- /dev/null +++ b/core/database/src/androidMain/kotlin/org/mifos/mobile/core/database/TypeConverter.android.kt @@ -0,0 +1,14 @@ +/* + * Copyright 2025 Mifos Initiative + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * See https://github.com/openMF/mobile-mobile/blob/master/LICENSE.md + */ +package org.mifos.mobile.core.database + +import androidx.room.TypeConverter + +actual typealias TypeConverter = TypeConverter diff --git a/core/database/src/androidMain/kotlin/org/mifos/mobile/core/database/di/DatabaseModule.android.kt b/core/database/src/androidMain/kotlin/org/mifos/mobile/core/database/di/DatabaseModule.android.kt new file mode 100644 index 000000000..a07286b04 --- /dev/null +++ b/core/database/src/androidMain/kotlin/org/mifos/mobile/core/database/di/DatabaseModule.android.kt @@ -0,0 +1,25 @@ +/* + * Copyright 2025 Mifos Initiative + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * See https://github.com/openMF/mobile-mobile/blob/master/LICENSE.md + */ +package org.mifos.mobile.core.database.di + +import androidx.sqlite.driver.bundled.BundledSQLiteDriver +import org.koin.android.ext.koin.androidApplication +import org.koin.core.module.Module +import org.koin.dsl.module +import org.mifos.mobile.core.database.AppDatabaseFactory + +actual val platformModule: Module = module { + single { + AppDatabaseFactory(androidApplication()) + .createDatabase() + .setDriver(BundledSQLiteDriver()) + .build() + } +} diff --git a/core/database/src/commonMain/kotlin/org/mifos/mobile/core/database/AppDatabase.kt b/core/database/src/commonMain/kotlin/org/mifos/mobile/core/database/AppDatabase.kt new file mode 100644 index 000000000..d68e658b2 --- /dev/null +++ b/core/database/src/commonMain/kotlin/org/mifos/mobile/core/database/AppDatabase.kt @@ -0,0 +1,24 @@ +/* + * Copyright 2025 Mifos Initiative + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * See https://github.com/openMF/mobile-mobile/blob/master/LICENSE.md + */ +package org.mifos.mobile.core.database + +import org.mifos.mobile.core.database.dao.ChargeDao +import org.mifos.mobile.core.database.dao.MifosNotificationDao + +expect abstract class AppDatabase { + abstract val mifosNotificationDao: MifosNotificationDao + abstract val chargeDao: ChargeDao +} + +// fun getRoomDatabase( +// appDatabase: AppDatabase, +// ): AppDatabase { +// return appDatabase +// } diff --git a/core/database/src/commonMain/kotlin/org/mifos/mobile/core/database/Room.kt b/core/database/src/commonMain/kotlin/org/mifos/mobile/core/database/Room.kt new file mode 100644 index 000000000..c6f196cce --- /dev/null +++ b/core/database/src/commonMain/kotlin/org/mifos/mobile/core/database/Room.kt @@ -0,0 +1,71 @@ +/* + * Copyright 2025 Mifos Initiative + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * See https://github.com/openMF/mobile-mobile/blob/master/LICENSE.md + */ +package org.mifos.mobile.core.database + +import kotlin.reflect.KClass + +@Suppress("NO_ACTUAL_FOR_EXPECT") +expect annotation class Dao() + +@Suppress("NO_ACTUAL_FOR_EXPECT") +@Target(AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY_GETTER) +@Retention(AnnotationRetention.BINARY) +expect annotation class Query( + val value: String, +) + +// @Suppress("NO_ACTUAL_FOR_EXPECT") +// expect annotation class OnConflictStrategy { +// companion object { +// val NONE: Int +// val REPLACE: Int +// val ROLLBACK: Int +// val ABORT: Int +// val FAIL: Int +// val IGNORE: Int +// } +// } + +@Suppress("NO_ACTUAL_FOR_EXPECT") +@Target(AnnotationTarget.FUNCTION) +@Retention(AnnotationRetention.BINARY) +expect annotation class Insert( + val entity: KClass<*>, + val onConflict: Int, +) + +@Suppress("NO_ACTUAL_FOR_EXPECT") +@Target(AnnotationTarget.FIELD, AnnotationTarget.FUNCTION) +@Retention(AnnotationRetention.BINARY) +expect annotation class PrimaryKey( + val autoGenerate: Boolean, +) + +@Suppress("NO_ACTUAL_FOR_EXPECT") +@Target(allowedTargets = []) // Complex annotation target +@Retention(AnnotationRetention.BINARY) +expect annotation class ForeignKey + +@Suppress("NO_ACTUAL_FOR_EXPECT") +@Target(allowedTargets = []) // Complex annotation target +@Retention(AnnotationRetention.BINARY) +expect annotation class Index + +@Suppress("NO_ACTUAL_FOR_EXPECT") +@Target(AnnotationTarget.CLASS) +@Retention(AnnotationRetention.BINARY) +expect annotation class Entity( + val tableName: String, + val indices: Array, + val inheritSuperIndices: Boolean, + val primaryKeys: Array, + val foreignKeys: Array, + val ignoredColumns: Array, +) diff --git a/core/database/src/commonMain/kotlin/org/mifos/mobile/core/database/TypeConverter.kt b/core/database/src/commonMain/kotlin/org/mifos/mobile/core/database/TypeConverter.kt new file mode 100644 index 000000000..9fd2bebe5 --- /dev/null +++ b/core/database/src/commonMain/kotlin/org/mifos/mobile/core/database/TypeConverter.kt @@ -0,0 +1,14 @@ +/* + * Copyright 2025 Mifos Initiative + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * See https://github.com/openMF/mobile-mobile/blob/master/LICENSE.md + */ +package org.mifos.mobile.core.database + +@Target(AnnotationTarget.FUNCTION) +@Retention(AnnotationRetention.BINARY) +expect annotation class TypeConverter() diff --git a/core/database/src/main/kotlin/org/mifos/mobile/core/database/dao/ChargeDao.kt b/core/database/src/commonMain/kotlin/org/mifos/mobile/core/database/dao/ChargeDao.kt similarity index 73% rename from core/database/src/main/kotlin/org/mifos/mobile/core/database/dao/ChargeDao.kt rename to core/database/src/commonMain/kotlin/org/mifos/mobile/core/database/dao/ChargeDao.kt index c17238c56..0100244a9 100644 --- a/core/database/src/main/kotlin/org/mifos/mobile/core/database/dao/ChargeDao.kt +++ b/core/database/src/commonMain/kotlin/org/mifos/mobile/core/database/dao/ChargeDao.kt @@ -9,11 +9,10 @@ */ package org.mifos.mobile.core.database.dao -import androidx.room.Dao -import androidx.room.Insert -import androidx.room.OnConflictStrategy -import androidx.room.Query import kotlinx.coroutines.flow.Flow +import org.mifos.mobile.core.database.Dao +import org.mifos.mobile.core.database.Insert +import org.mifos.mobile.core.database.Query import org.mifos.mobile.core.database.entity.ChargeEntity @Dao @@ -22,9 +21,9 @@ interface ChargeDao { @Query("SELECT * FROM charges") fun getAllLocalCharges(): Flow> - @Insert(onConflict = OnConflictStrategy.REPLACE) + @Insert(entity = ChargeEntity::class, onConflict = 1) suspend fun insertCharge(charge: List) - @Insert(onConflict = OnConflictStrategy.REPLACE) + @Insert(entity = ChargeEntity::class, onConflict = 1) suspend fun syncCharges(charges: List) } diff --git a/core/database/src/main/kotlin/org/mifos/mobile/core/database/dao/MifosNotificationDao.kt b/core/database/src/commonMain/kotlin/org/mifos/mobile/core/database/dao/MifosNotificationDao.kt similarity index 84% rename from core/database/src/main/kotlin/org/mifos/mobile/core/database/dao/MifosNotificationDao.kt rename to core/database/src/commonMain/kotlin/org/mifos/mobile/core/database/dao/MifosNotificationDao.kt index 071ea5eae..94cdf43a8 100644 --- a/core/database/src/main/kotlin/org/mifos/mobile/core/database/dao/MifosNotificationDao.kt +++ b/core/database/src/commonMain/kotlin/org/mifos/mobile/core/database/dao/MifosNotificationDao.kt @@ -9,11 +9,10 @@ */ package org.mifos.mobile.core.database.dao -import androidx.room.Dao -import androidx.room.Insert -import androidx.room.OnConflictStrategy -import androidx.room.Query import kotlinx.coroutines.flow.Flow +import org.mifos.mobile.core.database.Dao +import org.mifos.mobile.core.database.Insert +import org.mifos.mobile.core.database.Query import org.mifos.mobile.core.database.entity.MifosNotificationEntity @Dao @@ -25,7 +24,7 @@ interface MifosNotificationDao { @Query("SELECT COUNT(*) FROM mifos_notifications WHERE read = 0") fun getUnreadNotificationsCount(): Flow - @Insert(onConflict = OnConflictStrategy.REPLACE) + @Insert(entity = MifosNotificationEntity::class, onConflict = 1) suspend fun saveNotification(notification: MifosNotificationEntity) @Query("DELETE FROM mifos_notifications WHERE timeStamp < :cutoffTime") diff --git a/core/database/src/commonMain/kotlin/org/mifos/mobile/core/database/di/DatabaseModule.kt b/core/database/src/commonMain/kotlin/org/mifos/mobile/core/database/di/DatabaseModule.kt new file mode 100644 index 000000000..01e02f9a4 --- /dev/null +++ b/core/database/src/commonMain/kotlin/org/mifos/mobile/core/database/di/DatabaseModule.kt @@ -0,0 +1,21 @@ +/* + * Copyright 2024 Mifos Initiative + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * See https://github.com/openMF/mobile-mobile/blob/master/LICENSE.md + */ +package org.mifos.mobile.core.database.di + +import org.koin.core.module.Module +import org.koin.dsl.module +import org.mifos.mobile.core.database.AppDatabase + +expect val platformModule: Module + +val sharedModule = module { + single { get().chargeDao } + single { get().mifosNotificationDao } +} diff --git a/core/database/src/main/kotlin/org/mifos/mobile/core/database/entity/ChargeCalculationTypeEntity.kt b/core/database/src/commonMain/kotlin/org/mifos/mobile/core/database/entity/ChargeCalculationTypeEntity.kt similarity index 100% rename from core/database/src/main/kotlin/org/mifos/mobile/core/database/entity/ChargeCalculationTypeEntity.kt rename to core/database/src/commonMain/kotlin/org/mifos/mobile/core/database/entity/ChargeCalculationTypeEntity.kt diff --git a/core/database/src/main/kotlin/org/mifos/mobile/core/database/entity/ChargeEntity.kt b/core/database/src/commonMain/kotlin/org/mifos/mobile/core/database/entity/ChargeEntity.kt similarity index 75% rename from core/database/src/main/kotlin/org/mifos/mobile/core/database/entity/ChargeEntity.kt rename to core/database/src/commonMain/kotlin/org/mifos/mobile/core/database/entity/ChargeEntity.kt index 5077fcfa8..8c6d316ce 100644 --- a/core/database/src/main/kotlin/org/mifos/mobile/core/database/entity/ChargeEntity.kt +++ b/core/database/src/commonMain/kotlin/org/mifos/mobile/core/database/entity/ChargeEntity.kt @@ -9,17 +9,24 @@ */ package org.mifos.mobile.core.database.entity -import androidx.room.Entity -import androidx.room.PrimaryKey +import org.mifos.mobile.core.database.Entity +import org.mifos.mobile.core.database.PrimaryKey -@Entity(tableName = "charges") +@Entity( + tableName = "charges", + indices = [], + inheritSuperIndices = false, + primaryKeys = [], + foreignKeys = [], + ignoredColumns = [], +) data class ChargeEntity( - @PrimaryKey(autoGenerate = true) + @PrimaryKey(autoGenerate = false) val id: Int? = null, val clientId: Int? = null, val chargeId: Int? = null, val name: String? = null, - val dueDate: ArrayList = ArrayList(), + val dueDate: ArrayList = arrayListOf(), val chargeTimeType: ChargeTimeTypeEntity? = null, val chargeCalculationType: ChargeCalculationTypeEntity? = null, val currency: CurrencyEntity? = null, diff --git a/core/database/src/main/kotlin/org/mifos/mobile/core/database/entity/ChargeListResponse.kt b/core/database/src/commonMain/kotlin/org/mifos/mobile/core/database/entity/ChargeListResponse.kt similarity index 100% rename from core/database/src/main/kotlin/org/mifos/mobile/core/database/entity/ChargeListResponse.kt rename to core/database/src/commonMain/kotlin/org/mifos/mobile/core/database/entity/ChargeListResponse.kt diff --git a/core/database/src/main/kotlin/org/mifos/mobile/core/database/entity/ChargeTimeTypeEntity.kt b/core/database/src/commonMain/kotlin/org/mifos/mobile/core/database/entity/ChargeTimeTypeEntity.kt similarity index 100% rename from core/database/src/main/kotlin/org/mifos/mobile/core/database/entity/ChargeTimeTypeEntity.kt rename to core/database/src/commonMain/kotlin/org/mifos/mobile/core/database/entity/ChargeTimeTypeEntity.kt diff --git a/core/database/src/main/kotlin/org/mifos/mobile/core/database/entity/CurrencyEntity.kt b/core/database/src/commonMain/kotlin/org/mifos/mobile/core/database/entity/CurrencyEntity.kt similarity index 100% rename from core/database/src/main/kotlin/org/mifos/mobile/core/database/entity/CurrencyEntity.kt rename to core/database/src/commonMain/kotlin/org/mifos/mobile/core/database/entity/CurrencyEntity.kt diff --git a/core/database/src/main/kotlin/org/mifos/mobile/core/database/entity/MifosNotificationEntity.kt b/core/database/src/commonMain/kotlin/org/mifos/mobile/core/database/entity/MifosNotificationEntity.kt similarity index 52% rename from core/database/src/main/kotlin/org/mifos/mobile/core/database/entity/MifosNotificationEntity.kt rename to core/database/src/commonMain/kotlin/org/mifos/mobile/core/database/entity/MifosNotificationEntity.kt index 862de6be2..b533aabfb 100644 --- a/core/database/src/main/kotlin/org/mifos/mobile/core/database/entity/MifosNotificationEntity.kt +++ b/core/database/src/commonMain/kotlin/org/mifos/mobile/core/database/entity/MifosNotificationEntity.kt @@ -9,12 +9,20 @@ */ package org.mifos.mobile.core.database.entity -import androidx.room.Entity -import androidx.room.PrimaryKey +import org.mifos.mobile.core.database.Entity +import org.mifos.mobile.core.database.PrimaryKey -@Entity(tableName = "mifos_notifications") +@Entity( + tableName = "mifos_notification", + indices = [], + inheritSuperIndices = false, + primaryKeys = [], + foreignKeys = [], + ignoredColumns = [], +) data class MifosNotificationEntity( - @PrimaryKey val timeStamp: Long, - val msg: String? = null, - val read: Boolean? = null, + @PrimaryKey(autoGenerate = false) + val timeStamp: Long, + val msg: String?, + val read: Boolean?, ) diff --git a/core/database/src/main/kotlin/org/mifos/mobile/core/database/utils/ChargeTypeConverters.kt b/core/database/src/commonMain/kotlin/org/mifos/mobile/core/database/utils/ChargeTypeConverters.kt similarity index 97% rename from core/database/src/main/kotlin/org/mifos/mobile/core/database/utils/ChargeTypeConverters.kt rename to core/database/src/commonMain/kotlin/org/mifos/mobile/core/database/utils/ChargeTypeConverters.kt index 137a04995..3cf9bbb44 100644 --- a/core/database/src/main/kotlin/org/mifos/mobile/core/database/utils/ChargeTypeConverters.kt +++ b/core/database/src/commonMain/kotlin/org/mifos/mobile/core/database/utils/ChargeTypeConverters.kt @@ -9,9 +9,9 @@ */ package org.mifos.mobile.core.database.utils -import androidx.room.TypeConverter import kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json +import org.mifos.mobile.core.database.TypeConverter import org.mifos.mobile.core.database.entity.ChargeCalculationTypeEntity import org.mifos.mobile.core.database.entity.ChargeTimeTypeEntity import org.mifos.mobile.core.database.entity.CurrencyEntity diff --git a/core/database/src/desktopMain/kotlin/org/mifos/mobile/core/database/AppDatabase.kt b/core/database/src/desktopMain/kotlin/org/mifos/mobile/core/database/AppDatabase.kt new file mode 100644 index 000000000..b89998d14 --- /dev/null +++ b/core/database/src/desktopMain/kotlin/org/mifos/mobile/core/database/AppDatabase.kt @@ -0,0 +1,48 @@ +/* + * Copyright 2025 Mifos Initiative + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * See https://github.com/openMF/mobile-mobile/blob/master/LICENSE.md + */ +package org.mifos.mobile.core.database + +import androidx.room.ConstructedBy +import androidx.room.Database +import androidx.room.RoomDatabase +import androidx.room.RoomDatabaseConstructor +import androidx.room.TypeConverters +import org.mifos.mobile.core.database.dao.ChargeDao +import org.mifos.mobile.core.database.dao.MifosNotificationDao +import org.mifos.mobile.core.database.entity.ChargeEntity +import org.mifos.mobile.core.database.entity.MifosNotificationEntity +import org.mifos.mobile.core.database.utils.ChargeTypeConverters + +@Suppress("NO_ACTUAL_FOR_EXPECT") +expect object AppDatabaseConstructor : RoomDatabaseConstructor { + override fun initialize(): AppDatabase +} + +@Database( + entities = [ + ChargeEntity::class, + MifosNotificationEntity::class, + ], + version = AppDatabase.VERSION, + exportSchema = true, + autoMigrations = [], +) +@TypeConverters(ChargeTypeConverters::class) +@ConstructedBy(AppDatabaseConstructor::class) +actual abstract class AppDatabase : RoomDatabase() { + + actual abstract val mifosNotificationDao: MifosNotificationDao + actual abstract val chargeDao: ChargeDao + + companion object { + const val VERSION = 1 + const val DATABASE_NAME = "mifos_database.db" + } +} diff --git a/core/database/src/desktopMain/kotlin/org/mifos/mobile/core/database/AppDatabaseFactory.desktop.kt b/core/database/src/desktopMain/kotlin/org/mifos/mobile/core/database/AppDatabaseFactory.desktop.kt new file mode 100644 index 000000000..374669c4f --- /dev/null +++ b/core/database/src/desktopMain/kotlin/org/mifos/mobile/core/database/AppDatabaseFactory.desktop.kt @@ -0,0 +1,35 @@ +/* + * Copyright 2025 Mifos Initiative + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * See https://github.com/openMF/mobile-mobile/blob/master/LICENSE.md + */ +package org.mifos.mobile.core.database + +import androidx.room.Room +import androidx.room.RoomDatabase +import java.io.File + +class AppDatabaseFactory { + fun createDatabase(): RoomDatabase.Builder { + val os = System.getProperty("os.name").lowercase() + val userHome = System.getProperty("user.home") + val appDataDir = when { + os.contains("win") -> File(System.getenv("APPDATA"), "Bookpedia") + os.contains("mac") -> File(userHome, "Library/Application Support/Bookpedia") + else -> File(userHome, ".local/share/Bookpedia") + } + + if (!appDataDir.exists()) { + appDataDir.mkdirs() + } + + val dbFile = File(appDataDir, AppDatabase.DATABASE_NAME) + return Room.databaseBuilder( + name = dbFile.absolutePath, + ) + } +} diff --git a/core/database/src/desktopMain/kotlin/org/mifos/mobile/core/database/Room.desktop.kt b/core/database/src/desktopMain/kotlin/org/mifos/mobile/core/database/Room.desktop.kt new file mode 100644 index 000000000..d89e08245 --- /dev/null +++ b/core/database/src/desktopMain/kotlin/org/mifos/mobile/core/database/Room.desktop.kt @@ -0,0 +1,34 @@ +/* + * Copyright 2025 Mifos Initiative + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * See https://github.com/openMF/mobile-mobile/blob/master/LICENSE.md + */ +package org.mifos.mobile.core.database + +import androidx.room.Dao +import androidx.room.Entity +import androidx.room.ForeignKey +import androidx.room.Index +import androidx.room.Insert +import androidx.room.PrimaryKey +import androidx.room.Query + +actual typealias Dao = Dao + +actual typealias Query = Query + +actual typealias Insert = Insert + +actual typealias PrimaryKey = PrimaryKey + +actual typealias ForeignKey = ForeignKey + +actual typealias Index = Index + +actual typealias Entity = Entity + +// actual typealias OnConflictStrategy = OnConflictStrategy diff --git a/core/database/src/desktopMain/kotlin/org/mifos/mobile/core/database/TypeConverter.desktop.kt b/core/database/src/desktopMain/kotlin/org/mifos/mobile/core/database/TypeConverter.desktop.kt new file mode 100644 index 000000000..1571791a8 --- /dev/null +++ b/core/database/src/desktopMain/kotlin/org/mifos/mobile/core/database/TypeConverter.desktop.kt @@ -0,0 +1,14 @@ +/* + * Copyright 2025 Mifos Initiative + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * See https://github.com/openMF/mobile-mobile/blob/master/LICENSE.md + */ +package org.mifos.mobile.core.database + +import androidx.room.TypeConverter + +actual typealias TypeConverter = TypeConverter diff --git a/core/database/src/desktopMain/kotlin/org/mifos/mobile/core/database/di/DatabaseModule.desktop.kt b/core/database/src/desktopMain/kotlin/org/mifos/mobile/core/database/di/DatabaseModule.desktop.kt new file mode 100644 index 000000000..1530e47bb --- /dev/null +++ b/core/database/src/desktopMain/kotlin/org/mifos/mobile/core/database/di/DatabaseModule.desktop.kt @@ -0,0 +1,23 @@ +/* + * Copyright 2025 Mifos Initiative + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * See https://github.com/openMF/mobile-mobile/blob/master/LICENSE.md + */ +package org.mifos.mobile.core.database.di + +import androidx.sqlite.driver.bundled.BundledSQLiteDriver +import org.koin.core.module.Module +import org.koin.dsl.module +import org.mifos.mobile.core.database.AppDatabaseFactory + +actual val platformModule: Module = module { + single { + AppDatabaseFactory().createDatabase() + .setDriver(BundledSQLiteDriver()) + .build() + } +} diff --git a/core/database/src/jsMain/kotlin/org/mifos/mobile/core/database/AppDatabase.js.kt b/core/database/src/jsMain/kotlin/org/mifos/mobile/core/database/AppDatabase.js.kt new file mode 100644 index 000000000..17eb1513a --- /dev/null +++ b/core/database/src/jsMain/kotlin/org/mifos/mobile/core/database/AppDatabase.js.kt @@ -0,0 +1,18 @@ +/* + * Copyright 2025 Mifos Initiative + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * See https://github.com/openMF/mobile-mobile/blob/master/LICENSE.md + */ +package org.mifos.mobile.core.database + +import org.mifos.mobile.core.database.dao.ChargeDao +import org.mifos.mobile.core.database.dao.MifosNotificationDao + +actual abstract class AppDatabase { + actual abstract val mifosNotificationDao: MifosNotificationDao + actual abstract val chargeDao: ChargeDao +} diff --git a/core/database/src/jsMain/kotlin/org/mifos/mobile/core/database/TypeConverter.js.kt b/core/database/src/jsMain/kotlin/org/mifos/mobile/core/database/TypeConverter.js.kt new file mode 100644 index 000000000..fb355542e --- /dev/null +++ b/core/database/src/jsMain/kotlin/org/mifos/mobile/core/database/TypeConverter.js.kt @@ -0,0 +1,14 @@ +/* + * Copyright 2025 Mifos Initiative + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * See https://github.com/openMF/mobile-mobile/blob/master/LICENSE.md + */ +package org.mifos.mobile.core.database + +@Target(AnnotationTarget.FUNCTION) +@Retention(AnnotationRetention.BINARY) +actual annotation class TypeConverter actual constructor() diff --git a/core/database/src/jsMain/kotlin/org/mifos/mobile/core/database/di/DatabaseModule.js.kt b/core/database/src/jsMain/kotlin/org/mifos/mobile/core/database/di/DatabaseModule.js.kt new file mode 100644 index 000000000..12080cdc9 --- /dev/null +++ b/core/database/src/jsMain/kotlin/org/mifos/mobile/core/database/di/DatabaseModule.js.kt @@ -0,0 +1,15 @@ +/* + * Copyright 2025 Mifos Initiative + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * See https://github.com/openMF/mobile-mobile/blob/master/LICENSE.md + */ +package org.mifos.mobile.core.database.di + +import org.koin.core.module.Module + +actual val platformModule: Module + get() = TODO("Not yet implemented") diff --git a/core/database/src/main/AndroidManifest.xml b/core/database/src/main/AndroidManifest.xml deleted file mode 100644 index 4ee22a4fb..000000000 --- a/core/database/src/main/AndroidManifest.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - \ No newline at end of file diff --git a/core/database/src/main/kotlin/org/mifos/mobile/core/database/di/DaoModule.kt b/core/database/src/main/kotlin/org/mifos/mobile/core/database/di/DaoModule.kt deleted file mode 100644 index e295fd081..000000000 --- a/core/database/src/main/kotlin/org/mifos/mobile/core/database/di/DaoModule.kt +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2025 Mifos Initiative - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at https://mozilla.org/MPL/2.0/. - * - * See https://github.com/openMF/mobile-mobile/blob/master/LICENSE.md - */ -package org.mifos.mobile.core.database.di - -import dagger.Module -import dagger.Provides -import dagger.hilt.InstallIn -import dagger.hilt.components.SingletonComponent -import org.mifos.mobile.core.database.SelfServiceDatabase -import org.mifos.mobile.core.database.dao.ChargeDao -import org.mifos.mobile.core.database.dao.MifosNotificationDao - -@Module -@InstallIn(SingletonComponent::class) -internal object DaoModule { - @Provides - fun provideMifosNotificationDao(database: SelfServiceDatabase): MifosNotificationDao { - return database.mifosNotificationDao() - } - - @Provides - fun provideChargeDao(database: SelfServiceDatabase): ChargeDao { - return database.chargeDao() - } -} diff --git a/core/database/src/main/kotlin/org/mifos/mobile/core/database/di/DatabaseModule.kt b/core/database/src/main/kotlin/org/mifos/mobile/core/database/di/DatabaseModule.kt deleted file mode 100644 index b0347b4a8..000000000 --- a/core/database/src/main/kotlin/org/mifos/mobile/core/database/di/DatabaseModule.kt +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2024 Mifos Initiative - * - * This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at https://mozilla.org/MPL/2.0/. - * - * See https://github.com/openMF/mobile-mobile/blob/master/LICENSE.md - */ -package org.mifos.mobile.core.database.di - -import android.content.Context -import androidx.room.Room -import dagger.Module -import dagger.Provides -import dagger.hilt.InstallIn -import dagger.hilt.android.qualifiers.ApplicationContext -import dagger.hilt.components.SingletonComponent -import org.mifos.mobile.core.database.SelfServiceDatabase -import javax.inject.Singleton - -@Module -@InstallIn(SingletonComponent::class) -internal object DatabaseModule { - - @Provides - @Singleton - fun provideDatabase(@ApplicationContext context: Context): SelfServiceDatabase { - return Room.databaseBuilder( - context = context, - klass = SelfServiceDatabase::class.java, - name = "self-service-database", - ).build() - } -} diff --git a/core/database/src/nativeMain/kotlin/org/mifos/mobile/core/database/AppDatabase.kt b/core/database/src/nativeMain/kotlin/org/mifos/mobile/core/database/AppDatabase.kt new file mode 100644 index 000000000..06f8ce4ca --- /dev/null +++ b/core/database/src/nativeMain/kotlin/org/mifos/mobile/core/database/AppDatabase.kt @@ -0,0 +1,47 @@ +/* + * Copyright 2025 Mifos Initiative + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * See https://github.com/openMF/mobile-mobile/blob/master/LICENSE.md + */ +package org.mifos.mobile.core.database + +import androidx.room.ConstructedBy +import androidx.room.Database +import androidx.room.RoomDatabase +import androidx.room.RoomDatabaseConstructor +import androidx.room.TypeConverters +import org.mifos.mobile.core.database.dao.ChargeDao +import org.mifos.mobile.core.database.dao.MifosNotificationDao +import org.mifos.mobile.core.database.entity.ChargeEntity +import org.mifos.mobile.core.database.entity.MifosNotificationEntity +import org.mifos.mobile.core.database.utils.ChargeTypeConverters + +@Suppress("NO_ACTUAL_FOR_EXPECT") +expect object AppDatabaseConstructor : RoomDatabaseConstructor { + override fun initialize(): AppDatabase +} + +@Database( + entities = [ + ChargeEntity::class, + MifosNotificationEntity::class, + ], + version = AppDatabase.VERSION, + exportSchema = true, + autoMigrations = [], +) +@TypeConverters(ChargeTypeConverters::class) +@ConstructedBy(AppDatabaseConstructor::class) +actual abstract class AppDatabase : RoomDatabase() { + actual abstract val mifosNotificationDao: MifosNotificationDao + actual abstract val chargeDao: ChargeDao + + companion object { + const val VERSION = 1 + const val DATABASE_NAME = "mifos_database.db" + } +} diff --git a/core/database/src/nativeMain/kotlin/org/mifos/mobile/core/database/AppDatabaseFactory.native.kt b/core/database/src/nativeMain/kotlin/org/mifos/mobile/core/database/AppDatabaseFactory.native.kt new file mode 100644 index 000000000..15fe17a28 --- /dev/null +++ b/core/database/src/nativeMain/kotlin/org/mifos/mobile/core/database/AppDatabaseFactory.native.kt @@ -0,0 +1,38 @@ +/* + * Copyright 2025 Mifos Initiative + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * See https://github.com/openMF/mobile-mobile/blob/master/LICENSE.md + */ +package org.mifos.mobile.core.database + +import androidx.room.Room +import androidx.room.RoomDatabase +import kotlinx.cinterop.ExperimentalForeignApi +import platform.Foundation.NSDocumentDirectory +import platform.Foundation.NSFileManager +import platform.Foundation.NSUserDomainMask + +class AppDatabaseFactory { + fun createDatabase(): RoomDatabase.Builder { + val dbFilePath = documentDirectory() + "/${AppDatabase.DATABASE_NAME}" + return Room.databaseBuilder( + name = dbFilePath, + ) + } + + @OptIn(ExperimentalForeignApi::class) + private fun documentDirectory(): String { + val documentDirectory = NSFileManager.defaultManager.URLForDirectory( + directory = NSDocumentDirectory, + inDomain = NSUserDomainMask, + appropriateForURL = null, + create = false, + error = null, + ) + return requireNotNull(documentDirectory?.path) + } +} diff --git a/core/database/src/nativeMain/kotlin/org/mifos/mobile/core/database/Room.native.kt b/core/database/src/nativeMain/kotlin/org/mifos/mobile/core/database/Room.native.kt new file mode 100644 index 000000000..d89e08245 --- /dev/null +++ b/core/database/src/nativeMain/kotlin/org/mifos/mobile/core/database/Room.native.kt @@ -0,0 +1,34 @@ +/* + * Copyright 2025 Mifos Initiative + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * See https://github.com/openMF/mobile-mobile/blob/master/LICENSE.md + */ +package org.mifos.mobile.core.database + +import androidx.room.Dao +import androidx.room.Entity +import androidx.room.ForeignKey +import androidx.room.Index +import androidx.room.Insert +import androidx.room.PrimaryKey +import androidx.room.Query + +actual typealias Dao = Dao + +actual typealias Query = Query + +actual typealias Insert = Insert + +actual typealias PrimaryKey = PrimaryKey + +actual typealias ForeignKey = ForeignKey + +actual typealias Index = Index + +actual typealias Entity = Entity + +// actual typealias OnConflictStrategy = OnConflictStrategy diff --git a/core/database/src/nativeMain/kotlin/org/mifos/mobile/core/database/TypeConverter.native.kt b/core/database/src/nativeMain/kotlin/org/mifos/mobile/core/database/TypeConverter.native.kt new file mode 100644 index 000000000..1571791a8 --- /dev/null +++ b/core/database/src/nativeMain/kotlin/org/mifos/mobile/core/database/TypeConverter.native.kt @@ -0,0 +1,14 @@ +/* + * Copyright 2025 Mifos Initiative + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * See https://github.com/openMF/mobile-mobile/blob/master/LICENSE.md + */ +package org.mifos.mobile.core.database + +import androidx.room.TypeConverter + +actual typealias TypeConverter = TypeConverter diff --git a/core/database/src/nativeMain/kotlin/org/mifos/mobile/core/database/di/DatabaseModule.native.kt b/core/database/src/nativeMain/kotlin/org/mifos/mobile/core/database/di/DatabaseModule.native.kt new file mode 100644 index 000000000..1530e47bb --- /dev/null +++ b/core/database/src/nativeMain/kotlin/org/mifos/mobile/core/database/di/DatabaseModule.native.kt @@ -0,0 +1,23 @@ +/* + * Copyright 2025 Mifos Initiative + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * See https://github.com/openMF/mobile-mobile/blob/master/LICENSE.md + */ +package org.mifos.mobile.core.database.di + +import androidx.sqlite.driver.bundled.BundledSQLiteDriver +import org.koin.core.module.Module +import org.koin.dsl.module +import org.mifos.mobile.core.database.AppDatabaseFactory + +actual val platformModule: Module = module { + single { + AppDatabaseFactory().createDatabase() + .setDriver(BundledSQLiteDriver()) + .build() + } +} diff --git a/core/database/src/wasmJsMain/kotlin/org/mifos/mobile/core/database/AppDatabase.wasmJs.kt b/core/database/src/wasmJsMain/kotlin/org/mifos/mobile/core/database/AppDatabase.wasmJs.kt new file mode 100644 index 000000000..17eb1513a --- /dev/null +++ b/core/database/src/wasmJsMain/kotlin/org/mifos/mobile/core/database/AppDatabase.wasmJs.kt @@ -0,0 +1,18 @@ +/* + * Copyright 2025 Mifos Initiative + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * See https://github.com/openMF/mobile-mobile/blob/master/LICENSE.md + */ +package org.mifos.mobile.core.database + +import org.mifos.mobile.core.database.dao.ChargeDao +import org.mifos.mobile.core.database.dao.MifosNotificationDao + +actual abstract class AppDatabase { + actual abstract val mifosNotificationDao: MifosNotificationDao + actual abstract val chargeDao: ChargeDao +} diff --git a/core/database/src/wasmJsMain/kotlin/org/mifos/mobile/core/database/TypeConverter.wasmJs.kt b/core/database/src/wasmJsMain/kotlin/org/mifos/mobile/core/database/TypeConverter.wasmJs.kt new file mode 100644 index 000000000..fb355542e --- /dev/null +++ b/core/database/src/wasmJsMain/kotlin/org/mifos/mobile/core/database/TypeConverter.wasmJs.kt @@ -0,0 +1,14 @@ +/* + * Copyright 2025 Mifos Initiative + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * See https://github.com/openMF/mobile-mobile/blob/master/LICENSE.md + */ +package org.mifos.mobile.core.database + +@Target(AnnotationTarget.FUNCTION) +@Retention(AnnotationRetention.BINARY) +actual annotation class TypeConverter actual constructor() diff --git a/core/database/src/wasmJsMain/kotlin/org/mifos/mobile/core/database/di/DatabaseModule.wasmJs.kt b/core/database/src/wasmJsMain/kotlin/org/mifos/mobile/core/database/di/DatabaseModule.wasmJs.kt new file mode 100644 index 000000000..12080cdc9 --- /dev/null +++ b/core/database/src/wasmJsMain/kotlin/org/mifos/mobile/core/database/di/DatabaseModule.wasmJs.kt @@ -0,0 +1,15 @@ +/* + * Copyright 2025 Mifos Initiative + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. + * + * See https://github.com/openMF/mobile-mobile/blob/master/LICENSE.md + */ +package org.mifos.mobile.core.database.di + +import org.koin.core.module.Module + +actual val platformModule: Module + get() = TODO("Not yet implemented") diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 60db80b2c..0f7eccfcd 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -57,10 +57,8 @@ playServicesCodeScanner = "16.1.0" playServicesVersion = "19.0.0" retrofitVersion = "2.11.0" roborazzi = "1.26.0" -room = "2.6.1" -roomKtxVersion = "2.6.1" -roomRuntimeVersion = "2.6.1" -roomTestingVersion = "2.6.1" +room = "2.7.0-alpha12" +sqliteBundled = "2.5.0-alpha12" rxandroidVersion = "2.1.1" rxjavaVersion = "2.2.21" secrets = "2.0.1" @@ -117,6 +115,7 @@ jbSavedState = "1.2.2" packageName = "MifosWallet" packageNamespace = "org.mifos.desktop" packageVersion = "1.0.0" +roomCommonVersion = "2.6.1" [libraries] accompanist-pager = { group = "com.google.accompanist", name = "accompanist-pager", version.ref = "accompanistVersion" } @@ -164,9 +163,10 @@ androidx-navigation-compose = { group = "androidx.navigation", name = "navigatio androidx-navigation-testing = { group = "androidx.navigation", name = "navigation-testing", version.ref = "androidxNavigation" } androidx-profileinstaller = { group = "androidx.profileinstaller", name = "profileinstaller", version.ref = "androidxProfileinstaller" } androidx-room-compiler = { group = "androidx.room", name = "room-compiler", version.ref = "room" } -androidx-room-ktx = { group = "androidx.room", name = "room-ktx", version.ref = "roomKtxVersion" } -androidx-room-runtime = { group = "androidx.room", name = "room-runtime", version.ref = "roomRuntimeVersion" } -androidx-room-testing = { group = "androidx.room", name = "room-testing", version.ref = "roomTestingVersion" } +androidx-sqlite-bundled = { module = "androidx.sqlite:sqlite-bundled", version.ref = "sqliteBundled" } +androidx-room-ktx = { group = "androidx.room", name = "room-ktx", version.ref = "room" } +androidx-room-runtime = { group = "androidx.room", name = "room-runtime", version.ref = "room" } +androidx-room-testing = { group = "androidx.room", name = "room-testing", version.ref = "room" } androidx-test-espresso-core = { group = "androidx.test.espresso", name = "espresso-core", version.ref = "androidxEspresso" } androidx-test-ext = { group = "androidx.test.ext", name = "junit-ktx", version.ref = "androidxTestExt" } androidx-test-ext-junit = { group = "androidx.test.ext", name = "junit", version.ref = "androidx-test-ext-junit" } @@ -317,6 +317,7 @@ moko-permission = { group = "dev.icerock.moko", name = "permissions", version.re moko-permission-compose = { group = "dev.icerock.moko", name = "permissions-compose", version.ref = "mokoPermission" } window-size = { group = "dev.chrisbanes.material3", name = "material3-window-size-class-multiplatform", version.ref = "windowsSizeClass" } +androidx-room-common = { group = "androidx.room", name = "room-common", version.ref = "roomCommonVersion" } [bundles] androidx-compose-ui-test = [