fix(folio): reject amounts parseCents cannot represent

This commit is contained in:
pj committed 2026-08-15 20:31:03 +05:30
1 parent f11bcd795e
commit a6fdcb5825
2 files changed
+40 -3

No files matched your search

@@ -54,9 +54,8 @@ fun parseCents(input: String): Long? {
val fracPadded = (frac + "00").substring(0, 2) val fracPadded = (frac + "00").substring(0, 2)
val wholeLong = whole.toLongOrNull() ?: return null val wholeLong = whole.toLongOrNull() ?: return null
val fracLong = fracPadded.toLongOrNull() ?: return null val fracLong = fracPadded.toLongOrNull() ?: return null
val total = wholeLong * 100 + fracLong if (wholeLong > (Long.MAX_VALUE - fracLong) / 100) return null
if (total < 0) return null return wholeLong * 100 + fracLong
return total
} }
fun signedAmount(t: Transaction): Long = if (t.type == TxnType.credit) t.amount else -t.amount fun signedAmount(t: Transaction): Long = if (t.type == TxnType.credit) t.amount else -t.amount
@@ -0,0 +1,38 @@
package app.folio.util
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertNull
class ParseCentsTest {
@Test
fun parsesEverydayAmountsExactly() {
assertEquals(1L, parseCents("0.01"))
assertEquals(1234L, parseCents("12.34"))
assertEquals(1250L, parseCents("12.5"))
assertEquals(1200L, parseCents("12.0"))
assertEquals(100000L, parseCents("1000"))
assertEquals(123456L, parseCents("1,234.56"))
}
@Test
fun rejectsEighteenDigitWholeThatWrapsToAPositiveLong() {
assertNull(parseCents("999999999999999999"))
}
@Test
fun rejectsSeventeenDigitWholeThatWrapsToANegativeLong() {
assertNull(parseCents("99999999999999999"))
}
@Test
fun rejectsNineteenDigitWholeThatNoLongerFitsALong() {
assertNull(parseCents("9999999999999999999"))
}
@Test
fun acceptsTheLargestRepresentableAmountAndRejectsOneCentMore() {
assertEquals(Long.MAX_VALUE, parseCents("92233720368547758.07"))
assertNull(parseCents("92233720368547758.08"))
}
}