/*
* 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.application.servicefacade;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.joda.time.LocalDate;
import org.mifos.accounts.business.AccountBO;
import org.mifos.accounts.business.AccountPaymentEntity;
import org.mifos.accounts.exceptions.AccountException;
import org.mifos.accounts.loan.business.LoanBO;
import org.mifos.accounts.loan.persistance.ClientAttendanceDao;
import org.mifos.accounts.loan.persistance.LegacyLoanDao;
import org.mifos.accounts.persistence.LegacyAccountDao;
import org.mifos.accounts.savings.business.SavingsBO;
import org.mifos.accounts.savings.persistence.SavingsDao;
import org.mifos.accounts.util.helpers.PaymentData;
import org.mifos.application.master.business.PaymentTypeEntity;
import org.mifos.core.MifosRuntimeException;
import org.mifos.customers.business.CustomerAccountBO;
import org.mifos.customers.business.CustomerBO;
import org.mifos.customers.client.business.ClientAttendanceBO;
import org.mifos.customers.client.business.ClientBO;
import org.mifos.customers.persistence.CustomerDao;
import org.mifos.customers.personnel.business.PersonnelBO;
import org.mifos.customers.personnel.persistence.LegacyPersonnelDao;
import org.mifos.framework.exceptions.PersistenceException;
import org.mifos.framework.hibernate.helper.StaticHibernateUtil;
import org.mifos.framework.util.helpers.DateUtils;
import org.mifos.framework.util.helpers.Money;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
/**
* Methods to assemble mifos business model from Save Collection Sheet Dto's
*
*/
public class SaveCollectionSheetAssembler {
private static final Logger logger = LoggerFactory.getLogger(SaveCollectionSheetAssembler.class);
@Autowired
private LegacyPersonnelDao legacyPersonnelDao;
@Autowired
private ClientAttendanceDao clientAttendanceDao;
@Autowired
private CustomerDao customerDao;
@Autowired
private LegacyLoanDao legacyLoanDao;
@Autowired
private LegacyAccountDao legacyAccountDao;
@Autowired
private SavingsDao savingsDao;
public List<SavingsBO> savingsAccountAssemblerFromDto(
final List<SaveCollectionSheetCustomerDto> saveCollectionSheetCustomers,
final AccountPaymentEntity payment, final List<String> failedSavingsDepositAccountNums,
final List<String> failedSavingsWithdrawalNums) {
final List<SavingsBO> savingsList = new ArrayList<SavingsBO>();
for (SaveCollectionSheetCustomerDto saveCollectionSheetCustomer : saveCollectionSheetCustomers) {
buildModelForSavingsAccounts(saveCollectionSheetCustomer.getSaveCollectionSheetCustomerSavings(), payment,
failedSavingsDepositAccountNums, failedSavingsWithdrawalNums, saveCollectionSheetCustomer
.getCustomerId(), savingsList);
buildModelForSavingsAccounts(saveCollectionSheetCustomer.getSaveCollectionSheetCustomerIndividualSavings(),
payment, failedSavingsDepositAccountNums, failedSavingsWithdrawalNums, saveCollectionSheetCustomer
.getCustomerId(), savingsList);
}
return savingsList;
}
private void buildModelForSavingsAccounts(
final List<SaveCollectionSheetCustomerSavingDto> saveCollectionSheetCustomerSavings,
final AccountPaymentEntity payment, final List<String> failedSavingsDepositAccountNums,
final List<String> failedSavingsWithdrawalNums, final Integer customerId, final List<SavingsBO> savingsList) {
if (null != saveCollectionSheetCustomerSavings && saveCollectionSheetCustomerSavings.size() > 0) {
final String receiptNumber = payment.getReceiptNumber();
final Date receiptDate = payment.getReceiptDate();
final PaymentTypeEntity paymentType = payment.getPaymentType();
final Date paymentDate = payment.getPaymentDate();
final PersonnelBO user = payment.getCreatedByUser();
for (SaveCollectionSheetCustomerSavingDto saveCollectionSheetCustomerSaving : saveCollectionSheetCustomerSavings) {
final BigDecimal amountToDeposit = saveCollectionSheetCustomerSaving.getTotalDeposit();
final BigDecimal amountToWithdraw = saveCollectionSheetCustomerSaving.getTotalWithdrawal();
Boolean isDeposit = isPositiveAmountEntered(amountToDeposit);
Boolean isWithdrawal = isPositiveAmountEntered(amountToWithdraw);
if (isDeposit || isWithdrawal) {
boolean storeAccountForSavingLater = false;
final CustomerBO payingCustomer = customerDao.findCustomerById(customerId);
SavingsBO account = savingsDao.findById(saveCollectionSheetCustomerSaving
.getAccountId());
if (isDeposit) {
final AccountPaymentEntity accountDeposit = new AccountPaymentEntity(account, new Money(
Money.getDefaultCurrency(), amountToDeposit.toString()), receiptNumber,
receiptDate, paymentType, paymentDate);
accountDeposit.setCreatedByUser(user);
try {
account.deposit(accountDeposit, payingCustomer);
storeAccountForSavingLater = true;
} catch (AccountException e) {
logger.warn("Savings deposit on account [" + account.getAccountId()
+ "] failed. Account changes will not be persisted due to: " + e.getMessage());
failedSavingsDepositAccountNums.add(account.getAccountId().toString());
}
}
if (isWithdrawal) {
final AccountPaymentEntity accountWithdrawal = new AccountPaymentEntity(account, new Money(
Money.getDefaultCurrency(), amountToWithdraw.toString()), receiptNumber,
receiptDate, paymentType, paymentDate);
accountWithdrawal.setCreatedByUser(user);
try {
account.withdraw(accountWithdrawal, payingCustomer);
storeAccountForSavingLater = true;
} catch (AccountException e) {
logger.warn("Savings withdrawal on account [" + account.getAccountId()
+ "] failed. Account changes will not be persisted due to: " + e.getMessage());
failedSavingsWithdrawalNums.add(account.getAccountId().toString());
}
}
if (storeAccountForSavingLater) {
if (!savingsList.contains(account)) {
savingsList.add(account);
}
} else {
StaticHibernateUtil.getSessionTL().evict(account);
}
}
}
}
}
private Boolean isPositiveAmountEntered(final BigDecimal amount) {
return amount != null && amount.compareTo(BigDecimal.ZERO) > 0;
}
public List<LoanBO> loanAccountAssemblerFromDto(
final List<SaveCollectionSheetCustomerDto> saveCollectionSheetCustomers,
final AccountPaymentEntity payment, final List<String> failedLoanDisbursementAccountNumbers,
final List<String> failedLoanRepaymentAccountNumbers, Short paymentTypeIdForFees) {
final List<LoanBO> loans = new ArrayList<LoanBO>();
Map<Integer, AccountPaymentEntity> groupLoanAccountParentsPayments =
new HashMap<Integer, AccountPaymentEntity>();
for (SaveCollectionSheetCustomerDto saveCollectionSheetCustomer : saveCollectionSheetCustomers) {
if (saveCollectionSheetCustomer.getSaveCollectionSheetCustomerLoans() != null
&& saveCollectionSheetCustomer.getSaveCollectionSheetCustomerLoans().size() > 0) {
for (SaveCollectionSheetCustomerLoanDto saveCollectionSheetCustomerLoan : saveCollectionSheetCustomer
.getSaveCollectionSheetCustomerLoans()) {
final Integer accountId = saveCollectionSheetCustomerLoan.getAccountId();
LoanBO account = findLoanAccountById(accountId);
final String globalAccountNum = account.getGlobalAccountNum();
final BigDecimal disbursalAmount = saveCollectionSheetCustomerLoan.getTotalDisbursement();
if (null != disbursalAmount && disbursalAmount.compareTo(BigDecimal.ZERO) > 0) {
try {
final AccountPaymentEntity accountDisbursalPayment = new AccountPaymentEntity(account,
new Money(account.getCurrency(), disbursalAmount.toString()), payment
.getReceiptNumber(), payment.getReceiptDate(), payment.getPaymentType(),
payment.getPaymentDate());
accountDisbursalPayment.setCreatedByUser(payment.getCreatedByUser());
Integer transferAccountId = (payment.getOtherTransferPayment() == null || payment.getOtherTransferPayment().getAccount() == null
|| payment.getOtherTransferPayment().getAccount().getAccountId() == null) ? null : payment.getOtherTransferPayment().getAccount().getAccountId();
account.disburseLoan(accountDisbursalPayment, paymentTypeIdForFees, transferAccountId);
loans.add(account);
} catch (AccountException ae) {
logger.warn("Disbursal of loan on account [" + globalAccountNum
+ "] failed. Account changes will not be persisted due to: " + ae.getMessage());
failedLoanDisbursementAccountNumbers.add(globalAccountNum);
StaticHibernateUtil.getSessionTL().evict(account);
} catch (PersistenceException e) {
logger.warn("Disbursal of loan on account [" + globalAccountNum
+ "] failed. Account changes will not be persisted due to: " + e.getMessage());
failedLoanDisbursementAccountNumbers.add(globalAccountNum);
StaticHibernateUtil.getSessionTL().evict(account);
}
} else {
final BigDecimal loanPaymentAmount = saveCollectionSheetCustomerLoan.getTotalLoanPayment();
if (loanPaymentAmount != null && loanPaymentAmount.compareTo(BigDecimal.ZERO) > 0) {
try {
final PaymentData paymentData = getCustomerAccountPaymentDataView(new Money(account
.getCurrency(), loanPaymentAmount.toString()), payment);
AccountPaymentEntity paymentEntity = account.applyPayment(paymentData);
if (account.isGroupLoanAccountParent()) {
groupLoanAccountParentsPayments.put(account.getAccountId(), paymentEntity);
} else if (account.isGroupLoanAccountMember()) {
paymentEntity.setParentPaymentId(
groupLoanAccountParentsPayments.get(account.getParentAccount().getAccountId()));
}
loans.add(account);
} catch (AccountException ae) {
logger.warn("Loan repayment on account [" + globalAccountNum
+ "] failed. Account changes will not be persisted due to: " + ae.getMessage());
failedLoanRepaymentAccountNumbers.add(globalAccountNum);
StaticHibernateUtil.getSessionTL().evict(account);
}
}
}
}
}
}
return loans;
}
public List<AccountBO> customerAccountAssemblerFromDto(
final List<SaveCollectionSheetCustomerDto> saveCollectionSheetCustomers,
final AccountPaymentEntity payment, final List<String> failedCustomerAccountPaymentNums) {
final List<AccountBO> customerAccountList = new ArrayList<AccountBO>();
for (SaveCollectionSheetCustomerDto saveCollectionSheetCustomer : saveCollectionSheetCustomers) {
SaveCollectionSheetCustomerAccountDto saveCollectionSheetCustomerAccount = saveCollectionSheetCustomer
.getSaveCollectionSheetCustomerAccount();
if (null != saveCollectionSheetCustomerAccount) {
final BigDecimal amount = saveCollectionSheetCustomerAccount.getTotalCustomerAccountCollectionFee();
if (null != amount && amount.compareTo(BigDecimal.ZERO) > 0) {
final PaymentData accountPaymentDataView = getCustomerAccountPaymentDataView(new Money(Money
.getDefaultCurrency(), amount.toString()), payment);
final Integer accountId = saveCollectionSheetCustomer.getSaveCollectionSheetCustomerAccount()
.getAccountId();
CustomerAccountBO account = null;
try {
account = findCustomerAccountById(accountId);
account.applyPayment(accountPaymentDataView);
customerAccountList.add(account);
} catch (AccountException ae) {
logger.warn("Payment of collection/fee on account [" + accountId
+ "] failed. Account changes will not be persisted due to: " + ae.getMessage());
failedCustomerAccountPaymentNums.add(accountId.toString());
StaticHibernateUtil.getSessionTL().evict(account);
}
}
}
}
return customerAccountList;
}
private PaymentData getCustomerAccountPaymentDataView(final Money totalAmount, final AccountPaymentEntity payment) {
PaymentData paymentData = PaymentData.createPaymentData(totalAmount, payment.getCreatedByUser(), payment
.getPaymentType().getId(), payment.getPaymentDate());
paymentData.setReceiptDate(payment.getReceiptDate());
paymentData.setReceiptNum(payment.getReceiptNumber());
return paymentData;
}
public AccountPaymentEntity accountPaymentAssemblerFromDto(final LocalDate transactionDate,
final Short paymentType, final String receiptId, final LocalDate receiptDate, final Short userId) {
final PersonnelBO user = legacyPersonnelDao.findPersonnelById(userId);
final AccountPaymentEntity payment = new AccountPaymentEntity(null, new Money(Money.getDefaultCurrency()),
receiptId, DateUtils.getDateFromLocalDate(receiptDate), new PaymentTypeEntity(paymentType), DateUtils
.getDateFromLocalDate(transactionDate));
payment.setCreatedByUser(user);
return payment;
}
public List<ClientAttendanceBO> clientAttendanceAssemblerfromDto(
final List<SaveCollectionSheetCustomerDto> saveCollectionSheetCustomers, final LocalDate transactionDate,
final Short branchId, final String searchId) {
List<ClientAttendanceBO> clientAttendanceList = null;
try {
clientAttendanceList = clientAttendanceDao.findClientAttendance(branchId, searchId, transactionDate);
for (SaveCollectionSheetCustomerDto saveCollectionSheetCustomer : saveCollectionSheetCustomers) {
ClientBO client = customerDao.findClientById(saveCollectionSheetCustomer.getCustomerId());
if (null != client) {
ClientAttendanceBO clientAttendance = findClientAttendance(clientAttendanceList, client);
if (clientAttendance == null) {
clientAttendance = new ClientAttendanceBO();
clientAttendance.setCustomer(client);
clientAttendance.setMeetingDate(DateUtils.getDateFromLocalDate(transactionDate));
}
clientAttendance.setAttendance(saveCollectionSheetCustomer.getAttendanceId());
clientAttendanceList.add(clientAttendance);
}
}
} catch (PersistenceException e) {
throw new MifosRuntimeException("Failure assembling client attendance list.", e);
}
return clientAttendanceList;
}
private ClientAttendanceBO findClientAttendance(final List<ClientAttendanceBO> clientAttendanceList,
final ClientBO client) {
if (clientAttendanceList != null && clientAttendanceList.size() > 0) {
for (ClientAttendanceBO clientAttendance : clientAttendanceList) {
if (clientAttendance.getCustomer().getCustomerId() == client.getCustomerId()) {
return clientAttendance;
}
}
}
return null;
}
private CustomerAccountBO findCustomerAccountById(final Integer accountId) {
try {
return (CustomerAccountBO) legacyAccountDao.getAccount(accountId);
} catch (PersistenceException e) {
throw new MifosRuntimeException(e);
}
}
private LoanBO findLoanAccountById(final Integer loanId) {
try {
return legacyLoanDao.getAccount(loanId);
} catch (PersistenceException e) {
throw new MifosRuntimeException(e);
}
}
private void doLog(String str) {
System.out.println(str);
}
}