/*
* 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.servicefacade;
import static java.util.Collections.EMPTY_LIST;
import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import static org.mifos.framework.util.helpers.TestObjectFactory.TEST_LOCALE;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.mockito.Mockito.atLeastOnce;
import java.math.BigDecimal;
import java.util.Date;
import org.hamcrest.CoreMatchers;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mifos.accounts.acceptedpaymenttype.persistence.LegacyAcceptedPaymentTypeDao;
import org.mifos.accounts.business.AccountPaymentEntity;
import org.mifos.accounts.business.AccountTypeEntity;
import org.mifos.accounts.business.service.AccountBusinessService;
import org.mifos.accounts.exceptions.AccountException;
import org.mifos.accounts.loan.business.LoanBO;
import org.mifos.accounts.loan.business.ScheduleCalculatorAdaptor;
import org.mifos.accounts.persistence.LegacyAccountDao;
import org.mifos.application.admin.servicefacade.MonthClosingServiceFacade;
import org.mifos.application.master.business.MifosCurrency;
import org.mifos.application.servicefacade.ClientServiceFacade;
import org.mifos.application.servicefacade.SavingsServiceFacade;
import org.mifos.core.MifosRuntimeException;
import org.mifos.customers.business.CustomerBO;
import org.mifos.customers.personnel.business.PersonnelBO;
import org.mifos.customers.personnel.persistence.LegacyPersonnelDao;
import org.mifos.dto.domain.CustomerDto;
import org.mifos.framework.TestUtils;
import org.mifos.framework.exceptions.PersistenceException;
import org.mifos.framework.exceptions.ServiceException;
import org.mifos.framework.hibernate.helper.HibernateTransactionHelper;
import org.mifos.framework.util.DateTimeService;
import org.mifos.framework.util.helpers.Constants;
import org.mifos.framework.util.helpers.Money;
import org.mifos.security.util.SecurityConstants;
import org.mifos.security.util.UserContext;
import org.mockito.Matchers;
import org.mockito.Mock;
import org.mockito.internal.verification.AtLeast;
import org.mockito.runners.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class WebTierAccountServiceFacadeTest {
@Mock
private ScheduleCalculatorAdaptor scheduleCalculatorAdaptor;
@Mock
private AccountBusinessService accountBusinessService;
@Mock
private LoanBO loanBO;
@Mock
private CustomerBO customerBO;
@Mock
private CustomerDto customerDto;
@Mock
private LegacyAcceptedPaymentTypeDao acceptedPaymentTypePersistence;
@Mock
private AccountTypeEntity accountTypeEntity;
@Mock
private LegacyPersonnelDao personnelPersistence;
@Mock
private LegacyAccountDao legacyAccountDao;
@Mock
private HibernateTransactionHelper transactionHelper;
@Mock
private UserContext userContext;
@Mock
private MonthClosingServiceFacade monthClosingServiceFacade;
@Mock
private ClientServiceFacade clientServiceFacade;
@Mock
private SavingsServiceFacade savingsServiceFacade;
private WebTierAccountServiceFacade accountServiceFacade;
private MifosCurrency rupee;
private static final int LOAN_ID = 1;
private static final int CUSTOMER_ID = 1;
@Before
public void setUp() throws Exception {
accountServiceFacade = new WebTierAccountServiceFacade(null, transactionHelper,
accountBusinessService, scheduleCalculatorAdaptor, acceptedPaymentTypePersistence, personnelPersistence,
legacyAccountDao, monthClosingServiceFacade, clientServiceFacade, savingsServiceFacade){
@Override
void clearSessionAndRollback() {
// do nothing
}
@Override
UserContext getUserContext() {
return userContext;
}
};
rupee = new MifosCurrency(Short.valueOf("1"), "Rupee", BigDecimal.valueOf(1), "INR");
}
@SuppressWarnings("unchecked")
@Test
public void testGetAccountPaymentInformation() throws ServiceException, PersistenceException {
Date paymentDate = TestUtils.getDate(12, 12, 2012);
when(accountBusinessService.getAccount(LOAN_ID)).thenReturn(loanBO);
when(accountTypeEntity.getAccountTypeId()).thenReturn((short)1);
when(loanBO.getAccountType()).thenReturn(accountTypeEntity);
when(loanBO.getTotalPaymentDue()).thenReturn(Money.zero(rupee));
when(loanBO.getTotalRepayableAmount()).thenReturn(Money.zero(rupee));
Date lastPaymentDate = TestUtils.getDate(12, 12, 2012);
when(loanBO.findMostRecentNonzeroPaymentByPaymentDate()).thenReturn(new AccountPaymentEntity(null, null, null, null, null, lastPaymentDate));
Short transactionId = Short.valueOf("2");
when(acceptedPaymentTypePersistence.getAcceptedPaymentTypesForATransaction(TEST_LOCALE, transactionId)).thenReturn(EMPTY_LIST);
when(loanBO.getCustomer()).thenReturn(customerBO);
when(customerBO.toCustomerDto()).thenReturn(customerDto);
when(customerDto.getCustomerId()).thenReturn(CUSTOMER_ID);
AccountPaymentDto accountPaymentInformation = accountServiceFacade.getAccountPaymentInformation(LOAN_ID, Constants.LOAN, (short) 1, null, paymentDate);
Assert.assertEquals(lastPaymentDate, accountPaymentInformation.getLastPaymentDate());
verify(loanBO).findMostRecentNonzeroPaymentByPaymentDate();
verify(scheduleCalculatorAdaptor, times(1)).computeExtraInterest(loanBO, paymentDate);
verify(accountBusinessService, times(1)).getAccount(LOAN_ID);
verify(accountTypeEntity, times(1)).getAccountTypeId();
verify(loanBO, times(1)).getAccountType();
verify(loanBO, times(1)).getTotalPaymentDue();
verify(acceptedPaymentTypePersistence, times(1)).getAcceptedPaymentTypesForATransaction(TEST_LOCALE, transactionId);
}
@SuppressWarnings("unchecked")
@Test
public void testGetAccountPaymentInformationWhenPreviousPaymentsDoNotExist() throws ServiceException, PersistenceException {
Date paymentDate = TestUtils.getDate(12, 12, 2012);
when(accountBusinessService.getAccount(LOAN_ID)).thenReturn(loanBO);
when(accountTypeEntity.getAccountTypeId()).thenReturn((short)1);
when(loanBO.getAccountType()).thenReturn(accountTypeEntity);
when(loanBO.getTotalPaymentDue()).thenReturn(Money.zero(rupee));
when(loanBO.getTotalRepayableAmount()).thenReturn(Money.zero(rupee));
when(loanBO.findMostRecentNonzeroPaymentByPaymentDate()).thenReturn(null);
Short transactionId = Short.valueOf("2");
when(acceptedPaymentTypePersistence.getAcceptedPaymentTypesForATransaction(TEST_LOCALE, transactionId)).thenReturn(EMPTY_LIST);
when(loanBO.getCustomer()).thenReturn(customerBO);
when(customerBO.toCustomerDto()).thenReturn(customerDto);
when(customerDto.getCustomerId()).thenReturn(CUSTOMER_ID);
AccountPaymentDto accountPaymentInformation = accountServiceFacade.getAccountPaymentInformation(LOAN_ID, Constants.LOAN, (short) 1, null, paymentDate);
Assert.assertEquals(new Date(0), accountPaymentInformation.getLastPaymentDate());
verify(loanBO).findMostRecentNonzeroPaymentByPaymentDate();
verify(scheduleCalculatorAdaptor, times(1)).computeExtraInterest(loanBO, paymentDate);
verify(accountBusinessService, times(1)).getAccount(LOAN_ID);
verify(accountTypeEntity, times(1)).getAccountTypeId();
verify(loanBO, times(1)).getAccountType();
verify(loanBO, times(1)).getTotalPaymentDue();
verify(acceptedPaymentTypePersistence, times(1)).getAcceptedPaymentTypesForATransaction(TEST_LOCALE, transactionId);
}
@Test
public void shouldAdjustBackdatedPaymentMadeOnAccountIfAllowed() throws ServiceException, AccountException, PersistenceException {
String globalAccountNum = "123";
String adjustmentNote = "note";
Short personnelId = Short.valueOf("1");
PersonnelBO personnelBO = mock(PersonnelBO.class);
PersonnelBO loanOfficer = mock(PersonnelBO.class);
Date paymentDate = TestUtils.getDate(10, 10, 2010);
new DateTimeService().setCurrentDateTime(TestUtils.getDateTime(11, 10, 2010));
Short recordOfficeId = new Short("1");
Short recordLoanOfficer = new Short("1");
Integer paymentId = 1;
AccountPaymentEntity lastPmntToBeAdjusted = mock(AccountPaymentEntity.class);
when(loanBO.getLastPmntToBeAdjusted()).thenReturn(lastPmntToBeAdjusted);
when(loanBO.getOfficeId()).thenReturn(recordOfficeId);
when(loanBO.getPersonnel()).thenReturn(loanOfficer);
when(loanBO.getUserContext()).thenReturn(userContext);
when(loanBO.findPaymentById(paymentId)).thenReturn(lastPmntToBeAdjusted);
when(loanOfficer.getPersonnelId()).thenReturn(recordOfficeId);
when(lastPmntToBeAdjusted.getPaymentDate()).thenReturn(paymentDate);
when(lastPmntToBeAdjusted.getPaymentId()).thenReturn(paymentId);
when(accountBusinessService.findBySystemId(globalAccountNum)).thenReturn(loanBO);
when(personnelPersistence.findPersonnelById(personnelId)).thenReturn(personnelBO);
accountServiceFacade.applyAdjustment(globalAccountNum, adjustmentNote, personnelId);
verify(accountBusinessService, atLeastOnce()).findBySystemId(globalAccountNum);
verify(personnelPersistence).findPersonnelById(personnelId);
verify(loanBO).adjustLastPayment(adjustmentNote, personnelBO);
verify(loanBO, atLeastOnce()).setUserContext(userContext);
verify(legacyAccountDao).createOrUpdate(loanBO);
verify(transactionHelper).startTransaction();
verify(transactionHelper).commitTransaction();
verify(accountBusinessService).checkPermissionForAdjustmentOnBackDatedPayments(paymentDate, userContext,
recordOfficeId, recordLoanOfficer);
verify(lastPmntToBeAdjusted, times(2)).getPaymentDate();
}
@Test
public void shouldNotAdjustBackdatedPaymentMadeOnAccountIfNotAllowed() throws ServiceException, AccountException, PersistenceException {
String globalAccountNum = "123";
String adjustmentNote = "note";
Short personnelId = Short.valueOf("1");
PersonnelBO personnelBO = mock(PersonnelBO.class);
Date paymentDate = TestUtils.getDate(10, 10, 2010);
new DateTimeService().setCurrentDateTime(TestUtils.getDateTime(11, 10, 2010));
AccountPaymentEntity lastPmntToBeAdjusted = mock(AccountPaymentEntity.class);
Short recordOfficeId = new Short("1");
Short recordLoanOfficer = new Short("1");
PersonnelBO loanOfficer = mock(PersonnelBO.class);
when(loanBO.getPersonnel()).thenReturn(loanOfficer);
when(loanBO.getUserContext()).thenReturn(userContext);
when(loanOfficer.getPersonnelId()).thenReturn(recordOfficeId);
when(loanBO.getOfficeId()).thenReturn(recordOfficeId);
when(loanBO.getLastPmntToBeAdjusted()).thenReturn(lastPmntToBeAdjusted);
when(lastPmntToBeAdjusted.getPaymentDate()).thenReturn(paymentDate);
when(accountBusinessService.findBySystemId(globalAccountNum)).thenReturn(loanBO);
when(personnelPersistence.findPersonnelById(personnelId)).thenReturn(personnelBO);
doThrow(new ServiceException(SecurityConstants.KEY_ACTIVITY_NOT_ALLOWED)).
when(accountBusinessService).checkPermissionForAdjustmentOnBackDatedPayments(paymentDate, userContext,
recordOfficeId,recordLoanOfficer);
try {
accountServiceFacade.applyAdjustment(globalAccountNum, adjustmentNote, personnelId);
} catch (MifosRuntimeException e) {
assertThat((ServiceException) e.getCause(), CoreMatchers.any(ServiceException.class));
assertThat(((ServiceException) e.getCause()).getKey(), is(SecurityConstants.KEY_ACTIVITY_NOT_ALLOWED));
}
verify(accountBusinessService, atLeastOnce()).findBySystemId(globalAccountNum);
verify(lastPmntToBeAdjusted).getPaymentDate();
verify(accountBusinessService).checkPermissionForAdjustmentOnBackDatedPayments(paymentDate, userContext, recordOfficeId, recordLoanOfficer);
verify(personnelPersistence, never()).findPersonnelById(personnelId);
verify(loanBO, never()).adjustLastPayment(anyString(), Matchers.<PersonnelBO>anyObject());
verify(legacyAccountDao, never()).createOrUpdate(loanBO);
verify(loanBO).setUserContext(userContext);
verify(transactionHelper, never()).startTransaction();
verify(transactionHelper, never()).commitTransaction();
verify(transactionHelper).rollbackTransaction();
}
}