diff --git a/mifosng-provider/src/main/java/org/mifosplatform/commands/domain/CommandWrapper.java b/mifosng-provider/src/main/java/org/mifosplatform/commands/domain/CommandWrapper.java index 380b4852c..5fb95a517 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/commands/domain/CommandWrapper.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/commands/domain/CommandWrapper.java @@ -215,4 +215,20 @@ public class CommandWrapper { public boolean isCloseLoanAsRescheduled() { return this.actionName.equalsIgnoreCase("CLOSEASRESCHEDULED") && this.entityName.equalsIgnoreCase("LOAN"); } + + public boolean isAddLoanCharge() { + return this.actionName.equalsIgnoreCase("CREATE") && this.entityName.equalsIgnoreCase("LOANCHARGE"); + } + + public boolean isDeleteLoanCharge() { + return this.actionName.equalsIgnoreCase("DELETE") && this.entityName.equalsIgnoreCase("LOANCHARGE"); + } + + public boolean isUpdateLoanCharge() { + return this.actionName.equalsIgnoreCase("UPDATE") && this.entityName.equalsIgnoreCase("LOANCHARGE"); + } + + public boolean isWaiveLoanCharge() { + return this.actionName.equalsIgnoreCase("WAIVE") && this.entityName.equalsIgnoreCase("LOANCHARGE"); + } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/commands/service/SynchronousCommandProcessingService.java b/mifosng-provider/src/main/java/org/mifosplatform/commands/service/SynchronousCommandProcessingService.java index 26fe37116..b39f6dc49 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/commands/service/SynchronousCommandProcessingService.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/commands/service/SynchronousCommandProcessingService.java @@ -236,6 +236,14 @@ public class SynchronousCommandProcessingService implements CommandProcessingSer handler = applicationContext.getBean("closeLoanCommandHandler", NewCommandSourceHandler.class); } else if (wrapper.isCloseLoanAsRescheduled()) { handler = applicationContext.getBean("closeLoanAsRescheduledCommandHandler", NewCommandSourceHandler.class); + } else if (wrapper.isAddLoanCharge()) { + handler = applicationContext.getBean("addLoanChargeCommandHandler", NewCommandSourceHandler.class); + } else if (wrapper.isDeleteLoanCharge()) { + handler = applicationContext.getBean("deleteLoanChargeCommandHandler", NewCommandSourceHandler.class); + } else if (wrapper.isUpdateLoanCharge()) { + handler = applicationContext.getBean("updateLoanChargeCommandHandler", NewCommandSourceHandler.class); + } else if (wrapper.isWaiveLoanCharge()) { + handler = applicationContext.getBean("waiveLoanChargeCommandHandler", NewCommandSourceHandler.class); } else if (wrapper.isCreate()) { handler = applicationContext.getBean("createLoanApplicationCommandHandler", NewCommandSourceHandler.class); } else if (wrapper.isUpdate()) { diff --git a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/api/GoogleGsonPortfolioApiJsonSerializerService.java b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/api/GoogleGsonPortfolioApiJsonSerializerService.java index 83d6fd9b7..38b420323 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/api/GoogleGsonPortfolioApiJsonSerializerService.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/api/GoogleGsonPortfolioApiJsonSerializerService.java @@ -15,7 +15,6 @@ import org.mifosplatform.organisation.staff.data.StaffData; import org.mifosplatform.portfolio.client.data.ClientAccountSummaryCollectionData; import org.mifosplatform.portfolio.group.data.GroupAccountSummaryCollectionData; import org.mifosplatform.portfolio.group.data.GroupData; -import org.mifosplatform.portfolio.loanaccount.data.LoanChargeData; import org.mifosplatform.portfolio.loanaccount.gaurantor.data.GuarantorData; import org.mifosplatform.portfolio.savingsaccount.data.SavingAccountData; import org.mifosplatform.portfolio.savingsaccount.data.SavingScheduleData; @@ -80,8 +79,6 @@ public class GoogleGsonPortfolioApiJsonSerializerService implements PortfolioApi private static final Set LOAN_REASSIGNMENT_DATA_PARAMETERS = new HashSet(Arrays.asList("officeId", "fromLoanOfficerId", "assignmentDate", "officeOptions", "loanOfficerOptions", "accountSummaryCollection")); - private static final Set LOAN_CHARGES_DATA_PARAMETERS = new HashSet(Arrays.asList("chargeOptions")); - private static final Set SAVINGS_ACCOUNTS_DATA_PARAMETERS = new HashSet(Arrays.asList("id", "status", "externalId", "clientId", "clientName", "productId", "productName", "productType", "currencyData", "savingsDepostiAmountPerPeriod", "savingsFrequencyType", "totalDepositAmount", "reccuringInterestRate", "savingInterestRate", "interestType", @@ -210,13 +207,6 @@ public class GoogleGsonPortfolioApiJsonSerializerService implements PortfolioApi return helper.serializedJsonFrom(gsonDeserializer, loanReassignmentData); } - @Override - public String serializeLoanChargeDataToJson(boolean prettyPrint, Set responseParameters, LoanChargeData charge) { - final Gson gsonDeserializer = helper.createGsonBuilderWithParameterExclusionSerializationStrategy(LOAN_CHARGES_DATA_PARAMETERS, - prettyPrint, responseParameters); - return helper.serializedJsonFrom(gsonDeserializer, charge); - } - @Override public String serializeStaffDataToJson(boolean prettyPrint, Set responseParameters, StaffData staff) { final Gson gsonDeserializer = helper.createGsonBuilderWithParameterExclusionSerializationStrategy(STAFF_DATA_PARAMETERS, diff --git a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/api/PortfolioApiDataConversionService.java b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/api/PortfolioApiDataConversionService.java index efb39b291..bc936c6c3 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/api/PortfolioApiDataConversionService.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/api/PortfolioApiDataConversionService.java @@ -4,7 +4,6 @@ import org.mifosplatform.organisation.staff.command.BulkTransferLoanOfficerComma import org.mifosplatform.portfolio.client.command.NoteCommand; import org.mifosplatform.portfolio.client.data.ClientData; import org.mifosplatform.portfolio.group.command.GroupCommand; -import org.mifosplatform.portfolio.loanaccount.command.LoanChargeCommand; import org.mifosplatform.portfolio.loanaccount.gaurantor.command.GuarantorCommand; import org.mifosplatform.portfolio.savingsaccount.command.SavingAccountCommand; import org.mifosplatform.portfolio.savingsaccountproduct.command.SavingProductCommand; @@ -25,8 +24,6 @@ public interface PortfolioApiDataConversionService { GroupCommand convertJsonToGroupCommand(Long resourceIdentifier, String json); - LoanChargeCommand convertJsonToLoanChargeCommand(Long loanChargeId, Long loanId, String json); - NoteCommand convertJsonToNoteCommand(Long resourceIdentifier, Long clientId, String json); DepositAccountCommand convertJsonToDepositAccountCommand(Long resourceIdentifier, String json); diff --git a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/api/PortfolioApiDataConversionServiceImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/api/PortfolioApiDataConversionServiceImpl.java index a0fb54517..4b5c338a8 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/api/PortfolioApiDataConversionServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/api/PortfolioApiDataConversionServiceImpl.java @@ -27,7 +27,6 @@ import org.mifosplatform.portfolio.client.command.NoteCommand; import org.mifosplatform.portfolio.client.data.ClientData; import org.mifosplatform.portfolio.client.serialization.ClientCommandFromApiJsonDeserializer; import org.mifosplatform.portfolio.group.command.GroupCommand; -import org.mifosplatform.portfolio.loanaccount.command.LoanChargeCommand; import org.mifosplatform.portfolio.loanaccount.gaurantor.command.GuarantorCommand; import org.mifosplatform.portfolio.savingsaccount.command.SavingAccountCommand; import org.mifosplatform.portfolio.savingsaccountproduct.command.SavingProductCommand; @@ -173,34 +172,6 @@ public class PortfolioApiDataConversionServiceImpl implements PortfolioApiDataCo return new GroupCommand(modifiedParameters, resourceIdentifier, externalId, name, officeId, clientMembers); } - /** - * @deprecated - to be removed soon - */ - @Deprecated - @Override - public LoanChargeCommand convertJsonToLoanChargeCommand(final Long loanChargeId, final Long loanId, final String json) { - if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); } - - Type typeOfMap = new TypeToken>() {}.getType(); - Map requestMap = gsonConverter.fromJson(json, typeOfMap); - - final Set supportedParams = new HashSet(Arrays.asList("chargeId", "amount", "chargeTimeType", - "chargeCalculationType", "specifiedDueDate", "locale", "dateFormat")); - - checkForUnsupportedParameters(requestMap, supportedParams); - - Set modifiedParameters = new HashSet(); - - Long chargeId = extractLongParameter("chargeId", requestMap, modifiedParameters); - BigDecimal amount = extractBigDecimalParameter("amount", requestMap, modifiedParameters); - Integer chargeTimeType = extractIntegerParameter("chargeTimeType", requestMap, modifiedParameters); - Integer chargeCalculationType = extractIntegerParameter("chargeCalculationType", requestMap, modifiedParameters); - final LocalDate submittedOnDate = extractLocalDateParameter("specifiedDueDate", requestMap, modifiedParameters); - - return new LoanChargeCommand(modifiedParameters, loanChargeId, loanId, chargeId, amount, chargeTimeType, chargeCalculationType, - submittedOnDate); - } - @Override public NoteCommand convertJsonToNoteCommand(final Long noteId, final Long clientId, final String json) { if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/api/PortfolioApiJsonSerializerService.java b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/api/PortfolioApiJsonSerializerService.java index 8107f8272..c7a688841 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/api/PortfolioApiJsonSerializerService.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/infrastructure/core/api/PortfolioApiJsonSerializerService.java @@ -12,7 +12,6 @@ import org.mifosplatform.organisation.staff.data.StaffData; import org.mifosplatform.portfolio.client.data.ClientAccountSummaryCollectionData; import org.mifosplatform.portfolio.group.data.GroupAccountSummaryCollectionData; import org.mifosplatform.portfolio.group.data.GroupData; -import org.mifosplatform.portfolio.loanaccount.data.LoanChargeData; import org.mifosplatform.portfolio.loanaccount.gaurantor.data.GuarantorData; import org.mifosplatform.portfolio.savingsaccount.data.SavingAccountData; import org.mifosplatform.portfolio.savingsaccount.data.SavingScheduleData; @@ -53,8 +52,6 @@ public interface PortfolioApiJsonSerializerService { String serializeLoanReassignmentDataToJson(boolean prettyPrint, Set responseParameters, BulkTransferLoanOfficerData loanReassignmentData); - String serializeLoanChargeDataToJson(boolean prettyPrint, Set responseParameters, LoanChargeData charge); - String serializeStaffDataToJson(boolean prettyPrint, Set responseParameters, StaffData staff); String serializeStaffDataToJson(boolean prettyPrint, Set responseParameters, Collection staff); diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/api/LoanChargesApiResource.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/api/LoanChargesApiResource.java index 778cbcf5e..68364b15b 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/api/LoanChargesApiResource.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/api/LoanChargesApiResource.java @@ -1,6 +1,8 @@ package org.mifosplatform.portfolio.loanaccount.api; +import java.util.Arrays; import java.util.Collection; +import java.util.HashSet; import java.util.Set; import javax.ws.rs.Consumes; @@ -14,23 +16,19 @@ import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.Context; import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; import javax.ws.rs.core.UriInfo; import org.apache.commons.lang.StringUtils; -import org.mifosplatform.infrastructure.core.api.ApiParameterHelper; -import org.mifosplatform.infrastructure.core.api.PortfolioApiDataConversionService; -import org.mifosplatform.infrastructure.core.api.PortfolioApiJsonSerializerService; +import org.mifosplatform.commands.service.PortfolioCommandSourceWritePlatformService; +import org.mifosplatform.infrastructure.core.api.ApiRequestParameterHelper; import org.mifosplatform.infrastructure.core.data.EntityIdentifier; import org.mifosplatform.infrastructure.core.exception.UnrecognizedQueryParamException; +import org.mifosplatform.infrastructure.core.serialization.ApiRequestJsonSerializationSettings; import org.mifosplatform.infrastructure.core.serialization.DefaultToApiJsonSerializer; import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext; import org.mifosplatform.portfolio.charge.data.ChargeData; import org.mifosplatform.portfolio.charge.service.ChargeReadPlatformService; -import org.mifosplatform.portfolio.loanaccount.command.LoanChargeCommand; -import org.mifosplatform.portfolio.loanaccount.data.LoanAccountData; import org.mifosplatform.portfolio.loanaccount.data.LoanChargeData; -import org.mifosplatform.portfolio.loanaccount.service.LoanWritePlatformService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; @@ -40,102 +38,87 @@ import org.springframework.stereotype.Component; @Scope("singleton") public class LoanChargesApiResource { + private final Set RESPONSE_DATA_PARAMETERS = new HashSet(Arrays.asList("id", "chargeId", "name", "penalty", + "chargeTimeType", "dueAsOfDate", "chargeCalculationType", "percentage", "amountPercentageAppliedTo", "currency", + "amountWaived", "amountWrittenOff", "amountOutstanding", "amountOrPercentage", "amount", "amountPaid", "chargeOptions")); + + private final String resourceNameForPermissions = "LOAN"; + private final PlatformSecurityContext context; - private final LoanWritePlatformService loanWritePlatformService; private final ChargeReadPlatformService chargeReadPlatformService; - private final PortfolioApiJsonSerializerService apiJsonSerializerService; - private final PortfolioApiDataConversionService apiDataConversionService; - private final DefaultToApiJsonSerializer toApiJsonSerializer; -// private final ApiRequestParameterHelper apiRequestParameterHelper; -// private final FromJsonHelper fromJsonHelper; -// private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService; + private final DefaultToApiJsonSerializer toApiJsonSerializer; + private final ApiRequestParameterHelper apiRequestParameterHelper; + private final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService; @Autowired - public LoanChargesApiResource(final PlatformSecurityContext context, final LoanWritePlatformService loanWritePlatformService, - final ChargeReadPlatformService chargeReadPlatformService, - final DefaultToApiJsonSerializer toApiJsonSerializer, -// final ApiRequestParameterHelper apiRequestParameterHelper, - final PortfolioApiJsonSerializerService apiJsonSerializerService, - final PortfolioApiDataConversionService apiDataConversionService - // , final FromJsonHelper fromJsonHelper, - // final PortfolioCommandSourceWritePlatformService - // commandsSourceWritePlatformService - ) { + public LoanChargesApiResource(final PlatformSecurityContext context, final ChargeReadPlatformService chargeReadPlatformService, + final DefaultToApiJsonSerializer toApiJsonSerializer, + final ApiRequestParameterHelper apiRequestParameterHelper, + final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService) { this.context = context; - this.loanWritePlatformService = loanWritePlatformService; this.chargeReadPlatformService = chargeReadPlatformService; this.toApiJsonSerializer = toApiJsonSerializer; -// this.apiRequestParameterHelper = apiRequestParameterHelper; - this.apiJsonSerializerService = apiJsonSerializerService; - this.apiDataConversionService = apiDataConversionService; -// this.fromJsonHelper = fromJsonHelper; -// this.commandsSourceWritePlatformService = commandsSourceWritePlatformService; + this.apiRequestParameterHelper = apiRequestParameterHelper; + this.commandsSourceWritePlatformService = commandsSourceWritePlatformService; } private boolean is(final String commandParam, final String commandValue) { return StringUtils.isNotBlank(commandParam) && commandParam.trim().equalsIgnoreCase(commandValue); } - @POST - @Consumes({ MediaType.APPLICATION_JSON }) - @Produces({ MediaType.APPLICATION_JSON }) - public Response addLoanCharge(@PathParam("loanId") final Long loanId, final String jsonRequestBody) { - - final LoanChargeCommand command = this.apiDataConversionService.convertJsonToLoanChargeCommand(null, loanId, jsonRequestBody); - - final EntityIdentifier identifier = this.loanWritePlatformService.addLoanCharge(command); - - return Response.ok().entity(identifier).build(); - } - @GET @Path("template") @Consumes({ MediaType.APPLICATION_JSON }) @Produces({ MediaType.APPLICATION_JSON }) public String retrieveNewLoanChargeDetails(@Context final UriInfo uriInfo) { - context.authenticatedUser().validateHasReadPermission("LOAN"); - - final Set responseParameters = ApiParameterHelper.extractFieldsForResponseIfProvided(uriInfo.getQueryParameters()); - final boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters()); + context.authenticatedUser().validateHasReadPermission(resourceNameForPermissions); final boolean feeChargesOnly = false; final Collection chargeOptions = this.chargeReadPlatformService.retrieveLoanApplicableCharges(feeChargesOnly); final LoanChargeData loanChargeTemplate = LoanChargeData.template(chargeOptions); - return this.apiJsonSerializerService.serializeLoanChargeDataToJson(prettyPrint, responseParameters, loanChargeTemplate); + final ApiRequestJsonSerializationSettings settings = apiRequestParameterHelper.process(uriInfo.getQueryParameters()); + return this.toApiJsonSerializer.serialize(settings, loanChargeTemplate, RESPONSE_DATA_PARAMETERS); } @GET - @Path("{chargeId}") + @Path("{loanChargeId}") @Consumes({ MediaType.APPLICATION_JSON }) @Produces({ MediaType.APPLICATION_JSON }) - public String retrieveLoanCharge(@PathParam("loanId") final Long loanId, @PathParam("chargeId") final Long loanChargeId, + public String retrieveLoanCharge(@PathParam("loanId") final Long loanId, @PathParam("loanChargeId") final Long loanChargeId, @Context final UriInfo uriInfo) { - context.authenticatedUser().validateHasReadPermission("LOAN"); - - final Set responseParameters = ApiParameterHelper.extractFieldsForResponseIfProvided(uriInfo.getQueryParameters()); - final boolean prettyPrint = ApiParameterHelper.prettyPrint(uriInfo.getQueryParameters()); + context.authenticatedUser().validateHasReadPermission(resourceNameForPermissions); final LoanChargeData loanCharge = this.chargeReadPlatformService.retrieveLoanChargeDetails(loanChargeId, loanId); - return this.apiJsonSerializerService.serializeLoanChargeDataToJson(prettyPrint, responseParameters, loanCharge); + final ApiRequestJsonSerializationSettings settings = apiRequestParameterHelper.process(uriInfo.getQueryParameters()); + return this.toApiJsonSerializer.serialize(settings, loanCharge, RESPONSE_DATA_PARAMETERS); + } + + @POST + @Consumes({ MediaType.APPLICATION_JSON }) + @Produces({ MediaType.APPLICATION_JSON }) + public String addLoanCharge(@PathParam("loanId") final Long loanId, final String apiRequestBodyAsJson) { + + final EntityIdentifier result = this.commandsSourceWritePlatformService.logCommandSource("CREATE", "LOANCHARGE", "N/A", "loans", + loanId, "charges", null, apiRequestBodyAsJson); + + return this.toApiJsonSerializer.serialize(result); } @PUT - @Path("{chargeId}") + @Path("{loanChargeId}") @Consumes({ MediaType.APPLICATION_JSON }) @Produces({ MediaType.APPLICATION_JSON }) - public String updateLoanCharge(@PathParam("loanId") final Long loanId, @PathParam("chargeId") final Long loanChargeId, - final String jsonRequestBody) { + public String updateLoanCharge(@PathParam("loanId") final Long loanId, @PathParam("loanChargeId") final Long loanChargeId, + final String apiRequestBodyAsJson) { - final LoanChargeCommand command = this.apiDataConversionService.convertJsonToLoanChargeCommand(loanChargeId, loanId, - jsonRequestBody); + final EntityIdentifier result = this.commandsSourceWritePlatformService.logCommandSource("UPDATE", "LOANCHARGE", "N/A", "loans", + loanId, "charges", loanChargeId, apiRequestBodyAsJson); - final EntityIdentifier identifier = this.loanWritePlatformService.updateLoanCharge(command); - - return this.toApiJsonSerializer.serialize(identifier); + return this.toApiJsonSerializer.serialize(result); } @POST @@ -145,12 +128,12 @@ public class LoanChargesApiResource { public String waiveLoanCharge(@PathParam("loanId") final Long loanId, @PathParam("chargeId") final Long loanChargeId, @QueryParam("command") final String commandParam) { - final LoanChargeCommand command = LoanChargeCommand.forWaiver(loanChargeId, loanId); - String json = ""; if (is(commandParam, "waive")) { - final EntityIdentifier identifier = this.loanWritePlatformService.waiveLoanCharge(command); - json = this.toApiJsonSerializer.serialize(identifier); + final EntityIdentifier result = this.commandsSourceWritePlatformService.logCommandSource("WAIVE", "LOANCHARGE", "N/A", "loans", + loanId, "charges", loanChargeId, "{}"); + + json = this.toApiJsonSerializer.serialize(result); } else { throw new UnrecognizedQueryParamException("command", commandParam); } @@ -164,7 +147,9 @@ public class LoanChargesApiResource { @Produces({ MediaType.APPLICATION_JSON }) public String deleteLoanCharge(@PathParam("loanId") final Long loanId, @PathParam("chargeId") final Long loanChargeId) { - final EntityIdentifier identifier = this.loanWritePlatformService.deleteLoanCharge(loanId, loanChargeId); - return this.toApiJsonSerializer.serialize(identifier); + final EntityIdentifier result = this.commandsSourceWritePlatformService.logCommandSource("DELETE", "LOANCHARGE", "N/A", "loans", + loanId, "charges", loanChargeId, "{}"); + + return this.toApiJsonSerializer.serialize(result); } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/api/LoanTransactionsApiResource.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/api/LoanTransactionsApiResource.java index d457d7290..44993ccb9 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/api/LoanTransactionsApiResource.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/api/LoanTransactionsApiResource.java @@ -30,8 +30,11 @@ import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Component; // FIXME: - undo disbursal fails when transactions have notes against them -// FIXME: - repayments before disbursement date allowed - +// FIXME: - modifying loan after disbursement +// FIXME: - does not take into account 'actual disbursement' date being different to 'expected' +// FIXME: - the schedule is 'generated' rather than been read from current loan schedule +// FIXME: - should not allow modify loan after disbursal (should be only restructure/reschedule) +// FIXME: - ui problem with default date for disburse dialog on some screens @Path("/loans/{loanId}/transactions") @Component @Scope("singleton") diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/command/LoanApplicationCommand.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/command/LoanApplicationCommand.java index 1026cdc52..c5de9925f 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/command/LoanApplicationCommand.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/command/LoanApplicationCommand.java @@ -289,8 +289,7 @@ public class LoanApplicationCommand { if (this.charges != null) { for (LoanChargeCommand loanChargeCommand : this.charges) { try { - LoanChargeCommandValidator validator = new LoanChargeCommandValidator(loanChargeCommand); - validator.validateForCreate(); + loanChargeCommand.validateForCreate(); } catch (PlatformApiDataValidationException e) { dataValidationErrors.addAll(e.getErrors()); } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/command/LoanChargeCommand.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/command/LoanChargeCommand.java index 5b94a421f..ecc5673da 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/command/LoanChargeCommand.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/command/LoanChargeCommand.java @@ -1,49 +1,34 @@ package org.mifosplatform.portfolio.loanaccount.command; import java.math.BigDecimal; -import java.util.HashSet; -import java.util.Set; +import java.util.ArrayList; +import java.util.List; import org.joda.time.LocalDate; +import org.mifosplatform.infrastructure.core.data.ApiParameterError; +import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder; +import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException; /** * Immutable command for creating and updating loan charges. */ public class LoanChargeCommand implements Comparable { - private final Long id; private final Long chargeId; - private final Long loanId; private final BigDecimal amount; - private final Integer chargeTimeType; private final LocalDate specifiedDueDate; private final Integer chargeCalculationType; - /** - * Used to capture what parameters were passed in the json api request. It - * does not indicate that these values are modified from their original - * values when tyring to update. - */ - private final Set requestParameters; - - public static LoanChargeCommand forWaiver(final Long id, final Long loanId) { - final Set parametersPassedInCommand = new HashSet(); - return new LoanChargeCommand(parametersPassedInCommand, id, loanId, null, null, null, null, null); - } - - public LoanChargeCommand(final Set parametersPassedInCommand, final Long id, final Long loanId, final Long chargeId, - final BigDecimal amount, final Integer chargeTimeType, final Integer chargeCalculationType, final LocalDate specifiedDueDate) { - this.requestParameters = parametersPassedInCommand; - this.id = id; + public LoanChargeCommand(final Long chargeId, final BigDecimal amount, final Integer chargeTimeType, + final Integer chargeCalculationType, final LocalDate specifiedDueDate) { this.chargeId = chargeId; - this.loanId = loanId; this.amount = amount; this.chargeTimeType = chargeTimeType; this.chargeCalculationType = chargeCalculationType; this.specifiedDueDate = specifiedDueDate; } - + @Override public int compareTo(final LoanChargeCommand o) { int comparison = this.chargeId.compareTo(o.chargeId); @@ -53,47 +38,38 @@ public class LoanChargeCommand implements Comparable { return comparison; } - public Long getId() { - return id; + public void validateForCreate() { + List dataValidationErrors = new ArrayList(); + + DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("charge"); + + baseDataValidator.reset().parameter("chargeId").value(this.chargeId).notNull().longGreaterThanZero(); + baseDataValidator.reset().parameter("amount").value(this.amount).notNull().positiveAmount(); + // baseDataValidator.reset().parameter("chargeTimeType").value(command.getChargeTimeType()).ignoreIfNull().inMinMaxRange(1, + // 2); + // + // if (command.getChargeTimeType().equals(Integer.valueOf(2))) { + // // date must be provided + // baseDataValidator.reset().parameter("specifiedDueDate").value(command.getSpecifiedDueDate()).notNull(); + // } + // + // baseDataValidator.reset().parameter("chargeCalculationType").value(command.getChargeCalculationType()).ignoreIfNull().inMinMaxRange(1, + // 4); + + if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", + "Validation errors exist.", dataValidationErrors); } } - public Long getChargeId() { - return chargeId; - } + public void validateForUpdate() { + List dataValidationErrors = new ArrayList(); - public Long getLoanId() { - return loanId; - } + DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("charge"); - public BigDecimal getAmount() { - return amount; - } + baseDataValidator.reset().parameter("amount").value(this.amount).ignoreIfNull().positiveAmount(); + baseDataValidator.reset().parameter("chargeTimeType").value(this.chargeTimeType).ignoreIfNull().inMinMaxRange(1, 2); + baseDataValidator.reset().parameter("chargeCalculationType").value(this.chargeCalculationType).ignoreIfNull().inMinMaxRange(1, 4); - public Integer getChargeTimeType() { - return chargeTimeType; - } - - public LocalDate getSpecifiedDueDate() { - return specifiedDueDate; - } - - public Integer getChargeCalculationType() { - return chargeCalculationType; - } - - public boolean isAmountChanged() { - return this.requestParameters.contains("amount"); - } - - public boolean isChargeTimeTypeChanged() { - return this.requestParameters.contains("chargeTimeType"); - } - - public boolean isSpecifiedDueDateChanged() { - return this.requestParameters.contains("specifiedDueDate"); - } - - public boolean isChargeCalculationTypeChanged() { - return this.requestParameters.contains("chargeCalculationType"); + if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", + "Validation errors exist.", dataValidationErrors); } } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/command/LoanChargeCommandValidator.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/command/LoanChargeCommandValidator.java deleted file mode 100644 index ed363b120..000000000 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/command/LoanChargeCommandValidator.java +++ /dev/null @@ -1,52 +0,0 @@ -package org.mifosplatform.portfolio.loanaccount.command; - -import org.mifosplatform.infrastructure.core.data.ApiParameterError; -import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder; -import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException; - -import java.util.ArrayList; -import java.util.List; - -public class LoanChargeCommandValidator { - - private final LoanChargeCommand command; - - public LoanChargeCommandValidator(final LoanChargeCommand command) { - this.command = command; - } - - public void validateForCreate() { - List dataValidationErrors = new ArrayList(); - - DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("charge"); - - baseDataValidator.reset().parameter("chargeId").value(command.getChargeId()).notNull().longGreaterThanZero(); - baseDataValidator.reset().parameter("amount").value(command.getAmount()).notNull().positiveAmount(); -// baseDataValidator.reset().parameter("chargeTimeType").value(command.getChargeTimeType()).ignoreIfNull().inMinMaxRange(1, 2); -// -// if (command.getChargeTimeType().equals(Integer.valueOf(2))) { -// // date must be provided -// baseDataValidator.reset().parameter("specifiedDueDate").value(command.getSpecifiedDueDate()).notNull(); -// } -// -// baseDataValidator.reset().parameter("chargeCalculationType").value(command.getChargeCalculationType()).ignoreIfNull().inMinMaxRange(1, 4); - - if (!dataValidationErrors.isEmpty()) { - throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.", dataValidationErrors); - } - } - - public void validateForUpdate() { - List dataValidationErrors = new ArrayList(); - - DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("charge"); - - baseDataValidator.reset().parameter("amount").value(command.getAmount()).ignoreIfNull().positiveAmount(); - baseDataValidator.reset().parameter("chargeTimeType").value(command.getChargeTimeType()).ignoreIfNull().inMinMaxRange(1, 2); - baseDataValidator.reset().parameter("chargeCalculationType").value(command.getChargeCalculationType()).ignoreIfNull().inMinMaxRange(1, 4); - - if (!dataValidationErrors.isEmpty()) { - throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist", "Validation errors exist.", dataValidationErrors); - } - } -} \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/data/LoanChargeData.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/data/LoanChargeData.java index ca71ae565..4e6e0da3c 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/data/LoanChargeData.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/data/LoanChargeData.java @@ -13,122 +13,99 @@ import org.mifosplatform.portfolio.charge.data.ChargeData; */ public class LoanChargeData { - @SuppressWarnings("unused") + @SuppressWarnings("unused") private final Long id; - - @SuppressWarnings("unused") + + @SuppressWarnings("unused") private final Long chargeId; - - @SuppressWarnings("unused") + + @SuppressWarnings("unused") private final String name; - - @SuppressWarnings("unused") + + @SuppressWarnings("unused") private final EnumOptionData chargeTimeType; - - @SuppressWarnings("unused") - private final LocalDate dueAsOfDate; - - @SuppressWarnings("unused") + + @SuppressWarnings("unused") + private final LocalDate dueAsOfDate; + + @SuppressWarnings("unused") private final EnumOptionData chargeCalculationType; - - private final BigDecimal percentage; - - @SuppressWarnings("unused") - private final BigDecimal amountPercentageAppliedTo; - - @SuppressWarnings("unused") + + private final BigDecimal percentage; + + @SuppressWarnings("unused") + private final BigDecimal amountPercentageAppliedTo; + + @SuppressWarnings("unused") private final CurrencyData currency; - - @SuppressWarnings("unused") + + @SuppressWarnings("unused") private final BigDecimal amount; - - @SuppressWarnings("unused") - private final BigDecimal amountPaid; - @SuppressWarnings("unused") - private final BigDecimal amountWaived; - @SuppressWarnings("unused") - private final BigDecimal amountWrittenOff; - - @SuppressWarnings("unused") - private final BigDecimal amountOutstanding; - - @SuppressWarnings("unused") - private final BigDecimal amountOrPercentage; - - @SuppressWarnings("unused") - private final Collection chargeOptions; @SuppressWarnings("unused") - private final boolean penalty; + private final BigDecimal amountPaid; + @SuppressWarnings("unused") + private final BigDecimal amountWaived; + @SuppressWarnings("unused") + private final BigDecimal amountWrittenOff; - public static LoanChargeData template(final Collection chargeOptions){ - return new LoanChargeData(null,null,null,null,null,null,null, chargeOptions, false); + @SuppressWarnings("unused") + private final BigDecimal amountOutstanding; + + @SuppressWarnings("unused") + private final BigDecimal amountOrPercentage; + + @SuppressWarnings("unused") + private final Collection chargeOptions; + + @SuppressWarnings("unused") + private final boolean penalty; + + public static LoanChargeData template(final Collection chargeOptions) { + return new LoanChargeData(null, null, null, null, null, null, null, chargeOptions, false); } - - /** - * used when populating with details from charge definition (for crud on charges) - */ - public static LoanChargeData newLoanChargeDetails( - final Long chargeId, - final String name, - final CurrencyData currency, - final BigDecimal value, - final EnumOptionData chargeTimeType, - final EnumOptionData chargeCalculationType, - final boolean penalty) { - return new LoanChargeData(null, chargeId, name, currency, value, chargeTimeType, chargeCalculationType, null, penalty); - } - public LoanChargeData( - final Long id, - final Long chargeId, - final String name, - final CurrencyData currency, - final BigDecimal amount, - final BigDecimal amountPaid, - final BigDecimal amountWaived, - final BigDecimal amountWrittenOff, - final BigDecimal amountOutstanding, - final EnumOptionData chargeTimeType, - final LocalDate dueAsOfDate, - final EnumOptionData chargeCalculationType, - final BigDecimal percentage, - final BigDecimal amountPercentageAppliedTo, - final boolean penalty) { + /** + * used when populating with details from charge definition (for crud on + * charges) + */ + public static LoanChargeData newLoanChargeDetails(final Long chargeId, final String name, final CurrencyData currency, + final BigDecimal value, final EnumOptionData chargeTimeType, final EnumOptionData chargeCalculationType, final boolean penalty) { + return new LoanChargeData(null, chargeId, name, currency, value, chargeTimeType, chargeCalculationType, null, penalty); + } + + public LoanChargeData(final Long id, final Long chargeId, final String name, final CurrencyData currency, final BigDecimal amount, + final BigDecimal amountPaid, final BigDecimal amountWaived, final BigDecimal amountWrittenOff, + final BigDecimal amountOutstanding, final EnumOptionData chargeTimeType, final LocalDate dueAsOfDate, + final EnumOptionData chargeCalculationType, final BigDecimal percentage, final BigDecimal amountPercentageAppliedTo, + final boolean penalty) { this.id = id; this.chargeId = chargeId; this.name = name; this.currency = currency; this.amount = amount; - this.amountPaid = amountPaid; - this.amountWaived = amountWaived; - this.amountWrittenOff = amountWrittenOff; - this.amountOutstanding = amountOutstanding; + this.amountPaid = amountPaid; + this.amountWaived = amountWaived; + this.amountWrittenOff = amountWrittenOff; + this.amountOutstanding = amountOutstanding; this.chargeTimeType = chargeTimeType; - this.dueAsOfDate = dueAsOfDate; + this.dueAsOfDate = dueAsOfDate; this.chargeCalculationType = chargeCalculationType; - this.percentage = percentage; - this.amountPercentageAppliedTo = amountPercentageAppliedTo; - this.penalty = penalty; + this.percentage = percentage; + this.amountPercentageAppliedTo = amountPercentageAppliedTo; + this.penalty = penalty; + + if (chargeCalculationType != null && chargeCalculationType.getId().intValue() > 1) { + this.amountOrPercentage = this.percentage; + } else { + this.amountOrPercentage = amount; + } - if (chargeCalculationType != null && chargeCalculationType.getId().intValue() > 1) { - this.amountOrPercentage = this.percentage; - } else { - this.amountOrPercentage = amount; - } - this.chargeOptions = null; } - private LoanChargeData( - final Long id, - final Long chargeId, - final String name, - final CurrencyData currency, - final BigDecimal amount, - final EnumOptionData chargeTimeType, - final EnumOptionData chargeCalculationType, - final Collection chargeOptions, + private LoanChargeData(final Long id, final Long chargeId, final String name, final CurrencyData currency, final BigDecimal amount, + final EnumOptionData chargeTimeType, final EnumOptionData chargeCalculationType, final Collection chargeOptions, final boolean penalty) { this.id = id; this.chargeId = chargeId; @@ -137,21 +114,21 @@ public class LoanChargeData { this.amount = amount; this.amountPaid = BigDecimal.ZERO; this.amountWaived = BigDecimal.ZERO; - this.amountWrittenOff = BigDecimal.ZERO; - this.amountOutstanding = amount; + this.amountWrittenOff = BigDecimal.ZERO; + this.amountOutstanding = amount; this.chargeTimeType = chargeTimeType; this.dueAsOfDate = null; this.chargeCalculationType = chargeCalculationType; this.percentage = null; - this.amountPercentageAppliedTo = null; - this.penalty = penalty; - - if (chargeCalculationType != null && chargeCalculationType.getId().intValue() > 1) { - this.amountOrPercentage = this.percentage; - } else { - this.amountOrPercentage = amount; - } - + this.amountPercentageAppliedTo = null; + this.penalty = penalty; + + if (chargeCalculationType != null && chargeCalculationType.getId().intValue() > 1) { + this.amountOrPercentage = this.percentage; + } else { + this.amountOrPercentage = amount; + } + this.chargeOptions = chargeOptions; } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/Loan.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/Loan.java index 5f164527a..72293ba10 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/Loan.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/Loan.java @@ -421,12 +421,15 @@ public class Loan extends AbstractAuditableCustom { } } - public void updateLoanCharge(final LoanCharge loanCharge, final LoanChargeCommand command) { + public Map updateLoanCharge(final LoanCharge loanCharge, final JsonCommand command) { + + final Map actualChanges = new LinkedHashMap(3); validateLoanIsNotClosed(loanCharge); if (this.charges.contains(loanCharge)) { - loanCharge.update(command, getPrincpal().getAmount()); + final Map loanChargeChanges = loanCharge.update(command, getPrincpal().getAmount()); + actualChanges.putAll(loanChargeChanges); updateTotalChargesDueAtDisbursement(); } @@ -441,13 +444,17 @@ public class Loan extends AbstractAuditableCustom { LoanScheduleWrapper wrapper = new LoanScheduleWrapper(); wrapper.reprocess(getCurrency(), getDisbursementDate(), this.repaymentScheduleInstallments, this.charges); } + + return actualChanges; } - public LoanTransaction waiveLoanCharge(final LoanCharge loanCharge, final LoanLifecycleStateMachine loanLifecycleStateMachine) { + public LoanTransaction waiveLoanCharge(final LoanCharge loanCharge, final LoanLifecycleStateMachine loanLifecycleStateMachine, final Map changes) { validateLoanIsNotClosed(loanCharge); final Money amountWaived = loanCharge.waive(loanCurrency()); + + changes.put("amount", amountWaived.getAmount()); Money feeChargesWaived = Money.of(loanCurrency(), loanCharge.amount()); Money penaltyChargesWaived = Money.zero(loanCurrency()); @@ -1368,9 +1375,11 @@ public class Loan extends AbstractAuditableCustom { return this.loanRepaymentScheduleDetail.getCurrency(); } - public LoanTransaction closeAsWrittenOff(final JsonCommand command, final LoanLifecycleStateMachine loanLifecycleStateMachine, final Map changes) { + public LoanTransaction closeAsWrittenOff(final JsonCommand command, final LoanLifecycleStateMachine loanLifecycleStateMachine, + final Map changes) { - final LoanStatus statusEnum = loanLifecycleStateMachine.transition(LoanEvent.WRITE_OFF_OUTSTANDING, LoanStatus.fromInt(this.loanStatus)); + final LoanStatus statusEnum = loanLifecycleStateMachine.transition(LoanEvent.WRITE_OFF_OUTSTANDING, + LoanStatus.fromInt(this.loanStatus)); if (!statusEnum.hasStateOf(LoanStatus.fromInt(this.loanStatus))) { this.loanStatus = statusEnum.getValue(); changes.put("status", LoanEnumerations.status(this.loanStatus)); @@ -1382,7 +1391,7 @@ public class Loan extends AbstractAuditableCustom { this.writtenOffOnDate = writtenOffOnLocalDate.toDate(); changes.put("closedOnDate", command.stringValueOfParameterNamed("transactionDate")); changes.put("writtenOffOnDate", command.stringValueOfParameterNamed("transactionDate")); - + if (writtenOffOnLocalDate.isBefore(this.getDisbursementDate())) { final String errorMessage = "The date on which a loan is written off cannot be before the loan disbursement date: " + getDisbursementDate().toString(); @@ -1412,7 +1421,8 @@ public class Loan extends AbstractAuditableCustom { return loanTransaction; } - public LoanTransaction close(final JsonCommand command, final LoanLifecycleStateMachine loanLifecycleStateMachine, final Map changes) { + public LoanTransaction close(final JsonCommand command, final LoanLifecycleStateMachine loanLifecycleStateMachine, + final Map changes) { final LocalDate closureDate = command.localDateValueOfParameterNamed("transactionDate"); @@ -1487,8 +1497,9 @@ public class Loan extends AbstractAuditableCustom { return totalOutstanding; } - private void updateLoanForClosure(final LocalDate closureDate, final LoanLifecycleStateMachine loanLifecycleStateMachine, final Map changes) { - + private void updateLoanForClosure(final LocalDate closureDate, final LoanLifecycleStateMachine loanLifecycleStateMachine, + final Map changes) { + final LoanStatus statusEnum = loanLifecycleStateMachine.transition(LoanEvent.REPAID_IN_FULL, LoanStatus.fromInt(this.loanStatus)); if (!statusEnum.hasStateOf(LoanStatus.fromInt(this.loanStatus))) { this.loanStatus = statusEnum.getValue(); @@ -1500,12 +1511,14 @@ public class Loan extends AbstractAuditableCustom { /** * Behaviour added to comply with capability of previous mifos product to * support easier transition to mifosx platform. - * @param changes + * + * @param changes */ - public void closeAsMarkedForReschedule(final JsonCommand command, final LoanLifecycleStateMachine loanLifecycleStateMachine, final Map changes) { + public void closeAsMarkedForReschedule(final JsonCommand command, final LoanLifecycleStateMachine loanLifecycleStateMachine, + final Map changes) { final LocalDate rescheduledOn = command.localDateValueOfParameterNamed("transactionDate"); - + final LoanStatus statusEnum = loanLifecycleStateMachine.transition(LoanEvent.LOAN_RESCHEDULE, LoanStatus.fromInt(this.loanStatus)); if (!statusEnum.hasStateOf(LoanStatus.fromInt(this.loanStatus))) { this.loanStatus = statusEnum.getValue(); diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/LoanCharge.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/LoanCharge.java index 66542c2a9..06aaeb05f 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/LoanCharge.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/LoanCharge.java @@ -4,8 +4,8 @@ import java.math.BigDecimal; import java.math.MathContext; import java.math.RoundingMode; import java.util.Date; -import java.util.HashSet; -import java.util.Set; +import java.util.LinkedHashMap; +import java.util.Map; import javax.persistence.Column; import javax.persistence.Entity; @@ -16,6 +16,7 @@ import javax.persistence.Temporal; import javax.persistence.TemporalType; import org.joda.time.LocalDate; +import org.mifosplatform.infrastructure.core.api.JsonCommand; import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency; import org.mifosplatform.organisation.monetary.domain.Money; import org.mifosplatform.portfolio.charge.domain.Charge; @@ -74,16 +75,24 @@ public class LoanCharge extends AbstractPersistable { @Column(name = "is_paid_derived", nullable = false) private boolean paid = false; - public static LoanCharge createNew(final Loan loan, final Charge chargeDefinition, final LoanChargeCommand command) { - return new LoanCharge(loan, chargeDefinition, command); - } + public static LoanCharge createNewFromJson(final Loan loan, final Charge chargeDefinition, final JsonCommand command) { - /* - * loanPrincipal is required for charges that are percentage based - */ - public static LoanCharge createNewWithoutLoan(final Charge chargeDefinition, final LoanChargeCommand command, - final BigDecimal loanPrincipal) { - return new LoanCharge(chargeDefinition, command, loanPrincipal); + final BigDecimal amount = command.bigDecimalValueOfParameterNamed("amount"); + final Integer chargeTimeType = command.integerValueOfParameterNamed("chargeTimeType"); + final Integer chargeCalculationType = command.integerValueOfParameterNamed("chargeCalculationType"); + final LocalDate specifiedDueDate = command.localDateValueOfParameterNamed("specifiedDueDate"); + + ChargeTimeType chargeTime = null; + if (chargeTimeType != null) { + chargeTime = ChargeTimeType.fromInt(chargeTimeType); + } + ChargeCalculationType chargeCalculation = null; + if (chargeCalculationType != null) { + chargeCalculation = ChargeCalculationType.fromInt(chargeCalculationType); + } + + return new LoanCharge(loan, chargeDefinition, loan.getPrincpal().getAmount(), amount, chargeTime, chargeCalculation, + specifiedDueDate); } /* @@ -91,20 +100,16 @@ public class LoanCharge extends AbstractPersistable { */ public static LoanCharge createNewWithoutLoan(final Charge chargeDefinition, final BigDecimal loanPrincipal, final BigDecimal amount, final ChargeTimeType chargeTime, final ChargeCalculationType chargeCalculation, final LocalDate specifiedDueDate) { - return new LoanCharge(chargeDefinition, loanPrincipal, amount, chargeTime, chargeCalculation, specifiedDueDate); - } - - public static LoanCharge createNew(final Charge chargeDefinition) { - return new LoanCharge(null, chargeDefinition); + return new LoanCharge(null, chargeDefinition, loanPrincipal, amount, chargeTime, chargeCalculation, specifiedDueDate); } protected LoanCharge() { // } - public LoanCharge(final Charge chargeDefinition, final BigDecimal loanPrincipal, final BigDecimal amount, + public LoanCharge(final Loan loan, final Charge chargeDefinition, final BigDecimal loanPrincipal, final BigDecimal amount, final ChargeTimeType chargeTime, final ChargeCalculationType chargeCalculation, final LocalDate specifiedDueDate) { - this.loan = null; + this.loan = loan; this.charge = chargeDefinition; this.penaltyCharge = chargeDefinition.isPenalty(); @@ -140,85 +145,6 @@ public class LoanCharge extends AbstractPersistable { this.paid = determineIfFullyPaid(); } - @Deprecated - public LoanCharge(final Charge chargeDefinition, final LoanChargeCommand command, final BigDecimal loanPrincipal) { - this.loan = null; - this.charge = chargeDefinition; - this.penaltyCharge = chargeDefinition.isPenalty(); - - if (command.isChargeTimeTypeChanged()) { - this.chargeTime = command.getChargeTimeType(); - } else { - this.chargeTime = chargeDefinition.getChargeTime(); - } - - if (ChargeTimeType.fromInt(this.chargeTime).equals(ChargeTimeType.SPECIFIED_DUE_DATE)) { - - if (command.getSpecifiedDueDate() == null) { - final String defaultUserMessage = "Loan charge is missing specified due date"; - throw new LoanChargeWithoutMandatoryFieldException("loancharge", "specifiedDueDate", defaultUserMessage, command.getId(), - chargeDefinition.getName()); - } - - this.dueForCollectionAsOfDate = command.getSpecifiedDueDate().toDate(); - } else { - this.dueForCollectionAsOfDate = null; - } - - if (command.isChargeCalculationTypeChanged()) { - this.chargeCalculation = command.getChargeCalculationType(); - } else { - this.chargeCalculation = chargeDefinition.getChargeCalculation(); - } - - BigDecimal chargeAmount = chargeDefinition.getAmount(); - if (command.isAmountChanged()) { - chargeAmount = command.getAmount(); - } - - populateDerivedFields(loanPrincipal, chargeAmount); - this.paid = determineIfFullyPaid(); - } - - @Deprecated - private LoanCharge(final Loan loan, final Charge chargeDefinition, final LoanChargeCommand command) { - this.loan = loan; - this.charge = chargeDefinition; - this.penaltyCharge = chargeDefinition.isPenalty(); - if (command.isChargeTimeTypeChanged()) { - this.chargeTime = command.getChargeTimeType(); - } else { - this.chargeTime = chargeDefinition.getChargeTime(); - } - - if (ChargeTimeType.fromInt(this.chargeTime).equals(ChargeTimeType.SPECIFIED_DUE_DATE)) { - - if (command.getSpecifiedDueDate() == null) { - final String defaultUserMessage = "Loan charge is missing specified due date"; - throw new LoanChargeWithoutMandatoryFieldException("loancharge", "specifiedDueDate", defaultUserMessage, command.getId(), - chargeDefinition.getName()); - } - - this.dueForCollectionAsOfDate = command.getSpecifiedDueDate().toDate(); - } else { - this.dueForCollectionAsOfDate = null; - } - - if (command.isChargeCalculationTypeChanged()) { - this.chargeCalculation = command.getChargeCalculationType(); - } else { - this.chargeCalculation = chargeDefinition.getChargeCalculation(); - } - - BigDecimal chargeAmount = chargeDefinition.getAmount(); - if (command.isAmountChanged()) { - chargeAmount = command.getAmount(); - } - - populateDerivedFields(loan.getPrincpal().getAmount(), chargeAmount); - this.paid = determineIfFullyPaid(); - } - private void populateDerivedFields(final BigDecimal loanPrincipal, final BigDecimal chargeAmount) { switch (ChargeCalculationType.fromInt(this.chargeCalculation)) { @@ -270,20 +196,6 @@ public class LoanCharge extends AbstractPersistable { } } - private LoanCharge(final Loan loan, final Charge chargeDefinition) { - this(loan, chargeDefinition, chargeDefinition.getAmount(), chargeDefinition.getChargeTime(), chargeDefinition - .getChargeCalculation()); - } - - private LoanCharge(final Loan loan, final Charge charge, final BigDecimal amount, final Integer chargeTime, - final Integer chargeCalculation) { - this.loan = loan; - this.charge = charge; - this.amount = amount; - this.chargeTime = chargeTime; - this.chargeCalculation = chargeCalculation; - } - public void markAsFullyPaid() { this.amountPaid = this.amount; this.amountOutstanding = BigDecimal.ZERO; @@ -318,7 +230,7 @@ public class LoanCharge extends AbstractPersistable { public void update(final Loan loan) { this.loan = loan; } - + public void update(final BigDecimal amount, final LocalDate specifiedDueDate, final BigDecimal loanPrincipal) { if (specifiedDueDate != null) { this.dueForCollectionAsOfDate = specifiedDueDate.toDate(); @@ -353,47 +265,73 @@ public class LoanCharge extends AbstractPersistable { } } - public void update(final LoanChargeCommand command, final BigDecimal loanPrincipal) { + public Map update(final JsonCommand command, final BigDecimal loanPrincipal) { - if (command.isChargeTimeTypeChanged()) { - this.chargeTime = ChargeTimeType.fromInt(command.getChargeTimeType()).getValue(); + final Map actualChanges = new LinkedHashMap(7); + + final String dateFormatAsInput = command.dateFormat(); + final String localeAsInput = command.locale(); + + final String chargeTimeParamName = "chargeTime"; + if (command.isChangeInIntegerParameterNamed(chargeTimeParamName, this.chargeTime)) { + final Integer newValue = command.integerValueOfParameterNamed(chargeTimeParamName); + actualChanges.put(chargeTimeParamName, newValue); + actualChanges.put("locale", localeAsInput); + this.chargeTime = ChargeTimeType.fromInt(newValue).getValue(); } - if (command.isChargeCalculationTypeChanged()) { - this.chargeCalculation = ChargeCalculationType.fromInt(command.getChargeCalculationType()).getValue(); + final String chargeCalculationParamName = "chargeCalculation"; + if (command.isChangeInIntegerParameterNamed(chargeCalculationParamName, this.chargeCalculation)) { + final Integer newValue = command.integerValueOfParameterNamed(chargeCalculationParamName); + actualChanges.put(chargeCalculationParamName, newValue); + actualChanges.put("locale", localeAsInput); + this.chargeCalculation = ChargeCalculationType.fromInt(newValue).getValue(); } - if (command.isSpecifiedDueDateChanged()) { - this.dueForCollectionAsOfDate = command.getSpecifiedDueDate().toDate(); + final String specifiedDueDateParamName = "specifiedDueDate"; + if (command.isChangeInLocalDateParameterNamed(specifiedDueDateParamName, getDueForCollectionAsOfLocalDate())) { + final String valueAsInput = command.stringValueOfParameterNamed(specifiedDueDateParamName); + actualChanges.put(specifiedDueDateParamName, valueAsInput); + actualChanges.put("dateFormat", dateFormatAsInput); + actualChanges.put("locale", localeAsInput); + + final LocalDate newValue = command.localDateValueOfParameterNamed(specifiedDueDateParamName); + this.dueForCollectionAsOfDate = newValue.toDate(); } - if (command.isAmountChanged()) { + final String amountParamName = "amount"; + if (command.isChangeInBigDecimalParameterNamed(amountParamName, this.amount)) { + final BigDecimal newValue = command.bigDecimalValueOfParameterNamed(amountParamName); + actualChanges.put(amountParamName, newValue); + actualChanges.put("locale", localeAsInput); switch (ChargeCalculationType.fromInt(this.chargeCalculation)) { case INVALID: break; case FLAT: - this.amount = command.getAmount(); + this.amount = newValue; break; case PERCENT_OF_AMOUNT: - this.percentage = command.getAmount(); + this.percentage = newValue; this.amountPercentageAppliedTo = loanPrincipal; this.amount = percentageOf(this.amountPercentageAppliedTo, this.percentage); this.amountOutstanding = calculateOutstanding(); break; case PERCENT_OF_AMOUNT_AND_INTEREST: - this.percentage = command.getAmount(); + this.percentage = newValue; this.amount = null; this.amountPercentageAppliedTo = null; this.amountOutstanding = null; break; case PERCENT_OF_INTEREST: - this.percentage = command.getAmount(); + this.percentage = newValue; this.amount = null; this.amountPercentageAppliedTo = null; this.amountOutstanding = null; break; } } + + return actualChanges; } public boolean isDueAtDisbursement() { @@ -411,9 +349,7 @@ public class LoanCharge extends AbstractPersistable { public LoanChargeCommand toCommand() { final LocalDate specifiedDueDate = getDueForCollectionAsOfLocalDate(); - final Set modifiedParameters = new HashSet(); - return new LoanChargeCommand(modifiedParameters, this.getId(), this.loan.getId(), this.charge.getId(), this.amount, - this.chargeTime, this.chargeCalculation, specifiedDueDate); + return new LoanChargeCommand(this.charge.getId(), this.amount, this.chargeTime, this.chargeCalculation, specifiedDueDate); } public LocalDate getDueForCollectionAsOfLocalDate() { diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/handler/AddLoanChargeCommandHandler.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/handler/AddLoanChargeCommandHandler.java new file mode 100644 index 000000000..d37f88bd2 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/handler/AddLoanChargeCommandHandler.java @@ -0,0 +1,27 @@ +package org.mifosplatform.portfolio.loanaccount.handler; + +import org.mifosplatform.commands.handler.NewCommandSourceHandler; +import org.mifosplatform.infrastructure.core.api.JsonCommand; +import org.mifosplatform.infrastructure.core.data.EntityIdentifier; +import org.mifosplatform.portfolio.loanaccount.service.LoanWritePlatformService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class AddLoanChargeCommandHandler implements NewCommandSourceHandler { + + private final LoanWritePlatformService writePlatformService; + + @Autowired + public AddLoanChargeCommandHandler(final LoanWritePlatformService writePlatformService) { + this.writePlatformService = writePlatformService; + } + + @Transactional + @Override + public EntityIdentifier processCommand(final JsonCommand command) { + + return this.writePlatformService.addLoanCharge(command.resourceId(), command); + } +} \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/handler/DeleteLoanChargeCommandHandler.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/handler/DeleteLoanChargeCommandHandler.java new file mode 100644 index 000000000..d4b0762a1 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/handler/DeleteLoanChargeCommandHandler.java @@ -0,0 +1,27 @@ +package org.mifosplatform.portfolio.loanaccount.handler; + +import org.mifosplatform.commands.handler.NewCommandSourceHandler; +import org.mifosplatform.infrastructure.core.api.JsonCommand; +import org.mifosplatform.infrastructure.core.data.EntityIdentifier; +import org.mifosplatform.portfolio.loanaccount.service.LoanWritePlatformService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class DeleteLoanChargeCommandHandler implements NewCommandSourceHandler { + + private final LoanWritePlatformService writePlatformService; + + @Autowired + public DeleteLoanChargeCommandHandler(final LoanWritePlatformService writePlatformService) { + this.writePlatformService = writePlatformService; + } + + @Transactional + @Override + public EntityIdentifier processCommand(final JsonCommand command) { + + return this.writePlatformService.deleteLoanCharge(command.resourceId(), command.subResourceId(), command); + } +} \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/handler/UpdateLoanChargeCommandHandler.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/handler/UpdateLoanChargeCommandHandler.java new file mode 100644 index 000000000..e3d0624bc --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/handler/UpdateLoanChargeCommandHandler.java @@ -0,0 +1,27 @@ +package org.mifosplatform.portfolio.loanaccount.handler; + +import org.mifosplatform.commands.handler.NewCommandSourceHandler; +import org.mifosplatform.infrastructure.core.api.JsonCommand; +import org.mifosplatform.infrastructure.core.data.EntityIdentifier; +import org.mifosplatform.portfolio.loanaccount.service.LoanWritePlatformService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class UpdateLoanChargeCommandHandler implements NewCommandSourceHandler { + + private final LoanWritePlatformService writePlatformService; + + @Autowired + public UpdateLoanChargeCommandHandler(final LoanWritePlatformService writePlatformService) { + this.writePlatformService = writePlatformService; + } + + @Transactional + @Override + public EntityIdentifier processCommand(final JsonCommand command) { + + return this.writePlatformService.updateLoanCharge(command.resourceId(), command.subResourceId(), command); + } +} \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/handler/WaiveLoanChargeCommandHandler.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/handler/WaiveLoanChargeCommandHandler.java new file mode 100644 index 000000000..b26d283b7 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/handler/WaiveLoanChargeCommandHandler.java @@ -0,0 +1,27 @@ +package org.mifosplatform.portfolio.loanaccount.handler; + +import org.mifosplatform.commands.handler.NewCommandSourceHandler; +import org.mifosplatform.infrastructure.core.api.JsonCommand; +import org.mifosplatform.infrastructure.core.data.EntityIdentifier; +import org.mifosplatform.portfolio.loanaccount.service.LoanWritePlatformService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +public class WaiveLoanChargeCommandHandler implements NewCommandSourceHandler { + + private final LoanWritePlatformService writePlatformService; + + @Autowired + public WaiveLoanChargeCommandHandler(final LoanWritePlatformService writePlatformService) { + this.writePlatformService = writePlatformService; + } + + @Transactional + @Override + public EntityIdentifier processCommand(final JsonCommand command) { + + return this.writePlatformService.waiveLoanCharge(command.resourceId(), command.subResourceId(), command); + } +} \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/serialization/CalculateLoanScheduleQueryFromApiJsonDeserializer.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/serialization/CalculateLoanScheduleQueryFromApiJsonDeserializer.java index b95788559..7d427ce37 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/serialization/CalculateLoanScheduleQueryFromApiJsonDeserializer.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/serialization/CalculateLoanScheduleQueryFromApiJsonDeserializer.java @@ -88,9 +88,9 @@ public final class CalculateLoanScheduleQueryFromApiJsonDeserializer extends Abs for (int i = 0; i < array.size(); i++) { final JsonObject loanChargeElement = array.get(i).getAsJsonObject(); - final Set parametersPassedInForChargesCommand = new HashSet(); - final Long id = fromApiJsonHelper.extractLongNamed("id", loanChargeElement); + // final Long id = fromApiJsonHelper.extractLongNamed("id", + // loanChargeElement); final Long chargeId = fromApiJsonHelper.extractLongNamed("chargeId", loanChargeElement); final BigDecimal amount = fromApiJsonHelper.extractBigDecimalNamed("amount", loanChargeElement, locale); final Integer chargeTimeType = fromApiJsonHelper.extractIntegerNamed("chargeTimeType", loanChargeElement, locale); @@ -99,8 +99,7 @@ public final class CalculateLoanScheduleQueryFromApiJsonDeserializer extends Abs final LocalDate specifiedDueDate = fromApiJsonHelper.extractLocalDateNamed("specifiedDueDate", loanChargeElement, dateFormat, locale); - charges[i] = new LoanChargeCommand(parametersPassedInForChargesCommand, id, null, chargeId, amount, chargeTimeType, - chargeCalculationType, specifiedDueDate); + charges[i] = new LoanChargeCommand(chargeId, amount, chargeTimeType, chargeCalculationType, specifiedDueDate); } } } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/serialization/LoanApplicationCommandFromApiJsonDeserializer.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/serialization/LoanApplicationCommandFromApiJsonDeserializer.java index 461676c40..87bd144a3 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/serialization/LoanApplicationCommandFromApiJsonDeserializer.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/serialization/LoanApplicationCommandFromApiJsonDeserializer.java @@ -116,9 +116,9 @@ public final class LoanApplicationCommandFromApiJsonDeserializer extends Abstrac for (int i = 0; i < array.size(); i++) { final JsonObject loanChargeElement = array.get(i).getAsJsonObject(); - final Set parametersPassedInForChargesCommand = new HashSet(); - final Long id = fromApiJsonHelper.extractLongNamed("id", loanChargeElement); + // final Long id = fromApiJsonHelper.extractLongNamed("id", + // loanChargeElement); final Long chargeId = fromApiJsonHelper.extractLongNamed("chargeId", loanChargeElement); final BigDecimal amount = fromApiJsonHelper.extractBigDecimalNamed("amount", loanChargeElement, locale); final Integer chargeTimeType = fromApiJsonHelper.extractIntegerNamed("chargeTimeType", loanChargeElement, locale); @@ -127,8 +127,7 @@ public final class LoanApplicationCommandFromApiJsonDeserializer extends Abstrac final LocalDate specifiedDueDate = fromApiJsonHelper.extractLocalDateNamed("specifiedDueDate", loanChargeElement, dateFormat, locale); - charges[i] = new LoanChargeCommand(parametersPassedInForChargesCommand, id, null, chargeId, amount, chargeTimeType, - chargeCalculationType, specifiedDueDate); + charges[i] = new LoanChargeCommand(chargeId, amount, chargeTimeType, chargeCalculationType, specifiedDueDate); } } } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/serialization/LoanChargeCommandFromApiJsonDeserializer.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/serialization/LoanChargeCommandFromApiJsonDeserializer.java new file mode 100644 index 000000000..39189f279 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/serialization/LoanChargeCommandFromApiJsonDeserializer.java @@ -0,0 +1,60 @@ +package org.mifosplatform.portfolio.loanaccount.serialization; + +import java.lang.reflect.Type; +import java.math.BigDecimal; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import org.apache.commons.lang.StringUtils; +import org.joda.time.LocalDate; +import org.mifosplatform.infrastructure.core.exception.InvalidJsonException; +import org.mifosplatform.infrastructure.core.serialization.AbstractFromApiJsonDeserializer; +import org.mifosplatform.infrastructure.core.serialization.FromApiJsonDeserializer; +import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper; +import org.mifosplatform.portfolio.loanaccount.command.LoanChargeCommand; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import com.google.gson.JsonElement; +import com.google.gson.reflect.TypeToken; + +/** + * Implementation of {@link FromApiJsonDeserializer} for + * {@link LoanChargeCommand}'s. + */ +@Component +public final class LoanChargeCommandFromApiJsonDeserializer extends AbstractFromApiJsonDeserializer { + + /** + * The parameters supported for this command. + */ + final Set supportedParameters = new HashSet(Arrays.asList("chargeId", "amount", "chargeTimeType", + "chargeCalculationType", "specifiedDueDate", "locale", "dateFormat")); + + private final FromJsonHelper fromApiJsonHelper; + + @Autowired + public LoanChargeCommandFromApiJsonDeserializer(final FromJsonHelper fromApiJsonHelper) { + this.fromApiJsonHelper = fromApiJsonHelper; + } + + @Override + public LoanChargeCommand commandFromApiJson(final String json) { + + if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); } + + final Type typeOfMap = new TypeToken>() {}.getType(); + fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, supportedParameters); + + final JsonElement element = fromApiJsonHelper.parse(json); + final Long chargeId = fromApiJsonHelper.extractLongNamed("chargeId", element); + final BigDecimal amount = fromApiJsonHelper.extractBigDecimalWithLocaleNamed("amount", element); + final Integer chargeTimeType = fromApiJsonHelper.extractIntegerWithLocaleNamed("chargeTimeType", element); + final Integer chargeCalculationType = fromApiJsonHelper.extractIntegerWithLocaleNamed("chargeCalculationType", element); + final LocalDate specifiedDueDate = fromApiJsonHelper.extractLocalDateNamed("specifiedDueDate", element); + + return new LoanChargeCommand(chargeId, amount, chargeTimeType, chargeCalculationType, specifiedDueDate); + } +} \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanWritePlatformService.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanWritePlatformService.java index c6dcc1559..6532ce4fe 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanWritePlatformService.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanWritePlatformService.java @@ -3,7 +3,6 @@ package org.mifosplatform.portfolio.loanaccount.service; import org.mifosplatform.infrastructure.core.api.JsonCommand; import org.mifosplatform.infrastructure.core.data.EntityIdentifier; import org.mifosplatform.organisation.staff.command.BulkTransferLoanOfficerCommand; -import org.mifosplatform.portfolio.loanaccount.command.LoanChargeCommand; import org.springframework.security.access.prepost.PreAuthorize; public interface LoanWritePlatformService { @@ -38,17 +37,13 @@ public interface LoanWritePlatformService { EntityIdentifier closeAsRescheduled(Long loanId, JsonCommand command); - @PreAuthorize(value = "hasAnyRole('ALL_FUNCTIONS', 'PORTFOLIO_MANAGEMENT_SUPER_USER', 'CREATE_LOANCHARGE')") - EntityIdentifier addLoanCharge(LoanChargeCommand command); + EntityIdentifier addLoanCharge(Long loanId, JsonCommand command); - @PreAuthorize(value = "hasAnyRole('ALL_FUNCTIONS', 'PORTFOLIO_MANAGEMENT_SUPER_USER', 'UPDATE_LOANCHARGE')") - EntityIdentifier updateLoanCharge(LoanChargeCommand command); + EntityIdentifier updateLoanCharge(Long loanId, Long loanChargeId, JsonCommand command); - @PreAuthorize(value = "hasAnyRole('ALL_FUNCTIONS', 'PORTFOLIO_MANAGEMENT_SUPER_USER', 'DELETE_LOANCHARGE')") - EntityIdentifier deleteLoanCharge(final Long loanId, final Long loanChargeId); + EntityIdentifier deleteLoanCharge(Long loanId, Long loanChargeId, JsonCommand command); - @PreAuthorize(value = "hasAnyRole('ALL_FUNCTIONS', 'PORTFOLIO_MANAGEMENT_SUPER_USER', 'WAIVE_LOANCHARGE')") - EntityIdentifier waiveLoanCharge(LoanChargeCommand command); + EntityIdentifier waiveLoanCharge(Long loanId, Long loanChargeId, JsonCommand command); @PreAuthorize(value = "hasAnyRole('ALL_FUNCTIONS', 'PORTFOLIO_MANAGEMENT_SUPER_USER', 'BULKREASSIGN_LOAN')") EntityIdentifier bulkLoanReassignment(final BulkTransferLoanOfficerCommand command); diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java index 48dd2e9ed..919d7b098 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java @@ -33,7 +33,6 @@ import org.mifosplatform.portfolio.client.exception.ClientNotFoundException; import org.mifosplatform.portfolio.fund.domain.Fund; import org.mifosplatform.portfolio.loanaccount.command.LoanApplicationCommand; import org.mifosplatform.portfolio.loanaccount.command.LoanChargeCommand; -import org.mifosplatform.portfolio.loanaccount.command.LoanChargeCommandValidator; import org.mifosplatform.portfolio.loanaccount.command.LoanStateTransitionCommand; import org.mifosplatform.portfolio.loanaccount.command.LoanTransactionCommand; import org.mifosplatform.portfolio.loanaccount.domain.DefaultLoanLifecycleStateMachine; @@ -55,6 +54,7 @@ import org.mifosplatform.portfolio.loanaccount.loanschedule.query.CalculateLoanS import org.mifosplatform.portfolio.loanaccount.loanschedule.service.LoanScheduleCalculationPlatformService; import org.mifosplatform.portfolio.loanaccount.serialization.CalculateLoanScheduleQueryFromApiJsonDeserializer; import org.mifosplatform.portfolio.loanaccount.serialization.LoanApplicationCommandFromApiJsonDeserializer; +import org.mifosplatform.portfolio.loanaccount.serialization.LoanChargeCommandFromApiJsonDeserializer; import org.mifosplatform.portfolio.loanaccount.serialization.LoanStateTransitionCommandFromApiJsonDeserializer; import org.mifosplatform.portfolio.loanaccount.serialization.LoanTransactionCommandFromApiJsonDeserializer; import org.mifosplatform.portfolio.loanproduct.domain.LoanProduct; @@ -78,6 +78,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf private final CalculateLoanScheduleQueryFromApiJsonDeserializer calculateLoanScheduleQueryFromApiJsonDeserializer; private final LoanStateTransitionCommandFromApiJsonDeserializer loanStateTransitionCommandFromApiJsonDeserializer; private final LoanTransactionCommandFromApiJsonDeserializer loanTransactionCommandFromApiJsonDeserializer; + private final LoanChargeCommandFromApiJsonDeserializer loanChargeCommandFromApiJsonDeserializer; private final LoanRepository loanRepository; private final NoteRepository noteRepository; private final LoanScheduleCalculationPlatformService calculationPlatformService; @@ -96,6 +97,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf final LoanApplicationCommandFromApiJsonDeserializer fromApiJsonDeserializer, final LoanStateTransitionCommandFromApiJsonDeserializer loanStateTransitionCommandFromApiJsonDeserializer, final LoanTransactionCommandFromApiJsonDeserializer loanTransactionCommandFromApiJsonDeserializer, + final LoanChargeCommandFromApiJsonDeserializer loanChargeCommandFromApiJsonDeserializer, final CalculateLoanScheduleQueryFromApiJsonDeserializer calculateLoanScheduleQueryFromApiJsonDeserializer, final AprCalculator aprCalculator, final LoanAssembler loanAssembler, final LoanChargeAssembler loanChargeAssembler, final LoanRepository loanRepository, final LoanTransactionRepository loanTransactionRepository, @@ -108,6 +110,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf this.fromApiJsonDeserializer = fromApiJsonDeserializer; this.loanStateTransitionCommandFromApiJsonDeserializer = loanStateTransitionCommandFromApiJsonDeserializer; this.loanTransactionCommandFromApiJsonDeserializer = loanTransactionCommandFromApiJsonDeserializer; + this.loanChargeCommandFromApiJsonDeserializer = loanChargeCommandFromApiJsonDeserializer; this.calculateLoanScheduleQueryFromApiJsonDeserializer = calculateLoanScheduleQueryFromApiJsonDeserializer; this.aprCalculator = aprCalculator; this.loanAssembler = loanAssembler; @@ -420,14 +423,14 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf final LoanTransactionCommand loanTransactionCommand = this.loanTransactionCommandFromApiJsonDeserializer.commandFromApiJson(command .json()); loanTransactionCommand.validate(); - + final LocalDate transactionDate = command.localDateValueOfParameterNamed("transactionDate"); final BigDecimal transactionAmount = command.bigDecimalValueOfParameterNamed("transactionAmount"); - + final Map changes = new LinkedHashMap(); changes.put("transactionDate", command.stringValueOfParameterNamed("transactionDate")); changes.put("transactionAmount", command.stringValueOfParameterNamed("transactionAmount")); - + final Loan loan = retrieveLoanBy(loanId); if (this.isBeforeToday(transactionDate) && currentUser.canNotMakeRepaymentOnLoanInPast()) { throw new NoAuthorizationException( @@ -443,7 +446,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf Note note = Note.loanTransactionNote(loan, loanRepayment, noteText); this.noteRepository.save(note); } - + changes.put("locale", command.locale()); changes.put("dateFormat", command.dateFormat()); @@ -459,7 +462,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf final LoanTransactionCommand loanTransactionCommand = this.loanTransactionCommandFromApiJsonDeserializer.commandFromApiJson(command .json()); loanTransactionCommand.validate(); - + final Loan loan = retrieveLoanBy(loanId); final LoanTransaction transactionToAdjust = this.loanTransactionRepository.findOne(transactionId); @@ -467,13 +470,13 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf final LocalDate transactionDate = command.localDateValueOfParameterNamed("transactionDate"); final BigDecimal transactionAmount = command.bigDecimalValueOfParameterNamed("transactionAmount"); - + final Map changes = new LinkedHashMap(); changes.put("transactionDate", command.stringValueOfParameterNamed("transactionDate")); changes.put("transactionAmount", command.stringValueOfParameterNamed("transactionAmount")); - - final LoanTransaction newTransactionDetail = loan.adjustExistingTransaction(transactionDate, transactionAmount, defaultLoanLifecycleStateMachine(), - transactionToAdjust); + + final LoanTransaction newTransactionDetail = loan.adjustExistingTransaction(transactionDate, transactionAmount, + defaultLoanLifecycleStateMachine(), transactionToAdjust); if (newTransactionDetail.isGreaterThanZero(loan.getPrincpal().getCurrency())) { this.loanTransactionRepository.save(newTransactionDetail); } @@ -489,7 +492,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf changes.put("locale", command.locale()); changes.put("dateFormat", command.dateFormat()); - + return EntityIdentifier.subResourceResult(loanId, transactionId, command.commandId(), changes); } @@ -502,7 +505,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf final LoanTransactionCommand loanTransactionCommand = this.loanTransactionCommandFromApiJsonDeserializer.commandFromApiJson(command .json()); loanTransactionCommand.validate(); - + final Map changes = new LinkedHashMap(); changes.put("transactionDate", command.stringValueOfParameterNamed("transactionDate")); changes.put("transactionAmount", command.stringValueOfParameterNamed("transactionAmount")); @@ -520,7 +523,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf final Note note = Note.loanTransactionNote(loan, waiveTransaction, noteText); this.noteRepository.save(note); } - + changes.put("locale", command.locale()); changes.put("dateFormat", command.dateFormat()); @@ -535,7 +538,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf final LoanTransactionCommand loanTransactionCommand = this.loanTransactionCommandFromApiJsonDeserializer.commandFromApiJson(command .json()); loanTransactionCommand.validateNonMonetaryTransaction(); - + final Map changes = new LinkedHashMap(); changes.put("transactionDate", command.stringValueOfParameterNamed("transactionDate")); @@ -570,7 +573,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf loanTransactionCommand.validateNonMonetaryTransaction(); final Loan loan = retrieveLoanBy(loanId); - + final Map changes = new LinkedHashMap(); changes.put("transactionDate", command.stringValueOfParameterNamed("transactionDate")); @@ -586,17 +589,17 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf final Note note = Note.loanNote(loan, noteText); this.noteRepository.save(note); } - + changes.put("locale", command.locale()); changes.put("dateFormat", command.dateFormat()); - + EntityIdentifier result = null; if (possibleClosingTransaction != null) { result = EntityIdentifier.subResourceResult(loanId, possibleClosingTransaction.getId(), command.commandId(), changes); } else { result = EntityIdentifier.resourceResult(loanId, command.commandId(), changes); } - + return result; } @@ -610,7 +613,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf loanTransactionCommand.validateNonMonetaryTransaction(); final Loan loan = retrieveLoanBy(loanId); - + final Map changes = new LinkedHashMap(); changes.put("transactionDate", command.stringValueOfParameterNamed("transactionDate")); @@ -624,7 +627,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf final Note note = Note.loanNote(loan, noteText); this.noteRepository.save(note); } - + changes.put("locale", command.locale()); changes.put("dateFormat", command.dateFormat()); @@ -633,72 +636,68 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf @Transactional @Override - public EntityIdentifier addLoanCharge(final LoanChargeCommand command) { + public EntityIdentifier addLoanCharge(final Long loanId, final JsonCommand command) { this.context.authenticatedUser(); - LoanChargeCommandValidator validator = new LoanChargeCommandValidator(command); - validator.validateForCreate(); + final LoanChargeCommand loanChargeCommand = this.loanChargeCommandFromApiJsonDeserializer.commandFromApiJson(command.json()); + loanChargeCommand.validateForCreate(); - final Loan loan = this.loanRepository.findOne(command.getLoanId()); - if (loan == null) { throw new LoanNotFoundException(command.getLoanId()); } - - final Charge chargeDefinition = this.chargeRepository.findOne(command.getChargeId()); - if (chargeDefinition == null || chargeDefinition.isDeleted()) { throw new ChargeNotFoundException(command.getChargeId()); } + final Loan loan = retrieveLoanBy(loanId); + final Long chargeDefinitionId = command.longValueOfParameterNamed("chargeId"); + final Charge chargeDefinition = this.chargeRepository.findOne(chargeDefinitionId); + if (chargeDefinition == null || chargeDefinition.isDeleted()) { throw new ChargeNotFoundException(chargeDefinitionId); } if (!chargeDefinition.isActive()) { throw new ChargeIsNotActiveException(chargeDefinition.getId(), chargeDefinition.getName()); } - final LoanCharge loanCharge = LoanCharge.createNew(loan, chargeDefinition, command); + final LoanCharge loanCharge = LoanCharge.createNewFromJson(loan, chargeDefinition, command); if (!loan.hasCurrencyCodeOf(chargeDefinition.getCurrencyCode())) { String errorMessage = "Charge and Loan must have the same currency."; throw new InvalidCurrencyException("charge", "attach.to.loan", errorMessage); } + this.loanChargeRepository.save(loanCharge); + loan.addLoanCharge(loanCharge); - this.loanRepository.saveAndFlush(loan); + this.loanRepository.save(loan); - return new EntityIdentifier(loanCharge.getId()); + return EntityIdentifier.subResourceResult(loanId, loanCharge.getId(), command.commandId()); } @Transactional @Override - public EntityIdentifier updateLoanCharge(final LoanChargeCommand command) { + public EntityIdentifier updateLoanCharge(final Long loanId, final Long loanChargeId, final JsonCommand command) { this.context.authenticatedUser(); - LoanChargeCommandValidator validator = new LoanChargeCommandValidator(command); - validator.validateForUpdate(); + final LoanChargeCommand loanChargeCommand = this.loanChargeCommandFromApiJsonDeserializer.commandFromApiJson(command.json()); + loanChargeCommand.validateForUpdate(); - final Long loanId = command.getLoanId(); final Loan loan = retrieveLoanBy(loanId); - - final Long loanChargeId = command.getId(); final LoanCharge loanCharge = retrieveLoanChargeBy(loanId, loanChargeId); - loan.updateLoanCharge(loanCharge, command); + final Map changes = loan.updateLoanCharge(loanCharge, command); this.loanRepository.save(loan); - return new EntityIdentifier(loanCharge.getId()); + return EntityIdentifier.subResourceResult(loanId, loanChargeId, command.commandId(), changes); } @Transactional @Override - public EntityIdentifier waiveLoanCharge(final LoanChargeCommand command) { + public EntityIdentifier waiveLoanCharge(final Long loanId, final Long loanChargeId, final JsonCommand command) { this.context.authenticatedUser(); - // LoanChargeCommandValidator validator = new - // LoanChargeCommandValidator(command); - // validator.validateForUpdate(); + final LoanChargeCommand loanChargeCommand = this.loanChargeCommandFromApiJsonDeserializer.commandFromApiJson(command.json()); + loanChargeCommand.validateForUpdate(); - final Long loanId = command.getLoanId(); final Loan loan = retrieveLoanBy(loanId); - - final Long loanChargeId = command.getId(); final LoanCharge loanCharge = retrieveLoanChargeBy(loanId, loanChargeId); + + final Map changes = new LinkedHashMap(3); - final LoanTransaction waiveTransaction = loan.waiveLoanCharge(loanCharge, defaultLoanLifecycleStateMachine()); + final LoanTransaction waiveTransaction = loan.waiveLoanCharge(loanCharge, defaultLoanLifecycleStateMachine(), changes); this.loanTransactionRepository.save(waiveTransaction); this.loanRepository.save(loan); @@ -709,23 +708,22 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf this.noteRepository.save(note); } - return new EntityIdentifier(loanCharge.getId()); + return EntityIdentifier.subResourceResult(loanId, loanChargeId, command.commandId(), changes); } @Transactional @Override - public EntityIdentifier deleteLoanCharge(final Long loanId, final Long loanChargeId) { + public EntityIdentifier deleteLoanCharge(final Long loanId, final Long loanChargeId, final JsonCommand command) { this.context.authenticatedUser(); final Loan loan = retrieveLoanBy(loanId); - final LoanCharge loanCharge = retrieveLoanChargeBy(loanId, loanChargeId); loan.removeLoanCharge(loanCharge); this.loanRepository.save(loan); - return new EntityIdentifier(loanCharge.getId()); + return EntityIdentifier.subResourceResult(loanId, loanChargeId, command.commandId()); } private Loan retrieveLoanBy(final Long loanId) {