Reputation: 25
I have a requirement where I get totalAmount and how much parts to divide that amount into as inputs. For the outputresponse i am using builder pattern and also avoiding null fields. Total amount is a big decimal (if null or less than 0, throw exception) and number of inputs can range between 1-3 (if outside of this range or non numeric, throw exception). I have written this code, but I am not convinced and think there may be a cleaner and better way that is also easy to understand just by looking at the code. Also while splitting, whatever additional cents are left, that would be added to 1st amount.
eg. if 100.01 is total amount that i have to divide into 3 parts, i should get 33.35 for first amount and 33.33 for recurring amounts. Please advise if there is a cleaner and better way to achieve this.
public OutputResponse splitAmount(BigDecimal totalAmount, int divideInto) {
if (!(1 <= divideInto && 3 >= divideInto)) {
throw new Exception();
}
OutputResponse outputResponse;
if (totalAmount != null && totalAmount.compareTo(BigDecimal.ZERO) > 0) {
BigDecimal recurringAmounts = null;
BigDecimal firstAmount = totalAmount;
if (divideInto > 1) {
recurringAmounts = totalAmount.divide(BigDecimal.valueOf(divideInto), 2, RoundingMode.FLOOR);
firstAmount = totalAmount.subtract(recurringAmounts.multiply(new BigDecimal(divideInto - 1)));
}
outputResponse = OutputResponse.builder()
.firstAmt(firstAmount)
.secondPmtAmt(recurringAmounts)
.build();
if (divideInto > 2) {
outputResponse.setThirdPmtAmt(recurringAmounts);
}
} else {
throw new Exception();
}
}
Upvotes: 0
Views: 106
Reputation: 16498
May be Optionals could help to make your code self-explanatory and avoid the nested if-else blocks:
public OutputResponse splitAmount(BigDecimal totalAmount, int divideInto) throws Exception {
IntStream.rangeClosed(1, 3)
.filter(x -> x == divideInto)
.findAny()
.orElseThrow(IllegalArgumentException::new);
Optional.ofNullable(totalAmount)
.filter(d -> d.compareTo(BigDecimal.ZERO) > 0)
.orElseThrow(IllegalArgumentException::new);
BigDecimal recurringAmounts = totalAmount.divide(BigDecimal.valueOf(divideInto), 2, RoundingMode.FLOOR);
BigDecimal rest = totalAmount.subtract(recurringAmounts.multiply(BigDecimal.valueOf(divideInto)));
OutputResponse outputResponse = OutputResponse.builder();
if(divideInto >= 1) {
outputResponse = outputResponse.firstAmt(recurringAmounts.add(rest));
}
if(divideInto >= 2) {
outputResponse = outputResponse.secondPmtAmt(recurringAmounts);
}
if(divideInto == 3) {
outputResponse = outputResponse.setThirdPmtAmt(recurringAmounts);
}
return outputResponse.build();
}
If optionals do not suit your taste:
public OutputResponse splitAmount(BigDecimal totalAmount, int divideInto) throws Exception {
if(divideInto < 1 || 3 < divideInto) {
throw new IllegalArgumentException();
}
if(totalAmount == null || totalAmount.compareTo(BigDecimal.ZERO) <= 0) {
throw new IllegalArgumentException();
}
BigDecimal recurringAmounts = totalAmount.divide(BigDecimal.valueOf(divideInto), 2, RoundingMode.FLOOR);
BigDecimal rest = totalAmount.subtract(recurringAmounts.multiply(BigDecimal.valueOf(divideInto)));
OutputResponse outputResponse = OutputResponse.builder();
if(divideInto >= 1) {
outputResponse = outputResponse.firstAmt(recurringAmounts.add(rest));
}
if(divideInto >= 2) {
outputResponse = outputResponse.secondPmtAmt(recurringAmounts);
}
if(divideInto == 3) {
outputResponse = outputResponse.setThirdPmtAmt(recurringAmounts);
}
return outputResponse.build();
}
Upvotes: 1