Skip to content

Commit

Permalink
Merge pull request #379 from gini/IPC-108-payment-component-with-pay-…
Browse files Browse the repository at this point in the history
…invoice-button

Ipc 108 payment component with pay invoice button
  • Loading branch information
a-szotyori authored Feb 14, 2024
2 parents 970287c + c9945a0 commit 417271b
Show file tree
Hide file tree
Showing 52 changed files with 856 additions and 180 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ val viewModelModule = module {
viewModel { UploadViewModel(get(), get(), get()) }
viewModel { ReviewViewModel(get()) }
viewModel { InvoicesViewModel(get()) }
factory { InvoicesRepository(get(), get(), get()) }
factory { InvoicesRepository(get(), get(), get(), get()) }
factory { InvoicesLocalDataSource(get()) }
factory { HardcodedInvoicesLocalDataSource(get())}
factory { HardcodedInvoicesLocalDataSource(get()) }
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ class InvoicesLocalDataSource(private val context: Context) {
val invoicesFlow = _invoicesFlow.asStateFlow()

private val moshi: Moshi = Moshi.Builder().build()

@OptIn(ExperimentalStdlibApi::class)
private val jsonAdapter: JsonAdapter<List<DocumentWithExtractions>> = moshi.adapter<List<DocumentWithExtractions>>()

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@ import net.gini.android.core.api.Resource
import net.gini.android.core.api.models.Document
import net.gini.android.core.api.models.ExtractionsContainer
import net.gini.android.health.api.GiniHealthAPI
import net.gini.android.health.sdk.GiniHealth
import net.gini.android.health.sdk.exampleapp.invoices.data.model.DocumentWithExtractions

class InvoicesRepository(
private val giniHealthAPI: GiniHealthAPI,
private val giniHealth: GiniHealth,
private val hardcodedInvoicesLocalDataSource: HardcodedInvoicesLocalDataSource,
private val invoicesLocalDataSource: InvoicesLocalDataSource
) {
Expand All @@ -34,7 +36,6 @@ class InvoicesRepository(
val hardcodedInvoices = hardcodedInvoicesLocalDataSource.getHardcodedInvoices()
val createdResources = hardcodedInvoices.map { invoiceBytes ->
var document: Document? = null
var extractionsContainer: ExtractionsContainer? = null
giniHealthAPI.documentManager.createPartialDocument(
invoiceBytes,
MediaTypes.IMAGE_JPEG
Expand All @@ -44,8 +45,16 @@ class InvoicesRepository(
document = compositeDocumentResource.data
giniHealthAPI.documentManager.getAllExtractionsWithPolling(compositeDocumentResource.data)
}.mapSuccess { extractionsResource ->
extractionsContainer = extractionsResource.data
documentsWithExtractions.add(DocumentWithExtractions.fromDocumentAndExtractions(document!!, extractionsContainer!!))
document?.let { doc ->
val isPayable = giniHealth.checkIfDocumentIsPayable(doc.id)
documentsWithExtractions.add(
DocumentWithExtractions.fromDocumentAndExtractions(
doc,
extractionsResource.data,
isPayable
)
)
}
extractionsResource
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,24 @@ data class DocumentWithExtractions(
val documentId: String,
val recipient: String?,
val amount: String?,
val dueDate: String?
val dueDate: String?,
val isPayable: Boolean = false
) {

companion object {
fun fromDocumentAndExtractions(
document: Document,
extractionsContainer: ExtractionsContainer
extractionsContainer: ExtractionsContainer,
isPayable: Boolean
): DocumentWithExtractions {
return DocumentWithExtractions(
document.id,
extractionsContainer.compoundExtractions["payment"]?.specificExtractionMaps?.get(0)?.get("payment_recipient")?.value,
extractionsContainer.compoundExtractions["payment"]?.specificExtractionMaps?.get(0)?.get("amount_to_pay")?.value,
extractionsContainer.specificExtractions["payment_due_date"]?.value
extractionsContainer.compoundExtractions["payment"]?.specificExtractionMaps?.get(0)
?.get("payment_recipient")?.value,
extractionsContainer.compoundExtractions["payment"]?.specificExtractionMaps?.get(0)
?.get("amount_to_pay")?.value,
extractionsContainer.specificExtractions["payment_due_date"]?.value,
isPayable
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ import kotlinx.coroutines.launch
import net.gini.android.health.sdk.exampleapp.R
import net.gini.android.health.sdk.exampleapp.databinding.ActivityInvoicesBinding
import net.gini.android.health.sdk.exampleapp.invoices.data.UploadHardcodedInvoicesState
import net.gini.android.health.sdk.exampleapp.invoices.data.model.DocumentWithExtractions
import net.gini.android.health.sdk.exampleapp.invoices.ui.model.InvoiceItem
import net.gini.android.health.sdk.paymentcomponent.PaymentComponentView
import org.koin.androidx.viewmodel.ext.android.viewModel


Expand All @@ -43,25 +43,28 @@ class InvoicesActivity : AppCompatActivity() {
dataSet = invoicesWithExtractions
notifyDataSetChanged()
}
binding.noInvoicesLabel.visibility = if (invoicesWithExtractions.isEmpty()) View.VISIBLE else View.GONE
binding.noInvoicesLabel.visibility =
if (invoicesWithExtractions.isEmpty()) View.VISIBLE else View.GONE
Log.d(this::class.simpleName, "Invoices with extractions: $invoicesWithExtractions")
}
}
launch {
viewModel.uploadHardcodedInvoicesState.collect { uploadState ->
when(uploadState) {
when (uploadState) {
is UploadHardcodedInvoicesState.Failure -> {
AlertDialog.Builder(this@InvoicesActivity)
.setTitle(R.string.upload_failed)
.setMessage(uploadState.errors.toSet().joinToString(", "))
.setPositiveButton(android.R.string.ok, null)
.show()
}

UploadHardcodedInvoicesState.Idle,
UploadHardcodedInvoicesState.Success -> {
binding.loadingIndicatorContainer.visibility = View.INVISIBLE
binding.loadingIndicator.visibility = View.INVISIBLE
}

UploadHardcodedInvoicesState.Loading -> {
binding.loadingIndicatorContainer.visibility = View.VISIBLE
binding.loadingIndicator.visibility = View.VISIBLE
Expand Down Expand Up @@ -91,6 +94,7 @@ class InvoicesActivity : AppCompatActivity() {
viewModel.uploadHardcodedInvoices()
true
}

else -> super.onOptionsItemSelected(item)
}
}
Expand All @@ -103,11 +107,13 @@ class InvoicesAdapter(var dataSet: List<InvoiceItem>) :
val recipient: TextView
val dueDate: TextView
val amount: TextView
val paymentComponent: PaymentComponentView

init {
recipient = view.findViewById(R.id.recipient)
dueDate = view.findViewById(R.id.due_date)
amount = view.findViewById(R.id.amount)
paymentComponent = view.findViewById(R.id.payment_component)
}
}

Expand All @@ -118,9 +124,13 @@ class InvoicesAdapter(var dataSet: List<InvoiceItem>) :
}

override fun onBindViewHolder(viewHolder: ViewHolder, position: Int) {
viewHolder.recipient.text = dataSet[position].recipient ?: ""
viewHolder.dueDate.text = dataSet[position].dueDate ?: ""
viewHolder.amount.text = dataSet[position].amount ?: ""
val invoiceItem = dataSet[position]
viewHolder.recipient.text = invoiceItem.recipient ?: ""
viewHolder.dueDate.text = invoiceItem.dueDate ?: ""
viewHolder.amount.text = invoiceItem.amount ?: ""

viewHolder.paymentComponent.prepareForReuse()
viewHolder.paymentComponent.isPayable = invoiceItem.isPayable
}

override fun getItemCount() = dataSet.size
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ data class InvoiceItem(
val documentId: String,
val recipient: String?,
val amount: String?,
val dueDate: String?
val dueDate: String?,
val isPayable: Boolean = false
) {

companion object {
Expand All @@ -24,15 +25,17 @@ data class InvoiceItem(
documentWithExtractions.documentId,
documentWithExtractions.recipient,
parseAmount(documentWithExtractions.amount),
documentWithExtractions.dueDate
documentWithExtractions.dueDate,
documentWithExtractions.isPayable
)
}

private fun parseAmount(amount: String?): String? {
return amount?.split(":")?.let { substrings ->
if (substrings.size != 2) {
throw java.lang.NumberFormatException(
"Invalid price format. Expected <Price>:<Currency Code>, but got: $amount")
"Invalid price format. Expected <Price>:<Currency Code>, but got: $amount"
)
}
val price = parsePrice(substrings[0])
val currency = Currency.getInstance(substrings[1])
Expand All @@ -51,9 +54,11 @@ data class InvoiceItem(
price.contains(".") -> {
parsePriceWithLocale(price, Locale.ENGLISH)
}

price.contains(",") -> {
parsePriceWithLocale(price, Locale.GERMAN)
}

else -> {
throw NumberFormatException("Unknown number format locale")
}
Expand All @@ -62,8 +67,10 @@ data class InvoiceItem(
throw NumberFormatException("Invalid number format")
}

private fun parsePriceWithLocale(price: String, locale: Locale) = DecimalFormat("0.00",
DecimalFormatSymbols.getInstance(locale))
private fun parsePriceWithLocale(price: String, locale: Locale) = DecimalFormat(
"0.00",
DecimalFormatSymbols.getInstance(locale)
)
.apply { isParseBigDecimal = true }
.run {
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,28 +33,38 @@ class UploadViewModel(
check(stream != null) { "ContentResolver failed" }
val partialDocumentResource = giniHealthAPI.documentManager.createPartialDocument(
stream.getBytes(),
MimeTypeMap.getSingleton().getExtensionFromMimeType(contentResolver.getType(pageUri)) ?: MediaTypes.IMAGE_JPEG
MimeTypeMap.getSingleton().getExtensionFromMimeType(contentResolver.getType(pageUri))
?: MediaTypes.IMAGE_JPEG
)
when (partialDocumentResource) {
is Resource.Cancelled -> throw Exception("Cancelled")
is Resource.Error -> throw Exception(partialDocumentResource.exception)
is Resource.Success -> partialDocumentResource.data
}
}
val polledDocumentResource = giniHealthAPI.documentManager.createCompositeDocument(documentPages).mapSuccess {
documentResource -> giniHealthAPI.documentManager.pollDocument(documentResource.data)
}
val polledDocumentResource = giniHealthAPI.documentManager.createCompositeDocument(documentPages)
.mapSuccess { documentResource ->
giniHealthAPI.documentManager.pollDocument(documentResource.data)
}
when (polledDocumentResource) {
is Resource.Cancelled -> throw Exception("Cancelled")
is Resource.Error -> throw Exception(polledDocumentResource.exception)
is Resource.Success -> {
_uploadState.value = UploadState.Success(polledDocumentResource.data.id)
setDocumentForReview(polledDocumentResource.data.id)

giniHealthAPI.documentManager.getAllExtractions(polledDocumentResource.data).mapSuccess { extractionsResource ->
invoicesLocalDataSource.appendInvoiceWithExtractions(DocumentWithExtractions.fromDocumentAndExtractions(polledDocumentResource.data, extractionsResource.data))
extractionsResource
}
giniHealthAPI.documentManager.getAllExtractions(polledDocumentResource.data)
.mapSuccess { extractionsResource ->
val isPayable = giniHealth.checkIfDocumentIsPayable(polledDocumentResource.data.id)
invoicesLocalDataSource.appendInvoiceWithExtractions(
DocumentWithExtractions.fromDocumentAndExtractions(
polledDocumentResource.data,
extractionsResource.data,
isPayable
)
)
extractionsResource
}
}
}
} catch (throwable: Throwable) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
android:shape="ring"
android:thickness="@dimen/indicator_size"
android:useLevel="false">
<solid android:color="@color/selected_dot"/>
<solid android:color="@color/ghs_color_contrast_03"/>
</shape>
</item>
</layer-list>
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
android:shape="ring"
android:thickness="@dimen/indicator_size"
android:useLevel="false">
<solid android:color="@color/black30"/>
<solid android:color="@color/ghs_color_03"/>
</shape>
</item>
</layer-list>
Loading

0 comments on commit 417271b

Please sign in to comment.