Skip to content

Commit

Permalink
Merge pull request #674 from scireum/feature/SE-14351_amount_jdbc_sca…
Browse files Browse the repository at this point in the history
…ling

Fixes amount with large scale persistence
  • Loading branch information
mkeckmkeck authored Feb 19, 2025
2 parents 767f28e + 5a4fe40 commit ba4a197
Show file tree
Hide file tree
Showing 7 changed files with 62 additions and 9 deletions.
18 changes: 11 additions & 7 deletions src/main/java/sirius/db/mixing/properties/AmountProperty.java
Original file line number Diff line number Diff line change
Expand Up @@ -129,10 +129,10 @@ protected Object transformValueFromImport(Value value) {

private Amount parseWithNLS(@Nonnull Value value) {
try {
return applyNumericRounding(Amount.ofMachineString(value.asString()));
return applyNumericRounding(Amount.ofRoundedMachineString(value.asString()));
} catch (IllegalArgumentException originalFormatException) {
try {
return applyNumericRounding(Amount.ofUserString(value.asString()));
return applyNumericRounding(Amount.ofRoundedUserString(value.asString()));
} catch (Exception ignored) {
throw originalFormatException;
}
Expand Down Expand Up @@ -173,12 +173,16 @@ public Optional<NumberFormat> getAnnotatedNumberFormat() {

@Override
protected Object transformToElastic(Object object) {
return object == null || ((Amount) object).isEmpty() ? null : ((Amount) object).getAmount().toPlainString();
return object == null || ((Amount) object).isEmpty() ?
null :
applyNumericRounding(((Amount) object)).getAmount().toPlainString();
}

@Override
protected Object transformToMongo(Object object) {
return object == null || ((Amount) object).isEmpty() ? null : ((Amount) object).getAmount();
return object == null || ((Amount) object).isEmpty() ?
null :
applyNumericRounding(((Amount) object)).getAmount();
}

@Override
Expand All @@ -193,7 +197,7 @@ protected Object transformFromJDBC(Value data) {
if (object instanceof Integer value) {
return Amount.of(value);
}
return Amount.of((BigDecimal) object);
return Amount.ofRounded((BigDecimal) object);
}

@Override
Expand All @@ -202,12 +206,12 @@ protected Object transformFromElastic(Value data) {
if (Strings.isEmpty(valueAsString)) {
return Amount.NOTHING;
}
return Amount.of(new BigDecimal(valueAsString));
return Amount.ofRounded(new BigDecimal(valueAsString));
}

@Override
protected Object transformFromMongo(Value object) {
return object.getAmount();
return object.getRoundedAmount();
}

@Override
Expand Down
4 changes: 4 additions & 0 deletions src/test/java/sirius/db/es/properties/ESDataTypesEntity.java
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
import sirius.db.mixing.Mapping;
import sirius.db.mixing.annotations.Length;
import sirius.db.mixing.annotations.NullAllowed;
import sirius.db.mixing.annotations.Numeric;
import sirius.db.mixing.annotations.Ordinal;
import sirius.db.mixing.types.BaseEntityRef;
import sirius.kernel.commons.Amount;
Expand All @@ -23,6 +24,8 @@

public class ESDataTypesEntity extends ElasticEntity {

public static final int AMOUNT_SCALE = 6;

public enum TestEnum {
Test1, Test2;

Expand All @@ -47,6 +50,7 @@ public String toString() {

private static final Mapping AMOUNT_VALUE = Mapping.named("amountValue");
@NullAllowed
@Numeric(precision = 20, scale = AMOUNT_SCALE)
private Amount amountValue = Amount.NOTHING;

private static final Mapping LOCALDATE_VALUE = Mapping.named("localDateValue");
Expand Down
2 changes: 1 addition & 1 deletion src/test/java/sirius/db/jdbc/DataTypesEntity.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@

public class DataTypesEntity extends SQLEntity {

public static final int AMOUNT_SCALE = 3;
public static final int AMOUNT_SCALE = 6;

public enum TestEnum {
Test1, TestTest, Test2
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

public class MongoAmountEntity extends MongoEntity {

public static final int AMOUNT_SCALE = 3;
public static final int AMOUNT_SCALE = 6;

public static final Mapping TEST_AMOUNT = Mapping.named("testAmount");
private Amount testAmount = Amount.NOTHING;
Expand Down
18 changes: 18 additions & 0 deletions src/test/kotlin/sirius/db/es/properties/ElasticDataTypesTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,12 @@ import org.junit.jupiter.api.BeforeAll
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
import sirius.db.es.Elastic
import sirius.db.jdbc.DataTypesEntity
import sirius.kernel.SiriusExtension
import sirius.kernel.commons.Amount
import sirius.kernel.di.std.Part
import java.math.BigDecimal
import java.math.RoundingMode
import java.time.Duration
import java.time.LocalDate
import java.time.LocalDateTime
Expand Down Expand Up @@ -132,6 +135,21 @@ class ElasticDataTypesTest {
assertEquals(Amount.of(400.5), esDataTypesEntity.amountValue)
}


@Test
fun `reading and writing large scale amount works`() {
var esDataTypesEntity = ESDataTypesEntity()

val unscaledValue = Amount.ofRounded(BigDecimal("1.23456789"))

esDataTypesEntity.amountValue = unscaledValue
elastic.update(esDataTypesEntity)
esDataTypesEntity = elastic.refreshOrFail(esDataTypesEntity)

val expectedAmount = unscaledValue.round(ESDataTypesEntity.AMOUNT_SCALE, RoundingMode.HALF_UP)
assertEquals(expectedAmount, esDataTypesEntity.amountValue)
}

@Test
fun `reading and writing LocalDate works`() {
var esDataTypesEntity = ESDataTypesEntity()
Expand Down
13 changes: 13 additions & 0 deletions src/test/kotlin/sirius/db/jdbc/DataTypesTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import sirius.kernel.SiriusExtension
import sirius.kernel.commons.Amount
import sirius.kernel.commons.Value
import sirius.kernel.di.std.Part
import java.math.BigDecimal
import java.math.RoundingMode
import java.time.Duration
import kotlin.test.assertEquals
Expand Down Expand Up @@ -103,6 +104,18 @@ class DataTypesTest {
assertFalse { test.isAnyMappingChanged }
}

@Test
fun `Persisting large scale amounts works properly`() {
var test = DataTypesEntity()
val unscaledValue = Amount.ofRounded(BigDecimal("1.23456789"))

test.amountValue = unscaledValue
oma.update(test)
test = oma.refreshOrFail(test)
val expectedAmount = unscaledValue.round(DataTypesEntity.AMOUNT_SCALE, RoundingMode.HALF_UP)
assertEquals(expectedAmount, test.amountValue)
}

@Test
fun `default values work`() {
var test = DataTypesEntity()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import sirius.kernel.SiriusExtension
import sirius.kernel.commons.Amount
import sirius.kernel.commons.Value
import sirius.kernel.di.std.Part
import java.math.BigDecimal
import java.math.RoundingMode
import kotlin.test.assertEquals
import kotlin.test.assertFalse
Expand Down Expand Up @@ -51,6 +52,19 @@ class MongoAmountPropertyTest {
assertFalse { test.isAnyMappingChanged }
}

@Test
fun `Persisting large scale amounts works properly`() {
var test = MongoAmountEntity()
val unscaledValue = Amount.ofRounded(BigDecimal("1.23456789"))

test.scaledAmount = unscaledValue
test.testAmount = Amount.ONE
mango.update(test)
test = mango.refreshOrFail(test)
val expectedAmount = unscaledValue.round(MongoAmountEntity.AMOUNT_SCALE, RoundingMode.HALF_UP)
assertEquals(expectedAmount, test.scaledAmount)
}

companion object {
@Part
private lateinit var mango: Mango
Expand Down

0 comments on commit ba4a197

Please sign in to comment.