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

Feat: Migrated KYC Module to KMP #1798

Merged
merged 1 commit into from
Oct 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ that can be used as a dependency in any other wallet based project. It is develo
| :feature:finance | Done | ✅ | ✅ | ❔ | ✅ | ❔ |
| :feature:account | Done | ✅ | ✅ | ❔ | ✅ | ❔ |
| :feature:invoices | Done | ✅ | ✅ | ❔ | ✅ | ❔ |
| :feature:kyc | Not started | ❌ | | | | |
| :feature:kyc | Done | ✅ | | | | |
| :feature:make-transfer | Not started | ❌ | ❌ | ❌ | ❌ | ❌ |
| :feature:merchants | Not started | ❌ | ❌ | ❌ | ❌ | ❌ |
| :feature:notification | Not started | ❌ | ❌ | ❌ | ❌ | ❌ |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ package org.mifospay.core.common

import kotlinx.datetime.Clock
import kotlinx.datetime.DateTimeUnit
import kotlinx.datetime.Instant
import kotlinx.datetime.LocalDate
import kotlinx.datetime.LocalDateTime
import kotlinx.datetime.Month
Expand Down Expand Up @@ -174,7 +175,10 @@ object DateHelper {
}

fun getDateAsStringFromLong(timeInMillis: Long): String {
return fullMonthFormat.parse(timeInMillis.toString()).toString()
val instant = Instant.fromEpochMilliseconds(timeInMillis)
.toLocalDateTime(TimeZone.currentSystemDefault())

return instant.format(shortMonthFormat)
}

val currentDate = Clock.System.now().toLocalDateTime(TimeZone.currentSystemDefault())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,14 @@ interface DocumentRepository {
fileName: PartData.FileItem,
): Flow<DataState<Unit>>

suspend fun createDocument(
entityType: String,
entityId: Long,
name: String,
description: String,
file: ByteArray,
): DataState<String>

suspend fun downloadDocument(entityType: String, entityId: Int, documentId: Int): Flow<DataState<Document>>

suspend fun deleteDocument(entityType: String, entityId: Int, documentId: Int): Flow<DataState<Unit>>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,18 @@ package org.mifospay.core.data.repository

import kotlinx.coroutines.flow.Flow
import org.mifospay.core.common.DataState
import org.mifospay.core.network.model.GenericResponse
import org.mifospay.core.network.model.entity.kyc.KYCLevel1Details
import org.mifospay.core.model.kyc.KYCLevel1Details

interface KycLevelRepository {
suspend fun fetchKYCLevel1Details(clientId: Int): Flow<DataState<List<KYCLevel1Details>>>
fun fetchKYCLevel1Details(clientId: Long): Flow<DataState<KYCLevel1Details?>>

suspend fun addKYCLevel1Details(
clientId: Int,
clientId: Long,
kycLevel1Details: KYCLevel1Details,
): Flow<DataState<GenericResponse>>
): DataState<String>

suspend fun updateKYCLevel1Details(
clientId: Int,
clientId: Long,
kycLevel1Details: KYCLevel1Details,
): Flow<DataState<GenericResponse>>
): DataState<String>
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,15 @@
*/
package org.mifospay.core.data.repositoryImp

import io.ktor.client.request.forms.MultiPartFormDataContent
import io.ktor.client.request.forms.formData
import io.ktor.http.Headers
import io.ktor.http.HttpHeaders
import io.ktor.http.content.PartData
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.withContext
import org.mifospay.core.common.DataState
import org.mifospay.core.common.asDataStateFlow
import org.mifospay.core.data.repository.DocumentRepository
Expand All @@ -23,7 +28,10 @@ class DocumentRepositoryImpl(
private val apiManager: FineractApiManager,
private val ioDispatcher: CoroutineDispatcher,
) : DocumentRepository {
override suspend fun getDocuments(entityType: String, entityId: Int): Flow<DataState<List<Document>>> {
override suspend fun getDocuments(
entityType: String,
entityId: Int,
): Flow<DataState<List<Document>>> {
return apiManager.documentApi
.getDocuments(entityType, entityId)
.asDataStateFlow().flowOn(ioDispatcher)
Expand All @@ -41,6 +49,46 @@ class DocumentRepositoryImpl(
.asDataStateFlow().flowOn(ioDispatcher)
}

override suspend fun createDocument(
entityType: String,
entityId: Long,
name: String,
description: String,
file: ByteArray,
): DataState<String> {
return try {
val formData = MultiPartFormDataContent(
formData {
// File part
append(
"file",
file,
Headers.build {
append(HttpHeaders.ContentType, "multipart/form-data")
append(HttpHeaders.ContentDisposition, "filename=\"$name\"")
},
)

// Name and description fields
append("name", name)
append("description", description)
},
)

withContext(ioDispatcher) {
apiManager.documentApi.createDocumentFile(
entityType = entityType,
entityId = entityId,
file = formData,
)
}

DataState.Success("Document Uploaded Successfully")
} catch (e: Exception) {
DataState.Error(e)
}
}

override suspend fun downloadDocument(
entityType: String,
entityId: Int,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,41 +11,57 @@ package org.mifospay.core.data.repositoryImp

import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.withContext
import org.mifospay.core.common.DataState
import org.mifospay.core.common.asDataStateFlow
import org.mifospay.core.data.repository.KycLevelRepository
import org.mifospay.core.model.kyc.KYCLevel1Details
import org.mifospay.core.network.FineractApiManager
import org.mifospay.core.network.model.GenericResponse
import org.mifospay.core.network.model.entity.kyc.KYCLevel1Details

class KycLevelRepositoryImpl(
private val apiManager: FineractApiManager,
private val ioDispatcher: CoroutineDispatcher,
) : KycLevelRepository {
override suspend fun fetchKYCLevel1Details(
clientId: Int,
): Flow<DataState<List<KYCLevel1Details>>> {
override fun fetchKYCLevel1Details(
clientId: Long,
): Flow<DataState<KYCLevel1Details?>> {
return apiManager.kycLevel1Api
.fetchKYCLevel1Details(clientId)
.catch { DataState.Error(it, null) }
.map { it.firstOrNull() }
.asDataStateFlow().flowOn(ioDispatcher)
}

override suspend fun addKYCLevel1Details(
clientId: Int,
clientId: Long,
kycLevel1Details: KYCLevel1Details,
): Flow<DataState<GenericResponse>> {
return apiManager.kycLevel1Api
.addKYCLevel1Details(clientId, kycLevel1Details)
.asDataStateFlow().flowOn(ioDispatcher)
): DataState<String> {
return try {
withContext(ioDispatcher) {
apiManager.kycLevel1Api.addKYCLevel1Details(clientId, kycLevel1Details)
}

DataState.Success("KYC Level One details added successfully")
} catch (e: Exception) {
DataState.Error(e)
}
}

override suspend fun updateKYCLevel1Details(
clientId: Int,
clientId: Long,
kycLevel1Details: KYCLevel1Details,
): Flow<DataState<GenericResponse>> {
return apiManager.kycLevel1Api
.updateKYCLevel1Details(clientId, kycLevel1Details)
.asDataStateFlow().flowOn(ioDispatcher)
): DataState<String> {
return try {
withContext(ioDispatcher) {
apiManager.kycLevel1Api.updateKYCLevel1Details(clientId, kycLevel1Details)
}

DataState.Success("KYC Level One details added successfully")
} catch (e: Exception) {
DataState.Error(e)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,22 @@ import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.automirrored.outlined.ArrowBack
import androidx.compose.material.icons.filled.ArrowOutward
import androidx.compose.material.icons.filled.AttachMoney
import androidx.compose.material.icons.filled.Badge
import androidx.compose.material.icons.filled.CalendarMonth
import androidx.compose.material.icons.filled.Camera
import androidx.compose.material.icons.filled.Check
import androidx.compose.material.icons.filled.ChevronLeft
import androidx.compose.material.icons.filled.ChevronRight
import androidx.compose.material.icons.filled.Close
import androidx.compose.material.icons.filled.ContentCopy
import androidx.compose.material.icons.filled.Delete
import androidx.compose.material.icons.filled.Description
import androidx.compose.material.icons.filled.Edit
import androidx.compose.material.icons.filled.FlashOff
import androidx.compose.material.icons.filled.FlashOn
import androidx.compose.material.icons.filled.Info
import androidx.compose.material.icons.filled.KeyboardArrowDown
import androidx.compose.material.icons.filled.Person
import androidx.compose.material.icons.filled.Photo
import androidx.compose.material.icons.filled.PhotoLibrary
import androidx.compose.material.icons.filled.QrCode
Expand All @@ -36,6 +40,7 @@ import androidx.compose.material.icons.filled.VisibilityOff
import androidx.compose.material.icons.outlined.AccountCircle
import androidx.compose.material.icons.outlined.Cancel
import androidx.compose.material.icons.outlined.DeleteOutline
import androidx.compose.material.icons.outlined.DoneAll
import androidx.compose.material.icons.outlined.Edit
import androidx.compose.material.icons.outlined.Home
import androidx.compose.material.icons.outlined.Info
Expand Down Expand Up @@ -113,4 +118,9 @@ object MifosIcons {
val QrCode2 = Icons.Filled.QrCode2
val Edit = Icons.Filled.Edit
val Edit2 = Icons.Outlined.Edit
val CalenderMonth = Icons.Filled.CalendarMonth
val OutlinedDoneAll = Icons.Outlined.DoneAll
val Person = Icons.Filled.Person
val Badge = Icons.Filled.Badge
val DataInfo = Icons.Filled.Description
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,20 @@
*
* See https://github.com/openMF/mobile-wallet/blob/master/LICENSE.md
*/
package org.mifospay.core.network.model.entity.kyc
package org.mifospay.core.model.kyc

import kotlinx.serialization.Serializable
import org.mifospay.core.common.Parcelable
import org.mifospay.core.common.Parcelize

@Serializable
@Parcelize
data class KYCLevel1Details(
val firstName: String? = null,
val lastName: String? = null,
val addressLine1: String? = null,
val addressLine2: String? = null,
val mobileNo: String? = null,
val dob: String? = null,
val currentLevel: String = "",
)
val firstName: String,
val lastName: String,
val addressLine1: String,
val addressLine2: String,
val mobileNo: String,
val dob: String,
val currentLevel: String,
) : Parcelable
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@
*/
package org.mifospay.core.network.services

import de.jensklingenberg.ktorfit.http.Body
import de.jensklingenberg.ktorfit.http.DELETE
import de.jensklingenberg.ktorfit.http.GET
import de.jensklingenberg.ktorfit.http.Multipart
import de.jensklingenberg.ktorfit.http.POST
import de.jensklingenberg.ktorfit.http.PUT
import de.jensklingenberg.ktorfit.http.Part
import de.jensklingenberg.ktorfit.http.Path
import io.ktor.client.request.forms.MultiPartFormDataContent
import io.ktor.http.content.PartData
import kotlinx.coroutines.flow.Flow
import org.mifospay.core.network.model.entity.noncore.Document
Expand Down Expand Up @@ -46,6 +48,13 @@ interface DocumentService {
@Part typedFile: PartData,
): Flow<Unit>

@POST("{entityType}/{entityId}/" + ApiEndPoints.DOCUMENTS)
suspend fun createDocumentFile(
@Path("entityType") entityType: String,
@Path("entityId") entityId: Long,
@Body file: MultiPartFormDataContent,
): Unit

/**
* This Service is for downloading the Document with EntityType and EntityId and Document Id
* Rest End Point :
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,24 +15,23 @@ import de.jensklingenberg.ktorfit.http.POST
import de.jensklingenberg.ktorfit.http.PUT
import de.jensklingenberg.ktorfit.http.Path
import kotlinx.coroutines.flow.Flow
import org.mifospay.core.network.model.GenericResponse
import org.mifospay.core.network.model.entity.kyc.KYCLevel1Details
import org.mifospay.core.model.kyc.KYCLevel1Details
import org.mifospay.core.network.utils.ApiEndPoints

interface KYCLevel1Service {

@GET(ApiEndPoints.DATATABLES + "/kyc_level1_details/{clientId}")
suspend fun fetchKYCLevel1Details(@Path("clientId") clientId: Int): Flow<List<KYCLevel1Details>>
fun fetchKYCLevel1Details(@Path("clientId") clientId: Long): Flow<List<KYCLevel1Details>>

@POST(ApiEndPoints.DATATABLES + "/kyc_level1_details/{clientId}")
suspend fun addKYCLevel1Details(
@Path("clientId") clientId: Int,
@Path("clientId") clientId: Long,
@Body kycLevel1Details: KYCLevel1Details,
): Flow<GenericResponse>
): Unit

@PUT(ApiEndPoints.DATATABLES + "/kyc_level1_details/{clientId}/")
suspend fun updateKYCLevel1Details(
@Path("clientId") clientId: Int,
@Path("clientId") clientId: Long,
@Body kycLevel1Details: KYCLevel1Details,
): Flow<GenericResponse>
): Unit
}
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ fun AvatarBox(
imageVector = icon,
contentDescription = "Avatar",
tint = contentColor,
modifier = Modifier.size((size / 2).dp),
)
}
}
27 changes: 15 additions & 12 deletions feature/kyc/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,24 @@
* See https://github.com/openMF/mobile-wallet/blob/master/LICENSE.md
*/
plugins {
alias(libs.plugins.mifospay.android.feature)
alias(libs.plugins.mifospay.android.library.compose)
alias(libs.plugins.mifospay.cmp.feature)
alias(libs.plugins.kotlin.parcelize)
}

android {
namespace = "org.mifospay.kyc"
namespace = "org.mifospay.feature.kyc"
}

dependencies {
implementation(projects.libs.countryCodePicker)
implementation(projects.libs.pullrefresh)

implementation(libs.sheets.compose.dialogs.core)
implementation(libs.sheets.compose.dialogs.calender)

// TODO:: this should be removed
implementation(libs.squareup.okhttp)
kotlin {
sourceSets {
commonMain.dependencies {
implementation(compose.ui)
implementation(compose.foundation)
implementation(compose.material3)
implementation(compose.components.resources)
implementation(compose.components.uiToolingPreview)
implementation(libs.filekit.compose)
implementation(libs.coil.kt.compose)
}
}
}
Empty file removed feature/kyc/consumer-rules.pro
Empty file.
Loading
Loading