MIFOSX-1163 : added functionality to transfer fixed deposit amount from savings account

This commit is contained in:
Pramod Nuthakki
2014-05-02 11:26:48 +05:30
parent 78c0761ae5
commit 3677d4eb53
32 changed files with 436 additions and 233 deletions
+1 -1
View File
@@ -18542,7 +18542,7 @@ No Request Body:
<br/> <br/>
<table class=matrixHeading> <table class=matrixHeading>
<tr class="matrixHeadingBG"><td><div class="mifosXHeading2">Optional Fields</div></td></tr> <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> </table>
<br/> <br/>
<table class=matrixHeading> <table class=matrixHeading>
@@ -109,7 +109,7 @@ public class FixedDepositTest {
Assert.assertNotNull(fixedDepositProductId); Assert.assertNotNull(fixedDepositProductId);
Integer fixedDepositAccountId = applyForFixedDepositApplication(clientId.toString(), fixedDepositProductId.toString(), VALID_FROM, 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); Assert.assertNotNull(fixedDepositAccountId);
HashMap fixedDepositAccountStatusHashMap = FixedDepositAccountStatusChecker.getStatusOfFixedDepositAccount(this.requestSpec, HashMap fixedDepositAccountStatusHashMap = FixedDepositAccountStatusChecker.getStatusOfFixedDepositAccount(this.requestSpec,
@@ -172,7 +172,7 @@ public class FixedDepositTest {
this.responseSpec, fixedDepositProductId.toString()); this.responseSpec, fixedDepositProductId.toString());
Integer fixedDepositAccountId = applyForFixedDepositApplication(clientId.toString(), fixedDepositProductId.toString(), VALID_FROM, 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); Assert.assertNotNull(fixedDepositAccountId);
todaysDate.add(Calendar.DATE, -1); todaysDate.add(Calendar.DATE, -1);
@@ -230,7 +230,7 @@ public class FixedDepositTest {
Assert.assertNotNull(fixedDepositProductId); Assert.assertNotNull(fixedDepositProductId);
Integer fixedDepositAccountId = applyForFixedDepositApplication(clientId.toString(), fixedDepositProductId.toString(), VALID_FROM, 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); Assert.assertNotNull(fixedDepositAccountId);
HashMap fixedDepositAccountStatusHashMap = FixedDepositAccountStatusChecker.getStatusOfFixedDepositAccount(this.requestSpec, HashMap fixedDepositAccountStatusHashMap = FixedDepositAccountStatusChecker.getStatusOfFixedDepositAccount(this.requestSpec,
@@ -311,7 +311,7 @@ public class FixedDepositTest {
Assert.assertNotNull(fixedDepositProductId); Assert.assertNotNull(fixedDepositProductId);
Integer fixedDepositAccountId = applyForFixedDepositApplication(clientId.toString(), fixedDepositProductId.toString(), VALID_FROM, 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); Assert.assertNotNull(fixedDepositAccountId);
HashMap fixedDepositAccountStatusHashMap = FixedDepositAccountStatusChecker.getStatusOfFixedDepositAccount(this.requestSpec, HashMap fixedDepositAccountStatusHashMap = FixedDepositAccountStatusChecker.getStatusOfFixedDepositAccount(this.requestSpec,
@@ -368,7 +368,7 @@ public class FixedDepositTest {
Assert.assertNotNull(fixedDepositProductId); Assert.assertNotNull(fixedDepositProductId);
Integer fixedDepositAccountId = applyForFixedDepositApplication(clientId.toString(), fixedDepositProductId.toString(), VALID_FROM, 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); Assert.assertNotNull(fixedDepositAccountId);
HashMap fixedDepositAccountStatusHashMap = FixedDepositAccountStatusChecker.getStatusOfFixedDepositAccount(this.requestSpec, HashMap fixedDepositAccountStatusHashMap = FixedDepositAccountStatusChecker.getStatusOfFixedDepositAccount(this.requestSpec,
@@ -410,7 +410,7 @@ public class FixedDepositTest {
Assert.assertNotNull(fixedDepositProductId); Assert.assertNotNull(fixedDepositProductId);
Integer fixedDepositAccountId = applyForFixedDepositApplication(clientId.toString(), fixedDepositProductId.toString(), VALID_FROM, 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); Assert.assertNotNull(fixedDepositAccountId);
HashMap fixedDepositAccountStatusHashMap = FixedDepositAccountStatusChecker.getStatusOfFixedDepositAccount(this.requestSpec, HashMap fixedDepositAccountStatusHashMap = FixedDepositAccountStatusChecker.getStatusOfFixedDepositAccount(this.requestSpec,
@@ -450,7 +450,7 @@ public class FixedDepositTest {
Assert.assertNotNull(fixedDepositProductId); Assert.assertNotNull(fixedDepositProductId);
Integer fixedDepositAccountId = applyForFixedDepositApplication(clientId.toString(), fixedDepositProductId.toString(), VALID_FROM, 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); Assert.assertNotNull(fixedDepositAccountId);
HashMap fixedDepositAccountStatusHashMap = FixedDepositAccountStatusChecker.getStatusOfFixedDepositAccount(this.requestSpec, HashMap fixedDepositAccountStatusHashMap = FixedDepositAccountStatusChecker.getStatusOfFixedDepositAccount(this.requestSpec,
@@ -488,7 +488,7 @@ public class FixedDepositTest {
Assert.assertNotNull(fixedDepositProductId); Assert.assertNotNull(fixedDepositProductId);
Integer fixedDepositAccountId = applyForFixedDepositApplication(clientId.toString(), fixedDepositProductId.toString(), VALID_FROM, 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); Assert.assertNotNull(fixedDepositAccountId);
HashMap fixedDepositAccountStatusHashMap = FixedDepositAccountStatusChecker.getStatusOfFixedDepositAccount(this.requestSpec, HashMap fixedDepositAccountStatusHashMap = FixedDepositAccountStatusChecker.getStatusOfFixedDepositAccount(this.requestSpec,
@@ -499,6 +499,64 @@ public class FixedDepositTest {
Assert.assertNotNull(fixedDepositAccountId); 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) { private Integer createFixedDepositProduct(final String validFrom, final String validTo, Account... accounts) {
System.out.println("------------------------------CREATING NEW FIXED DEPOSIT PRODUCT ---------------------------------------"); System.out.println("------------------------------CREATING NEW FIXED DEPOSIT PRODUCT ---------------------------------------");
FixedDepositProductHelper fixedDepositProductHelper = new FixedDepositProductHelper(this.requestSpec, this.responseSpec); 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, 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 --------------------------------"); System.out.println("--------------------------------APPLYING FOR FIXED DEPOSIT ACCOUNT --------------------------------");
final String fixedDepositApplicationJSON = new FixedDepositAccountHelper(this.requestSpec, this.responseSpec) // final String fixedDepositApplicationJSON = new FixedDepositAccountHelper(this.requestSpec, this.responseSpec)
.withSubmittedOnDate(submittedOnDate).build(clientID, productID, validFrom, validTo, penalInterestType); //
.withSubmittedOnDate(submittedOnDate).withSavings(savingsId)
.build(clientID, productID, validFrom, validTo, penalInterestType);
return this.fixedDepositAccountHelper return this.fixedDepositAccountHelper
.applyFixedDepositApplication(fixedDepositApplicationJSON, this.requestSpec, this.responseSpec); .applyFixedDepositApplication(fixedDepositApplicationJSON, this.requestSpec, this.responseSpec);
} }
@@ -528,4 +588,24 @@ public class FixedDepositTest {
.withMinimumOpenningBalance(minOpenningBalance).build(); .withMinimumOpenningBalance(minOpenningBalance).build();
return SavingsProductHelper.createSavingsProduct(savingsProductJSON, requestSpec, responseSpec); 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 preClosurePenalApplicable = true;
private final boolean isActiveChart = true; private final boolean isActiveChart = true;
private final String currencyCode = USD; private final String currencyCode = USD;
private final String depositAmount = "100000"; public static final String depositAmount = "100000";
private final String depositPeriod = "14"; private final String depositPeriod = "14";
private final String depositPeriodFrequencyId = MONTHS; private final String depositPeriodFrequencyId = MONTHS;
private String submittedOnDate = ""; private String submittedOnDate = "";
private String savingsId = null;
public String build(final String clientId, final String productId, final String validFrom, final String validTo, public String build(final String clientId, final String productId, final String validFrom, final String validTo,
final String penalInterestType) { final String penalInterestType) {
@@ -156,10 +157,11 @@ public class FixedDepositAccountHelper {
map.put("inMultiplesOfDepositTermTypeId", this.inMultiplesOfDepositTermTypeId); map.put("inMultiplesOfDepositTermTypeId", this.inMultiplesOfDepositTermTypeId);
map.put("preClosurePenalInterest", this.preClosurePenalInterest); map.put("preClosurePenalInterest", this.preClosurePenalInterest);
map.put("preClosurePenalInterestOnTypeId", penalInterestType); map.put("preClosurePenalInterestOnTypeId", penalInterestType);
map.put("depositAmount", this.depositAmount); map.put("depositAmount", depositAmount);
map.put("depositPeriod", this.depositPeriod); map.put("depositPeriod", this.depositPeriod);
map.put("depositPeriodFrequencyId", this.depositPeriodFrequencyId); map.put("depositPeriodFrequencyId", this.depositPeriodFrequencyId);
map.put("submittedOnDate", this.submittedOnDate); map.put("submittedOnDate", this.submittedOnDate);
map.put("linkAccountId", savingsId);
String fixedDepositAccountJson = new Gson().toJson(map); String fixedDepositAccountJson = new Gson().toJson(map);
System.out.println(fixedDepositAccountJson); System.out.println(fixedDepositAccountJson);
@@ -211,9 +213,10 @@ public class FixedDepositAccountHelper {
+ Utils.TENANT_IDENTIFIER, fixedDepositApplicationJSON, CommonConstants.RESPONSE_CHANGES); + Utils.TENANT_IDENTIFIER, fixedDepositApplicationJSON, CommonConstants.RESPONSE_CHANGES);
} }
public HashMap updateInterestCalculationConfigForFixedDeposit(final String clientID, final String productID, final String accountID, final String submittedOnDate, public HashMap updateInterestCalculationConfigForFixedDeposit(final String clientID, final String productID, final String accountID,
final String validFrom, final String validTo, final String numberOfDaysPerYear, final String penalInterestType, final String submittedOnDate, final String validFrom, final String validTo, final String numberOfDaysPerYear,
final String interestCalculationType, final String interestCompoundingPeriodType, final String interestPostingPeriodType) { final String penalInterestType, final String interestCalculationType, final String interestCompoundingPeriodType,
final String interestPostingPeriodType) {
final String fixedDepositApplicationJSON = new FixedDepositAccountHelper(this.requestSpec, this.responseSpec) // final String fixedDepositApplicationJSON = new FixedDepositAccountHelper(this.requestSpec, this.responseSpec) //
.withSubmittedOnDate(submittedOnDate) // .withSubmittedOnDate(submittedOnDate) //
@@ -425,4 +428,8 @@ public class FixedDepositAccountHelper {
return this; 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.account.domain.AccountTransferDetails;
import org.mifosplatform.portfolio.loanaccount.domain.Loan; import org.mifosplatform.portfolio.loanaccount.domain.Loan;
import org.mifosplatform.portfolio.paymentdetail.domain.PaymentDetail; import org.mifosplatform.portfolio.paymentdetail.domain.PaymentDetail;
import org.mifosplatform.portfolio.savings.domain.SavingsAccount;
public class AccountTransferDTO { public class AccountTransferDTO {
@@ -31,13 +32,14 @@ public class AccountTransferDTO {
private final String noteText; private final String noteText;
private final String txnExternalId; private final String txnExternalId;
private final Loan loan; private final Loan loan;
private final SavingsAccount savingsAccount;
public AccountTransferDTO(final LocalDate transactionDate, final BigDecimal transactionAmount, public AccountTransferDTO(final LocalDate transactionDate, final BigDecimal transactionAmount,
final PortfolioAccountType fromAccountType, final PortfolioAccountType toAccountType, final Long fromAccountId, final PortfolioAccountType fromAccountType, final PortfolioAccountType toAccountType, final Long fromAccountId,
final Long toAccountId, final String description, final Locale locale, final DateTimeFormatter fmt, final Long toAccountId, final String description, final Locale locale, final DateTimeFormatter fmt,
final PaymentDetail paymentDetail, final Integer fromTransferType, final Integer toTransferType, final Long chargeId, final PaymentDetail paymentDetail, final Integer fromTransferType, final Integer toTransferType, final Long chargeId,
Integer loanInstallmentNumber, Integer transferType, final AccountTransferDetails accountTransferDetails,final String noteText, Integer loanInstallmentNumber, Integer transferType, final AccountTransferDetails accountTransferDetails,
final String txnExternalId,final Loan loan) { final String noteText, final String txnExternalId, final Loan loan, SavingsAccount savingsAccount) {
this.transactionDate = transactionDate; this.transactionDate = transactionDate;
this.transactionAmount = transactionAmount; this.transactionAmount = transactionAmount;
this.fromAccountType = fromAccountType; this.fromAccountType = fromAccountType;
@@ -57,6 +59,7 @@ public class AccountTransferDTO {
this.noteText = noteText; this.noteText = noteText;
this.txnExternalId = txnExternalId; this.txnExternalId = txnExternalId;
this.loan = loan; this.loan = loan;
this.savingsAccount = savingsAccount;
} }
public LocalDate getTransactionDate() { public LocalDate getTransactionDate() {
@@ -131,9 +134,12 @@ public class AccountTransferDTO {
return this.txnExternalId; return this.txnExternalId;
} }
public Loan getLoan() { public Loan getLoan() {
return this.loan; 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") @Table(name = "m_portfolio_account_associations")
public class AccountAssociations extends AbstractPersistable<Long> { public class AccountAssociations extends AbstractPersistable<Long> {
@SuppressWarnings("unused")
@ManyToOne @ManyToOne
@JoinColumn(name = "loan_account_id", nullable = true) @JoinColumn(name = "loan_account_id", nullable = true)
private Loan loanAccount; private Loan loanAccount;
@SuppressWarnings("unused")
@ManyToOne @ManyToOne
@JoinColumn(name = "savings_account_id", nullable = true) @JoinColumn(name = "savings_account_id", nullable = true)
private SavingsAccount savingsAccount; private SavingsAccount savingsAccount;
@SuppressWarnings("unused")
@ManyToOne @ManyToOne
@JoinColumn(name = "linked_loan_account_id", nullable = true) @JoinColumn(name = "linked_loan_account_id", nullable = true)
private Loan linkedLoanAccount; private Loan linkedLoanAccount;
@@ -43,6 +46,10 @@ public class AccountAssociations extends AbstractPersistable<Long> {
return new AccountAssociations(loan, null, null, savingsAccount); 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() { public SavingsAccount linkedSavingsAccount() {
return this.linkedSavingsAccount; return this.linkedSavingsAccount;
} }
@@ -11,4 +11,6 @@ public interface AccountAssociationsRepository extends JpaRepository<AccountAsso
@Query("from AccountAssociations aa where aa.loanAccount.id= :loanId") @Query("from AccountAssociations aa where aa.loanAccount.id= :loanId")
AccountAssociations findByLoanId(@Param("loanId") Long 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 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.AccountAssociationsData;
import org.mifosplatform.portfolio.account.data.PortfolioAccountData; import org.mifosplatform.portfolio.account.data.PortfolioAccountData;
import org.mifosplatform.portfolio.loanaccount.domain.LoanStatus; import org.mifosplatform.portfolio.loanaccount.domain.LoanStatus;
import org.mifosplatform.portfolio.savings.domain.SavingsAccountStatusType;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@@ -43,22 +44,46 @@ public class AccountAssociationsReadPlatformServiceImpl implements AccountAssoci
} }
return linkedAccount; 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 @Override
public boolean isLinkedWithAnyActiveLoan(final Long savingsId) { public boolean isLinkedWithAnyActiveAccount(final Long savingsId) {
boolean hasActiveLoan = false; boolean hasActiveAccount = false;
final String sql = "select loanAccount.loan_status_id as status from m_portfolio_account_associations aa " 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 = ?"; + "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); final List<Integer> statusList = this.jdbcTemplate.queryForList(sql, Integer.class, savingsId);
for (final Integer status : statusList) { for (final Integer status : statusList) {
final LoanStatus loanStatus = LoanStatus.fromInt(status); final LoanStatus loanStatus = LoanStatus.fromInt(status);
if (loanStatus.isActiveOrAwaitingApprovalOrDisbursal() || loanStatus.isUnderTransfer()) { if (loanStatus.isActiveOrAwaitingApprovalOrDisbursal() || loanStatus.isUnderTransfer()) { return true; }
hasActiveLoan = true;
break;
}
} }
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> { 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; final String currencyCode = excludeThisAccountFromOptions != null ? excludeThisAccountFromOptions.currencyCode() : null;
Collection<PortfolioAccountData> accountOptions = this.portfolioAccountReadPlatformService.retrieveAllForLookup(toAccountType, Collection<PortfolioAccountData> accountOptions = this.portfolioAccountReadPlatformService.retrieveAllForLookup(toAccountType,
toClientId, currencyCode, null); toClientId, currencyCode, null, null);
if (!CollectionUtils.isEmpty(accountOptions)) { if (!CollectionUtils.isEmpty(accountOptions)) {
accountOptions.remove(excludeThisAccountFromOptions); accountOptions.remove(excludeThisAccountFromOptions);
} else { } else {
@@ -268,7 +268,11 @@ public class AccountTransfersWritePlatformServiceImpl implements AccountTransfer
SavingsAccount toSavingsAccount = null; SavingsAccount toSavingsAccount = null;
if (accountTransferDetails == null) { if (accountTransferDetails == null) {
fromSavingsAccount = this.savingsAccountAssembler.assembleFrom(accountTransferDTO.getFromAccountId()); 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 { } else {
fromSavingsAccount = accountTransferDetails.fromSavingsAccount(); fromSavingsAccount = accountTransferDetails.fromSavingsAccount();
this.savingsAccountAssembler.setHelpers(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, 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.math.BigDecimal;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.List;
import org.mifosplatform.infrastructure.core.domain.JdbcSupport; import org.mifosplatform.infrastructure.core.domain.JdbcSupport;
import org.mifosplatform.infrastructure.core.service.RoutingDataSource; import org.mifosplatform.infrastructure.core.service.RoutingDataSource;
@@ -86,14 +88,15 @@ public class PortfolioAccountReadPlatformServiceImpl implements PortfolioAccount
@Override @Override
public Collection<PortfolioAccountData> retrieveAllForLookup(final Integer accountTypeId, final Long clientId, public Collection<PortfolioAccountData> retrieveAllForLookup(final Integer accountTypeId, final Long clientId,
final long[] accountStatus) { final long[] accountStatus) {
return retrieveAllForLookup(accountTypeId, clientId, null, accountStatus); return retrieveAllForLookup(accountTypeId, clientId, null, accountStatus, null);
} }
@Override @Override
public Collection<PortfolioAccountData> retrieveAllForLookup(final Integer accountTypeId, final Long clientId, 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; Collection<PortfolioAccountData> accounts = null;
String sql = null; String sql = null;
String defaultAccountStatus = "300"; String defaultAccountStatus = "300";
@@ -112,20 +115,25 @@ public class PortfolioAccountReadPlatformServiceImpl implements PortfolioAccount
+ defaultAccountStatus.toString() + ")"; + defaultAccountStatus.toString() + ")";
if (currencyCode != null) { if (currencyCode != null) {
sql += " and la.currency_code = ?"; 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; break;
case SAVINGS: case SAVINGS:
sql = "select " + this.savingsAccountMapper.schema() + " where sa.client_id = ? and sa.status_enum in (" sql = "select " + this.savingsAccountMapper.schema() + " where sa.client_id = ? and sa.status_enum in ("
+ defaultAccountStatus.toString() + ")"; + defaultAccountStatus.toString() + ")";
if (currencyCode != null) { if (currencyCode != null) {
sql += " and sa.currency_code = ?"; 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; break;
default: default:
break; break;
@@ -229,7 +229,7 @@ public class StandingInstructionReadPlatformServiceImpl implements StandingInstr
final String currencyCode = excludeThisAccountFromOptions != null ? excludeThisAccountFromOptions.currencyCode() : null; final String currencyCode = excludeThisAccountFromOptions != null ? excludeThisAccountFromOptions.currencyCode() : null;
Collection<PortfolioAccountData> accountOptions = this.portfolioAccountReadPlatformService.retrieveAllForLookup(toAccountType, Collection<PortfolioAccountData> accountOptions = this.portfolioAccountReadPlatformService.retrieveAllForLookup(toAccountType,
toClientId, currencyCode, null); toClientId, currencyCode, null, null);
if (!CollectionUtils.isEmpty(accountOptions)) { if (!CollectionUtils.isEmpty(accountOptions)) {
accountOptions.remove(excludeThisAccountFromOptions); accountOptions.remove(excludeThisAccountFromOptions);
} else { } else {
@@ -217,7 +217,7 @@ public class StandingInstructionWritePlatformServiceImpl implements StandingInst
AccountTransferDTO accountTransferDTO = new AccountTransferDTO(transactionDate, transactionAmount, data.fromAccountType(), AccountTransferDTO accountTransferDTO = new AccountTransferDTO(transactionDate, transactionAmount, data.fromAccountType(),
data.toAccountType(), data.fromAccount().accountId(), data.toAccount().accountId(), data.name() data.toAccountType(), data.fromAccount().accountId(), data.toAccount().accountId(), data.name()
+ " Standing instruction trasfer ", null, null, null, null, data.toTransferType(), null, null, data + " 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()); 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.data.NoteData;
import org.mifosplatform.portfolio.note.domain.NoteType; import org.mifosplatform.portfolio.note.domain.NoteType;
import org.mifosplatform.portfolio.note.service.NoteReadPlatformServiceImpl; import org.mifosplatform.portfolio.note.service.NoteReadPlatformServiceImpl;
import org.mifosplatform.portfolio.savings.DepositAccountType;
import org.mifosplatform.portfolio.savings.domain.SavingsAccountStatusType; import org.mifosplatform.portfolio.savings.domain.SavingsAccountStatusType;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope; import org.springframework.context.annotation.Scope;
@@ -265,7 +266,8 @@ public class LoansApiResource {
} }
final long[] accountStatus = { SavingsAccountStatusType.ACTIVE.getValue() }; final long[] accountStatus = { SavingsAccountStatusType.ACTIVE.getValue() };
accountLinkingOptions = this.portfolioAccountReadPlatformService.retrieveAllForLookup( 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() }; final long[] accountStatus = { SavingsAccountStatusType.ACTIVE.getValue() };
accountLinkingOptions = this.portfolioAccountReadPlatformService.retrieveAllForLookup(PortfolioAccountType.SAVINGS.getValue(), accountLinkingOptions = this.portfolioAccountReadPlatformService.retrieveAllForLookup(PortfolioAccountType.SAVINGS.getValue(),
loanBasicDetails.clientId(), currencyCode, accountStatus); loanBasicDetails.clientId(), currencyCode, accountStatus, DepositAccountType.SAVINGS_DEPOSIT.getValue());
if (!associationParameters.contains("linkedAccount")) { if (!associationParameters.contains("linkedAccount")) {
mandatoryResponseParameters.add("linkedAccount"); mandatoryResponseParameters.add("linkedAccount");
@@ -252,7 +252,7 @@ public final class LoanApplicationCommandFromApiJsonHelper {
.integerGreaterThanZero(); .integerGreaterThanZero();
final String linkAccountIdParameterName = "linkAccountId"; final String linkAccountIdParameterName = "linkAccountId";
if (this.fromApiJsonHelper.parameterExists(submittedOnNoteParameterName, element)) { if (this.fromApiJsonHelper.parameterExists(linkAccountIdParameterName, element)) {
final Long linkAccountId = this.fromApiJsonHelper.extractLongNamed(linkAccountIdParameterName, element); final Long linkAccountId = this.fromApiJsonHelper.extractLongNamed(linkAccountIdParameterName, element);
baseDataValidator.reset().parameter(linkAccountIdParameterName).value(linkAccountId).ignoreIfNull().longGreaterThanZero(); 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(), final AccountTransferDTO accountTransferDTO = new AccountTransferDTO(actualDisbursementDate, entrySet.getValue(),
PortfolioAccountType.SAVINGS, PortfolioAccountType.LOAN, savingAccountData.accountId(), loanId, "Loan Charge Payment", PortfolioAccountType.SAVINGS, PortfolioAccountType.LOAN, savingAccountData.accountId(), loanId, "Loan Charge Payment",
locale, fmt, null, null, LoanTransactionType.REPAYMENT_AT_DISBURSEMENT.getValue(), entrySet.getKey(), null, 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); this.accountTransfersWritePlatformService.transferFunds(accountTransferDTO);
} }
@@ -494,7 +494,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
final AccountTransferDTO accountTransferDTO = new AccountTransferDTO(actualDisbursementDate, entrySet.getValue(), final AccountTransferDTO accountTransferDTO = new AccountTransferDTO(actualDisbursementDate, entrySet.getValue(),
PortfolioAccountType.SAVINGS, PortfolioAccountType.LOAN, savingAccountData.accountId(), loan.getId(), PortfolioAccountType.SAVINGS, PortfolioAccountType.LOAN, savingAccountData.accountId(), loan.getId(),
"Loan Charge Payment", locale, fmt, null, null, LoanTransactionType.REPAYMENT_AT_DISBURSEMENT.getValue(), "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); this.accountTransfersWritePlatformService.transferFunds(accountTransferDTO);
} }
} }
@@ -1253,7 +1253,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
final AccountTransferDTO accountTransferDTO = new AccountTransferDTO(transactionDate, amount, PortfolioAccountType.SAVINGS, final AccountTransferDTO accountTransferDTO = new AccountTransferDTO(transactionDate, amount, PortfolioAccountType.SAVINGS,
PortfolioAccountType.LOAN, portfolioAccountData.accountId(), loanId, "Loan Charge Payment", locale, fmt, null, null, PortfolioAccountType.LOAN, portfolioAccountData.accountId(), loanId, "Loan Charge Payment", locale, fmt, null, null,
LoanTransactionType.CHARGE_PAYMENT.getValue(), loanChargeId, loanInstallmentNumber, 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); this.accountTransfersWritePlatformService.transferFunds(accountTransferDTO);
return new CommandProcessingResultBuilder() // return new CommandProcessingResultBuilder() //
@@ -1282,7 +1282,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
final AccountTransferDTO accountTransferDTO = new AccountTransferDTO(transactionDate, amount.getAmount(), final AccountTransferDTO accountTransferDTO = new AccountTransferDTO(transactionDate, amount.getAmount(),
PortfolioAccountType.LOAN, PortfolioAccountType.SAVINGS, loan.getId(), portfolioAccountData.accountId(), PortfolioAccountType.LOAN, PortfolioAccountType.SAVINGS, loan.getId(), portfolioAccountData.accountId(),
"Loan Disbursement", locale, fmt, paymentDetail, LoanTransactionType.DISBURSEMENT.getValue(), null, null, null, "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); this.accountTransfersWritePlatformService.transferFunds(accountTransferDTO);
} }
@@ -1310,7 +1310,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
portfolioAccountData.accountId(), chargeData.getLoanId(), "Loan Charge Payment", null, null, null, portfolioAccountData.accountId(), chargeData.getLoanId(), "Loan Charge Payment", null, null, null,
null, LoanTransactionType.CHARGE_PAYMENT.getValue(), chargeData.getId(), null, LoanTransactionType.CHARGE_PAYMENT.getValue(), chargeData.getId(),
installmentChargeData.getInstallmentNumber(), AccountTransferType.CHARGE_PAYMENT.getValue(), null, installmentChargeData.getInstallmentNumber(), AccountTransferType.CHARGE_PAYMENT.getValue(), null,
null, null, null); null, null, null, null);
transferFeeCharge(sb, accountTransferDTO); transferFeeCharge(sb, accountTransferDTO);
} }
} }
@@ -1321,7 +1321,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
chargeData.getAmountOutstanding(), PortfolioAccountType.SAVINGS, PortfolioAccountType.LOAN, chargeData.getAmountOutstanding(), PortfolioAccountType.SAVINGS, PortfolioAccountType.LOAN,
portfolioAccountData.accountId(), chargeData.getLoanId(), "Loan Charge Payment", null, null, null, null, portfolioAccountData.accountId(), chargeData.getLoanId(), "Loan Charge Payment", null, null, null, null,
LoanTransactionType.CHARGE_PAYMENT.getValue(), chargeData.getId(), 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); transferFeeCharge(sb, accountTransferDTO);
} }
} }
@@ -2033,7 +2033,7 @@ public class LoanWritePlatformServiceJpaRepositoryImpl implements LoanWritePlatf
final AccountTransferDTO accountTransferDTO = new AccountTransferDTO(transactionDate, amount, PortfolioAccountType.SAVINGS, final AccountTransferDTO accountTransferDTO = new AccountTransferDTO(transactionDate, amount, PortfolioAccountType.SAVINGS,
PortfolioAccountType.LOAN, portfolioAccountData.accountId(), loanId, "Loan Charge Payment", locale, fmt, null, null, PortfolioAccountType.LOAN, portfolioAccountData.accountId(), loanId, "Loan Charge Payment", locale, fmt, null, null,
LoanTransactionType.CHARGE_PAYMENT.getValue(), loanChargeId, loanInstallmentNumber, 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); this.accountTransfersWritePlatformService.transferFunds(accountTransferDTO);
return transaction; return transaction;
@@ -178,6 +178,8 @@ public class DepositsApiConstants {
public static final String preMatureCloseOnDateParamName = "preMatureCloseOnDate"; public static final String preMatureCloseOnDateParamName = "preMatureCloseOnDate";
public static final String linkedAccountParamName = "linkAccountId";
// template // template
public static final String chartTemplate = "chartTemplate"; public static final String chartTemplate = "chartTemplate";
@@ -295,6 +297,7 @@ public class DepositsApiConstants {
fixedDepositRequestData.addAll(DEPOSIT_ACCOUNT_REQUEST_DATA_PARAMETERS); fixedDepositRequestData.addAll(DEPOSIT_ACCOUNT_REQUEST_DATA_PARAMETERS);
fixedDepositRequestData.addAll(PRECLOSURE_REQUEST_DATA_PARAMETERS); fixedDepositRequestData.addAll(PRECLOSURE_REQUEST_DATA_PARAMETERS);
fixedDepositRequestData.addAll(DEPOSIT_TERM_REQUEST_DATA_PARAMETERS); fixedDepositRequestData.addAll(DEPOSIT_TERM_REQUEST_DATA_PARAMETERS);
fixedDepositRequestData.add(linkedAccountParamName);
return fixedDepositRequestData; return fixedDepositRequestData;
} }
@@ -303,6 +306,7 @@ public class DepositsApiConstants {
fixedDepositResponseData.addAll(DEPOSIT_ACCOUNT_REQUEST_DATA_PARAMETERS); fixedDepositResponseData.addAll(DEPOSIT_ACCOUNT_REQUEST_DATA_PARAMETERS);
fixedDepositResponseData.addAll(PRECLOSURE_RESPONSE_DATA_PARAMETERS); fixedDepositResponseData.addAll(PRECLOSURE_RESPONSE_DATA_PARAMETERS);
fixedDepositResponseData.addAll(DEPOSIT_TERM_RESPONSE_DATA_PARAMETERS); fixedDepositResponseData.addAll(DEPOSIT_TERM_RESPONSE_DATA_PARAMETERS);
fixedDepositResponseData.add(linkedAccountParamName);
return fixedDepositResponseData; return fixedDepositResponseData;
} }
@@ -130,6 +130,7 @@ public class SavingsApiConstants {
// Savings account associations // Savings account associations
public static final String transactions = "transactions"; public static final String transactions = "transactions";
public static final String charges = "charges"; 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, public static final Set<String> SAVINGS_PRODUCT_REQUEST_DATA_PARAMETERS = new HashSet<String>(Arrays.asList(localeParamName,
monthDayFormatParamName, nameParamName, shortNameParamName, descriptionParamName, currencyCodeParamName, 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.serialization.FromJsonHelper;
import org.mifosplatform.infrastructure.core.service.Page; import org.mifosplatform.infrastructure.core.service.Page;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext; 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.DepositAccountType;
import org.mifosplatform.portfolio.savings.DepositsApiConstants; import org.mifosplatform.portfolio.savings.DepositsApiConstants;
import org.mifosplatform.portfolio.savings.SavingsApiConstants; import org.mifosplatform.portfolio.savings.SavingsApiConstants;
@@ -69,6 +71,7 @@ public class FixedDepositAccountsApiResource {
private final SavingsAccountChargeReadPlatformService savingsAccountChargeReadPlatformService; private final SavingsAccountChargeReadPlatformService savingsAccountChargeReadPlatformService;
private final FromJsonHelper fromJsonHelper; private final FromJsonHelper fromJsonHelper;
private final DepositAccountPreMatureCalculationPlatformService accountPreMatureCalculationPlatformService; private final DepositAccountPreMatureCalculationPlatformService accountPreMatureCalculationPlatformService;
private final AccountAssociationsReadPlatformService accountAssociationsReadPlatformService;
@Autowired @Autowired
public FixedDepositAccountsApiResource(final DepositAccountReadPlatformService depositAccountReadPlatformService, public FixedDepositAccountsApiResource(final DepositAccountReadPlatformService depositAccountReadPlatformService,
@@ -76,7 +79,8 @@ public class FixedDepositAccountsApiResource {
final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService, final PortfolioCommandSourceWritePlatformService commandsSourceWritePlatformService,
final ApiRequestParameterHelper apiRequestParameterHelper, final ApiRequestParameterHelper apiRequestParameterHelper,
final SavingsAccountChargeReadPlatformService savingsAccountChargeReadPlatformService, final FromJsonHelper fromJsonHelper, final SavingsAccountChargeReadPlatformService savingsAccountChargeReadPlatformService, final FromJsonHelper fromJsonHelper,
final DepositAccountPreMatureCalculationPlatformService accountPreMatureCalculationPlatformService) { final DepositAccountPreMatureCalculationPlatformService accountPreMatureCalculationPlatformService,
final AccountAssociationsReadPlatformService accountAssociationsReadPlatformService) {
this.depositAccountReadPlatformService = depositAccountReadPlatformService; this.depositAccountReadPlatformService = depositAccountReadPlatformService;
this.context = context; this.context = context;
this.toApiJsonSerializer = toApiJsonSerializer; this.toApiJsonSerializer = toApiJsonSerializer;
@@ -85,6 +89,7 @@ public class FixedDepositAccountsApiResource {
this.savingsAccountChargeReadPlatformService = savingsAccountChargeReadPlatformService; this.savingsAccountChargeReadPlatformService = savingsAccountChargeReadPlatformService;
this.fromJsonHelper = fromJsonHelper; this.fromJsonHelper = fromJsonHelper;
this.accountPreMatureCalculationPlatformService = accountPreMatureCalculationPlatformService; this.accountPreMatureCalculationPlatformService = accountPreMatureCalculationPlatformService;
this.accountAssociationsReadPlatformService = accountAssociationsReadPlatformService;
} }
@GET @GET
@@ -170,12 +175,14 @@ public class FixedDepositAccountsApiResource {
Collection<SavingsAccountTransactionData> transactions = null; Collection<SavingsAccountTransactionData> transactions = null;
Collection<SavingsAccountChargeData> charges = null; Collection<SavingsAccountChargeData> charges = null;
PortfolioAccountData linkedAccount = null;
final Set<String> associationParameters = ApiParameterHelper.extractAssociationsForResponseIfProvided(uriInfo.getQueryParameters()); final Set<String> associationParameters = ApiParameterHelper.extractAssociationsForResponseIfProvided(uriInfo.getQueryParameters());
if (!associationParameters.isEmpty()) { if (!associationParameters.isEmpty()) {
if (associationParameters.contains("all")) { 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)) { if (associationParameters.contains(SavingsApiConstants.transactions)) {
@@ -195,6 +202,11 @@ public class FixedDepositAccountsApiResource {
charges = currentCharges; charges = currentCharges;
} }
} }
if (associationParameters.contains(SavingsApiConstants.linkedAccount)) {
mandatoryResponseParameters.add(SavingsApiConstants.linkedAccount);
linkedAccount = this.accountAssociationsReadPlatformService.retriveSavingsAssociation(accountId);
}
} }
FixedDepositAccountData templateData = null; FixedDepositAccountData templateData = null;
@@ -206,7 +218,7 @@ public class FixedDepositAccountsApiResource {
staffInSelectedOfficeOnly); staffInSelectedOfficeOnly);
} }
return FixedDepositAccountData.withTemplateOptions(savingsAccount, templateData, transactions, charges); return FixedDepositAccountData.associationsAndTemplate(savingsAccount, templateData, transactions, charges, linkedAccount);
} }
@PUT @PUT
@@ -5,11 +5,9 @@
*/ */
package org.mifosplatform.portfolio.savings.data; 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.depositAmountParamName;
import static org.mifosplatform.portfolio.savings.DepositsApiConstants.depositPeriodParamName;
import static org.mifosplatform.portfolio.savings.DepositsApiConstants.depositPeriodFrequencyIdParamName; 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.inMultiplesOfDepositTermParamName;
import static org.mifosplatform.portfolio.savings.DepositsApiConstants.inMultiplesOfDepositTermTypeIdParamName; import static org.mifosplatform.portfolio.savings.DepositsApiConstants.inMultiplesOfDepositTermTypeIdParamName;
import static org.mifosplatform.portfolio.savings.DepositsApiConstants.interestFreeFromPeriodParamName; 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.interestFreePeriodFrequencyTypeIdParamName;
import static org.mifosplatform.portfolio.savings.DepositsApiConstants.interestFreeToPeriodParamName; import static org.mifosplatform.portfolio.savings.DepositsApiConstants.interestFreeToPeriodParamName;
import static org.mifosplatform.portfolio.savings.DepositsApiConstants.maxDepositTermParamName; 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.minDepositTermParamName;
import static org.mifosplatform.portfolio.savings.DepositsApiConstants.minDepositTermTypeIdParamName;
import static org.mifosplatform.portfolio.savings.DepositsApiConstants.preClosurePenalApplicableParamName; import static org.mifosplatform.portfolio.savings.DepositsApiConstants.preClosurePenalApplicableParamName;
import static org.mifosplatform.portfolio.savings.DepositsApiConstants.preClosurePenalInterestOnTypeIdParamName; import static org.mifosplatform.portfolio.savings.DepositsApiConstants.preClosurePenalInterestOnTypeIdParamName;
import static org.mifosplatform.portfolio.savings.DepositsApiConstants.preClosurePenalInterestParamName; 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.nominalAnnualInterestRateParamName;
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.productIdParamName; import static org.mifosplatform.portfolio.savings.SavingsApiConstants.productIdParamName;
import static org.mifosplatform.portfolio.savings.SavingsApiConstants.submittedOnDateParamName; import static org.mifosplatform.portfolio.savings.SavingsApiConstants.submittedOnDateParamName;
import static org.mifosplatform.portfolio.savings.DepositsApiConstants.linkedAccountParamName;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.math.BigDecimal; 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.SavingsInterestCalculationType;
import org.mifosplatform.portfolio.savings.SavingsPeriodFrequencyType; import org.mifosplatform.portfolio.savings.SavingsPeriodFrequencyType;
import org.mifosplatform.portfolio.savings.SavingsPostingInterestPeriodType; import org.mifosplatform.portfolio.savings.SavingsPostingInterestPeriodType;
import org.mifosplatform.portfolio.savings.domain.SavingsAccount;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@@ -276,6 +278,11 @@ public class DepositAccountDataValidator {
.integerZeroOrGreater(); .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) { 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); 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) { private void validatePreClosureDetailForSubmit(final JsonElement element, final DataValidatorBuilder baseDataValidator) {
@@ -464,7 +476,7 @@ public class DepositAccountDataValidator {
baseDataValidator.reset().parameter(minDepositTermTypeIdParamName).value(minDepositTermType) baseDataValidator.reset().parameter(minDepositTermTypeIdParamName).value(minDepositTermType)
.isOneOfTheseValues(SavingsPeriodFrequencyType.integerValues()); .isOneOfTheseValues(SavingsPeriodFrequencyType.integerValues());
} }
if (fromApiJsonHelper.parameterExists(maxDepositTermTypeIdParamName, element)) { if (fromApiJsonHelper.parameterExists(maxDepositTermTypeIdParamName, element)) {
final Integer maxDepositTermType = this.fromApiJsonHelper.extractIntegerSansLocaleNamed(maxDepositTermTypeIdParamName, element); final Integer maxDepositTermType = this.fromApiJsonHelper.extractIntegerSansLocaleNamed(maxDepositTermTypeIdParamName, element);
baseDataValidator.reset().parameter(maxDepositTermTypeIdParamName).value(maxDepositTermType) 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) { private void validateSavingsCharges(final JsonElement element, final DataValidatorBuilder baseDataValidator) {
if (element.isJsonObject()) { if (element.isJsonObject()) {
@@ -15,6 +15,7 @@ import org.mifosplatform.infrastructure.codes.data.CodeValueData;
import org.mifosplatform.infrastructure.core.data.EnumOptionData; import org.mifosplatform.infrastructure.core.data.EnumOptionData;
import org.mifosplatform.organisation.monetary.data.CurrencyData; import org.mifosplatform.organisation.monetary.data.CurrencyData;
import org.mifosplatform.organisation.staff.data.StaffData; 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.charge.data.ChargeData;
import org.mifosplatform.portfolio.savings.DepositAccountType; import org.mifosplatform.portfolio.savings.DepositAccountType;
import org.mifosplatform.portfolio.savings.service.SavingsEnumerations; import org.mifosplatform.portfolio.savings.service.SavingsEnumerations;
@@ -47,6 +48,8 @@ public class FixedDepositAccountData extends DepositAccountData {
// used for account close // used for account close
private EnumOptionData onAccountClosure; private EnumOptionData onAccountClosure;
private final PortfolioAccountData linkedAccount;
private Collection<EnumOptionData> interestFreePeriodTypeOptions; private Collection<EnumOptionData> interestFreePeriodTypeOptions;
private Collection<EnumOptionData> preClosurePenalInterestOnTypeOptions; private Collection<EnumOptionData> preClosurePenalInterestOnTypeOptions;
private Collection<EnumOptionData> depositTermTypeOptions; private Collection<EnumOptionData> depositTermTypeOptions;
@@ -67,6 +70,7 @@ public class FixedDepositAccountData extends DepositAccountData {
final LocalDate maturityDate, final Integer depositPeriod, final EnumOptionData depositPeriodFrequency, final LocalDate maturityDate, final Integer depositPeriod, final EnumOptionData depositPeriodFrequency,
final EnumOptionData onAccountClosure) { final EnumOptionData onAccountClosure) {
final PortfolioAccountData linkedAccount = null;
final Collection<EnumOptionData> interestFreePeriodTypeOptions = null; final Collection<EnumOptionData> interestFreePeriodTypeOptions = null;
final Collection<EnumOptionData> preClosurePenalInterestOnTypeOptions = null; final Collection<EnumOptionData> preClosurePenalInterestOnTypeOptions = null;
final Collection<EnumOptionData> depositTermTypeOptions = null; final Collection<EnumOptionData> depositTermTypeOptions = null;
@@ -97,7 +101,7 @@ public class FixedDepositAccountData extends DepositAccountData {
maxDepositTermType, inMultiplesOfDepositTerm, inMultiplesOfDepositTermType, depositAmount, maturityAmount, maturityDate, maxDepositTermType, inMultiplesOfDepositTerm, inMultiplesOfDepositTermType, depositAmount, maturityAmount, maturityDate,
depositPeriod, depositPeriodFrequency, depositTermTypeOptions, inMultiplesOfDepositTermTypeOptions, depositPeriod, depositPeriodFrequency, depositTermTypeOptions, inMultiplesOfDepositTermTypeOptions,
depositPeriodFrequencyOptions, depositType, onAccountClosure, onAccountClosureOptions, paymentTypeOptions, depositPeriodFrequencyOptions, depositType, onAccountClosure, onAccountClosureOptions, paymentTypeOptions,
savingsAccountDatas); savingsAccountDatas, linkedAccount);
} }
public static FixedDepositAccountData withInterestChart(final FixedDepositAccountData account, 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.inMultiplesOfDepositTerm, account.inMultiplesOfDepositTermType, account.depositAmount, account.maturityAmount,
account.maturityDate, account.depositPeriod, account.depositPeriodFrequency, account.depositTermTypeOptions, account.maturityDate, account.depositPeriod, account.depositPeriodFrequency, account.depositTermTypeOptions,
account.inMultiplesOfDepositTermTypeOptions, account.depositTermTypeOptions, account.depositType, account.onAccountClosure, 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, public static FixedDepositAccountData associationsAndTemplate(final FixedDepositAccountData account, FixedDepositAccountData template,
final FixedDepositAccountData template, final Collection<SavingsAccountTransactionData> transactions, final Collection<SavingsAccountTransactionData> transactions, final Collection<SavingsAccountChargeData> charges,
final Collection<SavingsAccountChargeData> charges) { final PortfolioAccountData linkedAccount) {
if (template == null) { if (template == null) {
final Collection<DepositProductData> productOptions = null; template = account;
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);
} }
return new FixedDepositAccountData(account.id, account.accountNo, account.externalId, account.groupId, account.groupName, 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, account.maturityAmount, account.maturityDate, account.depositPeriod, account.depositPeriodFrequency,
template.depositTermTypeOptions, template.inMultiplesOfDepositTermTypeOptions, template.depositPeriodFrequencyOptions, template.depositTermTypeOptions, template.inMultiplesOfDepositTermTypeOptions, template.depositPeriodFrequencyOptions,
account.depositType, account.onAccountClosure, account.onAccountClosureOptions, account.paymentTypeOptions, account.depositType, account.onAccountClosure, account.onAccountClosureOptions, account.paymentTypeOptions,
account.savingsAccounts); template.savingsAccounts, linkedAccount);
} }
public static FixedDepositAccountData withTemplateOptions(final FixedDepositAccountData account, 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<ChargeData> chargeOptions, final Collection<EnumOptionData> interestFreePeriodTypeOptions,
final Collection<EnumOptionData> preClosurePenalInterestOnTypeOptions, final Collection<EnumOptionData> depositTermTypeOptions, final Collection<EnumOptionData> preClosurePenalInterestOnTypeOptions, final Collection<EnumOptionData> depositTermTypeOptions,
final Collection<EnumOptionData> inMultiplesOfDepositTermTypeOptions, 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, return new FixedDepositAccountData(account.id, account.accountNo, account.externalId, account.groupId, account.groupName,
account.clientId, account.clientName, account.savingsProductId, account.savingsProductName, account.fieldOfficerId, 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.inMultiplesOfDepositTerm, account.inMultiplesOfDepositTermType, account.depositAmount, account.maturityAmount,
account.maturityDate, account.depositPeriod, account.depositPeriodFrequency, depositTermTypeOptions, account.maturityDate, account.depositPeriod, account.depositPeriodFrequency, depositTermTypeOptions,
inMultiplesOfDepositTermTypeOptions, depositPeriodFrequencyOptions, account.depositType, account.onAccountClosure, 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, 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 Integer depositPeriod = null;
final EnumOptionData depositPeriodFrequency = null; final EnumOptionData depositPeriodFrequency = null;
final EnumOptionData onAccountClosure = null; final EnumOptionData onAccountClosure = null;
final PortfolioAccountData linkedAccount = null;
final Collection<EnumOptionData> interestFreePeriodTypeOptions = null; final Collection<EnumOptionData> interestFreePeriodTypeOptions = null;
final Collection<EnumOptionData> preClosurePenalInterestOnTypeOptions = null; final Collection<EnumOptionData> preClosurePenalInterestOnTypeOptions = null;
@@ -284,7 +269,7 @@ public class FixedDepositAccountData extends DepositAccountData {
preClosurePenalInterestOnTypeOptions, minDepositTerm, maxDepositTerm, minDepositTermType, maxDepositTermType, preClosurePenalInterestOnTypeOptions, minDepositTerm, maxDepositTerm, minDepositTermType, maxDepositTermType,
inMultiplesOfDepositTerm, inMultiplesOfDepositTermType, depositAmount, maturityAmount, maturityDate, depositPeriod, inMultiplesOfDepositTerm, inMultiplesOfDepositTermType, depositAmount, maturityAmount, maturityDate, depositPeriod,
depositPeriodFrequency, depositTermTypeOptions, inMultiplesOfDepositTermTypeOptions, depositPeriodFrequencyOptions, depositPeriodFrequency, depositTermTypeOptions, inMultiplesOfDepositTermTypeOptions, depositPeriodFrequencyOptions,
depositType, onAccountClosure, onAccountClosureOptions, paymentTypeOptions, savingsAccountDatas); depositType, onAccountClosure, onAccountClosureOptions, paymentTypeOptions, savingsAccountDatas, linkedAccount);
} }
public static FixedDepositAccountData preClosureDetails(final Long accountId, BigDecimal maturityAmount, 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> inMultiplesOfDepositTermTypeOptions = null;
final Collection<EnumOptionData> depositPeriodFrequencyOptions = null; final Collection<EnumOptionData> depositPeriodFrequencyOptions = null;
final EnumOptionData depositType = SavingsEnumerations.depositType(DepositAccountType.FIXED_DEPOSIT.getValue()); final EnumOptionData depositType = SavingsEnumerations.depositType(DepositAccountType.FIXED_DEPOSIT.getValue());
final PortfolioAccountData linkedAccount = null;
return new FixedDepositAccountData(accountId, accountNo, externalId, groupId, groupName, clientId, clientName, productId, return new FixedDepositAccountData(accountId, accountNo, externalId, groupId, groupName, clientId, clientName, productId,
productName, fieldOfficerId, fieldOfficerName, status, timeline, currency, nominalAnnualInterestRate, interestPeriodType, productName, fieldOfficerId, fieldOfficerName, status, timeline, currency, nominalAnnualInterestRate, interestPeriodType,
@@ -368,7 +354,7 @@ public class FixedDepositAccountData extends DepositAccountData {
preClosurePenalInterestOnTypeOptions, minDepositTerm, maxDepositTerm, minDepositTermType, maxDepositTermType, preClosurePenalInterestOnTypeOptions, minDepositTerm, maxDepositTerm, minDepositTermType, maxDepositTermType,
inMultiplesOfDepositTerm, inMultiplesOfDepositTermType, depositAmount, maturityAmount, maturityDate, depositPeriod, inMultiplesOfDepositTerm, inMultiplesOfDepositTermType, depositAmount, maturityAmount, maturityDate, depositPeriod,
depositPeriodFrequency, depositTermTypeOptions, inMultiplesOfDepositTermTypeOptions, depositPeriodFrequencyOptions, depositPeriodFrequency, depositTermTypeOptions, inMultiplesOfDepositTermTypeOptions, depositPeriodFrequencyOptions,
depositType, onAccountClosure, onAccountClosureOptions, paymentTypeOptions, savingsAccountDatas); depositType, onAccountClosure, onAccountClosureOptions, paymentTypeOptions, savingsAccountDatas, linkedAccount);
} }
public static FixedDepositAccountData withClosureTemplateDetails(final FixedDepositAccountData account, 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.inMultiplesOfDepositTerm, account.inMultiplesOfDepositTermType, account.depositAmount, account.maturityAmount,
account.maturityDate, account.depositPeriod, account.depositPeriodFrequency, account.depositTermTypeOptions, account.maturityDate, account.depositPeriod, account.depositPeriodFrequency, account.depositTermTypeOptions,
account.inMultiplesOfDepositTermTypeOptions, account.depositPeriodFrequencyOptions, account.depositType, 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, 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> inMultiplesOfDepositTermTypeOptions,
final Collection<EnumOptionData> depositPeriodFrequencyOptions, final EnumOptionData depositType, final Collection<EnumOptionData> depositPeriodFrequencyOptions, final EnumOptionData depositType,
final EnumOptionData onAccountClosure, final Collection<EnumOptionData> onAccountClosureOptions, 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, super(id, accountNo, externalId, groupId, groupName, clientId, clientName, productId, productName, fieldofficerId,
fieldofficerName, status, timeline, currency, nominalAnnualInterestRate, interestPeriodType, interestPostingPeriodType, fieldofficerName, status, timeline, currency, nominalAnnualInterestRate, interestPeriodType, interestPostingPeriodType,
@@ -454,6 +441,7 @@ public class FixedDepositAccountData extends DepositAccountData {
this.depositPeriod = depositPeriod; this.depositPeriod = depositPeriod;
this.depositPeriodFrequency = depositPeriodFrequency; this.depositPeriodFrequency = depositPeriodFrequency;
this.onAccountClosure = onAccountClosure; this.onAccountClosure = onAccountClosure;
this.linkedAccount = linkedAccount;
// template // template
this.interestFreePeriodTypeOptions = interestFreePeriodTypeOptions; this.interestFreePeriodTypeOptions = interestFreePeriodTypeOptions;
@@ -185,9 +185,13 @@ public class DepositAccountDomainServiceJpa implements DepositAccountDomainServi
final LocalDate transactionStartDate = reinvestedDeposit.getActivationLocalDate(); final LocalDate transactionStartDate = reinvestedDeposit.getActivationLocalDate();
final LocalDate nextTransactionStartDate = reinvestedDeposit.nextDepositDate(transactionStartDate); final LocalDate nextTransactionStartDate = reinvestedDeposit.nextDepositDate(transactionStartDate);
reinvestedDeposit.updateMaturityDateAndAmount(mc, nextTransactionStartDate); 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); reinvestedDeposit.updateMaturityDateAndAmount(mc, nextTransactionStartDate);
this.savingsAccountRepository.save(reinvestedDeposit); this.savingsAccountRepository.save(reinvestedDeposit);
autoGenerateAccountNumber(reinvestedDeposit); autoGenerateAccountNumber(reinvestedDeposit);
} else if (rdAccount.isTransferToSavingsOnClosure()) { } 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.SavingsInterestCalculationType;
import org.mifosplatform.portfolio.savings.SavingsPeriodFrequencyType; import org.mifosplatform.portfolio.savings.SavingsPeriodFrequencyType;
import org.mifosplatform.portfolio.savings.SavingsPostingInterestPeriodType; 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.domain.interest.PostingPeriod;
import org.mifosplatform.portfolio.savings.service.SavingsEnumerations; import org.mifosplatform.portfolio.savings.service.SavingsEnumerations;
import org.mifosplatform.useradministration.domain.AppUser; import org.mifosplatform.useradministration.domain.AppUser;
@@ -326,7 +325,7 @@ public class FixedDepositAccount extends SavingsAccount {
final Integer onAccountClosureId = command.integerValueOfParameterNamed(onAccountClosureIdParamName); final Integer onAccountClosureId = command.integerValueOfParameterNamed(onAccountClosureIdParamName);
final DepositAccountOnClosureType onClosureType = DepositAccountOnClosureType.fromInt(onAccountClosureId); final DepositAccountOnClosureType onClosureType = DepositAccountOnClosureType.fromInt(onAccountClosureId);
this.accountTermAndPreClosure.updateOnAccountClosureStatus(onClosureType); this.accountTermAndPreClosure.updateOnAccountClosureStatus(onClosureType);
postPreMaturityInterest(closedDate); postPreMaturityInterest(closedDate);
// withdraw deposit amount before closing the account // withdraw deposit amount before closing the account
@@ -351,18 +350,8 @@ public class FixedDepositAccount extends SavingsAccount {
} }
@Override @Override
protected void processAccountUponActivation(final DateTimeFormatter fmt) { public Money activateWithBalance() {
final Money depositAmount = Money.of(this.currency, this.accountTermAndPreClosure.depositAmount()); return 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 SavingsAccountTransaction close(final AppUser currentUser, final JsonCommand command, final LocalDate tenantsTodayDate, public SavingsAccountTransaction close(final AppUser currentUser, final JsonCommand command, final LocalDate tenantsTodayDate,
@@ -576,14 +565,10 @@ public class FixedDepositAccount extends SavingsAccount {
return interestPostedToDate; return interestPostedToDate;
} }
@Override public void updateMaturityDateAndAmountAfterAccountActivation(final MathContext mc) {
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;
List<SavingsAccountTransaction> allTransactions = new ArrayList<SavingsAccountTransaction>(); List<SavingsAccountTransaction> allTransactions = new ArrayList<SavingsAccountTransaction>();
allTransactions.addAll(retreiveOrderedNonInterestPostingTransactions()); allTransactions.addAll(retreiveOrderedNonInterestPostingTransactions());
updateMaturityDateAndAmount(mc, allTransactions); updateMaturityDateAndAmount(mc, allTransactions);
return actualChanges;
} }
private LocalDate depositStartDate() { 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"); baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode("no.valid.interest.rate.slab.available");
}else{ } else {
final LocalDate chartFromDate = this.chart.getFromDateAsLocalDate(); final LocalDate chartFromDate = this.chart.getFromDateAsLocalDate();
LocalDate chartEndDate = this.chart.getEndDateAsLocalDate(); LocalDate chartEndDate = this.chart.getEndDateAsLocalDate();
chartEndDate = chartEndDate == null ? DateUtils.getLocalDateOfTenant() : chartEndDate; chartEndDate = chartEndDate == null ? DateUtils.getLocalDateOfTenant() : chartEndDate;
final LocalDateInterval chartInterval = LocalDateInterval.create(chartFromDate, 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"); baseDataValidator.reset().failWithCodeNoParameterAddedToErrorCode("no.valid.interest.rate.slab.available");
} }
} }
@@ -657,7 +642,7 @@ public class FixedDepositAccount extends SavingsAccount {
public boolean isReinvestOnClosure() { public boolean isReinvestOnClosure() {
return this.accountTermAndPreClosure.isReinvestOnClosure(); return this.accountTermAndPreClosure.isReinvestOnClosure();
} }
public boolean isTransferToSavingsOnClosure() { public boolean isTransferToSavingsOnClosure() {
return this.accountTermAndPreClosure.isTransferToSavingsOnClosure(); return this.accountTermAndPreClosure.isTransferToSavingsOnClosure();
} }
@@ -683,14 +668,15 @@ public class FixedDepositAccount extends SavingsAccount {
final Integer lockinPeriodFrequency = this.lockinPeriodFrequency; final Integer lockinPeriodFrequency = this.lockinPeriodFrequency;
final boolean withdrawalFeeApplicableForTransfer = false; final boolean withdrawalFeeApplicableForTransfer = false;
final String accountNumber = null; final String accountNumber = null;
final FixedDepositAccount reInvestedAccount = FixedDepositAccount.createNewApplicationForSubmittal(client, group, product, fieldOfficer, accountNumber, externalId, final FixedDepositAccount reInvestedAccount = FixedDepositAccount
accountType, getClosedOnDate(), closedBy, interestRate, compoundingPeriodType, postingPeriodType, interestCalculationType, .createNewApplicationForSubmittal(client, group, product, fieldOfficer, accountNumber, externalId, accountType,
daysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType, getClosedOnDate(), closedBy, interestRate, compoundingPeriodType, postingPeriodType, interestCalculationType,
withdrawalFeeApplicableForTransfer, savingsAccountCharges, newAccountTermAndPreClosure, newChart); daysInYearType, minRequiredOpeningBalance, lockinPeriodFrequency, lockinPeriodFrequencyType,
withdrawalFeeApplicableForTransfer, savingsAccountCharges, newAccountTermAndPreClosure, newChart);
newAccountTermAndPreClosure.updateAccountReference(reInvestedAccount); newAccountTermAndPreClosure.updateAccountReference(reInvestedAccount);
newChart.updateDepositAccountReference(reInvestedAccount); newChart.updateDepositAccountReference(reInvestedAccount);
return reInvestedAccount; return reInvestedAccount;
} }
@@ -459,19 +459,8 @@ public class RecurringDepositAccount extends SavingsAccount {
} }
@Override @Override
protected void processAccountUponActivation(final DateTimeFormatter fmt) { public Money activateWithBalance() {
final Money minRequiredOpeningBalance = Money.of(this.currency, this.minRequiredOpeningBalance); return 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 SavingsAccountTransaction close(final AppUser currentUser, final JsonCommand command, final LocalDate tenantsTodayDate, 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(); 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 // auto enter deposit for minimum required opening balance when
// activating account. // activating account.
processAccountUponActivation(fmt); processAccountUponActivation();
return actualChanges; return actualChanges;
} }
protected void processAccountUponActivation(final DateTimeFormatter fmt) { public void processAccountUponActivation() {
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());
}
// update annual fee due date // update annual fee due date
for (SavingsAccountCharge charge : this.charges()) { for (SavingsAccountCharge charge : this.charges()) {
@@ -1573,7 +1558,11 @@ public class SavingsAccount extends AbstractPersistable<Long> {
// TODO : AA add activation charges to actual changes list // 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.status = SavingsAccountStatusType.ACTIVE.getValue();
this.approvedOnDate = appliedonDate; this.approvedOnDate = appliedonDate;
this.approvedBy = appliedBy; this.approvedBy = appliedBy;
@@ -1586,7 +1575,6 @@ public class SavingsAccount extends AbstractPersistable<Long> {
this.activatedOnDate = appliedonDate; this.activatedOnDate = appliedonDate;
this.activatedBy = appliedBy; this.activatedBy = appliedBy;
this.lockedInUntilDate = calculateDateAccountIsLockedUntil(getActivationLocalDate()); this.lockedInUntilDate = calculateDateAccountIsLockedUntil(getActivationLocalDate());
processAccountUponActivation(fmt);
} }
private void payActivationCharges() { private void payActivationCharges() {
@@ -100,6 +100,10 @@ public enum SavingsAccountStatusType {
public boolean isActive() { public boolean isActive() {
return this.value.equals(SavingsAccountStatusType.ACTIVE.getValue()); return this.value.equals(SavingsAccountStatusType.ACTIVE.getValue());
} }
public boolean isActiveOrAwaitingApprovalOrDisbursal() {
return isApproved() || isSubmittedAndPendingApproval() || isActive();
}
public boolean isClosed() { public boolean isClosed() {
return this.value.equals(SavingsAccountStatusType.CLOSED.getValue()) || isRejected() || isApplicationWithdrawnByApplicant(); return this.value.equals(SavingsAccountStatusType.CLOSED.getValue()) || isRejected() || isApplicationWithdrawnByApplicant();
@@ -278,9 +278,12 @@ public class DepositAccountReadPlatformServiceImpl implements DepositAccountRead
Long officeId = loggedInUser.getOffice().getId(); Long officeId = loggedInUser.getOffice().getId();
ClientData client = null; ClientData client = null;
Collection<SavingsAccountData> savingsAccountDatas = null;
if (clientId != null) { if (clientId != null) {
client = this.clientReadPlatformService.retrieveOne(clientId); client = this.clientReadPlatformService.retrieveOne(clientId);
officeId = client.officeId(); officeId = client.officeId();
savingsAccountDatas = this.savingsAccountReadPlatformService.retrieveActiveForLookup(clientId,
DepositAccountType.SAVINGS_DEPOSIT);
} }
GroupGeneralData group = null; GroupGeneralData group = null;
@@ -381,7 +384,7 @@ public class DepositAccountReadPlatformServiceImpl implements DepositAccountRead
interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions,
withdrawalFeeTypeOptions, transactions, charges, chargeOptions, interestFreePeriodTypeOptions, withdrawalFeeTypeOptions, transactions, charges, chargeOptions, interestFreePeriodTypeOptions,
preClosurePenalInterestOnTypeOptions, depositTermTypeOptions, inMultiplesOfDepositTermTypeOptions, preClosurePenalInterestOnTypeOptions, depositTermTypeOptions, inMultiplesOfDepositTermTypeOptions,
depositPeriodFrequencyOptions); depositPeriodFrequencyOptions, savingsAccountDatas);
template = FixedDepositAccountData.withInterestChart((FixedDepositAccountData) template, accountChart); template = FixedDepositAccountData.withInterestChart((FixedDepositAccountData) template, accountChart);
} else if (depositAccountType.isRecurringDeposit()) { } else if (depositAccountType.isRecurringDeposit()) {
@@ -431,7 +434,7 @@ public class DepositAccountReadPlatformServiceImpl implements DepositAccountRead
interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions, interestCalculationTypeOptions, interestCalculationDaysInYearTypeOptions, lockinPeriodFrequencyTypeOptions,
withdrawalFeeTypeOptions, transactions, charges, chargeOptions, interestFreePeriodTypeOptions, withdrawalFeeTypeOptions, transactions, charges, chargeOptions, interestFreePeriodTypeOptions,
preClosurePenalInterestOnTypeOptions, depositTermTypeOptions, inMultiplesOfDepositTermTypeOptions, preClosurePenalInterestOnTypeOptions, depositTermTypeOptions, inMultiplesOfDepositTermTypeOptions,
depositPeriodFrequencyOptions); depositPeriodFrequencyOptions, savingsAccountDatas);
} else if (depositAccountType.isRecurringDeposit()) { } else if (depositAccountType.isRecurringDeposit()) {
template = RecurringDepositAccountData.withClientTemplate(clientId, clientName, groupId, groupName); 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.ApplicationCurrency;
import org.mifosplatform.organisation.monetary.domain.ApplicationCurrencyRepositoryWrapper; import org.mifosplatform.organisation.monetary.domain.ApplicationCurrencyRepositoryWrapper;
import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency; 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.office.domain.Office;
import org.mifosplatform.organisation.staff.domain.Staff; import org.mifosplatform.organisation.staff.domain.Staff;
import org.mifosplatform.organisation.workingdays.service.WorkingDaysWritePlatformService; import org.mifosplatform.organisation.workingdays.service.WorkingDaysWritePlatformService;
import org.mifosplatform.portfolio.account.PortfolioAccountType; 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.AccountTransfersReadPlatformService;
import org.mifosplatform.portfolio.account.service.AccountTransfersWritePlatformService;
import org.mifosplatform.portfolio.charge.domain.Charge; import org.mifosplatform.portfolio.charge.domain.Charge;
import org.mifosplatform.portfolio.charge.domain.ChargeRepositoryWrapper; import org.mifosplatform.portfolio.charge.domain.ChargeRepositoryWrapper;
import org.mifosplatform.portfolio.client.domain.Client; import org.mifosplatform.portfolio.client.domain.Client;
@@ -98,6 +104,8 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
private final SavingsAccountChargeRepositoryWrapper savingsAccountChargeRepository; private final SavingsAccountChargeRepositoryWrapper savingsAccountChargeRepository;
private final HolidayWritePlatformService holidayWritePlatformService; private final HolidayWritePlatformService holidayWritePlatformService;
private final WorkingDaysWritePlatformService workingDaysWritePlatformService; private final WorkingDaysWritePlatformService workingDaysWritePlatformService;
private final AccountAssociationsReadPlatformService accountAssociationsReadPlatformService;
private final AccountTransfersWritePlatformService accountTransfersWritePlatformService;
@Autowired @Autowired
public DepositAccountWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context, public DepositAccountWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context,
@@ -113,7 +121,9 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
final AccountTransfersReadPlatformService accountTransfersReadPlatformService, final ChargeRepositoryWrapper chargeRepository, final AccountTransfersReadPlatformService accountTransfersReadPlatformService, final ChargeRepositoryWrapper chargeRepository,
final SavingsAccountChargeRepositoryWrapper savingsAccountChargeRepository, final SavingsAccountChargeRepositoryWrapper savingsAccountChargeRepository,
final HolidayWritePlatformService holidayWritePlatformService, final HolidayWritePlatformService holidayWritePlatformService,
final WorkingDaysWritePlatformService workingDaysWritePlatformService) { final WorkingDaysWritePlatformService workingDaysWritePlatformService,
final AccountAssociationsReadPlatformService accountAssociationsReadPlatformService,
final AccountTransfersWritePlatformService accountTransfersWritePlatformService) {
this.context = context; this.context = context;
this.savingAccountRepository = savingAccountRepository; this.savingAccountRepository = savingAccountRepository;
this.savingsAccountTransactionRepository = savingsAccountTransactionRepository; this.savingsAccountTransactionRepository = savingsAccountTransactionRepository;
@@ -130,6 +140,8 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
this.savingsAccountChargeRepository = savingsAccountChargeRepository; this.savingsAccountChargeRepository = savingsAccountChargeRepository;
this.holidayWritePlatformService = holidayWritePlatformService; this.holidayWritePlatformService = holidayWritePlatformService;
this.workingDaysWritePlatformService = workingDaysWritePlatformService; this.workingDaysWritePlatformService = workingDaysWritePlatformService;
this.accountAssociationsReadPlatformService = accountAssociationsReadPlatformService;
this.accountTransfersWritePlatformService = accountTransfersWritePlatformService;
} }
@Transactional @Transactional
@@ -149,15 +161,24 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
final Map<String, Object> changes = account.activate(user, command, DateUtils.getLocalDateOfTenant()); final Map<String, Object> changes = account.activate(user, command, DateUtils.getLocalDateOfTenant());
if (!changes.isEmpty()) { if (!changes.isEmpty()) {
final Locale locale = command.extractLocale();
final MathContext mc = MathContext.DECIMAL64; final DateTimeFormatter fmt = DateTimeFormat.forPattern(command.dateFormat()).withLocale(locale);
if (account.isBeforeLastPostingPeriod(account.getActivationLocalDate())) { Money amountForDeposit = account.activateWithBalance();
final LocalDate today = DateUtils.getLocalDateOfTenant(); if (amountForDeposit.isGreaterThanZero()) {
account.postInterest(mc, today); final PortfolioAccountData portfolioAccountData = this.accountAssociationsReadPlatformService
} else { .retriveSavingsAssociation(savingsId);
final LocalDate today = DateUtils.getLocalDateOfTenant(); if (portfolioAccountData == null) {
account.calculateInterestUsing(mc, today); 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);
}
} }
// account.processAccountUponActivation(fmt);
account.validateAccountBalanceDoesNotBecomeNegative(SavingsAccountTransactionType.PAY_CHARGE.name()); account.validateAccountBalanceDoesNotBecomeNegative(SavingsAccountTransactionType.PAY_CHARGE.name());
@@ -182,10 +203,9 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
this.context.authenticatedUser(); this.context.authenticatedUser();
if(depositAccountType.isFixedDeposit()){ if (depositAccountType.isFixedDeposit()) { throw new DepositAccountTransactionNotAllowedException(savingsId, "deposit",
throw new DepositAccountTransactionNotAllowedException(savingsId, "deposit", depositAccountType); depositAccountType); }
}
this.depositAccountTransactionDataValidator.validate(command, depositAccountType); this.depositAccountTransactionDataValidator.validate(command, depositAccountType);
final SavingsAccount account = this.depositAccountAssembler.assembleFrom(savingsId, depositAccountType); final SavingsAccount account = this.depositAccountAssembler.assembleFrom(savingsId, depositAccountType);
@@ -224,10 +244,9 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
this.depositAccountTransactionDataValidator.validate(command, depositAccountType); this.depositAccountTransactionDataValidator.validate(command, depositAccountType);
if(depositAccountType.isFixedDeposit()){ if (depositAccountType.isFixedDeposit()) { throw new DepositAccountTransactionNotAllowedException(savingsId, "withdraw",
throw new DepositAccountTransactionNotAllowedException(savingsId, "withdraw", depositAccountType); depositAccountType); }
}
final LocalDate transactionDate = command.localDateValueOfParameterNamed("transactionDate"); final LocalDate transactionDate = command.localDateValueOfParameterNamed("transactionDate");
final BigDecimal transactionAmount = command.bigDecimalValueOfParameterNamed("transactionAmount"); final BigDecimal transactionAmount = command.bigDecimalValueOfParameterNamed("transactionAmount");
@@ -309,11 +328,10 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
@Override @Override
public CommandProcessingResult undoTransaction(final Long savingsId, final Long transactionId, public CommandProcessingResult undoTransaction(final Long savingsId, final Long transactionId,
final boolean allowAccountTransferModification, final DepositAccountType depositAccountType) { final boolean allowAccountTransferModification, final DepositAccountType depositAccountType) {
if(depositAccountType.isFixedDeposit()){ if (depositAccountType.isFixedDeposit()) { throw new DepositAccountTransactionNotAllowedException(savingsId, "undo",
throw new DepositAccountTransactionNotAllowedException(savingsId, "undo", depositAccountType); depositAccountType); }
}
final SavingsAccount account = this.depositAccountAssembler.assembleFrom(savingsId, depositAccountType); final SavingsAccount account = this.depositAccountAssembler.assembleFrom(savingsId, depositAccountType);
final Set<Long> existingTransactionIds = new HashSet<Long>(); final Set<Long> existingTransactionIds = new HashSet<Long>();
final Set<Long> existingReversedTransactionIds = new HashSet<Long>(); final Set<Long> existingReversedTransactionIds = new HashSet<Long>();
@@ -360,11 +378,10 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
public CommandProcessingResult adjustDepositTransaction(final Long savingsId, final Long transactionId, final JsonCommand command, public CommandProcessingResult adjustDepositTransaction(final Long savingsId, final Long transactionId, final JsonCommand command,
final DepositAccountType depositAccountType) { final DepositAccountType depositAccountType) {
if(depositAccountType.isFixedDeposit()){ if (depositAccountType.isFixedDeposit()) { throw new DepositAccountTransactionNotAllowedException(savingsId, "modify",
throw new DepositAccountTransactionNotAllowedException(savingsId, "modify", depositAccountType); depositAccountType); }
}
this.depositAccountTransactionDataValidator.validate(command, depositAccountType); this.depositAccountTransactionDataValidator.validate(command, depositAccountType);
final SavingsAccountTransaction savingsAccountTransaction = this.savingsAccountTransactionRepository final SavingsAccountTransaction savingsAccountTransaction = this.savingsAccountTransactionRepository
.findOneByIdAndSavingsAccountId(transactionId, savingsId); .findOneByIdAndSavingsAccountId(transactionId, savingsId);
if (savingsAccountTransaction == null) { throw new SavingsAccountTransactionNotFoundException(savingsId, transactionId); } if (savingsAccountTransaction == null) { throw new SavingsAccountTransactionNotFoundException(savingsId, transactionId); }
@@ -375,7 +392,6 @@ public class DepositAccountWritePlatformServiceJpaRepositoryImpl implements Depo
if (this.accountTransfersReadPlatformService.isAccountTransfer(transactionId, PortfolioAccountType.SAVINGS)) { throw new PlatformServiceUnavailableException( if (this.accountTransfersReadPlatformService.isAccountTransfer(transactionId, PortfolioAccountType.SAVINGS)) { throw new PlatformServiceUnavailableException(
"error.msg.saving.account.transfer.transaction.update.not.allowed", "Deposit account transaction:" + transactionId "error.msg.saving.account.transfer.transaction.update.not.allowed", "Deposit account transaction:" + transactionId
+ " update not allowed as it involves in account transfer", transactionId); } + " update not allowed as it involves in account transfer", transactionId); }
final LocalDate today = DateUtils.getLocalDateOfTenant(); 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.data.DataValidatorBuilder;
import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException; import org.mifosplatform.infrastructure.core.exception.PlatformApiDataValidationException;
import org.mifosplatform.infrastructure.core.exception.PlatformDataIntegrityException; 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.core.service.DateUtils;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext; import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext;
import org.mifosplatform.organisation.staff.domain.Staff; import org.mifosplatform.organisation.staff.domain.Staff;
import org.mifosplatform.organisation.staff.domain.StaffRepositoryWrapper; 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.AccountNumberGenerator;
import org.mifosplatform.portfolio.client.domain.AccountNumberGeneratorFactory; import org.mifosplatform.portfolio.client.domain.AccountNumberGeneratorFactory;
import org.mifosplatform.portfolio.client.domain.Client; import org.mifosplatform.portfolio.client.domain.Client;
@@ -80,6 +83,8 @@ public class DepositApplicationProcessWritePlatformServiceJpaRepositoryImpl impl
private final StaffRepositoryWrapper staffRepository; private final StaffRepositoryWrapper staffRepository;
private final SavingsAccountApplicationTransitionApiJsonValidator savingsAccountApplicationTransitionApiJsonValidator; private final SavingsAccountApplicationTransitionApiJsonValidator savingsAccountApplicationTransitionApiJsonValidator;
private final SavingsAccountChargeAssembler savingsAccountChargeAssembler; private final SavingsAccountChargeAssembler savingsAccountChargeAssembler;
private final AccountAssociationsRepository accountAssociationsRepository;
private final FromJsonHelper fromJsonHelper;
@Autowired @Autowired
public DepositApplicationProcessWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context, public DepositApplicationProcessWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context,
@@ -91,7 +96,8 @@ public class DepositApplicationProcessWritePlatformServiceJpaRepositoryImpl impl
final SavingsAccountApplicationTransitionApiJsonValidator savingsAccountApplicationTransitionApiJsonValidator, final SavingsAccountApplicationTransitionApiJsonValidator savingsAccountApplicationTransitionApiJsonValidator,
final SavingsAccountChargeAssembler savingsAccountChargeAssembler, final SavingsAccountChargeAssembler savingsAccountChargeAssembler,
final FixedDepositAccountRepository fixedDepositAccountRepository, final FixedDepositAccountRepository fixedDepositAccountRepository,
final RecurringDepositAccountRepository recurringDepositAccountRepository) { final RecurringDepositAccountRepository recurringDepositAccountRepository,
final AccountAssociationsRepository accountAssociationsRepository, final FromJsonHelper fromJsonHelper) {
this.context = context; this.context = context;
this.savingAccountRepository = savingAccountRepository; this.savingAccountRepository = savingAccountRepository;
this.depositAccountAssembler = depositAccountAssembler; this.depositAccountAssembler = depositAccountAssembler;
@@ -106,6 +112,8 @@ public class DepositApplicationProcessWritePlatformServiceJpaRepositoryImpl impl
this.savingsAccountChargeAssembler = savingsAccountChargeAssembler; this.savingsAccountChargeAssembler = savingsAccountChargeAssembler;
this.fixedDepositAccountRepository = fixedDepositAccountRepository; this.fixedDepositAccountRepository = fixedDepositAccountRepository;
this.recurringDepositAccountRepository = recurringDepositAccountRepository; this.recurringDepositAccountRepository = recurringDepositAccountRepository;
this.accountAssociationsRepository = accountAssociationsRepository;
this.fromJsonHelper = fromJsonHelper;
} }
/* /*
@@ -164,6 +172,16 @@ public class DepositApplicationProcessWritePlatformServiceJpaRepositoryImpl impl
this.savingAccountRepository.save(account); 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(); final Long savingsId = account.getId();
return new CommandProcessingResultBuilder() // return new CommandProcessingResultBuilder() //
.withCommandId(command.commandId()) // .withCommandId(command.commandId()) //
@@ -261,6 +279,40 @@ public class DepositApplicationProcessWritePlatformServiceJpaRepositoryImpl impl
this.savingAccountRepository.saveAndFlush(account); 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() // return new CommandProcessingResultBuilder() //
.withCommandId(command.commandId()) // .withCommandId(command.commandId()) //
.withEntityId(accountId) // .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.ApplicationCurrency;
import org.mifosplatform.organisation.monetary.domain.ApplicationCurrencyRepositoryWrapper; import org.mifosplatform.organisation.monetary.domain.ApplicationCurrencyRepositoryWrapper;
import org.mifosplatform.organisation.monetary.domain.MonetaryCurrency; 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.office.domain.Office;
import org.mifosplatform.organisation.staff.domain.Staff; import org.mifosplatform.organisation.staff.domain.Staff;
import org.mifosplatform.organisation.workingdays.service.WorkingDaysWritePlatformService; import org.mifosplatform.organisation.workingdays.service.WorkingDaysWritePlatformService;
@@ -152,16 +153,14 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
final Map<String, Object> changes = account.activate(user, command, DateUtils.getLocalDateOfTenant()); final Map<String, Object> changes = account.activate(user, command, DateUtils.getLocalDateOfTenant());
if (!changes.isEmpty()) { if (!changes.isEmpty()) {
final Locale locale = command.extractLocale();
final MathContext mc = MathContext.DECIMAL64; final DateTimeFormatter fmt = DateTimeFormat.forPattern(command.dateFormat()).withLocale(locale);
if (account.isBeforeLastPostingPeriod(account.getActivationLocalDate())) { Money amountForDeposit = account.activateWithBalance();
final LocalDate today = DateUtils.getLocalDateOfTenant(); if (amountForDeposit.isGreaterThanZero()) {
account.postInterest(mc, today); this.savingsAccountDomainService.handleDeposit(account, fmt, account.getActivationLocalDate(),
} else { amountForDeposit.getAmount(), null);
final LocalDate today = DateUtils.getLocalDateOfTenant();
account.calculateInterestUsing(mc, today);
} }
account.processAccountUponActivation();
account.validateAccountBalanceDoesNotBecomeNegative(SavingsAccountTransactionType.PAY_CHARGE.name()); account.validateAccountBalanceDoesNotBecomeNegative(SavingsAccountTransactionType.PAY_CHARGE.name());
this.savingAccountRepository.save(account); this.savingAccountRepository.save(account);
@@ -499,11 +498,11 @@ public class SavingsAccountWritePlatformServiceJpaRepositoryImpl implements Savi
this.savingsAccountTransactionDataValidator.validateClosing(command); this.savingsAccountTransactionDataValidator.validateClosing(command);
final SavingsAccount account = this.savingAccountAssembler.assembleFrom(savingsId); final SavingsAccount account = this.savingAccountAssembler.assembleFrom(savingsId);
final boolean isLinkedWithAnyActiveLoan = this.accountAssociationsReadPlatformService.isLinkedWithAnyActiveLoan(savingsId); final boolean isLinkedWithAnyActiveLoan = this.accountAssociationsReadPlatformService.isLinkedWithAnyActiveAccount(savingsId);
if (isLinkedWithAnyActiveLoan) { if (isLinkedWithAnyActiveLoan) {
final String defaultUserMessage = "Closing savings account with id:" + savingsId 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); 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.exception.PlatformDataIntegrityException;
import org.mifosplatform.infrastructure.core.service.DateUtils; import org.mifosplatform.infrastructure.core.service.DateUtils;
import org.mifosplatform.infrastructure.security.service.PlatformSecurityContext; 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.Staff;
import org.mifosplatform.organisation.staff.domain.StaffRepositoryWrapper; import org.mifosplatform.organisation.staff.domain.StaffRepositoryWrapper;
import org.mifosplatform.portfolio.client.domain.AccountNumberGenerator; 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.SavingsAccountAssembler;
import org.mifosplatform.portfolio.savings.domain.SavingsAccountCharge; import org.mifosplatform.portfolio.savings.domain.SavingsAccountCharge;
import org.mifosplatform.portfolio.savings.domain.SavingsAccountChargeAssembler; 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.SavingsAccountRepositoryWrapper;
import org.mifosplatform.portfolio.savings.domain.SavingsProduct; import org.mifosplatform.portfolio.savings.domain.SavingsProduct;
import org.mifosplatform.portfolio.savings.domain.SavingsProductRepository; import org.mifosplatform.portfolio.savings.domain.SavingsProductRepository;
@@ -77,6 +79,7 @@ public class SavingsApplicationProcessWritePlatformServiceJpaRepositoryImpl impl
private final SavingsAccountApplicationTransitionApiJsonValidator savingsAccountApplicationTransitionApiJsonValidator; private final SavingsAccountApplicationTransitionApiJsonValidator savingsAccountApplicationTransitionApiJsonValidator;
private final SavingsAccountChargeAssembler savingsAccountChargeAssembler; private final SavingsAccountChargeAssembler savingsAccountChargeAssembler;
private final CommandProcessingService commandProcessingService; private final CommandProcessingService commandProcessingService;
private final SavingsAccountDomainService savingsAccountDomainService;
@Autowired @Autowired
public SavingsApplicationProcessWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context, public SavingsApplicationProcessWritePlatformServiceJpaRepositoryImpl(final PlatformSecurityContext context,
@@ -86,8 +89,8 @@ public class SavingsApplicationProcessWritePlatformServiceJpaRepositoryImpl impl
final GroupRepository groupRepository, final SavingsProductRepository savingsProductRepository, final GroupRepository groupRepository, final SavingsProductRepository savingsProductRepository,
final NoteRepository noteRepository, final StaffRepositoryWrapper staffRepository, final NoteRepository noteRepository, final StaffRepositoryWrapper staffRepository,
final SavingsAccountApplicationTransitionApiJsonValidator savingsAccountApplicationTransitionApiJsonValidator, final SavingsAccountApplicationTransitionApiJsonValidator savingsAccountApplicationTransitionApiJsonValidator,
final SavingsAccountChargeAssembler savingsAccountChargeAssembler, final SavingsAccountChargeAssembler savingsAccountChargeAssembler, final CommandProcessingService commandProcessingService,
final CommandProcessingService commandProcessingService) { final SavingsAccountDomainService savingsAccountDomainService) {
this.context = context; this.context = context;
this.savingAccountRepository = savingAccountRepository; this.savingAccountRepository = savingAccountRepository;
this.savingAccountAssembler = savingAccountAssembler; this.savingAccountAssembler = savingAccountAssembler;
@@ -101,6 +104,7 @@ public class SavingsApplicationProcessWritePlatformServiceJpaRepositoryImpl impl
this.savingsAccountApplicationTransitionApiJsonValidator = savingsAccountApplicationTransitionApiJsonValidator; this.savingsAccountApplicationTransitionApiJsonValidator = savingsAccountApplicationTransitionApiJsonValidator;
this.savingsAccountChargeAssembler = savingsAccountChargeAssembler; this.savingsAccountChargeAssembler = savingsAccountChargeAssembler;
this.commandProcessingService = commandProcessingService; this.commandProcessingService = commandProcessingService;
this.savingsAccountDomainService = savingsAccountDomainService;
} }
/* /*
@@ -438,13 +442,20 @@ public class SavingsApplicationProcessWritePlatformServiceJpaRepositoryImpl impl
@Override @Override
public CommandProcessingResult createActiveApplication(final SavingsAccountDataDTO savingsAccountDataDTO) { public CommandProcessingResult createActiveApplication(final SavingsAccountDataDTO savingsAccountDataDTO) {
final CommandWrapper commandWrapper = new CommandWrapperBuilder().savingsAccountActivation(null).build(); final CommandWrapper commandWrapper = new CommandWrapperBuilder().savingsAccountActivation(null).build();
boolean rollbackTransaction = this.commandProcessingService.validateCommand(commandWrapper, savingsAccountDataDTO.getAppliedBy()); boolean rollbackTransaction = this.commandProcessingService.validateCommand(commandWrapper, savingsAccountDataDTO.getAppliedBy());
final SavingsAccount account = this.savingAccountAssembler.assembleFrom(savingsAccountDataDTO.getClient(),savingsAccountDataDTO.getGroup(), final SavingsAccount account = this.savingAccountAssembler.assembleFrom(savingsAccountDataDTO.getClient(),
savingsAccountDataDTO.getSavingsProduct(),savingsAccountDataDTO.getApplicationDate(),savingsAccountDataDTO.getAppliedBy()); savingsAccountDataDTO.getGroup(), savingsAccountDataDTO.getSavingsProduct(), savingsAccountDataDTO.getApplicationDate(),
account.approveAndActivateApplication(savingsAccountDataDTO.getApplicationDate().toDate(), savingsAccountDataDTO.getAppliedBy(), savingsAccountDataDTO.getFmt()); 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); this.savingAccountRepository.save(account);
if (account.isAccountNumberRequiresAutoGeneration()) { if (account.isAccountNumberRequiresAutoGeneration()) {
@@ -454,8 +465,8 @@ public class SavingsApplicationProcessWritePlatformServiceJpaRepositoryImpl impl
this.savingAccountRepository.save(account); this.savingAccountRepository.save(account);
} }
return new CommandProcessingResultBuilder() // return new CommandProcessingResultBuilder() //
.withSavingsId(account.getId()) // .withSavingsId(account.getId()) //
.setRollbackTransaction(rollbackTransaction)// .setRollbackTransaction(rollbackTransaction)//
.build(); .build();
} }
} }