From 190b9a58b3057c4f65ec2b995807288017f056b9 Mon Sep 17 00:00:00 2001 From: Vishwas Babu A J Date: Tue, 10 Sep 2013 17:13:53 +0530 Subject: [PATCH] wip:enabling transfer of saving accounts --- .../common/AccountingConstants.java | 5 +- ...ashBasedAccountingProcessorForSavings.java | 15 +++ ...AccountMappingFromApiJsonDeserializer.java | 5 + ...AccountMappingReadPlatformServiceImpl.java | 2 + ...ccountMappingWritePlatformServiceImpl.java | 3 + ...avingsProductToGLAccountMappingHelper.java | 6 ++ .../loanaccount/domain/LoanStatus.java | 8 +- .../loanaccount/domain/LoanTransaction.java | 2 +- .../loanproduct/service/LoanEnumerations.java | 2 +- .../SavingsAccountTransactionType.java | 18 +++- .../savings/SavingsApiConstants.java | 3 +- .../data/SavingsAccountStatusEnumData.java | 9 +- .../SavingsAccountTransactionEnumData.java | 24 +++++ .../data/SavingsProductDataValidator.java | 32 ++++-- .../savings/domain/SavingsAccount.java | 17 +++- .../domain/SavingsAccountStatusType.java | 20 ++++ .../savings/domain/SavingsAccountSummary.java | 5 + .../domain/SavingsAccountTransaction.java | 31 +++++- .../SavingsAccountWritePlatformService.java | 13 ++- ...WritePlatformServiceJpaRepositoryImpl.java | 97 ++++++++++++++++--- .../savings/service/SavingsEnumerations.java | 31 ++++-- ...WritePlatformServiceJpaRepositoryImpl.java | 33 ++++++- 22 files changed, 333 insertions(+), 48 deletions(-) diff --git a/mifosng-provider/src/main/java/org/mifosplatform/accounting/common/AccountingConstants.java b/mifosng-provider/src/main/java/org/mifosplatform/accounting/common/AccountingConstants.java index c6afeccab..1ccaabab3 100755 --- a/mifosng-provider/src/main/java/org/mifosplatform/accounting/common/AccountingConstants.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/accounting/common/AccountingConstants.java @@ -108,7 +108,7 @@ public class AccountingConstants { /*** Accounting placeholders for cash based accounting for savings products ***/ public static enum CASH_ACCOUNTS_FOR_SAVINGS { - SAVINGS_REFERENCE(1), SAVINGS_CONTROL(2), INTEREST_ON_SAVINGS(3), INCOME_FROM_FEES(4); + SAVINGS_REFERENCE(1), SAVINGS_CONTROL(2), INTEREST_ON_SAVINGS(3), INCOME_FROM_FEES(4), TRANSFERS_SUSPENSE(10); private final Integer value; @@ -145,7 +145,8 @@ public class AccountingConstants { public static enum SAVINGS_PRODUCT_ACCOUNTING_PARAMS { SAVINGS_REFERENCE("savingsReferenceAccountId"), SAVINGS_CONTROL("savingsControlAccountId"), INCOME_FROM_FEES( "incomeFromFeeAccountId"), INTEREST_ON_SAVINGS("interestOnSavingsAccountId"), PAYMENT_CHANNEL_FUND_SOURCE_MAPPING( - "paymentChannelToFundSourceMappings"), PAYMENT_TYPE("paymentTypeId"), FUND_SOURCE("fundSourceAccountId"); + "paymentChannelToFundSourceMappings"), PAYMENT_TYPE("paymentTypeId"), FUND_SOURCE("fundSourceAccountId"), TRANSFERS_SUSPENSE( + "transfersInSuspenseAccountId"); private final String value; diff --git a/mifosng-provider/src/main/java/org/mifosplatform/accounting/journalentry/service/CashBasedAccountingProcessorForSavings.java b/mifosng-provider/src/main/java/org/mifosplatform/accounting/journalentry/service/CashBasedAccountingProcessorForSavings.java index 7a57c9751..35cc08a21 100755 --- a/mifosng-provider/src/main/java/org/mifosplatform/accounting/journalentry/service/CashBasedAccountingProcessorForSavings.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/accounting/journalentry/service/CashBasedAccountingProcessorForSavings.java @@ -72,6 +72,21 @@ public class CashBasedAccountingProcessorForSavings implements AccountingProcess transactionDate, amount, isReversal); } + /** Handle Transfers proposal **/ + else if (savingsTransactionDTO.getTransactionType().isInitiateTransfer()) { + helper.createCashBasedJournalEntriesAndReversalsForSavings(office, CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_CONTROL, + CASH_ACCOUNTS_FOR_SAVINGS.TRANSFERS_SUSPENSE, savingsProductId, paymentTypeId, savingsId, transactionId, + transactionDate, amount, isReversal); + } + + /** Handle Transfer Withdrawal or Acceptance **/ + else if (savingsTransactionDTO.getTransactionType().isWithdrawTransfer() + || savingsTransactionDTO.getTransactionType().isApproveTransfer()) { + helper.createCashBasedJournalEntriesAndReversalsForSavings(office, CASH_ACCOUNTS_FOR_SAVINGS.TRANSFERS_SUSPENSE, + CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_CONTROL, savingsProductId, paymentTypeId, savingsId, transactionId, + transactionDate, amount, isReversal); + } + } } } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/accounting/producttoaccountmapping/serialization/ProductToGLAccountMappingFromApiJsonDeserializer.java b/mifosng-provider/src/main/java/org/mifosplatform/accounting/producttoaccountmapping/serialization/ProductToGLAccountMappingFromApiJsonDeserializer.java index e44557141..669d661af 100755 --- a/mifosng-provider/src/main/java/org/mifosplatform/accounting/producttoaccountmapping/serialization/ProductToGLAccountMappingFromApiJsonDeserializer.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/accounting/producttoaccountmapping/serialization/ProductToGLAccountMappingFromApiJsonDeserializer.java @@ -156,6 +156,11 @@ public final class ProductToGLAccountMappingFromApiJsonDeserializer { baseDataValidator.reset().parameter(SAVINGS_PRODUCT_ACCOUNTING_PARAMS.SAVINGS_REFERENCE.getValue()) .value(savingsReferenceAccountId).notNull().integerGreaterThanZero(); + final Long transfersInSuspenseAccountId = fromApiJsonHelper.extractLongNamed( + SAVINGS_PRODUCT_ACCOUNTING_PARAMS.TRANSFERS_SUSPENSE.getValue(), element); + baseDataValidator.reset().parameter(SAVINGS_PRODUCT_ACCOUNTING_PARAMS.TRANSFERS_SUSPENSE.getValue()) + .value(transfersInSuspenseAccountId).notNull().integerGreaterThanZero(); + final Long interestOnSavingsAccountId = fromApiJsonHelper.extractLongNamed( SAVINGS_PRODUCT_ACCOUNTING_PARAMS.INTEREST_ON_SAVINGS.getValue(), element); baseDataValidator.reset().parameter(SAVINGS_PRODUCT_ACCOUNTING_PARAMS.INTEREST_ON_SAVINGS.getValue()) diff --git a/mifosng-provider/src/main/java/org/mifosplatform/accounting/producttoaccountmapping/service/ProductToGLAccountMappingReadPlatformServiceImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/accounting/producttoaccountmapping/service/ProductToGLAccountMappingReadPlatformServiceImpl.java index 392538403..d6db8dea2 100755 --- a/mifosng-provider/src/main/java/org/mifosplatform/accounting/producttoaccountmapping/service/ProductToGLAccountMappingReadPlatformServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/accounting/producttoaccountmapping/service/ProductToGLAccountMappingReadPlatformServiceImpl.java @@ -169,6 +169,8 @@ public class ProductToGLAccountMappingReadPlatformServiceImpl implements Product accountMappingDetails.put(SAVINGS_PRODUCT_ACCOUNTING_PARAMS.SAVINGS_CONTROL.getValue(), glAccountId); } else if (glAccountForSavings.equals(CASH_ACCOUNTS_FOR_SAVINGS.INCOME_FROM_FEES)) { accountMappingDetails.put(SAVINGS_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_FEES.getValue(), glAccountId); + } else if (glAccountForSavings.equals(CASH_ACCOUNTS_FOR_SAVINGS.TRANSFERS_SUSPENSE)) { + accountMappingDetails.put(SAVINGS_PRODUCT_ACCOUNTING_PARAMS.TRANSFERS_SUSPENSE.getValue(), glAccountId); } else if (glAccountForSavings.equals(CASH_ACCOUNTS_FOR_SAVINGS.INTEREST_ON_SAVINGS)) { accountMappingDetails.put(SAVINGS_PRODUCT_ACCOUNTING_PARAMS.INTEREST_ON_SAVINGS.getValue(), glAccountId); } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/accounting/producttoaccountmapping/service/ProductToGLAccountMappingWritePlatformServiceImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/accounting/producttoaccountmapping/service/ProductToGLAccountMappingWritePlatformServiceImpl.java index 840758ee2..5a8e18e8f 100755 --- a/mifosng-provider/src/main/java/org/mifosplatform/accounting/producttoaccountmapping/service/ProductToGLAccountMappingWritePlatformServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/accounting/producttoaccountmapping/service/ProductToGLAccountMappingWritePlatformServiceImpl.java @@ -163,6 +163,9 @@ public class ProductToGLAccountMappingWritePlatformServiceImpl implements Produc savingsProductToGLAccountMappingHelper.saveSavingsToLiabilityAccountMapping(element, SAVINGS_PRODUCT_ACCOUNTING_PARAMS.SAVINGS_CONTROL.getValue(), savingProductId, CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_CONTROL.getValue()); + savingsProductToGLAccountMappingHelper.saveSavingsToLiabilityAccountMapping(element, + SAVINGS_PRODUCT_ACCOUNTING_PARAMS.TRANSFERS_SUSPENSE.getValue(), savingProductId, + CASH_ACCOUNTS_FOR_SAVINGS.TRANSFERS_SUSPENSE.getValue()); // advanced accounting mappings savingsProductToGLAccountMappingHelper.savePaymentChannelToFundSourceMappings(command, element, savingProductId, null); diff --git a/mifosng-provider/src/main/java/org/mifosplatform/accounting/producttoaccountmapping/service/SavingsProductToGLAccountMappingHelper.java b/mifosng-provider/src/main/java/org/mifosplatform/accounting/producttoaccountmapping/service/SavingsProductToGLAccountMappingHelper.java index 9416c3f5c..1b5d41353 100755 --- a/mifosng-provider/src/main/java/org/mifosplatform/accounting/producttoaccountmapping/service/SavingsProductToGLAccountMappingHelper.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/accounting/producttoaccountmapping/service/SavingsProductToGLAccountMappingHelper.java @@ -106,6 +106,8 @@ public class SavingsProductToGLAccountMappingHelper extends ProductToGLAccountMa SAVINGS_PRODUCT_ACCOUNTING_PARAMS.INTEREST_ON_SAVINGS.getValue(), element); final Long savingsControlId = this.fromApiJsonHelper.extractLongNamed(SAVINGS_PRODUCT_ACCOUNTING_PARAMS.SAVINGS_CONTROL.getValue(), element); + final Long transfersInSuspenseAccountId = this.fromApiJsonHelper.extractLongNamed( + SAVINGS_PRODUCT_ACCOUNTING_PARAMS.TRANSFERS_SUSPENSE.getValue(), element); switch (accountingRuleType) { case NONE: @@ -115,6 +117,7 @@ public class SavingsProductToGLAccountMappingHelper extends ProductToGLAccountMa changes.put(SAVINGS_PRODUCT_ACCOUNTING_PARAMS.SAVINGS_REFERENCE.getValue(), savingsReferenceId); changes.put(SAVINGS_PRODUCT_ACCOUNTING_PARAMS.INTEREST_ON_SAVINGS.getValue(), interestOnSavingsId); changes.put(SAVINGS_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_FEES.getValue(), incomeFromFeesId); + changes.put(SAVINGS_PRODUCT_ACCOUNTING_PARAMS.TRANSFERS_SUSPENSE.getValue(), transfersInSuspenseAccountId); break; case ACCRUAL_BASED: break; @@ -156,6 +159,9 @@ public class SavingsProductToGLAccountMappingHelper extends ProductToGLAccountMa mergeSavingsToLiabilityAccountMappingChanges(element, SAVINGS_PRODUCT_ACCOUNTING_PARAMS.SAVINGS_CONTROL.getValue(), savingsProductId, CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_CONTROL.getValue(), CASH_ACCOUNTS_FOR_SAVINGS.SAVINGS_CONTROL.toString(), changes); + mergeSavingsToLiabilityAccountMappingChanges(element, SAVINGS_PRODUCT_ACCOUNTING_PARAMS.TRANSFERS_SUSPENSE.getValue(), + savingsProductId, CASH_ACCOUNTS_FOR_SAVINGS.TRANSFERS_SUSPENSE.getValue(), + CASH_ACCOUNTS_FOR_SAVINGS.TRANSFERS_SUSPENSE.toString(), changes); break; case ACCRUAL_BASED: break; diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/LoanStatus.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/LoanStatus.java index e4633a2b0..74c852e91 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/LoanStatus.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/LoanStatus.java @@ -125,18 +125,18 @@ public enum LoanStatus { } public boolean isTransferInProgress() { - return this.isTransferInProgress(); + return this.value.equals(LoanStatus.TRANSFER_IN_PROGRESS.getValue()); } public boolean isTransferOnHold() { - return this.isTransferOnHold(); + return this.value.equals(LoanStatus.TRANSFER_ON_HOLD.getValue()); } public boolean isUnderTransfer() { return isTransferInProgress() || isTransferOnHold(); } - - public boolean isOverpaid(){ + + public boolean isOverpaid() { return this.value.equals(LoanStatus.OVERPAID.getValue()); } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/LoanTransaction.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/LoanTransaction.java index 29e7148d2..b93e54df9 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/LoanTransaction.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/LoanTransaction.java @@ -138,7 +138,7 @@ public final class LoanTransaction extends AbstractPersistable { } public static LoanTransaction withdrawTransfer(final Office office, final Loan loan, final LocalDate transferDate) { - return new LoanTransaction(loan, office, LoanTransactionType.APPROVE_TRANSFER.getValue(), transferDate.toDateMidnight().toDate(), + return new LoanTransaction(loan, office, LoanTransactionType.WITHDRAW_TRANSFER.getValue(), transferDate.toDateMidnight().toDate(), loan.getSummary().getTotalOutstanding(), loan.getSummary().getTotalPrincipalOutstanding(), loan.getSummary() .getTotalInterestOutstanding(), loan.getSummary().getTotalFeeChargesOutstanding(), loan.getSummary() .getTotalPenaltyChargesOutstanding(), false, null); diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/service/LoanEnumerations.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/service/LoanEnumerations.java index 37a2f750b..c426545ca 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/service/LoanEnumerations.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanproduct/service/LoanEnumerations.java @@ -357,7 +357,7 @@ public class LoanEnumerations { break; case TRANSFER_ON_HOLD: optionData = new LoanStatusEnumData(LoanStatus.TRANSFER_ON_HOLD.getValue().longValue(), - LoanStatus.TRANSFER_ON_HOLD.getCode(), "Transfer in hold"); + LoanStatus.TRANSFER_ON_HOLD.getCode(), "Transfer on hold"); break; default: break; diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/SavingsAccountTransactionType.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/SavingsAccountTransactionType.java index e660f11ca..6141da8de 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/SavingsAccountTransactionType.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/SavingsAccountTransactionType.java @@ -18,7 +18,11 @@ public enum SavingsAccountTransactionType { WITHDRAWAL(2, "savingsAccountTransactionType.withdrawal"), // INTEREST_POSTING(3, "savingsAccountTransactionType.interestPosting"), // WITHDRAWAL_FEE(4, "savingsAccountTransactionType.withdrawalFee"), // - ANNUAL_FEE(5, "savingsAccountTransactionType.annualFee"); + ANNUAL_FEE(5, "savingsAccountTransactionType.annualFee"), // + INITIATE_TRANSFER(12, "savingsAccountTransactionType.initiateTransfer"), // + APPROVE_TRANSFER(13, "savingsAccountTransactionType.approveTransfer"), // + WITHDRAW_TRANSFER(14, "savingsAccountTransactionType.withdrawTransfer"), // + REJECT_TRANSFER(15, "savingsAccountTransactionType.rejectTransfer"); private final Integer value; private final String code; @@ -57,6 +61,18 @@ public enum SavingsAccountTransactionType { case 5: loanTransactionType = SavingsAccountTransactionType.ANNUAL_FEE; break; + case 12: + loanTransactionType = SavingsAccountTransactionType.INITIATE_TRANSFER; + break; + case 13: + loanTransactionType = SavingsAccountTransactionType.APPROVE_TRANSFER; + break; + case 14: + loanTransactionType = SavingsAccountTransactionType.WITHDRAW_TRANSFER; + break; + case 15: + loanTransactionType = SavingsAccountTransactionType.REJECT_TRANSFER; + break; } return loanTransactionType; } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/SavingsApiConstants.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/SavingsApiConstants.java index 0e60dff4c..fea9326a2 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/SavingsApiConstants.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/SavingsApiConstants.java @@ -105,7 +105,8 @@ public class SavingsApiConstants { annualFeeOnMonthDayParamName, accountingRuleParamName, SAVINGS_PRODUCT_ACCOUNTING_PARAMS.INCOME_FROM_FEES.getValue(), SAVINGS_PRODUCT_ACCOUNTING_PARAMS.INTEREST_ON_SAVINGS.getValue(), SAVINGS_PRODUCT_ACCOUNTING_PARAMS.PAYMENT_CHANNEL_FUND_SOURCE_MAPPING.getValue(), - SAVINGS_PRODUCT_ACCOUNTING_PARAMS.SAVINGS_CONTROL.getValue(), SAVINGS_PRODUCT_ACCOUNTING_PARAMS.SAVINGS_REFERENCE.getValue())); + SAVINGS_PRODUCT_ACCOUNTING_PARAMS.SAVINGS_CONTROL.getValue(), SAVINGS_PRODUCT_ACCOUNTING_PARAMS.TRANSFERS_SUSPENSE.getValue(), + SAVINGS_PRODUCT_ACCOUNTING_PARAMS.SAVINGS_REFERENCE.getValue())); /** * These parameters will match the class level parameters of diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/SavingsAccountStatusEnumData.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/SavingsAccountStatusEnumData.java index 6318639b6..904958226 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/SavingsAccountStatusEnumData.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/SavingsAccountStatusEnumData.java @@ -27,9 +27,14 @@ public class SavingsAccountStatusEnumData { private final boolean active; @SuppressWarnings("unused") private final boolean closed; + @SuppressWarnings("unused") + private final boolean transferInProgress; + @SuppressWarnings("unused") + private final boolean transferOnHold; public SavingsAccountStatusEnumData(final Long id, final String code, final String value, final boolean submittedAndPendingApproval, - final boolean approved, final boolean rejected, final boolean withdrawnByApplicant, final boolean active, final boolean closed) { + final boolean approved, final boolean rejected, final boolean withdrawnByApplicant, final boolean active, final boolean closed, + final boolean transferInProgress, final boolean transferOnHold) { this.id = id; this.code = code; this.value = value; @@ -39,6 +44,8 @@ public class SavingsAccountStatusEnumData { this.withdrawnByApplicant = withdrawnByApplicant; this.active = active; this.closed = closed; + this.transferInProgress = transferInProgress; + this.transferOnHold = transferOnHold; } public Long id() { diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/SavingsAccountTransactionEnumData.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/SavingsAccountTransactionEnumData.java index e429031c7..f82e028e6 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/SavingsAccountTransactionEnumData.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/SavingsAccountTransactionEnumData.java @@ -22,6 +22,10 @@ public class SavingsAccountTransactionEnumData { private final boolean withdrawal; private final boolean interestPosting; private final boolean feeDeduction; + private final boolean initiateTransfer; + private final boolean approveTransfer; + private final boolean withdrawTransfer; + private final boolean rejectTransfer; public SavingsAccountTransactionEnumData(final Long id, final String code, final String value) { this.id = id; @@ -32,6 +36,10 @@ public class SavingsAccountTransactionEnumData { this.interestPosting = Long.valueOf(SavingsAccountTransactionType.INTEREST_POSTING.getValue()).equals(this.id); this.feeDeduction = Long.valueOf(SavingsAccountTransactionType.ANNUAL_FEE.getValue()).equals(this.id) || Long.valueOf(SavingsAccountTransactionType.WITHDRAWAL_FEE.getValue()).equals(this.id); + this.initiateTransfer = Long.valueOf(SavingsAccountTransactionType.INITIATE_TRANSFER.getValue()).equals(this.id); + this.approveTransfer = Long.valueOf(SavingsAccountTransactionType.APPROVE_TRANSFER.getValue()).equals(this.id); + this.withdrawTransfer = Long.valueOf(SavingsAccountTransactionType.WITHDRAW_TRANSFER.getValue()).equals(this.id); + this.rejectTransfer = Long.valueOf(SavingsAccountTransactionType.REJECT_TRANSFER.getValue()).equals(this.id); } public boolean isDeposit() { @@ -54,4 +62,20 @@ public class SavingsAccountTransactionEnumData { return this.feeDeduction; } + public boolean isInitiateTransfer() { + return this.initiateTransfer; + } + + public boolean isApproveTransfer() { + return this.approveTransfer; + } + + public boolean isWithdrawTransfer() { + return this.withdrawTransfer; + } + + public boolean isRejectTransfer() { + return this.rejectTransfer; + } + } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/SavingsProductDataValidator.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/SavingsProductDataValidator.java index f2fba572e..91420f8ab 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/SavingsProductDataValidator.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/data/SavingsProductDataValidator.java @@ -174,11 +174,12 @@ public class SavingsProductDataValidator { .zeroOrPositiveAmount(); } } - - if(this.fromApiJsonHelper.parameterExists(withdrawalFeeForTransfersParamName, element)) { - final Boolean isWithdrawalFeeApplicableForTransfers = fromApiJsonHelper.extractBooleanNamed(withdrawalFeeForTransfersParamName, element); - baseDataValidator.reset().parameter(withdrawalFeeForTransfersParamName).value(isWithdrawalFeeApplicableForTransfers).ignoreIfNull() - .validateForBooleanValue(); + + if (this.fromApiJsonHelper.parameterExists(withdrawalFeeForTransfersParamName, element)) { + final Boolean isWithdrawalFeeApplicableForTransfers = fromApiJsonHelper.extractBooleanNamed(withdrawalFeeForTransfersParamName, + element); + baseDataValidator.reset().parameter(withdrawalFeeForTransfersParamName).value(isWithdrawalFeeApplicableForTransfers) + .ignoreIfNull().validateForBooleanValue(); } if (this.fromApiJsonHelper.parameterExists(annualFeeAmountParamName, element)) { @@ -216,6 +217,11 @@ public class SavingsProductDataValidator { baseDataValidator.reset().parameter(SAVINGS_PRODUCT_ACCOUNTING_PARAMS.SAVINGS_REFERENCE.getValue()) .value(savingsReferenceAccountId).notNull().integerGreaterThanZero(); + final Long transfersInSuspenseAccountId = fromApiJsonHelper.extractLongNamed( + SAVINGS_PRODUCT_ACCOUNTING_PARAMS.TRANSFERS_SUSPENSE.getValue(), element); + baseDataValidator.reset().parameter(SAVINGS_PRODUCT_ACCOUNTING_PARAMS.TRANSFERS_SUSPENSE.getValue()) + .value(transfersInSuspenseAccountId).notNull().integerGreaterThanZero(); + final Long interestOnSavingsAccountId = fromApiJsonHelper.extractLongNamed( SAVINGS_PRODUCT_ACCOUNTING_PARAMS.INTEREST_ON_SAVINGS.getValue(), element); baseDataValidator.reset().parameter(SAVINGS_PRODUCT_ACCOUNTING_PARAMS.INTEREST_ON_SAVINGS.getValue()) @@ -326,11 +332,12 @@ public class SavingsProductDataValidator { baseDataValidator.reset().parameter(withdrawalFeeTypeParamName).value(withdrawalFeeType).ignoreIfNull() .isOneOfTheseValues(1, 2); } - - if(this.fromApiJsonHelper.parameterExists(withdrawalFeeForTransfersParamName, element)) { - final Boolean isWithdrawalFeeApplicableForTransfers = fromApiJsonHelper.extractBooleanNamed(withdrawalFeeForTransfersParamName, element); - baseDataValidator.reset().parameter(withdrawalFeeForTransfersParamName).value(isWithdrawalFeeApplicableForTransfers).ignoreIfNull() - .validateForBooleanValue(); + + if (this.fromApiJsonHelper.parameterExists(withdrawalFeeForTransfersParamName, element)) { + final Boolean isWithdrawalFeeApplicableForTransfers = fromApiJsonHelper.extractBooleanNamed(withdrawalFeeForTransfersParamName, + element); + baseDataValidator.reset().parameter(withdrawalFeeForTransfersParamName).value(isWithdrawalFeeApplicableForTransfers) + .ignoreIfNull().validateForBooleanValue(); } if (this.fromApiJsonHelper.parameterExists(annualFeeAmountParamName, element)) { @@ -353,6 +360,11 @@ public class SavingsProductDataValidator { baseDataValidator.reset().parameter(SAVINGS_PRODUCT_ACCOUNTING_PARAMS.SAVINGS_REFERENCE.getValue()) .value(savingsReferenceAccountId).ignoreIfNull().integerGreaterThanZero(); + final Long transfersInSuspenseAccountId = fromApiJsonHelper.extractLongNamed( + SAVINGS_PRODUCT_ACCOUNTING_PARAMS.TRANSFERS_SUSPENSE.getValue(), element); + baseDataValidator.reset().parameter(SAVINGS_PRODUCT_ACCOUNTING_PARAMS.TRANSFERS_SUSPENSE.getValue()) + .value(transfersInSuspenseAccountId).ignoreIfNull().integerGreaterThanZero(); + final Long interestOnSavingsAccountId = fromApiJsonHelper.extractLongNamed( SAVINGS_PRODUCT_ACCOUNTING_PARAMS.INTEREST_ON_SAVINGS.getValue(), element); baseDataValidator.reset().parameter(SAVINGS_PRODUCT_ACCOUNTING_PARAMS.INTEREST_ON_SAVINGS.getValue()) diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/SavingsAccount.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/SavingsAccount.java index 7efb73b8b..46b7239e8 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/SavingsAccount.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/SavingsAccount.java @@ -1178,7 +1178,7 @@ public class SavingsAccount extends AbstractPersistable { return accountingBridgeData; } - private Collection findExistingTransactionIds() { + public Collection findExistingTransactionIds() { final Collection ids = new ArrayList(); @@ -1189,7 +1189,7 @@ public class SavingsAccount extends AbstractPersistable { return ids; } - private Collection findExistingReversedTransactionIds() { + public Collection findExistingReversedTransactionIds() { final Collection ids = new ArrayList(); @@ -1787,4 +1787,17 @@ public class SavingsAccount extends AbstractPersistable { public LocalDate getClosedOnDate() { return (LocalDate) ObjectUtils.defaultIfNull(new LocalDate(this.closedOnDate), null); } + + public SavingsAccountSummary getSummary() { + return this.summary; + } + + public List getTransactions() { + return this.transactions; + } + + public void setStatus(Integer status) { + this.status = status; + } + } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/SavingsAccountStatusType.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/SavingsAccountStatusType.java index 1858e7bc9..2f09829c8 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/SavingsAccountStatusType.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/SavingsAccountStatusType.java @@ -14,6 +14,8 @@ public enum SavingsAccountStatusType { SUBMITTED_AND_PENDING_APPROVAL(100, "savingsAccountStatusType.submitted.and.pending.approval"), // APPROVED(200, "savingsAccountStatusType.approved"), // ACTIVE(300, "savingsAccountStatusType.active"), // + TRANSFER_IN_PROGRESS(303, "savingsAccountStatusType.transfer.in.progress"), // + TRANSFER_ON_HOLD(304, "savingsAccountStatusType.transfer.on.hold"), // WITHDRAWN_BY_APPLICANT(400, "savingsAccountStatusType.withdrawn.by.applicant"), // REJECTED(500, "savingsAccountStatusType.rejected"), // CLOSED(600, "savingsAccountStatusType.closed"); @@ -34,6 +36,12 @@ public enum SavingsAccountStatusType { case 300: enumeration = SavingsAccountStatusType.ACTIVE; break; + case 303: + enumeration = SavingsAccountStatusType.TRANSFER_IN_PROGRESS; + break; + case 304: + enumeration = SavingsAccountStatusType.TRANSFER_ON_HOLD; + break; case 400: enumeration = SavingsAccountStatusType.WITHDRAWN_BY_APPLICANT; break; @@ -87,4 +95,16 @@ public enum SavingsAccountStatusType { public boolean isClosed() { return this.value.equals(SavingsAccountStatusType.CLOSED.getValue()) || isRejected() || isApplicationWithdrawnByApplicant(); } + + public boolean isTransferInProgress() { + return this.value.equals(SavingsAccountStatusType.TRANSFER_IN_PROGRESS.getValue()); + } + + public boolean isTransferOnHold() { + return this.value.equals(SavingsAccountStatusType.TRANSFER_ON_HOLD.getValue()); + } + + public boolean isUnderTransfer() { + return isTransferInProgress() || isTransferOnHold(); + } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/SavingsAccountSummary.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/SavingsAccountSummary.java index 986cee5fd..846253b27 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/SavingsAccountSummary.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/SavingsAccountSummary.java @@ -79,4 +79,9 @@ public final class SavingsAccountSummary { public Money getAccountBalance(final MonetaryCurrency currency) { return Money.of(currency, this.accountBalance); } + + public BigDecimal getAccountBalance() { + return this.accountBalance; + } + } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/SavingsAccountTransaction.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/SavingsAccountTransaction.java index 498325be9..e4b6fd55d 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/SavingsAccountTransaction.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/domain/SavingsAccountTransaction.java @@ -117,6 +117,30 @@ public final class SavingsAccountTransaction extends AbstractPersistable { isReversed); } + public static SavingsAccountTransaction initiateTransfer(final SavingsAccount savingsAccount, final Office office, final LocalDate date) { + final boolean isReversed = false; + final PaymentDetail paymentDetail = null; + return new SavingsAccountTransaction(savingsAccount, office, paymentDetail, + SavingsAccountTransactionType.INITIATE_TRANSFER.getValue(), date, savingsAccount.getSummary().getAccountBalance(), + isReversed); + } + + public static SavingsAccountTransaction approveTransfer(final SavingsAccount savingsAccount, final Office office, final LocalDate date) { + final boolean isReversed = false; + final PaymentDetail paymentDetail = null; + return new SavingsAccountTransaction(savingsAccount, office, paymentDetail, + SavingsAccountTransactionType.APPROVE_TRANSFER.getValue(), date, savingsAccount.getSummary().getAccountBalance(), + isReversed); + } + + public static SavingsAccountTransaction withdrawTransfer(final SavingsAccount savingsAccount, final Office office, final LocalDate date) { + final boolean isReversed = false; + final PaymentDetail paymentDetail = null; + return new SavingsAccountTransaction(savingsAccount, office, paymentDetail, + SavingsAccountTransactionType.WITHDRAW_TRANSFER.getValue(), date, savingsAccount.getSummary().getAccountBalance(), + isReversed); + } + private SavingsAccountTransaction(final SavingsAccount savingsAccount, final Office office, final Integer typeOf, final LocalDate transactionLocalDate, final Money amount, final boolean isReversed) { this(savingsAccount, office, null, typeOf, transactionLocalDate, amount, isReversed); @@ -124,11 +148,16 @@ public final class SavingsAccountTransaction extends AbstractPersistable { private SavingsAccountTransaction(final SavingsAccount savingsAccount, final Office office, final PaymentDetail paymentDetail, final Integer typeOf, final LocalDate transactionLocalDate, final Money amount, final boolean isReversed) { + this(savingsAccount, office, paymentDetail, typeOf, transactionLocalDate, amount.getAmount(), isReversed); + } + + private SavingsAccountTransaction(final SavingsAccount savingsAccount, final Office office, final PaymentDetail paymentDetail, + final Integer typeOf, final LocalDate transactionLocalDate, final BigDecimal amount, final boolean isReversed) { this.savingsAccount = savingsAccount; this.office = office; this.typeOf = typeOf; this.dateOf = transactionLocalDate.toDate(); - this.amount = amount.getAmount(); + this.amount = amount; this.reversed = isReversed; this.paymentDetail = paymentDetail; diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/service/SavingsAccountWritePlatformService.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/service/SavingsAccountWritePlatformService.java index b649dd5b1..806713b36 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/service/SavingsAccountWritePlatformService.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/service/SavingsAccountWritePlatformService.java @@ -8,6 +8,9 @@ package org.mifosplatform.portfolio.savings.service; import org.joda.time.LocalDate; import org.mifosplatform.infrastructure.core.api.JsonCommand; import org.mifosplatform.infrastructure.core.data.CommandProcessingResult; +import org.mifosplatform.organisation.office.domain.Office; +import org.mifosplatform.organisation.staff.domain.Staff; +import org.mifosplatform.portfolio.savings.domain.SavingsAccountTransaction; public interface SavingsAccountWritePlatformService { @@ -28,6 +31,14 @@ public interface SavingsAccountWritePlatformService { void postInterestForAccounts(); CommandProcessingResult adjustSavingsTransaction(Long savingsId, Long transactionId, JsonCommand command); - + CommandProcessingResult close(Long savingsId, JsonCommand command); + + SavingsAccountTransaction initiateSavingsTransfer(Long accountId, LocalDate transferDate); + + SavingsAccountTransaction withdrawSavingsTransfer(Long accountId, LocalDate transferDate); + + void rejectSavingsTransfer(Long accountId); + + SavingsAccountTransaction acceptSavingsTransfer(Long accountId, LocalDate transferDate, Office acceptedInOffice, Staff staff); } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/service/SavingsAccountWritePlatformServiceJpaRepositoryImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/service/SavingsAccountWritePlatformServiceJpaRepositoryImpl.java index 4c3d9e59f..e67a6c136 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/service/SavingsAccountWritePlatformServiceJpaRepositoryImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/service/SavingsAccountWritePlatformServiceJpaRepositoryImpl.java @@ -34,6 +34,8 @@ import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext import org.mifosplatform.organisation.monetary.domain.ApplicationCurrency; import org.mifosplatform.organisation.monetary.domain.ApplicationCurrencyRepositoryWrapper; import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency; +import org.mifosplatform.organisation.office.domain.Office; +import org.mifosplatform.organisation.staff.domain.Staff; import org.mifosplatform.portfolio.client.domain.Client; import org.mifosplatform.portfolio.client.exception.ClientNotActiveException; import org.mifosplatform.portfolio.group.domain.Group; @@ -304,7 +306,7 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi final MathContext mc = new MathContext(15, RoundingMode.HALF_EVEN); final SavingsAccount account = this.savingAccountAssembler.assembleFrom(savingsId); - if(account.isNotActive()){ + if (account.isNotActive()) { throwValidationForActiveStatus(SavingsApiConstants.undoTransactionAction); } account.undoTransaction(transactionId, reversedTransactionIds); @@ -342,7 +344,7 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi final LocalDate today = DateUtils.getLocalDateOfTenant(); final SavingsAccount account = this.savingAccountAssembler.assembleFrom(savingsId); - if(account.isNotActive()){ + if (account.isNotActive()) { throwValidationForActiveStatus(SavingsApiConstants.adjustTransactionAction); } @@ -357,23 +359,23 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi final MathContext mc = new MathContext(10, RoundingMode.HALF_EVEN); account.undoTransaction(transactionId, existingReversedTransactionIds); - - //for undo withdrawal fee + + // for undo withdrawal fee SavingsAccountTransaction nextSavingsAccountTransaction = this.savingsAccountTransactionRepository.findOneByIdAndSavingsAccountId( - transactionId+1, savingsId); - if(nextSavingsAccountTransaction.isWithdrawalFeeAndNotReversed()){ - account.undoTransaction(transactionId+1, existingReversedTransactionIds); + transactionId + 1, savingsId); + if (nextSavingsAccountTransaction.isWithdrawalFeeAndNotReversed()) { + account.undoTransaction(transactionId + 1, existingReversedTransactionIds); } - + SavingsAccountTransaction transaction = null; if (savingsAccountTransaction.isDeposit()) { - SavingsAccountTransactionDTO transactionDTO = new SavingsAccountTransactionDTO(fmt, transactionDate, transactionAmount, - existingTransactionIds, existingReversedTransactionIds,paymentDetail); + SavingsAccountTransactionDTO transactionDTO = new SavingsAccountTransactionDTO(fmt, transactionDate, transactionAmount, + existingTransactionIds, existingReversedTransactionIds, paymentDetail); transaction = account.deposit(transactionDTO); } else { - SavingsAccountTransactionDTO transactionDTO = new SavingsAccountTransactionDTO(fmt, transactionDate, transactionAmount, + SavingsAccountTransactionDTO transactionDTO = new SavingsAccountTransactionDTO(fmt, transactionDate, transactionAmount, existingTransactionIds, existingReversedTransactionIds, paymentDetail); - transaction = account.withdraw(transactionDTO , true); + transaction = account.withdraw(transactionDTO, true); } final Long newtransactionId = saveTransactionToGenerateTransactionId(transaction); @@ -455,4 +457,75 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi .with(changes) // .build(); } + + @Override + public SavingsAccountTransaction initiateSavingsTransfer(Long accountId, LocalDate transferDate) { + final SavingsAccount savingsAccount = this.savingAccountAssembler.assembleFrom(accountId); + + final List existingTransactionIds = new ArrayList(savingsAccount.findExistingTransactionIds()); + final List existingReversedTransactionIds = new ArrayList(savingsAccount.findExistingReversedTransactionIds()); + + final SavingsAccountTransaction newTransferTransaction = SavingsAccountTransaction.initiateTransfer(savingsAccount, + savingsAccount.office(), transferDate); + savingsAccount.getTransactions().add(newTransferTransaction); + savingsAccount.setStatus(SavingsAccountStatusType.TRANSFER_IN_PROGRESS.getValue()); + + this.savingsAccountTransactionRepository.save(newTransferTransaction); + this.savingAccountRepository.save(savingsAccount); + + postJournalEntries(savingsAccount, existingTransactionIds, existingReversedTransactionIds); + + return newTransferTransaction; + } + + @Override + public SavingsAccountTransaction withdrawSavingsTransfer(Long accountId, LocalDate transferDate) { + final SavingsAccount savingsAccount = this.savingAccountAssembler.assembleFrom(accountId); + + final List existingTransactionIds = new ArrayList(savingsAccount.findExistingTransactionIds()); + final List existingReversedTransactionIds = new ArrayList(savingsAccount.findExistingReversedTransactionIds()); + + final SavingsAccountTransaction withdrawtransferTransaction = SavingsAccountTransaction.withdrawTransfer(savingsAccount, + savingsAccount.office(), transferDate); + savingsAccount.getTransactions().add(withdrawtransferTransaction); + savingsAccount.setStatus(SavingsAccountStatusType.ACTIVE.getValue()); + + this.savingsAccountTransactionRepository.save(withdrawtransferTransaction); + this.savingAccountRepository.save(savingsAccount); + + postJournalEntries(savingsAccount, existingTransactionIds, existingReversedTransactionIds); + + return withdrawtransferTransaction; + } + + @Override + public void rejectSavingsTransfer(Long accountId) { + final SavingsAccount savingsAccount = this.savingAccountAssembler.assembleFrom(accountId); + savingsAccount.setStatus(SavingsAccountStatusType.TRANSFER_ON_HOLD.getValue()); + this.savingAccountRepository.save(savingsAccount); + } + + @Override + public SavingsAccountTransaction acceptSavingsTransfer(Long accountId, LocalDate transferDate, Office acceptedInOffice, + Staff fieldOfficer) { + final SavingsAccount savingsAccount = this.savingAccountAssembler.assembleFrom(accountId); + + final List existingTransactionIds = new ArrayList(savingsAccount.findExistingTransactionIds()); + final List existingReversedTransactionIds = new ArrayList(savingsAccount.findExistingReversedTransactionIds()); + + final SavingsAccountTransaction acceptTransferTransaction = SavingsAccountTransaction.approveTransfer(savingsAccount, + acceptedInOffice, transferDate); + savingsAccount.getTransactions().add(acceptTransferTransaction); + savingsAccount.setStatus(SavingsAccountStatusType.ACTIVE.getValue()); + if (fieldOfficer != null) { + savingsAccount.update(fieldOfficer); + } + + this.savingsAccountTransactionRepository.save(acceptTransferTransaction); + this.savingAccountRepository.save(savingsAccount); + + postJournalEntries(savingsAccount, existingTransactionIds, existingReversedTransactionIds); + + return acceptTransferTransaction; + } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/service/SavingsEnumerations.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/service/SavingsEnumerations.java index aa87c8286..fe4e74be5 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/service/SavingsEnumerations.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/savings/service/SavingsEnumerations.java @@ -100,46 +100,61 @@ public class SavingsEnumerations { final boolean isWithdrawnByApplicant = type.isApplicationWithdrawnByApplicant(); final boolean isActive = type.isActive(); final boolean isClosed = type.isClosed(); + final boolean isTransferInProgress = type.isTransferInProgress(); + final boolean isTransferOnHold = type.isTransferOnHold(); SavingsAccountStatusEnumData optionData = new SavingsAccountStatusEnumData(SavingsAccountStatusType.INVALID.getValue().longValue(), SavingsAccountStatusType.INVALID.getCode(), "Invalid", submittedAndPendingApproval, isApproved, isRejected, - isWithdrawnByApplicant, isActive, isClosed); + isWithdrawnByApplicant, isActive, isClosed, isTransferInProgress, isTransferOnHold); switch (type) { case INVALID: optionData = new SavingsAccountStatusEnumData(SavingsAccountStatusType.INVALID.getValue().longValue(), SavingsAccountStatusType.INVALID.getCode(), "Invalid", submittedAndPendingApproval, isApproved, isRejected, - isWithdrawnByApplicant, isActive, isClosed); + isWithdrawnByApplicant, isActive, isClosed, isTransferInProgress, isTransferOnHold); break; case SUBMITTED_AND_PENDING_APPROVAL: optionData = new SavingsAccountStatusEnumData(SavingsAccountStatusType.SUBMITTED_AND_PENDING_APPROVAL.getValue() .longValue(), SavingsAccountStatusType.SUBMITTED_AND_PENDING_APPROVAL.getCode(), "Submitted and pending approval", - submittedAndPendingApproval, isApproved, isRejected, isWithdrawnByApplicant, isActive, isClosed); + submittedAndPendingApproval, isApproved, isRejected, isWithdrawnByApplicant, isActive, isClosed, + isTransferInProgress, isTransferOnHold); break; case REJECTED: optionData = new SavingsAccountStatusEnumData(SavingsAccountStatusType.REJECTED.getValue().longValue(), SavingsAccountStatusType.REJECTED.getCode(), "Rejected", submittedAndPendingApproval, isApproved, isRejected, - isWithdrawnByApplicant, isActive, isClosed); + isWithdrawnByApplicant, isActive, isClosed, isTransferInProgress, isTransferOnHold); break; case WITHDRAWN_BY_APPLICANT: optionData = new SavingsAccountStatusEnumData(SavingsAccountStatusType.WITHDRAWN_BY_APPLICANT.getValue().longValue(), SavingsAccountStatusType.WITHDRAWN_BY_APPLICANT.getCode(), "Withdrawn by applicant", submittedAndPendingApproval, - isApproved, isRejected, isWithdrawnByApplicant, isActive, isClosed); + isApproved, isRejected, isWithdrawnByApplicant, isActive, isClosed, isTransferInProgress, isTransferOnHold); break; case APPROVED: optionData = new SavingsAccountStatusEnumData(SavingsAccountStatusType.APPROVED.getValue().longValue(), SavingsAccountStatusType.APPROVED.getCode(), "Approved", submittedAndPendingApproval, isApproved, isRejected, - isWithdrawnByApplicant, isActive, isClosed); + isWithdrawnByApplicant, isActive, isClosed, isTransferInProgress, isTransferOnHold); break; case ACTIVE: optionData = new SavingsAccountStatusEnumData(SavingsAccountStatusType.ACTIVE.getValue().longValue(), SavingsAccountStatusType.ACTIVE.getCode(), "Active", submittedAndPendingApproval, isApproved, isRejected, - isWithdrawnByApplicant, isActive, isClosed); + isWithdrawnByApplicant, isActive, isClosed, isTransferInProgress, isTransferOnHold); break; case CLOSED: optionData = new SavingsAccountStatusEnumData(SavingsAccountStatusType.CLOSED.getValue().longValue(), SavingsAccountStatusType.CLOSED.getCode(), "Closed", submittedAndPendingApproval, isApproved, isRejected, - isWithdrawnByApplicant, isActive, isClosed); + isWithdrawnByApplicant, isActive, isClosed, isTransferInProgress, isTransferOnHold); + break; + case TRANSFER_IN_PROGRESS: + optionData = new SavingsAccountStatusEnumData(SavingsAccountStatusType.TRANSFER_IN_PROGRESS.getValue().longValue(), + SavingsAccountStatusType.TRANSFER_IN_PROGRESS.getCode(), "Transfer in progress", submittedAndPendingApproval, + isApproved, isRejected, isWithdrawnByApplicant, isActive, isClosed, isTransferInProgress, isTransferOnHold); + break; + case TRANSFER_ON_HOLD: + optionData = new SavingsAccountStatusEnumData(SavingsAccountStatusType.TRANSFER_IN_PROGRESS.getValue().longValue(), + SavingsAccountStatusType.TRANSFER_ON_HOLD.getCode(), "Transfer in progress", submittedAndPendingApproval, + isApproved, isRejected, isWithdrawnByApplicant, isActive, isClosed, isTransferInProgress, isTransferOnHold); + break; + default: break; } return optionData; diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/transfer/service/TransferWritePlatformServiceJpaRepositoryImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/transfer/service/TransferWritePlatformServiceJpaRepositoryImpl.java index 8095b2522..7673d561b 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/transfer/service/TransferWritePlatformServiceJpaRepositoryImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/transfer/service/TransferWritePlatformServiceJpaRepositoryImpl.java @@ -35,7 +35,9 @@ import org.mifosplatform.portfolio.loanaccount.domain.Loan; import org.mifosplatform.portfolio.loanaccount.domain.LoanRepository; import org.mifosplatform.portfolio.loanaccount.service.LoanWritePlatformService; import org.mifosplatform.portfolio.note.service.NoteWritePlatformService; +import org.mifosplatform.portfolio.savings.domain.SavingsAccount; import org.mifosplatform.portfolio.savings.domain.SavingsAccountRepository; +import org.mifosplatform.portfolio.savings.service.SavingsAccountWritePlatformService; import org.mifosplatform.portfolio.transfer.api.TransferApiConstants; import org.mifosplatform.portfolio.transfer.data.TransfersDataValidator; import org.mifosplatform.portfolio.transfer.exception.ClientNotAwaitingTransferApprovalException; @@ -58,6 +60,7 @@ public class TransferWritePlatformServiceJpaRepositoryImpl implements TransferWr private final CalendarInstanceRepository calendarInstanceRepository; private final GroupRepositoryWrapper groupRepository; private final LoanWritePlatformService loanWritePlatformService; + private final SavingsAccountWritePlatformService savingsAccountWritePlatformService; private final LoanRepository loanRepository; private final SavingsAccountRepository savingsAccountRepository; private final TransfersDataValidator transfersDataValidator; @@ -70,7 +73,8 @@ public class TransferWritePlatformServiceJpaRepositoryImpl implements TransferWr final LoanWritePlatformService loanWritePlatformService, final GroupRepositoryWrapper groupRepository, final LoanRepository loanRepository, final TransfersDataValidator transfersDataValidator, final NoteWritePlatformService noteWritePlatformService, final StaffRepositoryWrapper staffRepositoryWrapper, - final SavingsAccountRepository savingsAccountRepository) { + final SavingsAccountRepository savingsAccountRepository, + final SavingsAccountWritePlatformService savingsAccountWritePlatformService) { this.clientRepository = clientRepository; this.officeRepository = officeRepository; this.calendarInstanceRepository = calendarInstanceRepository; @@ -81,6 +85,7 @@ public class TransferWritePlatformServiceJpaRepositoryImpl implements TransferWr this.noteWritePlatformService = noteWritePlatformService; this.staffRepositoryWrapper = staffRepositoryWrapper; this.savingsAccountRepository = savingsAccountRepository; + this.savingsAccountWritePlatformService = savingsAccountWritePlatformService; } @Override @@ -345,8 +350,30 @@ public class TransferWritePlatformServiceJpaRepositoryImpl implements TransferWr } /*** Handle Active Savings (Currently throw and exception) ***/ - if (savingsAccountRepository.doNonClosedSavingAccountsExistForClient(client.getId())) { throw new TransferNotSupportedException( - TRANSFER_NOT_SUPPORTED_REASON.ACTIVE_SAVINGS_ACCOUNT, client.getId()); } + if (savingsAccountRepository.doNonClosedSavingAccountsExistForClient(client.getId())) { + // get each individual saving account for the client + for (SavingsAccount savingsAccount : savingsAccountRepository.findSavingAccountByClientId(client.getId())) { + if (!savingsAccount.isClosed()) { + switch (transferEventType) { + case ACCEPTANCE: + this.savingsAccountWritePlatformService.acceptSavingsTransfer(savingsAccount.getId(), + DateUtils.getLocalDateOfTenant(), destinationOffice, staff); + break; + case PROPOSAL: + this.savingsAccountWritePlatformService.initiateSavingsTransfer(savingsAccount.getId(), + DateUtils.getLocalDateOfTenant()); + break; + case REJECTION: + this.savingsAccountWritePlatformService.withdrawSavingsTransfer(savingsAccount.getId(), + DateUtils.getLocalDateOfTenant()); + break; + case WITHDRAWAL: + this.savingsAccountWritePlatformService.withdrawSavingsTransfer(savingsAccount.getId(), + DateUtils.getLocalDateOfTenant()); + } + } + } + } switch (transferEventType) { case ACCEPTANCE: