/*
* 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 static org.mifos.accounts.loan.util.helpers.LoanConstants.METHODCALLED;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang.StringUtils;
import org.apache.struts.action.ActionErrors;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.mifos.accounts.business.AccountBO;
import org.mifos.accounts.business.AccountPaymentEntity;
import org.mifos.accounts.business.AccountStateEntity;
import org.mifos.accounts.business.AccountStateFlagEntity;
import org.mifos.accounts.business.service.AccountBusinessService;
import org.mifos.accounts.loan.business.LoanBO;
import org.mifos.accounts.savings.business.SavingsBO;
import org.mifos.accounts.savings.util.helpers.SavingsConstants;
import org.mifos.accounts.struts.actionforms.EditStatusActionForm;
import org.mifos.accounts.util.helpers.AccountState;
import org.mifos.accounts.util.helpers.AccountTypes;
import org.mifos.application.master.MessageLookup;
import org.mifos.application.questionnaire.struts.DefaultQuestionnaireServiceFacadeLocator;
import org.mifos.application.questionnaire.struts.QuestionnaireFlowAdapter;
import org.mifos.application.servicefacade.ApplicationContextProvider;
import org.mifos.application.util.helpers.ActionForwards;
import org.mifos.application.util.helpers.Methods;
import org.mifos.config.AccountingRules;
import org.mifos.customers.checklist.business.AccountCheckListBO;
import org.mifos.dto.domain.AccountStatusDto;
import org.mifos.dto.domain.AccountUpdateStatus;
import org.mifos.framework.exceptions.ServiceException;
import org.mifos.framework.struts.action.BaseAction;
import org.mifos.framework.util.DateTimeService;
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.reports.admindocuments.business.AdminDocAccStateMixBO;
import org.mifos.reports.admindocuments.business.AdminDocumentBO;
import org.mifos.reports.admindocuments.persistence.LegacyAdminDocumentDao;
import org.mifos.security.util.SecurityConstants;
import org.mifos.security.util.UserContext;
import org.springframework.security.access.AccessDeniedException;
public class EditStatusAction extends BaseAction {
private QuestionnaireFlowAdapter loanQuestionnaire;
@TransactionDemarcate(joinToken = true)
public ActionForward load(ActionMapping mapping, ActionForm form, HttpServletRequest request,
@SuppressWarnings("unused") HttpServletResponse response) throws Exception {
EditStatusActionForm actionForm = (EditStatusActionForm) form;
actionForm.setSelectedItems(null);
actionForm.setNotes(null);
actionForm.setNewStatusId(null);
actionForm.setFlagId(null);
actionForm.setQuestionGroups(null);
actionForm.setTransactionDate(DateUtils.makeDateAsSentFromBrowser());
actionForm.setAllowBackDatedApprovals(AccountingRules.isBackDatedApprovalAllowed());
request.getSession().removeAttribute(Constants.BUSINESS_KEY);
UserContext userContext = getUserContext(request);
Integer accountId = Integer.valueOf(actionForm.getAccountId());
AccountBO accountBO = new AccountBusinessService().getAccount(accountId);
java.util.Date lastPaymentDate = new java.util.Date(0);
AccountPaymentEntity lastPayment = accountBO.findMostRecentNonzeroPaymentByPaymentDate();
if(lastPayment != null){
lastPaymentDate = lastPayment.getPaymentDate();
}
actionForm.setLastPaymentDate(lastPaymentDate);
if (accountBO.isLoanAccount() || accountBO.isGroupLoanAccount()) {
// NOTE - not using dto values at present but available when ui is refactored away from jsp
AccountStatusDto accountStatuses = this.loanAccountServiceFacade.retrieveAccountStatuses(accountId.longValue());
LoanBO loanAccount = this.loanDao.findById(accountId);
EditStatusActionForm editStatusActionForm = (EditStatusActionForm) form;
editStatusActionForm.setAccountTypeId(AccountTypes.LOAN_ACCOUNT.getValue().toString());
editStatusActionForm.setCurrentStatusId(loanAccount.getAccountState().getId().toString());
editStatusActionForm.setGlobalAccountNum(loanAccount.getGlobalAccountNum());
editStatusActionForm.setAccountName(loanAccount.getLoanOffering().getPrdOfferingName());
if (loanAccount.isGroupLoanAccount() && loanAccount.getParentAccount() == null) {
editStatusActionForm.setInput("grouploan");
} else {
editStatusActionForm.setInput("loan");
}
if(loanAccount.getAccountState().getId().equals(Short.valueOf("2"))) {
List<AdminDocumentBO> allAdminDocuments = legacyAdminDocumentDao.getAllActiveAdminDocuments();
List<AdminDocumentBO> loanAdminDocuments = new ArrayList();
for(AdminDocumentBO adminDocumentBO : allAdminDocuments) {
List<AdminDocAccStateMixBO> admindoclist = legacyAdminDocAccStateMixDao.getMixByAdminDocuments(adminDocumentBO.getAdmindocId());
if (!loanAdminDocuments.contains(adminDocumentBO) && admindoclist.size() > 0
&& admindoclist.get(0).getAccountStateID().getPrdType().getProductTypeID().equals(loanAccount.getType().getValue().shortValue())){
for(AdminDocAccStateMixBO admindoc : admindoclist) {
if(admindoc.getAccountStateID().getId().shortValue()==loanAccount.getAccountState().getId().shortValue()) {
loanAdminDocuments.add(adminDocumentBO);
}
}
}
}
SessionUtils.setCollectionAttribute("editAccountStatusDocumentsList", loanAdminDocuments, request);
} else {
SessionUtils.setCollectionAttribute("editAccountStatusDocumentsList", null, request);
}
} if (accountBO.isSavingsAccount()) {
// NOTE - not using dto values at present but available when ui is refactored away from jsp
AccountStatusDto accountStatuses = this.savingsServiceFacade.retrieveAccountStatuses(accountId.longValue());
SavingsBO savingsAccount = this.savingsDao.findById(accountId.longValue());
EditStatusActionForm editStatusActionForm = (EditStatusActionForm) form;
editStatusActionForm.setAccountTypeId(AccountTypes.SAVINGS_ACCOUNT.getValue().toString());
editStatusActionForm.setCurrentStatusId(savingsAccount.getAccountState().getId().toString());
editStatusActionForm.setGlobalAccountNum(savingsAccount.getGlobalAccountNum());
editStatusActionForm.setAccountName(savingsAccount.getSavingsOffering().getPrdOfferingName());
editStatusActionForm.setInput("savings");
}
List<AccountStateEntity> accountStatuses = new AccountBusinessService().getStatusList(accountBO.getAccountState(), accountBO.getType(), userContext.getLocaleId());
for (AccountStateEntity customerStatusEntity : accountStatuses) {
for (AccountStateFlagEntity flag : customerStatusEntity.getFlagSet()) {
String statusMessageText = ApplicationContextProvider.getBean(MessageLookup.class).lookup(flag.getLookUpValue().getPropertiesKey());
flag.setStatusFlagMessageText(statusMessageText);
}
}
SessionUtils.setAttribute(Constants.BUSINESS_KEY, accountBO, request);
SessionUtils.setCollectionAttribute(SavingsConstants.STATUS_LIST, accountStatuses, request);
return mapping.findForward(ActionForwards.load_success.toString());
}
@TransactionDemarcate(joinToken = true)
public ActionForward preview(ActionMapping mapping, ActionForm form, HttpServletRequest request,
@SuppressWarnings("unused") HttpServletResponse response) throws Exception {
AccountBO accountBO = (AccountBO) SessionUtils.getAttribute(Constants.BUSINESS_KEY, request);
EditStatusActionForm editStatusActionForm = (EditStatusActionForm) form;
// FIXME - ElsieF - KEITHW - is checklist functionality being removed from application?
List<AccountCheckListBO> checklist = new AccountBusinessService().getStatusChecklist(
getShortValue(editStatusActionForm.getNewStatusId()),
getShortValue(editStatusActionForm.getAccountTypeId()));
SessionUtils.setCollectionAttribute(SavingsConstants.STATUS_CHECK_LIST, checklist, request);
String newStatusId = editStatusActionForm.getNewStatusId();
String newStatusName = null;
if (StringUtils.isNotBlank(editStatusActionForm.getNewStatusId())) {
newStatusName = new AccountBusinessService().getStatusName(AccountState.fromShort(getShortValue(editStatusActionForm.getNewStatusId())), accountBO.getType());
}
SessionUtils.setAttribute(SavingsConstants.NEW_STATUS_NAME, newStatusName, request);
initializeLoanQuestionnaire(accountBO.getGlobalAccountNum(), newStatusId);
if (loanApproved(newStatusId) || loanClosed(newStatusId)) {
return loanQuestionnaire.fetchAppliedQuestions(mapping, editStatusActionForm, request, ActionForwards.preview_success);
}
return mapping.findForward(ActionForwards.preview_success.toString());
}
private void initializeLoanQuestionnaire(String globalAccountNum, String newStatusId) {
if (loanClosed(newStatusId)) {
loanQuestionnaire = new QuestionnaireFlowAdapter("Close", "Loan", ActionForwards.preview_success,
"loanAccountAction.do?method=get&globalAccountNum=" + globalAccountNum, new DefaultQuestionnaireServiceFacadeLocator());
}
else {
loanQuestionnaire = new QuestionnaireFlowAdapter("Approve", "Loan", ActionForwards.preview_success,
"loanAccountAction.do?method=get&globalAccountNum=" + globalAccountNum, new DefaultQuestionnaireServiceFacadeLocator());
}
}
private boolean loanApproved(String newStatusId) {
return AccountState.LOAN_APPROVED.getValue().toString().equals(newStatusId);
}
private boolean loanClosed(String newStatusId) {
return AccountState.LOAN_CLOSED_RESCHEDULED.getValue().toString().equals(newStatusId) ||
AccountState.LOAN_CLOSED_WRITTEN_OFF.getValue().toString().equals(newStatusId);
}
@TransactionDemarcate(joinToken = true)
public ActionForward previous(ActionMapping mapping, @SuppressWarnings("unused") ActionForm form, @SuppressWarnings("unused") HttpServletRequest request,
@SuppressWarnings("unused") HttpServletResponse response) throws Exception {
return mapping.findForward(ActionForwards.previous_success.toString());
}
@TransactionDemarcate(validateAndResetToken = true)
public ActionForward cancel(ActionMapping mapping, ActionForm form, @SuppressWarnings("unused") HttpServletRequest request,
@SuppressWarnings("unused") HttpServletResponse response) throws Exception {
return mapping.findForward(getDetailAccountPage(form));
}
@TransactionDemarcate(validateAndResetToken = true)
@CloseSession
public ActionForward update(ActionMapping mapping, ActionForm form, HttpServletRequest request,
@SuppressWarnings("unused") HttpServletResponse response) throws Exception {
UserContext userContext = getUserContext(request);
EditStatusActionForm editStatusActionForm = (EditStatusActionForm) form;
Integer accountId = Integer.valueOf(editStatusActionForm.getAccountId());
AccountBO accountBO = new AccountBusinessService().getAccount(accountId);
Short flagId = null;
Short newStatusId = null;
String updateComment = editStatusActionForm.getNotes();
if (StringUtils.isNotBlank(editStatusActionForm.getFlagId())) {
flagId = getShortValue(editStatusActionForm.getFlagId());
}
if (StringUtils.isNotBlank(editStatusActionForm.getNewStatusId())) {
newStatusId = getShortValue(editStatusActionForm.getNewStatusId());
}
Date trxnDate = editStatusActionForm.getTransactionDateValue(userContext.getPreferredLocale());
if (editStatusActionForm.getNewStatusId().equals(AccountState.LOAN_APPROVED) &&
!AccountingRules.isBackDatedApprovalAllowed()) {
trxnDate = new DateTimeService().getCurrentJavaDateTime();
}
checkPermission(accountBO, getUserContext(request), newStatusId, flagId);
if (accountBO.isLoanAccount() || accountBO.isGroupLoanAccount()) {
initializeLoanQuestionnaire(accountBO.getGlobalAccountNum(), newStatusId != null ? newStatusId.toString() : null);
loanQuestionnaire.saveResponses(request, editStatusActionForm, accountId);
//GLIM
List<LoanBO> individualLoans = this.loanDao.findIndividualLoans(accountId);
List<AccountUpdateStatus> updateStatus = new ArrayList<AccountUpdateStatus>(individualLoans.size() + 1);
updateStatus.add(new AccountUpdateStatus(accountId.longValue(), newStatusId, flagId, updateComment));
for(LoanBO individual : individualLoans) {
updateStatus.add(new AccountUpdateStatus(individual.getAccountId().longValue(), newStatusId, flagId, updateComment));
}
try {
if (individualLoans.size() == 0) {
this.loanAccountServiceFacade.updateSingleLoanAccountStatus(updateStatus.get(0), trxnDate);
}
else {
this.loanAccountServiceFacade.updateSeveralLoanAccountStatuses(updateStatus, trxnDate);
}
} catch (AccessDeniedException e) {
throw new ServiceException(SecurityConstants.KEY_ACTIVITY_APPROVE_LOAN_NOT_ALLOWED);
}
return mapping.findForward(ActionForwards.loan_detail_page.toString());
} if (accountBO.isSavingsAccount()) {
AccountUpdateStatus updateStatus = new AccountUpdateStatus(accountId.longValue(), newStatusId, flagId, updateComment);
this.savingsServiceFacade.updateSavingsAccountStatus(updateStatus);
return mapping.findForward(ActionForwards.savings_details_page.toString());
}
// nothing but loan of savings account should be detected. customer account status change goes through separate action.
return null;
}
@TransactionDemarcate(joinToken = true)
public ActionForward validate(ActionMapping mapping, ActionForm form, HttpServletRequest request,
@SuppressWarnings("unused") HttpServletResponse response) throws Exception {
String method = (String) request.getAttribute(SavingsConstants.METHODCALLED);
String forward = null;
if (method != null) {
if (method.equals(Methods.preview.toString())) {
forward = ActionForwards.preview_failure.toString();
} else if (method.equals(Methods.load.toString())) {
forward = getDetailAccountPage(form);
} else if (method.equals(Methods.update.toString())) {
forward = ActionForwards.update_failure.toString();
}
}
return mapping.findForward(forward);
}
@TransactionDemarcate(joinToken = true)
public ActionForward captureQuestionResponses(
final ActionMapping mapping, final ActionForm form, final HttpServletRequest request,
@SuppressWarnings("unused") final HttpServletResponse response) throws Exception {
request.setAttribute(METHODCALLED, "captureQuestionResponses");
ActionErrors errors = loanQuestionnaire.validateResponses(request, (EditStatusActionForm) form);
if (errors != null && !errors.isEmpty()) {
addErrors(request, errors);
return mapping.findForward(ActionForwards.captureQuestionResponses.toString());
}
return loanQuestionnaire.rejoinFlow(mapping);
}
@TransactionDemarcate(joinToken = true)
public ActionForward editQuestionResponses(
final ActionMapping mapping, final ActionForm form,
final HttpServletRequest request, @SuppressWarnings("unused") final HttpServletResponse response) throws Exception {
request.setAttribute(METHODCALLED, "editQuestionResponses");
return loanQuestionnaire.editResponses(mapping, request, (EditStatusActionForm) form);
}
private String getDetailAccountPage(ActionForm form) {
EditStatusActionForm editStatusActionForm = (EditStatusActionForm) form;
String input = editStatusActionForm.getInput();
String forward = null;
if (input.equals("loan")) {
forward = ActionForwards.loan_detail_page.toString();
} else if (input.equals("grouploan")) {
forward = ActionForwards.group_loan_detail_page.toString();
} else if (input.equals("savings")) {
forward = ActionForwards.savings_details_page.toString();
}
return forward;
}
private void checkPermission(AccountBO accountBO, UserContext userContext, Short newStatusId, Short flagId)
throws Exception {
if (null != accountBO.getPersonnel()) {
new AccountBusinessService().checkPermissionForStatusChange(newStatusId, userContext, flagId,
accountBO.getOffice().getOfficeId(), accountBO.getPersonnel().getPersonnelId());
} else {
new AccountBusinessService().checkPermissionForStatusChange(newStatusId, userContext, flagId,
accountBO.getOffice().getOfficeId(), userContext.getId());
}
}
}