FINERACT-1932: Fineract modularization - fineract-charge
This commit is contained in:
committed by
Adam Saghy
parent
e13a9cba01
commit
a3fb836b73
+30
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.charge.api;
|
||||
|
||||
public final class ChargesApiConstants {
|
||||
|
||||
private ChargesApiConstants() {
|
||||
|
||||
}
|
||||
|
||||
public static final String glAccountIdParamName = "incomeAccountId";
|
||||
public static final String taxGroupIdParamName = "taxGroupId";
|
||||
|
||||
}
|
||||
+187
@@ -0,0 +1,187 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.charge.api;
|
||||
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.media.ArraySchema;
|
||||
import io.swagger.v3.oas.annotations.media.Content;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import io.swagger.v3.oas.annotations.parameters.RequestBody;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponse;
|
||||
import io.swagger.v3.oas.annotations.responses.ApiResponses;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import jakarta.ws.rs.Consumes;
|
||||
import jakarta.ws.rs.DELETE;
|
||||
import jakarta.ws.rs.GET;
|
||||
import jakarta.ws.rs.POST;
|
||||
import jakarta.ws.rs.PUT;
|
||||
import jakarta.ws.rs.Path;
|
||||
import jakarta.ws.rs.PathParam;
|
||||
import jakarta.ws.rs.Produces;
|
||||
import jakarta.ws.rs.core.Context;
|
||||
import jakarta.ws.rs.core.MediaType;
|
||||
import jakarta.ws.rs.core.UriInfo;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import org.apache.fineract.commands.domain.CommandWrapper;
|
||||
import org.apache.fineract.commands.service.CommandWrapperBuilder;
|
||||
import org.apache.fineract.commands.service.PortfolioCommandSourceWritePlatformService;
|
||||
import org.apache.fineract.infrastructure.core.api.ApiRequestParameterHelper;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.apache.fineract.infrastructure.core.serialization.ApiRequestJsonSerializationSettings;
|
||||
import org.apache.fineract.infrastructure.core.serialization.DefaultToApiJsonSerializer;
|
||||
import org.apache.fineract.infrastructure.security.service.PlatformSecurityContext;
|
||||
import org.apache.fineract.portfolio.charge.data.ChargeData;
|
||||
import org.apache.fineract.portfolio.charge.service.ChargeReadPlatformService;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Path("/v1/charges")
|
||||
@Component
|
||||
@Tag(name = "Charges", description = "Its typical for MFIs to add extra costs for their financial products. These are typically Fees or Penalties.\n"
|
||||
+ "\n" + "A Charge on fineract platform is what we use to model both Fees and Penalties.\n" + "\n"
|
||||
+ "At present we support defining charges for use with Client accounts and both loan and saving products.")
|
||||
@RequiredArgsConstructor
|
||||
public class ChargesApiResource {
|
||||
|
||||
private static final Set<String> CHARGES_DATA_PARAMETERS = new HashSet<>(Arrays.asList("id", "name", "amount", "currency", "penalty",
|
||||
"active", "chargeAppliesTo", "chargeTimeType", "chargeCalculationType", "chargeCalculationTypeOptions",
|
||||
"chargeAppliesToOptions", "chargeTimeTypeOptions", "currencyOptions", "loanChargeCalculationTypeOptions",
|
||||
"loanChargeTimeTypeOptions", "savingsChargeCalculationTypeOptions", "savingsChargeTimeTypeOptions", "incomeAccount",
|
||||
"clientChargeCalculationTypeOptions", "clientChargeTimeTypeOptions"));
|
||||
|
||||
private static final String RESOURCE_NAME_FOR_PERMISSIONS = "CHARGE";
|
||||
|
||||
private final PlatformSecurityContext context;
|
||||
private final ChargeReadPlatformService readPlatformService;
|
||||
private final DefaultToApiJsonSerializer<ChargeData> toApiJsonSerializer;
|
||||
private final ApiRequestParameterHelper apiRequestParameterHelper;
|
||||
private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService;
|
||||
|
||||
@GET
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Retrieve Charges", description = "Returns the list of defined charges.\n" + "\n" + "Example Requests:\n" + "\n"
|
||||
+ "charges")
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(array = @ArraySchema(schema = @Schema(implementation = ChargesApiResourceSwagger.GetChargesResponse.class)))) })
|
||||
public String retrieveAllCharges(@Context final UriInfo uriInfo) {
|
||||
|
||||
this.context.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSIONS);
|
||||
|
||||
final Collection<ChargeData> charges = this.readPlatformService.retrieveAllCharges();
|
||||
|
||||
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
||||
return this.toApiJsonSerializer.serialize(settings, charges, CHARGES_DATA_PARAMETERS);
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("{chargeId}")
|
||||
@Consumes({ 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"
|
||||
+ "\n" + "charges/1")
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = ChargesApiResourceSwagger.GetChargesResponse.class))) })
|
||||
public String retrieveCharge(@PathParam("chargeId") @Parameter(description = "chargeId") final Long chargeId,
|
||||
@Context final UriInfo uriInfo) {
|
||||
|
||||
this.context.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSIONS);
|
||||
|
||||
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
||||
|
||||
ChargeData charge = this.readPlatformService.retrieveCharge(chargeId);
|
||||
if (settings.isTemplate()) {
|
||||
final ChargeData templateData = this.readPlatformService.retrieveNewChargeDetails();
|
||||
charge = ChargeData.withTemplate(charge, templateData);
|
||||
}
|
||||
|
||||
return this.toApiJsonSerializer.serialize(settings, charge, CHARGES_DATA_PARAMETERS);
|
||||
}
|
||||
|
||||
@GET
|
||||
@Path("template")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Retrieve Charge Template", description = "This is a convenience resource. It can be useful when building maintenance user interface screens for client applications. The template data returned consists of any or all of:\n"
|
||||
+ "\n" + "Field Defaults\n" + "Allowed description Lists\n" + "Example Request:\n" + "\n" + "charges/template\n")
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = ChargesApiResourceSwagger.GetChargesTemplateResponse.class))) })
|
||||
public String retrieveNewChargeDetails(@Context final UriInfo uriInfo) {
|
||||
|
||||
this.context.authenticatedUser().validateHasReadPermission(RESOURCE_NAME_FOR_PERMISSIONS);
|
||||
|
||||
final ChargeData charge = this.readPlatformService.retrieveNewChargeDetails();
|
||||
|
||||
final ApiRequestJsonSerializationSettings settings = this.apiRequestParameterHelper.process(uriInfo.getQueryParameters());
|
||||
return this.toApiJsonSerializer.serialize(settings, charge, CHARGES_DATA_PARAMETERS);
|
||||
}
|
||||
|
||||
@POST
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Create/Define a Charge", description = "Define a new charge that can later be associated with loans and savings through their respective product definitions or directly on each account instance.")
|
||||
@RequestBody(required = true, content = @Content(schema = @Schema(implementation = ChargesApiResourceSwagger.PostChargesRequest.class)))
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = ChargesApiResourceSwagger.PostChargesResponse.class))) })
|
||||
public String createCharge(@Parameter(hidden = true) final String apiRequestBodyAsJson) {
|
||||
|
||||
final CommandWrapper commandRequest = new CommandWrapperBuilder().createCharge().withJson(apiRequestBodyAsJson).build();
|
||||
|
||||
final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||
|
||||
return this.toApiJsonSerializer.serialize(result);
|
||||
}
|
||||
|
||||
@PUT
|
||||
@Path("{chargeId}")
|
||||
@Consumes({ MediaType.APPLICATION_JSON })
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Update a Charge", description = "Updates the details of a Charge.")
|
||||
@RequestBody(required = true, content = @Content(schema = @Schema(implementation = ChargesApiResourceSwagger.PutChargesChargeIdRequest.class)))
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = ChargesApiResourceSwagger.PutChargesChargeIdResponse.class))) })
|
||||
public String updateCharge(@PathParam("chargeId") @Parameter(description = "chargeId") final Long chargeId,
|
||||
@Parameter(hidden = true) final String apiRequestBodyAsJson) {
|
||||
|
||||
final CommandWrapper commandRequest = new CommandWrapperBuilder().updateCharge(chargeId).withJson(apiRequestBodyAsJson).build();
|
||||
|
||||
final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||
|
||||
return this.toApiJsonSerializer.serialize(result);
|
||||
}
|
||||
|
||||
@DELETE
|
||||
@Path("{chargeId}")
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
@Operation(summary = "Delete a Charge", description = "Deletes a Charge.")
|
||||
@ApiResponses({
|
||||
@ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = ChargesApiResourceSwagger.DeleteChargesChargeIdResponse.class))) })
|
||||
public String deleteCharge(@PathParam("chargeId") @Parameter(description = "chargeId") final Long chargeId) {
|
||||
|
||||
final CommandWrapper commandRequest = new CommandWrapperBuilder().deleteCharge(chargeId).build();
|
||||
|
||||
final CommandProcessingResult result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
|
||||
|
||||
return this.toApiJsonSerializer.serialize(result);
|
||||
}
|
||||
}
|
||||
+237
@@ -0,0 +1,237 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.charge.api;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Created by Chirag Gupta on 12/01/17.
|
||||
*/
|
||||
final class ChargesApiResourceSwagger {
|
||||
|
||||
@Schema(description = "GetChargesResponse")
|
||||
public static final class GetChargesResponse {
|
||||
|
||||
private GetChargesResponse() {}
|
||||
|
||||
static final class GetChargesCurrencyResponse {
|
||||
|
||||
@Schema(example = "USD")
|
||||
public String code;
|
||||
@Schema(example = "US Dollar")
|
||||
public String name;
|
||||
@Schema(example = "2")
|
||||
public Integer decimalPlaces;
|
||||
@Schema(example = "$")
|
||||
public String displaySymbol;
|
||||
@Schema(example = "currency.USD")
|
||||
public String nameCode;
|
||||
@Schema(example = "US Dollar ($)")
|
||||
public String displayLabel;
|
||||
}
|
||||
|
||||
static final class GetChargesTimeTypeResponse {
|
||||
|
||||
private GetChargesTimeTypeResponse() {}
|
||||
|
||||
@Schema(example = "1")
|
||||
public Long id;
|
||||
@Schema(example = "chargeTimeType.disbursement")
|
||||
public String code;
|
||||
@Schema(example = "Disbursement")
|
||||
public String description;
|
||||
}
|
||||
|
||||
static final class GetChargesAppliesToResponse {
|
||||
|
||||
private GetChargesAppliesToResponse() {}
|
||||
|
||||
@Schema(example = "1")
|
||||
public Long id;
|
||||
@Schema(example = "chargeAppliesTo.loan")
|
||||
public String code;
|
||||
@Schema(example = "Loan")
|
||||
public String description;
|
||||
}
|
||||
|
||||
static final class GetChargesCalculationTypeResponse {
|
||||
|
||||
private GetChargesCalculationTypeResponse() {}
|
||||
|
||||
@Schema(example = "1")
|
||||
public Long id;
|
||||
@Schema(example = "chargeCalculationType.flat")
|
||||
public String code;
|
||||
@Schema(example = "Flat")
|
||||
public String description;
|
||||
}
|
||||
|
||||
static final class GetChargesPaymentModeResponse {
|
||||
|
||||
private GetChargesPaymentModeResponse() {}
|
||||
|
||||
@Schema(example = "1")
|
||||
public Long id;
|
||||
@Schema(example = "chargepaymentmode.accounttransfer")
|
||||
public String code;
|
||||
@Schema(example = "Account Transfer")
|
||||
public String description;
|
||||
}
|
||||
|
||||
@Schema(example = "1")
|
||||
public Long id;
|
||||
@Schema(example = "Loan Service fee")
|
||||
public String name;
|
||||
@Schema(example = "true")
|
||||
public boolean active;
|
||||
@Schema(example = "false")
|
||||
public boolean penalty;
|
||||
public GetChargesCurrencyResponse currency;
|
||||
@Schema(example = "230.56")
|
||||
public Double amount;
|
||||
public GetChargesTimeTypeResponse chargeTimeType;
|
||||
public GetChargesAppliesToResponse chargeAppliesTo;
|
||||
public GetChargesCalculationTypeResponse chargeCalculationType;
|
||||
public GetChargesPaymentModeResponse chargePaymentMode;
|
||||
}
|
||||
|
||||
@Schema(description = "PostChargesRequest")
|
||||
public static final class PostChargesRequest {
|
||||
|
||||
private PostChargesRequest() {}
|
||||
|
||||
@Schema(example = "Loan Service fee")
|
||||
public String name;
|
||||
@Schema(example = "1")
|
||||
public Integer chargeAppliesTo;
|
||||
@Schema(example = "USD")
|
||||
public String currencyCode;
|
||||
@Schema(example = "en")
|
||||
public String locale;
|
||||
@Schema(example = "230.56")
|
||||
public Double amount;
|
||||
@Schema(example = "1")
|
||||
public Integer chargeTimeType;
|
||||
@Schema(example = "1")
|
||||
public Integer chargeCalculationType;
|
||||
@Schema(example = "1")
|
||||
public Integer chargePaymentMode;
|
||||
@Schema(example = "true")
|
||||
public boolean active;
|
||||
@Schema(example = "dd MMMM")
|
||||
public String monthDayFormat;
|
||||
@Schema(example = "false")
|
||||
public boolean penalty;
|
||||
}
|
||||
|
||||
@Schema(description = "PostChargesResponse")
|
||||
public static final class PostChargesResponse {
|
||||
|
||||
private PostChargesResponse() {}
|
||||
|
||||
@Schema(example = "1")
|
||||
public Long resourceId;
|
||||
}
|
||||
|
||||
@Schema(description = "PutChargesChargeIdRequest")
|
||||
public static final class PutChargesChargeIdRequest {
|
||||
|
||||
private PutChargesChargeIdRequest() {}
|
||||
|
||||
@Schema(example = "Loan service fee(changed)")
|
||||
public String name;
|
||||
}
|
||||
|
||||
@Schema(description = "PutChargesChargeIdResponse")
|
||||
public static final class PutChargesChargeIdResponse {
|
||||
|
||||
private PutChargesChargeIdResponse() {}
|
||||
|
||||
@Schema(example = "1")
|
||||
public Long resourceId;
|
||||
public PutChargesChargeIdRequest changes;
|
||||
}
|
||||
|
||||
@Schema(description = "DeleteChargesChargeIdResponse")
|
||||
public static final class DeleteChargesChargeIdResponse {
|
||||
|
||||
private DeleteChargesChargeIdResponse() {}
|
||||
|
||||
@Schema(example = "1")
|
||||
public Long resourceId;
|
||||
}
|
||||
|
||||
@Schema(description = "GetChargesTemplateResponse")
|
||||
public static final class GetChargesTemplateResponse {
|
||||
|
||||
private GetChargesTemplateResponse() {}
|
||||
|
||||
static final class GetChargesTemplateLoanChargeCalculationTypeOptions {
|
||||
|
||||
private GetChargesTemplateLoanChargeCalculationTypeOptions() {}
|
||||
|
||||
@Schema(example = "1")
|
||||
public Long id;
|
||||
@Schema(example = "chargeCalculationType.flat")
|
||||
public String code;
|
||||
@Schema(example = "Flat")
|
||||
public String description;
|
||||
}
|
||||
|
||||
static final class GetChargesTemplateLoanChargeTimeTypeOptions {
|
||||
|
||||
private GetChargesTemplateLoanChargeTimeTypeOptions() {}
|
||||
|
||||
@Schema(example = "2")
|
||||
public Long id;
|
||||
@Schema(example = "chargeTimeType.specifiedDueDate")
|
||||
public String code;
|
||||
@Schema(example = "Specified due date")
|
||||
public String description;
|
||||
}
|
||||
|
||||
static final class GetChargesTemplateFeeFrequencyOptions {
|
||||
|
||||
private GetChargesTemplateFeeFrequencyOptions() {}
|
||||
|
||||
@Schema(example = "0")
|
||||
public Long id;
|
||||
@Schema(example = "loanTermFrequency.periodFrequencyType.days")
|
||||
public String code;
|
||||
@Schema(example = "Days")
|
||||
public String description;
|
||||
}
|
||||
|
||||
@Schema(example = "false")
|
||||
public boolean active;
|
||||
@Schema(example = "false")
|
||||
public boolean penalty;
|
||||
public Set<GetChargesResponse.GetChargesCurrencyResponse> currencyOptions;
|
||||
public Set<GetChargesResponse.GetChargesCalculationTypeResponse> chargeCalculationTypeOptions;
|
||||
public Set<GetChargesResponse.GetChargesAppliesToResponse> chargeAppliesToOptions;
|
||||
public Set<GetChargesResponse.GetChargesTimeTypeResponse> chargeTimeTypeOptions;
|
||||
public Set<GetChargesResponse.GetChargesPaymentModeResponse> chargePaymentModeOptions;
|
||||
public Set<GetChargesTemplateLoanChargeCalculationTypeOptions> loanChargeCalculationTypeOptions;
|
||||
public Set<GetChargesTemplateLoanChargeTimeTypeOptions> loanChargeTimeTypeOptions;
|
||||
public Set<GetChargesTemplateLoanChargeCalculationTypeOptions> savingsChargeCalculationTypeOptions;
|
||||
public Set<GetChargesTemplateLoanChargeTimeTypeOptions> savingsChargeTimeTypeOptions;
|
||||
public Set<GetChargesTemplateFeeFrequencyOptions> feeFrequencyOptions;
|
||||
}
|
||||
}
|
||||
+783
@@ -0,0 +1,783 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.charge.domain;
|
||||
|
||||
import jakarta.persistence.Column;
|
||||
import jakarta.persistence.Entity;
|
||||
import jakarta.persistence.FetchType;
|
||||
import jakarta.persistence.JoinColumn;
|
||||
import jakarta.persistence.ManyToOne;
|
||||
import jakarta.persistence.Table;
|
||||
import jakarta.persistence.UniqueConstraint;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.MonthDay;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import org.apache.fineract.accounting.glaccount.data.GLAccountData;
|
||||
import org.apache.fineract.accounting.glaccount.domain.GLAccount;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.ApiParameterError;
|
||||
import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder;
|
||||
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
|
||||
import org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom;
|
||||
import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
|
||||
import org.apache.fineract.infrastructure.core.service.DateUtils;
|
||||
import org.apache.fineract.organisation.monetary.data.CurrencyData;
|
||||
import org.apache.fineract.portfolio.charge.api.ChargesApiConstants;
|
||||
import org.apache.fineract.portfolio.charge.data.ChargeData;
|
||||
import org.apache.fineract.portfolio.charge.exception.ChargeDueAtDisbursementCannotBePenaltyException;
|
||||
import org.apache.fineract.portfolio.charge.exception.ChargeMustBePenaltyException;
|
||||
import org.apache.fineract.portfolio.charge.exception.ChargeParameterUpdateNotSupportedException;
|
||||
import org.apache.fineract.portfolio.charge.service.ChargeEnumerations;
|
||||
import org.apache.fineract.portfolio.common.domain.PeriodFrequencyType;
|
||||
import org.apache.fineract.portfolio.paymenttype.data.PaymentTypeData;
|
||||
import org.apache.fineract.portfolio.paymenttype.domain.PaymentType;
|
||||
import org.apache.fineract.portfolio.tax.data.TaxGroupData;
|
||||
import org.apache.fineract.portfolio.tax.domain.TaxGroup;
|
||||
|
||||
@Entity
|
||||
@Table(name = "m_charge", uniqueConstraints = { @UniqueConstraint(columnNames = { "name" }, name = "name") })
|
||||
public class Charge extends AbstractPersistableCustom {
|
||||
|
||||
@Column(name = "name", length = 100)
|
||||
private String name;
|
||||
|
||||
@Column(name = "amount", scale = 6, precision = 19, nullable = false)
|
||||
private BigDecimal amount;
|
||||
|
||||
@Column(name = "currency_code", length = 3)
|
||||
private String currencyCode;
|
||||
|
||||
@Column(name = "charge_applies_to_enum", nullable = false)
|
||||
private Integer chargeAppliesTo;
|
||||
|
||||
@Column(name = "charge_time_enum", nullable = false)
|
||||
private Integer chargeTimeType;
|
||||
|
||||
@Column(name = "charge_calculation_enum")
|
||||
private Integer chargeCalculation;
|
||||
|
||||
@Column(name = "charge_payment_mode_enum", nullable = true)
|
||||
private Integer chargePaymentMode;
|
||||
|
||||
@Column(name = "fee_on_day", nullable = true)
|
||||
private Integer feeOnDay;
|
||||
|
||||
@Column(name = "fee_interval", nullable = true)
|
||||
private Integer feeInterval;
|
||||
|
||||
@Column(name = "fee_on_month", nullable = true)
|
||||
private Integer feeOnMonth;
|
||||
|
||||
@Column(name = "is_penalty", nullable = false)
|
||||
private boolean penalty;
|
||||
|
||||
@Column(name = "is_active", nullable = false)
|
||||
private boolean active;
|
||||
|
||||
@Column(name = "is_deleted", nullable = false)
|
||||
private boolean deleted = false;
|
||||
|
||||
@Column(name = "min_cap", scale = 6, precision = 19, nullable = true)
|
||||
private BigDecimal minCap;
|
||||
|
||||
@Column(name = "max_cap", scale = 6, precision = 19, nullable = true)
|
||||
private BigDecimal maxCap;
|
||||
|
||||
@Column(name = "fee_frequency", nullable = true)
|
||||
private Integer feeFrequency;
|
||||
|
||||
@Column(name = "is_free_withdrawal", nullable = false)
|
||||
private boolean enableFreeWithdrawal;
|
||||
|
||||
@Column(name = "free_withdrawal_charge_frequency", nullable = true)
|
||||
private Integer freeWithdrawalFrequency;
|
||||
|
||||
@Column(name = "restart_frequency", nullable = true)
|
||||
private Integer restartFrequency;
|
||||
|
||||
@Column(name = "restart_frequency_enum", nullable = true)
|
||||
private Integer restartFrequencyEnum;
|
||||
|
||||
@Column(name = "is_payment_type", nullable = false)
|
||||
private boolean enablePaymentType;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "payment_type_id", nullable = false)
|
||||
private PaymentType paymentType;
|
||||
|
||||
@ManyToOne(fetch = FetchType.LAZY)
|
||||
@JoinColumn(name = "income_or_liability_account_id")
|
||||
private GLAccount account;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "tax_group_id")
|
||||
private TaxGroup taxGroup;
|
||||
|
||||
public static Charge fromJson(final JsonCommand command, final GLAccount account, final TaxGroup taxGroup,
|
||||
final PaymentType paymentType) {
|
||||
|
||||
final String name = command.stringValueOfParameterNamed("name");
|
||||
final BigDecimal amount = command.bigDecimalValueOfParameterNamed("amount");
|
||||
final String currencyCode = command.stringValueOfParameterNamed("currencyCode");
|
||||
|
||||
final ChargeAppliesTo chargeAppliesTo = ChargeAppliesTo.fromInt(command.integerValueOfParameterNamed("chargeAppliesTo"));
|
||||
final ChargeTimeType chargeTimeType = ChargeTimeType.fromInt(command.integerValueOfParameterNamed("chargeTimeType"));
|
||||
final ChargeCalculationType chargeCalculationType = ChargeCalculationType
|
||||
.fromInt(command.integerValueOfParameterNamed("chargeCalculationType"));
|
||||
final Integer chargePaymentMode = command.integerValueOfParameterNamed("chargePaymentMode");
|
||||
|
||||
final ChargePaymentMode paymentMode = chargePaymentMode == null ? null : ChargePaymentMode.fromInt(chargePaymentMode);
|
||||
|
||||
final boolean penalty = command.booleanPrimitiveValueOfParameterNamed("penalty");
|
||||
final boolean active = command.booleanPrimitiveValueOfParameterNamed("active");
|
||||
final MonthDay feeOnMonthDay = command.extractMonthDayNamed("feeOnMonthDay");
|
||||
final Integer feeInterval = command.integerValueOfParameterNamed("feeInterval");
|
||||
final BigDecimal minCap = command.bigDecimalValueOfParameterNamed("minCap");
|
||||
final BigDecimal maxCap = command.bigDecimalValueOfParameterNamed("maxCap");
|
||||
final Integer feeFrequency = command.integerValueOfParameterNamed("feeFrequency");
|
||||
|
||||
boolean enableFreeWithdrawalCharge = false;
|
||||
enableFreeWithdrawalCharge = command.booleanPrimitiveValueOfParameterNamed("enableFreeWithdrawalCharge");
|
||||
|
||||
boolean enablePaymentType = false;
|
||||
enablePaymentType = command.booleanPrimitiveValueOfParameterNamed("enablePaymentType");
|
||||
|
||||
Integer freeWithdrawalFrequency = null;
|
||||
Integer restartCountFrequency = null;
|
||||
PeriodFrequencyType countFrequencyType = null;
|
||||
|
||||
if (enableFreeWithdrawalCharge) {
|
||||
freeWithdrawalFrequency = command.integerValueOfParameterNamed("freeWithdrawalFrequency");
|
||||
restartCountFrequency = command.integerValueOfParameterNamed("restartCountFrequency");
|
||||
|
||||
countFrequencyType = PeriodFrequencyType.fromInt(command.integerValueOfParameterNamed("countFrequencyType"));
|
||||
}
|
||||
|
||||
return new Charge(name, amount, currencyCode, chargeAppliesTo, chargeTimeType, chargeCalculationType, penalty, active, paymentMode,
|
||||
feeOnMonthDay, feeInterval, minCap, maxCap, feeFrequency, enableFreeWithdrawalCharge, freeWithdrawalFrequency,
|
||||
restartCountFrequency, countFrequencyType, account, taxGroup, enablePaymentType, paymentType);
|
||||
}
|
||||
|
||||
protected Charge() {}
|
||||
|
||||
private Charge(final String name, final BigDecimal amount, final String currencyCode, final ChargeAppliesTo chargeAppliesTo,
|
||||
final ChargeTimeType chargeTime, final ChargeCalculationType chargeCalculationType, final boolean penalty, final boolean active,
|
||||
final ChargePaymentMode paymentMode, final MonthDay feeOnMonthDay, final Integer feeInterval, final BigDecimal minCap,
|
||||
final BigDecimal maxCap, final Integer feeFrequency, final boolean enableFreeWithdrawalCharge,
|
||||
final Integer freeWithdrawalFrequency, final Integer restartFrequency, final PeriodFrequencyType restartFrequencyEnum,
|
||||
final GLAccount account, final TaxGroup taxGroup, final boolean enablePaymentType, final PaymentType paymentType) {
|
||||
this.name = name;
|
||||
this.amount = amount;
|
||||
this.currencyCode = currencyCode;
|
||||
this.chargeAppliesTo = chargeAppliesTo.getValue();
|
||||
this.chargeTimeType = chargeTime.getValue();
|
||||
this.chargeCalculation = chargeCalculationType.getValue();
|
||||
this.penalty = penalty;
|
||||
this.active = active;
|
||||
this.account = account;
|
||||
this.taxGroup = taxGroup;
|
||||
this.chargePaymentMode = paymentMode == null ? null : paymentMode.getValue();
|
||||
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("charges");
|
||||
|
||||
if (isMonthlyFee() || isAnnualFee()) {
|
||||
this.feeOnMonth = feeOnMonthDay.getMonthValue();
|
||||
this.feeOnDay = feeOnMonthDay.getDayOfMonth();
|
||||
}
|
||||
this.feeInterval = feeInterval;
|
||||
this.feeFrequency = feeFrequency;
|
||||
|
||||
if (isSavingsCharge()) {
|
||||
// TODO vishwas, this validation seems unnecessary as identical
|
||||
// validation is performed in the write service
|
||||
if (!isAllowedSavingsChargeTime()) {
|
||||
baseDataValidator.reset().parameter("chargeTimeType").value(this.chargeTimeType)
|
||||
.failWithCodeNoParameterAddedToErrorCode("not.allowed.charge.time.for.savings");
|
||||
}
|
||||
// TODO vishwas, this validation seems unnecessary as identical
|
||||
// validation is performed in the writeservice
|
||||
if (!isAllowedSavingsChargeCalculationType()) {
|
||||
baseDataValidator.reset().parameter("chargeCalculationType").value(this.chargeCalculation)
|
||||
.failWithCodeNoParameterAddedToErrorCode("not.allowed.charge.calculation.type.for.savings");
|
||||
}
|
||||
|
||||
if (!(ChargeTimeType.fromInt(getChargeTimeType()).isWithdrawalFee()
|
||||
|| ChargeTimeType.fromInt(getChargeTimeType()).isSavingsNoActivityFee())
|
||||
&& ChargeCalculationType.fromInt(getChargeCalculation()).isPercentageOfAmount()) {
|
||||
baseDataValidator.reset().parameter("chargeCalculationType").value(this.chargeCalculation)
|
||||
.failWithCodeNoParameterAddedToErrorCode(
|
||||
"savings.charge.calculation.type.percentage.allowed.only.for.withdrawal.or.NoActivity");
|
||||
}
|
||||
|
||||
if (enableFreeWithdrawalCharge) {
|
||||
this.enableFreeWithdrawal = true;
|
||||
this.freeWithdrawalFrequency = freeWithdrawalFrequency;
|
||||
this.restartFrequency = restartFrequency;
|
||||
this.restartFrequencyEnum = restartFrequencyEnum.getValue();
|
||||
}
|
||||
|
||||
if (enablePaymentType) {
|
||||
if (paymentType != null) {
|
||||
|
||||
this.enablePaymentType = true;
|
||||
this.paymentType = paymentType;
|
||||
}
|
||||
}
|
||||
|
||||
} else if (isLoanCharge()) {
|
||||
|
||||
if (penalty && (chargeTime.isTimeOfDisbursement() || chargeTime.isTrancheDisbursement())) {
|
||||
throw new ChargeDueAtDisbursementCannotBePenaltyException(name);
|
||||
}
|
||||
if (!penalty && chargeTime.isOverdueInstallment()) {
|
||||
throw new ChargeMustBePenaltyException(name);
|
||||
}
|
||||
// TODO vishwas, this validation seems unnecessary as identical
|
||||
// validation is performed in the write service
|
||||
if (!isAllowedLoanChargeTime()) {
|
||||
baseDataValidator.reset().parameter("chargeTimeType").value(this.chargeTimeType)
|
||||
.failWithCodeNoParameterAddedToErrorCode("not.allowed.charge.time.for.loan");
|
||||
}
|
||||
}
|
||||
|
||||
if (isPercentageOfApprovedAmount()) {
|
||||
this.minCap = minCap;
|
||||
this.maxCap = maxCap;
|
||||
}
|
||||
|
||||
if (!dataValidationErrors.isEmpty()) {
|
||||
throw new PlatformApiDataValidationException(dataValidationErrors);
|
||||
}
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
public BigDecimal getAmount() {
|
||||
return this.amount;
|
||||
}
|
||||
|
||||
public String getCurrencyCode() {
|
||||
return this.currencyCode;
|
||||
}
|
||||
|
||||
public Integer getChargeTimeType() {
|
||||
return this.chargeTimeType;
|
||||
}
|
||||
|
||||
public Integer getChargeCalculation() {
|
||||
return this.chargeCalculation;
|
||||
}
|
||||
|
||||
public boolean isActive() {
|
||||
return this.active;
|
||||
}
|
||||
|
||||
public boolean isPenalty() {
|
||||
return this.penalty;
|
||||
}
|
||||
|
||||
public boolean isDeleted() {
|
||||
return this.deleted;
|
||||
}
|
||||
|
||||
public boolean isLoanCharge() {
|
||||
return ChargeAppliesTo.fromInt(this.chargeAppliesTo).isLoanCharge();
|
||||
}
|
||||
|
||||
public boolean isAllowedLoanChargeTime() {
|
||||
return ChargeTimeType.fromInt(this.chargeTimeType).isAllowedLoanChargeTime();
|
||||
}
|
||||
|
||||
public boolean isAllowedClientChargeTime() {
|
||||
return ChargeTimeType.fromInt(this.chargeTimeType).isAllowedClientChargeTime();
|
||||
}
|
||||
|
||||
public boolean isSavingsCharge() {
|
||||
return ChargeAppliesTo.fromInt(this.chargeAppliesTo).isSavingsCharge();
|
||||
}
|
||||
|
||||
public boolean isClientCharge() {
|
||||
return ChargeAppliesTo.fromInt(this.chargeAppliesTo).isClientCharge();
|
||||
}
|
||||
|
||||
public boolean isAllowedSavingsChargeTime() {
|
||||
return ChargeTimeType.fromInt(this.chargeTimeType).isAllowedSavingsChargeTime();
|
||||
}
|
||||
|
||||
public boolean isAllowedSavingsChargeCalculationType() {
|
||||
return ChargeCalculationType.fromInt(this.chargeCalculation).isAllowedSavingsChargeCalculationType();
|
||||
}
|
||||
|
||||
public boolean isAllowedClientChargeCalculationType() {
|
||||
return ChargeCalculationType.fromInt(this.chargeCalculation).isAllowedClientChargeCalculationType();
|
||||
}
|
||||
|
||||
public boolean isPercentageOfApprovedAmount() {
|
||||
return ChargeCalculationType.fromInt(this.chargeCalculation).isPercentageOfAmount();
|
||||
}
|
||||
|
||||
public boolean isPercentageOfDisbursementAmount() {
|
||||
return ChargeCalculationType.fromInt(this.chargeCalculation).isPercentageOfDisbursementAmount();
|
||||
}
|
||||
|
||||
public BigDecimal getMinCap() {
|
||||
return this.minCap;
|
||||
}
|
||||
|
||||
public BigDecimal getMaxCap() {
|
||||
return this.maxCap;
|
||||
}
|
||||
|
||||
public boolean isEnableFreeWithdrawal() {
|
||||
return this.enableFreeWithdrawal;
|
||||
}
|
||||
|
||||
public boolean isEnablePaymentType() {
|
||||
return this.enablePaymentType;
|
||||
}
|
||||
|
||||
public Integer getFrequencyFreeWithdrawalCharge() {
|
||||
return this.freeWithdrawalFrequency;
|
||||
}
|
||||
|
||||
public Integer getRestartFrequency() {
|
||||
return this.restartFrequency;
|
||||
}
|
||||
|
||||
public Integer getRestartFrequencyEnum() {
|
||||
return this.restartFrequencyEnum;
|
||||
}
|
||||
|
||||
public PaymentType getPaymentType() {
|
||||
return this.paymentType;
|
||||
}
|
||||
|
||||
public void setPaymentType(PaymentType paymentType) {
|
||||
this.paymentType = paymentType;
|
||||
}
|
||||
|
||||
private Long getPaymentTypeId() {
|
||||
Long paymentTypeId = null;
|
||||
if (this.paymentType != null) {
|
||||
paymentTypeId = this.paymentType.getId();
|
||||
}
|
||||
return paymentTypeId;
|
||||
}
|
||||
|
||||
public Map<String, Object> update(final JsonCommand command) {
|
||||
final Map<String, Object> actualChanges = new LinkedHashMap<>(7);
|
||||
|
||||
final Locale locale = command.extractLocale();
|
||||
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("charges");
|
||||
|
||||
final String nameParamName = "name";
|
||||
if (command.isChangeInStringParameterNamed(nameParamName, this.name)) {
|
||||
final String newValue = command.stringValueOfParameterNamed(nameParamName);
|
||||
actualChanges.put(nameParamName, newValue);
|
||||
this.name = newValue;
|
||||
}
|
||||
|
||||
final String currencyCodeParamName = "currencyCode";
|
||||
if (command.isChangeInStringParameterNamed(currencyCodeParamName, this.currencyCode)) {
|
||||
final String newValue = command.stringValueOfParameterNamed(currencyCodeParamName);
|
||||
actualChanges.put(currencyCodeParamName, newValue);
|
||||
this.currencyCode = newValue;
|
||||
}
|
||||
|
||||
final String amountParamName = "amount";
|
||||
if (command.isChangeInBigDecimalParameterNamed(amountParamName, this.amount)) {
|
||||
final BigDecimal newValue = command.bigDecimalValueOfParameterNamed(amountParamName, locale);
|
||||
actualChanges.put(amountParamName, newValue);
|
||||
actualChanges.put("locale", locale.getLanguage());
|
||||
this.amount = newValue;
|
||||
}
|
||||
|
||||
final String chargeTimeParamName = "chargeTimeType";
|
||||
if (command.isChangeInIntegerParameterNamed(chargeTimeParamName, this.chargeTimeType)) {
|
||||
final Integer newValue = command.integerValueOfParameterNamed(chargeTimeParamName);
|
||||
actualChanges.put(chargeTimeParamName, newValue);
|
||||
actualChanges.put("locale", locale.getLanguage());
|
||||
this.chargeTimeType = ChargeTimeType.fromInt(newValue).getValue();
|
||||
|
||||
if (isSavingsCharge()) {
|
||||
if (!isAllowedSavingsChargeTime()) {
|
||||
baseDataValidator.reset().parameter("chargeTimeType").value(this.chargeTimeType)
|
||||
.failWithCodeNoParameterAddedToErrorCode("not.allowed.charge.time.for.savings");
|
||||
}
|
||||
// if charge time is changed to monthly then validate for
|
||||
// feeOnMonthDay and feeInterval
|
||||
if (isMonthlyFee()) {
|
||||
final MonthDay monthDay = command.extractMonthDayNamed("feeOnMonthDay");
|
||||
baseDataValidator.reset().parameter("feeOnMonthDay").value(monthDay).notNull();
|
||||
|
||||
final Integer feeInterval = command.integerValueOfParameterNamed("feeInterval");
|
||||
baseDataValidator.reset().parameter("feeInterval").value(feeInterval).notNull().inMinMaxRange(1, 12);
|
||||
}
|
||||
} else if (isLoanCharge()) {
|
||||
if (!isAllowedLoanChargeTime()) {
|
||||
baseDataValidator.reset().parameter("chargeTimeType").value(this.chargeTimeType)
|
||||
.failWithCodeNoParameterAddedToErrorCode("not.allowed.charge.time.for.loan");
|
||||
}
|
||||
} else if (isClientCharge()) {
|
||||
if (!isAllowedLoanChargeTime()) {
|
||||
baseDataValidator.reset().parameter("chargeTimeType").value(this.chargeTimeType)
|
||||
.failWithCodeNoParameterAddedToErrorCode("not.allowed.charge.time.for.client");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final String freeWithdrawalFrequencyParamName = "freeWithdrawalFrequency";
|
||||
if (command.isChangeInIntegerParameterNamed(freeWithdrawalFrequencyParamName, this.freeWithdrawalFrequency)) {
|
||||
final Integer enableFreeWithdrawalChargeNewValue = command.integerValueOfParameterNamed(freeWithdrawalFrequencyParamName);
|
||||
actualChanges.put(freeWithdrawalFrequencyParamName, enableFreeWithdrawalChargeNewValue);
|
||||
this.freeWithdrawalFrequency = enableFreeWithdrawalChargeNewValue;
|
||||
}
|
||||
|
||||
final String restartCountFrequencyParamName = "restartCountFrequency";
|
||||
if (command.isChangeInIntegerParameterNamed(restartCountFrequencyParamName, this.restartFrequency)) {
|
||||
final Integer restartCountFrequencyNewValue = command.integerValueOfParameterNamed(restartCountFrequencyParamName);
|
||||
actualChanges.put(restartCountFrequencyParamName, restartCountFrequencyNewValue);
|
||||
this.restartFrequency = restartCountFrequencyNewValue;
|
||||
}
|
||||
|
||||
final String countFrequencyTypeParamName = "countFrequencyType";
|
||||
if (command.isChangeInIntegerParameterNamed(countFrequencyTypeParamName, this.restartFrequencyEnum)) {
|
||||
final Integer countFrequencyTypeNewValue = command.integerValueOfParameterNamed(countFrequencyTypeParamName);
|
||||
actualChanges.put(countFrequencyTypeParamName, countFrequencyTypeNewValue);
|
||||
this.restartFrequencyEnum = ChargeTimeType.fromInt(countFrequencyTypeNewValue).getValue();
|
||||
}
|
||||
|
||||
final String enableFreeWithdrawalChargeParamName = "enableFreeWithdrawalCharge";
|
||||
if (command.isChangeInBooleanParameterNamed(enableFreeWithdrawalChargeParamName, this.enableFreeWithdrawal)) {
|
||||
final boolean newValue = command.booleanPrimitiveValueOfParameterNamed(enableFreeWithdrawalChargeParamName);
|
||||
actualChanges.put(enableFreeWithdrawalChargeParamName, newValue);
|
||||
this.enableFreeWithdrawal = newValue;
|
||||
|
||||
}
|
||||
|
||||
final String enablePaymentTypeParamName = "enablePaymentType";
|
||||
if (command.isChangeInBooleanParameterNamed(enablePaymentTypeParamName, this.enablePaymentType)) {
|
||||
final boolean newValue = command.booleanPrimitiveValueOfParameterNamed(enablePaymentTypeParamName);
|
||||
actualChanges.put(enablePaymentTypeParamName, newValue);
|
||||
this.enablePaymentType = newValue;
|
||||
}
|
||||
|
||||
final String paymentTypeParamName = "paymentTypeId";
|
||||
if (command.isChangeInLongParameterNamed(paymentTypeParamName, getPaymentTypeId())) {
|
||||
final Long newValue = command.longValueOfParameterNamed(paymentTypeParamName);
|
||||
actualChanges.put(paymentTypeParamName, newValue);
|
||||
}
|
||||
|
||||
final String chargeAppliesToParamName = "chargeAppliesTo";
|
||||
if (command.isChangeInIntegerParameterNamed(chargeAppliesToParamName, this.chargeAppliesTo)) {
|
||||
/*
|
||||
* final Integer newValue = command.integerValueOfParameterNamed(chargeAppliesToParamName);
|
||||
* actualChanges.put(chargeAppliesToParamName, newValue); actualChanges.put("locale", localeAsInput);
|
||||
* this.chargeAppliesTo = ChargeAppliesTo.fromInt(newValue).getValue();
|
||||
*/
|
||||
|
||||
// AA: Do not allow to change chargeAppliesTo.
|
||||
final String errorMessage = "Update of Charge applies to is not supported";
|
||||
throw new ChargeParameterUpdateNotSupportedException("charge.applies.to", errorMessage);
|
||||
}
|
||||
|
||||
final String chargeCalculationParamName = "chargeCalculationType";
|
||||
if (command.isChangeInIntegerParameterNamed(chargeCalculationParamName, this.chargeCalculation)) {
|
||||
final Integer newValue = command.integerValueOfParameterNamed(chargeCalculationParamName);
|
||||
actualChanges.put(chargeCalculationParamName, newValue);
|
||||
actualChanges.put("locale", locale.getLanguage());
|
||||
this.chargeCalculation = ChargeCalculationType.fromInt(newValue).getValue();
|
||||
|
||||
if (isSavingsCharge()) {
|
||||
if (!isAllowedSavingsChargeCalculationType()) {
|
||||
baseDataValidator.reset().parameter("chargeCalculationType").value(this.chargeCalculation)
|
||||
.failWithCodeNoParameterAddedToErrorCode("not.allowed.charge.calculation.type.for.savings");
|
||||
}
|
||||
|
||||
if (!(ChargeTimeType.fromInt(getChargeTimeType()).isWithdrawalFee()
|
||||
|| ChargeTimeType.fromInt(getChargeTimeType()).isSavingsNoActivityFee())
|
||||
&& ChargeCalculationType.fromInt(getChargeCalculation()).isPercentageOfAmount()) {
|
||||
baseDataValidator.reset().parameter("chargeCalculationType").value(this.chargeCalculation)
|
||||
.failWithCodeNoParameterAddedToErrorCode(
|
||||
"charge.calculation.type.percentage.allowed.only.for.withdrawal.or.noactivity");
|
||||
}
|
||||
} else if (isClientCharge()) {
|
||||
if (!isAllowedClientChargeCalculationType()) {
|
||||
baseDataValidator.reset().parameter("chargeCalculationType").value(this.chargeCalculation)
|
||||
.failWithCodeNoParameterAddedToErrorCode("not.allowed.charge.calculation.type.for.client");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// validate only for loan charge
|
||||
if (isLoanCharge()) {
|
||||
final String paymentModeParamName = "chargePaymentMode";
|
||||
if (command.isChangeInIntegerParameterNamed(paymentModeParamName, this.chargePaymentMode)) {
|
||||
final Integer newValue = command.integerValueOfParameterNamed(paymentModeParamName);
|
||||
actualChanges.put(paymentModeParamName, newValue);
|
||||
actualChanges.put("locale", locale.getLanguage());
|
||||
this.chargePaymentMode = ChargePaymentMode.fromInt(newValue).getValue();
|
||||
}
|
||||
}
|
||||
|
||||
if (command.hasParameter("feeOnMonthDay")) {
|
||||
final MonthDay monthDay = command.extractMonthDayNamed("feeOnMonthDay");
|
||||
final String actualValueEntered = command.stringValueOfParameterNamed("feeOnMonthDay");
|
||||
final Integer dayOfMonthValue = monthDay.getDayOfMonth();
|
||||
if (!this.feeOnDay.equals(dayOfMonthValue)) {
|
||||
actualChanges.put("feeOnMonthDay", actualValueEntered);
|
||||
actualChanges.put("locale", locale.getLanguage());
|
||||
this.feeOnDay = dayOfMonthValue;
|
||||
}
|
||||
|
||||
final Integer monthOfYear = monthDay.getMonthValue();
|
||||
if (!this.feeOnMonth.equals(monthOfYear)) {
|
||||
actualChanges.put("feeOnMonthDay", actualValueEntered);
|
||||
actualChanges.put("locale", locale.getLanguage());
|
||||
this.feeOnMonth = monthOfYear;
|
||||
}
|
||||
}
|
||||
|
||||
final String feeInterval = "feeInterval";
|
||||
if (command.isChangeInIntegerParameterNamed(feeInterval, this.feeInterval)) {
|
||||
final Integer newValue = command.integerValueOfParameterNamed(feeInterval);
|
||||
actualChanges.put(feeInterval, newValue);
|
||||
actualChanges.put("locale", locale.getLanguage());
|
||||
this.feeInterval = newValue;
|
||||
}
|
||||
|
||||
final String feeFrequency = "feeFrequency";
|
||||
if (command.isChangeInIntegerParameterNamed(feeFrequency, this.feeFrequency)) {
|
||||
final Integer newValue = command.integerValueOfParameterNamed(feeFrequency);
|
||||
actualChanges.put(feeFrequency, newValue);
|
||||
actualChanges.put("locale", locale.getLanguage());
|
||||
this.feeFrequency = newValue;
|
||||
}
|
||||
|
||||
if (this.feeFrequency != null) {
|
||||
baseDataValidator.reset().parameter("feeInterval").value(this.feeInterval).notNull();
|
||||
}
|
||||
|
||||
final String penaltyParamName = "penalty";
|
||||
if (command.isChangeInBooleanParameterNamed(penaltyParamName, this.penalty)) {
|
||||
final boolean newValue = command.booleanPrimitiveValueOfParameterNamed(penaltyParamName);
|
||||
actualChanges.put(penaltyParamName, newValue);
|
||||
this.penalty = newValue;
|
||||
}
|
||||
|
||||
final String activeParamName = "active";
|
||||
if (command.isChangeInBooleanParameterNamed(activeParamName, this.active)) {
|
||||
final boolean newValue = command.booleanPrimitiveValueOfParameterNamed(activeParamName);
|
||||
actualChanges.put(activeParamName, newValue);
|
||||
this.active = newValue;
|
||||
}
|
||||
// allow min and max cap to be only added to PERCENT_OF_AMOUNT for now
|
||||
if (isPercentageOfApprovedAmount()) {
|
||||
final String minCapParamName = "minCap";
|
||||
if (command.isChangeInBigDecimalParameterNamed(minCapParamName, this.minCap)) {
|
||||
final BigDecimal newValue = command.bigDecimalValueOfParameterNamed(minCapParamName);
|
||||
actualChanges.put(minCapParamName, newValue);
|
||||
actualChanges.put("locale", locale.getLanguage());
|
||||
this.minCap = newValue;
|
||||
}
|
||||
final String maxCapParamName = "maxCap";
|
||||
if (command.isChangeInBigDecimalParameterNamed(maxCapParamName, this.maxCap)) {
|
||||
final BigDecimal newValue = command.bigDecimalValueOfParameterNamed(maxCapParamName);
|
||||
actualChanges.put(maxCapParamName, newValue);
|
||||
actualChanges.put("locale", locale.getLanguage());
|
||||
this.maxCap = newValue;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (this.penalty && ChargeTimeType.fromInt(this.chargeTimeType).isTimeOfDisbursement()) {
|
||||
throw new ChargeDueAtDisbursementCannotBePenaltyException(this.name);
|
||||
}
|
||||
if (!penalty && ChargeTimeType.fromInt(this.chargeTimeType).isOverdueInstallment()) {
|
||||
throw new ChargeMustBePenaltyException(name);
|
||||
}
|
||||
|
||||
if (command.isChangeInLongParameterNamed(ChargesApiConstants.glAccountIdParamName, getIncomeAccountId())) {
|
||||
final Long newValue = command.longValueOfParameterNamed(ChargesApiConstants.glAccountIdParamName);
|
||||
actualChanges.put(ChargesApiConstants.glAccountIdParamName, newValue);
|
||||
}
|
||||
|
||||
if (command.isChangeInLongParameterNamed(ChargesApiConstants.taxGroupIdParamName, getTaxGroupId())) {
|
||||
final Long newValue = command.longValueOfParameterNamed(ChargesApiConstants.taxGroupIdParamName);
|
||||
actualChanges.put(ChargesApiConstants.taxGroupIdParamName, newValue);
|
||||
if (taxGroup != null) {
|
||||
baseDataValidator.reset().parameter(ChargesApiConstants.taxGroupIdParamName).failWithCode("modification.not.supported");
|
||||
}
|
||||
}
|
||||
|
||||
if (!dataValidationErrors.isEmpty()) {
|
||||
throw new PlatformApiDataValidationException(dataValidationErrors);
|
||||
}
|
||||
|
||||
return actualChanges;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete is a <i>soft delete</i>. Updates flag on charge so it wont appear in query/report results.
|
||||
*
|
||||
* Any fields with unique constraints and prepended with id of record.
|
||||
*/
|
||||
public void delete() {
|
||||
this.deleted = true;
|
||||
this.name = getId() + "_" + this.name;
|
||||
}
|
||||
|
||||
public ChargeData toData() {
|
||||
final EnumOptionData chargeTimeType = ChargeEnumerations.chargeTimeType(this.chargeTimeType);
|
||||
final EnumOptionData chargeAppliesTo = ChargeEnumerations.chargeAppliesTo(this.chargeAppliesTo);
|
||||
final EnumOptionData chargeCalculationType = ChargeEnumerations.chargeCalculationType(this.chargeCalculation);
|
||||
final EnumOptionData chargePaymentMode = ChargeEnumerations.chargePaymentMode(this.chargePaymentMode);
|
||||
EnumOptionData feeFrequencyType = null;
|
||||
if (this.feeFrequency != null) {
|
||||
feeFrequencyType = ChargeEnumerations.feeFrequencyType(this.feeFrequency);
|
||||
}
|
||||
GLAccountData accountData = null;
|
||||
if (account != null) {
|
||||
accountData = new GLAccountData().setId(account.getId()).setName(account.getName()).setGlCode(account.getGlCode());
|
||||
}
|
||||
TaxGroupData taxGroupData = null;
|
||||
if (this.taxGroup != null) {
|
||||
taxGroupData = TaxGroupData.lookup(taxGroup.getId(), taxGroup.getName());
|
||||
}
|
||||
|
||||
PaymentTypeData paymentTypeData = null;
|
||||
if (this.paymentType != null) {
|
||||
paymentTypeData = PaymentTypeData.instance(paymentType.getId(), paymentType.getName());
|
||||
}
|
||||
|
||||
final CurrencyData currency = new CurrencyData(this.currencyCode, null, 0, 0, null, null);
|
||||
return ChargeData.instance(getId(), this.name, this.amount, currency, chargeTimeType, chargeAppliesTo, chargeCalculationType,
|
||||
chargePaymentMode, getFeeOnMonthDay(), this.feeInterval, this.penalty, this.active, this.enableFreeWithdrawal,
|
||||
this.freeWithdrawalFrequency, this.restartFrequency, this.restartFrequencyEnum, this.enablePaymentType, paymentTypeData,
|
||||
this.minCap, this.maxCap, feeFrequencyType, accountData, taxGroupData);
|
||||
}
|
||||
|
||||
public Integer getChargePaymentMode() {
|
||||
return this.chargePaymentMode;
|
||||
}
|
||||
|
||||
public Integer getFeeInterval() {
|
||||
return this.feeInterval;
|
||||
}
|
||||
|
||||
public boolean isMonthlyFee() {
|
||||
return ChargeTimeType.fromInt(this.chargeTimeType).isMonthlyFee();
|
||||
}
|
||||
|
||||
public boolean isAnnualFee() {
|
||||
return ChargeTimeType.fromInt(this.chargeTimeType).isAnnualFee();
|
||||
}
|
||||
|
||||
public boolean isOverdueInstallment() {
|
||||
return ChargeTimeType.fromInt(this.chargeTimeType).isOverdueInstallment();
|
||||
}
|
||||
|
||||
public MonthDay getFeeOnMonthDay() {
|
||||
MonthDay feeOnMonthDay = null;
|
||||
if (this.feeOnDay != null && this.feeOnMonth != null) {
|
||||
feeOnMonthDay = MonthDay.now(DateUtils.getDateTimeZoneOfTenant()).withMonth(this.feeOnMonth).withDayOfMonth(this.feeOnDay);
|
||||
}
|
||||
return feeOnMonthDay;
|
||||
}
|
||||
|
||||
public Integer feeInterval() {
|
||||
return this.feeInterval;
|
||||
}
|
||||
|
||||
public Integer feeFrequency() {
|
||||
return this.feeFrequency;
|
||||
}
|
||||
|
||||
public GLAccount getAccount() {
|
||||
return this.account;
|
||||
}
|
||||
|
||||
public void setAccount(GLAccount account) {
|
||||
this.account = account;
|
||||
}
|
||||
|
||||
public Long getIncomeAccountId() {
|
||||
Long incomeAccountId = null;
|
||||
if (this.account != null) {
|
||||
incomeAccountId = this.account.getId();
|
||||
}
|
||||
return incomeAccountId;
|
||||
}
|
||||
|
||||
private Long getTaxGroupId() {
|
||||
Long taxGroupId = null;
|
||||
if (this.taxGroup != null) {
|
||||
taxGroupId = this.taxGroup.getId();
|
||||
}
|
||||
return taxGroupId;
|
||||
}
|
||||
|
||||
public boolean isDisbursementCharge() {
|
||||
return ChargeTimeType.fromInt(this.chargeTimeType).equals(ChargeTimeType.DISBURSEMENT)
|
||||
|| ChargeTimeType.fromInt(this.chargeTimeType).equals(ChargeTimeType.TRANCHE_DISBURSEMENT);
|
||||
}
|
||||
|
||||
public TaxGroup getTaxGroup() {
|
||||
return this.taxGroup;
|
||||
}
|
||||
|
||||
public void setTaxGroup(TaxGroup taxGroup) {
|
||||
this.taxGroup = taxGroup;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (!(o instanceof Charge)) {
|
||||
return false;
|
||||
}
|
||||
Charge other = (Charge) o;
|
||||
return Objects.equals(name, other.name) && Objects.equals(amount, other.amount) && Objects.equals(currencyCode, other.currencyCode)
|
||||
&& Objects.equals(chargeAppliesTo, other.chargeAppliesTo) && Objects.equals(chargeTimeType, other.chargeTimeType)
|
||||
&& Objects.equals(chargeCalculation, other.chargeCalculation) && Objects.equals(chargePaymentMode, other.chargePaymentMode)
|
||||
&& Objects.equals(feeOnDay, other.feeOnDay) && Objects.equals(feeInterval, other.feeInterval)
|
||||
&& Objects.equals(feeOnMonth, other.feeOnMonth) && penalty == other.penalty && active == other.active
|
||||
&& deleted == other.deleted && Objects.equals(minCap, other.minCap) && Objects.equals(maxCap, other.maxCap)
|
||||
&& Objects.equals(feeFrequency, other.feeFrequency) && Objects.equals(account, other.account)
|
||||
&& Objects.equals(taxGroup, other.taxGroup);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(name, amount, currencyCode, chargeAppliesTo, chargeTimeType, chargeCalculation, chargePaymentMode, feeOnDay,
|
||||
feeInterval, feeOnMonth, penalty, active, deleted, minCap, maxCap, feeFrequency, account, taxGroup);
|
||||
}
|
||||
}
|
||||
+90
@@ -0,0 +1,90 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.charge.domain;
|
||||
|
||||
public enum ChargeAppliesTo {
|
||||
|
||||
INVALID(0, "chargeAppliesTo.invalid"), //
|
||||
LOAN(1, "chargeAppliesTo.loan"), //
|
||||
SAVINGS(2, "chargeAppliesTo.savings"), //
|
||||
CLIENT(3, "chargeAppliesTo.client"), SHARES(4, "chargeAppliesTo.shares");
|
||||
|
||||
private final Integer value;
|
||||
private final String code;
|
||||
|
||||
ChargeAppliesTo(final Integer value, final String code) {
|
||||
this.value = value;
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public Integer getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return this.code;
|
||||
}
|
||||
|
||||
public static ChargeAppliesTo fromInt(final Integer chargeAppliesTo) {
|
||||
ChargeAppliesTo chargeAppliesToType = ChargeAppliesTo.INVALID;
|
||||
|
||||
if (chargeAppliesTo != null) {
|
||||
switch (chargeAppliesTo) {
|
||||
case 1:
|
||||
chargeAppliesToType = LOAN;
|
||||
break;
|
||||
case 2:
|
||||
chargeAppliesToType = SAVINGS;
|
||||
break;
|
||||
case 3:
|
||||
chargeAppliesToType = CLIENT;
|
||||
break;
|
||||
case 4:
|
||||
chargeAppliesToType = SHARES;
|
||||
break;
|
||||
default:
|
||||
chargeAppliesToType = INVALID;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return chargeAppliesToType;
|
||||
}
|
||||
|
||||
public boolean isLoanCharge() {
|
||||
return this.value.equals(ChargeAppliesTo.LOAN.getValue());
|
||||
}
|
||||
|
||||
public boolean isSavingsCharge() {
|
||||
return this.value.equals(ChargeAppliesTo.SAVINGS.getValue());
|
||||
}
|
||||
|
||||
public boolean isClientCharge() {
|
||||
return this.value.equals(ChargeAppliesTo.CLIENT.getValue());
|
||||
}
|
||||
|
||||
public boolean isSharesCharge() {
|
||||
return this.value.equals(SHARES.getValue());
|
||||
}
|
||||
|
||||
public static Object[] validValues() {
|
||||
return new Object[] { ChargeAppliesTo.LOAN.getValue(), ChargeAppliesTo.SAVINGS.getValue(), ChargeAppliesTo.CLIENT.getValue(),
|
||||
ChargeAppliesTo.SHARES.getValue() };
|
||||
}
|
||||
}
|
||||
+126
@@ -0,0 +1,126 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.charge.domain;
|
||||
|
||||
public enum ChargeCalculationType {
|
||||
|
||||
INVALID(0, "chargeCalculationType.invalid"), //
|
||||
FLAT(1, "chargeCalculationType.flat"), //
|
||||
PERCENT_OF_AMOUNT(2, "chargeCalculationType.percent.of.amount"), //
|
||||
PERCENT_OF_AMOUNT_AND_INTEREST(3, "chargeCalculationType.percent.of.amount.and.interest"), //
|
||||
PERCENT_OF_INTEREST(4, "chargeCalculationType.percent.of.interest"), PERCENT_OF_DISBURSEMENT_AMOUNT(5,
|
||||
"chargeCalculationType.percent.of.disbursement.amount");
|
||||
|
||||
private final Integer value;
|
||||
private final String code;
|
||||
|
||||
ChargeCalculationType(final Integer value, final String code) {
|
||||
this.value = value;
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public Integer getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return this.code;
|
||||
}
|
||||
|
||||
public static Object[] validValuesForLoan() {
|
||||
return new Integer[] { ChargeCalculationType.FLAT.getValue(), ChargeCalculationType.PERCENT_OF_AMOUNT.getValue(),
|
||||
ChargeCalculationType.PERCENT_OF_AMOUNT_AND_INTEREST.getValue(), ChargeCalculationType.PERCENT_OF_INTEREST.getValue(),
|
||||
ChargeCalculationType.PERCENT_OF_DISBURSEMENT_AMOUNT.getValue() };
|
||||
}
|
||||
|
||||
public static Object[] validValuesForSavings() {
|
||||
return new Integer[] { ChargeCalculationType.FLAT.getValue(), ChargeCalculationType.PERCENT_OF_AMOUNT.getValue() };
|
||||
}
|
||||
|
||||
public static Object[] validValuesForShares() {
|
||||
return new Integer[] { ChargeCalculationType.FLAT.getValue(), ChargeCalculationType.PERCENT_OF_AMOUNT.getValue() };
|
||||
}
|
||||
|
||||
public static Object[] validValuesForClients() {
|
||||
return new Integer[] { ChargeCalculationType.FLAT.getValue() };
|
||||
}
|
||||
|
||||
public static Object[] validValuesForShareAccountActivation() {
|
||||
return new Integer[] { ChargeCalculationType.FLAT.getValue() };
|
||||
}
|
||||
|
||||
public static Object[] validValuesForTrancheDisbursement() {
|
||||
return new Integer[] { ChargeCalculationType.FLAT.getValue(), ChargeCalculationType.PERCENT_OF_DISBURSEMENT_AMOUNT.getValue() };
|
||||
}
|
||||
|
||||
public static ChargeCalculationType fromInt(final Integer chargeCalculation) {
|
||||
ChargeCalculationType chargeCalculationType = ChargeCalculationType.INVALID;
|
||||
switch (chargeCalculation) {
|
||||
case 1:
|
||||
chargeCalculationType = FLAT;
|
||||
break;
|
||||
case 2:
|
||||
chargeCalculationType = PERCENT_OF_AMOUNT;
|
||||
break;
|
||||
case 3:
|
||||
chargeCalculationType = PERCENT_OF_AMOUNT_AND_INTEREST;
|
||||
break;
|
||||
case 4:
|
||||
chargeCalculationType = PERCENT_OF_INTEREST;
|
||||
break;
|
||||
case 5:
|
||||
chargeCalculationType = PERCENT_OF_DISBURSEMENT_AMOUNT;
|
||||
break;
|
||||
}
|
||||
return chargeCalculationType;
|
||||
}
|
||||
|
||||
public boolean isPercentageOfAmount() {
|
||||
return this.value.equals(ChargeCalculationType.PERCENT_OF_AMOUNT.getValue());
|
||||
}
|
||||
|
||||
public boolean isPercentageOfAmountAndInterest() {
|
||||
return this.value.equals(ChargeCalculationType.PERCENT_OF_AMOUNT_AND_INTEREST.getValue());
|
||||
}
|
||||
|
||||
public boolean isPercentageOfInterest() {
|
||||
return this.value.equals(ChargeCalculationType.PERCENT_OF_INTEREST.getValue());
|
||||
}
|
||||
|
||||
public boolean isFlat() {
|
||||
return this.value.equals(ChargeCalculationType.FLAT.getValue());
|
||||
}
|
||||
|
||||
public boolean isAllowedSavingsChargeCalculationType() {
|
||||
return isFlat() || isPercentageOfAmount();
|
||||
}
|
||||
|
||||
public boolean isAllowedClientChargeCalculationType() {
|
||||
return isFlat();
|
||||
}
|
||||
|
||||
public boolean isPercentageBased() {
|
||||
return isPercentageOfAmount() || isPercentageOfAmountAndInterest() || isPercentageOfInterest()
|
||||
|| isPercentageOfDisbursementAmount();
|
||||
}
|
||||
|
||||
public boolean isPercentageOfDisbursementAmount() {
|
||||
return this.value.equals(ChargeCalculationType.PERCENT_OF_DISBURSEMENT_AMOUNT.getValue());
|
||||
}
|
||||
}
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.charge.domain;
|
||||
|
||||
public enum ChargePaymentMode {
|
||||
|
||||
REGULAR(0, "chargepaymentmode.regular"), //
|
||||
ACCOUNT_TRANSFER(1, "chargepaymentmode.accounttransfer");
|
||||
|
||||
private final Integer value;
|
||||
private final String code;
|
||||
|
||||
ChargePaymentMode(final Integer value, final String code) {
|
||||
this.value = value;
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
public Integer getValue() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
public String getCode() {
|
||||
return this.code;
|
||||
}
|
||||
|
||||
public static Object[] validValues() {
|
||||
return new Integer[] { ChargePaymentMode.REGULAR.getValue(), ChargePaymentMode.ACCOUNT_TRANSFER.getValue() };
|
||||
}
|
||||
|
||||
public static ChargePaymentMode fromInt(final Integer paymentMode) {
|
||||
ChargePaymentMode chargeAppliesToType = ChargePaymentMode.REGULAR;
|
||||
switch (paymentMode) {
|
||||
case 1:
|
||||
chargeAppliesToType = ACCOUNT_TRANSFER;
|
||||
break;
|
||||
default:
|
||||
chargeAppliesToType = REGULAR;
|
||||
break;
|
||||
}
|
||||
return chargeAppliesToType;
|
||||
}
|
||||
|
||||
public boolean isPaymentModeAccountTransfer() {
|
||||
return this.value.equals(ChargePaymentMode.ACCOUNT_TRANSFER.getValue());
|
||||
}
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.charge.domain;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
|
||||
|
||||
public interface ChargeRepository extends JpaRepository<Charge, Long>, JpaSpecificationExecutor<Charge> {
|
||||
// no added behaviour
|
||||
}
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.charge.domain;
|
||||
|
||||
import org.apache.fineract.portfolio.charge.exception.ChargeIsNotActiveException;
|
||||
import org.apache.fineract.portfolio.charge.exception.ChargeNotFoundException;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Wrapper for {@link ChargeRepository} that is responsible for checking if {@link Charge} is returned when using
|
||||
* <code>findOne</code> repository method and throwing an appropriate not found exception.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* This is to avoid need for checking and throwing in multiple areas of code base where {@link ChargeRepository} is
|
||||
* required.
|
||||
* </p>
|
||||
*/
|
||||
@Service
|
||||
public class ChargeRepositoryWrapper {
|
||||
|
||||
private final ChargeRepository repository;
|
||||
|
||||
@Autowired
|
||||
public ChargeRepositoryWrapper(final ChargeRepository repository) {
|
||||
this.repository = repository;
|
||||
}
|
||||
|
||||
public Charge findOneWithNotFoundDetection(final Long id) {
|
||||
|
||||
final Charge chargeDefinition = this.repository.findById(id).orElseThrow(() -> new ChargeNotFoundException(id));
|
||||
if (chargeDefinition.isDeleted()) {
|
||||
throw new ChargeNotFoundException(id);
|
||||
}
|
||||
if (!chargeDefinition.isActive()) {
|
||||
throw new ChargeIsNotActiveException(id, chargeDefinition.getName());
|
||||
}
|
||||
|
||||
return chargeDefinition;
|
||||
}
|
||||
}
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.charge.exception;
|
||||
|
||||
import org.apache.fineract.infrastructure.core.exception.AbstractPlatformDomainRuleException;
|
||||
|
||||
public class ChargeCannotBeAppliedToException extends AbstractPlatformDomainRuleException {
|
||||
|
||||
public ChargeCannotBeAppliedToException(final String postFix, final String defaultUserMessage, final Object... defaultUserMessageArgs) {
|
||||
|
||||
super("error.msg.charge.cannot.be.applied.to" + postFix, defaultUserMessage, defaultUserMessageArgs);
|
||||
}
|
||||
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.charge.exception;
|
||||
|
||||
import org.apache.fineract.infrastructure.core.exception.AbstractPlatformDomainRuleException;
|
||||
|
||||
public class ChargeCannotBeDeletedException extends AbstractPlatformDomainRuleException {
|
||||
|
||||
public ChargeCannotBeDeletedException(final String globalisationMessageCode, final String defaultUserMessage,
|
||||
final Object... defaultUserMessageArgs) {
|
||||
|
||||
super(globalisationMessageCode, defaultUserMessage, defaultUserMessageArgs);
|
||||
}
|
||||
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.charge.exception;
|
||||
|
||||
import org.apache.fineract.infrastructure.core.exception.AbstractPlatformDomainRuleException;
|
||||
|
||||
public class ChargeCannotBeUpdatedException extends AbstractPlatformDomainRuleException {
|
||||
|
||||
public ChargeCannotBeUpdatedException(final String globalisationMessageCode, final String defaultUserMessage,
|
||||
final Object... defaultUserMessageArgs) {
|
||||
|
||||
super(globalisationMessageCode, defaultUserMessage, defaultUserMessageArgs);
|
||||
}
|
||||
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.charge.exception;
|
||||
|
||||
import org.apache.fineract.infrastructure.core.exception.AbstractPlatformDomainRuleException;
|
||||
|
||||
/**
|
||||
* {@link AbstractPlatformDomainRuleException} thrown when attempting to crate charge of type penalty due at
|
||||
* disbursement .
|
||||
*/
|
||||
public class ChargeDueAtDisbursementCannotBePenaltyException extends AbstractPlatformDomainRuleException {
|
||||
|
||||
public ChargeDueAtDisbursementCannotBePenaltyException(final String name) {
|
||||
super("error.msg.charge.due.at.disbursement.cannot.be.penalty", "Charge '" + name + "' is invalid.", name, name);
|
||||
}
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.charge.exception;
|
||||
|
||||
import org.apache.fineract.infrastructure.core.exception.AbstractPlatformDomainRuleException;
|
||||
|
||||
/**
|
||||
* {@link AbstractPlatformDomainRuleException} thrown when charge is not active.
|
||||
*/
|
||||
public class ChargeIsNotActiveException extends AbstractPlatformDomainRuleException {
|
||||
|
||||
public ChargeIsNotActiveException(final Long id, final String name) {
|
||||
super("error.msg.charge.is.not.active", "Charge '" + name + "' with identifier " + id + " is not active", name, id);
|
||||
}
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.charge.exception;
|
||||
|
||||
import org.apache.fineract.infrastructure.core.exception.AbstractPlatformDomainRuleException;
|
||||
|
||||
/**
|
||||
* {@link AbstractPlatformDomainRuleException} thrown when attempting to crate charge of type penalty due at
|
||||
* disbursement .
|
||||
*/
|
||||
public class ChargeMustBePenaltyException extends AbstractPlatformDomainRuleException {
|
||||
|
||||
public ChargeMustBePenaltyException(final String name) {
|
||||
super("error.msg.charge.must.be.penalty", "Charge '" + name + "' is invalid.", name, name);
|
||||
}
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.charge.exception;
|
||||
|
||||
import org.apache.fineract.infrastructure.core.exception.AbstractPlatformResourceNotFoundException;
|
||||
import org.springframework.dao.EmptyResultDataAccessException;
|
||||
|
||||
public class ChargeNotFoundException extends AbstractPlatformResourceNotFoundException {
|
||||
|
||||
public ChargeNotFoundException(final Long id) {
|
||||
super("error.msg.charge.id.invalid", "Charge with identifier " + id + " does not exist", id);
|
||||
}
|
||||
|
||||
public ChargeNotFoundException(Long id, EmptyResultDataAccessException e) {
|
||||
super("error.msg.charge.id.invalid", "Charge with identifier " + id + " does not exist", id, e);
|
||||
}
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.charge.exception;
|
||||
|
||||
import org.apache.fineract.infrastructure.core.exception.AbstractPlatformDomainRuleException;
|
||||
|
||||
/**
|
||||
* {@link AbstractPlatformDomainRuleException} thrown when loan charge is not allowed to be added to the loan.
|
||||
*/
|
||||
public class LoanChargeCannotBeAddedException extends AbstractPlatformDomainRuleException {
|
||||
|
||||
public LoanChargeCannotBeAddedException(final String entity, final String postFix, final String defaultUserMessage,
|
||||
final Object... defaultUserMessageArgs) {
|
||||
super("error.msg." + entity + ".cannot.be.added.as." + postFix, defaultUserMessage, defaultUserMessageArgs);
|
||||
}
|
||||
|
||||
}
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.charge.exception;
|
||||
|
||||
import org.apache.fineract.infrastructure.core.exception.AbstractPlatformDomainRuleException;
|
||||
|
||||
public class LoanChargeCannotBeDeletedException extends AbstractPlatformDomainRuleException {
|
||||
|
||||
/*** enum of reasons of why Loan Charge cannot be waived **/
|
||||
public enum LoanChargeCannotBeDeletedReason {
|
||||
|
||||
ALREADY_PAID, ALREADY_WAIVED, LOAN_NOT_IN_SUBMITTED_AND_PENDING_APPROVAL_STAGE;
|
||||
|
||||
public String errorMessage() {
|
||||
if (name().toString().equalsIgnoreCase("ALREADY_PAID")) {
|
||||
return "This loan charge has been partially/completely paid";
|
||||
} else if (name().toString().equalsIgnoreCase("ALREADY_WAIVED")) {
|
||||
return "This loan charge has already been waived";
|
||||
} else if (name().toString().equalsIgnoreCase("LOAN_NOT_IN_SUBMITTED_AND_PENDING_APPROVAL_STAGE")) {
|
||||
return "This charge cannot be deleted as the loan it is associated with is not in submitted and pending approval stage";
|
||||
}
|
||||
return name().toString();
|
||||
}
|
||||
|
||||
public String errorCode() {
|
||||
if (name().toString().equalsIgnoreCase("ALREADY_PAID")) {
|
||||
return "error.msg.loan.charge.already.paid";
|
||||
} else if (name().toString().equalsIgnoreCase("ALREADY_WAIVED")) {
|
||||
return "error.msg.loan.charge.already.waived";
|
||||
} else if (name().toString().equalsIgnoreCase("LOAN_NOT_IN_SUBMITTED_AND_PENDING_APPROVAL_STAGE")) {
|
||||
return "error.msg.loan.charge.associated.loan.not.in.submitted.and.pending.approval.stage";
|
||||
}
|
||||
return name().toString();
|
||||
}
|
||||
}
|
||||
|
||||
public LoanChargeCannotBeDeletedException(final LoanChargeCannotBeDeletedReason reason, final Long loanChargeId) {
|
||||
super(reason.errorCode(), reason.errorMessage(), loanChargeId);
|
||||
}
|
||||
}
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.charge.exception;
|
||||
|
||||
import org.apache.fineract.infrastructure.core.exception.AbstractPlatformDomainRuleException;
|
||||
|
||||
public class LoanChargeCannotBePayedException extends AbstractPlatformDomainRuleException {
|
||||
|
||||
/*** enum of reasons of why Loan Charge cannot be waived **/
|
||||
public enum LoanChargeCannotBePayedReason {
|
||||
|
||||
ALREADY_PAID, ALREADY_WAIVED, LOAN_INACTIVE, CHARGE_NOT_ACCOUNT_TRANSFER, CHARGE_NOT_PAYABLE;
|
||||
|
||||
public String errorMessage() {
|
||||
if (name().toString().equalsIgnoreCase("ALREADY_PAID")) {
|
||||
return "This loan charge has been completely paid";
|
||||
} else if (name().toString().equalsIgnoreCase("ALREADY_WAIVED")) {
|
||||
return "This loan charge has already been waived";
|
||||
} else if (name().toString().equalsIgnoreCase("LOAN_INACTIVE")) {
|
||||
return "This loan charge can be payed as the loan associated with it is currently inactive";
|
||||
} else if (name().toString().equalsIgnoreCase("CHARGE_NOT_ACCOUNT_TRANSFER")) {
|
||||
return "This loan charge can be payed as the charge payment mode is not account transfer";
|
||||
} else if (name().toString().equalsIgnoreCase("CHARGE_NOT_PAYABLE")) {
|
||||
return "This loan charge is not Payable through account transfer";
|
||||
}
|
||||
|
||||
return name().toString();
|
||||
}
|
||||
|
||||
public String errorCode() {
|
||||
if (name().toString().equalsIgnoreCase("ALREADY_PAID")) {
|
||||
return "error.msg.loan.charge.already.paid";
|
||||
} else if (name().toString().equalsIgnoreCase("ALREADY_WAIVED")) {
|
||||
return "error.msg.loan.charge.already.waived";
|
||||
} else if (name().toString().equalsIgnoreCase("LOAN_INACTIVE")) {
|
||||
return "error.msg.loan.charge.associated.loan.inactive";
|
||||
} else if (name().toString().equalsIgnoreCase("CHARGE_NOT_ACCOUNT_TRANSFER")) {
|
||||
return "error.msg.loan.charge.payment.mode.not.account.transfer";
|
||||
} else if (name().toString().equalsIgnoreCase("CHARGE_NOT_PAYABLE")) {
|
||||
return "error.msg.loan.charge.payment.not.allowed.account.transfer";
|
||||
}
|
||||
return name().toString();
|
||||
}
|
||||
}
|
||||
|
||||
public LoanChargeCannotBePayedException(final LoanChargeCannotBePayedReason reason, final Long loanChargeId) {
|
||||
super(reason.errorCode(), reason.errorMessage(), loanChargeId);
|
||||
}
|
||||
}
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.charge.exception;
|
||||
|
||||
import org.apache.fineract.infrastructure.core.exception.AbstractPlatformDomainRuleException;
|
||||
|
||||
public class LoanChargeCannotBeUpdatedException extends AbstractPlatformDomainRuleException {
|
||||
|
||||
/*** enum of reasons of why Loan Charge cannot be waived **/
|
||||
public enum LoanChargeCannotBeUpdatedReason {
|
||||
|
||||
ALREADY_PAID, ALREADY_WAIVED, LOAN_NOT_IN_SUBMITTED_AND_PENDING_APPROVAL_STAGE;
|
||||
|
||||
public String errorMessage() {
|
||||
if (name().toString().equalsIgnoreCase("ALREADY_PAID")) {
|
||||
return "This loan charge has been partially/completely paid";
|
||||
} else if (name().toString().equalsIgnoreCase("ALREADY_WAIVED")) {
|
||||
return "This loan charge has already been waived";
|
||||
} else if (name().toString().equalsIgnoreCase("LOAN_NOT_IN_SUBMITTED_AND_PENDING_APPROVAL_STAGE")) {
|
||||
return "This charge cannot be updated as the loan it is associated with is not in submitted and pending approval stage";
|
||||
}
|
||||
return name().toString();
|
||||
}
|
||||
|
||||
public String errorCode() {
|
||||
if (name().toString().equalsIgnoreCase("ALREADY_PAID")) {
|
||||
return "error.msg.loan.charge.already.paid";
|
||||
} else if (name().toString().equalsIgnoreCase("ALREADY_WAIVED")) {
|
||||
return "error.msg.loan.charge.already.waived";
|
||||
} else if (name().toString().equalsIgnoreCase("LOAN_NOT_IN_SUBMITTED_AND_PENDING_APPROVAL_STAGE")) {
|
||||
return "error.msg.loan.charge.associated.loan.not.in.submitted.and.pending.approval.stage";
|
||||
}
|
||||
return name().toString();
|
||||
}
|
||||
}
|
||||
|
||||
public LoanChargeCannotBeUpdatedException(final LoanChargeCannotBeUpdatedReason reason, final Long loanChargeId) {
|
||||
super(reason.errorCode(), reason.errorMessage(), loanChargeId);
|
||||
}
|
||||
}
|
||||
+61
@@ -0,0 +1,61 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.charge.exception;
|
||||
|
||||
import org.apache.fineract.infrastructure.core.exception.AbstractPlatformDomainRuleException;
|
||||
|
||||
public class LoanChargeCannotBeWaivedException extends AbstractPlatformDomainRuleException {
|
||||
|
||||
/*** enum of reasons of why Loan Charge cannot be waived **/
|
||||
public enum LoanChargeCannotBeWaivedReason {
|
||||
|
||||
ALREADY_PAID, ALREADY_WAIVED, LOAN_INACTIVE, WAIVE_NOT_ALLOWED_FOR_CHARGE;
|
||||
|
||||
public String errorMessage() {
|
||||
if (name().toString().equalsIgnoreCase("ALREADY_PAID")) {
|
||||
return "This loan charge has been completely paid";
|
||||
} else if (name().toString().equalsIgnoreCase("ALREADY_WAIVED")) {
|
||||
return "This loan charge has already been waived";
|
||||
} else if (name().toString().equalsIgnoreCase("LOAN_INACTIVE")) {
|
||||
return "This loan charge can be waived as the loan associated with it is currently inactive";
|
||||
} else if (name().toString().equalsIgnoreCase("WAIVE_NOT_ALLOWED_FOR_CHARGE")) {
|
||||
return "This loan charge can be waived";
|
||||
}
|
||||
|
||||
return name().toString();
|
||||
}
|
||||
|
||||
public String errorCode() {
|
||||
if (name().toString().equalsIgnoreCase("ALREADY_PAID")) {
|
||||
return "error.msg.loan.charge.already.paid";
|
||||
} else if (name().toString().equalsIgnoreCase("ALREADY_WAIVED")) {
|
||||
return "error.msg.loan.charge.already.waived";
|
||||
} else if (name().toString().equalsIgnoreCase("LOAN_INACTIVE")) {
|
||||
return "error.msg.loan.charge.associated.loan.inactive";
|
||||
} else if (name().toString().equalsIgnoreCase("WAIVE_NOT_ALLOWED_FOR_CHARGE")) {
|
||||
return "error.msg.loan.charge.waive.not.allowed";
|
||||
}
|
||||
return name().toString();
|
||||
}
|
||||
}
|
||||
|
||||
public LoanChargeCannotBeWaivedException(final LoanChargeCannotBeWaivedReason reason, final Long loanChargeId) {
|
||||
super(reason.errorCode(), reason.errorMessage(), loanChargeId);
|
||||
}
|
||||
}
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.charge.exception;
|
||||
|
||||
import org.apache.commons.lang3.ObjectUtils;
|
||||
import org.apache.fineract.infrastructure.core.domain.ExternalId;
|
||||
import org.apache.fineract.infrastructure.core.exception.AbstractPlatformDomainRuleException;
|
||||
import org.apache.fineract.infrastructure.core.exception.AbstractPlatformResourceNotFoundException;
|
||||
import org.springframework.dao.EmptyResultDataAccessException;
|
||||
|
||||
/**
|
||||
* {@link AbstractPlatformDomainRuleException} thrown when loan charge does not exist.
|
||||
*/
|
||||
public class LoanChargeNotFoundException extends AbstractPlatformResourceNotFoundException {
|
||||
|
||||
public LoanChargeNotFoundException() {
|
||||
super("error.msg.loanCharge.invalid", "Loan charge cannot be found");
|
||||
}
|
||||
|
||||
public LoanChargeNotFoundException(final Long id) {
|
||||
super("error.msg.loanCharge.id.invalid", "Loan charge with identifier " + id + " does not exist", id);
|
||||
}
|
||||
|
||||
public LoanChargeNotFoundException(final Long id, final Long loanId) {
|
||||
super("error.msg.loanCharge.id.invalid.for.given.loan", "Loan charge with identifier " + id + " does not exist for loan " + loanId,
|
||||
id, loanId);
|
||||
}
|
||||
|
||||
public LoanChargeNotFoundException(final Long id, final Long loanId, final EmptyResultDataAccessException e) {
|
||||
super("error.msg.loanCharge.id.invalid.for.given.loan", "Loan charge with identifier " + id + " does not exist for loan " + loanId,
|
||||
id, loanId, e);
|
||||
}
|
||||
|
||||
public LoanChargeNotFoundException(ExternalId externalId) {
|
||||
super("error.msg.loanCharge.external.id.invalid", "Loan Charge with external identifier "
|
||||
+ ObjectUtils.defaultIfNull(externalId, ExternalId.empty()).getValue() + " does not exist", externalId);
|
||||
}
|
||||
}
|
||||
+71
@@ -0,0 +1,71 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.charge.exception;
|
||||
|
||||
import org.apache.fineract.infrastructure.core.exception.AbstractPlatformDomainRuleException;
|
||||
|
||||
public class LoanChargeWaiveCannotBeReversedException extends AbstractPlatformDomainRuleException {
|
||||
|
||||
/*** enum of reasons of why Loan Charge waive cannot undo **/
|
||||
public enum LoanChargeWaiveCannotUndoReason {
|
||||
|
||||
ALREADY_PAID, ALREADY_WAIVED, LOAN_INACTIVE, WAIVE_NOT_ALLOWED_FOR_CHARGE, NOT_WAIVED, ALREADY_REVERSED;
|
||||
|
||||
public String errorMessage() {
|
||||
|
||||
if (name().equalsIgnoreCase("ALREADY_PAID")) {
|
||||
return "This loan charge has been completely paid";
|
||||
} else if (name().equalsIgnoreCase("ALREADY_WAIVED")) {
|
||||
return "This loan charge has already been waived";
|
||||
} else if (name().equalsIgnoreCase("LOAN_INACTIVE")) {
|
||||
return "This loan charge can be waived as the loan associated with it is currently inactive";
|
||||
} else if (name().equalsIgnoreCase("WAIVE_NOT_ALLOWED_FOR_CHARGE")) {
|
||||
return "This loan charge can be waived";
|
||||
} else if (name().equalsIgnoreCase("NOT_WAIVED")) {
|
||||
return "This loan charge waive cannot be reversed as this charge is not waived";
|
||||
} else if (name().equalsIgnoreCase("ALREADY_REVERSED")) {
|
||||
return "This loan charge waive cannot be reversed as this transaction is already reversed";
|
||||
}
|
||||
|
||||
return name();
|
||||
}
|
||||
|
||||
public String errorCode() {
|
||||
if (name().equalsIgnoreCase("ALREADY_PAID")) {
|
||||
return "error.msg.loan.charge.already.paid";
|
||||
} else if (name().equalsIgnoreCase("ALREADY_WAIVED")) {
|
||||
return "error.msg.loan.charge.already.waived";
|
||||
} else if (name().equalsIgnoreCase("LOAN_INACTIVE")) {
|
||||
return "error.msg.loan.charge.associated.loan.inactive";
|
||||
} else if (name().equalsIgnoreCase("WAIVE_NOT_ALLOWED_FOR_CHARGE")) {
|
||||
return "error.msg.loan.charge.waive.not.allowed";
|
||||
} else if (name().equalsIgnoreCase("NOT_WAIVED")) {
|
||||
return "error.msg.loan.charge.waive.cannot.undo";
|
||||
} else if (name().equalsIgnoreCase("ALREADY_REVERSED")) {
|
||||
return "error.msg.transaction.cannot.reverse";
|
||||
}
|
||||
return name();
|
||||
}
|
||||
}
|
||||
|
||||
public LoanChargeWaiveCannotBeReversedException(final LoanChargeWaiveCannotUndoReason reason, final Long id) {
|
||||
super(reason.errorCode(), reason.errorMessage(), id);
|
||||
}
|
||||
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.charge.exception;
|
||||
|
||||
import org.apache.fineract.infrastructure.core.exception.AbstractPlatformDomainRuleException;
|
||||
|
||||
/**
|
||||
* {@link AbstractPlatformDomainRuleException} thrown when currency mismatch occurs
|
||||
*/
|
||||
public class ShareAccountChargeWithoutMandatoryFieldException extends AbstractPlatformDomainRuleException {
|
||||
|
||||
public ShareAccountChargeWithoutMandatoryFieldException(final String entity, final String postFix, final String defaultUserMessage,
|
||||
final Object... defaultUserMessageArgs) {
|
||||
super("error.msg." + entity + "." + postFix + ".cannot.be.blank", defaultUserMessage, defaultUserMessageArgs);
|
||||
}
|
||||
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.charge.handler;
|
||||
|
||||
import org.apache.fineract.commands.annotation.CommandType;
|
||||
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.apache.fineract.portfolio.charge.service.ChargeWritePlatformService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Service
|
||||
@CommandType(entity = "CHARGE", action = "CREATE")
|
||||
public class CreateChargeDefinitionCommandHandler implements NewCommandSourceHandler {
|
||||
|
||||
private final ChargeWritePlatformService clientWritePlatformService;
|
||||
|
||||
@Autowired
|
||||
public CreateChargeDefinitionCommandHandler(final ChargeWritePlatformService clientWritePlatformService) {
|
||||
this.clientWritePlatformService = clientWritePlatformService;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public CommandProcessingResult processCommand(final JsonCommand command) {
|
||||
|
||||
return this.clientWritePlatformService.createCharge(command);
|
||||
}
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.charge.handler;
|
||||
|
||||
import org.apache.fineract.commands.annotation.CommandType;
|
||||
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.apache.fineract.portfolio.charge.service.ChargeWritePlatformService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Service
|
||||
@CommandType(entity = "CHARGE", action = "DELETE")
|
||||
public class DeleteChargeDefinitionCommandHandler implements NewCommandSourceHandler {
|
||||
|
||||
private final ChargeWritePlatformService clientWritePlatformService;
|
||||
|
||||
@Autowired
|
||||
public DeleteChargeDefinitionCommandHandler(final ChargeWritePlatformService clientWritePlatformService) {
|
||||
this.clientWritePlatformService = clientWritePlatformService;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public CommandProcessingResult processCommand(final JsonCommand command) {
|
||||
|
||||
return this.clientWritePlatformService.deleteCharge(command.entityId());
|
||||
}
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.charge.handler;
|
||||
|
||||
import org.apache.fineract.commands.annotation.CommandType;
|
||||
import org.apache.fineract.commands.handler.NewCommandSourceHandler;
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
import org.apache.fineract.portfolio.charge.service.ChargeWritePlatformService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Service
|
||||
@CommandType(entity = "CHARGE", action = "UPDATE")
|
||||
public class UpdateChargeDefinitionCommandHandler implements NewCommandSourceHandler {
|
||||
|
||||
private final ChargeWritePlatformService clientWritePlatformService;
|
||||
|
||||
@Autowired
|
||||
public UpdateChargeDefinitionCommandHandler(final ChargeWritePlatformService clientWritePlatformService) {
|
||||
this.clientWritePlatformService = clientWritePlatformService;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@Override
|
||||
public CommandProcessingResult processCommand(final JsonCommand command) {
|
||||
|
||||
return this.clientWritePlatformService.updateCharge(command.entityId(), command);
|
||||
}
|
||||
}
|
||||
+487
@@ -0,0 +1,487 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.charge.serialization;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import java.lang.reflect.Type;
|
||||
import java.math.BigDecimal;
|
||||
import java.time.MonthDay;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.fineract.infrastructure.core.data.ApiParameterError;
|
||||
import org.apache.fineract.infrastructure.core.data.DataValidatorBuilder;
|
||||
import org.apache.fineract.infrastructure.core.exception.InvalidJsonException;
|
||||
import org.apache.fineract.infrastructure.core.exception.PlatformApiDataValidationException;
|
||||
import org.apache.fineract.infrastructure.core.serialization.FromJsonHelper;
|
||||
import org.apache.fineract.portfolio.charge.api.ChargesApiConstants;
|
||||
import org.apache.fineract.portfolio.charge.domain.ChargeAppliesTo;
|
||||
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.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public final class ChargeDefinitionCommandFromApiJsonDeserializer {
|
||||
|
||||
public static final String NAME = "name";
|
||||
public static final String AMOUNT = "amount";
|
||||
public static final String LOCALE = "locale";
|
||||
public static final String CURRENCY_CODE = "currencyCode";
|
||||
public static final String PENALTY = "penalty";
|
||||
public static final String CHARGE_CALCULATION_TYPE_OPTIONS = "chargeCalculationTypeOptions";
|
||||
public static final String CHARGE_CALCULATION_TYPE = "chargeCalculationType";
|
||||
public static final String CHARGE_TIME_TYPE = "chargeTimeType";
|
||||
public static final String CHARGE_APPLIES_TO = "chargeAppliesTo";
|
||||
public static final String CURRENCY_OPTIONS = "currencyOptions";
|
||||
public static final String ACTIVE = "active";
|
||||
public static final String CHARGE_PAYMENT_MODE = "chargePaymentMode";
|
||||
public static final String FEE_ON_MONTH_DAY = "feeOnMonthDay";
|
||||
public static final String FEE_INTERVAL = "feeInterval";
|
||||
public static final String MONTH_DAY_FORMAT = "monthDayFormat";
|
||||
public static final String MIN_CAP = "minCap";
|
||||
public static final String MAX_CAP = "maxCap";
|
||||
public static final String FEE_FREQUENCY = "feeFrequency";
|
||||
public static final String ENABLE_FREE_WITHDRAWAL_CHARGE = "enableFreeWithdrawalCharge";
|
||||
public static final String FREE_WITHDRAWAL_FREQUENCY = "freeWithdrawalFrequency";
|
||||
public static final String RESTART_COUNT_FREQUENCY = "restartCountFrequency";
|
||||
public static final String COUNT_FREQUENCY_TYPE = "countFrequencyType";
|
||||
public static final String ENABLE_PAYMENT_TYPE = "enablePaymentType";
|
||||
public static final String PAYMENT_TYPE_ID = "paymentTypeId";
|
||||
public static final String CHARGE = "charge";
|
||||
/**
|
||||
* The parameters supported for this command.
|
||||
*/
|
||||
private static final Set<String> SUPPORTED_PARAMETERS = new HashSet<>(Arrays.asList(NAME, AMOUNT, LOCALE, CURRENCY_CODE,
|
||||
CURRENCY_OPTIONS, CHARGE_APPLIES_TO, CHARGE_TIME_TYPE, CHARGE_CALCULATION_TYPE, CHARGE_CALCULATION_TYPE_OPTIONS, PENALTY,
|
||||
ACTIVE, CHARGE_PAYMENT_MODE, FEE_ON_MONTH_DAY, FEE_INTERVAL, MONTH_DAY_FORMAT, MIN_CAP, MAX_CAP, FEE_FREQUENCY,
|
||||
ENABLE_FREE_WITHDRAWAL_CHARGE, FREE_WITHDRAWAL_FREQUENCY, RESTART_COUNT_FREQUENCY, COUNT_FREQUENCY_TYPE, PAYMENT_TYPE_ID,
|
||||
ENABLE_PAYMENT_TYPE, ChargesApiConstants.glAccountIdParamName, ChargesApiConstants.taxGroupIdParamName));
|
||||
private final FromJsonHelper fromApiJsonHelper;
|
||||
|
||||
@Autowired
|
||||
public ChargeDefinitionCommandFromApiJsonDeserializer(final FromJsonHelper fromApiJsonHelper) {
|
||||
this.fromApiJsonHelper = fromApiJsonHelper;
|
||||
}
|
||||
|
||||
public void validateForCreate(final String json) {
|
||||
if (StringUtils.isBlank(json)) {
|
||||
throw new InvalidJsonException();
|
||||
}
|
||||
|
||||
final Type typeOfMap = new TypeToken<Map<String, Object>>() {
|
||||
|
||||
}.getType();
|
||||
this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, SUPPORTED_PARAMETERS);
|
||||
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource(CHARGE);
|
||||
|
||||
final JsonElement element = this.fromApiJsonHelper.parse(json);
|
||||
|
||||
final Integer chargeAppliesTo = this.fromApiJsonHelper.extractIntegerSansLocaleNamed(CHARGE_APPLIES_TO, element);
|
||||
baseDataValidator.reset().parameter(CHARGE_APPLIES_TO).value(chargeAppliesTo).notNull();
|
||||
if (chargeAppliesTo != null) {
|
||||
baseDataValidator.reset().parameter(CHARGE_APPLIES_TO).value(chargeAppliesTo).isOneOfTheseValues(ChargeAppliesTo.validValues());
|
||||
}
|
||||
|
||||
final Integer chargeCalculationType = this.fromApiJsonHelper.extractIntegerSansLocaleNamed(CHARGE_CALCULATION_TYPE, element);
|
||||
baseDataValidator.reset().parameter(CHARGE_CALCULATION_TYPE).value(chargeCalculationType).notNull();
|
||||
|
||||
final Integer feeInterval = this.fromApiJsonHelper.extractIntegerNamed(FEE_INTERVAL, element, Locale.getDefault());
|
||||
baseDataValidator.reset().parameter(FEE_INTERVAL).value(feeInterval).integerGreaterThanZero();
|
||||
|
||||
final Integer feeFrequency = this.fromApiJsonHelper.extractIntegerNamed(FEE_FREQUENCY, element, Locale.getDefault());
|
||||
baseDataValidator.reset().parameter(FEE_FREQUENCY).value(feeFrequency).inMinMaxRange(0, 3);
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(ENABLE_FREE_WITHDRAWAL_CHARGE, element)) {
|
||||
|
||||
final Boolean enableFreeWithdrawalCharge = this.fromApiJsonHelper.extractBooleanNamed(ENABLE_FREE_WITHDRAWAL_CHARGE, element);
|
||||
baseDataValidator.reset().parameter(ENABLE_FREE_WITHDRAWAL_CHARGE).value(enableFreeWithdrawalCharge).notNull();
|
||||
|
||||
if (enableFreeWithdrawalCharge) {
|
||||
|
||||
final Integer freeWithdrawalFrequency = this.fromApiJsonHelper.extractIntegerNamed(FREE_WITHDRAWAL_FREQUENCY, element,
|
||||
Locale.getDefault());
|
||||
baseDataValidator.reset().parameter(FREE_WITHDRAWAL_FREQUENCY).value(freeWithdrawalFrequency).integerGreaterThanZero();
|
||||
|
||||
final Integer restartCountFrequency = this.fromApiJsonHelper.extractIntegerNamed(RESTART_COUNT_FREQUENCY, element,
|
||||
Locale.getDefault());
|
||||
baseDataValidator.reset().parameter(RESTART_COUNT_FREQUENCY).value(restartCountFrequency).integerGreaterThanZero();
|
||||
|
||||
final Integer countFrequencyType = this.fromApiJsonHelper.extractIntegerNamed(COUNT_FREQUENCY_TYPE, element,
|
||||
Locale.getDefault());
|
||||
baseDataValidator.reset().parameter(COUNT_FREQUENCY_TYPE).value(countFrequencyType);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(ENABLE_PAYMENT_TYPE, element)) {
|
||||
|
||||
final boolean enablePaymentType = this.fromApiJsonHelper.extractBooleanNamed(ENABLE_PAYMENT_TYPE, element);
|
||||
baseDataValidator.reset().parameter(ENABLE_PAYMENT_TYPE).value(enablePaymentType).notNull();
|
||||
|
||||
if (enablePaymentType) {
|
||||
final Integer paymentTypeId = this.fromApiJsonHelper.extractIntegerNamed(PAYMENT_TYPE_ID, element, Locale.getDefault());
|
||||
baseDataValidator.reset().parameter(PAYMENT_TYPE_ID).value(paymentTypeId).integerGreaterThanZero();
|
||||
}
|
||||
}
|
||||
|
||||
if (feeFrequency != null) {
|
||||
baseDataValidator.reset().parameter(FEE_INTERVAL).value(feeInterval).notNull();
|
||||
}
|
||||
|
||||
final ChargeAppliesTo appliesTo = ChargeAppliesTo.fromInt(chargeAppliesTo);
|
||||
if (appliesTo.isLoanCharge()) {
|
||||
// loan applicable validation
|
||||
final Integer chargeTimeType = this.fromApiJsonHelper.extractIntegerSansLocaleNamed(CHARGE_TIME_TYPE, element);
|
||||
baseDataValidator.reset().parameter(CHARGE_TIME_TYPE).value(chargeTimeType).notNull();
|
||||
if (chargeTimeType != null) {
|
||||
baseDataValidator.reset().parameter(CHARGE_TIME_TYPE).value(chargeTimeType)
|
||||
.isOneOfTheseValues(ChargeTimeType.validLoanValues());
|
||||
}
|
||||
|
||||
final Integer chargePaymentMode = this.fromApiJsonHelper.extractIntegerSansLocaleNamed(CHARGE_PAYMENT_MODE, element);
|
||||
baseDataValidator.reset().parameter(CHARGE_PAYMENT_MODE).value(chargePaymentMode).notNull()
|
||||
.isOneOfTheseValues(ChargePaymentMode.validValues());
|
||||
if (chargePaymentMode != null) {
|
||||
baseDataValidator.reset().parameter(CHARGE_PAYMENT_MODE).value(chargePaymentMode)
|
||||
.isOneOfTheseValues(ChargePaymentMode.validValues());
|
||||
}
|
||||
|
||||
if (chargeCalculationType != null) {
|
||||
baseDataValidator.reset().parameter(CHARGE_CALCULATION_TYPE).value(chargeCalculationType)
|
||||
.isOneOfTheseValues(ChargeCalculationType.validValuesForLoan());
|
||||
}
|
||||
|
||||
if (chargeTimeType != null && chargeCalculationType != null) {
|
||||
performChargeTimeNCalculationTypeValidation(baseDataValidator, chargeTimeType, chargeCalculationType);
|
||||
}
|
||||
|
||||
} else if (appliesTo.isSavingsCharge()) {
|
||||
// savings applicable validation
|
||||
final Integer chargeTimeType = this.fromApiJsonHelper.extractIntegerSansLocaleNamed(CHARGE_TIME_TYPE, element);
|
||||
baseDataValidator.reset().parameter(CHARGE_TIME_TYPE).value(chargeTimeType).notNull();
|
||||
if (chargeTimeType != null) {
|
||||
baseDataValidator.reset().parameter(CHARGE_TIME_TYPE).value(chargeTimeType)
|
||||
.isOneOfTheseValues(ChargeTimeType.validSavingsValues());
|
||||
}
|
||||
|
||||
final ChargeTimeType ctt = ChargeTimeType.fromInt(chargeTimeType);
|
||||
|
||||
if (ctt.isWeeklyFee()) {
|
||||
final String monthDay = this.fromApiJsonHelper.extractStringNamed(FEE_ON_MONTH_DAY, element);
|
||||
baseDataValidator.reset().parameter(FEE_ON_MONTH_DAY).value(monthDay).mustBeBlankWhenParameterProvidedIs(CHARGE_TIME_TYPE,
|
||||
chargeTimeType);
|
||||
}
|
||||
|
||||
if (ctt.isMonthlyFee()) {
|
||||
final MonthDay monthDay = this.fromApiJsonHelper.extractMonthDayNamed(FEE_ON_MONTH_DAY, element);
|
||||
baseDataValidator.reset().parameter(FEE_ON_MONTH_DAY).value(monthDay).notNull();
|
||||
|
||||
baseDataValidator.reset().parameter(FEE_INTERVAL).value(feeInterval).notNull().inMinMaxRange(1, 12);
|
||||
}
|
||||
|
||||
if (ctt.isAnnualFee()) {
|
||||
final MonthDay monthDay = this.fromApiJsonHelper.extractMonthDayNamed(FEE_ON_MONTH_DAY, element);
|
||||
baseDataValidator.reset().parameter(FEE_ON_MONTH_DAY).value(monthDay).notNull();
|
||||
}
|
||||
|
||||
if (chargeCalculationType != null) {
|
||||
baseDataValidator.reset().parameter(CHARGE_CALCULATION_TYPE).value(chargeCalculationType)
|
||||
.isOneOfTheseValues(ChargeCalculationType.validValuesForSavings());
|
||||
}
|
||||
|
||||
} else if (appliesTo.isClientCharge()) {
|
||||
// client applicable validation
|
||||
final Integer chargeTimeType = this.fromApiJsonHelper.extractIntegerSansLocaleNamed(CHARGE_TIME_TYPE, element);
|
||||
baseDataValidator.reset().parameter(CHARGE_TIME_TYPE).value(chargeTimeType).notNull();
|
||||
if (chargeTimeType != null) {
|
||||
baseDataValidator.reset().parameter(CHARGE_TIME_TYPE).value(chargeTimeType)
|
||||
.isOneOfTheseValues(ChargeTimeType.validClientValues());
|
||||
}
|
||||
|
||||
if (chargeCalculationType != null) {
|
||||
baseDataValidator.reset().parameter(CHARGE_CALCULATION_TYPE).value(chargeCalculationType)
|
||||
.isOneOfTheseValues(ChargeCalculationType.validValuesForClients());
|
||||
}
|
||||
|
||||
// GL Account can be linked to clients
|
||||
if (this.fromApiJsonHelper.parameterExists(ChargesApiConstants.glAccountIdParamName, element)) {
|
||||
final Long glAccountId = this.fromApiJsonHelper.extractLongNamed(ChargesApiConstants.glAccountIdParamName, element);
|
||||
baseDataValidator.reset().parameter(ChargesApiConstants.glAccountIdParamName).value(glAccountId).notNull()
|
||||
.longGreaterThanZero();
|
||||
}
|
||||
|
||||
} else if (appliesTo.isSharesCharge()) {
|
||||
final Integer chargeTimeType = this.fromApiJsonHelper.extractIntegerSansLocaleNamed(CHARGE_TIME_TYPE, element);
|
||||
baseDataValidator.reset().parameter(CHARGE_TIME_TYPE).value(chargeTimeType).notNull();
|
||||
if (chargeTimeType != null) {
|
||||
baseDataValidator.reset().parameter(CHARGE_TIME_TYPE).value(chargeTimeType)
|
||||
.isOneOfTheseValues(ChargeTimeType.validShareValues());
|
||||
}
|
||||
|
||||
if (chargeCalculationType != null) {
|
||||
baseDataValidator.reset().parameter(CHARGE_CALCULATION_TYPE).value(chargeCalculationType)
|
||||
.isOneOfTheseValues(ChargeCalculationType.validValuesForShares());
|
||||
}
|
||||
|
||||
if (chargeTimeType != null && chargeTimeType.equals(ChargeTimeType.SHAREACCOUNT_ACTIVATION.getValue())
|
||||
&& chargeCalculationType != null) {
|
||||
baseDataValidator.reset().parameter(CHARGE_CALCULATION_TYPE).value(chargeCalculationType)
|
||||
.isOneOfTheseValues(ChargeCalculationType.validValuesForShareAccountActivation());
|
||||
}
|
||||
}
|
||||
|
||||
final String name = this.fromApiJsonHelper.extractStringNamed(NAME, element);
|
||||
baseDataValidator.reset().parameter(NAME).value(name).notBlank().notExceedingLengthOf(100);
|
||||
|
||||
final String currencyCode = this.fromApiJsonHelper.extractStringNamed(CURRENCY_CODE, element);
|
||||
baseDataValidator.reset().parameter(CURRENCY_CODE).value(currencyCode).notBlank().notExceedingLengthOf(3);
|
||||
|
||||
final BigDecimal amount = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(AMOUNT, element.getAsJsonObject());
|
||||
baseDataValidator.reset().parameter(AMOUNT).value(amount).notNull().positiveAmount();
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(PENALTY, element)) {
|
||||
final Boolean penalty = this.fromApiJsonHelper.extractBooleanNamed(PENALTY, element);
|
||||
baseDataValidator.reset().parameter(PENALTY).value(penalty).notNull();
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(ACTIVE, element)) {
|
||||
final Boolean active = this.fromApiJsonHelper.extractBooleanNamed(ACTIVE, element);
|
||||
baseDataValidator.reset().parameter(ACTIVE).value(active).notNull();
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(MIN_CAP, element)) {
|
||||
final BigDecimal minCap = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(MIN_CAP, element.getAsJsonObject());
|
||||
baseDataValidator.reset().parameter(MIN_CAP).value(minCap).notNull().positiveAmount();
|
||||
}
|
||||
if (this.fromApiJsonHelper.parameterExists(MAX_CAP, element)) {
|
||||
final BigDecimal maxCap = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(MAX_CAP, element.getAsJsonObject());
|
||||
baseDataValidator.reset().parameter(MAX_CAP).value(maxCap).notNull().positiveAmount();
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(ChargesApiConstants.taxGroupIdParamName, element)) {
|
||||
final Long taxGroupId = this.fromApiJsonHelper.extractLongNamed(ChargesApiConstants.taxGroupIdParamName, element);
|
||||
baseDataValidator.reset().parameter(ChargesApiConstants.taxGroupIdParamName).value(taxGroupId).notNull().longGreaterThanZero();
|
||||
}
|
||||
|
||||
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||
}
|
||||
|
||||
public void validateForUpdate(final String json) {
|
||||
if (StringUtils.isBlank(json)) {
|
||||
throw new InvalidJsonException();
|
||||
}
|
||||
|
||||
final Type typeOfMap = new TypeToken<Map<String, Object>>() {
|
||||
|
||||
}.getType();
|
||||
this.fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, SUPPORTED_PARAMETERS);
|
||||
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource(CHARGE);
|
||||
|
||||
final JsonElement element = this.fromApiJsonHelper.parse(json);
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(NAME, element)) {
|
||||
final String name = this.fromApiJsonHelper.extractStringNamed(NAME, element);
|
||||
baseDataValidator.reset().parameter(NAME).value(name).notBlank().notExceedingLengthOf(100);
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(CURRENCY_CODE, element)) {
|
||||
final String currencyCode = this.fromApiJsonHelper.extractStringNamed(CURRENCY_CODE, element);
|
||||
baseDataValidator.reset().parameter(CURRENCY_CODE).value(currencyCode).notBlank().notExceedingLengthOf(3);
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(AMOUNT, element)) {
|
||||
final BigDecimal amount = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(AMOUNT, element.getAsJsonObject());
|
||||
baseDataValidator.reset().parameter(AMOUNT).value(amount).notNull().positiveAmount();
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(MIN_CAP, element)) {
|
||||
final BigDecimal minCap = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(MIN_CAP, element.getAsJsonObject());
|
||||
baseDataValidator.reset().parameter(MIN_CAP).value(minCap).notNull().positiveAmount();
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(MAX_CAP, element)) {
|
||||
final BigDecimal maxCap = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(MAX_CAP, element.getAsJsonObject());
|
||||
baseDataValidator.reset().parameter(MAX_CAP).value(maxCap).notNull().positiveAmount();
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(CHARGE_APPLIES_TO, element)) {
|
||||
final Integer chargeAppliesTo = this.fromApiJsonHelper.extractIntegerSansLocaleNamed(CHARGE_APPLIES_TO, element);
|
||||
baseDataValidator.reset().parameter(CHARGE_APPLIES_TO).value(chargeAppliesTo).notNull()
|
||||
.isOneOfTheseValues(ChargeAppliesTo.validValues());
|
||||
}
|
||||
|
||||
Boolean enableFreeWithdrawalCharge = false;
|
||||
if (this.fromApiJsonHelper.parameterExists(ENABLE_FREE_WITHDRAWAL_CHARGE, element)) {
|
||||
enableFreeWithdrawalCharge = this.fromApiJsonHelper.extractBooleanNamed(ENABLE_FREE_WITHDRAWAL_CHARGE, element);
|
||||
baseDataValidator.reset().parameter(ENABLE_FREE_WITHDRAWAL_CHARGE).value(enableFreeWithdrawalCharge).notNull();
|
||||
|
||||
if (enableFreeWithdrawalCharge) {
|
||||
|
||||
final Integer freeWithdrawalFrequency = this.fromApiJsonHelper.extractIntegerNamed(FREE_WITHDRAWAL_FREQUENCY, element,
|
||||
Locale.getDefault());
|
||||
baseDataValidator.reset().parameter(FREE_WITHDRAWAL_FREQUENCY).value(freeWithdrawalFrequency).integerGreaterThanZero();
|
||||
|
||||
final Integer restartCountFrequency = this.fromApiJsonHelper.extractIntegerNamed(RESTART_COUNT_FREQUENCY, element,
|
||||
Locale.getDefault());
|
||||
baseDataValidator.reset().parameter(RESTART_COUNT_FREQUENCY).value(restartCountFrequency).integerGreaterThanZero();
|
||||
|
||||
final Integer countFrequencyType = this.fromApiJsonHelper.extractIntegerNamed(COUNT_FREQUENCY_TYPE, element,
|
||||
Locale.getDefault());
|
||||
baseDataValidator.reset().parameter(COUNT_FREQUENCY_TYPE).value(countFrequencyType);
|
||||
}
|
||||
|
||||
Boolean enablePaymentType = false;
|
||||
if (this.fromApiJsonHelper.parameterExists(ENABLE_PAYMENT_TYPE, element)) {
|
||||
enablePaymentType = this.fromApiJsonHelper.extractBooleanNamed(ENABLE_PAYMENT_TYPE, element);
|
||||
baseDataValidator.reset().parameter(ENABLE_PAYMENT_TYPE).value(enablePaymentType).notNull();
|
||||
|
||||
if (enablePaymentType) {
|
||||
final Integer paymentTypeId = this.fromApiJsonHelper.extractIntegerNamed(PAYMENT_TYPE_ID, element, Locale.getDefault());
|
||||
baseDataValidator.reset().parameter(PAYMENT_TYPE_ID).value(paymentTypeId).integerGreaterThanZero();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(CHARGE_APPLIES_TO, element)) {
|
||||
final Integer chargeAppliesTo = this.fromApiJsonHelper.extractIntegerSansLocaleNamed(CHARGE_APPLIES_TO, element);
|
||||
baseDataValidator.reset().parameter(CHARGE_APPLIES_TO).value(chargeAppliesTo).notNull()
|
||||
.isOneOfTheseValues(ChargeAppliesTo.validValues());
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(CHARGE_APPLIES_TO, element)) {
|
||||
final Integer chargeAppliesTo = this.fromApiJsonHelper.extractIntegerSansLocaleNamed(CHARGE_APPLIES_TO, element);
|
||||
baseDataValidator.reset().parameter(CHARGE_APPLIES_TO).value(chargeAppliesTo).notNull()
|
||||
.isOneOfTheseValues(ChargeAppliesTo.validValues());
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(CHARGE_TIME_TYPE, element)) {
|
||||
|
||||
final Integer chargeTimeType = this.fromApiJsonHelper.extractIntegerSansLocaleNamed(CHARGE_TIME_TYPE, element);
|
||||
|
||||
final Collection<Object> validLoanValues = Arrays.asList(ChargeTimeType.validLoanValues());
|
||||
final Collection<Object> validSavingsValues = Arrays.asList(ChargeTimeType.validSavingsValues());
|
||||
final Collection<Object> validClientValues = Arrays.asList(ChargeTimeType.validClientValues());
|
||||
final Collection<Object> validShareValues = Arrays.asList(ChargeTimeType.validShareValues());
|
||||
final Collection<Object> allValidValues = new ArrayList<>(validLoanValues);
|
||||
allValidValues.addAll(validSavingsValues);
|
||||
allValidValues.addAll(validClientValues);
|
||||
allValidValues.addAll(validShareValues);
|
||||
baseDataValidator.reset().parameter(CHARGE_TIME_TYPE).value(chargeTimeType).notNull()
|
||||
.isOneOfTheseValues(allValidValues.toArray(new Object[allValidValues.size()]));
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(FEE_ON_MONTH_DAY, element)) {
|
||||
final MonthDay monthDay = this.fromApiJsonHelper.extractMonthDayNamed(FEE_ON_MONTH_DAY, element);
|
||||
baseDataValidator.reset().parameter(FEE_ON_MONTH_DAY).value(monthDay).notNull();
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(FEE_INTERVAL, element)) {
|
||||
final Integer feeInterval = this.fromApiJsonHelper.extractIntegerNamed(FEE_INTERVAL, element, Locale.getDefault());
|
||||
baseDataValidator.reset().parameter(FEE_INTERVAL).value(feeInterval).integerGreaterThanZero();
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(CHARGE_CALCULATION_TYPE, element)) {
|
||||
final Integer chargeCalculationType = this.fromApiJsonHelper.extractIntegerNamed(CHARGE_CALCULATION_TYPE, element,
|
||||
Locale.getDefault());
|
||||
baseDataValidator.reset().parameter(CHARGE_CALCULATION_TYPE).value(chargeCalculationType).notNull().inMinMaxRange(1, 5);
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(CHARGE_PAYMENT_MODE, element)) {
|
||||
final Integer chargePaymentMode = this.fromApiJsonHelper.extractIntegerNamed(CHARGE_PAYMENT_MODE, element, Locale.getDefault());
|
||||
baseDataValidator.reset().parameter(CHARGE_PAYMENT_MODE).value(chargePaymentMode).notNull().inMinMaxRange(0, 1);
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(PENALTY, element)) {
|
||||
final Boolean penalty = this.fromApiJsonHelper.extractBooleanNamed(PENALTY, element);
|
||||
baseDataValidator.reset().parameter(PENALTY).value(penalty).notNull();
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(ACTIVE, element)) {
|
||||
final Boolean active = this.fromApiJsonHelper.extractBooleanNamed(ACTIVE, element);
|
||||
baseDataValidator.reset().parameter(ACTIVE).value(active).notNull();
|
||||
}
|
||||
if (this.fromApiJsonHelper.parameterExists(MIN_CAP, element)) {
|
||||
final BigDecimal minCap = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(MIN_CAP, element.getAsJsonObject());
|
||||
baseDataValidator.reset().parameter(MIN_CAP).value(minCap).notNull().positiveAmount();
|
||||
}
|
||||
if (this.fromApiJsonHelper.parameterExists(MAX_CAP, element)) {
|
||||
final BigDecimal maxCap = this.fromApiJsonHelper.extractBigDecimalWithLocaleNamed(MAX_CAP, element.getAsJsonObject());
|
||||
baseDataValidator.reset().parameter(MAX_CAP).value(maxCap).notNull().positiveAmount();
|
||||
}
|
||||
if (this.fromApiJsonHelper.parameterExists(FEE_FREQUENCY, element)) {
|
||||
final Integer feeFrequency = this.fromApiJsonHelper.extractIntegerNamed(FEE_FREQUENCY, element, Locale.getDefault());
|
||||
baseDataValidator.reset().parameter(FEE_FREQUENCY).value(feeFrequency).inMinMaxRange(0, 3);
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(ChargesApiConstants.glAccountIdParamName, element)) {
|
||||
final Long glAccountId = this.fromApiJsonHelper.extractLongNamed(ChargesApiConstants.glAccountIdParamName, element);
|
||||
baseDataValidator.reset().parameter(ChargesApiConstants.glAccountIdParamName).value(glAccountId).notNull()
|
||||
.longGreaterThanZero();
|
||||
}
|
||||
|
||||
if (this.fromApiJsonHelper.parameterExists(ChargesApiConstants.taxGroupIdParamName, element)) {
|
||||
final Long taxGroupId = this.fromApiJsonHelper.extractLongNamed(ChargesApiConstants.taxGroupIdParamName, element);
|
||||
baseDataValidator.reset().parameter(ChargesApiConstants.taxGroupIdParamName).value(taxGroupId).notNull().longGreaterThanZero();
|
||||
}
|
||||
|
||||
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||
}
|
||||
|
||||
public void validateChargeTimeNCalculationType(Integer chargeTimeType, Integer chargeCalculationType) {
|
||||
final List<ApiParameterError> dataValidationErrors = new ArrayList<>();
|
||||
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource(CHARGE);
|
||||
performChargeTimeNCalculationTypeValidation(baseDataValidator, chargeTimeType, chargeCalculationType);
|
||||
throwExceptionIfValidationWarningsExist(dataValidationErrors);
|
||||
}
|
||||
|
||||
private void performChargeTimeNCalculationTypeValidation(DataValidatorBuilder baseDataValidator, final Integer chargeTimeType,
|
||||
final Integer chargeCalculationType) {
|
||||
if (chargeTimeType.equals(ChargeTimeType.SHAREACCOUNT_ACTIVATION.getValue())) {
|
||||
baseDataValidator.reset().parameter(CHARGE_CALCULATION_TYPE).value(chargeCalculationType)
|
||||
.isOneOfTheseValues(ChargeCalculationType.validValuesForShareAccountActivation());
|
||||
}
|
||||
|
||||
if (chargeTimeType.equals(ChargeTimeType.TRANCHE_DISBURSEMENT.getValue())) {
|
||||
baseDataValidator.reset().parameter(CHARGE_CALCULATION_TYPE).value(chargeCalculationType)
|
||||
.isOneOfTheseValues(ChargeCalculationType.validValuesForTrancheDisbursement());
|
||||
} else {
|
||||
baseDataValidator.reset().parameter(CHARGE_CALCULATION_TYPE).value(chargeCalculationType)
|
||||
.isNotOneOfTheseValues(ChargeCalculationType.PERCENT_OF_DISBURSEMENT_AMOUNT.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
private void throwExceptionIfValidationWarningsExist(final List<ApiParameterError> dataValidationErrors) {
|
||||
if (!dataValidationErrors.isEmpty()) {
|
||||
throw new PlatformApiDataValidationException(dataValidationErrors);
|
||||
}
|
||||
}
|
||||
}
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.charge.service;
|
||||
|
||||
import java.util.List;
|
||||
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
|
||||
|
||||
public interface ChargeDropdownReadPlatformService {
|
||||
|
||||
List<EnumOptionData> retrieveCalculationTypes();
|
||||
|
||||
List<EnumOptionData> retrieveApplicableToTypes();
|
||||
|
||||
List<EnumOptionData> retrieveCollectionTimeTypes();
|
||||
|
||||
List<EnumOptionData> retrivePaymentModes();
|
||||
|
||||
List<EnumOptionData> retrieveLoanCalculationTypes();
|
||||
|
||||
List<EnumOptionData> retrieveLoanCollectionTimeTypes();
|
||||
|
||||
List<EnumOptionData> retrieveSavingsCalculationTypes();
|
||||
|
||||
List<EnumOptionData> retrieveSavingsCollectionTimeTypes();
|
||||
|
||||
List<EnumOptionData> retrieveClientCalculationTypes();
|
||||
|
||||
List<EnumOptionData> retrieveClientCollectionTimeTypes();
|
||||
|
||||
List<EnumOptionData> retrieveSharesCalculationTypes();
|
||||
|
||||
List<EnumOptionData> retrieveSharesCollectionTimeTypes();
|
||||
|
||||
}
|
||||
+127
@@ -0,0 +1,127 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.charge.service;
|
||||
|
||||
import static org.apache.fineract.portfolio.charge.service.ChargeEnumerations.chargeCalculationType;
|
||||
import static org.apache.fineract.portfolio.charge.service.ChargeEnumerations.chargePaymentMode;
|
||||
import static org.apache.fineract.portfolio.charge.service.ChargeEnumerations.chargeTimeType;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
|
||||
import org.apache.fineract.portfolio.charge.domain.ChargeAppliesTo;
|
||||
import org.apache.fineract.portfolio.charge.domain.ChargeCalculationType;
|
||||
import org.apache.fineract.portfolio.charge.domain.ChargePaymentMode;
|
||||
import org.apache.fineract.portfolio.charge.domain.ChargeTimeType;
|
||||
|
||||
public class ChargeDropdownReadPlatformServiceImpl implements ChargeDropdownReadPlatformService {
|
||||
|
||||
@Override
|
||||
public List<EnumOptionData> retrieveCalculationTypes() {
|
||||
|
||||
return Arrays.asList(chargeCalculationType(ChargeCalculationType.FLAT),
|
||||
chargeCalculationType(ChargeCalculationType.PERCENT_OF_AMOUNT),
|
||||
chargeCalculationType(ChargeCalculationType.PERCENT_OF_AMOUNT_AND_INTEREST),
|
||||
chargeCalculationType(ChargeCalculationType.PERCENT_OF_INTEREST),
|
||||
chargeCalculationType(ChargeCalculationType.PERCENT_OF_DISBURSEMENT_AMOUNT));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<EnumOptionData> retrieveApplicableToTypes() {
|
||||
final List<EnumOptionData> chargeAppliesToTypes = new ArrayList<>();
|
||||
for (final ChargeAppliesTo chargeAppliesTo : ChargeAppliesTo.values()) {
|
||||
if (ChargeAppliesTo.INVALID.equals(chargeAppliesTo)) {
|
||||
continue;
|
||||
}
|
||||
chargeAppliesToTypes.add(ChargeEnumerations.chargeAppliesTo(chargeAppliesTo));
|
||||
}
|
||||
return chargeAppliesToTypes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<EnumOptionData> retrieveCollectionTimeTypes() {
|
||||
final List<EnumOptionData> chargeTimeTypes = new ArrayList<>();
|
||||
for (final ChargeTimeType chargeTimeType : ChargeTimeType.values()) {
|
||||
if (ChargeTimeType.INVALID.equals(chargeTimeType) || ChargeTimeType.SAVINGS_CLOSURE.equals(chargeTimeType)) {
|
||||
continue;
|
||||
}
|
||||
chargeTimeTypes.add(ChargeEnumerations.chargeTimeType(chargeTimeType));
|
||||
}
|
||||
return chargeTimeTypes;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<EnumOptionData> retrivePaymentModes() {
|
||||
return Arrays.asList(chargePaymentMode(ChargePaymentMode.REGULAR), chargePaymentMode(ChargePaymentMode.ACCOUNT_TRANSFER));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<EnumOptionData> retrieveLoanCalculationTypes() {
|
||||
return Arrays.asList(chargeCalculationType(ChargeCalculationType.FLAT),
|
||||
chargeCalculationType(ChargeCalculationType.PERCENT_OF_AMOUNT),
|
||||
chargeCalculationType(ChargeCalculationType.PERCENT_OF_AMOUNT_AND_INTEREST),
|
||||
chargeCalculationType(ChargeCalculationType.PERCENT_OF_INTEREST),
|
||||
chargeCalculationType(ChargeCalculationType.PERCENT_OF_DISBURSEMENT_AMOUNT));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<EnumOptionData> retrieveLoanCollectionTimeTypes() {
|
||||
return Arrays.asList(chargeTimeType(ChargeTimeType.DISBURSEMENT), chargeTimeType(ChargeTimeType.SPECIFIED_DUE_DATE),
|
||||
chargeTimeType(ChargeTimeType.INSTALMENT_FEE), chargeTimeType(ChargeTimeType.OVERDUE_INSTALLMENT),
|
||||
chargeTimeType(ChargeTimeType.TRANCHE_DISBURSEMENT));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<EnumOptionData> retrieveSavingsCalculationTypes() {
|
||||
return Arrays.asList(chargeCalculationType(ChargeCalculationType.FLAT),
|
||||
chargeCalculationType(ChargeCalculationType.PERCENT_OF_AMOUNT));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<EnumOptionData> retrieveSavingsCollectionTimeTypes() {
|
||||
return Arrays.asList(chargeTimeType(ChargeTimeType.SPECIFIED_DUE_DATE), chargeTimeType(ChargeTimeType.SAVINGS_ACTIVATION),
|
||||
// chargeTimeType(ChargeTimeType.SAVINGS_CLOSURE),
|
||||
chargeTimeType(ChargeTimeType.WITHDRAWAL_FEE), chargeTimeType(ChargeTimeType.ANNUAL_FEE),
|
||||
chargeTimeType(ChargeTimeType.MONTHLY_FEE), chargeTimeType(ChargeTimeType.WEEKLY_FEE),
|
||||
chargeTimeType(ChargeTimeType.OVERDRAFT_FEE), chargeTimeType(ChargeTimeType.SAVINGS_NOACTIVITY_FEE));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<EnumOptionData> retrieveClientCalculationTypes() {
|
||||
return Arrays.asList(chargeCalculationType(ChargeCalculationType.FLAT));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<EnumOptionData> retrieveClientCollectionTimeTypes() {
|
||||
return Arrays.asList(chargeTimeType(ChargeTimeType.SPECIFIED_DUE_DATE));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<EnumOptionData> retrieveSharesCalculationTypes() {
|
||||
return Arrays.asList(chargeCalculationType(ChargeCalculationType.FLAT),
|
||||
chargeCalculationType(ChargeCalculationType.PERCENT_OF_AMOUNT));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<EnumOptionData> retrieveSharesCollectionTimeTypes() {
|
||||
return Arrays.asList(chargeTimeType(ChargeTimeType.SHAREACCOUNT_ACTIVATION), chargeTimeType(ChargeTimeType.SHARE_PURCHASE),
|
||||
chargeTimeType(ChargeTimeType.SHARE_REDEEM));
|
||||
}
|
||||
}
|
||||
+217
@@ -0,0 +1,217 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.charge.service;
|
||||
|
||||
import org.apache.fineract.infrastructure.core.data.EnumOptionData;
|
||||
import org.apache.fineract.portfolio.charge.domain.ChargeAppliesTo;
|
||||
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.apache.fineract.portfolio.common.domain.PeriodFrequencyType;
|
||||
|
||||
public final class ChargeEnumerations {
|
||||
|
||||
private ChargeEnumerations() {
|
||||
|
||||
}
|
||||
|
||||
public static EnumOptionData chargeTimeType(final int id) {
|
||||
return chargeTimeType(ChargeTimeType.fromInt(id));
|
||||
}
|
||||
|
||||
public static EnumOptionData chargeTimeType(final ChargeTimeType type) {
|
||||
EnumOptionData optionData = null;
|
||||
switch (type) {
|
||||
case DISBURSEMENT:
|
||||
optionData = new EnumOptionData(ChargeTimeType.DISBURSEMENT.getValue().longValue(), ChargeTimeType.DISBURSEMENT.getCode(),
|
||||
"Disbursement");
|
||||
break;
|
||||
case SPECIFIED_DUE_DATE:
|
||||
optionData = new EnumOptionData(ChargeTimeType.SPECIFIED_DUE_DATE.getValue().longValue(),
|
||||
ChargeTimeType.SPECIFIED_DUE_DATE.getCode(), "Specified due date");
|
||||
break;
|
||||
case SAVINGS_ACTIVATION:
|
||||
optionData = new EnumOptionData(ChargeTimeType.SAVINGS_ACTIVATION.getValue().longValue(),
|
||||
ChargeTimeType.SAVINGS_ACTIVATION.getCode(), "Savings Activation");
|
||||
break;
|
||||
case SAVINGS_CLOSURE:
|
||||
optionData = new EnumOptionData(ChargeTimeType.SAVINGS_CLOSURE.getValue().longValue(),
|
||||
ChargeTimeType.SAVINGS_CLOSURE.getCode(), "Savings Closure");
|
||||
break;
|
||||
case WITHDRAWAL_FEE:
|
||||
optionData = new EnumOptionData(ChargeTimeType.WITHDRAWAL_FEE.getValue().longValue(),
|
||||
ChargeTimeType.WITHDRAWAL_FEE.getCode(), "Withdrawal Fee");
|
||||
break;
|
||||
case ANNUAL_FEE:
|
||||
optionData = new EnumOptionData(ChargeTimeType.ANNUAL_FEE.getValue().longValue(), ChargeTimeType.ANNUAL_FEE.getCode(),
|
||||
"Annual Fee");
|
||||
break;
|
||||
case MONTHLY_FEE:
|
||||
optionData = new EnumOptionData(ChargeTimeType.MONTHLY_FEE.getValue().longValue(), ChargeTimeType.MONTHLY_FEE.getCode(),
|
||||
"Monthly Fee");
|
||||
break;
|
||||
case WEEKLY_FEE:
|
||||
optionData = new EnumOptionData(ChargeTimeType.WEEKLY_FEE.getValue().longValue(), ChargeTimeType.WEEKLY_FEE.getCode(),
|
||||
"Weekly Fee");
|
||||
break;
|
||||
case INSTALMENT_FEE:
|
||||
optionData = new EnumOptionData(ChargeTimeType.INSTALMENT_FEE.getValue().longValue(),
|
||||
ChargeTimeType.INSTALMENT_FEE.getCode(), "Installment Fee");
|
||||
break;
|
||||
case OVERDUE_INSTALLMENT:
|
||||
optionData = new EnumOptionData(ChargeTimeType.OVERDUE_INSTALLMENT.getValue().longValue(),
|
||||
ChargeTimeType.OVERDUE_INSTALLMENT.getCode(), "Overdue Fees");
|
||||
break;
|
||||
case OVERDRAFT_FEE:
|
||||
optionData = new EnumOptionData(ChargeTimeType.OVERDRAFT_FEE.getValue().longValue(), ChargeTimeType.OVERDRAFT_FEE.getCode(),
|
||||
"Overdraft Fee");
|
||||
break;
|
||||
case TRANCHE_DISBURSEMENT:
|
||||
optionData = new EnumOptionData(ChargeTimeType.TRANCHE_DISBURSEMENT.getValue().longValue(),
|
||||
ChargeTimeType.TRANCHE_DISBURSEMENT.getCode(), "Tranche Disbursement");
|
||||
break;
|
||||
case SHAREACCOUNT_ACTIVATION:
|
||||
optionData = new EnumOptionData(ChargeTimeType.SHAREACCOUNT_ACTIVATION.getValue().longValue(),
|
||||
ChargeTimeType.SHAREACCOUNT_ACTIVATION.getCode(), "Share Account Activate");
|
||||
break;
|
||||
|
||||
case SHARE_PURCHASE:
|
||||
optionData = new EnumOptionData(ChargeTimeType.SHARE_PURCHASE.getValue().longValue(),
|
||||
ChargeTimeType.SHARE_PURCHASE.getCode(), "Share Purchase");
|
||||
break;
|
||||
case SHARE_REDEEM:
|
||||
optionData = new EnumOptionData(ChargeTimeType.SHARE_REDEEM.getValue().longValue(), ChargeTimeType.SHARE_REDEEM.getCode(),
|
||||
"Share Redeem");
|
||||
break;
|
||||
case SAVINGS_NOACTIVITY_FEE:
|
||||
optionData = new EnumOptionData(ChargeTimeType.SAVINGS_NOACTIVITY_FEE.getValue().longValue(),
|
||||
ChargeTimeType.SAVINGS_NOACTIVITY_FEE.getCode(), "Saving No Activity Fee");
|
||||
break;
|
||||
default:
|
||||
optionData = new EnumOptionData(ChargeTimeType.INVALID.getValue().longValue(), ChargeTimeType.INVALID.getCode(), "Invalid");
|
||||
break;
|
||||
}
|
||||
return optionData;
|
||||
}
|
||||
|
||||
public static EnumOptionData chargeAppliesTo(final int id) {
|
||||
return chargeAppliesTo(ChargeAppliesTo.fromInt(id));
|
||||
}
|
||||
|
||||
public static EnumOptionData chargeAppliesTo(final ChargeAppliesTo type) {
|
||||
EnumOptionData optionData = null;
|
||||
switch (type) {
|
||||
case LOAN:
|
||||
optionData = new EnumOptionData(ChargeAppliesTo.LOAN.getValue().longValue(), ChargeAppliesTo.LOAN.getCode(), "Loan");
|
||||
break;
|
||||
case SAVINGS:
|
||||
optionData = new EnumOptionData(ChargeAppliesTo.SAVINGS.getValue().longValue(), ChargeAppliesTo.SAVINGS.getCode(),
|
||||
"Savings");
|
||||
break;
|
||||
case CLIENT:
|
||||
optionData = new EnumOptionData(ChargeAppliesTo.CLIENT.getValue().longValue(), ChargeAppliesTo.CLIENT.getCode(), "Client");
|
||||
break;
|
||||
case SHARES:
|
||||
optionData = new EnumOptionData(ChargeAppliesTo.SHARES.getValue().longValue(), ChargeAppliesTo.SHARES.getCode(), "Shares");
|
||||
break;
|
||||
default:
|
||||
optionData = new EnumOptionData(ChargeAppliesTo.INVALID.getValue().longValue(), ChargeAppliesTo.INVALID.getCode(),
|
||||
"Invalid");
|
||||
break;
|
||||
}
|
||||
return optionData;
|
||||
}
|
||||
|
||||
public static EnumOptionData chargeCalculationType(final int id) {
|
||||
return chargeCalculationType(ChargeCalculationType.fromInt(id));
|
||||
}
|
||||
|
||||
public static EnumOptionData chargeCalculationType(final ChargeCalculationType type) {
|
||||
EnumOptionData optionData = null;
|
||||
switch (type) {
|
||||
case FLAT:
|
||||
optionData = new EnumOptionData(ChargeCalculationType.FLAT.getValue().longValue(), ChargeCalculationType.FLAT.getCode(),
|
||||
"Flat");
|
||||
break;
|
||||
case PERCENT_OF_AMOUNT:
|
||||
optionData = new EnumOptionData(ChargeCalculationType.PERCENT_OF_AMOUNT.getValue().longValue(),
|
||||
ChargeCalculationType.PERCENT_OF_AMOUNT.getCode(), "% Amount");
|
||||
break;
|
||||
case PERCENT_OF_AMOUNT_AND_INTEREST:
|
||||
optionData = new EnumOptionData(ChargeCalculationType.PERCENT_OF_AMOUNT_AND_INTEREST.getValue().longValue(),
|
||||
ChargeCalculationType.PERCENT_OF_AMOUNT_AND_INTEREST.getCode(), "% Loan Amount + Interest");
|
||||
break;
|
||||
case PERCENT_OF_INTEREST:
|
||||
optionData = new EnumOptionData(ChargeCalculationType.PERCENT_OF_INTEREST.getValue().longValue(),
|
||||
ChargeCalculationType.PERCENT_OF_INTEREST.getCode(), "% Interest");
|
||||
break;
|
||||
case PERCENT_OF_DISBURSEMENT_AMOUNT:
|
||||
optionData = new EnumOptionData(ChargeCalculationType.PERCENT_OF_DISBURSEMENT_AMOUNT.getValue().longValue(),
|
||||
ChargeCalculationType.PERCENT_OF_DISBURSEMENT_AMOUNT.getCode(), "% Disbursement Amount");
|
||||
break;
|
||||
default:
|
||||
optionData = new EnumOptionData(ChargeCalculationType.INVALID.getValue().longValue(),
|
||||
ChargeCalculationType.INVALID.getCode(), "Invalid");
|
||||
break;
|
||||
}
|
||||
return optionData;
|
||||
}
|
||||
|
||||
public static EnumOptionData chargePaymentMode(final int id) {
|
||||
return chargePaymentMode(ChargePaymentMode.fromInt(id));
|
||||
}
|
||||
|
||||
public static EnumOptionData chargePaymentMode(final ChargePaymentMode type) {
|
||||
EnumOptionData optionData = null;
|
||||
switch (type) {
|
||||
case ACCOUNT_TRANSFER:
|
||||
optionData = new EnumOptionData(ChargePaymentMode.ACCOUNT_TRANSFER.getValue().longValue(),
|
||||
ChargePaymentMode.ACCOUNT_TRANSFER.getCode(), "Account transfer");
|
||||
break;
|
||||
default:
|
||||
optionData = new EnumOptionData(ChargePaymentMode.REGULAR.getValue().longValue(), ChargePaymentMode.REGULAR.getCode(),
|
||||
"Regular");
|
||||
break;
|
||||
}
|
||||
return optionData;
|
||||
}
|
||||
|
||||
public static EnumOptionData feeFrequencyType(final int id) {
|
||||
return feeFrequencyType(PeriodFrequencyType.fromInt(id));
|
||||
}
|
||||
|
||||
public static EnumOptionData feeFrequencyType(final PeriodFrequencyType frequencyType) {
|
||||
EnumOptionData optionData;
|
||||
switch (frequencyType) {
|
||||
case DAYS -> optionData = new EnumOptionData(PeriodFrequencyType.DAYS.getValue().longValue(),
|
||||
PeriodFrequencyType.DAYS.getCode(), "Daily");
|
||||
case WEEKS -> optionData = new EnumOptionData(PeriodFrequencyType.WEEKS.getValue().longValue(),
|
||||
PeriodFrequencyType.WEEKS.getCode(), "Weekly");
|
||||
case MONTHS -> optionData = new EnumOptionData(PeriodFrequencyType.MONTHS.getValue().longValue(),
|
||||
PeriodFrequencyType.MONTHS.getCode(), "Monthly");
|
||||
case YEARS -> optionData = new EnumOptionData(PeriodFrequencyType.YEARS.getValue().longValue(),
|
||||
PeriodFrequencyType.YEARS.getCode(), "Yearly");
|
||||
case WHOLE_TERM -> optionData = new EnumOptionData(PeriodFrequencyType.WHOLE_TERM.getValue().longValue(),
|
||||
PeriodFrequencyType.WHOLE_TERM.getCode(), "Whole term");
|
||||
default -> throw new UnsupportedOperationException(frequencyType + " is not supported");
|
||||
}
|
||||
return optionData;
|
||||
}
|
||||
|
||||
}
|
||||
+124
@@ -0,0 +1,124 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.charge.service;
|
||||
|
||||
import java.util.Collection;
|
||||
import org.apache.fineract.portfolio.charge.data.ChargeData;
|
||||
import org.apache.fineract.portfolio.charge.domain.ChargeTimeType;
|
||||
|
||||
public interface ChargeReadPlatformService {
|
||||
|
||||
Collection<ChargeData> retrieveAllCharges();
|
||||
|
||||
Collection<ChargeData> retrieveAllChargesForCurrency(String currencyCode);
|
||||
|
||||
ChargeData retrieveCharge(Long chargeId);
|
||||
|
||||
ChargeData retrieveNewChargeDetails();
|
||||
|
||||
/**
|
||||
* Returns all charges that can be applied to Cients
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
Collection<ChargeData> retrieveAllChargesApplicableToClients();
|
||||
|
||||
/**
|
||||
* Returns all Fees (excluding penalties) applicable for loans
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
Collection<ChargeData> retrieveLoanApplicableFees();
|
||||
|
||||
/**
|
||||
* Returns all charges applicable for a given loan account
|
||||
*
|
||||
* @param excludeChargeTimes
|
||||
* Excludes Given List of Charge Types from the response
|
||||
* @return
|
||||
*/
|
||||
Collection<ChargeData> retrieveLoanAccountApplicableCharges(Long loanId, ChargeTimeType[] excludeChargeTimes);
|
||||
|
||||
/**
|
||||
* Returns all charges applicable for a given loan product (filter based on Currency of Selected Loan Product)
|
||||
*
|
||||
* @param excludeChargeTimes
|
||||
* Excludes Given List of Charge Types from the response
|
||||
* @return
|
||||
*/
|
||||
Collection<ChargeData> retrieveLoanProductApplicableCharges(Long loanProductId, ChargeTimeType[] excludeChargeTimes);
|
||||
|
||||
/**
|
||||
* Returns all Penalties applicable for loans
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
Collection<ChargeData> retrieveLoanApplicablePenalties();
|
||||
|
||||
/**
|
||||
* Returns all Charges associated with a given Loan Product
|
||||
*
|
||||
* @param loanProductId
|
||||
* @return
|
||||
*/
|
||||
Collection<ChargeData> retrieveLoanProductCharges(Long loanProductId);
|
||||
|
||||
/**
|
||||
* Returns all charges applicable for a given loan product
|
||||
*
|
||||
* @param loanProductId
|
||||
* @param chargeTime
|
||||
* Filters based on the type of the charge to be returned
|
||||
* @return
|
||||
*/
|
||||
Collection<ChargeData> retrieveLoanProductCharges(Long loanProductId, ChargeTimeType chargeTime);
|
||||
|
||||
/**
|
||||
* Returns all charges applicable for savings
|
||||
*
|
||||
* @param feeChargesOnly
|
||||
* @return
|
||||
*/
|
||||
Collection<ChargeData> retrieveSavingsProductApplicableCharges(boolean feeChargesOnly);
|
||||
|
||||
/**
|
||||
* Returns all penalties applicable for savings
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
Collection<ChargeData> retrieveSavingsApplicablePenalties();
|
||||
|
||||
/**
|
||||
* Returns all charges applicable for a given savings product
|
||||
*
|
||||
* @param savingsProductId
|
||||
* @return
|
||||
*/
|
||||
Collection<ChargeData> retrieveSavingsProductCharges(Long savingsProductId);
|
||||
|
||||
/** Retrieve savings account charges **/
|
||||
Collection<ChargeData> retrieveSavingsAccountApplicableCharges(Long savingsId);
|
||||
|
||||
/**
|
||||
* Returns charge definitions which are applicable for shares
|
||||
*/
|
||||
Collection<ChargeData> retrieveSharesApplicableCharges();
|
||||
|
||||
Collection<ChargeData> retrieveShareProductCharges(Long shareProductId);
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.fineract.portfolio.charge.service;
|
||||
|
||||
import org.apache.fineract.infrastructure.core.api.JsonCommand;
|
||||
import org.apache.fineract.infrastructure.core.data.CommandProcessingResult;
|
||||
|
||||
public interface ChargeWritePlatformService {
|
||||
|
||||
CommandProcessingResult createCharge(JsonCommand command);
|
||||
|
||||
CommandProcessingResult updateCharge(Long chargeId, JsonCommand command);
|
||||
|
||||
CommandProcessingResult deleteCharge(Long chargeId);
|
||||
}
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
|
||||
-->
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.1.xsd">
|
||||
<!-- Sequence is starting from 6000 to make it easier to move existing liquibase changesets here -->
|
||||
</databaseChangeLog>
|
||||
@@ -0,0 +1,76 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
|
||||
Licensed to the Apache Software Foundation (ASF) under one
|
||||
or more contributor license agreements. See the NOTICE file
|
||||
distributed with this work for additional information
|
||||
regarding copyright ownership. The ASF licenses this file
|
||||
to you under the Apache License, Version 2.0 (the
|
||||
"License"); you may not use this file except in compliance
|
||||
with the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing,
|
||||
software distributed under the License is distributed on an
|
||||
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
KIND, either express or implied. See the License for the
|
||||
specific language governing permissions and limitations
|
||||
under the License.
|
||||
|
||||
-->
|
||||
|
||||
|
||||
<persistence version="2.0"
|
||||
xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
|
||||
|
||||
<!-- This file is only used for static weaving, nothing more. -->
|
||||
<!-- You can find the runtime configuration in the JPAConfig class -->
|
||||
<persistence-unit name="jpa-pu" transaction-type="RESOURCE_LOCAL">
|
||||
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
|
||||
<!-- Fineract core module -->
|
||||
<class>org.apache.fineract.accounting.glaccount.domain.GLAccount</class>
|
||||
<class>org.apache.fineract.accounting.journalentry.domain.JournalEntry</class>
|
||||
<class>org.apache.fineract.infrastructure.core.domain.AbstractPersistableCustom</class>
|
||||
<class>org.apache.fineract.infrastructure.core.domain.AbstractAuditableWithUTCDateTimeCustom</class>
|
||||
<class>org.apache.fineract.infrastructure.codes.domain.Code</class>
|
||||
<class>org.apache.fineract.infrastructure.codes.domain.CodeValue</class>
|
||||
<class>org.apache.fineract.infrastructure.documentmanagement.domain.Image</class>
|
||||
<class>org.apache.fineract.organisation.staff.domain.Staff</class>
|
||||
<class>org.apache.fineract.organisation.office.domain.Office</class>
|
||||
<class>org.apache.fineract.organisation.office.domain.OrganisationCurrency</class>
|
||||
<class>org.apache.fineract.organisation.monetary.domain.ApplicationCurrency</class>
|
||||
<class>org.apache.fineract.organisation.holiday.domain.Holiday</class>
|
||||
<class>org.apache.fineract.organisation.workingdays.domain.WorkingDays</class>
|
||||
<class>org.apache.fineract.portfolio.group.domain.Group</class>
|
||||
<class>org.apache.fineract.portfolio.group.domain.GroupLevel</class>
|
||||
<class>org.apache.fineract.portfolio.group.domain.StaffAssignmentHistory</class>
|
||||
<class>org.apache.fineract.portfolio.group.domain.GroupRole</class>
|
||||
<class>org.apache.fineract.portfolio.client.domain.Client</class>
|
||||
<class>org.apache.fineract.portfolio.client.domain.ClientIdentifier</class>
|
||||
<class>org.apache.fineract.portfolio.rate.domain.Rate</class>
|
||||
<class>org.apache.fineract.portfolio.fund.domain.Fund</class>
|
||||
<class>org.apache.fineract.portfolio.delinquency.domain.DelinquencyBucket</class>
|
||||
<class>org.apache.fineract.portfolio.delinquency.domain.DelinquencyRange</class>
|
||||
<class>org.apache.fineract.portfolio.paymenttype.domain.PaymentType</class>
|
||||
<class>org.apache.fineract.portfolio.paymentdetail.domain.PaymentDetail</class>
|
||||
<class>org.apache.fineract.portfolio.tax.domain.TaxGroup</class>
|
||||
<class>org.apache.fineract.portfolio.tax.domain.TaxGroupMappings</class>
|
||||
<class>org.apache.fineract.portfolio.tax.domain.TaxComponent</class>
|
||||
<class>org.apache.fineract.portfolio.tax.domain.TaxComponentHistory</class>
|
||||
<class>org.apache.fineract.portfolio.floatingrates.domain.FloatingRate</class>
|
||||
<class>org.apache.fineract.portfolio.floatingrates.domain.FloatingRatePeriod</class>
|
||||
<class>org.apache.fineract.portfolio.calendar.domain.Calendar</class>
|
||||
<class>org.apache.fineract.portfolio.calendar.domain.CalendarHistory</class>
|
||||
<class>org.apache.fineract.portfolio.calendar.domain.CalendarInstance</class>
|
||||
<class>org.apache.fineract.useradministration.domain.AppUser</class>
|
||||
<class>org.apache.fineract.useradministration.domain.Role</class>
|
||||
<class>org.apache.fineract.useradministration.domain.Permission</class>
|
||||
<class>org.apache.fineract.useradministration.domain.AppUserClientMapping</class>
|
||||
<exclude-unlisted-classes>false</exclude-unlisted-classes>
|
||||
<properties>
|
||||
<property name="eclipselink.weaving" value="static" />
|
||||
</properties>
|
||||
</persistence-unit>
|
||||
</persistence>
|
||||
Reference in New Issue
Block a user