From 82821cedecf05814c57c511fcedc6c4e0420382e Mon Sep 17 00:00:00 2001 From: Pramod Nuthakki Date: Thu, 29 Aug 2013 15:53:16 +0530 Subject: [PATCH] changes to transfer funds from overpaid account --- .../account/data/AccountTransferData.java | 6 +- .../account/data/PortfolioAccountData.java | 34 ++++++++- .../account/domain/AccountTransfer.java | 69 ++++++++++++++++--- .../domain/AccountTransferAssembler.java | 28 ++++++++ .../domain/AccountTransferRepository.java | 6 ++ ...countTransfersReadPlatformServiceImpl.java | 42 ++++++----- .../AccountTransfersWritePlatformService.java | 3 + ...ountTransfersWritePlatformServiceImpl.java | 48 ++++++++++++- .../PortfolioAccountReadPlatformService.java | 4 +- ...rtfolioAccountReadPlatformServiceImpl.java | 53 ++++++++------ .../portfolio/loanaccount/domain/Loan.java | 64 ++++++++++++++++- .../domain/LoanAccountDomainService.java | 7 +- .../domain/LoanAccountDomainServiceJpa.java | 45 ++++++++++++ .../loanaccount/domain/LoanStatus.java | 4 ++ .../loanaccount/domain/LoanTransaction.java | 9 +++ .../domain/LoanTransactionType.java | 7 +- ...WritePlatformServiceJpaRepositoryImpl.java | 9 ++- .../loanproduct/service/LoanEnumerations.java | 4 ++ 18 files changed, 378 insertions(+), 64 deletions(-) diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/account/data/AccountTransferData.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/account/data/AccountTransferData.java index eeeb11d7e..93d6612f6 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/account/data/AccountTransferData.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/account/data/AccountTransferData.java @@ -54,11 +54,13 @@ public class AccountTransferData { final Collection toAccountTypeOptions, final Collection toAccountOptions) { final Long id = null; CurrencyData currency = null; + BigDecimal transferAmount = BigDecimal.ZERO; if (fromAccount != null) { currency = fromAccount.currency(); + if(fromAccount.getAmtForTransfer() != null){ + transferAmount = fromAccount.getAmtForTransfer(); + } } - - final BigDecimal transferAmount = BigDecimal.ZERO; final String transferDescription = null; final Boolean reversed = null; return new AccountTransferData(id, reversed, fromOffice, fromClient, fromAccountType, fromAccount, currency, transferAmount, diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/account/data/PortfolioAccountData.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/account/data/PortfolioAccountData.java index f34ea35ea..717a3efb5 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/account/data/PortfolioAccountData.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/account/data/PortfolioAccountData.java @@ -5,6 +5,8 @@ */ package org.mifosplatform.portfolio.account.data; +import java.math.BigDecimal; + import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.commons.lang3.builder.HashCodeBuilder; import org.mifosplatform.organisation.monetary.data.CurrencyData; @@ -27,9 +29,10 @@ public class PortfolioAccountData { private final Long fieldOfficerId; private final String fieldOfficerName; private final CurrencyData currency; + private final BigDecimal amtForTransfer; public static PortfolioAccountData lookup(final Long accountId, final String accountNo) { - return new PortfolioAccountData(accountId, accountNo, null, null, null, null, null, null, null, null, null, null); + return new PortfolioAccountData(accountId, accountNo, null, null, null, null, null, null, null, null, null, null, null); } public PortfolioAccountData(final Long id, final String accountNo, final String externalId, final Long groupId, final String groupName, @@ -47,6 +50,25 @@ public class PortfolioAccountData { this.fieldOfficerId = fieldofficerId; this.fieldOfficerName = fieldofficerName; this.currency = currency; + this.amtForTransfer = null; + } + + public PortfolioAccountData(final Long id, final String accountNo, final String externalId, final Long groupId, final String groupName, + final Long clientId, final String clientName, final Long productId, final String productName, final Long fieldofficerId, + final String fieldofficerName, final CurrencyData currency, final BigDecimal amtForTransfer) { + this.id = id; + this.accountNo = accountNo; + this.externalId = externalId; + this.groupId = groupId; + this.groupName = groupName; + this.clientId = clientId; + this.clientName = clientName; + this.productId = productId; + this.productName = productName; + this.fieldOfficerId = fieldofficerId; + this.fieldOfficerName = fieldofficerName; + this.currency = currency; + this.amtForTransfer = amtForTransfer; } @Override @@ -56,12 +78,14 @@ public class PortfolioAccountData { if (obj == this) { return true; } if (obj.getClass() != getClass()) { return false; } final PortfolioAccountData rhs = (PortfolioAccountData) obj; - return new EqualsBuilder().append(this.id, rhs.id).append(this.accountNo, rhs.accountNo).append(this.productId, rhs.productId).append(this.productName, rhs.productName).isEquals(); + return new EqualsBuilder().append(this.id, rhs.id).append(this.accountNo, rhs.accountNo).append(this.productId, rhs.productId) + .append(this.productName, rhs.productName).isEquals(); } @Override public int hashCode() { - return new HashCodeBuilder(17, 37).append(this.id).append(this.accountNo).append(this.productId).append(this.productName).toHashCode(); + return new HashCodeBuilder(17, 37).append(this.id).append(this.accountNo).append(this.productId).append(this.productName) + .toHashCode(); } public Long clientId() { @@ -75,4 +99,8 @@ public class PortfolioAccountData { public String currencyCode() { return this.currency.code(); } + + public BigDecimal getAmtForTransfer() { + return this.amtForTransfer; + } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/account/domain/AccountTransfer.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/account/domain/AccountTransfer.java index 6a52ee403..c21f7967b 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/account/domain/AccountTransfer.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/account/domain/AccountTransfer.java @@ -68,12 +68,20 @@ public class AccountTransfer extends AbstractPersistable { @JoinColumn(name = "to_loan_account_id", nullable = true) private Loan toLoanAccount; + @ManyToOne + @JoinColumn(name = "from_loan_account_id", nullable = true) + private Loan fromLoanAccount; + @ManyToOne @JoinColumn(name = "to_loan_transaction_id", nullable = true) private LoanTransaction toLoanTransaction; + @ManyToOne + @JoinColumn(name = "from_loan_transaction_id", nullable = true) + private LoanTransaction fromLoanTransaction; + @Column(name = "is_reversed", nullable = false) - private final boolean reversed = false; + private boolean reversed = false; @Temporal(TemporalType.DATE) @Column(name = "transaction_date") @@ -93,16 +101,23 @@ public class AccountTransfer extends AbstractPersistable { final SavingsAccountTransaction withdrawal, final SavingsAccountTransaction deposit, final LocalDate transactionDate, final Money transactionAmount, final String description) { - return new AccountTransfer(fromOffice, fromClient, fromSavingsAccount, toOffice, toClient, toSavingsAccount, null, withdrawal, - deposit, null, transactionDate, transactionAmount, description); + return new AccountTransfer(fromOffice, fromClient, fromSavingsAccount, null, toOffice, toClient, toSavingsAccount, null, + withdrawal, deposit, null, null, transactionDate, transactionAmount, description); } public static AccountTransfer savingsToLoanTransfer(final Office fromOffice, final Client fromClient, final SavingsAccount fromSavingsAccount, final Office toOffice, final Client toClient, final Loan toLoanAccount, final SavingsAccountTransaction withdrawal, final LoanTransaction loanRepaymentTransaction, final LocalDate transactionDate, final Money transactionAmount, final String description) { - return new AccountTransfer(fromOffice, fromClient, fromSavingsAccount, toOffice, toClient, null, toLoanAccount, withdrawal, null, - loanRepaymentTransaction, transactionDate, transactionAmount, description); + return new AccountTransfer(fromOffice, fromClient, fromSavingsAccount, null, toOffice, toClient, null, toLoanAccount, withdrawal, + null, loanRepaymentTransaction, null, transactionDate, transactionAmount, description); + } + + public static AccountTransfer LoanTosavingsTransfer(final Office fromOffice, final Client fromClient, final Loan fromLoanAccount, + final Office toOffice, final Client toClient, final SavingsAccount toSavingsAccount, final SavingsAccountTransaction deposit, + final LoanTransaction loanRefundTransaction, final LocalDate transactionDate, final Money transactionAmount, final String description) { + return new AccountTransfer(fromOffice, fromClient, null, fromLoanAccount, toOffice, toClient, toSavingsAccount, null, null, + deposit, null, loanRefundTransaction, transactionDate, transactionAmount, description); } protected AccountTransfer() { @@ -110,13 +125,15 @@ public class AccountTransfer extends AbstractPersistable { } private AccountTransfer(final Office fromOffice, final Client fromClient, final SavingsAccount fromSavingsAccount, - final Office toOffice, final Client toClient, final SavingsAccount toSavingsAccount, final Loan toLoanAccount, - final SavingsAccountTransaction withdrawal, final SavingsAccountTransaction deposit, - final LoanTransaction loanRepaymentTransaction, final LocalDate transactionDate, final Money transactionAmount, - final String description) { + final Loan fromLoanAccount, final Office toOffice, final Client toClient, final SavingsAccount toSavingsAccount, + final Loan toLoanAccount, final SavingsAccountTransaction withdrawal, final SavingsAccountTransaction deposit, + final LoanTransaction loanRepaymentTransaction, LoanTransaction loanRefundTransaction, final LocalDate transactionDate, + final Money transactionAmount, final String description) { this.fromOffice = fromOffice; this.fromClient = fromClient; this.fromAccount = fromSavingsAccount; + this.fromLoanAccount = fromLoanAccount; + this.fromLoanTransaction = loanRefundTransaction; this.toOffice = toOffice; this.toClient = toClient; this.toSavingsAccount = toSavingsAccount; @@ -129,4 +146,38 @@ public class AccountTransfer extends AbstractPersistable { this.amount = transactionAmount.getAmountDefaultedToNullIfZero(); this.description = description; } + + + public LoanTransaction getFromLoanTransaction() { + return this.fromLoanTransaction; + } + + + public SavingsAccountTransaction getFromTransaction() { + return this.fromTransaction; + } + + + public LoanTransaction getToLoanTransaction() { + return this.toLoanTransaction; + } + + + public SavingsAccountTransaction getToSavingsTransaction() { + return this.toSavingsTransaction; + } + + public void reverse() { + this.reversed = true; + } + + + public SavingsAccount getToSavingsAccount() { + return this.toSavingsAccount; + } + + + public SavingsAccount getFromAccount() { + return this.fromAccount; + } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/account/domain/AccountTransferAssembler.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/account/domain/AccountTransferAssembler.java index ffdadd61e..54625a820 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/account/domain/AccountTransferAssembler.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/account/domain/AccountTransferAssembler.java @@ -111,4 +111,32 @@ public class AccountTransferAssembler { return AccountTransfer.savingsToLoanTransfer(fromOffice, fromClient, fromSavingsAccount, toOffice, toClient, toLoanAccount, withdrawal, loanRepaymentTransaction, transactionDate, transactionMonetaryAmount, description); } + + public AccountTransfer assembleLoanToSavingsTransfer(final JsonCommand command, final Loan fromLoanAccount, + final SavingsAccount toSavingsAccount, final SavingsAccountTransaction deposit, final LoanTransaction loanRefundTransaction) { + + final JsonElement element = command.parsedJson(); + + final Long fromOfficeId = this.fromApiJsonHelper.extractLongNamed(fromOfficeIdParamName, element); + final Office fromOffice = this.officeRepository.findOne(fromOfficeId); + + final Long fromClientId = this.fromApiJsonHelper.extractLongNamed(fromClientIdParamName, element); + final Client fromClient = this.clientRepository.findOneWithNotFoundDetection(fromClientId); + + final Long toOfficeId = this.fromApiJsonHelper.extractLongNamed(toOfficeIdParamName, element); + final Office toOffice = this.officeRepository.findOne(toOfficeId); + + final Long toClientId = this.fromApiJsonHelper.extractLongNamed(toClientIdParamName, element); + final Client toClient = this.clientRepository.findOneWithNotFoundDetection(toClientId); + + final LocalDate transactionDate = command.localDateValueOfParameterNamed(transferDateParamName); + final BigDecimal transactionAmount = command.bigDecimalValueOfParameterNamed(transferAmountParamName); + final Money transactionMonetaryAmount = Money.of(toSavingsAccount.getCurrency(), transactionAmount); + + final String description = command.stringValueOfParameterNamed(transferDescriptionParamName); + + return AccountTransfer.LoanTosavingsTransfer(fromOffice, fromClient, fromLoanAccount, toOffice, toClient, toSavingsAccount, + deposit, loanRefundTransaction, transactionDate, transactionMonetaryAmount, description); + } + } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/account/domain/AccountTransferRepository.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/account/domain/AccountTransferRepository.java index 352490aec..d16d86b29 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/account/domain/AccountTransferRepository.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/account/domain/AccountTransferRepository.java @@ -5,9 +5,15 @@ */ package org.mifosplatform.portfolio.account.domain; +import java.util.List; + import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaSpecificationExecutor; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; public interface AccountTransferRepository extends JpaRepository, JpaSpecificationExecutor { + @Query("from AccountTransfer at where at.fromLoanAccount.id= :accountNumber and at.reversed=false") + List findByLoanId(@Param("accountNumber") Long accountNumber); } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/account/service/AccountTransfersReadPlatformServiceImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/account/service/AccountTransfersReadPlatformServiceImpl.java index 166bb43df..e5135302d 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/account/service/AccountTransfersReadPlatformServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/account/service/AccountTransfersReadPlatformServiceImpl.java @@ -13,7 +13,6 @@ import java.util.Arrays; import java.util.Collection; import org.joda.time.LocalDate; -import org.mifosplatform.commands.exception.UnsupportedCommandException; import org.mifosplatform.infrastructure.core.data.EnumOptionData; import org.mifosplatform.infrastructure.core.domain.JdbcSupport; import org.mifosplatform.infrastructure.core.service.DateUtils; @@ -70,23 +69,20 @@ public class AccountTransfersReadPlatformServiceImpl implements AccountTransfers final EnumOptionData loanAccountType = AccountTransferEnumerations.accountType(PortfolioAccountType.LOAN); final EnumOptionData savingsAccountType = AccountTransferEnumerations.accountType(PortfolioAccountType.SAVINGS); - final Collection fromAccountTypeOptions = Arrays.asList(savingsAccountType); - final Collection toAccountTypeOptions = Arrays.asList(loanAccountType, savingsAccountType); - - // TODO - remove this after doing overpaid loan to savings transfers Integer mostRelevantFromAccountType = fromAccountType; - if (mostRelevantFromAccountType == null) { - mostRelevantFromAccountType = 2; // savings + final Collection fromAccountTypeOptions = Arrays.asList(savingsAccountType, loanAccountType); + final Collection toAccountTypeOptions; + if (mostRelevantFromAccountType == 1) { + // overpaid loan amt transfer to savings account + toAccountTypeOptions = Arrays.asList(savingsAccountType); + } else { + toAccountTypeOptions = Arrays.asList(loanAccountType, savingsAccountType); } - final Integer mostRelevantToAccountType = toAccountType; final EnumOptionData fromAccountTypeData = AccountTransferEnumerations.accountType(mostRelevantFromAccountType); final EnumOptionData toAccountTypeData = AccountTransferEnumerations.accountType(mostRelevantToAccountType); - // check for now that only savings account type is passed and used. - if (mostRelevantFromAccountType != 2) { throw new UnsupportedCommandException("transferFromLoanAccountNotSupported"); } - // from settings OfficeData fromOffice = null; ClientData fromClient = null; @@ -106,21 +102,28 @@ public class AccountTransfersReadPlatformServiceImpl implements AccountTransfers Long mostRelevantToOfficeId = toOfficeId; Long mostRelevantToClientId = toClientId; - if (fromAccountId != null && mostRelevantFromAccountType == 2) { - fromAccount = this.portfolioAccountReadPlatformService.retrieveOne(fromAccountId, PortfolioAccountType.SAVINGS.getValue()); + if (fromAccountId != null) { + Integer accountType; + if (mostRelevantFromAccountType == 1) { + accountType = PortfolioAccountType.LOAN.getValue(); + } else { + accountType = PortfolioAccountType.SAVINGS.getValue(); + } + fromAccount = this.portfolioAccountReadPlatformService.retrieveOne(fromAccountId, accountType); // override provided fromClient with client of account mostRelevantFromClientId = fromAccount.clientId(); - } else if (fromAccountId != null && mostRelevantFromAccountType == 1) { // loans - // fetch loan account } if (mostRelevantFromClientId != null) { fromClient = this.clientReadPlatformService.retrieveOne(mostRelevantFromClientId); mostRelevantFromOfficeId = fromClient.officeId(); - + long[] loanStatus = null; + if (mostRelevantFromAccountType == 1) { + loanStatus = new long[] { 300, 700 }; + } fromAccountOptions = this.portfolioAccountReadPlatformService.retrieveAllForLookup(mostRelevantFromAccountType, - mostRelevantFromClientId); + mostRelevantFromClientId, loanStatus); } Collection fromOfficeOptions = null; @@ -137,7 +140,8 @@ public class AccountTransfersReadPlatformServiceImpl implements AccountTransfers Collection toClientOptions = null; if (toAccountId != null && fromAccount != null) { - toAccount = this.portfolioAccountReadPlatformService.retrieveOne(toAccountId, mostRelevantToAccountType, fromAccount.currencyCode()); + toAccount = this.portfolioAccountReadPlatformService.retrieveOne(toAccountId, mostRelevantToAccountType, + fromAccount.currencyCode()); mostRelevantToClientId = toAccount.clientId(); } @@ -173,7 +177,7 @@ public class AccountTransfersReadPlatformServiceImpl implements AccountTransfers final String currencyCode = excludeThisAccountFromOptions != null ? excludeThisAccountFromOptions.currencyCode() : null; Collection accountOptions = this.portfolioAccountReadPlatformService.retrieveAllForLookup(toAccountType, - toClientId, currencyCode); + toClientId, currencyCode, null); if (!CollectionUtils.isEmpty(accountOptions)) { accountOptions.remove(excludeThisAccountFromOptions); } else { diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/account/service/AccountTransfersWritePlatformService.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/account/service/AccountTransfersWritePlatformService.java index 821478df9..ffd48dfb4 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/account/service/AccountTransfersWritePlatformService.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/account/service/AccountTransfersWritePlatformService.java @@ -7,8 +7,11 @@ package org.mifosplatform.portfolio.account.service; import org.mifosplatform.infrastructure.core.api.JsonCommand; import org.mifosplatform.infrastructure.core.data.CommandProcessingResult; +import org.mifosplatform.portfolio.account.PortfolioAccountType; public interface AccountTransfersWritePlatformService { CommandProcessingResult create(JsonCommand command); + + void reverseTransfers(Long accountNumber, PortfolioAccountType accountTypeId); } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/account/service/AccountTransfersWritePlatformServiceImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/account/service/AccountTransfersWritePlatformServiceImpl.java index fed01d77b..fe70b7fc0 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/account/service/AccountTransfersWritePlatformServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/account/service/AccountTransfersWritePlatformServiceImpl.java @@ -13,6 +13,7 @@ import static org.mifosplatform.portfolio.account.AccountTransfersApiConstants.t import static org.mifosplatform.portfolio.account.AccountTransfersApiConstants.transferDateParamName; import java.math.BigDecimal; +import java.util.List; import java.util.Locale; import org.joda.time.LocalDate; @@ -35,6 +36,7 @@ import org.mifosplatform.portfolio.savings.domain.SavingsAccount; import org.mifosplatform.portfolio.savings.domain.SavingsAccountAssembler; import org.mifosplatform.portfolio.savings.domain.SavingsAccountDomainService; import org.mifosplatform.portfolio.savings.domain.SavingsAccountTransaction; +import org.mifosplatform.portfolio.savings.service.SavingsAccountWritePlatformService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -49,12 +51,14 @@ public class AccountTransfersWritePlatformServiceImpl implements AccountTransfer private final SavingsAccountDomainService savingsAccountDomainService; private final LoanAssembler loanAccountAssembler; private final LoanAccountDomainService loanAccountDomainService; + private final SavingsAccountWritePlatformService savingsAccountWritePlatformService; @Autowired public AccountTransfersWritePlatformServiceImpl(final AccountTransfersDataValidator accountTransfersDataValidator, final AccountTransferAssembler accountTransferAssembler, final AccountTransferRepository accountTransferRepository, final SavingsAccountAssembler savingsAccountAssembler, final SavingsAccountDomainService savingsAccountDomainService, - final LoanAssembler loanAssembler, final LoanAccountDomainService loanAccountDomainService) { + final LoanAssembler loanAssembler, final LoanAccountDomainService loanAccountDomainService, + final SavingsAccountWritePlatformService savingsAccountWritePlatformService) { this.accountTransfersDataValidator = accountTransfersDataValidator; this.accountTransferAssembler = accountTransferAssembler; this.accountTransferRepository = accountTransferRepository; @@ -62,6 +66,7 @@ public class AccountTransfersWritePlatformServiceImpl implements AccountTransfer this.savingsAccountDomainService = savingsAccountDomainService; this.loanAccountAssembler = loanAssembler; this.loanAccountDomainService = loanAccountDomainService; + this.savingsAccountWritePlatformService = savingsAccountWritePlatformService; } @Transactional @@ -124,7 +129,27 @@ public class AccountTransfersWritePlatformServiceImpl implements AccountTransfer transferTransactionId = transferTransaction.getId(); } else if (isLoanToSavingsAccountTransfer(fromAccountType, toAccountType)) { - // FIXME - kw - ADD overpaid loan to savings account transfer support. + // FIXME - kw - ADD overpaid loan to savings account transfer + // support. + + // + final Long fromLoanAccountId = command.longValueOfParameterNamed(fromAccountIdParamName); + final Loan fromLoanAccount = this.loanAccountAssembler.assembleFrom(fromLoanAccountId); + + final LoanTransaction loanRefundTransaction = this.loanAccountDomainService.makeRefund(fromLoanAccountId, + new CommandProcessingResultBuilder(), transactionDate, transactionAmount, paymentDetail, null, null); + + final Long toSavingsAccountId = command.longValueOfParameterNamed(toAccountIdParamName); + final SavingsAccount toSavingsAccount = this.savingsAccountAssembler.assembleFrom(toSavingsAccountId); + + final SavingsAccountTransaction deposit = this.savingsAccountDomainService.handleDeposit(toSavingsAccount, fmt, + transactionDate, transactionAmount, paymentDetail); + + final AccountTransfer transferTransaction = this.accountTransferAssembler.assembleLoanToSavingsTransfer(command, + fromLoanAccount, toSavingsAccount, deposit, loanRefundTransaction); + this.accountTransferRepository.saveAndFlush(transferTransaction); + transferTransactionId = transferTransaction.getId(); + } else { } @@ -139,6 +164,25 @@ public class AccountTransfersWritePlatformServiceImpl implements AccountTransfer return builder.build(); } + @Override + @Transactional + public void reverseTransfers(Long accountNumber, PortfolioAccountType accountTypeId) { + List acccountTransfers = null; + if (accountTypeId.isLoanAccount()) { + acccountTransfers = this.accountTransferRepository.findByLoanId(accountNumber); + } + if (acccountTransfers != null && acccountTransfers.size() > 0) { + for (AccountTransfer accountTransfer : acccountTransfers) { + this.loanAccountDomainService.reverseTransfer(accountTransfer.getFromLoanTransaction()); + this.savingsAccountWritePlatformService.undoTransaction(accountTransfer.getToSavingsAccount().getId(), accountTransfer + .getToSavingsTransaction().getId()); + accountTransfer.reverse(); + this.accountTransferRepository.save(accountTransfer); + } + } + + } + private boolean isLoanToSavingsAccountTransfer(final PortfolioAccountType fromAccountType, final PortfolioAccountType toAccountType) { return fromAccountType.isLoanAccount() && toAccountType.isSavingsAccount(); } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/account/service/PortfolioAccountReadPlatformService.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/account/service/PortfolioAccountReadPlatformService.java index 7fc417b2e..f85b55c3b 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/account/service/PortfolioAccountReadPlatformService.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/account/service/PortfolioAccountReadPlatformService.java @@ -15,7 +15,7 @@ public interface PortfolioAccountReadPlatformService { PortfolioAccountData retrieveOne(Long accountId, Integer accountTypeId, String currencyCode); - Collection retrieveAllForLookup(Integer toAccountType, Long toClientId); + Collection retrieveAllForLookup(Integer toAccountType, Long toClientId, long[] accountStatus); - Collection retrieveAllForLookup(Integer toAccountType, Long toClientId, String currencyCode); + Collection retrieveAllForLookup(Integer toAccountType, Long toClientId, String currencyCode, long[] accountStatus); } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/account/service/PortfolioAccountReadPlatformServiceImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/account/service/PortfolioAccountReadPlatformServiceImpl.java index 96deaf1f7..02a0a6c50 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/account/service/PortfolioAccountReadPlatformServiceImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/account/service/PortfolioAccountReadPlatformServiceImpl.java @@ -5,6 +5,7 @@ */ package org.mifosplatform.portfolio.account.service; +import java.math.BigDecimal; import java.sql.ResultSet; import java.sql.SQLException; import java.util.Collection; @@ -45,24 +46,24 @@ public class PortfolioAccountReadPlatformServiceImpl implements PortfolioAccount @Override public PortfolioAccountData retrieveOne(final Long accountId, final Integer accountTypeId, final String currencyCode) { - Object[] sqlParams = new Object[] {accountId}; + Object[] sqlParams = new Object[] { accountId }; PortfolioAccountData accountData = null; try { String sql = null; final PortfolioAccountType accountType = PortfolioAccountType.fromInt(accountTypeId); switch (accountType) { case INVALID: - break; + break; case LOAN: sql = "select " + this.loanAccountMapper.schema() + " where la.id = ?"; if (currencyCode != null) { sql += " and la.currency_code = ?"; - sqlParams = new Object[] {accountId, currencyCode}; + sqlParams = new Object[] { accountId, currencyCode }; } - accountData = this.jdbcTemplate.queryForObject(sql, this.savingsAccountMapper, sqlParams); - break; + accountData = this.jdbcTemplate.queryForObject(sql, this.loanAccountMapper, sqlParams); + break; case SAVINGS: sql = "select " + this.savingsAccountMapper.schema() + " where sa.id = ?"; if (currencyCode != null) { @@ -71,9 +72,9 @@ public class PortfolioAccountReadPlatformServiceImpl implements PortfolioAccount } accountData = this.jdbcTemplate.queryForObject(sql, this.savingsAccountMapper, sqlParams); - break; + break; default: - break; + break; } } catch (final EmptyResultDataAccessException e) { throw new AccountTransferNotFoundException(accountId); @@ -83,40 +84,50 @@ public class PortfolioAccountReadPlatformServiceImpl implements PortfolioAccount } @Override - public Collection retrieveAllForLookup(final Integer accountTypeId, final Long clientId) { - return retrieveAllForLookup(accountTypeId, clientId, null); + public Collection retrieveAllForLookup(final Integer accountTypeId, final Long clientId, long[] accountStatus) { + return retrieveAllForLookup(accountTypeId, clientId, null, accountStatus); } @Override - public Collection retrieveAllForLookup(final Integer accountTypeId, final Long clientId, final String currencyCode) { + public Collection retrieveAllForLookup(final Integer accountTypeId, final Long clientId, + final String currencyCode, long[] accountStatus) { - Object[] sqlParams = new Object[] {clientId}; + Object[] sqlParams = new Object[] { clientId }; Collection accounts = null; String sql = null; + String defaultAccountStatus = "300"; + if (accountStatus != null) { + for (long status : accountStatus) { + defaultAccountStatus += ", " + status; + } + defaultAccountStatus = defaultAccountStatus.substring(defaultAccountStatus.indexOf(",")+1); + } final PortfolioAccountType accountType = PortfolioAccountType.fromInt(accountTypeId); switch (accountType) { case INVALID: - break; + break; case LOAN: - sql = "select " + this.loanAccountMapper.schema() + " where la.client_id = ? and la.loan_status_id = 300"; + sql = "select " + this.loanAccountMapper.schema() + " where la.client_id = ? and la.loan_status_id in (" + + defaultAccountStatus.toString() + ")"; if (currencyCode != null) { sql += " and la.currency_code = ?"; - sqlParams = new Object[] {clientId, currencyCode}; + sqlParams = new Object[] { clientId, currencyCode }; } accounts = this.jdbcTemplate.query(sql, this.loanAccountMapper, sqlParams); - break; + break; case SAVINGS: - sql = "select " + this.savingsAccountMapper.schema() + " where sa.client_id = ? and sa.status_enum = 300"; + sql = "select " + this.savingsAccountMapper.schema() + " where sa.client_id = ? and sa.status_enum in (" + + defaultAccountStatus.toString() + ")"; if (currencyCode != null) { sql += " and sa.currency_code = ?"; - sqlParams = new Object[] {clientId, currencyCode}; + sqlParams = new Object[] { clientId, currencyCode }; } accounts = this.jdbcTemplate.query(sql, this.savingsAccountMapper, sqlParams); - break; + break; default: - break; + break; } return accounts; @@ -198,6 +209,7 @@ public class PortfolioAccountReadPlatformServiceImpl implements PortfolioAccount sqlBuilder.append("s.id as fieldOfficerId, s.display_name as fieldOfficerName, "); sqlBuilder.append("la.currency_code as currencyCode, la.currency_digits as currencyDigits,"); sqlBuilder.append("la.currency_multiplesof as inMultiplesOf, "); + sqlBuilder.append("la.total_overpaid_derived as totalOverpaid, "); sqlBuilder.append("curr.name as currencyName, curr.internationalized_name_code as currencyNameCode, "); sqlBuilder.append("curr.display_symbol as currencyDisplaySymbol "); sqlBuilder.append("from m_loan la "); @@ -238,11 +250,12 @@ public class PortfolioAccountReadPlatformServiceImpl implements PortfolioAccount final String currencyDisplaySymbol = rs.getString("currencyDisplaySymbol"); final Integer currencyDigits = JdbcSupport.getInteger(rs, "currencyDigits"); final Integer inMulitplesOf = JdbcSupport.getInteger(rs, "inMultiplesOf"); + final BigDecimal amtForTransfer = JdbcSupport.getBigDecimalDefaultToNullIfZero(rs, "totalOverpaid"); final CurrencyData currency = new CurrencyData(currencyCode, currencyName, currencyDigits, inMulitplesOf, currencyDisplaySymbol, currencyNameCode); return new PortfolioAccountData(id, accountNo, externalId, groupId, groupName, clientId, clientName, productId, productName, - fieldOfficerId, fieldOfficerName, currency); + fieldOfficerId, fieldOfficerName, currency, amtForTransfer); } } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/Loan.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/Loan.java index 3b57cb70e..abbd95086 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/Loan.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/Loan.java @@ -1528,6 +1528,42 @@ public class Loan extends AbstractPersistable { return changedTransactionDetail; } + public void makeRefund(final LoanTransaction loanTransaction, final LoanLifecycleStateMachine loanLifecycleStateMachine, + final List existingTransactionIds, final List existingReversedTransactionIds, + final boolean allowTransactionsOnHoliday, final List holidays, final WorkingDays workingDays, + final boolean allowTransactionsOnNonWorkingDay) { + + validateRepaymentDateIsOnHoliday(loanTransaction.getTransactionDate(), allowTransactionsOnHoliday, holidays); + validateRepaymentDateIsOnNonWorkingDay(loanTransaction.getTransactionDate(), workingDays, allowTransactionsOnNonWorkingDay); + + existingTransactionIds.addAll(findExistingTransactionIds()); + existingReversedTransactionIds.addAll(findExistingReversedTransactionIds()); + + if (status().isOverpaid()) { + if (this.totalOverpaid.compareTo(loanTransaction.getAmount(getCurrency()).getAmount()) == -1) { + final String errorMessage = "The refund amount must be less than or equal to overpaid amount "; + throw new InvalidLoanStateTransitionException("transaction", "is.exceeding.overpaid.amount", errorMessage, totalOverpaid, + loanTransaction.getAmount(getCurrency()).getAmount()); + } else if (!isAfterLatRepayment(loanTransaction, loanTransactions)) { + final String errorMessage = "Transfer funds is allowed only after last repayment date"; + throw new InvalidLoanStateTransitionException("transaction", "is.not.after.repayment.date", errorMessage); + } + } else { + final String errorMessage = "Transfer funds is allowed only for loan accounts with overpaid status "; + throw new InvalidLoanStateTransitionException("transaction", "is.not.a.overpaid.loan", errorMessage); + } + this.totalOverpaid = this.totalOverpaid.subtract(loanTransaction.getAmount(getCurrency()).getAmount()); + if (this.totalOverpaid.compareTo(BigDecimal.ZERO) == 0) { + handleLoanRepaymentInFull(loanTransaction.getTransactionDate(), loanLifecycleStateMachine); + } + loanTransaction.updateLoan(this); + + if (loanTransaction.isNotZero(loanCurrency())) { + this.loanTransactions.add(loanTransaction); + } + + } + private ChangedTransactionDetail handleRepaymentOrWaiverTransaction(final LoanTransaction loanTransaction, final LoanLifecycleStateMachine loanLifecycleStateMachine, final LoanTransaction adjustedTransaction) { @@ -1656,6 +1692,22 @@ public class Loan extends AbstractPersistable { return isChronologicallyLatestRepaymentOrWaiver; } + private boolean isAfterLatRepayment(final LoanTransaction loanTransaction, final List loanTransactions) { + + boolean isAfterLatRepayment = true; + + final LocalDate currentTransactionDate = loanTransaction.getTransactionDate(); + for (final LoanTransaction previousTransaction : loanTransactions) { + if (previousTransaction.isRepayment() && previousTransaction.isNotReversed()) { + if (currentTransactionDate.isBefore(previousTransaction.getTransactionDate())) { + isAfterLatRepayment = false; + break; + } + } + } + return isAfterLatRepayment; + } + private boolean isChronologicallyLatestTransaction(final LoanTransaction loanTransaction, final List loanTransactions) { boolean isChronologicallyLatestRepaymentOrWaiver = true; @@ -1794,7 +1846,7 @@ public class Loan extends AbstractPersistable { private Money calculateTotalOverpayment() { - final Money totalPaidInRepayments = getTotalPaidInRepayments(); + Money totalPaidInRepayments = getTotalPaidInRepayments(); final MonetaryCurrency currency = loanCurrency(); Money cumulativeTotalPaidOnInstallments = Money.zero(currency); @@ -1809,6 +1861,12 @@ public class Loan extends AbstractPersistable { cumulativeTotalWaivedOnInstallments = cumulativeTotalWaivedOnInstallments.plus(scheduledRepayment.getInterestWaived(currency)); } + for (LoanTransaction loanTransaction : this.loanTransactions) { + if (loanTransaction.isRefund() && !loanTransaction.isReversed()) { + totalPaidInRepayments = totalPaidInRepayments.minus(loanTransaction.getAmount(currency)); + } + } + // if total paid in transactions doesnt match repayment schedule then // theres an overpayment. return totalPaidInRepayments.minus(cumulativeTotalPaidOnInstallments); @@ -2578,11 +2636,11 @@ public class Loan extends AbstractPersistable { public Integer getTermPeriodFrequencyType() { return this.termPeriodFrequencyType; } - + public List getLoanTransactions() { return this.loanTransactions; } - + public void setLoanStatus(Integer loanStatus) { this.loanStatus = loanStatus; } diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/LoanAccountDomainService.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/LoanAccountDomainService.java index ef82156a8..55b9e2fe3 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/LoanAccountDomainService.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/LoanAccountDomainService.java @@ -15,4 +15,9 @@ public interface LoanAccountDomainService { LoanTransaction makeRepayment(Long accountId, CommandProcessingResultBuilder builderResult, LocalDate transactionDate, BigDecimal transactionAmount, PaymentDetail paymentDetail, String noteText, String txnExternalId); -} \ No newline at end of file + + LoanTransaction makeRefund(Long accountId, CommandProcessingResultBuilder builderResult, LocalDate transactionDate, + BigDecimal transactionAmount, PaymentDetail paymentDetail, String noteText, String txnExternalId); + + void reverseTransfer(LoanTransaction loanTransaction); +} diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/LoanAccountDomainServiceJpa.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/LoanAccountDomainServiceJpa.java index 13d6a244a..0e43bf709 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/LoanAccountDomainServiceJpa.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/LoanAccountDomainServiceJpa.java @@ -163,4 +163,49 @@ public class LoanAccountDomainServiceJpa implements LoanAccountDomainService { if (group.isNotActive()) { throw new GroupNotActiveException(group.getId()); } } } + + @Override + public LoanTransaction makeRefund(Long accountId, CommandProcessingResultBuilder builderResult, LocalDate transactionDate, + BigDecimal transactionAmount, PaymentDetail paymentDetail, String noteText, String txnExternalId) { + final Loan loan = this.loanAccountAssembler.assembleFrom(accountId); + checkClientOrGroupActive(loan); + + final List existingTransactionIds = new ArrayList(); + final List existingReversedTransactionIds = new ArrayList(); + + final Money refundAmount = Money.of(loan.getCurrency(), transactionAmount); + final LoanTransaction newRefundTransaction = LoanTransaction.refund(loan.getOffice(), refundAmount, paymentDetail, transactionDate, + txnExternalId); + final boolean allowTransactionsOnHoliday = this.configurationDomainService.allowTransactionsOnHolidayEnabled(); + final List holidays = this.holidayRepository + .findByOfficeIdAndGreaterThanDate(loan.getOfficeId(), transactionDate.toDate()); + final WorkingDays workingDays = this.workingDaysRepository.findOne(); + final boolean allowTransactionsOnNonWorkingDay = this.configurationDomainService.allowTransactionsOnNonWorkingDayEnabled(); + + loan.makeRefund(newRefundTransaction, defaultLoanLifecycleStateMachine(), existingTransactionIds, existingReversedTransactionIds, + allowTransactionsOnHoliday, holidays, workingDays, allowTransactionsOnNonWorkingDay); + + this.loanTransactionRepository.save(newRefundTransaction); + this.loanRepository.save(loan); + + if (StringUtils.isNotBlank(noteText)) { + final Note note = Note.loanTransactionNote(loan, newRefundTransaction, noteText); + this.noteRepository.save(note); + } + + postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds); + + builderResult.withEntityId(newRefundTransaction.getId()) // + .withOfficeId(loan.getOfficeId()) // + .withClientId(loan.getClientId()) // + .withGroupId(loan.getGroupId()); // + + return newRefundTransaction; + } + + @Override + public void reverseTransfer(LoanTransaction loanTransaction) { + loanTransaction.reverse(); + this.loanTransactionRepository.save(loanTransaction); + } } \ No newline at end of file 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 d1d8bed8d..e4633a2b0 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 @@ -135,4 +135,8 @@ public enum LoanStatus { public boolean isUnderTransfer() { return isTransferInProgress() || isTransferOnHold(); } + + 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 b83f622fe..f8953c220 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 @@ -137,6 +137,11 @@ public final class LoanTransaction extends AbstractPersistable { .getTotalPenaltyChargesOutstanding(), false, null); } + public static LoanTransaction refund(final Office office, final Money amount, final PaymentDetail paymentDetail, + final LocalDate paymentDate, final String externalId) { + return new LoanTransaction(null, office, LoanTransactionType.REFUND, paymentDetail, amount.getAmount(), paymentDate, externalId); + } + public static LoanTransaction copyTransactionProperties(LoanTransaction loanTransaction) { return new LoanTransaction(loanTransaction.loan, loanTransaction.office, loanTransaction.typeOf, loanTransaction.dateOf, loanTransaction.amount, loanTransaction.principalPortion, loanTransaction.interestPortion, @@ -446,5 +451,9 @@ public final class LoanTransaction extends AbstractPersistable { public String getExternalId() { return externalId; } + + public boolean isRefund(){ + return LoanTransactionType.REFUND.equals(getTypeOf()) && isNotReversed(); + } } \ No newline at end of file diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/LoanTransactionType.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/LoanTransactionType.java index f691ccda2..b8ee6fc53 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/LoanTransactionType.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/domain/LoanTransactionType.java @@ -32,7 +32,9 @@ public enum LoanTransactionType { INITIATE_TRANSFER(12, "loanTransactionType.initiateTransfer"), // APPROVE_TRANSFER(13, "loanTransactionType.approveTransfer"), // WITHDRAW_TRANSFER(14, "loanTransactionType.withdrawTransfer"), // - REJECT_TRANSFER(15, "loanTransactionType.rejectTransfer"); + REJECT_TRANSFER(15, "loanTransactionType.rejectTransfer"), + + REFUND(16,"loanTransactionType.refund"); private final Integer value; private final String code; @@ -101,6 +103,9 @@ public enum LoanTransactionType { case 15: loanTransactionType = LoanTransactionType.REJECT_TRANSFER; break; + case 16: + loanTransactionType = LoanTransactionType.REFUND; + break; default: loanTransactionType = LoanTransactionType.INVALID; break; diff --git a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java index 3035d3aaf..efcdd8538 100644 --- a/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java +++ b/mifosng-provider/src/main/java/org/mifosplatform/portfolio/loanaccount/service/LoanWritePlatformServiceJpaRepositoryImpl.java @@ -34,6 +34,8 @@ import org.mifosplatform.organisation.office.domain.Office; import org.mifosplatform.organisation.staff.domain.Staff; import org.mifosplatform.organisation.workingdays.domain.WorkingDays; import org.mifosplatform.organisation.workingdays.domain.WorkingDaysRepositoryWrapper; +import org.mifosplatform.portfolio.account.PortfolioAccountType; +import org.mifosplatform.portfolio.account.service.AccountTransfersWritePlatformService; import org.mifosplatform.portfolio.accountdetails.domain.AccountType; import org.mifosplatform.portfolio.calendar.domain.Calendar; import org.mifosplatform.portfolio.calendar.domain.CalendarEntityType; @@ -113,6 +115,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf private final ConfigurationDomainService configurationDomainService; private final WorkingDaysRepositoryWrapper workingDaysRepository; private final LoanProductReadPlatformService loanProductReadPlatformService; + private final AccountTransfersWritePlatformService accountTransfersWritePlatformService; @Autowired public LoanWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context, @@ -126,7 +129,8 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf final LoanScheduleGeneratorFactory loanScheduleFactory, final CalendarInstanceRepository calendarInstanceRepository, final PaymentDetailWritePlatformService paymentDetailWritePlatformService, final HolidayRepository holidayRepository, final ConfigurationDomainService configurationDomainService, final WorkingDaysRepositoryWrapper workingDaysRepository, - final LoanProductReadPlatformService loanProductReadPlatformService) { + final LoanProductReadPlatformService loanProductReadPlatformService, + final AccountTransfersWritePlatformService accountTransfersWritePlatformService) { this.context = context; this.loanEventApiJsonValidator = loanEventApiJsonValidator; this.loanAssembler = loanAssembler; @@ -146,6 +150,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf this.configurationDomainService = configurationDomainService; this.workingDaysRepository = workingDaysRepository; this.loanProductReadPlatformService = loanProductReadPlatformService; + this.accountTransfersWritePlatformService = accountTransfersWritePlatformService; } private LoanLifecycleStateMachine defaultLoanLifecycleStateMachine() { @@ -477,7 +482,6 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf } this.loanRepository.save(loan); - final String noteText = command.stringValueOfParameterNamed("note"); if (StringUtils.isNotBlank(noteText)) { changes.put("note", noteText); @@ -493,6 +497,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf } this.noteRepository.save(note); } + this.accountTransfersWritePlatformService.reverseTransfers(loanId, PortfolioAccountType.LOAN); postJournalEntries(loan, existingTransactionIds, existingReversedTransactionIds); 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 0aeecb9bb..37a2f750b 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 @@ -298,6 +298,10 @@ public class LoanEnumerations { optionData = new LoanTransactionEnumData(LoanTransactionType.REJECT_TRANSFER.getValue().longValue(), LoanTransactionType.REJECT_TRANSFER.getCode(), "Transfer Rejected"); break; + case REFUND: + optionData = new LoanTransactionEnumData(LoanTransactionType.REFUND.getValue().longValue(), + LoanTransactionType.REFUND.getCode(), "Transfer Refund"); + break; default: break; }