MIFOSX-172: WIP - update api docs on loan application workflow api.

This commit is contained in:
Keith Woodlock
2013-02-22 14:30:47 +00:00
parent 29360a8fd6
commit 634a66cbe9
16 changed files with 837 additions and 379 deletions
@@ -234,8 +234,7 @@ public class LoansApiResource {
if (!associationParameters.isEmpty()) {
if (associationParameters.contains("all")) {
associationParameters.addAll(Arrays.asList("repaymentSchedule", "transactions", "permissions", "charges", "guarantors",
"collateral"));
associationParameters.addAll(Arrays.asList("repaymentSchedule", "transactions", "charges", "guarantors", "collateral"));
}
if (associationParameters.contains("guarantors")) {
@@ -254,11 +253,8 @@ public class LoansApiResource {
}
}
if (associationParameters.contains("repaymentSchedule") || associationParameters.contains("permissions")) {
if (associationParameters.contains("repaymentSchedule")) {
mandatoryResponseParameters.add("repaymentSchedule");
}
if (associationParameters.contains("repaymentSchedule")) {
mandatoryResponseParameters.add("repaymentSchedule");
final RepaymentScheduleRelatedLoanData repaymentScheduleRelatedData = loanBasicDetails.repaymentScheduleRelatedData();
repaymentSchedule = this.loanReadPlatformService.retrieveRepaymentSchedule(loanId, repaymentScheduleRelatedData);
@@ -393,7 +389,7 @@ public class LoansApiResource {
if (is(commandParam, "reject")) {
final CommandWrapper commandRequest = builder.rejectLoanApplication(loanId).build();
result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
} else if (is(commandParam, "withdrewbyclient")) {
} else if (is(commandParam, "withdrawnByApplicant")) {
final CommandWrapper commandRequest = builder.withdrawLoanApplication(loanId).build();
result = this.commandsSourceWritePlatformService.logCommandSource(commandRequest);
} else if (is(commandParam, "approve")) {
@@ -1,82 +0,0 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.portfolio.loanaccount.command;
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 any of the loan state transitions eg. reject, withdrawn
* by client, approve, disburse
*/
public class LoanStateTransitionCommand {
private final LocalDate eventDate;
private final String note;
private final LocalDate approvedOnDate;
private final LocalDate rejectedOnDate;
private final LocalDate withdrawnOnDate;
private final LocalDate disbursedOnDate;
public LoanStateTransitionCommand(final LocalDate eventDate, final String note, final LocalDate approvedOnDate,
final LocalDate rejectedOnDate, final LocalDate withdrawnOnDate, final LocalDate disbursedOnDate) {
this.eventDate = eventDate;
this.note = note;
this.approvedOnDate = approvedOnDate;
this.rejectedOnDate = rejectedOnDate;
this.withdrawnOnDate = withdrawnOnDate;
this.disbursedOnDate = disbursedOnDate;
}
public LocalDate getApprovedOnDate() {
LocalDate dateValue = this.approvedOnDate;
if (this.approvedOnDate == null) {
dateValue = eventDate;
}
return dateValue;
}
public LocalDate getRejectedOnDate() {
LocalDate dateValue = this.rejectedOnDate;
if (this.rejectedOnDate == null) {
dateValue = eventDate;
}
return dateValue;
}
public LocalDate getWithdrawnOnDate() {
LocalDate dateValue = this.withdrawnOnDate;
if (this.withdrawnOnDate == null) {
dateValue = eventDate;
}
return dateValue;
}
public LocalDate getDisbursedOnDate() {
LocalDate dateValue = this.disbursedOnDate;
if (this.disbursedOnDate == null) {
dateValue = eventDate;
}
return dateValue;
}
public void validate() {
List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("loan.transition");
baseDataValidator.reset().parameter("eventDate").value(this.eventDate).notNull();
baseDataValidator.reset().parameter("note").value(this.note).notExceedingLengthOf(1000);
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist",
"Validation errors exist.", dataValidationErrors); }
}
}
@@ -931,9 +931,6 @@ public class Loan extends AbstractAuditableCustom<AppUser, Long> {
actualChanges.put("status", LoanEnumerations.status(this.loanStatus));
LocalDate rejectedOn = command.localDateValueOfParameterNamed("rejectedOnDate");
if (rejectedOn == null) {
rejectedOn = command.localDateValueOfParameterNamed("eventDate");
}
final Locale locale = new Locale(command.locale());
final DateTimeFormatter fmt = DateTimeFormat.forPattern(command.dateFormat()).withLocale(locale);
@@ -146,6 +146,12 @@ public final class CalculateLoanScheduleQueryFromApiJsonHelper {
validateRepaymentsStartingFromDateAndInterestChargedFromDate(dataValidationErrors, expectedDisbursementDate,
repaymentsStartingFromDate, interestChargedFromDate);
final String transactionProcessingStrategyIdParameterName = "transactionProcessingStrategyId";
final Long transactionProcessingStrategyId = fromApiJsonHelper.extractLongNamed(transactionProcessingStrategyIdParameterName,
element);
baseDataValidator.reset().parameter(transactionProcessingStrategyIdParameterName).value(transactionProcessingStrategyId).notNull()
.integerGreaterThanZero();
// charges
final String chargesParameterName = "charges";
if (element.isJsonObject() && fromApiJsonHelper.parameterExists(chargesParameterName, element)) {
@@ -547,4 +547,25 @@ public final class LoanApplicationCommandFromApiJsonHelper {
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist",
"Validation errors exist.", dataValidationErrors); }
}
public void validateForUndo(final String json) {
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
final Set<String> undoSupportedParameters = new HashSet<String>(Arrays.asList("note"));
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, undoSupportedParameters);
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("loanapplication.undo");
final JsonElement element = fromApiJsonHelper.parse(json);
final String note = "note";
if (fromApiJsonHelper.parameterExists(note, element)) {
final String noteText = fromApiJsonHelper.extractStringNamed(note, element);
baseDataValidator.reset().parameter(note).value(noteText).notExceedingLengthOf(1000);
}
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist",
"Validation errors exist.", dataValidationErrors); }
}
}
@@ -0,0 +1,110 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.portfolio.loanaccount.serialization;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.lang.StringUtils;
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.InvalidJsonException;
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import com.google.gson.JsonElement;
import com.google.gson.reflect.TypeToken;
@Component
public final class LoanApplicationTransitionApiJsonValidator {
private final FromJsonHelper fromApiJsonHelper;
@Autowired
public LoanApplicationTransitionApiJsonValidator(final FromJsonHelper fromApiJsonHelper) {
this.fromApiJsonHelper = fromApiJsonHelper;
}
private void throwExceptionIfValidationWarningsExist(final List<ApiParameterError> dataValidationErrors) {
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist",
"Validation errors exist.", dataValidationErrors); }
}
public void validateApproval(final String json) {
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
final Set<String> disbursementParameters = new HashSet<String>(Arrays.asList("approvedOnDate", "note", "locale",
"dateFormat"));
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, disbursementParameters);
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("loanapplication");
final JsonElement element = fromApiJsonHelper.parse(json);
final LocalDate approvedOnDate = fromApiJsonHelper.extractLocalDateNamed("approvedOnDate", element);
baseDataValidator.reset().parameter("approvedOnDate").value(approvedOnDate).notNull();
final String note = fromApiJsonHelper.extractStringNamed("note", element);
baseDataValidator.reset().parameter("note").value(note).notExceedingLengthOf(1000);
throwExceptionIfValidationWarningsExist(dataValidationErrors);
}
public void validateRejection(final String json) {
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
final Set<String> disbursementParameters = new HashSet<String>(Arrays.asList("rejectedOnDate", "note", "locale", "dateFormat"));
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, disbursementParameters);
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("loanapplication");
final JsonElement element = fromApiJsonHelper.parse(json);
final LocalDate rejectedOnDate = fromApiJsonHelper.extractLocalDateNamed("rejectedOnDate", element);
baseDataValidator.reset().parameter("rejectedOnDate").value(rejectedOnDate).notNull();
final String note = fromApiJsonHelper.extractStringNamed("note", element);
baseDataValidator.reset().parameter("note").value(note).notExceedingLengthOf(1000);
throwExceptionIfValidationWarningsExist(dataValidationErrors);
}
public void validateApplicantWithdrawal(final String json) {
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
final Set<String> disbursementParameters = new HashSet<String>(Arrays.asList("withdrawnOnDate", "note", "locale", "dateFormat"));
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, disbursementParameters);
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
final DataValidatorBuilder baseDataValidator = new DataValidatorBuilder(dataValidationErrors).resource("loanapplication");
final JsonElement element = fromApiJsonHelper.parse(json);
final LocalDate withdrawnOnDate = fromApiJsonHelper.extractLocalDateNamed("withdrawnOnDate", element);
baseDataValidator.reset().parameter("withdrawnOnDate").value(withdrawnOnDate).notNull();
final String note = fromApiJsonHelper.extractStringNamed("note", element);
baseDataValidator.reset().parameter("note").value(note).notExceedingLengthOf(1000);
throwExceptionIfValidationWarningsExist(dataValidationErrors);
}
}
@@ -1,66 +0,0 @@
/**
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.mifosplatform.portfolio.loanaccount.serialization;
import java.lang.reflect.Type;
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.LoanStateTransitionCommand;
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 LoanStateTransitionCommand}'s.
*/
@Component
public final class LoanStateTransitionCommandFromApiJsonDeserializer extends AbstractFromApiJsonDeserializer<LoanStateTransitionCommand> {
/**
* The parameters supported for this command.
*/
final Set<String> supportedParameters = new HashSet<String>(Arrays.asList("eventDate", "note", "locale", "dateFormat", "status",
"approvedOnDate", "rejectedOnDate", "withdrawnOnDate", "disbursedOnDate", "expectedMaturityDate"));
private final FromJsonHelper fromApiJsonHelper;
@Autowired
public LoanStateTransitionCommandFromApiJsonDeserializer(final FromJsonHelper fromApiJsonHelper) {
this.fromApiJsonHelper = fromApiJsonHelper;
}
@Override
public LoanStateTransitionCommand commandFromApiJson(final String json) {
if (StringUtils.isBlank(json)) { throw new InvalidJsonException(); }
final Type typeOfMap = new TypeToken<Map<String, Object>>() {}.getType();
fromApiJsonHelper.checkForUnsupportedParameters(typeOfMap, json, supportedParameters);
final JsonElement element = fromApiJsonHelper.parse(json);
final LocalDate eventDate = fromApiJsonHelper.extractLocalDateNamed("eventDate", element);
final String note = fromApiJsonHelper.extractStringNamed("note", element);
final LocalDate approvedOnDate = fromApiJsonHelper.extractLocalDateNamed("approvedOnDate", element);
final LocalDate rejectedOnDate = fromApiJsonHelper.extractLocalDateNamed("rejectedOnDate", element);
final LocalDate withdrawnOnDate = fromApiJsonHelper.extractLocalDateNamed("withdrawnOnDate", element);
final LocalDate disbursedOnDate = fromApiJsonHelper.extractLocalDateNamed("disbursedOnDate", element);
return new LoanStateTransitionCommand(eventDate, note, approvedOnDate, rejectedOnDate, withdrawnOnDate, disbursedOnDate);
}
}
@@ -15,9 +15,7 @@ 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.LoanStateTransitionCommand;
import org.mifosplatform.portfolio.loanaccount.command.LoanUpdateCommand;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@@ -25,10 +23,6 @@ import org.springframework.stereotype.Component;
import com.google.gson.JsonElement;
import com.google.gson.reflect.TypeToken;
/**
* Implementation of {@link FromApiJsonDeserializer} for
* {@link LoanStateTransitionCommand}'s.
*/
@Component
public final class LoanUpdateCommandFromApiJsonDeserializer extends AbstractFromApiJsonDeserializer<LoanUpdateCommand> {
@@ -11,7 +11,6 @@ import java.util.Map;
import java.util.Set;
import org.apache.commons.lang.StringUtils;
import org.joda.time.LocalDate;
import org.mifosplatform.infrastructure.codes.domain.CodeValue;
import org.mifosplatform.infrastructure.core.api.JsonCommand;
import org.mifosplatform.infrastructure.core.api.JsonQuery;
@@ -19,7 +18,6 @@ import org.mifosplatform.infrastructure.core.data.CommandProcessingResult;
import org.mifosplatform.infrastructure.core.data.CommandProcessingResultBuilder;
import org.mifosplatform.infrastructure.core.exception.PlatformDataIntegrityException;
import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper;
import org.mifosplatform.infrastructure.security.exception.NoAuthorizationException;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.mifosplatform.organisation.staff.domain.Staff;
import org.mifosplatform.portfolio.client.domain.AccountNumberGenerator;
@@ -30,7 +28,6 @@ import org.mifosplatform.portfolio.client.domain.Note;
import org.mifosplatform.portfolio.client.domain.NoteRepository;
import org.mifosplatform.portfolio.client.exception.ClientNotFoundException;
import org.mifosplatform.portfolio.fund.domain.Fund;
import org.mifosplatform.portfolio.loanaccount.command.LoanStateTransitionCommand;
import org.mifosplatform.portfolio.loanaccount.domain.DefaultLoanLifecycleStateMachine;
import org.mifosplatform.portfolio.loanaccount.domain.Loan;
import org.mifosplatform.portfolio.loanaccount.domain.LoanCharge;
@@ -45,7 +42,7 @@ import org.mifosplatform.portfolio.loanaccount.loanschedule.data.LoanScheduleDat
import org.mifosplatform.portfolio.loanaccount.loanschedule.domain.AprCalculator;
import org.mifosplatform.portfolio.loanaccount.loanschedule.service.LoanScheduleCalculationPlatformService;
import org.mifosplatform.portfolio.loanaccount.serialization.LoanApplicationCommandFromApiJsonHelper;
import org.mifosplatform.portfolio.loanaccount.serialization.LoanStateTransitionCommandFromApiJsonDeserializer;
import org.mifosplatform.portfolio.loanaccount.serialization.LoanApplicationTransitionApiJsonValidator;
import org.mifosplatform.portfolio.loanproduct.domain.LoanProduct;
import org.mifosplatform.portfolio.loanproduct.domain.LoanProductRepository;
import org.mifosplatform.portfolio.loanproduct.domain.LoanTransactionProcessingStrategy;
@@ -67,8 +64,8 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
private final PlatformSecurityContext context;
private final FromJsonHelper fromJsonHelper;
private final LoanApplicationTransitionApiJsonValidator loanApplicationTransitionApiJsonValidator;
private final LoanApplicationCommandFromApiJsonHelper fromApiJsonDeserializer;
private final LoanStateTransitionCommandFromApiJsonDeserializer loanStateTransitionCommandFromApiJsonDeserializer;
private final LoanRepository loanRepository;
private final NoteRepository noteRepository;
private final LoanScheduleCalculationPlatformService calculationPlatformService;
@@ -82,17 +79,17 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
@Autowired
public LoanApplicationWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context, final FromJsonHelper fromJsonHelper,
final LoanApplicationCommandFromApiJsonHelper fromApiJsonDeserializer,
final LoanStateTransitionCommandFromApiJsonDeserializer loanStateTransitionCommandFromApiJsonDeserializer,
final AprCalculator aprCalculator, final LoanAssembler loanAssembler, final LoanChargeAssembler loanChargeAssembler,
final LoanApplicationTransitionApiJsonValidator loanApplicationTransitionApiJsonValidator,
final LoanApplicationCommandFromApiJsonHelper fromApiJsonDeserializer, final AprCalculator aprCalculator,
final LoanAssembler loanAssembler, final LoanChargeAssembler loanChargeAssembler,
final LoanCollateralAssembler loanCollateralAssembler, final LoanRepository loanRepository,
final NoteRepository noteRepository, final LoanScheduleCalculationPlatformService calculationPlatformService,
final ClientRepository clientRepository, final LoanProductRepository loanProductRepository,
final AccountNumberGeneratorFactory accountIdentifierGeneratorFactory) {
this.context = context;
this.fromJsonHelper = fromJsonHelper;
this.loanApplicationTransitionApiJsonValidator = loanApplicationTransitionApiJsonValidator;
this.fromApiJsonDeserializer = fromApiJsonDeserializer;
this.loanStateTransitionCommandFromApiJsonDeserializer = loanStateTransitionCommandFromApiJsonDeserializer;
this.aprCalculator = aprCalculator;
this.loanAssembler = loanAssembler;
this.loanChargeAssembler = loanChargeAssembler;
@@ -105,10 +102,6 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
this.accountIdentifierGeneratorFactory = accountIdentifierGeneratorFactory;
}
private boolean isBeforeToday(final LocalDate date) {
return date.isBefore(new LocalDate());
}
private LoanLifecycleStateMachine defaultLoanLifecycleStateMachine() {
List<LoanStatus> allowedLoanStatuses = Arrays.asList(LoanStatus.values());
return new DefaultLoanLifecycleStateMachine(allowedLoanStatuses);
@@ -319,16 +312,10 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
final AppUser currentUser = context.authenticatedUser();
final LoanStateTransitionCommand approveLoanApplication = this.loanStateTransitionCommandFromApiJsonDeserializer
.commandFromApiJson(command.json());
approveLoanApplication.validate();
this.loanApplicationTransitionApiJsonValidator.validateApproval(command.json());
final Loan loan = retrieveLoanBy(loanId);
final LocalDate approvedOnLocalDate = approveLoanApplication.getApprovedOnDate();
if (this.isBeforeToday(approvedOnLocalDate) && currentUser.canNotApproveLoanInPast()) { throw new NoAuthorizationException(
"User has no authority to approve loan with a date in the past."); }
final Map<String, Object> changes = loan.loanApplicationApproval(currentUser, command, defaultLoanLifecycleStateMachine());
if (!changes.isEmpty()) {
this.loanRepository.save(loan);
@@ -358,6 +345,8 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
context.authenticatedUser();
this.fromApiJsonDeserializer.validateForUndo(command.json());
final Loan loan = retrieveLoanBy(loanId);
final Map<String, Object> changes = loan.undoApproval(defaultLoanLifecycleStateMachine());
@@ -388,16 +377,10 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
final AppUser currentUser = context.authenticatedUser();
final LoanStateTransitionCommand rejectLoanApplication = this.loanStateTransitionCommandFromApiJsonDeserializer
.commandFromApiJson(command.json());
rejectLoanApplication.validate();
this.loanApplicationTransitionApiJsonValidator.validateRejection(command.json());
final Loan loan = retrieveLoanBy(loanId);
final LocalDate eventDate = rejectLoanApplication.getRejectedOnDate();
if (this.isBeforeToday(eventDate) && currentUser.canNotRejectLoanInPast()) { throw new NoAuthorizationException(
"User has no authority to reject loan with a date in the past."); }
final Map<String, Object> changes = loan.loanApplicationRejection(currentUser, command, defaultLoanLifecycleStateMachine());
if (!changes.isEmpty()) {
this.loanRepository.save(loan);
@@ -426,16 +409,10 @@ public class LoanApplicationWritePlatformServiceJpaRepositoryImpl implements Loa
final AppUser currentUser = context.authenticatedUser();
final LoanStateTransitionCommand applicantWithdrawsFromLoanApplication = this.loanStateTransitionCommandFromApiJsonDeserializer
.commandFromApiJson(command.json());
applicantWithdrawsFromLoanApplication.validate();
this.loanApplicationTransitionApiJsonValidator.validateApplicantWithdrawal(command.json());
final Loan loan = retrieveLoanBy(loanId);
final LocalDate eventDate = applicantWithdrawsFromLoanApplication.getWithdrawnOnDate();
if (this.isBeforeToday(eventDate) && currentUser.canNotWithdrawByClientLoanInPast()) { throw new NoAuthorizationException(
"User has no authority to mark loan as withdrawn by applicant with a date in the past."); }
final Map<String, Object> changes = loan.loanApplicationWithdrawnByApplicant(currentUser, command,
defaultLoanLifecycleStateMachine());
if (!changes.isEmpty()) {
@@ -10,12 +10,26 @@ import java.util.Map;
public enum AccountingRuleType {
NONE(1, "accountingRuleType.none"), CASH_BASED(2, "accountingRuleType.cash"), ACCRUAL_BASED(3, "accountingRuleType.accrual");
NONE(1, "accountingRuleType.none"), //
CASH_BASED(2, "accountingRuleType.cash"), //
ACCRUAL_BASED(3, "accountingRuleType.accrual");
private final Integer value;
private final String code;
private AccountingRuleType(final Integer value, String code) {
private static final Map<Integer, AccountingRuleType> intToEnumMap = new HashMap<Integer, AccountingRuleType>();
static {
for (AccountingRuleType type : AccountingRuleType.values()) {
intToEnumMap.put(type.value, type);
}
}
public static AccountingRuleType fromInt(final Integer ruleTypeValue) {
AccountingRuleType type = intToEnumMap.get(ruleTypeValue);
return type;
}
private AccountingRuleType(final Integer value, final String code) {
this.value = value;
this.code = code;
}
@@ -32,17 +46,4 @@ public enum AccountingRuleType {
public String getCode() {
return this.code;
}
private static final Map<Integer, AccountingRuleType> intToEnumMap = new HashMap<Integer, AccountingRuleType>();
static {
for (AccountingRuleType type : AccountingRuleType.values()) {
intToEnumMap.put(type.value, type);
}
}
public static AccountingRuleType fromInt(int i) {
AccountingRuleType type = intToEnumMap.get(Integer.valueOf(i));
return type;
}
}
}
@@ -64,7 +64,7 @@ public class LoanProduct extends AbstractPersistable<Long> {
private final LoanProductRelatedDetail loanProductRelatedDetail;
@Column(name = "accounting_type", nullable = false)
private Integer accountingType;
private Integer accountingRule;
public static LoanProduct assembleFromJson(final Fund fund, final LoanTransactionProcessingStrategy loanTransactionProcessingStrategy,
final Set<Charge> productCharges, final JsonCommand command, final AprCalculator aprCalculator) {
@@ -91,7 +91,7 @@ public class LoanProduct extends AbstractPersistable<Long> {
final Integer repaymentEvery = command.integerValueOfParameterNamed("repaymentEvery");
final Integer numberOfRepayments = command.integerValueOfParameterNamed("numberOfRepayments");
final BigDecimal inArrearsTolerance = command.bigDecimalValueOfParameterNamed("inArrearsTolerance");
final AccountingRuleType accountingRuleType = AccountingRuleType.fromInt(command.integerValueOfParameterNamed("accountingType"));
final AccountingRuleType accountingRuleType = AccountingRuleType.fromInt(command.integerValueOfParameterNamed("accountingRule"));
return new LoanProduct(fund, loanTransactionProcessingStrategy, name, description, currency, principal, interestRatePerPeriod,
interestFrequencyType, annualInterestRate, interestMethod, interestCalculationPeriodMethod, repaymentEvery,
@@ -128,7 +128,7 @@ public class LoanProduct extends AbstractPersistable<Long> {
repaymentFrequencyType, defaultNumberOfInstallments, amortizationMethod, inArrearsTolerance);
if (accountingRuleType != null) {
this.accountingType = accountingRuleType.getValue();
this.accountingRule = accountingRuleType.getValue();
}
}
@@ -153,7 +153,7 @@ public class LoanProduct extends AbstractPersistable<Long> {
}
public Integer getAccountingType() {
return this.accountingType;
return this.accountingRule;
}
public Map<String, Object> update(final JsonCommand command, final AprCalculator aprCalculator) {
@@ -161,10 +161,10 @@ public class LoanProduct extends AbstractPersistable<Long> {
final Map<String, Object> actualChanges = this.loanProductRelatedDetail.update(command, aprCalculator);
final String accountingTypeParamName = "accountingRule";
if (command.isChangeInIntegerParameterNamed(accountingTypeParamName, this.accountingType)) {
if (command.isChangeInIntegerParameterNamed(accountingTypeParamName, this.accountingRule)) {
final Integer newValue = command.integerValueOfParameterNamed(accountingTypeParamName);
actualChanges.put(accountingTypeParamName, newValue);
this.accountingType = newValue;
this.accountingRule = newValue;
}
final String nameParamName = "name";
@@ -223,14 +223,14 @@ public class LoanProduct extends AbstractPersistable<Long> {
}
public boolean isAccountingEnabled() {
return !AccountingRuleType.NONE.getValue().equals(this.accountingType);
return !AccountingRuleType.NONE.getValue().equals(this.accountingRule);
}
public boolean isCashBasedAccountingEnabled() {
return AccountingRuleType.CASH_BASED.getValue().equals(this.accountingType);
return AccountingRuleType.CASH_BASED.getValue().equals(this.accountingRule);
}
public boolean isAccrualBasedAccountingEnabled() {
return AccountingRuleType.ACCRUAL_BASED.getValue().equals(this.accountingType);
return AccountingRuleType.ACCRUAL_BASED.getValue().equals(this.accountingRule);
}
}