Predicting Cash Payments in Indonesian Rupiah

Rahmad Hidayat
4 min readMay 31, 2023

A few years ago, I wrote a function to predict cash payments based on the transaction bill at Qasir. When dealing with cash transactions, it can be helpful to suggest appropriate payment amounts to the cashier. It can improve the experience and make the process faster instead of typing the amount of cash manually.

In the case of the Indonesian Rupiah (IDR), there are specific denominations that can be used for cash payments. In this article, we will explore how to create a Kotlin function that generates suggestions for cash payment amounts based on IDR denominations.

Cash Payments prediction feature based on IDR denominations in Qasir POS.

Setting Up the Function

To begin, let’s define the function generateSuggestedPayments(). This function takes an integer parameter representing the transaction amount and returns a list of integers representing the suggested cash payment amounts.

fun generateSuggestedPayments(transactionAmount: Int): List<Int> {
// Function body will be added in the next steps
}

Determining Suggested Payment Amounts

To generate the suggestions, we need to consider the available IDR denominations and the transaction amount. We’ll start by declaring the denominations and creating an empty mutable list to store the suggestions.

val denominations = listOf(1000, 2000, 5000, 10000, 20000, 50000, 100000)
val suggestions = mutableListOf<Int>()

Next, we iterate over each denomination. If a denomination is greater than the transaction amount, we add it to our list of suggestions.

for (denomination in denominations) {
if (denomination > transactionAmount) {
suggestions.add(denomination)
}
}

We also want to include the next rounded amounts, such as the next thousand, ten thousand, or hundred thousand, depending on the transaction amount. For example, if the transaction amount is 6000 IDR, the next rounded thousand is 7000 IDR. We’ll add these rounded amounts to our suggestions.

if (transactionAmount > 1000) {
val nextThousand = ((transactionAmount / 1000) + 1) * 1000
suggestions.add(nextThousand)
}

if (transactionAmount > 10000) {
val nextTenThousand = ((transactionAmount / 10000) + 1) * 10000
suggestions.add(nextTenThousand)
}

if (transactionAmount > 100000) {
val nextHundredThousand = ((transactionAmount / 100000) + 1) * 100000
val nextFiftyThousand = ((transactionAmount / 50000) + 1) * 50000

suggestions.add(nextHundredThousand)
suggestions.add(nextFiftyThousand)
}

Confused by the formula? Let’s break down ((transactionAmount / 1000) + 1) * 1000 step by step to understand its purpose.

  1. transactionAmount / 1000: This division calculates the quotient when the transactionAmount is divided by 1000. Since both transactionAmount and 1000 are integers, the division performs integer division, which discards the decimal part and keeps only the whole number quotient.
  2. (transactionAmount / 1000) + 1: After calculating the quotient, we add 1 to the result. This step ensures that we round up to the next whole number. For example, if the transactionAmount is 6000, the division would yield 6, and adding 1 gives us 7.
  3. ((transactionAmount / 1000) + 1) * 1000: Finally, we multiply the result from the previous step by 1000. This step is done to get the next multiple of 1000. Multiplying by 1000 brings the rounded-up value back to the original scale. In the example above, the result would be 7000.

In summary, this formula rounds up the transactionAmount to the next multiple of 1000. It ensures that the suggestion is always a whole number and is greater than or equal to the original transactionAmount.

After generating the suggestions, we want to ensure they are unique, sorted in ascending order, and limit the list to a maximum of 5 suggestions.

val uniqueSuggestions = suggestions.sorted().distinct().take(5)

Finally, we can return the list of suggested payment amounts.

return uniqueSuggestions

Here is the full code:

fun generateSuggestedPayments(transactionAmount: Int): List<Int> {
val denominations = listOf(1000, 2000, 5000, 10000, 20000, 50000, 100000)
val suggestions = mutableListOf<Int>()

for (denomination in denominations) {
if (denomination > transactionAmount) {
suggestions.add(denomination)
}
}

if (transactionAmount > 1000) {
val nextThousand = ((transactionAmount / 1000) + 1) * 1000
suggestions.add(nextThousand)
}

if (transactionAmount > 10000) {
val nextTenThousand = ((transactionAmount / 10000) + 1) * 10000
suggestions.add(nextTenThousand)
}

if (transactionAmount > 100000) {
val nextHundredThousand = ((transactionAmount / 100000) + 1) * 100000
val nextFiftyThousand = ((transactionAmount / 50000) + 1) * 50000

suggestions.add(nextHundredThousand)
suggestions.add(nextFiftyThousand)
}

return suggestions.sorted().distinct().take(5)
}

Testing the Function

To verify that our function works as expected, let’s add a main() function to test it with different transaction amounts.

fun main() {
val amounts = listOf(4000, 6574, 7400, 13000, 15600, 213000)
for (transactionAmount in amounts) {
val suggestions = generateSuggestedPayments(transactionAmount)
println

And, here is the result:

For the transaction of IDR 4000, the suggested cash amounts are: 
IDR 5000
IDR 10000
IDR 20000
IDR 50000
IDR 100000

For the transaction of IDR 6574, the suggested cash amounts are:
IDR 7000
IDR 10000
IDR 20000
IDR 50000
IDR 100000

For the transaction of IDR 7400, the suggested cash amounts are:
IDR 8000
IDR 10000
IDR 20000
IDR 50000
IDR 100000

For the transaction of IDR 13000, the suggested cash amounts are:
IDR 14000
IDR 20000
IDR 50000
IDR 100000

For the transaction of IDR 15600, the suggested cash amounts are:
IDR 16000
IDR 20000
IDR 50000
IDR 100000


For the transaction of IDR 213000, the suggested cash amounts are:
IDR 214000
IDR 220000
IDR 250000
IDR 300000

There is more combination that is not covered. But in our case, this prediction is enough to help the cashier settle the transaction faster than inputting the amount manually. Or do you have any idea to improve it? let’s discuss this in the comment section below.

Thank you for reading.

--

--

Rahmad Hidayat

I talk about software engineering especially mobile apps and my whole experience during my career. Currently my role is Sr Principal Engineer at SaaS Company.