FINERACT-2181: fix Charges using percentage calculation with min and max gap values

This commit is contained in:
Jose Alberto Hernandez
2025-05-16 15:44:37 +02:00
committed by Adam Saghy
parent 793dcd8e8b
commit 62afd41182
6 changed files with 51 additions and 3 deletions
@@ -84,6 +84,8 @@ public class ChargesApiResource {
@Produces({ MediaType.APPLICATION_JSON }) @Produces({ MediaType.APPLICATION_JSON })
@Operation(summary = "Retrieve a Charge", description = "Returns the details of a defined Charge.\n" + "\n" + "Example Requests:\n" @Operation(summary = "Retrieve a Charge", description = "Returns the details of a defined Charge.\n" + "\n" + "Example Requests:\n"
+ "\n" + "charges/1") + "\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, public ChargeData retrieveCharge(@PathParam("chargeId") @Parameter(description = "chargeId") final Long chargeId,
@Context final UriInfo uriInfo) { @Context final UriInfo uriInfo) {
context.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSIONS); context.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSIONS);
@@ -19,6 +19,7 @@
package org.apache.fineract.portfolio.charge.api; package org.apache.fineract.portfolio.charge.api;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import java.math.BigDecimal;
import java.util.Set; import java.util.Set;
/** /**
@@ -110,6 +111,8 @@ final class ChargesApiResourceSwagger {
public GetChargesAppliesToResponse chargeAppliesTo; public GetChargesAppliesToResponse chargeAppliesTo;
public GetChargesCalculationTypeResponse chargeCalculationType; public GetChargesCalculationTypeResponse chargeCalculationType;
public GetChargesPaymentModeResponse chargePaymentMode; public GetChargesPaymentModeResponse chargePaymentMode;
public BigDecimal minCap;
public BigDecimal maxCap;
} }
@Schema(description = "PostChargesRequest") @Schema(description = "PostChargesRequest")
@@ -139,6 +142,10 @@ final class ChargesApiResourceSwagger {
public String monthDayFormat; public String monthDayFormat;
@Schema(example = "false") @Schema(example = "false")
public boolean penalty; public boolean penalty;
@Schema(example = "23.43")
public BigDecimal minCap;
@Schema(example = "45.56")
public BigDecimal maxCap;
} }
@Schema(description = "PostChargesResponse") @Schema(description = "PostChargesResponse")
@@ -196,9 +203,9 @@ final class ChargesApiResourceSwagger {
@Schema(example = "1") @Schema(example = "1")
public Long paymentTypeId; public Long paymentTypeId;
@Schema(example = "10.0") @Schema(example = "10.0")
public Double minCap; public BigDecimal minCap;
@Schema(example = "120.0") @Schema(example = "120.0")
public Double maxCap; public BigDecimal maxCap;
} }
@Schema(description = "PutChargesChargeIdResponse") @Schema(description = "PutChargesChargeIdResponse")
@@ -262,7 +262,7 @@ public class Charge extends AbstractPersistableCustom<Long> {
} }
} }
if (isPercentageOfApprovedAmount()) { if (isPercentageOfDisbursementAmount() || isPercentageOfApprovedAmount()) {
this.minCap = minCap; this.minCap = minCap;
this.maxCap = maxCap; this.maxCap = maxCap;
} }
@@ -20,6 +20,7 @@ package org.apache.fineract.portfolio.charge.request;
import java.io.Serial; import java.io.Serial;
import java.io.Serializable; import java.io.Serializable;
import java.math.BigDecimal;
import lombok.Data; import lombok.Data;
import lombok.NoArgsConstructor; import lombok.NoArgsConstructor;
import lombok.experimental.Accessors; import lombok.experimental.Accessors;
@@ -48,5 +49,7 @@ public class ChargeRequest implements Serializable {
private String feeFrequency; private String feeFrequency;
private Long paymentTypeId; private Long paymentTypeId;
private Boolean enablePaymentType; private Boolean enablePaymentType;
private BigDecimal minCap;
private BigDecimal maxCap;
} }
@@ -23,10 +23,18 @@ import io.restassured.builder.ResponseSpecBuilder;
import io.restassured.http.ContentType; import io.restassured.http.ContentType;
import io.restassured.specification.RequestSpecification; import io.restassured.specification.RequestSpecification;
import io.restassured.specification.ResponseSpecification; import io.restassured.specification.ResponseSpecification;
import java.math.BigDecimal;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap; 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.Utils;
import org.apache.fineract.integrationtests.common.charges.ChargesHelper; 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.Assertions;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@@ -321,4 +329,27 @@ public class ChargesTest {
chargeIdAfterDeletion = ChargesHelper.deleteCharge(this.responseSpec, this.requestSpec, overdraftFeeChargeId); chargeIdAfterDeletion = ChargesHelper.deleteCharge(this.responseSpec, this.requestSpec, overdraftFeeChargeId);
Assertions.assertEquals(overdraftFeeChargeId, chargeIdAfterDeletion, "Verifying Charge ID after deletion"); 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());
}
} }
@@ -24,6 +24,7 @@ import io.restassured.specification.ResponseSpecification;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import org.apache.fineract.client.models.ChargeRequest; 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.models.PostChargesResponse;
import org.apache.fineract.client.util.Calls; import org.apache.fineract.client.util.Calls;
import org.apache.fineract.client.util.JSON; import org.apache.fineract.client.util.JSON;
@@ -810,4 +811,8 @@ public final class ChargesHelper {
public PostChargesResponse createCharges(ChargeRequest request) { public PostChargesResponse createCharges(ChargeRequest request) {
return Calls.ok(FineractClientHelper.getFineractClient().charges.createCharge(request)); return Calls.ok(FineractClientHelper.getFineractClient().charges.createCharge(request));
} }
public GetChargesResponse retrieveCharge(final Long chargeId) {
return Calls.ok(FineractClientHelper.getFineractClient().charges.retrieveCharge(chargeId));
}
} }