/*
* Copyright (c) 2005-2011 Grameen Foundation USA
* All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*
* See also http://www.apache.org/licenses/LICENSE-2.0.html for an
* explanation of the license and how it is applied.
*/
package org.mifos.accounts.loan.persistence;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertThat;
import static org.mifos.application.meeting.util.helpers.MeetingType.CUSTOMER_MEETING;
import static org.mifos.application.meeting.util.helpers.RecurrenceType.WEEKLY;
import static org.mifos.framework.util.helpers.TestObjectFactory.EVERY_WEEK;
import java.io.IOException;
import java.math.BigDecimal;
import java.sql.Date;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.List;
import junit.framework.Assert;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.mifos.accounts.business.AccountActionDateEntity;
import org.mifos.accounts.business.AccountBO;
import org.mifos.accounts.business.AccountFeesEntity;
import org.mifos.accounts.business.AccountTestUtils;
import org.mifos.accounts.fees.business.FeeBO;
import org.mifos.accounts.fees.util.helpers.FeeCategory;
import org.mifos.accounts.fees.util.helpers.FeeFormula;
import org.mifos.accounts.fees.util.helpers.FeePayment;
import org.mifos.accounts.fees.util.helpers.FeeStatus;
import org.mifos.accounts.loan.business.LoanBO;
import org.mifos.accounts.loan.business.LoanBOTestUtils;
import org.mifos.accounts.loan.business.LoanFeeScheduleEntity;
import org.mifos.accounts.loan.business.LoanScheduleEntity;
import org.mifos.accounts.loan.business.OriginalLoanFeeScheduleEntity;
import org.mifos.accounts.loan.business.OriginalLoanScheduleEntity;
import org.mifos.accounts.loan.business.matchers.OriginalLoanFeeScheduleEntityMatcher;
import org.mifos.accounts.loan.business.matchers.OriginalLoanScheduleEntitiesMatcher;
import org.mifos.accounts.loan.persistance.LegacyLoanDao;
import org.mifos.accounts.persistence.LegacyAccountDao;
import org.mifos.accounts.productdefinition.business.LoanOfferingBO;
import org.mifos.accounts.productdefinition.util.helpers.ApplicableTo;
import org.mifos.accounts.productdefinition.util.helpers.InterestType;
import org.mifos.accounts.productdefinition.util.helpers.PrdStatus;
import org.mifos.accounts.util.helpers.AccountActionTypes;
import org.mifos.accounts.util.helpers.AccountState;
import org.mifos.accounts.util.helpers.AccountStates;
import org.mifos.accounts.util.helpers.PaymentStatus;
import org.mifos.application.admin.servicefacade.InvalidDateException;
import org.mifos.application.meeting.business.MeetingBO;
import org.mifos.customers.business.CustomerBO;
import org.mifos.customers.util.helpers.CustomerStatus;
import org.mifos.framework.MifosIntegrationTestCase;
import org.mifos.framework.exceptions.PersistenceException;
import org.mifos.framework.hibernate.helper.StaticHibernateUtil;
import org.mifos.framework.util.helpers.Money;
import org.mifos.framework.util.helpers.TestObjectFactory;
import org.springframework.beans.factory.annotation.Autowired;
public class LegacyLoanDaoIntegrationTest extends MifosIntegrationTestCase {
private static final double DELTA = 0.00000001;
@Autowired
private LegacyLoanDao legacyLoanDao;
// collaborators
private CustomerBO center;
private CustomerBO group;
private MeetingBO meeting;
private AccountBO loanAccount;
private AccountBO loanAccountForDisbursement;
private LoanBO badAccount;
private LoanBO goodAccount;
@Autowired
private LegacyAccountDao legacyAccountDao;
@Before
public void setUp() throws Exception {
meeting = TestObjectFactory.createMeeting(TestObjectFactory.getNewMeetingForToday(WEEKLY, EVERY_WEEK,
CUSTOMER_MEETING));
center = TestObjectFactory.createWeeklyFeeCenterForTestGetLoanAccounts("Center", meeting);
group = TestObjectFactory.createWeeklyFeeGroupUnderCenter("Group", CustomerStatus.GROUP_ACTIVE, center);
loanAccount = getLoanAccount(group, meeting);
badAccount = getBadAccount();
goodAccount = getGoodAccount();
}
@After
public void tearDown() throws Exception {
try {
loanAccount = null;
badAccount = null;
goodAccount = null;
loanAccountForDisbursement = null;
group = null;
center = null;
} catch (Exception e) {
} finally {
StaticHibernateUtil.flushSession();
}
}
@Test
public void testFindBySystemId() throws Exception {
LegacyLoanDao loanPersistance = legacyLoanDao;
LoanBO loanBO = loanPersistance.findBySystemId(loanAccount.getGlobalAccountNum());
Assert.assertEquals(loanAccount.getGlobalAccountNum(), loanBO.getGlobalAccountNum());
Assert.assertEquals(loanAccount.getAccountId(), loanBO.getAccountId());
}
@Test
public void testFindByExternalId() throws Exception {
String externalId = "ABC";
StaticHibernateUtil.startTransaction();
loanAccount.setExternalId(externalId);
StaticHibernateUtil.flushSession();
LegacyLoanDao loanPersistance = legacyLoanDao;
LoanBO loanBO = loanPersistance.findByExternalId(loanAccount.getExternalId());
Assert.assertEquals(externalId, loanBO.getExternalId());
Assert.assertEquals(loanAccount.getAccountId(), loanBO.getAccountId());
}
@Test
public void testFindIndividualLoans() throws Exception {
LegacyLoanDao loanPersistance = legacyLoanDao;
List<LoanBO> listLoanBO = loanPersistance.findIndividualLoans(loanAccount.getAccountId().toString());
Assert.assertEquals(0, listLoanBO.size());
}
@Ignore
@Test
public void testGetFeeAmountAtDisbursement() throws Exception {
loanAccountForDisbursement = getLoanAccount("cdfg", group, meeting, AccountState.LOAN_APPROVED);
Assert.assertEquals(30.0,
legacyLoanDao.getFeeAmountAtDisbursement(loanAccountForDisbursement.getAccountId(), getCurrency()).getAmountDoubleValue(), DELTA);
}
@Test
public void testGetLoanAccountsInArrearsInGoodStanding() throws PersistenceException, InvalidDateException {
Short latenessDays = 1;
Calendar actionDate = new GregorianCalendar();
int year = actionDate.get(Calendar.YEAR);
int month = actionDate.get(Calendar.MONTH);
int day = actionDate.get(Calendar.DAY_OF_MONTH);
actionDate = new GregorianCalendar(year, month, day - latenessDays);
Date date = new Date(actionDate.getTimeInMillis());
Calendar checkDate = new GregorianCalendar(year, month, day - 15);
Date startDate = new Date(checkDate.getTimeInMillis());
for (AccountActionDateEntity accountAction : loanAccount.getAccountActionDates()) {
LoanBOTestUtils.setActionDate(accountAction, startDate);
}
TestObjectFactory.updateObject(loanAccount);
loanAccount = legacyAccountDao.getAccount(loanAccount.getAccountId());
List<Integer> list = legacyLoanDao.getLoanAccountsInArrearsInGoodStanding(latenessDays);
Assert.assertNotNull(list);
LoanBO testBO = TestObjectFactory.getObject(LoanBO.class, list.get(0));
Assert
.assertEquals(Short.valueOf(AccountStates.LOANACC_ACTIVEINGOODSTANDING), testBO.getAccountState()
.getId());
// Get the first action date i.e for the first Installment
Short firstInstallment = 1;
AccountActionDateEntity actionDates = testBO.getAccountActionDate(firstInstallment);
Assert.assertTrue(date.after(actionDates.getActionDate()));
Assert.assertFalse(actionDates.isPaid());
}
@Test
public void testGetAccount() throws Exception {
LoanBO loanBO = legacyLoanDao.getAccount(loanAccount.getAccountId());
Assert.assertEquals(loanBO.getAccountId(), loanAccount.getAccountId());
}
@Test
public void testGetLoanAccountsActiveInGoodBadStanding() throws PersistenceException {
List<LoanBO> loanBO1 = legacyLoanDao.getLoanAccountsActiveInGoodBadStanding(loanAccount.getCustomer()
.getCustomerId());
Assert.assertEquals(3, loanBO1.size());
}
@Test
public void testGetLastPaymentAction() throws Exception {
Date startDate = new Date(System.currentTimeMillis());
loanAccountForDisbursement = getLoanAccount(AccountState.LOAN_APPROVED, startDate);
disburseLoan(startDate);
Assert.assertEquals("Last payment action should be 'PAYMENT'", AccountActionTypes.DISBURSAL.getValue(),
legacyLoanDao.getLastPaymentAction(loanAccountForDisbursement.getAccountId()));
}
@Test
public void testGetLoanOffering() throws Exception {
LoanOfferingBO loanOffering = TestObjectFactory.createCompleteLoanOfferingObject();
LoanOfferingBO loanOfferingBO = legacyLoanDao.getLoanOffering(loanOffering.getPrdOfferingId(),
TestObjectFactory.TEST_LOCALE);
Assert.assertEquals(loanOfferingBO.getPrdOfferingId(), loanOffering.getPrdOfferingId());
TestObjectFactory.removeObject(loanOfferingBO);
}
@SuppressWarnings("deprecation")
private void disburseLoan(final Date startDate) throws Exception {
((LoanBO) loanAccountForDisbursement).disburseLoan("1234", startDate, Short.valueOf("1"),
loanAccountForDisbursement.getPersonnel(), startDate, Short.valueOf("1"), Short.valueOf("1"), null);
StaticHibernateUtil.flushSession();
}
private AccountBO getLoanAccount(final AccountState state, final Date startDate) {
LoanOfferingBO loanOffering = TestObjectFactory.createLoanOffering("Loanvcfg", "bhgf", ApplicableTo.GROUPS,
startDate, PrdStatus.LOAN_ACTIVE, 300.0, 1.2, (short) 3, InterestType.FLAT, meeting);
final int disbursalType = 1;
return TestObjectFactory.createLoanAccountWithDisbursement("99999999999", group, state, startDate,
loanOffering, disbursalType);
}
private AccountBO getLoanAccount(final String shortName, final CustomerBO customer, final MeetingBO meeting,
final AccountState state) {
Date startDate = new Date(System.currentTimeMillis());
LoanOfferingBO loanOffering = TestObjectFactory.createLoanOffering("Loan123", shortName, ApplicableTo.GROUPS,
startDate, PrdStatus.LOAN_ACTIVE, 300.0, 1.2, (short) 3, InterestType.FLAT, meeting);
final int disbursalType = 1;
return TestObjectFactory.createLoanAccountWithDisbursement("42423142341", customer, state, startDate, loanOffering, disbursalType);
}
private AccountBO getLoanAccount(final CustomerBO customer, final MeetingBO meeting) {
Date startDate = new Date(System.currentTimeMillis());
LoanOfferingBO loanOffering = TestObjectFactory.createLoanOffering("Loancfgb", "dhsq", ApplicableTo.GROUPS,
startDate, PrdStatus.LOAN_ACTIVE, 300.0, 1.2, (short) 3, InterestType.FLAT, meeting);
return TestObjectFactory.createLoanAccount("42423142341", customer, AccountState.LOAN_ACTIVE_IN_GOOD_STANDING,
startDate, loanOffering);
}
private LoanBO getBadAccount() {
Date startDate = new Date(System.currentTimeMillis());
LoanOfferingBO loanOffering = TestObjectFactory.createLoanOffering("Loanabcd", "abcd", ApplicableTo.CLIENTS,
startDate, PrdStatus.LOAN_ACTIVE, 300.0, 1.2, (short) 3, InterestType.FLAT, meeting);
return TestObjectFactory.createLoanAccount("42423142323", group, AccountState.LOAN_ACTIVE_IN_BAD_STANDING,
startDate, loanOffering);
}
private LoanBO getGoodAccount() {
Date startDate = new Date(System.currentTimeMillis());
LoanOfferingBO loanOffering = TestObjectFactory.createLoanOffering("Loanabf", "abf", ApplicableTo.CLIENTS,
startDate, PrdStatus.LOAN_ACTIVE, 300.0, 1.2, (short) 3, InterestType.FLAT, meeting);
return TestObjectFactory.createLoanAccount("42423142342", group, AccountState.LOAN_ACTIVE_IN_GOOD_STANDING,
startDate, loanOffering);
}
@Ignore
@Test
public void testGetLoanAccountsInActiveBadStandingShouldReturnLoanBOInActiveBadByBranchId() throws Exception {
short branchId = 3;
List<LoanBO> loanList = legacyLoanDao.getLoanAccountsInActiveBadStanding(branchId, (short) -1, (short) -1);
Assert.assertEquals(1, loanList.size());
}
@Ignore
@Test
public void testGetLoanAccountsInActiveBadStandingShouldReturnLoanBOInActiveBadByBranchIdAndLoanOfficerId()
throws Exception {
short branchId = 3;
short loanOfficerId = 3;
List<LoanBO> loanList = legacyLoanDao.getLoanAccountsInActiveBadStanding(branchId, loanOfficerId, (short) -1);
Assert.assertEquals(1, loanList.size());
}
@Ignore
@Test
public void testGetLoanAccountsInActiveBadStandingShouldReturnLoanBOInActiveBadByBranchIdLoanOfficerIdAndLoanProductId()
throws Exception {
short branchId = 3;
short loanOfficerId = 3;
short loanProductId = badAccount.getLoanOffering().getPrdOfferingId();
List<LoanBO> loanList = legacyLoanDao.getLoanAccountsInActiveBadStanding(branchId, loanOfficerId,
loanProductId);
Assert.assertEquals(1, loanList.size());
}
@Ignore
@Test
public void testGetTotalOutstandingPrincipalOfLoanAccountsInActiveGoodStandingByBranchId() throws Exception {
short branchId = 3;
BigDecimal money = legacyLoanDao.getTotalOutstandingPrincipalOfLoanAccountsInActiveGoodStanding(branchId,
(short) -1, (short) -1);
Assert.assertEquals(0, new BigDecimal(600).compareTo(money));
}
@Ignore
@Test
public void testGetTotalOutstandingPrincipalOfLoanAccountsInActiveGoodStandingByBranchIdAndLoanOfficerId()
throws Exception {
short branchId = 3;
short loanOfficerId = 3;
BigDecimal money = legacyLoanDao.getTotalOutstandingPrincipalOfLoanAccountsInActiveGoodStanding(branchId,
loanOfficerId, (short) -1);
Assert.assertEquals(0, new BigDecimal(600).compareTo(money));
}
@Test
public void testGetTotalOutstandingPrincipalOfLoanAccountsInActiveGoodStandingByBranchIdLoanOfficerIdAndLoanProductId()
throws Exception {
short branchId = 3;
short loanOfficerId = 3;
short loanProductId = goodAccount.getLoanOffering().getPrdOfferingId();
BigDecimal money = legacyLoanDao.getTotalOutstandingPrincipalOfLoanAccountsInActiveGoodStanding(branchId,
loanOfficerId, loanProductId);
Assert.assertEquals(0, new BigDecimal(300).compareTo(money));
}
@Test
public void testGetActiveLoansBothInGoodAndBadStandingByLoanOfficer() throws Exception {
short branchId = 3;
short loanOfficerId = 3;
List<LoanBO> loanList = legacyLoanDao.getActiveLoansBothInGoodAndBadStandingByLoanOfficer(branchId,
loanOfficerId, (short) -1);
Assert.assertEquals(3, loanList.size());
}
@Test
public void testGetActiveLoansBothInGoodAndBadStandingByLoanOfficerAndLoanProduct() throws Exception {
short branchId = 3;
short loanOfficerId = 3;
short goodLoanProductId = goodAccount.getLoanOffering().getPrdOfferingId();
List<LoanBO> goodLoanList = legacyLoanDao.getActiveLoansBothInGoodAndBadStandingByLoanOfficer(branchId,
loanOfficerId, goodLoanProductId);
Assert.assertEquals(1, goodLoanList.size());
short badLoanProductId = badAccount.getLoanOffering().getPrdOfferingId();
List<LoanBO> badLoanList = legacyLoanDao.getActiveLoansBothInGoodAndBadStandingByLoanOfficer(branchId,
loanOfficerId, badLoanProductId);
Assert.assertEquals(1, badLoanList.size());
}
@Test
public void testSaveAndGetOriginalLoanScheduleEntity() throws PersistenceException, IOException {
ArrayList<OriginalLoanScheduleEntity> originalLoanScheduleEntities = new ArrayList<OriginalLoanScheduleEntity>();
Short installmentId = new Short("1");
Date date = new Date(new java.util.Date().getTime());
LoanScheduleEntity loanScheduleEntity = new LoanScheduleEntity(goodAccount, group, installmentId, date, PaymentStatus.UNPAID, Money.zero(), Money.zero());
originalLoanScheduleEntities.add(new OriginalLoanScheduleEntity(loanScheduleEntity));
legacyLoanDao.saveOriginalSchedule(originalLoanScheduleEntities);
List<OriginalLoanScheduleEntity> actual = legacyLoanDao.getOriginalLoanScheduleEntity(goodAccount.getAccountId());
Assert.assertEquals(1, actual.size());
Assert.assertNotNull(actual.get(0));
assertThat(actual, is(new OriginalLoanScheduleEntitiesMatcher(originalLoanScheduleEntities)));
}
@Test
public void testSaveAndGetOriginalLoanScheduleEntityWithFees() throws PersistenceException {
ArrayList<OriginalLoanScheduleEntity> originalLoanScheduleEntities = new ArrayList<OriginalLoanScheduleEntity>();
Date date = new Date(new java.util.Date().getTime());
Short installmentId = new Short("1");
FeeBO upfrontFee = TestObjectFactory.createOneTimeRateFee("Upfront Fee", FeeCategory.LOAN,
Double.valueOf("20"), FeeFormula.AMOUNT, FeePayment.UPFRONT, null);
AccountFeesEntity accountUpfrontFee = new AccountFeesEntity(goodAccount, upfrontFee, new Double("20.0"),
FeeStatus.ACTIVE.getValue(), null, date);
AccountTestUtils.addAccountFees(accountUpfrontFee, goodAccount);
TestObjectFactory.updateObject(goodAccount);
goodAccount = (LoanBO) TestObjectFactory.getObject(AccountBO.class, goodAccount.getAccountId());
LoanScheduleEntity loanScheduleEntity = new LoanScheduleEntity(goodAccount, group, installmentId, date, PaymentStatus.UNPAID, Money.zero(), Money.zero());
LoanFeeScheduleEntity feesEntity = new LoanFeeScheduleEntity(loanScheduleEntity, upfrontFee, accountUpfrontFee, Money.zero());
loanScheduleEntity.addAccountFeesAction(feesEntity);
OriginalLoanScheduleEntity originalLoanScheduleEntity = new OriginalLoanScheduleEntity(loanScheduleEntity);
OriginalLoanFeeScheduleEntity scheduleEntityFee = new OriginalLoanFeeScheduleEntity(feesEntity, originalLoanScheduleEntity);
originalLoanScheduleEntities.add(originalLoanScheduleEntity);
legacyLoanDao.saveOriginalSchedule(originalLoanScheduleEntities);
List<OriginalLoanScheduleEntity> actual = legacyLoanDao.getOriginalLoanScheduleEntity(goodAccount.getAccountId());
List<OriginalLoanFeeScheduleEntity> fees = new ArrayList<OriginalLoanFeeScheduleEntity>(actual.get(0).getAccountFeesActionDetails());
Assert.assertEquals(1, actual.size());
Assert.assertEquals(1, fees.size());
assertThat(actual, is(new OriginalLoanScheduleEntitiesMatcher(originalLoanScheduleEntities)));
assertThat(fees.get(0), is(new OriginalLoanFeeScheduleEntityMatcher(scheduleEntityFee)));
}
@Test
public void testGetAllLoanAccounts() throws Exception {
List<LoanBO> loanAccounts = legacyLoanDao.getAllLoanAccounts();
Assert.assertEquals(3, loanAccounts.size());
}
}