/* * 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.struts.action; import java.math.BigDecimal; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.struts.action.ActionForm; import org.apache.struts.action.ActionForward; import org.apache.struts.action.ActionMapping; import org.mifos.accounts.acceptedpaymenttype.persistence.LegacyAcceptedPaymentTypeDao; import org.mifos.accounts.api.AccountService; import org.mifos.accounts.business.AccountTypeEntity; import org.mifos.accounts.loan.business.LoanBO; import org.mifos.accounts.servicefacade.AccountPaymentDto; import org.mifos.accounts.servicefacade.AccountServiceFacade; import org.mifos.accounts.servicefacade.AccountTypeDto; import org.mifos.accounts.struts.actionforms.AccountApplyPaymentActionForm; import org.mifos.accounts.util.helpers.AccountConstants; import org.mifos.accounts.util.helpers.AccountState; import org.mifos.accounts.util.helpers.AccountTypes; import org.mifos.application.admin.servicefacade.InvalidDateException; import org.mifos.application.master.util.helpers.MasterConstants; import org.mifos.application.servicefacade.ApplicationContextProvider; import org.mifos.application.servicefacade.GroupLoanAccountServiceFacade; import org.mifos.application.servicefacade.LoanAccountServiceFacade; import org.mifos.application.util.helpers.ActionForwards; import org.mifos.core.MifosRuntimeException; import org.mifos.customers.exceptions.CustomerException; import org.mifos.dto.domain.AccountPaymentParametersDto; import org.mifos.dto.domain.AccountReferenceDto; import org.mifos.dto.domain.GroupIndividualLoanDto; import org.mifos.dto.domain.PaymentTypeDto; import org.mifos.dto.domain.UserReferenceDto; import org.mifos.framework.exceptions.ApplicationException; import org.mifos.framework.exceptions.PageExpiredException; import org.mifos.framework.struts.action.BaseAction; import org.mifos.framework.util.helpers.CloseSession; import org.mifos.framework.util.helpers.Constants; import org.mifos.framework.util.helpers.DateUtils; import org.mifos.framework.util.helpers.SessionUtils; import org.mifos.framework.util.helpers.TransactionDemarcate; import org.mifos.security.util.SecurityConstants; import org.mifos.security.util.UserContext; public class AccountApplyGroupPaymentAction extends BaseAction { private final static String ZERO_PAYMENT = "0.0"; private final static String LOAN_TYPE = "loanType"; private final static String PARENT = "parent"; private final static String MEMBER = "member"; private AccountService accountService = null; private GroupLoanAccountServiceFacade groupLoanService; private LoanAccountServiceFacade loanService; public AccountApplyGroupPaymentAction() throws Exception { accountService = ApplicationContextProvider.getBean(AccountService.class); groupLoanService = ApplicationContextProvider.getBean(GroupLoanAccountServiceFacade.class); loanService = ApplicationContextProvider.getBean(LoanAccountServiceFacade.class); } @Deprecated // For unit testing public AccountApplyGroupPaymentAction(AccountServiceFacade accountServiceFacade, LegacyAcceptedPaymentTypeDao legacyAcceptedPaymentTypeDao) { this.accountServiceFacade = accountServiceFacade; this.legacyAcceptedPaymentTypeDao = legacyAcceptedPaymentTypeDao; } @TransactionDemarcate(joinToken = true) public ActionForward load(ActionMapping mapping, ActionForm form, HttpServletRequest request, @SuppressWarnings("unused") HttpServletResponse response) throws Exception { UserContext userContext = getUserContext(request); AccountApplyPaymentActionForm actionForm = (AccountApplyPaymentActionForm) form; actionForm.setReceiptDate(null); actionForm.setReceiptId(null); actionForm.setPaymentTypeId(null); actionForm.setTransactionDate(DateUtils.makeDateAsSentFromBrowser()); actionForm.setPrintReceipt(false); actionForm.setTruePrintReceipt(false); final AccountReferenceDto accountReferenceDto = new AccountReferenceDto(Integer.valueOf(actionForm.getAccountId())); AccountPaymentDto accountPaymentDto = accountServiceFacade.getAccountPaymentInformation( accountReferenceDto.getAccountId(), request.getParameter(Constants.INPUT), userContext.getLocaleId(), new UserReferenceDto(userContext.getId()), DateUtils.getCurrentJavaDateTime()); setValuesInSession(request, actionForm, accountPaymentDto); actionForm.setLastPaymentDate(accountPaymentDto.getLastPaymentDate()); actionForm.setAmount(accountPaymentDto.getTotalPaymentDue()); actionForm.setTransferPaymentTypeId(this.legacyAcceptedPaymentTypeDao.getSavingsTransferId()); LoanBO loan = loanDao.findById(accountReferenceDto.getAccountId()); if (loan.isGroupLoanAccountParent()) { SessionUtils.setAttribute(LOAN_TYPE, PARENT, request); } else if (loan.isGroupLoanAccountMember()) { SessionUtils.setAttribute(LOAN_TYPE, MEMBER, request); } List<LoanBO> memberInfos = getMemberAccountsInformation(actionForm.getAccountId()); SessionUtils.setCollectionAttribute("memberInfos", memberInfos, request); if (memberInfos.size() > 0) { actionForm.getIndividualValues().clear(); List<GroupIndividualLoanDto> memberAccounts = groupLoanService.getMemberLoansAndDefaultPayments( Integer.valueOf(actionForm.getAccountId()), new BigDecimal(actionForm.getAmount())); for(int i = 0 ; i < memberAccounts.size() ; i++) { actionForm.getIndividualValues().put(memberAccounts.get(i).getAccountId(), String.valueOf(memberAccounts.get(i).getDefaultAmount().doubleValue())); } } return mapping.findForward(ActionForwards.load_success.toString()); } @TransactionDemarcate(joinToken = true) public ActionForward divide(ActionMapping mapping, ActionForm form, HttpServletRequest request, @SuppressWarnings("unused") HttpServletResponse response) throws Exception { AccountApplyPaymentActionForm actionForm = (AccountApplyPaymentActionForm) form; actionForm.getIndividualValues().clear(); List<GroupIndividualLoanDto> memberAccounts = groupLoanService.getMemberLoansAndDefaultPayments( Integer.valueOf(actionForm.getAccountId()), new BigDecimal(actionForm.getAmount())); for(int i = 0 ; i < memberAccounts.size() ; i++) { actionForm.getIndividualValues().put(memberAccounts.get(i).getAccountId(), String.valueOf(memberAccounts.get(i).getDefaultAmount().doubleValue())); } List<LoanBO> memberInfos = getMemberAccountsInformation(actionForm.getAccountId()); SessionUtils.setCollectionAttribute("memberInfos", memberInfos, request); return mapping.findForward(ActionForwards.load_success.toString()); } private List<LoanBO> getMemberAccountsInformation(String accountId) { List<LoanBO> membersInfo = new ArrayList<LoanBO>(); for (LoanBO memberAcc : loanDao.findById(Integer.valueOf(accountId)).getMemberAccounts()) { if (memberAcc.isActiveLoanAccount()) { membersInfo.add(memberAcc); } } return membersInfo; } void setValuesInSession(HttpServletRequest request, AccountApplyPaymentActionForm actionForm, AccountPaymentDto accountPaymentDto) throws PageExpiredException { SessionUtils.setAttribute(Constants.ACCOUNT_VERSION, accountPaymentDto.getVersion(), request); SessionUtils.setAttribute(Constants.ACCOUNT_TYPE, accountPaymentDto.getAccountType().name(), request); SessionUtils.setAttribute(Constants.ACCOUNT_ID, Integer.valueOf(actionForm.getAccountId()), request); SessionUtils.setCollectionAttribute(MasterConstants.PAYMENT_TYPE, accountPaymentDto.getPaymentTypeList(), request); SessionUtils.setCollectionAttribute(Constants.ACCOUNTS_FOR_TRANSFER, accountPaymentDto.getSavingsAccountsFroTransfer(), request); } @TransactionDemarcate(joinToken = true) public ActionForward preview(ActionMapping mapping, @SuppressWarnings("unused") ActionForm form, @SuppressWarnings("unused") HttpServletRequest request, @SuppressWarnings("unused") HttpServletResponse response) throws Exception { AccountApplyPaymentActionForm accountApplyPaymentActionForm = (AccountApplyPaymentActionForm) form; Double oldAmmount = Double.valueOf(accountApplyPaymentActionForm.getAmount()); Double newAmounts = 0.0; if (accountApplyPaymentActionForm.getMemberType().equals("member")){ accountApplyPaymentActionForm.setAmount(oldAmmount.toString()); } else if (!accountApplyPaymentActionForm.getIndividualValues().isEmpty()) { for(String amount : accountApplyPaymentActionForm.getIndividualValues().values()) { newAmounts += Double.valueOf(amount); } if (!oldAmmount.equals(newAmounts)) { accountApplyPaymentActionForm.setAmount(newAmounts.toString()); } } return mapping.findForward(ActionForwards.preview_success.toString()); } @TransactionDemarcate(joinToken = true) public ActionForward previous(ActionMapping mapping, @SuppressWarnings("unused") ActionForm form, @SuppressWarnings("unused") HttpServletRequest request, @SuppressWarnings("unused") HttpServletResponse response) throws Exception { //workaround for checkbox problem AccountApplyPaymentActionForm accountApplyPaymentActionForm = (AccountApplyPaymentActionForm) form; accountApplyPaymentActionForm.setTruePrintReceipt(accountApplyPaymentActionForm.getPrintReceipt()); accountApplyPaymentActionForm.setPrintReceipt(false); return mapping.findForward(ActionForwards.previous_success.toString()); } @TransactionDemarcate(validateAndResetToken = true) @CloseSession public ActionForward applyPayment(ActionMapping mapping, ActionForm form, HttpServletRequest request, @SuppressWarnings("unused") HttpServletResponse response) throws Exception { UserContext userContext = (UserContext) SessionUtils.getAttribute(Constants.USER_CONTEXT_KEY, request.getSession()); AccountApplyPaymentActionForm actionForm = (AccountApplyPaymentActionForm) form; String paymentType = request.getParameter(Constants.INPUT); Integer accountId; if (actionForm.getAccountId().isEmpty() || actionForm.getAccountId() == null) { accountId = loanDao.findByGlobalAccountNum(actionForm.getGlobalAccountNum()).getAccountId(); } else { accountId = Integer.valueOf(actionForm.getAccountId()); } UserReferenceDto userReferenceDto = new UserReferenceDto(userContext.getId()); AccountPaymentDto accountPaymentDto = accountServiceFacade.getAccountPaymentInformation(accountId, paymentType, userContext.getLocaleId(), userReferenceDto, actionForm.getTrxnDate()); validateAccountPayment(accountPaymentDto, accountId, request); validateAmount(accountPaymentDto, actionForm.getAmount()); PaymentTypeDto paymentTypeDto; String amount = actionForm.getAmount(); if (accountPaymentDto.getAccountType().equals(AccountTypeDto.LOAN_ACCOUNT) || accountPaymentDto.getAccountType().equals(AccountTypeDto.GROUP_LOAN_ACCOUNT)) { paymentTypeDto = getLoanPaymentTypeDtoForId(Short.valueOf(actionForm.getPaymentTypeId())); } else { paymentTypeDto = getFeePaymentTypeDtoForId(Short.valueOf(actionForm.getPaymentTypeId())); } AccountPaymentParametersDto accountPaymentParametersDto; if (isGroupParentAccount(accountId)) { accountPaymentParametersDto = new AccountPaymentParametersDto(userReferenceDto, new AccountReferenceDto(accountId), new BigDecimal(amount), actionForm.getTrxnDateAsLocalDate(), paymentTypeDto, AccountConstants.NO_COMMENT, actionForm.getReceiptDateAsLocalDate(), actionForm.getReceiptId(), accountPaymentDto.getCustomerDto(), actionForm.getIndividualValues()); } else if (isGroupMemberAccount(accountId)) { accountPaymentParametersDto = preparePaymentParametersDto(accountId, userReferenceDto, amount, actionForm, paymentTypeDto, userContext, paymentType); } else { accountPaymentParametersDto = new AccountPaymentParametersDto(userReferenceDto, new AccountReferenceDto(accountId), new BigDecimal(amount), actionForm.getTrxnDateAsLocalDate(), paymentTypeDto, AccountConstants.NO_COMMENT, actionForm.getReceiptDateAsLocalDate(), actionForm.getReceiptId(), accountPaymentDto.getCustomerDto()); } if (paymentTypeDto.getValue().equals(this.legacyAcceptedPaymentTypeDao.getSavingsTransferId())) { this.accountServiceFacade.makePaymentFromSavingsAcc(accountPaymentParametersDto, actionForm.getAccountForTransfer()); } else { this.accountServiceFacade.makePayment(accountPaymentParametersDto); } request.getSession().setAttribute("globalAccountNum", ((AccountApplyPaymentActionForm) form).getGlobalAccountNum()); ActionForward findForward; if(actionForm.getPrintReceipt()){ findForward = mapping.findForward(getForward("PRINT")); } else { findForward = mapping.findForward(getForward(((AccountApplyPaymentActionForm) form).getInput())); } return findForward; } private boolean isGroupParentAccount(Integer accountId) { return this.loanDao.findById(accountId).isGroupLoanAccountParent(); } private boolean isGroupMemberAccount(Integer accountId) { return this.loanDao.findById(accountId).isGroupLoanAccountMember(); } private AccountPaymentParametersDto preparePaymentParametersDto(Integer accountId, UserReferenceDto userReferenceDto, String amount, AccountApplyPaymentActionForm actionForm, PaymentTypeDto paymentTypeDto, UserContext userContext, String paymentType) throws InvalidDateException { LoanBO acctualMemberAccount = loanDao.findById(accountId); LoanBO parrentAccount = acctualMemberAccount.getParentAccount(); Integer parentAccountId = parrentAccount.getAccountId(); AccountPaymentDto accountPaymentDto = accountServiceFacade.getAccountPaymentInformation(parentAccountId, paymentType, userContext.getLocaleId(), userReferenceDto, actionForm.getTrxnDate()); HashMap<Integer, String> individualValues = new HashMap<Integer, String>(); for (LoanBO member : loanDao.findIndividualLoans(parentAccountId)) { if (member.isAccountActive()) { if (member.getAccountId().equals(acctualMemberAccount.getAccountId())){ individualValues.put(member.getAccountId(), amount); } else { individualValues.put(member.getAccountId(), ZERO_PAYMENT); } } } return new AccountPaymentParametersDto(userReferenceDto, new AccountReferenceDto(parentAccountId), new BigDecimal(amount), actionForm.getTrxnDateAsLocalDate(), paymentTypeDto, AccountConstants.NO_COMMENT, actionForm.getReceiptDateAsLocalDate(), actionForm.getReceiptId(), accountPaymentDto.getCustomerDto(), individualValues); } private void validateAmount(AccountPaymentDto accountPaymentDto, String amount) throws ApplicationException { if (new BigDecimal(amount).compareTo(BigDecimal.ZERO) <= 0) { throw new ApplicationException("errors.invalid_amount_according_to_due"); } if (!accountPaymentDto.getAccountType().equals(AccountTypeDto.LOAN_ACCOUNT) && !accountPaymentDto.getAccountType().equals(AccountTypeDto.GROUP_LOAN_ACCOUNT)) { if (new BigDecimal(amount).compareTo(new BigDecimal(accountPaymentDto.getTotalPaymentDue())) > 0) { throw new ApplicationException("errors.invalid_amount_according_to_due"); } } } private void validateAccountPayment(AccountPaymentDto accountPaymentDto, Integer accountId, HttpServletRequest request) throws Exception { checkPermission(accountId); } private void checkPermission(Integer accountId) throws CustomerException { if (!accountServiceFacade.isPaymentPermitted(accountId)) { throw new CustomerException(SecurityConstants.KEY_ACTIVITY_NOT_ALLOWED); } } private PaymentTypeDto getLoanPaymentTypeDtoForId(short id) throws Exception { for (PaymentTypeDto paymentTypeDto : accountService.getLoanPaymentTypes()) { if (paymentTypeDto.getValue() == id) { return paymentTypeDto; } } throw new MifosRuntimeException("Expected loan PaymentTypeDto not found for id: " + id); } private PaymentTypeDto getFeePaymentTypeDtoForId(short id) throws Exception { for (PaymentTypeDto paymentTypeDto : accountService.getFeePaymentTypes()) { if (paymentTypeDto.getValue() == id) { return paymentTypeDto; } } throw new MifosRuntimeException("Expected fee PaymentTypeDto not found for id: " + id); } @TransactionDemarcate(validateAndResetToken = true) public ActionForward cancel(ActionMapping mapping, ActionForm form, @SuppressWarnings("unused") HttpServletRequest request, @SuppressWarnings("unused") HttpServletResponse response) throws Exception { return mapping.findForward(getForward(((AccountApplyPaymentActionForm) form).getInput())); } private String getForward(String input) { if (input.equals(Constants.LOAN)) { return ActionForwards.loan_detail_page.toString(); } else if (input.equals("PRINT")) { return ActionForwards.printPaymentReceipt.toString(); } return "applyPayment_success"; } @TransactionDemarcate(joinToken = true) public ActionForward validate(ActionMapping mapping, @SuppressWarnings("unused") ActionForm form, HttpServletRequest request, @SuppressWarnings("unused") HttpServletResponse response) throws Exception { String method = (String) request.getAttribute("methodCalled"); String forward = null; //workaround for checkbox problem AccountApplyPaymentActionForm accountApplyPaymentActionForm = (AccountApplyPaymentActionForm) form; accountApplyPaymentActionForm.setTruePrintReceipt(accountApplyPaymentActionForm.getPrintReceipt()); accountApplyPaymentActionForm.setPrintReceipt(false); if (method != null) { forward = method + "_failure"; } return mapping.findForward(forward); } }