From 82ebfea45f7e65780e7208d6d3176602ec5e7843 Mon Sep 17 00:00:00 2001 From: Madhukar Date: Mon, 17 Sep 2012 19:38:57 +0530 Subject: [PATCH] Withdraw for deposit account --- .../api/DepositAccountsApiResource.java | 3 - .../ApiDataConversionServiceImpl.java | 2 +- .../DepositAccountReopenException.java | 11 +++ .../saving/domain/DepositAccount.java | 72 ++++++++++--------- .../saving/domain/DepositAccountEvent.java | 2 +- .../saving/domain/DepositAccountStatus.java | 12 +++- .../DepositLifecycleStateMachineImpl.java | 10 +++ .../service/DepositAccountAssembler.java | 4 ++ .../service/DepositAccountEnumerations.java | 3 + ...WritePlatformServiceJpaRepositoryImpl.java | 15 ++-- 10 files changed, 91 insertions(+), 43 deletions(-) create mode 100644 mifosng-provider/src/main/java/org/mifosng/platform/exceptions/DepositAccountReopenException.java diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/DepositAccountsApiResource.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/DepositAccountsApiResource.java index a3686e4b4..92fcfb05e 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/DepositAccountsApiResource.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/DepositAccountsApiResource.java @@ -209,9 +209,6 @@ public class DepositAccountsApiResource { } else if (is(commandParam, "withdrewbyclient")) { EntityIdentifier identifier = this.depositAccountWritePlatformService.withdrawDepositApplication(command); response = Response.ok().entity(identifier).build(); - /*} else if (is(commandParam, "withdrawal")){ - EntityIdentifier identifier = this.depositAccountWritePlatformService.matureDepositApplication(command); - response = Response.ok().entity(identifier).build();*/ } UndoStateTransitionCommand undoCommand = new UndoStateTransitionCommand(accountId, command.getNote()); diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/ApiDataConversionServiceImpl.java b/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/ApiDataConversionServiceImpl.java index 94b383f13..bbc489b23 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/ApiDataConversionServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/api/infrastructure/ApiDataConversionServiceImpl.java @@ -1156,7 +1156,7 @@ public class ApiDataConversionServiceImpl implements ApiDataConversionService { Type typeOfMap = new TypeToken>(){}.getType(); Map requestMap = gsonConverter.fromJson(json, typeOfMap); - Set supportedParams = new HashSet(Arrays.asList("renewAccount","deposit", "note")); + Set supportedParams = new HashSet(Arrays.asList("renewAccount","deposit", "note","locale")); checkForUnsupportedParameters(requestMap, supportedParams); diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/exceptions/DepositAccountReopenException.java b/mifosng-provider/src/main/java/org/mifosng/platform/exceptions/DepositAccountReopenException.java new file mode 100644 index 000000000..680531524 --- /dev/null +++ b/mifosng-provider/src/main/java/org/mifosng/platform/exceptions/DepositAccountReopenException.java @@ -0,0 +1,11 @@ +package org.mifosng.platform.exceptions; + +import org.joda.time.LocalDate; + +public class DepositAccountReopenException extends AbstractPlatformResourceNotFoundException{ + + public DepositAccountReopenException(LocalDate maturedDate) { + super("error.msg.depositaccount.cannot.reopen.before.mature", "You cannot renew the account that is not matured:"+maturedDate); + } + +} diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/saving/domain/DepositAccount.java b/mifosng-provider/src/main/java/org/mifosng/platform/saving/domain/DepositAccount.java index 1c64337d5..d9c7097b3 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/saving/domain/DepositAccount.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/saving/domain/DepositAccount.java @@ -23,6 +23,7 @@ import org.apache.commons.lang.StringUtils; import org.hibernate.annotations.LazyCollection; import org.hibernate.annotations.LazyCollectionOption; import org.joda.time.LocalDate; +import org.joda.time.Months; import org.mifosng.platform.api.commands.DepositStateTransitionApprovalCommand; import org.mifosng.platform.client.domain.Client; import org.mifosng.platform.currency.domain.MonetaryCurrency; @@ -304,6 +305,10 @@ public class DepositAccount extends AbstractAuditableCustom { return projectedTotalOnMaturity; } + public BigDecimal getTotal() { + return total; + } + public void reject(final LocalDate rejectedOn, final DepositLifecycleStateMachine depositLifecycleStateMachine) { @@ -474,46 +479,49 @@ public class DepositAccount extends AbstractAuditableCustom { public void withdrawDepositAccountMoney(boolean renewAccount, DepositLifecycleStateMachine depositLifecycleStateMachine) { if (new LocalDate().isAfter(maturesOnDate()) || new LocalDate().equals(maturesOnDate())) { - DepositAccountStatus statusEnum = depositLifecycleStateMachine.transition( - DepositAccountEvent.DEPOSIT_MATURED, - DepositAccountStatus.fromInt(this.depositStatus)); + + DepositAccountStatus statusEnum = depositLifecycleStateMachine.transition(DepositAccountEvent.DEPOSIT_MATURED, DepositAccountStatus.fromInt(this.depositStatus)); this.depositStatus = statusEnum.getValue(); - if(!renewAccount){ - DepositAccountTransaction depositaccountTransaction = DepositAccountTransaction.withdraw(Money.of(this.currency, this.total), new LocalDate()); - depositaccountTransaction.updateAccount(this); - this.depositaccountTransactions.add(depositaccountTransaction); + DepositAccountTransaction depositaccountTransaction = DepositAccountTransaction.withdraw(Money.of(this.currency, this.total), new LocalDate()); + depositaccountTransaction.updateAccount(this); + this.depositaccountTransactions.add(depositaccountTransaction); - DepositAccountStatus statusEnumForClose = depositLifecycleStateMachine.transition( - DepositAccountEvent.DEPOSIT_CLOSED, - DepositAccountStatus.fromInt(this.depositStatus)); - this.depositStatus = statusEnumForClose.getValue(); + DepositAccountStatus statusEnumForClose = depositLifecycleStateMachine.transition(DepositAccountEvent.DEPOSIT_CLOSED, DepositAccountStatus.fromInt(this.depositStatus)); + this.depositStatus = statusEnumForClose.getValue(); - this.depositAmount = null; - this.interestRate = null; - this.tenureInMonths = null; - this.interestCompoundedEvery = null; - this.interestCompoundedFrequencyType = null; - this.closedOnDate = new LocalDate().toDate(); - this.withdrawnOnDate = null; - this.rejectedOnDate = null; + this.closedOnDate = new LocalDate().toDate(); + this.withdrawnOnDate = null; + this.rejectedOnDate = null; - }else if(renewAccount){ - DepositAccountStatus statusEnumForClose = depositLifecycleStateMachine.transition( - DepositAccountEvent.DEPOSIT_CLOSED, - DepositAccountStatus.fromInt(this.depositStatus)); - this.depositStatus = statusEnumForClose.getValue(); + }else if(new LocalDate().isBefore(maturesOnDate())){ + + DepositAccountStatus statusEnum = depositLifecycleStateMachine.transition(DepositAccountEvent.DEPOSIT_PRECLOSED, DepositAccountStatus.fromInt(this.depositStatus)); + this.depositStatus = statusEnum.getValue(); + + DepositAccountTransaction depositaccountTransaction = DepositAccountTransaction.withdraw(Money.of(this.currency, this.total), new LocalDate()); + depositaccountTransaction.updateAccount(this); + this.depositaccountTransactions.add(depositaccountTransaction); - DepositAccountTransaction depositaccountTransaction = DepositAccountTransaction.withdraw(Money.of(this.currency, this.total), new LocalDate()); - depositaccountTransaction.updateAccount(this); - this.depositaccountTransactions.add(depositaccountTransaction); - - this.closedOnDate = new LocalDate().toDate(); - this.withdrawnOnDate = null; - this.rejectedOnDate = null; - } + this.closedOnDate = new LocalDate().toDate(); + this.withdrawnOnDate = null; + this.rejectedOnDate = null; + } + } + + public void adjustTotalAmountForPreclosureInterest(DepositAccount account, FixedTermDepositInterestCalculator fixedTermDepositInterestCalculator) { + LocalDate commnencementDate = new LocalDate(this.actualCommencementDate); + LocalDate preClosedDate = new LocalDate(); + + Integer tenure = Months.monthsBetween(commnencementDate, preClosedDate).getMonths(); + + Money deposit = Money.of(account.getDeposit().getCurrency(), account.getDeposit().getAmount()); + Money accuredtotalAmount = fixedTermDepositInterestCalculator.calculateInterestOnMaturityFor(deposit, tenure, + preClosureInterestRate, interestCompoundedEvery, this.product.getInterestCompoundedEveryPeriodType()); + + this.total = accuredtotalAmount.getAmount(); } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/saving/domain/DepositAccountEvent.java b/mifosng-provider/src/main/java/org/mifosng/platform/saving/domain/DepositAccountEvent.java index 363c95305..8a6209c83 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/saving/domain/DepositAccountEvent.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/saving/domain/DepositAccountEvent.java @@ -2,6 +2,6 @@ package org.mifosng.platform.saving.domain; public enum DepositAccountEvent { - DEPOSIT_CREATED, DEPOSIT_REJECTED, DEPOSIT_APPROVED, DEPOSIT_APPROVAL_UNDO, DEPOSIT_WITHDRAWN, DEPOSIT_MATURED, DEPOSIT_CLOSED; + DEPOSIT_CREATED, DEPOSIT_REJECTED, DEPOSIT_APPROVED, DEPOSIT_APPROVAL_UNDO, DEPOSIT_WITHDRAWN, DEPOSIT_MATURED, DEPOSIT_CLOSED, DEPOSIT_PRECLOSED; } diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/saving/domain/DepositAccountStatus.java b/mifosng-provider/src/main/java/org/mifosng/platform/saving/domain/DepositAccountStatus.java index a9c77b06b..f2cd31a95 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/saving/domain/DepositAccountStatus.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/saving/domain/DepositAccountStatus.java @@ -9,7 +9,8 @@ public enum DepositAccountStatus { WITHDRAWN_BY_CLIENT(400, "depositStatusType.withdrawn.by.client"), // REJECTED(500, "depositStatusType.rejected"), // CLOSED(600, "depositStatusType.closed"), // - MATURED(700,"depositStatusType.matured"); + MATURED(700,"depositStatusType.matured"), + PRECLOSED(800,"depositStatusType.preclosed"); private final Integer value; private final String code; @@ -55,6 +56,10 @@ public enum DepositAccountStatus { return this.value.equals(DepositAccountStatus.REJECTED.getValue()); } + public boolean isPreClosed(){ + return this.value.equals(DepositAccountStatus.PRECLOSED.getValue()); + } + public static DepositAccountStatus fromInt(final Integer statusValue) { DepositAccountStatus enumeration = DepositAccountStatus.INVALID; @@ -80,7 +85,10 @@ public enum DepositAccountStatus { case 700: enumeration = DepositAccountStatus.MATURED; break; - } + case 800: + enumeration = DepositAccountStatus.PRECLOSED; + break; + } return enumeration; } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/saving/domain/DepositLifecycleStateMachineImpl.java b/mifosng-provider/src/main/java/org/mifosng/platform/saving/domain/DepositLifecycleStateMachineImpl.java index f4e480eae..5a0f68226 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/saving/domain/DepositLifecycleStateMachineImpl.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/saving/domain/DepositLifecycleStateMachineImpl.java @@ -78,8 +78,18 @@ public class DepositLifecycleStateMachineImpl implements throw new InvalidDepositStateTransitionException("closed", "failed", errorMessage,from); } break; + case DEPOSIT_PRECLOSED: + if (from.hasStateOf(DepositAccountStatus.APPROVED) ){ + newState = stateOf(DepositAccountStatus.PRECLOSED, allowedDepositStatuses); + } + else{ + final String errorMessage = "The DepositApplication can not be matured from "+from.getCode() ; + throw new InvalidDepositStateTransitionException("preclosure", "failed", errorMessage,from); + } + break; default: break; + } return newState; diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/saving/service/DepositAccountAssembler.java b/mifosng-provider/src/main/java/org/mifosng/platform/saving/service/DepositAccountAssembler.java index 2d5fd9450..6231f15a2 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/saving/service/DepositAccountAssembler.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/saving/service/DepositAccountAssembler.java @@ -147,4 +147,8 @@ public class DepositAccountAssembler { return newAccount; } + + public void adjustTotalAmountForPreclosureInterest(DepositAccount account) { + account.adjustTotalAmountForPreclosureInterest(account,this.fixedTermDepositInterestCalculator); + } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/saving/service/DepositAccountEnumerations.java b/mifosng-provider/src/main/java/org/mifosng/platform/saving/service/DepositAccountEnumerations.java index f2c387970..1798ddb81 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/saving/service/DepositAccountEnumerations.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/saving/service/DepositAccountEnumerations.java @@ -33,6 +33,9 @@ public class DepositAccountEnumerations { case CLOSED: optionData = new EnumOptionData(DepositAccountStatus.CLOSED.getValue().longValue(), DepositAccountStatus.CLOSED.getCode(), "Closed"); break; + case PRECLOSED: + optionData = new EnumOptionData(DepositAccountStatus.PRECLOSED.getValue().longValue(), DepositAccountStatus.PRECLOSED.getCode(), "Preclosed"); + break; default: optionData = new EnumOptionData(DepositAccountStatus.INVALID.getValue().longValue(), DepositAccountStatus.INVALID.getCode(), "Invalid"); break; diff --git a/mifosng-provider/src/main/java/org/mifosng/platform/saving/service/DepositAccountWritePlatformServiceJpaRepositoryImpl.java b/mifosng-provider/src/main/java/org/mifosng/platform/saving/service/DepositAccountWritePlatformServiceJpaRepositoryImpl.java index 1c3efdea2..705a88585 100644 --- a/mifosng-provider/src/main/java/org/mifosng/platform/saving/service/DepositAccountWritePlatformServiceJpaRepositoryImpl.java +++ b/mifosng-provider/src/main/java/org/mifosng/platform/saving/service/DepositAccountWritePlatformServiceJpaRepositoryImpl.java @@ -15,6 +15,7 @@ import org.mifosng.platform.api.data.EntityIdentifier; import org.mifosng.platform.client.domain.Note; import org.mifosng.platform.client.domain.NoteRepository; import org.mifosng.platform.exceptions.DepositAccountNotFoundException; +import org.mifosng.platform.exceptions.DepositAccountReopenException; import org.mifosng.platform.exceptions.NoAuthorizationException; import org.mifosng.platform.exceptions.PlatformDataIntegrityException; import org.mifosng.platform.exceptions.ProductNotFoundException; @@ -285,14 +286,20 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo throw new DepositAccountNotFoundException(command.getAccountId()); } + if(new LocalDate().isBefore(account.maturesOnDate())){ + this.depositAccountAssembler.adjustTotalAmountForPreclosureInterest(account); + } account.withdrawDepositAccountMoney(command.isRenewAccount(), defaultDepositLifecycleStateMachine()); this.depositAccountRepository.save(account); - BigDecimal deposit = account.getProjectedTotalOnMaturity(); - if(command.getDeposit() != null) - deposit = command.getDeposit(); - if(command.isRenewAccount()){ + + BigDecimal deposit = account.getTotal(); + if(command.getDeposit() != null) + deposit = command.getDeposit(); + if(new LocalDate().isBefore(account.maturesOnDate())){ + throw new DepositAccountReopenException(account.maturesOnDate()); + } final DepositAccount renewedAccount = this.depositAccountAssembler.assembleFrom(account,deposit); this.depositAccountRepository.save(renewedAccount); return new EntityIdentifier(renewedAccount.getId()); //returns the new deposit application id