Merge pull request #890 from pramodn02/develop

MIFOSX-1163 : added functionality to transfer fixed deposit amount from ...
This commit is contained in:
Vishwas Babu A J
2014-05-04 14:21:28 +05:30
32 changed files with 438 additions and 233 deletions
+1 -1
View File
@@ -18542,7 +18542,7 @@ No Request Body:
<br/>
<table class=matrixHeading>
<tr class="matrixHeadingBG"><td><div class="mifosXHeading2">Optional Fields</div></td></tr>
<tr class=alt><td>accountNo, externalId, fieldOfficerId</td></tr>
<tr class=alt><td>accountNo, externalId, fieldOfficerId,linkAccountId</td></tr>
</table>
<br/>
<table class=matrixHeading>
@@ -109,7 +109,7 @@ public class FixedDepositTest {
Assert.assertNotNull(fixedDepositProductId);
Integer fixedDepositAccountId = applyForFixedDepositApplication(clientId.toString(), fixedDepositProductId.toString(), VALID_FROM,
VALID_TO, SUBMITTED_ON_DATE, WHOLE_TERM);
VALID_TO, SUBMITTED_ON_DATE, WHOLE_TERM, null);
Assert.assertNotNull(fixedDepositAccountId);
HashMap fixedDepositAccountStatusHashMap = FixedDepositAccountStatusChecker.getStatusOfFixedDepositAccount(this.requestSpec,
@@ -172,7 +172,7 @@ public class FixedDepositTest {
this.responseSpec, fixedDepositProductId.toString());
Integer fixedDepositAccountId = applyForFixedDepositApplication(clientId.toString(), fixedDepositProductId.toString(), VALID_FROM,
VALID_TO, SUBMITTED_ON_DATE, WHOLE_TERM);
VALID_TO, SUBMITTED_ON_DATE, WHOLE_TERM, null);
Assert.assertNotNull(fixedDepositAccountId);
todaysDate.add(Calendar.DATE, -1);
@@ -230,7 +230,7 @@ public class FixedDepositTest {
Assert.assertNotNull(fixedDepositProductId);
Integer fixedDepositAccountId = applyForFixedDepositApplication(clientId.toString(), fixedDepositProductId.toString(), VALID_FROM,
VALID_TO, SUBMITTED_ON_DATE, WHOLE_TERM);
VALID_TO, SUBMITTED_ON_DATE, WHOLE_TERM, null);
Assert.assertNotNull(fixedDepositAccountId);
HashMap fixedDepositAccountStatusHashMap = FixedDepositAccountStatusChecker.getStatusOfFixedDepositAccount(this.requestSpec,
@@ -311,7 +311,7 @@ public class FixedDepositTest {
Assert.assertNotNull(fixedDepositProductId);
Integer fixedDepositAccountId = applyForFixedDepositApplication(clientId.toString(), fixedDepositProductId.toString(), VALID_FROM,
VALID_TO, SUBMITTED_ON_DATE, WHOLE_TERM);
VALID_TO, SUBMITTED_ON_DATE, WHOLE_TERM, null);
Assert.assertNotNull(fixedDepositAccountId);
HashMap fixedDepositAccountStatusHashMap = FixedDepositAccountStatusChecker.getStatusOfFixedDepositAccount(this.requestSpec,
@@ -368,7 +368,7 @@ public class FixedDepositTest {
Assert.assertNotNull(fixedDepositProductId);
Integer fixedDepositAccountId = applyForFixedDepositApplication(clientId.toString(), fixedDepositProductId.toString(), VALID_FROM,
VALID_TO, SUBMITTED_ON_DATE, WHOLE_TERM);
VALID_TO, SUBMITTED_ON_DATE, WHOLE_TERM, null);
Assert.assertNotNull(fixedDepositAccountId);
HashMap fixedDepositAccountStatusHashMap = FixedDepositAccountStatusChecker.getStatusOfFixedDepositAccount(this.requestSpec,
@@ -410,7 +410,7 @@ public class FixedDepositTest {
Assert.assertNotNull(fixedDepositProductId);
Integer fixedDepositAccountId = applyForFixedDepositApplication(clientId.toString(), fixedDepositProductId.toString(), VALID_FROM,
VALID_TO, SUBMITTED_ON_DATE, WHOLE_TERM);
VALID_TO, SUBMITTED_ON_DATE, WHOLE_TERM, null);
Assert.assertNotNull(fixedDepositAccountId);
HashMap fixedDepositAccountStatusHashMap = FixedDepositAccountStatusChecker.getStatusOfFixedDepositAccount(this.requestSpec,
@@ -450,7 +450,7 @@ public class FixedDepositTest {
Assert.assertNotNull(fixedDepositProductId);
Integer fixedDepositAccountId = applyForFixedDepositApplication(clientId.toString(), fixedDepositProductId.toString(), VALID_FROM,
VALID_TO, SUBMITTED_ON_DATE, WHOLE_TERM);
VALID_TO, SUBMITTED_ON_DATE, WHOLE_TERM, null);
Assert.assertNotNull(fixedDepositAccountId);
HashMap fixedDepositAccountStatusHashMap = FixedDepositAccountStatusChecker.getStatusOfFixedDepositAccount(this.requestSpec,
@@ -488,7 +488,7 @@ public class FixedDepositTest {
Assert.assertNotNull(fixedDepositProductId);
Integer fixedDepositAccountId = applyForFixedDepositApplication(clientId.toString(), fixedDepositProductId.toString(), VALID_FROM,
VALID_TO, SUBMITTED_ON_DATE, WHOLE_TERM);
VALID_TO, SUBMITTED_ON_DATE, WHOLE_TERM, null);
Assert.assertNotNull(fixedDepositAccountId);
HashMap fixedDepositAccountStatusHashMap = FixedDepositAccountStatusChecker.getStatusOfFixedDepositAccount(this.requestSpec,
@@ -499,6 +499,64 @@ public class FixedDepositTest {
Assert.assertNotNull(fixedDepositAccountId);
}
@Test
public void testFixedDepositAccountWithLinkedAccount() {
this.fixedDepositProductHelper = new FixedDepositProductHelper(this.requestSpec, this.responseSpec);
this.accountHelper = new AccountHelper(this.requestSpec, this.responseSpec);
this.savingsAccountHelper = new SavingsAccountHelper(this.requestSpec, this.responseSpec);
this.fixedDepositAccountHelper = new FixedDepositAccountHelper(this.requestSpec, this.responseSpec);
FixedDepositAccountHelper fixedDepositAccountHelperValidationError = new FixedDepositAccountHelper(this.requestSpec,
new ResponseSpecBuilder().build());
DateFormat dateFormat = new SimpleDateFormat("dd MMMM yyyy");
DateFormat monthDayFormat = new SimpleDateFormat("dd MMM");
Calendar todaysDate = Calendar.getInstance();
todaysDate.add(Calendar.MONTH, -3);
final String VALID_FROM = dateFormat.format(todaysDate.getTime());
todaysDate.add(Calendar.YEAR, 10);
final String VALID_TO = dateFormat.format(todaysDate.getTime());
todaysDate = Calendar.getInstance();
todaysDate.add(Calendar.MONTH, -1);
final String SUBMITTED_ON_DATE = dateFormat.format(todaysDate.getTime());
final String APPROVED_ON_DATE = dateFormat.format(todaysDate.getTime());
final String ACTIVATION_DATE = dateFormat.format(todaysDate.getTime());
final String MONTH_DAY = monthDayFormat.format(todaysDate.getTime());
todaysDate.add(Calendar.MONTH, 1);
final String CLOSED_ON_DATE = dateFormat.format(todaysDate.getTime());
Integer clientId = ClientHelper.createClient(this.requestSpec, this.responseSpec);
Assert.assertNotNull(clientId);
Float balance = new Float(MINIMUM_OPENING_BALANCE) + new Float(FixedDepositAccountHelper.depositAmount);
final Integer savingsId = createSavings(clientId, String.valueOf(balance));
HashMap summary = savingsAccountHelper.getSavingsSummary(savingsId);
assertEquals("Verifying opening Balance", balance, summary.get("accountBalance"));
Integer fixedDepositProductId = createFixedDepositProduct(VALID_FROM, VALID_TO);
Assert.assertNotNull(fixedDepositProductId);
Integer fixedDepositAccountId = applyForFixedDepositApplication(clientId.toString(), fixedDepositProductId.toString(), VALID_FROM,
VALID_TO, SUBMITTED_ON_DATE, WHOLE_TERM, savingsId.toString());
Assert.assertNotNull(fixedDepositAccountId);
HashMap fixedDepositAccountStatusHashMap = FixedDepositAccountStatusChecker.getStatusOfFixedDepositAccount(this.requestSpec,
this.responseSpec, fixedDepositAccountId.toString());
FixedDepositAccountStatusChecker.verifyFixedDepositIsPending(fixedDepositAccountStatusHashMap);
fixedDepositAccountStatusHashMap = this.fixedDepositAccountHelper.approveFixedDeposit(fixedDepositAccountId, APPROVED_ON_DATE);
FixedDepositAccountStatusChecker.verifyFixedDepositIsApproved(fixedDepositAccountStatusHashMap);
fixedDepositAccountStatusHashMap = this.fixedDepositAccountHelper.activateFixedDeposit(fixedDepositAccountId, ACTIVATION_DATE);
FixedDepositAccountStatusChecker.verifyFixedDepositIsActive(fixedDepositAccountStatusHashMap);
summary = savingsAccountHelper.getSavingsSummary(savingsId);
balance = new Float(MINIMUM_OPENING_BALANCE);
assertEquals("Verifying opening Balance", balance, summary.get("accountBalance"));
}
private Integer createFixedDepositProduct(final String validFrom, final String validTo, Account... accounts) {
System.out.println("------------------------------CREATING NEW FIXED DEPOSIT PRODUCT ---------------------------------------");
FixedDepositProductHelper fixedDepositProductHelper = new FixedDepositProductHelper(this.requestSpec, this.responseSpec);
@@ -509,10 +567,12 @@ public class FixedDepositTest {
}
private Integer applyForFixedDepositApplication(final String clientID, final String productID, final String validFrom,
final String validTo, final String submittedOnDate, final String penalInterestType) {
final String validTo, final String submittedOnDate, final String penalInterestType, String savingsId) {
System.out.println("--------------------------------APPLYING FOR FIXED DEPOSIT ACCOUNT --------------------------------");
final String fixedDepositApplicationJSON = new FixedDepositAccountHelper(this.requestSpec, this.responseSpec) //
.withSubmittedOnDate(submittedOnDate).build(clientID, productID, validFrom, validTo, penalInterestType);
final String fixedDepositApplicationJSON = new FixedDepositAccountHelper(this.requestSpec, this.responseSpec)
//
.withSubmittedOnDate(submittedOnDate).withSavings(savingsId)
.build(clientID, productID, validFrom, validTo, penalInterestType);
return this.fixedDepositAccountHelper
.applyFixedDepositApplication(fixedDepositApplicationJSON, this.requestSpec, this.responseSpec);
}
@@ -528,4 +588,24 @@ public class FixedDepositTest {
.withMinimumOpenningBalance(minOpenningBalance).build();
return SavingsProductHelper.createSavingsProduct(savingsProductJSON, requestSpec, responseSpec);
}
private Integer createSavings(Integer clientID, String openningBalance) {
final Integer savingsProductID = createSavingsProduct(this.requestSpec, this.responseSpec, openningBalance);
Assert.assertNotNull(savingsProductID);
SavingsAccountHelper savingsAccountHelper = new SavingsAccountHelper(this.requestSpec, this.responseSpec);
final Integer savingsId = savingsAccountHelper.applyForSavingsApplication(clientID, savingsProductID, ACCOUNT_TYPE_INDIVIDUAL);
Assert.assertNotNull(savingsProductID);
HashMap savingsStatusHashMap = SavingsStatusChecker.getStatusOfSavings(this.requestSpec, this.responseSpec, savingsId);
SavingsStatusChecker.verifySavingsIsPending(savingsStatusHashMap);
savingsStatusHashMap = savingsAccountHelper.approveSavings(savingsId);
SavingsStatusChecker.verifySavingsIsApproved(savingsStatusHashMap);
savingsStatusHashMap = savingsAccountHelper.activateSavings(savingsId);
SavingsStatusChecker.verifySavingsIsActive(savingsStatusHashMap);
return savingsId;
}
}
@@ -78,10 +78,11 @@ public class FixedDepositAccountHelper {
private final boolean preClosurePenalApplicable = true;
private final boolean isActiveChart = true;
private final String currencyCode = USD;
private final String depositAmount = "100000";
public static final String depositAmount = "100000";
private final String depositPeriod = "14";
private final String depositPeriodFrequencyId = MONTHS;
private String submittedOnDate = "";
private String savingsId = null;
public String build(final String clientId, final String productId, final String validFrom, final String validTo,
final String penalInterestType) {
@@ -156,10 +157,11 @@ public class FixedDepositAccountHelper {
map.put("inMultiplesOfDepositTermTypeId", this.inMultiplesOfDepositTermTypeId);
map.put("preClosurePenalInterest", this.preClosurePenalInterest);
map.put("preClosurePenalInterestOnTypeId", penalInterestType);
map.put("depositAmount", this.depositAmount);
map.put("depositAmount", depositAmount);
map.put("depositPeriod", this.depositPeriod);
map.put("depositPeriodFrequencyId", this.depositPeriodFrequencyId);
map.put("submittedOnDate", this.submittedOnDate);
map.put("linkAccountId", savingsId);
String fixedDepositAccountJson = new Gson().toJson(map);
System.out.println(fixedDepositAccountJson);
@@ -211,9 +213,10 @@ public class FixedDepositAccountHelper {
+ Utils.TENANT_IDENTIFIER, fixedDepositApplicationJSON, CommonConstants.RESPONSE_CHANGES);
}
public HashMap updateInterestCalculationConfigForFixedDeposit(final String clientID, final String productID, final String accountID, final String submittedOnDate,
final String validFrom, final String validTo, final String numberOfDaysPerYear, final String penalInterestType,
final String interestCalculationType, final String interestCompoundingPeriodType, final String interestPostingPeriodType) {
public HashMap updateInterestCalculationConfigForFixedDeposit(final String clientID, final String productID, final String accountID,
final String submittedOnDate, final String validFrom, final String validTo, final String numberOfDaysPerYear,
final String penalInterestType, final String interestCalculationType, final String interestCompoundingPeriodType,
final String interestPostingPeriodType) {
final String fixedDepositApplicationJSON = new FixedDepositAccountHelper(this.requestSpec, this.responseSpec) //
.withSubmittedOnDate(submittedOnDate) //
@@ -425,4 +428,8 @@ public class FixedDepositAccountHelper {
return this;
}
public FixedDepositAccountHelper withSavings(final String savingsId) {
this.savingsId = savingsId;
return this;
}
}
@@ -9,6 +9,7 @@ import org.mifosplatform.portfolio.account.PortfolioAccountType;
import org.mifosplatform.portfolio.account.domain.AccountTransferDetails;
import org.mifosplatform.portfolio.loanaccount.domain.Loan;
import org.mifosplatform.portfolio.paymentdetail.domain.PaymentDetail;
import org.mifosplatform.portfolio.savings.domain.SavingsAccount;
public class AccountTransferDTO {
@@ -31,13 +32,14 @@ public class AccountTransferDTO {
private final String noteText;
private final String txnExternalId;
private final Loan loan;
private final SavingsAccount savingsAccount;
public AccountTransferDTO(final LocalDate transactionDate, final BigDecimal transactionAmount,
final PortfolioAccountType fromAccountType, final PortfolioAccountType toAccountType, final Long fromAccountId,
final Long toAccountId, final String description, final Locale locale, final DateTimeFormatter fmt,
final PaymentDetail paymentDetail, final Integer fromTransferType, final Integer toTransferType, final Long chargeId,
Integer loanInstallmentNumber, Integer transferType, final AccountTransferDetails accountTransferDetails,final String noteText,
final String txnExternalId,final Loan loan) {
Integer loanInstallmentNumber, Integer transferType, final AccountTransferDetails accountTransferDetails,
final String noteText, final String txnExternalId, final Loan loan, SavingsAccount savingsAccount) {
this.transactionDate = transactionDate;
this.transactionAmount = transactionAmount;
this.fromAccountType = fromAccountType;
@@ -57,6 +59,7 @@ public class AccountTransferDTO {
this.noteText = noteText;
this.txnExternalId = txnExternalId;
this.loan = loan;
this.savingsAccount = savingsAccount;
}
public LocalDate getTransactionDate() {
@@ -131,9 +134,12 @@ public class AccountTransferDTO {
return this.txnExternalId;
}
public Loan getLoan() {
return this.loan;
}
public SavingsAccount getSavingsAccount() {
return this.savingsAccount;
}
}
@@ -13,14 +13,17 @@ import org.springframework.data.jpa.domain.AbstractPersistable;
@Table(name = "m_portfolio_account_associations")
public class AccountAssociations extends AbstractPersistable<Long> {
@SuppressWarnings("unused")
@ManyToOne
@JoinColumn(name = "loan_account_id", nullable = true)
private Loan loanAccount;
@SuppressWarnings("unused")
@ManyToOne
@JoinColumn(name = "savings_account_id", nullable = true)
private SavingsAccount savingsAccount;
@SuppressWarnings("unused")
@ManyToOne
@JoinColumn(name = "linked_loan_account_id", nullable = true)
private Loan linkedLoanAccount;
@@ -43,6 +46,10 @@ public class AccountAssociations extends AbstractPersistable<Long> {
return new AccountAssociations(loan, null, null, savingsAccount);
}
public static AccountAssociations associateSavingsAccount(final SavingsAccount savingsAccount, final SavingsAccount linkedSavingsAccount) {
return new AccountAssociations(null, savingsAccount, null, linkedSavingsAccount);
}
public SavingsAccount linkedSavingsAccount() {
return this.linkedSavingsAccount;
}
@@ -11,4 +11,6 @@ public interface AccountAssociationsRepository extends JpaRepository<AccountAsso
@Query("from AccountAssociations aa where aa.loanAccount.id= :loanId")
AccountAssociations findByLoanId(@Param("loanId") Long loanId);
@Query("from AccountAssociations aa where aa.savingsAccount.id= :savingsId")
AccountAssociations findBySavingsId(@Param("savingsId") Long savingsId);
}
@@ -6,5 +6,7 @@ public interface AccountAssociationsReadPlatformService {
public PortfolioAccountData retriveLoanAssociation(final Long loanId);
public boolean isLinkedWithAnyActiveLoan(final Long savingsId);
public boolean isLinkedWithAnyActiveAccount(final Long savingsId);
public PortfolioAccountData retriveSavingsAssociation(final Long savingsId);
}
@@ -9,6 +9,7 @@ import org.mifosplatform.infrastructure.core.service.RoutingDataSource;
import org.mifosplatform.portfolio.account.data.AccountAssociationsData;
import org.mifosplatform.portfolio.account.data.PortfolioAccountData;
import org.mifosplatform.portfolio.loanaccount.domain.LoanStatus;
import org.mifosplatform.portfolio.savings.domain.SavingsAccountStatusType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@@ -43,22 +44,46 @@ public class AccountAssociationsReadPlatformServiceImpl implements AccountAssoci
}
return linkedAccount;
}
@Override
public PortfolioAccountData retriveSavingsAssociation(final Long savingsId) {
PortfolioAccountData linkedAccount = null;
final AccountAssociationsMapper mapper = new AccountAssociationsMapper();
final String sql = "select " + mapper.schema() + " where aa.savings_account_id = ? ";
try {
final AccountAssociationsData accountAssociationsData = this.jdbcTemplate.queryForObject(sql, mapper, savingsId);
if (accountAssociationsData != null) {
linkedAccount = accountAssociationsData.linkedAccount();
}
} catch (final EmptyResultDataAccessException e) {
logger.debug("Linking account is not configured");
}
return linkedAccount;
}
@Override
public boolean isLinkedWithAnyActiveLoan(final Long savingsId) {
boolean hasActiveLoan = false;
public boolean isLinkedWithAnyActiveAccount(final Long savingsId) {
boolean hasActiveAccount = false;
final String sql = "select loanAccount.loan_status_id as status from m_portfolio_account_associations aa "
+ "left join m_loan loanAccount on loanAccount.id = aa.loan_account_id " + "where aa.linked_savings_account_id = ?";
final List<Integer> statusList = this.jdbcTemplate.queryForList(sql, Integer.class, savingsId);
for (final Integer status : statusList) {
final LoanStatus loanStatus = LoanStatus.fromInt(status);
if (loanStatus.isActiveOrAwaitingApprovalOrDisbursal() || loanStatus.isUnderTransfer()) {
hasActiveLoan = true;
break;
}
if (loanStatus.isActiveOrAwaitingApprovalOrDisbursal() || loanStatus.isUnderTransfer()) { return true; }
}
return hasActiveLoan;
final String savsql = "select savingAccount.status_enum as status from m_portfolio_account_associations aa "
+ "left join m_savings_account savingAccount on savingAccount.id = aa.savings_account_id "
+ "where aa.linked_savings_account_id = ?";
final List<Integer> savstatusList = this.jdbcTemplate.queryForList(savsql, Integer.class, savingsId);
for (final Integer status : savstatusList) {
final SavingsAccountStatusType saveStatus = SavingsAccountStatusType.fromInt(status);
if (saveStatus.isActiveOrAwaitingApprovalOrDisbursal() || saveStatus.isUnderTransfer()) { return true; }
}
return hasActiveAccount;
}
private static final class AccountAssociationsMapper implements RowMapper<AccountAssociationsData> {
@@ -177,7 +177,7 @@ public class AccountTransfersReadPlatformServiceImpl implements AccountTransfers
final String currencyCode = excludeThisAccountFromOptions != null ? excludeThisAccountFromOptions.currencyCode() : null;
Collection<PortfolioAccountData> accountOptions = this.portfolioAccountReadPlatformService.retrieveAllForLookup(toAccountType,
toClientId, currencyCode, null);
toClientId, currencyCode, null, null);
if (!CollectionUtils.isEmpty(accountOptions)) {
accountOptions.remove(excludeThisAccountFromOptions);
} else {
@@ -268,7 +268,11 @@ public class AccountTransfersWritePlatformServiceImpl implements AccountTransfer
SavingsAccount toSavingsAccount = null;
if (accountTransferDetails == null) {
fromSavingsAccount = this.savingsAccountAssembler.assembleFrom(accountTransferDTO.getFromAccountId());
toSavingsAccount = this.savingsAccountAssembler.assembleFrom(accountTransferDTO.getToAccountId());
if (accountTransferDTO.getSavingsAccount() == null) {
toSavingsAccount = this.savingsAccountAssembler.assembleFrom(accountTransferDTO.getToAccountId());
} else {
toSavingsAccount = accountTransferDTO.getSavingsAccount();
}
} else {
fromSavingsAccount = accountTransferDetails.fromSavingsAccount();
this.savingsAccountAssembler.setHelpers(fromSavingsAccount);
@@ -17,5 +17,5 @@ public interface PortfolioAccountReadPlatformService {
Collection<PortfolioAccountData> retrieveAllForLookup(Integer toAccountType, Long toClientId, long[] accountStatus);
Collection<PortfolioAccountData> retrieveAllForLookup(Integer toAccountType, Long toClientId, String currencyCode, long[] accountStatus);
Collection<PortfolioAccountData> retrieveAllForLookup(Integer toAccountType, Long toClientId, String currencyCode, long[] accountStatus, Integer depositType);
}
@@ -8,7 +8,9 @@ package org.mifosplatform.portfolio.account.service;
import java.math.BigDecimal;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.mifosplatform.infrastructure.core.domain.JdbcSupport;
import org.mifosplatform.infrastructure.core.service.RoutingDataSource;
@@ -86,14 +88,15 @@ public class PortfolioAccountReadPlatformServiceImpl implements PortfolioAccount
@Override
public Collection<PortfolioAccountData> retrieveAllForLookup(final Integer accountTypeId, final Long clientId,
final long[] accountStatus) {
return retrieveAllForLookup(accountTypeId, clientId, null, accountStatus);
return retrieveAllForLookup(accountTypeId, clientId, null, accountStatus, null);
}
@Override
public Collection<PortfolioAccountData> retrieveAllForLookup(final Integer accountTypeId, final Long clientId,
final String currencyCode, final long[] accountStatus) {
final String currencyCode, final long[] accountStatus,final Integer depositType) {
Object[] sqlParams = new Object[] { clientId };
List<Object> sqlParams = new ArrayList<Object>();
sqlParams.add(clientId);
Collection<PortfolioAccountData> accounts = null;
String sql = null;
String defaultAccountStatus = "300";
@@ -112,20 +115,25 @@ public class PortfolioAccountReadPlatformServiceImpl implements PortfolioAccount
+ defaultAccountStatus.toString() + ")";
if (currencyCode != null) {
sql += " and la.currency_code = ?";
sqlParams = new Object[] { clientId, currencyCode };
sqlParams.add(currencyCode);
}
accounts = this.jdbcTemplate.query(sql, this.loanAccountMapper, sqlParams);
accounts = this.jdbcTemplate.query(sql, this.loanAccountMapper, sqlParams.toArray());
break;
case SAVINGS:
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.add(currencyCode);
}
if(depositType != null){
sql += " and sa.deposit_type_enum = ?";
sqlParams.add(depositType);
}
accounts = this.jdbcTemplate.query(sql, this.savingsAccountMapper, sqlParams);
accounts = this.jdbcTemplate.query(sql, this.savingsAccountMapper, sqlParams.toArray());
break;
default:
break;
@@ -229,7 +229,7 @@ public class StandingInstructionReadPlatformServiceImpl implements StandingInstr
final String currencyCode = excludeThisAccountFromOptions != null ? excludeThisAccountFromOptions.currencyCode() : null;
Collection<PortfolioAccountData> accountOptions = this.portfolioAccountReadPlatformService.retrieveAllForLookup(toAccountType,
toClientId, currencyCode, null);
toClientId, currencyCode, null, null);
if (!CollectionUtils.isEmpty(accountOptions)) {
accountOptions.remove(excludeThisAccountFromOptions);
} else {
@@ -217,7 +217,7 @@ public class StandingInstructionWritePlatformServiceImpl implements StandingInst
AccountTransferDTO accountTransferDTO = new AccountTransferDTO(transactionDate, transactionAmount, data.fromAccountType(),
data.toAccountType(), data.fromAccount().accountId(), data.toAccount().accountId(), data.name()
+ " Standing instruction trasfer ", null, null, null, null, data.toTransferType(), null, null, data
.transferType().getValue(), accountTransferDetails, null, null, null);
.transferType().getValue(), accountTransferDetails, null, null, null, null);
transferAmount(sb, accountTransferDTO, data.getId());
}
}
@@ -85,6 +85,7 @@ import org.mifosplatform.portfolio.loanproduct.service.LoanProductReadPlatformSe
import org.mifosplatform.portfolio.note.data.NoteData;
import org.mifosplatform.portfolio.note.domain.NoteType;
import org.mifosplatform.portfolio.note.service.NoteReadPlatformServiceImpl;
import org.mifosplatform.portfolio.savings.DepositAccountType;
import org.mifosplatform.portfolio.savings.domain.SavingsAccountStatusType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
@@ -265,7 +266,8 @@ public class LoansApiResource {
}
final long[] accountStatus = { SavingsAccountStatusType.ACTIVE.getValue() };
accountLinkingOptions = this.portfolioAccountReadPlatformService.retrieveAllForLookup(
PortfolioAccountType.SAVINGS.getValue(), clientId, currencyCode, accountStatus);
PortfolioAccountType.SAVINGS.getValue(), clientId, currencyCode, accountStatus,
DepositAccountType.SAVINGS_DEPOSIT.getValue());
}
@@ -428,7 +430,7 @@ public class LoansApiResource {
}
final long[] accountStatus = { SavingsAccountStatusType.ACTIVE.getValue() };
accountLinkingOptions = this.portfolioAccountReadPlatformService.retrieveAllForLookup(PortfolioAccountType.SAVINGS.getValue(),
loanBasicDetails.clientId(), currencyCode, accountStatus);
loanBasicDetails.clientId(), currencyCode, accountStatus, DepositAccountType.SAVINGS_DEPOSIT.getValue());
if (!associationParameters.contains("linkedAccount")) {
mandatoryResponseParameters.add("linkedAccount");
@@ -252,7 +252,7 @@ public final class LoanApplicationCommandFromApiJsonHelper {
.integerGreaterThanZero();
final String linkAccountIdParameterName = "linkAccountId";
if (this.fromApiJsonHelper.parameterExists(submittedOnNoteParameterName, element)) {
if (this.fromApiJsonHelper.parameterExists(linkAccountIdParameterName, element)) {
final Long linkAccountId = this.fromApiJsonHelper.extractLongNamed(linkAccountIdParameterName, element);
baseDataValidator.reset().parameter(linkAccountIdParameterName).value(linkAccountId).ignoreIfNull().longGreaterThanZero();
}
@@ -322,7 +322,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
final AccountTransferDTO accountTransferDTO = new AccountTransferDTO(actualDisbursementDate, entrySet.getValue(),
PortfolioAccountType.SAVINGS, PortfolioAccountType.LOAN, savingAccountData.accountId(), loanId, "Loan Charge Payment",
locale, fmt, null, null, LoanTransactionType.REPAYMENT_AT_DISBURSEMENT.getValue(), entrySet.getKey(), null,
AccountTransferType.CHARGE_PAYMENT.getValue(), null, null, null, null);
AccountTransferType.CHARGE_PAYMENT.getValue(), null, null, null, null, null);
this.accountTransfersWritePlatformService.transferFunds(accountTransferDTO);
}
@@ -494,7 +494,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
final AccountTransferDTO accountTransferDTO = new AccountTransferDTO(actualDisbursementDate, entrySet.getValue(),
PortfolioAccountType.SAVINGS, PortfolioAccountType.LOAN, savingAccountData.accountId(), loan.getId(),
"Loan Charge Payment", locale, fmt, null, null, LoanTransactionType.REPAYMENT_AT_DISBURSEMENT.getValue(),
entrySet.getKey(), null, AccountTransferType.CHARGE_PAYMENT.getValue(), null, null, null, null);
entrySet.getKey(), null, AccountTransferType.CHARGE_PAYMENT.getValue(), null, null, null, null, null);
this.accountTransfersWritePlatformService.transferFunds(accountTransferDTO);
}
}
@@ -1253,7 +1253,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
final AccountTransferDTO accountTransferDTO = new AccountTransferDTO(transactionDate, amount, PortfolioAccountType.SAVINGS,
PortfolioAccountType.LOAN, portfolioAccountData.accountId(), loanId, "Loan Charge Payment", locale, fmt, null, null,
LoanTransactionType.CHARGE_PAYMENT.getValue(), loanChargeId, loanInstallmentNumber,
AccountTransferType.CHARGE_PAYMENT.getValue(), null, null, null, null);
AccountTransferType.CHARGE_PAYMENT.getValue(), null, null, null, null, null);
this.accountTransfersWritePlatformService.transferFunds(accountTransferDTO);
return new CommandProcessingResultBuilder() //
@@ -1282,7 +1282,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
final AccountTransferDTO accountTransferDTO = new AccountTransferDTO(transactionDate, amount.getAmount(),
PortfolioAccountType.LOAN, PortfolioAccountType.SAVINGS, loan.getId(), portfolioAccountData.accountId(),
"Loan Disbursement", locale, fmt, paymentDetail, LoanTransactionType.DISBURSEMENT.getValue(), null, null, null,
AccountTransferType.ACCOUNT_TRANSFER.getValue(), null, null, txnExternalId, loan);
AccountTransferType.ACCOUNT_TRANSFER.getValue(), null, null, txnExternalId, loan, null);
this.accountTransfersWritePlatformService.transferFunds(accountTransferDTO);
}
@@ -1310,7 +1310,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
portfolioAccountData.accountId(), chargeData.getLoanId(), "Loan Charge Payment", null, null, null,
null, LoanTransactionType.CHARGE_PAYMENT.getValue(), chargeData.getId(),
installmentChargeData.getInstallmentNumber(), AccountTransferType.CHARGE_PAYMENT.getValue(), null,
null, null, null);
null, null, null, null);
transferFeeCharge(sb, accountTransferDTO);
}
}
@@ -1321,7 +1321,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
chargeData.getAmountOutstanding(), PortfolioAccountType.SAVINGS, PortfolioAccountType.LOAN,
portfolioAccountData.accountId(), chargeData.getLoanId(), "Loan Charge Payment", null, null, null, null,
LoanTransactionType.CHARGE_PAYMENT.getValue(), chargeData.getId(), null,
AccountTransferType.CHARGE_PAYMENT.getValue(), null, null, null, null);
AccountTransferType.CHARGE_PAYMENT.getValue(), null, null, null, null, null);
transferFeeCharge(sb, accountTransferDTO);
}
}
@@ -2033,7 +2033,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
final AccountTransferDTO accountTransferDTO = new AccountTransferDTO(transactionDate, amount, PortfolioAccountType.SAVINGS,
PortfolioAccountType.LOAN, portfolioAccountData.accountId(), loanId, "Loan Charge Payment", locale, fmt, null, null,
LoanTransactionType.CHARGE_PAYMENT.getValue(), loanChargeId, loanInstallmentNumber,
AccountTransferType.CHARGE_PAYMENT.getValue(), null, null, null, null);
AccountTransferType.CHARGE_PAYMENT.getValue(), null, null, null, null, null);
this.accountTransfersWritePlatformService.transferFunds(accountTransferDTO);
return transaction;
@@ -178,6 +178,8 @@ public class DepositsApiConstants {
public static final String preMatureCloseOnDateParamName = "preMatureCloseOnDate";
public static final String linkedAccountParamName = "linkAccountId";
// template
public static final String chartTemplate = "chartTemplate";
@@ -295,6 +297,7 @@ public class DepositsApiConstants {
fixedDepositRequestData.addAll(DEPOSIT_ACCOUNT_REQUEST_DATA_PARAMETERS);
fixedDepositRequestData.addAll(PRECLOSURE_REQUEST_DATA_PARAMETERS);
fixedDepositRequestData.addAll(DEPOSIT_TERM_REQUEST_DATA_PARAMETERS);
fixedDepositRequestData.add(linkedAccountParamName);
return fixedDepositRequestData;
}
@@ -303,6 +306,7 @@ public class DepositsApiConstants {
fixedDepositResponseData.addAll(DEPOSIT_ACCOUNT_REQUEST_DATA_PARAMETERS);
fixedDepositResponseData.addAll(PRECLOSURE_RESPONSE_DATA_PARAMETERS);
fixedDepositResponseData.addAll(DEPOSIT_TERM_RESPONSE_DATA_PARAMETERS);
fixedDepositResponseData.add(linkedAccountParamName);
return fixedDepositResponseData;
}
@@ -130,6 +130,7 @@ public class SavingsApiConstants {
// Savings account associations
public static final String transactions = "transactions";
public static final String charges = "charges";
public static final String linkedAccount = "linkedAccount";
public static final Set<String> SAVINGS_PRODUCT_REQUEST_DATA_PARAMETERS = new HashSet<String>(Arrays.asList(localeParamName,
monthDayFormatParamName, nameParamName, shortNameParamName, descriptionParamName, currencyCodeParamName,
@@ -39,6 +39,8 @@ import org.mifosplatform.infrastructure.core.serialization.DefaultToApiJsonSeria
import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper;
import org.mifosplatform.infrastructure.core.service.Page;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.mifosplatform.portfolio.account.data.PortfolioAccountData;
import org.mifosplatform.portfolio.account.service.AccountAssociationsReadPlatformService;
import org.mifosplatform.portfolio.savings.DepositAccountType;
import org.mifosplatform.portfolio.savings.DepositsApiConstants;
import org.mifosplatform.portfolio.savings.SavingsApiConstants;
@@ -69,6 +71,7 @@ public class FixedDepositAccountsApiResource {
private final SavingsAccountChargeReadPlatformService savingsAccountChargeReadPlatformService;
private final FromJsonHelper fromJsonHelper;
private final DepositAccountPreMatureCalculationPlatformService accountPreMatureCalculationPlatformService;
private final AccountAssociationsReadPlatformService accountAssociationsReadPlatformService;
@Autowired
public FixedDepositAccountsApiResource(final DepositAccountReadPlatformService depositAccountReadPlatformService,
@@ -76,7 +79,8 @@ public class FixedDepositAccountsApiResource {
final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService,
final ApiRequestParameterHelper apiRequestParameterHelper,
final SavingsAccountChargeReadPlatformService savingsAccountChargeReadPlatformService, final FromJsonHelper fromJsonHelper,
final DepositAccountPreMatureCalculationPlatformService accountPreMatureCalculationPlatformService) {
final DepositAccountPreMatureCalculationPlatformService accountPreMatureCalculationPlatformService,
final AccountAssociationsReadPlatformService accountAssociationsReadPlatformService) {
this.depositAccountReadPlatformService = depositAccountReadPlatformService;
this.context = context;
this.toApiJsonSerializer = toApiJsonSerializer;
@@ -85,6 +89,7 @@ public class FixedDepositAccountsApiResource {
this.savingsAccountChargeReadPlatformService = savingsAccountChargeReadPlatformService;
this.fromJsonHelper = fromJsonHelper;
this.accountPreMatureCalculationPlatformService = accountPreMatureCalculationPlatformService;
this.accountAssociationsReadPlatformService = accountAssociationsReadPlatformService;
}
@GET
@@ -170,12 +175,14 @@ public class FixedDepositAccountsApiResource {
Collection<SavingsAccountTransactionData> transactions = null;
Collection<SavingsAccountChargeData> charges = null;
PortfolioAccountData linkedAccount = null;
final Set<String> associationParameters = ApiParameterHelper.extractAssociationsForResponseIfProvided(uriInfo.getQueryParameters());
if (!associationParameters.isEmpty()) {
if (associationParameters.contains("all")) {
associationParameters.addAll(Arrays.asList(SavingsApiConstants.transactions, SavingsApiConstants.charges));
associationParameters.addAll(Arrays.asList(SavingsApiConstants.transactions, SavingsApiConstants.charges,
SavingsApiConstants.linkedAccount));
}
if (associationParameters.contains(SavingsApiConstants.transactions)) {
@@ -195,6 +202,11 @@ public class FixedDepositAccountsApiResource {
charges = currentCharges;
}
}
if (associationParameters.contains(SavingsApiConstants.linkedAccount)) {
mandatoryResponseParameters.add(SavingsApiConstants.linkedAccount);
linkedAccount = this.accountAssociationsReadPlatformService.retriveSavingsAssociation(accountId);
}
}
FixedDepositAccountData templateData = null;
@@ -206,7 +218,7 @@ public class FixedDepositAccountsApiResource {
staffInSelectedOfficeOnly);
}
return FixedDepositAccountData.withTemplateOptions(savingsAccount, templateData, transactions, charges);
return FixedDepositAccountData.associationsAndTemplate(savingsAccount, templateData, transactions, charges, linkedAccount);
}
@PUT
@@ -5,11 +5,9 @@
*/
package org.mifosplatform.portfolio.savings.data;
import static org.mifosplatform.portfolio.savings.DepositsApiConstants.minDepositTermTypeIdParamName;
import static org.mifosplatform.portfolio.savings.DepositsApiConstants.maxDepositTermTypeIdParamName;
import static org.mifosplatform.portfolio.savings.DepositsApiConstants.depositAmountParamName;
import static org.mifosplatform.portfolio.savings.DepositsApiConstants.depositPeriodParamName;
import static org.mifosplatform.portfolio.savings.DepositsApiConstants.depositPeriodFrequencyIdParamName;
import static org.mifosplatform.portfolio.savings.DepositsApiConstants.depositPeriodParamName;
import static org.mifosplatform.portfolio.savings.DepositsApiConstants.inMultiplesOfDepositTermParamName;
import static org.mifosplatform.portfolio.savings.DepositsApiConstants.inMultiplesOfDepositTermTypeIdParamName;
import static org.mifosplatform.portfolio.savings.DepositsApiConstants.interestFreeFromPeriodParamName;
@@ -17,7 +15,9 @@ import static org.mifosplatform.portfolio.savings.DepositsApiConstants.interestF
import static org.mifosplatform.portfolio.savings.DepositsApiConstants.interestFreePeriodFrequencyTypeIdParamName;
import static org.mifosplatform.portfolio.savings.DepositsApiConstants.interestFreeToPeriodParamName;
import static org.mifosplatform.portfolio.savings.DepositsApiConstants.maxDepositTermParamName;
import static org.mifosplatform.portfolio.savings.DepositsApiConstants.maxDepositTermTypeIdParamName;
import static org.mifosplatform.portfolio.savings.DepositsApiConstants.minDepositTermParamName;
import static org.mifosplatform.portfolio.savings.DepositsApiConstants.minDepositTermTypeIdParamName;
import static org.mifosplatform.portfolio.savings.DepositsApiConstants.preClosurePenalApplicableParamName;
import static org.mifosplatform.portfolio.savings.DepositsApiConstants.preClosurePenalInterestOnTypeIdParamName;
import static org.mifosplatform.portfolio.savings.DepositsApiConstants.preClosurePenalInterestParamName;
@@ -44,6 +44,7 @@ import static org.mifosplatform.portfolio.savings.SavingsApiConstants.minRequire
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.nominalAnnualInterestRateParamName;
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.productIdParamName;
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.submittedOnDateParamName;
import static org.mifosplatform.portfolio.savings.DepositsApiConstants.linkedAccountParamName;
import java.lang.reflect.Type;
import java.math.BigDecimal;
@@ -70,6 +71,7 @@ import org.mifosplatform.portfolio.savings.SavingsInterestCalculationDaysInYearT
import org.mifosplatform.portfolio.savings.SavingsInterestCalculationType;
import org.mifosplatform.portfolio.savings.SavingsPeriodFrequencyType;
import org.mifosplatform.portfolio.savings.SavingsPostingInterestPeriodType;
import org.mifosplatform.portfolio.savings.domain.SavingsAccount;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@@ -276,6 +278,11 @@ public class DepositAccountDataValidator {
.integerZeroOrGreater();
}
}
if (this.fromApiJsonHelper.parameterExists(linkedAccountParamName, element)) {
final Long linkAccountId = this.fromApiJsonHelper.extractLongNamed(linkedAccountParamName, element);
baseDataValidator.reset().parameter(linkedAccountParamName).value(linkAccountId).ignoreIfNull().longGreaterThanZero();
}
}
private void validateDepositDetailsForUpdate(final JsonElement element, final DataValidatorBuilder baseDataValidator) {
@@ -393,6 +400,11 @@ public class DepositAccountDataValidator {
baseDataValidator.reset().parameter(lockinPeriodFrequencyTypeParamName).value(lockinPeriodFrequencyType).inMinMaxRange(0, 3);
}
if (this.fromApiJsonHelper.parameterExists(linkedAccountParamName, element)) {
final Long linkAccountId = this.fromApiJsonHelper.extractLongNamed(linkedAccountParamName, element);
baseDataValidator.reset().parameter(linkedAccountParamName).value(linkAccountId).ignoreIfNull().longGreaterThanZero();
}
}
private void validatePreClosureDetailForSubmit(final JsonElement element, final DataValidatorBuilder baseDataValidator) {
@@ -464,7 +476,7 @@ public class DepositAccountDataValidator {
baseDataValidator.reset().parameter(minDepositTermTypeIdParamName).value(minDepositTermType)
.isOneOfTheseValues(SavingsPeriodFrequencyType.integerValues());
}
if (fromApiJsonHelper.parameterExists(maxDepositTermTypeIdParamName, element)) {
final Integer maxDepositTermType = this.fromApiJsonHelper.extractIntegerSansLocaleNamed(maxDepositTermTypeIdParamName, element);
baseDataValidator.reset().parameter(maxDepositTermTypeIdParamName).value(maxDepositTermType)
@@ -555,6 +567,24 @@ public class DepositAccountDataValidator {
}
}
public void validatelinkedSavingsAccount(final SavingsAccount linkedSavingsAccount, final SavingsAccount savingsAccount) {
final List<ApiParameterError> dataValidationErrors = new ArrayList<ApiParameterError>();
if (linkedSavingsAccount.isNotActive()) {
final ApiParameterError error = ApiParameterError.parameterError("validation.msg.loan.linked.savings.account.is.not.active",
"Linked Savings account with id:" + linkedSavingsAccount.getId() + " is not in active state", "linkAccountId",
linkedSavingsAccount.getId());
dataValidationErrors.add(error);
} else if (savingsAccount.clientId() != linkedSavingsAccount.clientId()) {
final ApiParameterError error = ApiParameterError.parameterError(
"validation.msg.loan.linked.savings.account.not.belongs.to.same.client", "Linked Savings account with id:"
+ linkedSavingsAccount.getId() + " is not belongs to the same client", "linkAccountId",
linkedSavingsAccount.getId());
dataValidationErrors.add(error);
}
if (!dataValidationErrors.isEmpty()) { throw new PlatformApiDataValidationException("validation.msg.validation.errors.exist",
"Validation errors exist.", dataValidationErrors); }
}
private void validateSavingsCharges(final JsonElement element, final DataValidatorBuilder baseDataValidator) {
if (element.isJsonObject()) {
@@ -15,6 +15,7 @@ import org.mifosplatform.infrastructure.codes.data.CodeValueData;
import org.mifosplatform.infrastructure.core.data.EnumOptionData;
import org.mifosplatform.organisation.monetary.data.CurrencyData;
import org.mifosplatform.organisation.staff.data.StaffData;
import org.mifosplatform.portfolio.account.data.PortfolioAccountData;
import org.mifosplatform.portfolio.charge.data.ChargeData;
import org.mifosplatform.portfolio.savings.DepositAccountType;
import org.mifosplatform.portfolio.savings.service.SavingsEnumerations;
@@ -47,6 +48,8 @@ public class FixedDepositAccountData extends DepositAccountData {
// used for account close
private EnumOptionData onAccountClosure;
private final PortfolioAccountData linkedAccount;
private Collection<EnumOptionData> interestFreePeriodTypeOptions;
private Collection<EnumOptionData> preClosurePenalInterestOnTypeOptions;
private Collection<EnumOptionData> depositTermTypeOptions;
@@ -67,6 +70,7 @@ public class FixedDepositAccountData extends DepositAccountData {
final LocalDate maturityDate, final Integer depositPeriod, final EnumOptionData depositPeriodFrequency,
final EnumOptionData onAccountClosure) {
final PortfolioAccountData linkedAccount = null;
final Collection<EnumOptionData> interestFreePeriodTypeOptions = null;
final Collection<EnumOptionData> preClosurePenalInterestOnTypeOptions = null;
final Collection<EnumOptionData> depositTermTypeOptions = null;
@@ -97,7 +101,7 @@ public class FixedDepositAccountData extends DepositAccountData {
maxDepositTermType, inMultiplesOfDepositTerm, inMultiplesOfDepositTermType, depositAmount, maturityAmount, maturityDate,
depositPeriod, depositPeriodFrequency, depositTermTypeOptions, inMultiplesOfDepositTermTypeOptions,
depositPeriodFrequencyOptions, depositType, onAccountClosure, onAccountClosureOptions, paymentTypeOptions,
savingsAccountDatas);
savingsAccountDatas, linkedAccount);
}
public static FixedDepositAccountData withInterestChart(final FixedDepositAccountData account,
@@ -119,35 +123,15 @@ public class FixedDepositAccountData extends DepositAccountData {
account.inMultiplesOfDepositTerm, account.inMultiplesOfDepositTermType, account.depositAmount, account.maturityAmount,
account.maturityDate, account.depositPeriod, account.depositPeriodFrequency, account.depositTermTypeOptions,
account.inMultiplesOfDepositTermTypeOptions, account.depositTermTypeOptions, account.depositType, account.onAccountClosure,
account.onAccountClosureOptions, account.paymentTypeOptions, account.savingsAccounts);
account.onAccountClosureOptions, account.paymentTypeOptions, account.savingsAccounts, account.linkedAccount);
}
public static FixedDepositAccountData withTemplateOptions(final FixedDepositAccountData account,
final FixedDepositAccountData template, final Collection<SavingsAccountTransactionData> transactions,
final Collection<SavingsAccountChargeData> charges) {
public static FixedDepositAccountData associationsAndTemplate(final FixedDepositAccountData account, FixedDepositAccountData template,
final Collection<SavingsAccountTransactionData> transactions, final Collection<SavingsAccountChargeData> charges,
final PortfolioAccountData linkedAccount) {
if (template == null) {
final Collection<DepositProductData> productOptions = null;
final Collection<StaffData> fieldOfficerOptions = null;
final Collection<EnumOptionData> interestCompoundingPeriodTypeOptions = null;
final Collection<EnumOptionData> interestPostingPeriodTypeOptions = null;
final Collection<EnumOptionData> interestCalculationTypeOptions = null;
final Collection<EnumOptionData> interestCalculationDaysInYearTypeOptions = null;
final Collection<EnumOptionData> lockinPeriodFrequencyTypeOptions = null;
final Collection<EnumOptionData> withdrawalFeeTypeOptions = null;
final Collection<ChargeData> chargeOptions = null;
final Collection<EnumOptionData> interestFreePeriodTypeOptions = null;
final Collection<EnumOptionData> preClosurePenalInterestOnTypeOptions = null;
final Collection<EnumOptionData> depositTermTypeOptions = null;
final Collection<EnumOptionData> inMultiplesOfDepositTermTypeOptions = null;
final Collection<EnumOptionData> depositPeriodFrequencyOptions = null;
return withTemplateOptions(account, productOptions, fieldOfficerOptions, interestCompoundingPeriodTypeOptions,
interestPostingPeriodTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions,
lockinPeriodFrequencyTypeOptions, withdrawalFeeTypeOptions, transactions, charges, chargeOptions,
interestFreePeriodTypeOptions, preClosurePenalInterestOnTypeOptions, depositTermTypeOptions,
inMultiplesOfDepositTermTypeOptions, depositPeriodFrequencyOptions);
template = account;
}
return new FixedDepositAccountData(account.id, account.accountNo, account.externalId, account.groupId, account.groupName,
@@ -168,7 +152,7 @@ public class FixedDepositAccountData extends DepositAccountData {
account.maturityAmount, account.maturityDate, account.depositPeriod, account.depositPeriodFrequency,
template.depositTermTypeOptions, template.inMultiplesOfDepositTermTypeOptions, template.depositPeriodFrequencyOptions,
account.depositType, account.onAccountClosure, account.onAccountClosureOptions, account.paymentTypeOptions,
account.savingsAccounts);
template.savingsAccounts, linkedAccount);
}
public static FixedDepositAccountData withTemplateOptions(final FixedDepositAccountData account,
@@ -182,7 +166,7 @@ public class FixedDepositAccountData extends DepositAccountData {
final Collection<ChargeData> chargeOptions, final Collection<EnumOptionData> interestFreePeriodTypeOptions,
final Collection<EnumOptionData> preClosurePenalInterestOnTypeOptions, final Collection<EnumOptionData> depositTermTypeOptions,
final Collection<EnumOptionData> inMultiplesOfDepositTermTypeOptions,
final Collection<EnumOptionData> depositPeriodFrequencyOptions) {
final Collection<EnumOptionData> depositPeriodFrequencyOptions, final Collection<SavingsAccountData> savingsAccounts) {
return new FixedDepositAccountData(account.id, account.accountNo, account.externalId, account.groupId, account.groupName,
account.clientId, account.clientName, account.savingsProductId, account.savingsProductName, account.fieldOfficerId,
@@ -200,7 +184,7 @@ public class FixedDepositAccountData extends DepositAccountData {
account.inMultiplesOfDepositTerm, account.inMultiplesOfDepositTermType, account.depositAmount, account.maturityAmount,
account.maturityDate, account.depositPeriod, account.depositPeriodFrequency, depositTermTypeOptions,
inMultiplesOfDepositTermTypeOptions, depositPeriodFrequencyOptions, account.depositType, account.onAccountClosure,
account.onAccountClosureOptions, account.paymentTypeOptions, account.savingsAccounts);
account.onAccountClosureOptions, account.paymentTypeOptions, savingsAccounts, account.linkedAccount);
}
public static FixedDepositAccountData withClientTemplate(final Long clientId, final String clientName, final Long groupId,
@@ -261,6 +245,7 @@ public class FixedDepositAccountData extends DepositAccountData {
final Integer depositPeriod = null;
final EnumOptionData depositPeriodFrequency = null;
final EnumOptionData onAccountClosure = null;
final PortfolioAccountData linkedAccount = null;
final Collection<EnumOptionData> interestFreePeriodTypeOptions = null;
final Collection<EnumOptionData> preClosurePenalInterestOnTypeOptions = null;
@@ -284,7 +269,7 @@ public class FixedDepositAccountData extends DepositAccountData {
preClosurePenalInterestOnTypeOptions, minDepositTerm, maxDepositTerm, minDepositTermType, maxDepositTermType,
inMultiplesOfDepositTerm, inMultiplesOfDepositTermType, depositAmount, maturityAmount, maturityDate, depositPeriod,
depositPeriodFrequency, depositTermTypeOptions, inMultiplesOfDepositTermTypeOptions, depositPeriodFrequencyOptions,
depositType, onAccountClosure, onAccountClosureOptions, paymentTypeOptions, savingsAccountDatas);
depositType, onAccountClosure, onAccountClosureOptions, paymentTypeOptions, savingsAccountDatas, linkedAccount);
}
public static FixedDepositAccountData preClosureDetails(final Long accountId, BigDecimal maturityAmount,
@@ -355,6 +340,7 @@ public class FixedDepositAccountData extends DepositAccountData {
final Collection<EnumOptionData> inMultiplesOfDepositTermTypeOptions = null;
final Collection<EnumOptionData> depositPeriodFrequencyOptions = null;
final EnumOptionData depositType = SavingsEnumerations.depositType(DepositAccountType.FIXED_DEPOSIT.getValue());
final PortfolioAccountData linkedAccount = null;
return new FixedDepositAccountData(accountId, accountNo, externalId, groupId, groupName, clientId, clientName, productId,
productName, fieldOfficerId, fieldOfficerName, status, timeline, currency, nominalAnnualInterestRate, interestPeriodType,
@@ -368,7 +354,7 @@ public class FixedDepositAccountData extends DepositAccountData {
preClosurePenalInterestOnTypeOptions, minDepositTerm, maxDepositTerm, minDepositTermType, maxDepositTermType,
inMultiplesOfDepositTerm, inMultiplesOfDepositTermType, depositAmount, maturityAmount, maturityDate, depositPeriod,
depositPeriodFrequency, depositTermTypeOptions, inMultiplesOfDepositTermTypeOptions, depositPeriodFrequencyOptions,
depositType, onAccountClosure, onAccountClosureOptions, paymentTypeOptions, savingsAccountDatas);
depositType, onAccountClosure, onAccountClosureOptions, paymentTypeOptions, savingsAccountDatas, linkedAccount);
}
public static FixedDepositAccountData withClosureTemplateDetails(final FixedDepositAccountData account,
@@ -392,7 +378,7 @@ public class FixedDepositAccountData extends DepositAccountData {
account.inMultiplesOfDepositTerm, account.inMultiplesOfDepositTermType, account.depositAmount, account.maturityAmount,
account.maturityDate, account.depositPeriod, account.depositPeriodFrequency, account.depositTermTypeOptions,
account.inMultiplesOfDepositTermTypeOptions, account.depositPeriodFrequencyOptions, account.depositType,
account.onAccountClosure, onAccountClosureOptions, paymentTypeOptions, savingsAccountDatas);
account.onAccountClosure, onAccountClosureOptions, paymentTypeOptions, savingsAccountDatas, account.linkedAccount);
}
private FixedDepositAccountData(final Long id, final String accountNo, final String externalId, final Long groupId,
@@ -424,7 +410,8 @@ public class FixedDepositAccountData extends DepositAccountData {
final Collection<EnumOptionData> inMultiplesOfDepositTermTypeOptions,
final Collection<EnumOptionData> depositPeriodFrequencyOptions, final EnumOptionData depositType,
final EnumOptionData onAccountClosure, final Collection<EnumOptionData> onAccountClosureOptions,
final Collection<CodeValueData> paymentTypeOptions, final Collection<SavingsAccountData> savingsAccountDatas) {
final Collection<CodeValueData> paymentTypeOptions, final Collection<SavingsAccountData> savingsAccountDatas,
final PortfolioAccountData linkedAccount) {
super(id, accountNo, externalId, groupId, groupName, clientId, clientName, productId, productName, fieldofficerId,
fieldofficerName, status, timeline, currency, nominalAnnualInterestRate, interestPeriodType, interestPostingPeriodType,
@@ -454,6 +441,7 @@ public class FixedDepositAccountData extends DepositAccountData {
this.depositPeriod = depositPeriod;
this.depositPeriodFrequency = depositPeriodFrequency;
this.onAccountClosure = onAccountClosure;
this.linkedAccount = linkedAccount;
// template
this.interestFreePeriodTypeOptions = interestFreePeriodTypeOptions;
@@ -185,9 +185,13 @@ public class DepositAccountDomainServiceJpa implements DepositAccountDomainServi
final LocalDate transactionStartDate = reinvestedDeposit.getActivationLocalDate();
final LocalDate nextTransactionStartDate = reinvestedDeposit.nextDepositDate(transactionStartDate);
reinvestedDeposit.updateMaturityDateAndAmount(mc, nextTransactionStartDate);
reinvestedDeposit.processAccountUponActivation(fmt);
this.savingsAccountRepository.save(reinvestedDeposit);
Money amountForDeposit = reinvestedDeposit.activateWithBalance();
if (amountForDeposit.isGreaterThanZero()) {
handleDeposit(reinvestedDeposit, fmt, reinvestedDeposit.getActivationLocalDate(), amountForDeposit.getAmount(), null);
}
reinvestedDeposit.updateMaturityDateAndAmount(mc, nextTransactionStartDate);
this.savingsAccountRepository.save(reinvestedDeposit);
autoGenerateAccountNumber(reinvestedDeposit);
} else if (rdAccount.isTransferToSavingsOnClosure()) {
@@ -52,7 +52,6 @@ import org.mifosplatform.portfolio.savings.SavingsInterestCalculationDaysInYearT
import org.mifosplatform.portfolio.savings.SavingsInterestCalculationType;
import org.mifosplatform.portfolio.savings.SavingsPeriodFrequencyType;
import org.mifosplatform.portfolio.savings.SavingsPostingInterestPeriodType;
import org.mifosplatform.portfolio.savings.data.SavingsAccountTransactionDTO;
import org.mifosplatform.portfolio.savings.domain.interest.PostingPeriod;
import org.mifosplatform.portfolio.savings.service.SavingsEnumerations;
import org.mifosplatform.useradministration.domain.AppUser;
@@ -326,7 +325,7 @@ public class FixedDepositAccount extends SavingsAccount {
final Integer onAccountClosureId = command.integerValueOfParameterNamed(onAccountClosureIdParamName);
final DepositAccountOnClosureType onClosureType = DepositAccountOnClosureType.fromInt(onAccountClosureId);
this.accountTermAndPreClosure.updateOnAccountClosureStatus(onClosureType);
postPreMaturityInterest(closedDate);
// withdraw deposit amount before closing the account
@@ -351,18 +350,8 @@ public class FixedDepositAccount extends SavingsAccount {
}
@Override
protected void processAccountUponActivation(final DateTimeFormatter fmt) {
final Money depositAmount = Money.of(this.currency, this.accountTermAndPreClosure.depositAmount());
if (depositAmount.isGreaterThanZero()) {
final SavingsAccountTransactionDTO transactionDTO = new SavingsAccountTransactionDTO(fmt, getActivationLocalDate(),
depositAmount.getAmount(), null, new Date());
deposit(transactionDTO);
final LocalDate interestPostingUpToDate = interestPostingUpToDate(DateUtils.getLocalDateOfTenant());
// update existing transactions so derived balance fields are
// correct.
recalculateDailyBalances(Money.zero(this.currency), interestPostingUpToDate);
}
public Money activateWithBalance() {
return Money.of(this.currency, this.accountTermAndPreClosure.depositAmount());
}
public SavingsAccountTransaction close(final AppUser currentUser, final JsonCommand command, final LocalDate tenantsTodayDate,
@@ -576,14 +565,10 @@ public class FixedDepositAccount extends SavingsAccount {
return interestPostedToDate;
}
@Override
public Map<String, Object> activate(final AppUser currentUser, final JsonCommand command, final LocalDate tenantsTodayDate) {
final Map<String, Object> actualChanges = super.activate(currentUser, command, tenantsTodayDate);
final MathContext mc = MathContext.DECIMAL64;
public void updateMaturityDateAndAmountAfterAccountActivation(final MathContext mc) {
List<SavingsAccountTransaction> allTransactions = new ArrayList<SavingsAccountTransaction>();
allTransactions.addAll(retreiveOrderedNonInterestPostingTransactions());
updateMaturityDateAndAmount(mc, allTransactions);
return actualChanges;
}
private LocalDate depositStartDate() {
@@ -640,15 +625,15 @@ public class FixedDepositAccount extends SavingsAccount {
}
}
if(this.chart == null){
if (this.chart == null) {
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode("no.valid.interest.rate.slab.available");
}else{
} else {
final LocalDate chartFromDate = this.chart.getFromDateAsLocalDate();
LocalDate chartEndDate = this.chart.getEndDateAsLocalDate();
chartEndDate = chartEndDate == null ? DateUtils.getLocalDateOfTenant() : chartEndDate;
final LocalDateInterval chartInterval = LocalDateInterval.create(chartFromDate, chartEndDate);
if(!chartInterval.contains(accountSubmittedOrActivationDate())){
if (!chartInterval.contains(accountSubmittedOrActivationDate())) {
baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode("no.valid.interest.rate.slab.available");
}
}
@@ -657,7 +642,7 @@ public class FixedDepositAccount extends SavingsAccount {
public boolean isReinvestOnClosure() {
return this.accountTermAndPreClosure.isReinvestOnClosure();
}
public boolean isTransferToSavingsOnClosure() {
return this.accountTermAndPreClosure.isTransferToSavingsOnClosure();
}
@@ -683,14 +668,15 @@ public class FixedDepositAccount extends SavingsAccount {
final Integer lockinPeriodFrequency = this.lockinPeriodFrequency;
final boolean withdrawalFeeApplicableForTransfer = false;
final String accountNumber = null;
final FixedDepositAccount reInvestedAccount = FixedDepositAccount.createNewApplicationForSubmittal(client, group, product, fieldOfficer, accountNumber, externalId,
accountType, getClosedOnDate(), closedBy, interestRate, compoundingPeriodType, postingPeriodType, interestCalculationType,
daysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType,
withdrawalFeeApplicableForTransfer, savingsAccountCharges, newAccountTermAndPreClosure, newChart);
final FixedDepositAccount reInvestedAccount = FixedDepositAccount
.createNewApplicationForSubmittal(client, group, product, fieldOfficer, accountNumber, externalId, accountType,
getClosedOnDate(), closedBy, interestRate, compoundingPeriodType, postingPeriodType, interestCalculationType,
daysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType,
withdrawalFeeApplicableForTransfer, savingsAccountCharges, newAccountTermAndPreClosure, newChart);
newAccountTermAndPreClosure.updateAccountReference(reInvestedAccount);
newChart.updateDepositAccountReference(reInvestedAccount);
newChart.updateDepositAccountReference(reInvestedAccount);
return reInvestedAccount;
}
@@ -459,19 +459,8 @@ public class RecurringDepositAccount extends SavingsAccount {
}
@Override
protected void processAccountUponActivation(final DateTimeFormatter fmt) {
final Money minRequiredOpeningBalance = Money.of(this.currency, this.minRequiredOpeningBalance);
if (minRequiredOpeningBalance.isGreaterThanZero()) {
final SavingsAccountTransactionDTO transactionDTO = new SavingsAccountTransactionDTO(fmt, getActivationLocalDate(),
minRequiredOpeningBalance.getAmount(), null, new Date());
deposit(transactionDTO);
// update existing transactions so derived balance fields are
// correct.
recalculateDailyBalances(Money.zero(this.currency), DateUtils.getLocalDateOfTenant());
}
public Money activateWithBalance() {
return Money.of(this.currency, this.minRequiredOpeningBalance);
}
public SavingsAccountTransaction close(final AppUser currentUser, final JsonCommand command, final LocalDate tenantsTodayDate,
@@ -902,31 +891,4 @@ public class RecurringDepositAccount extends SavingsAccount {
this.activatedOnDate = now.toDate();
}
private boolean recurringFrequencyBeforeDepositPeriod() {
final int recurringFrequency = recurringDetail.recurringDepositFrequency();
final SavingsPeriodFrequencyType recurringfrequencyType = recurringDetail.recurringDepositFrequencyType();
LocalDate depositStartDate = accountTermAndPreClosure.getExpectedFirstDepositOnDate();
LocalDate endDateWithFirstRecurringFrequency = null;
switch (recurringfrequencyType) {
case DAYS:
endDateWithFirstRecurringFrequency = depositStartDate.plusDays(recurringFrequency);
break;
case MONTHS:
endDateWithFirstRecurringFrequency = depositStartDate.plusMonths(recurringFrequency);
break;
case WEEKS:
endDateWithFirstRecurringFrequency = depositStartDate.plusWeeks(recurringFrequency);
break;
case YEARS:
endDateWithFirstRecurringFrequency = depositStartDate.plusYears(recurringFrequency);
break;
default:
break;
}
return endDateWithFirstRecurringFrequency != null && endDateWithFirstRecurringFrequency.isBefore(calculateMaturityDate());
}
}
@@ -1541,27 +1541,12 @@ public class SavingsAccount extends AbstractPersistable<Long> {
// auto enter deposit for minimum required opening balance when
// activating account.
processAccountUponActivation(fmt);
processAccountUponActivation();
return actualChanges;
}
protected void processAccountUponActivation(final DateTimeFormatter fmt) {
final Money minRequiredOpeningBalance = Money.of(this.currency, this.minRequiredOpeningBalance);
if (minRequiredOpeningBalance.isGreaterThanZero()) {
final SavingsAccountTransactionDTO transactionDTO = new SavingsAccountTransactionDTO(fmt, getActivationLocalDate(),
minRequiredOpeningBalance.getAmount(), null, new Date());
deposit(transactionDTO);
// no openingBalance concept supported yet but probably will to
// allow
// for migrations.
final Money openingAccountBalance = Money.zero(this.currency);
// update existing transactions so derived balance fields are
// correct.
recalculateDailyBalances(openingAccountBalance, DateUtils.getLocalDateOfTenant());
}
public void processAccountUponActivation() {
// update annual fee due date
for (SavingsAccountCharge charge : this.charges()) {
@@ -1573,7 +1558,11 @@ public class SavingsAccount extends AbstractPersistable<Long> {
// TODO : AA add activation charges to actual changes list
}
public void approveAndActivateApplication(final Date appliedonDate, final AppUser appliedBy, final DateTimeFormatter fmt) {
public Money activateWithBalance() {
return Money.of(this.currency, this.minRequiredOpeningBalance);
}
public void approveAndActivateApplication(final Date appliedonDate, final AppUser appliedBy) {
this.status = SavingsAccountStatusType.ACTIVE.getValue();
this.approvedOnDate = appliedonDate;
this.approvedBy = appliedBy;
@@ -1586,7 +1575,6 @@ public class SavingsAccount extends AbstractPersistable<Long> {
this.activatedOnDate = appliedonDate;
this.activatedBy = appliedBy;
this.lockedInUntilDate = calculateDateAccountIsLockedUntil(getActivationLocalDate());
processAccountUponActivation(fmt);
}
private void payActivationCharges() {
@@ -100,6 +100,10 @@ public enum SavingsAccountStatusType {
public boolean isActive() {
return this.value.equals(SavingsAccountStatusType.ACTIVE.getValue());
}
public boolean isActiveOrAwaitingApprovalOrDisbursal() {
return isApproved() || isSubmittedAndPendingApproval() || isActive();
}
public boolean isClosed() {
return this.value.equals(SavingsAccountStatusType.CLOSED.getValue()) || isRejected() || isApplicationWithdrawnByApplicant();
@@ -278,9 +278,12 @@ public class DepositAccountReadPlatformServiceImpl implements DepositAccountRead
Long officeId = loggedInUser.getOffice().getId();
ClientData client = null;
Collection<SavingsAccountData> savingsAccountDatas = null;
if (clientId != null) {
client = this.clientReadPlatformService.retrieveOne(clientId);
officeId = client.officeId();
savingsAccountDatas = this.savingsAccountReadPlatformService.retrieveActiveForLookup(clientId,
DepositAccountType.SAVINGS_DEPOSIT);
}
GroupGeneralData group = null;
@@ -381,7 +384,7 @@ public class DepositAccountReadPlatformServiceImpl implements DepositAccountRead
interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions,
withdrawalFeeTypeOptions, transactions, charges, chargeOptions, interestFreePeriodTypeOptions,
preClosurePenalInterestOnTypeOptions, depositTermTypeOptions, inMultiplesOfDepositTermTypeOptions,
depositPeriodFrequencyOptions);
depositPeriodFrequencyOptions, savingsAccountDatas);
template = FixedDepositAccountData.withInterestChart((FixedDepositAccountData) template, accountChart);
} else if (depositAccountType.isRecurringDeposit()) {
@@ -431,7 +434,7 @@ public class DepositAccountReadPlatformServiceImpl implements DepositAccountRead
interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions,
withdrawalFeeTypeOptions, transactions, charges, chargeOptions, interestFreePeriodTypeOptions,
preClosurePenalInterestOnTypeOptions, depositTermTypeOptions, inMultiplesOfDepositTermTypeOptions,
depositPeriodFrequencyOptions);
depositPeriodFrequencyOptions, savingsAccountDatas);
} else if (depositAccountType.isRecurringDeposit()) {
template = RecurringDepositAccountData.withClientTemplate(clientId, clientName, groupId, groupName);
@@ -39,11 +39,17 @@ import org.mifosplatform.organisation.holiday.service.HolidayWritePlatformServic
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.monetary.domain.Money;
import org.mifosplatform.organisation.office.domain.Office;
import org.mifosplatform.organisation.staff.domain.Staff;
import org.mifosplatform.organisation.workingdays.service.WorkingDaysWritePlatformService;
import org.mifosplatform.portfolio.account.PortfolioAccountType;
import org.mifosplatform.portfolio.account.data.AccountTransferDTO;
import org.mifosplatform.portfolio.account.data.PortfolioAccountData;
import org.mifosplatform.portfolio.account.domain.AccountTransferType;
import org.mifosplatform.portfolio.account.service.AccountAssociationsReadPlatformService;
import org.mifosplatform.portfolio.account.service.AccountTransfersReadPlatformService;
import org.mifosplatform.portfolio.account.service.AccountTransfersWritePlatformService;
import org.mifosplatform.portfolio.charge.domain.Charge;
import org.mifosplatform.portfolio.charge.domain.ChargeRepositoryWrapper;
import org.mifosplatform.portfolio.client.domain.Client;
@@ -98,6 +104,8 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
private final SavingsAccountChargeRepositoryWrapper savingsAccountChargeRepository;
private final HolidayWritePlatformService holidayWritePlatformService;
private final WorkingDaysWritePlatformService workingDaysWritePlatformService;
private final AccountAssociationsReadPlatformService accountAssociationsReadPlatformService;
private final AccountTransfersWritePlatformService accountTransfersWritePlatformService;
@Autowired
public DepositAccountWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context,
@@ -113,7 +121,9 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
final AccountTransfersReadPlatformService accountTransfersReadPlatformService, final ChargeRepositoryWrapper chargeRepository,
final SavingsAccountChargeRepositoryWrapper savingsAccountChargeRepository,
final HolidayWritePlatformService holidayWritePlatformService,
final WorkingDaysWritePlatformService workingDaysWritePlatformService) {
final WorkingDaysWritePlatformService workingDaysWritePlatformService,
final AccountAssociationsReadPlatformService accountAssociationsReadPlatformService,
final AccountTransfersWritePlatformService accountTransfersWritePlatformService) {
this.context = context;
this.savingAccountRepository = savingAccountRepository;
this.savingsAccountTransactionRepository = savingsAccountTransactionRepository;
@@ -130,6 +140,8 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
this.savingsAccountChargeRepository = savingsAccountChargeRepository;
this.holidayWritePlatformService = holidayWritePlatformService;
this.workingDaysWritePlatformService = workingDaysWritePlatformService;
this.accountAssociationsReadPlatformService = accountAssociationsReadPlatformService;
this.accountTransfersWritePlatformService = accountTransfersWritePlatformService;
}
@Transactional
@@ -149,15 +161,25 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
final Map<String, Object> changes = account.activate(user, command, DateUtils.getLocalDateOfTenant());
if (!changes.isEmpty()) {
final MathContext mc = MathContext.DECIMAL64;
if (account.isBeforeLastPostingPeriod(account.getActivationLocalDate())) {
final LocalDate today = DateUtils.getLocalDateOfTenant();
account.postInterest(mc, today);
} else {
final LocalDate today = DateUtils.getLocalDateOfTenant();
account.calculateInterestUsing(mc, today);
final Locale locale = command.extractLocale();
final DateTimeFormatter fmt = DateTimeFormat.forPattern(command.dateFormat()).withLocale(locale);
Money amountForDeposit = account.activateWithBalance();
if (amountForDeposit.isGreaterThanZero()) {
final PortfolioAccountData portfolioAccountData = this.accountAssociationsReadPlatformService
.retriveSavingsAssociation(savingsId);
if (portfolioAccountData == null) {
this.depositAccountDomainService.handleDeposit(account, fmt, account.getActivationLocalDate(),
amountForDeposit.getAmount(), null);
} else {
final AccountTransferDTO accountTransferDTO = new AccountTransferDTO(account.getActivationLocalDate(),
amountForDeposit.getAmount(), PortfolioAccountType.SAVINGS, PortfolioAccountType.SAVINGS,
portfolioAccountData.accountId(), account.getId(), "Account Transfer", locale, fmt, null, null, null, null,
null, AccountTransferType.ACCOUNT_TRANSFER.getValue(), null, null, null, null, account);
this.accountTransfersWritePlatformService.transferFunds(accountTransferDTO);
}
updateExistingTransactionsDetails(account, existingTransactionIds, existingReversedTransactionIds);
}
// account.processAccountUponActivation(fmt);
account.validateAccountBalanceDoesNotBecomeNegative(SavingsAccountTransactionType.PAY_CHARGE.name());
@@ -182,10 +204,9 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
this.context.authenticatedUser();
if(depositAccountType.isFixedDeposit()){
throw new DepositAccountTransactionNotAllowedException(savingsId, "deposit", depositAccountType);
}
if (depositAccountType.isFixedDeposit()) { throw new DepositAccountTransactionNotAllowedException(savingsId, "deposit",
depositAccountType); }
this.depositAccountTransactionDataValidator.validate(command, depositAccountType);
final SavingsAccount account = this.depositAccountAssembler.assembleFrom(savingsId, depositAccountType);
@@ -224,10 +245,9 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
this.depositAccountTransactionDataValidator.validate(command, depositAccountType);
if(depositAccountType.isFixedDeposit()){
throw new DepositAccountTransactionNotAllowedException(savingsId, "withdraw", depositAccountType);
}
if (depositAccountType.isFixedDeposit()) { throw new DepositAccountTransactionNotAllowedException(savingsId, "withdraw",
depositAccountType); }
final LocalDate transactionDate = command.localDateValueOfParameterNamed("transactionDate");
final BigDecimal transactionAmount = command.bigDecimalValueOfParameterNamed("transactionAmount");
@@ -309,11 +329,10 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
@Override
public CommandProcessingResult undoTransaction(final Long savingsId, final Long transactionId,
final boolean allowAccountTransferModification, final DepositAccountType depositAccountType) {
if(depositAccountType.isFixedDeposit()){
throw new DepositAccountTransactionNotAllowedException(savingsId, "undo", depositAccountType);
}
if (depositAccountType.isFixedDeposit()) { throw new DepositAccountTransactionNotAllowedException(savingsId, "undo",
depositAccountType); }
final SavingsAccount account = this.depositAccountAssembler.assembleFrom(savingsId, depositAccountType);
final Set<Long> existingTransactionIds = new HashSet<Long>();
final Set<Long> existingReversedTransactionIds = new HashSet<Long>();
@@ -360,11 +379,10 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
public CommandProcessingResult adjustDepositTransaction(final Long savingsId, final Long transactionId, final JsonCommand command,
final DepositAccountType depositAccountType) {
if(depositAccountType.isFixedDeposit()){
throw new DepositAccountTransactionNotAllowedException(savingsId, "modify", depositAccountType);
}
if (depositAccountType.isFixedDeposit()) { throw new DepositAccountTransactionNotAllowedException(savingsId, "modify",
depositAccountType); }
this.depositAccountTransactionDataValidator.validate(command, depositAccountType);
final SavingsAccountTransaction savingsAccountTransaction = this.savingsAccountTransactionRepository
.findOneByIdAndSavingsAccountId(transactionId, savingsId);
if (savingsAccountTransaction == null) { throw new SavingsAccountTransactionNotFoundException(savingsId, transactionId); }
@@ -375,7 +393,6 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
if (this.accountTransfersReadPlatformService.isAccountTransfer(transactionId, PortfolioAccountType.SAVINGS)) { throw new PlatformServiceUnavailableException(
"error.msg.saving.account.transfer.transaction.update.not.allowed", "Deposit account transaction:" + transactionId
+ " update not allowed as it involves in account transfer", transactionId); }
final LocalDate today = DateUtils.getLocalDateOfTenant();
@@ -21,10 +21,13 @@ import org.mifosplatform.infrastructure.core.data.CommandProcessingResultBuilder
import org.mifosplatform.infrastructure.core.data.DataValidatorBuilder;
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
import org.mifosplatform.infrastructure.core.exception.PlatformDataIntegrityException;
import org.mifosplatform.infrastructure.core.serialization.FromJsonHelper;
import org.mifosplatform.infrastructure.core.service.DateUtils;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.mifosplatform.organisation.staff.domain.Staff;
import org.mifosplatform.organisation.staff.domain.StaffRepositoryWrapper;
import org.mifosplatform.portfolio.account.domain.AccountAssociations;
import org.mifosplatform.portfolio.account.domain.AccountAssociationsRepository;
import org.mifosplatform.portfolio.client.domain.AccountNumberGenerator;
import org.mifosplatform.portfolio.client.domain.AccountNumberGeneratorFactory;
import org.mifosplatform.portfolio.client.domain.Client;
@@ -80,6 +83,8 @@ public class DepositApplicationProcessWritePlatformServiceJpaRepositoryImpl impl
private final StaffRepositoryWrapper staffRepository;
private final SavingsAccountApplicationTransitionApiJsonValidator savingsAccountApplicationTransitionApiJsonValidator;
private final SavingsAccountChargeAssembler savingsAccountChargeAssembler;
private final AccountAssociationsRepository accountAssociationsRepository;
private final FromJsonHelper fromJsonHelper;
@Autowired
public DepositApplicationProcessWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context,
@@ -91,7 +96,8 @@ public class DepositApplicationProcessWritePlatformServiceJpaRepositoryImpl impl
final SavingsAccountApplicationTransitionApiJsonValidator savingsAccountApplicationTransitionApiJsonValidator,
final SavingsAccountChargeAssembler savingsAccountChargeAssembler,
final FixedDepositAccountRepository fixedDepositAccountRepository,
final RecurringDepositAccountRepository recurringDepositAccountRepository) {
final RecurringDepositAccountRepository recurringDepositAccountRepository,
final AccountAssociationsRepository accountAssociationsRepository, final FromJsonHelper fromJsonHelper) {
this.context = context;
this.savingAccountRepository = savingAccountRepository;
this.depositAccountAssembler = depositAccountAssembler;
@@ -106,6 +112,8 @@ public class DepositApplicationProcessWritePlatformServiceJpaRepositoryImpl impl
this.savingsAccountChargeAssembler = savingsAccountChargeAssembler;
this.fixedDepositAccountRepository = fixedDepositAccountRepository;
this.recurringDepositAccountRepository = recurringDepositAccountRepository;
this.accountAssociationsRepository = accountAssociationsRepository;
this.fromJsonHelper = fromJsonHelper;
}
/*
@@ -164,6 +172,16 @@ public class DepositApplicationProcessWritePlatformServiceJpaRepositoryImpl impl
this.savingAccountRepository.save(account);
}
// Save linked account information
final Long savingsAccountId = command.longValueOfParameterNamed(DepositsApiConstants.linkedAccountParamName);
if (savingsAccountId != null) {
final SavingsAccount savingsAccount = this.depositAccountAssembler.assembleFrom(savingsAccountId,
DepositAccountType.SAVINGS_DEPOSIT);
this.depositAccountDataValidator.validatelinkedSavingsAccount(savingsAccount, account);
final AccountAssociations accountAssociations = AccountAssociations.associateSavingsAccount(account, savingsAccount);
this.accountAssociationsRepository.save(accountAssociations);
}
final Long savingsId = account.getId();
return new CommandProcessingResultBuilder() //
.withCommandId(command.commandId()) //
@@ -261,6 +279,40 @@ public class DepositApplicationProcessWritePlatformServiceJpaRepositoryImpl impl
this.savingAccountRepository.saveAndFlush(account);
}
// Save linked account information
final Long savingsAccountId = command.longValueOfParameterNamed(DepositsApiConstants.linkedAccountParamName);
AccountAssociations accountAssociations = this.accountAssociationsRepository.findBySavingsId(accountId);
if (savingsAccountId == null) {
if (accountAssociations != null) {
if (this.fromJsonHelper.parameterExists(DepositsApiConstants.linkedAccountParamName, command.parsedJson())) {
this.accountAssociationsRepository.delete(accountAssociations);
changes.put(DepositsApiConstants.linkedAccountParamName, null);
}
}
} else {
boolean isModified = false;
if (accountAssociations == null) {
isModified = true;
} else {
final SavingsAccount savingsAccount = accountAssociations.linkedSavingsAccount();
if (savingsAccount == null || savingsAccount.getId() != savingsAccountId) {
isModified = true;
}
}
if (isModified) {
final SavingsAccount savingsAccount = this.depositAccountAssembler.assembleFrom(savingsAccountId,
DepositAccountType.SAVINGS_DEPOSIT);
this.depositAccountDataValidator.validatelinkedSavingsAccount(savingsAccount, account);
if (accountAssociations == null) {
accountAssociations = AccountAssociations.associateSavingsAccount(account, savingsAccount);
} else {
accountAssociations.updateLinkedSavingsAccount(savingsAccount);
}
changes.put(DepositsApiConstants.linkedAccountParamName, savingsAccountId);
this.accountAssociationsRepository.save(accountAssociations);
}
}
return new CommandProcessingResultBuilder() //
.withCommandId(command.commandId()) //
.withEntityId(accountId) //
@@ -41,6 +41,7 @@ import org.mifosplatform.organisation.holiday.service.HolidayWritePlatformServic
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.monetary.domain.Money;
import org.mifosplatform.organisation.office.domain.Office;
import org.mifosplatform.organisation.staff.domain.Staff;
import org.mifosplatform.organisation.workingdays.service.WorkingDaysWritePlatformService;
@@ -152,16 +153,15 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
final Map<String, Object> changes = account.activate(user, command, DateUtils.getLocalDateOfTenant());
if (!changes.isEmpty()) {
final MathContext mc = MathContext.DECIMAL64;
if (account.isBeforeLastPostingPeriod(account.getActivationLocalDate())) {
final LocalDate today = DateUtils.getLocalDateOfTenant();
account.postInterest(mc, today);
} else {
final LocalDate today = DateUtils.getLocalDateOfTenant();
account.calculateInterestUsing(mc, today);
final Locale locale = command.extractLocale();
final DateTimeFormatter fmt = DateTimeFormat.forPattern(command.dateFormat()).withLocale(locale);
Money amountForDeposit = account.activateWithBalance();
if (amountForDeposit.isGreaterThanZero()) {
this.savingsAccountDomainService.handleDeposit(account, fmt, account.getActivationLocalDate(),
amountForDeposit.getAmount(), null);
updateExistingTransactionsDetails(account, existingTransactionIds, existingReversedTransactionIds);
}
account.processAccountUponActivation();
account.validateAccountBalanceDoesNotBecomeNegative(SavingsAccountTransactionType.PAY_CHARGE.name());
this.savingAccountRepository.save(account);
@@ -499,11 +499,11 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
this.savingsAccountTransactionDataValidator.validateClosing(command);
final SavingsAccount account = this.savingAccountAssembler.assembleFrom(savingsId);
final boolean isLinkedWithAnyActiveLoan = this.accountAssociationsReadPlatformService.isLinkedWithAnyActiveLoan(savingsId);
final boolean isLinkedWithAnyActiveLoan = this.accountAssociationsReadPlatformService.isLinkedWithAnyActiveAccount(savingsId);
if (isLinkedWithAnyActiveLoan) {
final String defaultUserMessage = "Closing savings account with id:" + savingsId
+ " is not allowed, since it is linked with one of the active loans";
+ " is not allowed, since it is linked with one of the active accounts";
throw new SavingsAccountClosingNotAllowedException("linked", defaultUserMessage, savingsId);
}
@@ -26,6 +26,7 @@ import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidation
import org.mifosplatform.infrastructure.core.exception.PlatformDataIntegrityException;
import org.mifosplatform.infrastructure.core.service.DateUtils;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.mifosplatform.organisation.monetary.domain.Money;
import org.mifosplatform.organisation.staff.domain.Staff;
import org.mifosplatform.organisation.staff.domain.StaffRepositoryWrapper;
import org.mifosplatform.portfolio.client.domain.AccountNumberGenerator;
@@ -47,6 +48,7 @@ import org.mifosplatform.portfolio.savings.domain.SavingsAccount;
import org.mifosplatform.portfolio.savings.domain.SavingsAccountAssembler;
import org.mifosplatform.portfolio.savings.domain.SavingsAccountCharge;
import org.mifosplatform.portfolio.savings.domain.SavingsAccountChargeAssembler;
import org.mifosplatform.portfolio.savings.domain.SavingsAccountDomainService;
import org.mifosplatform.portfolio.savings.domain.SavingsAccountRepositoryWrapper;
import org.mifosplatform.portfolio.savings.domain.SavingsProduct;
import org.mifosplatform.portfolio.savings.domain.SavingsProductRepository;
@@ -77,6 +79,7 @@ public class SavingsApplicationProcessWritePlatformServiceJpaRepositoryImpl impl
private final SavingsAccountApplicationTransitionApiJsonValidator savingsAccountApplicationTransitionApiJsonValidator;
private final SavingsAccountChargeAssembler savingsAccountChargeAssembler;
private final CommandProcessingService commandProcessingService;
private final SavingsAccountDomainService savingsAccountDomainService;
@Autowired
public SavingsApplicationProcessWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context,
@@ -86,8 +89,8 @@ public class SavingsApplicationProcessWritePlatformServiceJpaRepositoryImpl impl
final GroupRepository groupRepository, final SavingsProductRepository savingsProductRepository,
final NoteRepository noteRepository, final StaffRepositoryWrapper staffRepository,
final SavingsAccountApplicationTransitionApiJsonValidator savingsAccountApplicationTransitionApiJsonValidator,
final SavingsAccountChargeAssembler savingsAccountChargeAssembler,
final CommandProcessingService commandProcessingService) {
final SavingsAccountChargeAssembler savingsAccountChargeAssembler, final CommandProcessingService commandProcessingService,
final SavingsAccountDomainService savingsAccountDomainService) {
this.context = context;
this.savingAccountRepository = savingAccountRepository;
this.savingAccountAssembler = savingAccountAssembler;
@@ -101,6 +104,7 @@ public class SavingsApplicationProcessWritePlatformServiceJpaRepositoryImpl impl
this.savingsAccountApplicationTransitionApiJsonValidator = savingsAccountApplicationTransitionApiJsonValidator;
this.savingsAccountChargeAssembler = savingsAccountChargeAssembler;
this.commandProcessingService = commandProcessingService;
this.savingsAccountDomainService = savingsAccountDomainService;
}
/*
@@ -438,13 +442,20 @@ public class SavingsApplicationProcessWritePlatformServiceJpaRepositoryImpl impl
@Override
public CommandProcessingResult createActiveApplication(final SavingsAccountDataDTO savingsAccountDataDTO) {
final CommandWrapper commandWrapper = new CommandWrapperBuilder().savingsAccountActivation(null).build();
boolean rollbackTransaction = this.commandProcessingService.validateCommand(commandWrapper, savingsAccountDataDTO.getAppliedBy());
final SavingsAccount account = this.savingAccountAssembler.assembleFrom(savingsAccountDataDTO.getClient(),savingsAccountDataDTO.getGroup(),
savingsAccountDataDTO.getSavingsProduct(),savingsAccountDataDTO.getApplicationDate(),savingsAccountDataDTO.getAppliedBy());
account.approveAndActivateApplication(savingsAccountDataDTO.getApplicationDate().toDate(), savingsAccountDataDTO.getAppliedBy(), savingsAccountDataDTO.getFmt());
final SavingsAccount account = this.savingAccountAssembler.assembleFrom(savingsAccountDataDTO.getClient(),
savingsAccountDataDTO.getGroup(), savingsAccountDataDTO.getSavingsProduct(), savingsAccountDataDTO.getApplicationDate(),
savingsAccountDataDTO.getAppliedBy());
account.approveAndActivateApplication(savingsAccountDataDTO.getApplicationDate().toDate(), savingsAccountDataDTO.getAppliedBy());
Money amountForDeposit = account.activateWithBalance();
if (amountForDeposit.isGreaterThanZero()) {
this.savingsAccountDomainService.handleDeposit(account, savingsAccountDataDTO.getFmt(), account.getActivationLocalDate(),
amountForDeposit.getAmount(), null);
}
account.processAccountUponActivation();
this.savingAccountRepository.save(account);
if (account.isAccountNumberRequiresAutoGeneration()) {
@@ -454,8 +465,8 @@ public class SavingsApplicationProcessWritePlatformServiceJpaRepositoryImpl impl
this.savingAccountRepository.save(account);
}
return new CommandProcessingResultBuilder() //
.withSavingsId(account.getId()) //
.setRollbackTransaction(rollbackTransaction)//
.build();
.withSavingsId(account.getId()) //
.setRollbackTransaction(rollbackTransaction)//
.build();
}
}