Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(core): migrate from dbflow to room for client #2300

Draft
wants to merge 9 commits into
base: kmp-impl
Choose a base branch
from
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ package com.mifos.core.data.pagingSource

import androidx.paging.PagingSource
import androidx.paging.PagingState
import com.mifos.core.entity.client.Charges
import com.mifos.core.model.objects.clients.Page
import com.mifos.core.network.datamanager.DataManagerCharge
import com.mifos.core.objects.clients.Page
import com.mifos.room.entities.client.Charges
import kotlinx.coroutines.suspendCancellableCoroutine
import rx.Subscriber
import rx.android.schedulers.AndroidSchedulers
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ package com.mifos.core.data.pagingSource

import androidx.paging.PagingSource
import androidx.paging.PagingState
import com.mifos.core.entity.client.Client
import com.mifos.core.model.objects.clients.Page
import com.mifos.core.network.datamanager.DataManagerClient
import com.mifos.core.objects.clients.Page
import com.mifos.room.entities.client.Client
import rx.Subscriber
import rx.android.schedulers.AndroidSchedulers
import rx.schedulers.Schedulers
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
package com.mifos.core.data.repository

import androidx.paging.PagingData
import com.mifos.core.entity.client.Charges
import com.mifos.room.entities.client.Charges
import kotlinx.coroutines.flow.Flow

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,20 @@
*/
package com.mifos.core.data.repository

import com.mifos.core.entity.client.Client
import com.mifos.room.entities.accounts.ClientAccounts
import com.mifos.room.entities.client.Client
import kotlinx.coroutines.flow.Flow
import okhttp3.MultipartBody
import okhttp3.ResponseBody
import rx.Observable

/**
* Created by Aditya Gupta on 06/08/23.
*/
interface ClientDetailsRepository {

fun uploadClientImage(id: Int, file: MultipartBody.Part?): Observable<ResponseBody>
fun uploadClientImage(id: Int, file: MultipartBody.Part?): Flow<ResponseBody>

fun deleteClientImage(clientId: Int): Observable<ResponseBody>
fun deleteClientImage(clientId: Int): Flow<ResponseBody>

suspend fun getClientAccounts(clientId: Int): ClientAccounts

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
*/
package com.mifos.core.data.repository

import com.mifos.core.objects.noncoreobjects.IdentifierCreationResponse
import com.mifos.core.objects.noncoreobjects.IdentifierPayload
import com.mifos.core.objects.noncoreobjects.IdentifierTemplate
import com.mifos.core.model.objects.noncoreobjects.IdentifierCreationResponse
import com.mifos.core.model.objects.noncoreobjects.IdentifierPayload
import com.mifos.core.model.objects.noncoreobjects.IdentifierTemplate

/**
* Created by Aditya Gupta on 16/08/23.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
*/
package com.mifos.core.data.repository

import com.mifos.core.objects.noncoreobjects.Identifier
import com.mifos.core.model.objects.noncoreobjects.Identifier
import org.openapitools.client.models.DeleteClientsClientIdIdentifiersIdentifierIdResponse

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,9 @@
package com.mifos.core.data.repository

import androidx.paging.PagingData
import com.mifos.core.entity.client.Client
import com.mifos.core.objects.clients.Page
import com.mifos.core.model.objects.clients.Page
import com.mifos.room.entities.client.Client
import kotlinx.coroutines.flow.Flow
import rx.Observable

/**
* Created by Aditya Gupta on 08/08/23.
Expand All @@ -22,5 +21,5 @@ interface ClientListRepository {

fun getAllClients(): Flow<PagingData<Client>>

fun allDatabaseClients(): Observable<Page<Client>>
fun allDatabaseClients(): Flow<Page<Client>>
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,27 +9,27 @@
*/
package com.mifos.core.data.repository

import com.mifos.core.entity.client.Client
import com.mifos.core.entity.client.ClientPayload
import com.mifos.core.entity.organisation.Office
import com.mifos.core.entity.organisation.Staff
import com.mifos.core.entity.templates.clients.ClientsTemplate
import com.mifos.room.entities.client.Client
import com.mifos.room.entities.client.ClientPayload
import com.mifos.room.entities.organisation.Office
import com.mifos.room.entities.organisation.Staff
import com.mifos.room.entities.templates.clients.ClientsTemplate
import kotlinx.coroutines.flow.Flow
import okhttp3.MultipartBody
import okhttp3.ResponseBody
import rx.Observable

/**
* Created by Aditya Gupta on 10/08/23.
*/
interface CreateNewClientRepository {

fun clientTemplate(): Observable<ClientsTemplate>
fun clientTemplate(): Flow<ClientsTemplate>

suspend fun offices(): List<Office>

suspend fun getStaffInOffice(officeId: Int): List<Staff>

fun createClient(clientPayload: ClientPayload): Observable<Client>
fun createClient(clientPayload: ClientPayload): Flow<Client>

fun uploadClientImage(id: Int, file: MultipartBody.Part?): Observable<ResponseBody>
fun uploadClientImage(id: Int, file: MultipartBody.Part?): Flow<ResponseBody>
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,17 @@ import androidx.paging.PagingConfig
import androidx.paging.PagingData
import com.mifos.core.data.pagingSource.ClientChargesPagingSource
import com.mifos.core.data.repository.ClientChargeRepository
import com.mifos.core.entity.client.Charges
import com.mifos.core.network.datamanager.DataManagerCharge
import com.mifos.room.entities.client.Charges
import kotlinx.coroutines.flow.Flow
import javax.inject.Inject

/**
* Created by Aditya Gupta on 08/08/23.
*/
class ClientChargeRepositoryImp @Inject constructor(private val dataManagerCharge: DataManagerCharge) :
ClientChargeRepository {
class ClientChargeRepositoryImp @Inject constructor(
private val dataManagerCharge: DataManagerCharge,
) : ClientChargeRepository {

override fun getClientCharges(
clientId: Int,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,25 +10,26 @@
package com.mifos.core.data.repositoryImp

import com.mifos.core.data.repository.ClientDetailsRepository
import com.mifos.core.entity.client.Client
import com.mifos.core.network.datamanager.DataManagerClient
import com.mifos.room.entities.accounts.ClientAccounts
import com.mifos.room.entities.client.Client
import kotlinx.coroutines.flow.Flow
import okhttp3.MultipartBody
import okhttp3.ResponseBody
import rx.Observable
import javax.inject.Inject

/**
* Created by Aditya Gupta on 06/08/23.
*/
class ClientDetailsRepositoryImp @Inject constructor(private val dataManagerClient: DataManagerClient) :
ClientDetailsRepository {
class ClientDetailsRepositoryImp @Inject constructor(
private val dataManagerClient: DataManagerClient,
) : ClientDetailsRepository {

override fun uploadClientImage(id: Int, file: MultipartBody.Part?): Observable<ResponseBody> {
override fun uploadClientImage(id: Int, file: MultipartBody.Part?): Flow<ResponseBody> {
return dataManagerClient.uploadClientImage(id, file)
}

override fun deleteClientImage(clientId: Int): Observable<ResponseBody> {
override fun deleteClientImage(clientId: Int): Flow<ResponseBody> {
return dataManagerClient.deleteClientImage(clientId)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,18 @@
package com.mifos.core.data.repositoryImp

import com.mifos.core.data.repository.ClientIdentifierDialogRepository
import com.mifos.core.model.objects.noncoreobjects.IdentifierCreationResponse
import com.mifos.core.model.objects.noncoreobjects.IdentifierPayload
import com.mifos.core.model.objects.noncoreobjects.IdentifierTemplate
import com.mifos.core.network.datamanager.DataManagerClient
import com.mifos.core.objects.noncoreobjects.IdentifierCreationResponse
import com.mifos.core.objects.noncoreobjects.IdentifierPayload
import com.mifos.core.objects.noncoreobjects.IdentifierTemplate
import javax.inject.Inject

/**
* Created by Aditya Gupta on 16/08/23.
*/
class ClientIdentifierDialogRepositoryImp @Inject constructor(private val dataManagerClient: DataManagerClient) :
ClientIdentifierDialogRepository {
class ClientIdentifierDialogRepositoryImp @Inject constructor(
private val dataManagerClient: DataManagerClient,
) : ClientIdentifierDialogRepository {

override suspend fun getClientIdentifierTemplate(clientId: Int): IdentifierTemplate {
return dataManagerClient.getClientIdentifierTemplate(clientId)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,17 @@
package com.mifos.core.data.repositoryImp

import com.mifos.core.data.repository.ClientIdentifiersRepository
import com.mifos.core.model.objects.noncoreobjects.Identifier
import com.mifos.core.network.datamanager.DataManagerClient
import com.mifos.core.objects.noncoreobjects.Identifier
import org.openapitools.client.models.DeleteClientsClientIdIdentifiersIdentifierIdResponse
import javax.inject.Inject

/**
* Created by Aditya Gupta on 08/08/23.
*/
class ClientIdentifiersRepositoryImp @Inject constructor(private val dataManagerClient: DataManagerClient) :
ClientIdentifiersRepository {
class ClientIdentifiersRepositoryImp @Inject constructor(
private val dataManagerClient: DataManagerClient,
) : ClientIdentifiersRepository {

override suspend fun getClientIdentifiers(clientId: Int): List<Identifier> {
return dataManagerClient.getClientIdentifiers(clientId)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,10 @@ import androidx.paging.PagingConfig
import androidx.paging.PagingData
import com.mifos.core.data.pagingSource.ClientListPagingSource
import com.mifos.core.data.repository.ClientListRepository
import com.mifos.core.entity.client.Client
import com.mifos.core.model.objects.clients.Page
import com.mifos.core.network.datamanager.DataManagerClient
import com.mifos.core.objects.clients.Page
import com.mifos.room.entities.client.Client
import kotlinx.coroutines.flow.Flow
import rx.Observable
import javax.inject.Inject

/**
Expand All @@ -39,7 +38,7 @@ class ClientListRepositoryImp @Inject constructor(
).flow
}

override fun allDatabaseClients(): Observable<Page<Client>> {
override fun allDatabaseClients(): Flow<Page<Client>> {
return dataManagerClient.allDatabaseClients
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,17 @@
package com.mifos.core.data.repositoryImp

import com.mifos.core.data.repository.CreateNewClientRepository
import com.mifos.core.entity.client.Client
import com.mifos.core.entity.client.ClientPayload
import com.mifos.core.entity.organisation.Office
import com.mifos.core.entity.organisation.Staff
import com.mifos.core.entity.templates.clients.ClientsTemplate
import com.mifos.core.network.datamanager.DataManagerClient
import com.mifos.core.network.datamanager.DataManagerOffices
import com.mifos.core.network.datamanager.DataManagerStaff
import com.mifos.room.entities.client.Client
import com.mifos.room.entities.client.ClientPayload
import com.mifos.room.entities.organisation.Office
import com.mifos.room.entities.organisation.Staff
import com.mifos.room.entities.templates.clients.ClientsTemplate
import kotlinx.coroutines.flow.Flow
import okhttp3.MultipartBody
import okhttp3.ResponseBody
import rx.Observable
import javax.inject.Inject

/**
Expand All @@ -32,7 +32,7 @@ class CreateNewClientRepositoryImp @Inject constructor(
private val dataManagerStaff: DataManagerStaff,
) : CreateNewClientRepository {

override fun clientTemplate(): Observable<ClientsTemplate> {
override fun clientTemplate(): Flow<ClientsTemplate> {
return dataManagerClient.clientTemplate
}

Expand All @@ -44,11 +44,11 @@ class CreateNewClientRepositoryImp @Inject constructor(
return dataManagerStaff.getStaffInOffice(officeId)
}

override fun createClient(clientPayload: ClientPayload): Observable<Client> {
override fun createClient(clientPayload: ClientPayload): Flow<Client> {
return dataManagerClient.createClient(clientPayload)
}

override fun uploadClientImage(id: Int, file: MultipartBody.Part?): Observable<ResponseBody> {
override fun uploadClientImage(id: Int, file: MultipartBody.Part?): Flow<ResponseBody> {
return dataManagerClient.uploadClientImage(id, file)
}
}
77 changes: 77 additions & 0 deletions core/database/src/main/java/com/mifos/room/dao/ClientDao.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/*
* 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/android-client/blob/master/LICENSE.md
*/
package com.mifos.room.dao

import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import androidx.room.Transaction
import androidx.room.Update
import com.mifos.core.model.objects.clients.Page
import com.mifos.room.entities.accounts.ClientAccounts
import com.mifos.room.entities.accounts.loans.LoanAccount
import com.mifos.room.entities.accounts.savings.SavingsAccount
import com.mifos.room.entities.client.Client
import com.mifos.room.entities.client.ClientPayload
import com.mifos.room.entities.group.GroupWithAssociations
import kotlinx.coroutines.flow.Flow

@Dao
interface ClientDao {

@Insert(onConflict = OnConflictStrategy.REPLACE)
suspend fun saveClient(client: Client)

@Query("SELECT * FROM Client")
fun readAllClients(): Flow<Page<Client>>

@Query("SELECT * FROM GroupTable WHERE id = :groupId")
fun getGroupAssociateClients(groupId: Int): Flow<GroupWithAssociations>
Copy link
Contributor

@itsPronay itsPronay Feb 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove Flow from here. Don't use Flow in dao unless we are retrieving list. Check the entire DAO

Copy link
Contributor

@itsPronay itsPronay Feb 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@biplab1 my apologies. Ignore the previous comment.
Check if we need a single item. If yes add 'LIMIT 1`

Copy link
Contributor Author

@biplab1 biplab1 Feb 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In DatabaseHelperClient.kt, this function was returning Observable<GroupWithAssociations>, so it was changed to Flow<GroupWithAssociations>

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

image
@biplab1 This is the function right?
it should be this instead

@Query("SELECT * FROM Client WHERE groupId = :groupId")
    fun getGroupAssociateClients(groupId: Int): Flow<List<Client>>


@Query("SELECT * FROM Client WHERE id = :clientId LIMIT 1")
fun getClient(clientId: Int): Flow<Client>

@Insert(onConflict = OnConflictStrategy.REPLACE)
fun saveClientAccounts(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Save, delete and update should be a suspend function always

Copy link
Contributor Author

@biplab1 biplab1 Feb 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does your statement hold true even when the function returns a flow?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes,
save, delete and update should not return flow because they are one time operations

clientAccounts: ClientAccounts,
clientId: Int,
): Flow<ClientAccounts>

@Query("SELECT * FROM LoanAccount WHERE clientId = :clientId")
fun getLoanAccounts(clientId: Long): Flow<List<LoanAccount>>

@Query("SELECT * FROM SavingsAccount WHERE clientId = :clientId")
fun getSavingsAccounts(clientId: Long): Flow<List<SavingsAccount>>

// TODO add readClientAccounts, use combine

// TODO saveClientTemplate

// TODO readClientTemplate

// TODO saveClientPayloadToDB

// TODO readClientPayloadFromDB

// TODO deleteClientPayload

@Query("DELETE FROM ClientPayload WHERE id = :id")
fun deleteClientPayloadById(id: Int)

@Query("DELETE FROM DataTablePayload WHERE clientCreationTime = :clientCreationTime")
fun deleteDataTablePayloadByTime(clientCreationTime: Long)

@Transaction
fun deleteClientPayload(id: Int, clientCreationTime: Long): Flow<List<ClientPayload>>

@Update
suspend fun updateDatabaseClientPayload(clientPayload: ClientPayload): Flow<ClientPayload>
}
Loading
Loading