/*
* 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.domain.builders;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import org.joda.time.DateTime;
import org.joda.time.Days;
import org.joda.time.LocalDate;
import org.mifos.accounts.business.AccountActionDateEntity;
import org.mifos.accounts.business.AccountPaymentEntity;
import org.mifos.accounts.exceptions.AccountException;
import org.mifos.accounts.productdefinition.business.SavingsOfferingBO;
import org.mifos.accounts.productdefinition.util.helpers.RecommendedAmountUnit;
import org.mifos.accounts.savings.business.SavingsAccountActivationDetail;
import org.mifos.accounts.savings.business.SavingsBO;
import org.mifos.accounts.savings.business.SavingsPaymentStrategy;
import org.mifos.accounts.savings.business.SavingsPaymentStrategyImpl;
import org.mifos.accounts.savings.business.SavingsScheduleEntity;
import org.mifos.accounts.savings.business.SavingsTransactionActivityHelper;
import org.mifos.accounts.savings.business.SavingsTransactionActivityHelperImpl;
import org.mifos.accounts.util.helpers.AccountState;
import org.mifos.application.holiday.business.Holiday;
import org.mifos.application.master.business.PaymentTypeEntity;
import org.mifos.application.master.util.helpers.PaymentTypes;
import org.mifos.calendar.CalendarEvent;
import org.mifos.clientportfolio.newloan.domain.CreationDetail;
import org.mifos.config.FiscalCalendarRules;
import org.mifos.core.MifosRuntimeException;
import org.mifos.customers.business.CustomerBO;
import org.mifos.customers.persistence.CustomerPersistence;
import org.mifos.customers.personnel.business.PersonnelBO;
import org.mifos.framework.TestUtils;
import org.mifos.framework.util.helpers.Money;
/**
*
*/
public class SavingsAccountBuilder {
private AccountState accountState = AccountState.SAVINGS_ACTIVE;
private CustomerBO customer;
List<CustomerBO> jointAccountMembers = new ArrayList<CustomerBO>();
private SavingsAccountActivationDetail activationDetails;
private DateTime activationDate = new DateTime();
private LocalDate nextInterestPostingDate = new LocalDate();
private Set<AccountActionDateEntity> scheduledPayments = null;
private final Date createdDate = new DateTime().minusDays(14).toDate();
private final Short createdByUserId = TestUtils.makeUserWithLocales().getId();
private SavingsOfferingBO savingsProduct = new SavingsProductBuilder().voluntary().minimumBalance().withInterestRate(Double.valueOf("4.0")).buildForUnitTests();
private RecommendedAmountUnit recommendedAmountUnit = RecommendedAmountUnit.COMPLETE_GROUP;
private Money recommendedAmount = new Money(TestUtils.RUPEE, "13.0");
private PersonnelBO createdBy = new PersonnelBuilder().asLoanOfficer().build();
private Money savingsBalanceAmount = new Money(TestUtils.RUPEE, "0.0");
private CustomerPersistence customerDao;
private SavingsTransactionActivityHelper savingsTransactionActivityHelper = new SavingsTransactionActivityHelperImpl();
private SavingsPaymentStrategy savingsPaymentStrategy = new SavingsPaymentStrategyImpl(savingsTransactionActivityHelper);
private List<Days> workingDays = new FiscalCalendarRules().getWorkingDaysAsJodaTimeDays();
private List<Holiday> holidays = new ArrayList<Holiday>();
private List<AccountPaymentEntity> deposits = new ArrayList<AccountPaymentEntity>();
private List<AccountPaymentEntity> withdrawals = new ArrayList<AccountPaymentEntity>();
public SavingsBO buildJointSavingsAccount() {
CalendarEvent calendarEvents = new CalendarEvent(workingDays, holidays);
SavingsAccountActivationDetail derivedActivationDetails = SavingsBO.determineAccountActivationDetails(customer, savingsProduct, recommendedAmount,
accountState, calendarEvents, jointAccountMembers);
return buildAccount(derivedActivationDetails);
}
// build individual savings account
public SavingsBO build() {
CalendarEvent calendarEvents = new CalendarEvent(workingDays, holidays);
LocalDate activationDate = new LocalDate(createdDate);
SavingsAccountActivationDetail derivedActivationDetails = SavingsBO.determineAccountActivationDetails(customer, savingsProduct, recommendedAmount, accountState, calendarEvents, activationDate);
return buildAccount(derivedActivationDetails);
}
public SavingsBO buildForUnitTests() {
List<AccountActionDateEntity> listOfScheduledPayments = new ArrayList<AccountActionDateEntity>();
if (scheduledPayments != null) {
listOfScheduledPayments = new ArrayList<AccountActionDateEntity>(scheduledPayments);
}
activationDetails = new SavingsAccountActivationDetail(new LocalDate(activationDate), nextInterestPostingDate, listOfScheduledPayments);
return buildAccount(activationDetails);
}
private SavingsBO buildAccount(SavingsAccountActivationDetail derivedActivationDetails) {
List<AccountActionDateEntity> listOfScheduledPayments = new ArrayList<AccountActionDateEntity>();
if (scheduledPayments == null) {
listOfScheduledPayments = derivedActivationDetails.getScheduledPayments();
} else {
listOfScheduledPayments = new ArrayList<AccountActionDateEntity>(scheduledPayments);
}
activationDetails = new SavingsAccountActivationDetail(new LocalDate(activationDate), nextInterestPostingDate, listOfScheduledPayments);
CreationDetail creationDetail = new CreationDetail(new DateTime(createdDate), createdByUserId.intValue());
SavingsBO savingsAccount = new SavingsBO(accountState, customer, activationDetails, creationDetail
,savingsProduct, recommendedAmountUnit,
recommendedAmount, createdBy, savingsBalanceAmount);
savingsAccount.setCustomerPersistence(customerDao);
savingsAccount.setSavingsPaymentStrategy(savingsPaymentStrategy);
savingsAccount.setSavingsTransactionActivityHelper(savingsTransactionActivityHelper);
savingsAccount.updateDetails(TestUtils.makeUserWithLocales());
// savingsAccount = new SavingsBO(savingsProduct, savingsBalanceAmount,
// savingsPaymentStrategy, savingsTransactionActivityHelper, scheduledPayments, accountState, customer, offsettingAllowable,
// scheduleForInterestCalculation, recommendedAmountUnit, recommendedAmount, createdDate,
// createdByUserId, holidays, activationDate);
for (AccountPaymentEntity depositPayment : deposits) {
try {
depositPayment.setAccount(savingsAccount);
savingsAccount.deposit(depositPayment, customer);
} catch (AccountException e) {
throw new MifosRuntimeException("builder failed to apply deposits.", e);
}
}
for (AccountPaymentEntity withdrawal : withdrawals) {
try {
withdrawal.setAccount(savingsAccount);
savingsAccount.withdraw(withdrawal, customer);
} catch (AccountException e) {
throw new MifosRuntimeException("builder failed to apply withdrawals.", e);
}
}
return savingsAccount;
}
public SavingsAccountBuilder withSavingsProduct(final SavingsOfferingBO withSavingsProduct) {
this.savingsProduct = withSavingsProduct;
if (withSavingsProduct.getRecommendedAmntUnit() != null) {
this.recommendedAmountUnit = RecommendedAmountUnit.fromInt(withSavingsProduct.getRecommendedAmntUnit().getId());
}
this.recommendedAmount = withSavingsProduct.getRecommendedAmount();
return this;
}
public SavingsAccountBuilder withCustomer(final CustomerBO withCustomer) {
this.customer = withCustomer;
return this;
}
public SavingsAccountBuilder completeGroup() {
this.recommendedAmountUnit = RecommendedAmountUnit.COMPLETE_GROUP;
return this;
}
public SavingsAccountBuilder perIndividual() {
this.recommendedAmountUnit = RecommendedAmountUnit.PER_INDIVIDUAL;
return this;
}
public SavingsAccountBuilder withCustomerDao(final CustomerPersistence withCustomerDao) {
this.customerDao = withCustomerDao;
return this;
}
public SavingsAccountBuilder withBalanceOf(final Money withBalanceAmount) {
this.savingsBalanceAmount = withBalanceAmount;
return this;
}
public SavingsAccountBuilder withPaymentStrategy(final SavingsPaymentStrategy withPaymentStrategy) {
this.savingsPaymentStrategy = withPaymentStrategy;
return this;
}
public SavingsAccountBuilder active() {
this.accountState = AccountState.SAVINGS_ACTIVE;
return this;
}
public SavingsAccountBuilder asInActive() {
this.accountState = AccountState.SAVINGS_INACTIVE;
return this;
}
public SavingsAccountBuilder asPendingApproval() {
this.accountState = AccountState.SAVINGS_PENDING_APPROVAL;
return this;
}
public SavingsAccountBuilder withPayments(final List<SavingsScheduleEntity> withPayments) {
this.scheduledPayments = new LinkedHashSet<AccountActionDateEntity>(withPayments);
return this;
}
public SavingsAccountBuilder withTransactionHelper(
final SavingsTransactionActivityHelper withTransactionActivityHelper) {
this.savingsTransactionActivityHelper = withTransactionActivityHelper;
return this;
}
public SavingsAccountBuilder withSavingsOfficer(final PersonnelBO withSavingsOfficer) {
customer.setPersonnel(withSavingsOfficer);
return this;
}
public SavingsAccountBuilder withRecommendedAmount(final Money withRecommendedAmount) {
this.recommendedAmount = withRecommendedAmount;
return this;
}
public SavingsAccountBuilder with(List<Holiday> withHolidays) {
this.holidays = withHolidays;
return this;
}
public SavingsAccountBuilder with(Holiday...holidays) {
for (Holiday holiday : holidays) {
this.holidays.add(holiday);
}
return this;
}
public SavingsAccountBuilder withActivationDate(DateTime withActivationDate) {
this.activationDate = withActivationDate;
return this;
}
public SavingsAccountBuilder withDepositOf(String depositAmount) {
Money amount = TestUtils.createMoney(depositAmount);
String receiptNumber = null;
Date receiptDate = null;
PaymentTypeEntity paymentType = new PaymentTypeEntity(PaymentTypes.CASH.getValue());
Date paymentDate = new DateTime().toDate();
AccountPaymentEntity deposit = new AccountPaymentEntity(null, amount, receiptNumber, receiptDate, paymentType, paymentDate);
this.deposits.add(deposit);
return this;
}
public SavingsAccountBuilder withDepositOn(String depositAmount, DateTime paymentDateTime) {
Money amount = TestUtils.createMoney(depositAmount);
String receiptNumber = null;
Date receiptDate = null;
PaymentTypeEntity paymentType = new PaymentTypeEntity(PaymentTypes.CASH.getValue());
Date paymentDate = paymentDateTime.toDate();
AccountPaymentEntity deposit = new AccountPaymentEntity(null, amount, receiptNumber, receiptDate, paymentType, paymentDate);
this.deposits.add(deposit);
return this;
}
public SavingsAccountBuilder withWithdrawalOf(String withdrawalAmount) {
Money amount = TestUtils.createMoney(withdrawalAmount);
String receiptNumber = null;
Date receiptDate = null;
PaymentTypeEntity paymentType = new PaymentTypeEntity(PaymentTypes.CASH.getValue());
Date paymentDate = new DateTime().toDate();
AccountPaymentEntity deposit = new AccountPaymentEntity(null, amount, receiptNumber, receiptDate, paymentType, paymentDate);
this.withdrawals.add(deposit);
return this;
}
public SavingsAccountBuilder withNextInterestPostingDateOf(DateTime nextInterestPostingDate) {
this.nextInterestPostingDate = new LocalDate(nextInterestPostingDate);
return this;
}
public SavingsAccountBuilder withCreatedBy(PersonnelBO testUser) {
this.createdBy = testUser;
return this;
}
public SavingsAccountBuilder withMember(CustomerBO withMember) {
this.jointAccountMembers.add(withMember);
return this;
}
}