From 62afd41182a8d4f8efdd31c42c5dbcb94ff62db0 Mon Sep 17 00:00:00 2001 From: Jose Alberto Hernandez Date: Tue, 6 May 2025 22:34:38 -0500 Subject: [PATCH] FINERACT-2181: fix Charges using percentage calculation with min and max gap values --- .../charge/api/ChargesApiResource.java | 2 ++ .../charge/api/ChargesApiResourceSwagger.java | 11 +++++-- .../portfolio/charge/domain/Charge.java | 2 +- .../charge/request/ChargeRequest.java | 3 ++ .../integrationtests/ChargesTest.java | 31 +++++++++++++++++++ .../common/charges/ChargesHelper.java | 5 +++ 6 files changed, 51 insertions(+), 3 deletions(-) diff --git a/fineract-charge/src/main/java/org/apache/fineract/portfolio/charge/api/ChargesApiResource.java b/fineract-charge/src/main/java/org/apache/fineract/portfolio/charge/api/ChargesApiResource.java index c137e7374..5314a3c71 100644 --- a/fineract-charge/src/main/java/org/apache/fineract/portfolio/charge/api/ChargesApiResource.java +++ b/fineract-charge/src/main/java/org/apache/fineract/portfolio/charge/api/ChargesApiResource.java @@ -84,6 +84,8 @@ public class ChargesApiResource { @Produces({ MediaType.APPLICATION_JSON }) @Operation(summary = "Retrieve a Charge", description = "Returns the details of a defined Charge.\n" + "\n" + "Example Requests:\n" + "\n" + "charges/1") + @ApiResponses({ + @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = ChargesApiResourceSwagger.GetChargesResponse.class))) }) public ChargeData retrieveCharge(@PathParam("chargeId") @Parameter(description = "chargeId") final Long chargeId, @Context final UriInfo uriInfo) { context.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSIONS); diff --git a/fineract-charge/src/main/java/org/apache/fineract/portfolio/charge/api/ChargesApiResourceSwagger.java b/fineract-charge/src/main/java/org/apache/fineract/portfolio/charge/api/ChargesApiResourceSwagger.java index c00b592fb..8fc27d688 100644 --- a/fineract-charge/src/main/java/org/apache/fineract/portfolio/charge/api/ChargesApiResourceSwagger.java +++ b/fineract-charge/src/main/java/org/apache/fineract/portfolio/charge/api/ChargesApiResourceSwagger.java @@ -19,6 +19,7 @@ package org.apache.fineract.portfolio.charge.api; import io.swagger.v3.oas.annotations.media.Schema; +import java.math.BigDecimal; import java.util.Set; /** @@ -110,6 +111,8 @@ final class ChargesApiResourceSwagger { public GetChargesAppliesToResponse chargeAppliesTo; public GetChargesCalculationTypeResponse chargeCalculationType; public GetChargesPaymentModeResponse chargePaymentMode; + public BigDecimal minCap; + public BigDecimal maxCap; } @Schema(description = "PostChargesRequest") @@ -139,6 +142,10 @@ final class ChargesApiResourceSwagger { public String monthDayFormat; @Schema(example = "false") public boolean penalty; + @Schema(example = "23.43") + public BigDecimal minCap; + @Schema(example = "45.56") + public BigDecimal maxCap; } @Schema(description = "PostChargesResponse") @@ -196,9 +203,9 @@ final class ChargesApiResourceSwagger { @Schema(example = "1") public Long paymentTypeId; @Schema(example = "10.0") - public Double minCap; + public BigDecimal minCap; @Schema(example = "120.0") - public Double maxCap; + public BigDecimal maxCap; } @Schema(description = "PutChargesChargeIdResponse") diff --git a/fineract-charge/src/main/java/org/apache/fineract/portfolio/charge/domain/Charge.java b/fineract-charge/src/main/java/org/apache/fineract/portfolio/charge/domain/Charge.java index 9a7269c35..c50c0ad35 100644 --- a/fineract-charge/src/main/java/org/apache/fineract/portfolio/charge/domain/Charge.java +++ b/fineract-charge/src/main/java/org/apache/fineract/portfolio/charge/domain/Charge.java @@ -262,7 +262,7 @@ public class Charge extends AbstractPersistableCustom { } } - if (isPercentageOfApprovedAmount()) { + if (isPercentageOfDisbursementAmount() || isPercentageOfApprovedAmount()) { this.minCap = minCap; this.maxCap = maxCap; } diff --git a/fineract-charge/src/main/java/org/apache/fineract/portfolio/charge/request/ChargeRequest.java b/fineract-charge/src/main/java/org/apache/fineract/portfolio/charge/request/ChargeRequest.java index de807979a..d4002823a 100644 --- a/fineract-charge/src/main/java/org/apache/fineract/portfolio/charge/request/ChargeRequest.java +++ b/fineract-charge/src/main/java/org/apache/fineract/portfolio/charge/request/ChargeRequest.java @@ -20,6 +20,7 @@ package org.apache.fineract.portfolio.charge.request; import java.io.Serial; import java.io.Serializable; +import java.math.BigDecimal; import lombok.Data; import lombok.NoArgsConstructor; import lombok.experimental.Accessors; @@ -48,5 +49,7 @@ public class ChargeRequest implements Serializable { private String feeFrequency; private Long paymentTypeId; private Boolean enablePaymentType; + private BigDecimal minCap; + private BigDecimal maxCap; } diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/ChargesTest.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/ChargesTest.java index 938760ee1..a84e0231d 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/ChargesTest.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/ChargesTest.java @@ -23,10 +23,18 @@ import io.restassured.builder.ResponseSpecBuilder; import io.restassured.http.ContentType; import io.restassured.specification.RequestSpecification; import io.restassured.specification.ResponseSpecification; +import java.math.BigDecimal; import java.util.ArrayList; +import java.util.Calendar; import java.util.HashMap; +import org.apache.fineract.client.models.ChargeRequest; +import org.apache.fineract.client.models.GetChargesResponse; +import org.apache.fineract.client.models.PostChargesResponse; import org.apache.fineract.integrationtests.common.Utils; import org.apache.fineract.integrationtests.common.charges.ChargesHelper; +import org.apache.fineract.portfolio.charge.domain.ChargeCalculationType; +import org.apache.fineract.portfolio.charge.domain.ChargePaymentMode; +import org.apache.fineract.portfolio.charge.domain.ChargeTimeType; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -321,4 +329,27 @@ public class ChargesTest { chargeIdAfterDeletion = ChargesHelper.deleteCharge(this.responseSpec, this.requestSpec, overdraftFeeChargeId); Assertions.assertEquals(overdraftFeeChargeId, chargeIdAfterDeletion, "Verifying Charge ID after deletion"); } + + @Test + public void testChargeUsingPercentageCalculationWithMinAndMaxGapValues() { + final ChargesHelper chargesHelper = new ChargesHelper(); + final BigDecimal minCapVal = BigDecimal.valueOf(23); + final BigDecimal maxCapVal = BigDecimal.valueOf(45); + + final PostChargesResponse feeCharge = chargesHelper.createCharges( + new ChargeRequest().penalty(false).amount(9.0).chargeCalculationType(ChargeCalculationType.PERCENT_OF_AMOUNT.getValue()) + .chargeTimeType(ChargeTimeType.DISBURSEMENT.getValue()).chargePaymentMode(ChargePaymentMode.REGULAR.getValue()) + .currencyCode("USD").name(Utils.randomStringGenerator("FEE_" + Calendar.getInstance().getTimeInMillis(), 5)) + .chargeAppliesTo(1).locale("en").active(true).minCap(minCapVal).maxCap(maxCapVal)); + + Assertions.assertNotNull(feeCharge); + final Long chargeId = feeCharge.getResourceId(); + Assertions.assertNotNull(chargeId); + + final GetChargesResponse chargeResponseData = chargesHelper.retrieveCharge(chargeId); + Assertions.assertNotNull(chargeResponseData); + Assertions.assertEquals(minCapVal.stripTrailingZeros(), chargeResponseData.getMinCap().stripTrailingZeros()); + Assertions.assertEquals(maxCapVal.stripTrailingZeros(), chargeResponseData.getMaxCap().stripTrailingZeros()); + } + } diff --git a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/charges/ChargesHelper.java b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/charges/ChargesHelper.java index 3d11148d7..dd4a680a3 100644 --- a/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/charges/ChargesHelper.java +++ b/integration-tests/src/test/java/org/apache/fineract/integrationtests/common/charges/ChargesHelper.java @@ -24,6 +24,7 @@ import io.restassured.specification.ResponseSpecification; import java.util.ArrayList; import java.util.HashMap; import org.apache.fineract.client.models.ChargeRequest; +import org.apache.fineract.client.models.GetChargesResponse; import org.apache.fineract.client.models.PostChargesResponse; import org.apache.fineract.client.util.Calls; import org.apache.fineract.client.util.JSON; @@ -810,4 +811,8 @@ public final class ChargesHelper { public PostChargesResponse createCharges(ChargeRequest request) { return Calls.ok(FineractClientHelper.getFineractClient().charges.createCharge(request)); } + + public GetChargesResponse retrieveCharge(final Long chargeId) { + return Calls.ok(FineractClientHelper.getFineractClient().charges.retrieveCharge(chargeId)); + } }