Skip to content

Commit

Permalink
feat(bank-sdk): Skonto screen. Backend Integration (#497)
Browse files Browse the repository at this point in the history
feat(bank-sdk): Skonto screen. Backend Integration

PP-480
  • Loading branch information
ndubkov-distcotech authored Jul 22, 2024
1 parent 90cf6ab commit 87bfb0d
Show file tree
Hide file tree
Showing 25 changed files with 1,091 additions and 372 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import net.gini.android.bank.sdk.capture.digitalinvoice.DigitalInvoiceException
import net.gini.android.bank.sdk.capture.digitalinvoice.DigitalInvoiceFragment
import net.gini.android.bank.sdk.capture.digitalinvoice.DigitalInvoiceFragmentListener
import net.gini.android.bank.sdk.capture.digitalinvoice.LineItemsValidator
import net.gini.android.bank.sdk.capture.skonto.SkontoDataExtractor
import net.gini.android.bank.sdk.util.disallowScreenshots
import net.gini.android.capture.CaptureSDKResult
import net.gini.android.capture.Document
Expand All @@ -26,13 +27,14 @@ import net.gini.android.capture.camera.CameraFragmentListener
import net.gini.android.capture.network.model.GiniCaptureCompoundExtraction
import net.gini.android.capture.network.model.GiniCaptureSpecificExtraction
import net.gini.android.capture.internal.util.CancelListener
import java.math.BigDecimal
import java.time.LocalDate

class CaptureFlowFragment(private val openWithDocument: Document? = null) :
Fragment(),
GiniCaptureFragmentListener,
DigitalInvoiceFragmentListener,
CancelListener
{
CancelListener {

private lateinit var navController: NavController
private lateinit var captureFlowFragmentListener: CaptureFlowFragmentListener
Expand All @@ -49,7 +51,8 @@ class CaptureFlowFragment(private val openWithDocument: Document? = null) :

override fun onGetLayoutInflater(savedInstanceState: Bundle?): LayoutInflater {
val inflater = super.onGetLayoutInflater(savedInstanceState)
val contextThemeWrapper = ContextThemeWrapper(requireContext(), net.gini.android.capture.R.style.GiniCaptureTheme)
val contextThemeWrapper =
ContextThemeWrapper(requireContext(), net.gini.android.capture.R.style.GiniCaptureTheme)
return inflater.cloneInContext(contextThemeWrapper)
}

Expand All @@ -70,7 +73,8 @@ class CaptureFlowFragment(private val openWithDocument: Document? = null) :


override fun onCreate(savedInstanceState: Bundle?) {
childFragmentManager.fragmentFactory = CaptureFlowFragmentFactory(this, openWithDocument, this, this)
childFragmentManager.fragmentFactory =
CaptureFlowFragmentFactory(this, openWithDocument, this, this)
super.onCreate(savedInstanceState)
if (GiniCapture.hasInstance() && !GiniCapture.getInstance().allowScreenshots) {
requireActivity().window.disallowScreenshots()
Expand Down Expand Up @@ -115,33 +119,60 @@ class CaptureFlowFragment(private val openWithDocument: Document? = null) :
}

override fun onFinishedWithResult(result: CaptureSDKResult) {
when(result) {
when (result) {
is CaptureSDKResult.Success -> {
if (GiniBank.getCaptureConfiguration()?.returnAssistantEnabled == true) {
try {
LineItemsValidator.validate(result.compoundExtractions)
navController.navigate(GiniCaptureFragmentDirections.toDigitalInvoiceFragment(
DigitalInvoiceFragment.getExtractionsBundle(result.specificExtractions),
DigitalInvoiceFragment.getCompoundExtractionsBundle(result.compoundExtractions),
result.returnReasons.toTypedArray(),
DigitalInvoiceFragment.getAmountsAreConsistentExtraction(result.specificExtractions)
))
} catch (notUsed: DigitalInvoiceException) {
didFinishWithResult = true
captureFlowFragmentListener.onFinishedWithResult(interceptSuccessResult(result).toCaptureResult())
tryShowingReturnAssistant(result)
} catch (digitalInvoiceException: DigitalInvoiceException) {
tryShowingSkontoScreen(result)
}
} else {
didFinishWithResult = true
captureFlowFragmentListener.onFinishedWithResult(interceptSuccessResult(result).toCaptureResult())
finishWithResult(result)
}
}

else -> {
didFinishWithResult = true
captureFlowFragmentListener.onFinishedWithResult(result.toCaptureResult())
}
}
}

private fun tryShowingSkontoScreen(result: CaptureSDKResult.Success) {
if (GiniBank.getCaptureConfiguration()?.skontoEnabled == true) {
try {
val skontoData = SkontoDataExtractor.extractSkontoData(
result.specificExtractions,
result.compoundExtractions
)

navController.navigate(
GiniCaptureFragmentDirections.toSkontoFragment(data = skontoData)
)
} catch (e: Exception) {
finishWithResult(result)
}
}
}

private fun tryShowingReturnAssistant(result: CaptureSDKResult.Success) {
LineItemsValidator.validate(result.compoundExtractions)
navController.navigate(
GiniCaptureFragmentDirections.toDigitalInvoiceFragment(
DigitalInvoiceFragment.getExtractionsBundle(result.specificExtractions),
DigitalInvoiceFragment.getCompoundExtractionsBundle(result.compoundExtractions),
result.returnReasons.toTypedArray(),
DigitalInvoiceFragment.getAmountsAreConsistentExtraction(result.specificExtractions)
)
)
}

private fun finishWithResult(result: CaptureSDKResult.Success) {
didFinishWithResult = true
captureFlowFragmentListener.onFinishedWithResult(interceptSuccessResult(result).toCaptureResult())
}

private fun interceptSuccessResult(result: CaptureSDKResult.Success): CaptureSDKResult {
return if (result.specificExtractions.isEmpty() ||
!pay5ExtractionsAvailable(result.specificExtractions) &&
Expand Down Expand Up @@ -172,11 +203,13 @@ class CaptureFlowFragment(private val openWithDocument: Document? = null) :
compoundExtractions: Map<String, GiniCaptureCompoundExtraction>
) {
didFinishWithResult = true
captureFlowFragmentListener.onFinishedWithResult(CaptureResult.Success(
specificExtractions,
compoundExtractions,
emptyList()
))
captureFlowFragmentListener.onFinishedWithResult(
CaptureResult.Success(
specificExtractions,
compoundExtractions,
emptyList()
)
)
}

override fun onCancelFlow() {
Expand Down Expand Up @@ -219,10 +252,12 @@ class CaptureFlowFragmentFactory(
giniCaptureFragmentListener
)
}

DigitalInvoiceFragment::class.java.name -> DigitalInvoiceFragment().apply {
listener = digitalInvoiceListener
cancelListener = cancelCallback
}

else -> super.instantiate(classLoader, className)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,12 @@ data class CaptureConfiguration(
* IMPORTANT: If you disallow screenshots and use the [CaptureFlowFragment] for launching the SDK in your activity, please clear the [android.view.WindowManager.LayoutParams.FLAG_SECURE]
* on your activity's window after the SDK has finished to allow users to take screenshots of your app again.
*/
val allowScreenshots: Boolean = true
val allowScreenshots: Boolean = true,

/**
* Enable/disable the skonto feature.
*/
val skontoEnabled: Boolean = true,
)

internal fun GiniCapture.Builder.applyConfiguration(configuration: CaptureConfiguration): GiniCapture.Builder {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package net.gini.android.bank.sdk.capture.skonto

import net.gini.android.bank.sdk.capture.skonto.model.SkontoData
import net.gini.android.bank.sdk.capture.skonto.model.SkontoData.Amount
import net.gini.android.bank.sdk.capture.skonto.model.SkontoData.SkontoPaymentMethod
import net.gini.android.capture.network.model.GiniCaptureCompoundExtraction
import net.gini.android.capture.network.model.GiniCaptureExtraction
import net.gini.android.capture.network.model.GiniCaptureSpecificExtraction
import java.math.BigDecimal
import java.time.LocalDate


internal class SkontoDataExtractor {

companion object {

fun extractSkontoData(
extractions: Map<String, GiniCaptureExtraction>,
compoundExtractions: Map<String, GiniCaptureCompoundExtraction>,
): SkontoData {
val totalAmountToPay = extractions["amountToPay"]
?: throw NoSuchElementException("Field `extractions.amountToPay` is missing")

val skontoDiscountMaps = compoundExtractions["skontoDiscounts"]?.specificExtractionMaps
?: throw NoSuchElementException("Field `compoundExtractions.skontoDiscounts` is missing")

return skontoDiscountMaps.map { skontoDiscountData ->
val skontoPercentageDiscounted = skontoDiscountData.extractDataByKeys(
"skontoPercentageDiscounted",
"skontoPercentageDiscountedCalculated",
) ?: throw NoSuchElementException("Data for `PercentageDiscounted` is missing")

val skontoPaymentMethod =
skontoDiscountData.extractDataByKeys("skontoPaymentMethod")


val skontoAmountToPay = skontoDiscountData.extractDataByKeys(
"skontoAmountToPay",
"skontoAmountToPayCalculated"
) ?: throw NoSuchElementException("Skonto data for `AmountToPay` is missing")

val skontoRemainingDays = skontoDiscountData.extractDataByKeys(
"skontoRemainingDays",
"skontoRemainingDaysCalculated"
) ?: throw NoSuchElementException("Skonto data for `RemainingDays` is missing")

val skontoDueDate = skontoDiscountData.extractDataByKeys(
"skontoDueDate",
"skontoDueDateCalculated"
) ?: throw NoSuchElementException("Skonto data for `DueDate` is missing")

val skontoAmountDiscounted = skontoDiscountData.extractDataByKeys(
"skontoAmountDiscounted",
"skontoAmountDiscountedCalculated"
)

SkontoData(
skontoPercentageDiscounted = BigDecimal(skontoPercentageDiscounted.value),
skontoAmountToPay = Amount.parse(skontoAmountToPay.value),
fullAmountToPay = Amount.parse(totalAmountToPay.value),
skontoRemainingDays = skontoRemainingDays.value.toInt(),
skontoDueDate = skontoDueDate.value.let(LocalDate::parse),
skontoPaymentMethod = skontoPaymentMethod?.let { SkontoPaymentMethod.valueOf(it.value) }
)
}.first()
}
}
}

fun Map<String, GiniCaptureSpecificExtraction>.extractDataByKeys(vararg keys: String) =
keys.firstNotNullOfOrNull { this[it] }

Loading

0 comments on commit 87bfb0d

Please sign in to comment.