/* * 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.Date; import java.util.Iterator; 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.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.AdjustablePaymentDto; import org.mifos.accounts.business.service.AccountBusinessService; import org.mifos.accounts.loan.business.LoanBO; import org.mifos.accounts.productdefinition.util.helpers.InterestType; import org.mifos.accounts.struts.actionforms.AccountApplyPaymentActionForm; import org.mifos.accounts.struts.actionforms.ApplyAdjustmentActionForm; 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.ListItem; import org.mifos.core.MifosRuntimeException; import org.mifos.dto.domain.AdjustedPaymentDto; import org.mifos.dto.domain.GroupIndividualLoanDto; import org.mifos.dto.screen.AccountPaymentDto; import org.mifos.dto.screen.GroupLoanMemberAdjustmentDto; import org.mifos.framework.business.service.BusinessService; import org.mifos.framework.exceptions.ApplicationException; import org.mifos.framework.exceptions.ServiceException; 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.Money; import org.mifos.framework.util.helpers.SessionUtils; import org.mifos.framework.util.helpers.TransactionDemarcate; import org.mifos.security.util.UserContext; /** * This is the action class for applying adjustment. This action is to be merged * with AccountAction once an AccountAction for M2 is done. */ public class ApplyAdjustment extends BaseAction { private GroupLoanAccountServiceFacade groupLoanService; public ApplyAdjustment() { this.groupLoanService = ApplicationContextProvider.getBean(GroupLoanAccountServiceFacade.class); } @Override protected BusinessService getService() throws ServiceException { return new AccountBusinessService(); } @TransactionDemarcate(joinToken=true) public ActionForward editAdjustment(ActionMapping mapping, ActionForm form, HttpServletRequest request, @SuppressWarnings("unused") HttpServletResponse response) throws Exception { ApplyAdjustmentActionForm appAdjustActionForm = (ApplyAdjustmentActionForm) form; boolean isRevert = Boolean.parseBoolean(request.getParameter(Constants.ADJUSTMENT_IS_REVERT)); appAdjustActionForm.setAdjustcheckbox(isRevert); request.setAttribute("method", "loadAdjustment"); return mapping.findForward("loadadjustment_success"); } @TransactionDemarcate(joinToken = true) public ActionForward loadAdjustment(ActionMapping mapping, ActionForm form, HttpServletRequest request, @SuppressWarnings("unused") HttpServletResponse response) throws Exception { ApplyAdjustmentActionForm appAdjustActionForm = (ApplyAdjustmentActionForm) form; AccountBO accnt = getBizService().findBySystemId(appAdjustActionForm.getGlobalAccountNum()); SessionUtils.setAttribute(Constants.BUSINESS_KEY, accnt, request); request.setAttribute("method", "loadAdjustment"); UserContext userContext = getUserContext(request); SessionUtils.setCollectionAttribute(MasterConstants.PAYMENT_TYPE, this.accountServiceFacade.constructPaymentTypeListForLoanRepayment(userContext.getLocaleId()), request); AccountPaymentEntity payment = null; if (request.getParameter(Constants.ADJ_TYPE_KEY) != null && request.getParameter(Constants.ADJ_TYPE_KEY).equals(Constants.ADJ_SPECIFIC)) { Integer paymentId = appAdjustActionForm.getPaymentId(); payment = accnt.findPaymentById(paymentId); AccountPaymentEntity previous = null; AccountPaymentEntity next = null; boolean getPrevious = false; for (AccountPaymentEntity p : accnt.getAccountPayments()) { if (!p.getAmount().equals(Money.zero())) { if (getPrevious) { previous = p; break; } else if (p.getPaymentId().equals(payment.getPaymentId())) { getPrevious = true; } else { next = p; } } } Date previousPaymentDate = (previous == null) ? null : previous.getPaymentDate(); Date nextPaymentDate = (next == null) ? null : next.getPaymentDate(); appAdjustActionForm.setPreviousPaymentDate(previousPaymentDate); appAdjustActionForm.setNextPaymentDate(nextPaymentDate); SessionUtils.setAttribute(Constants.ADJUSTED_AMOUNT, payment.getAmount().getAmount(), request); Short transferPaymentTypeId = legacyAcceptedPaymentTypeDao.getSavingsTransferId(); if (payment.getPaymentType().getId().equals(transferPaymentTypeId)) { List<ListItem<Short>> paymentTypeList = this.accountServiceFacade.constructPaymentTypeListForLoanRepayment(userContext.getLocaleId()); for (Iterator<ListItem<Short>> it = paymentTypeList.iterator(); it.hasNext(); ) { ListItem<Short> listItem = it.next(); if (!listItem.getId().equals(transferPaymentTypeId)) { it.remove(); } } SessionUtils.setCollectionAttribute(MasterConstants.PAYMENT_TYPE, paymentTypeList, request); } else { SessionUtils.setCollectionAttribute(MasterConstants.PAYMENT_TYPE, this.accountServiceFacade.constructPaymentTypeListForLoanRepayment(userContext.getLocaleId()), request); } } else { SessionUtils.setCollectionAttribute(MasterConstants.PAYMENT_TYPE, this.accountServiceFacade.constructPaymentTypeListForLoanRepayment(userContext.getLocaleId()), request); payment = accnt.getLastPmntToBeAdjusted(); appAdjustActionForm.setPaymentId(null); SessionUtils.setAttribute(Constants.ADJUSTED_AMOUNT, accnt.getLastPmntAmntToBeAdjusted(), request); } if (accnt.isParentGroupLoanAccount()) { SessionUtils.setAttribute(Constants.TYPE_OF_GROUP_LOAN, "parentAcc", request); } else if (accnt.isGroupLoanAccountMember()){ appAdjustActionForm.setGroupLoanMember(Boolean.TRUE); } populateForm(appAdjustActionForm, payment); return mapping.findForward("loadadjustment_success"); } @TransactionDemarcate(joinToken = true) public ActionForward loanGroupAdjustment(ActionMapping mapping, ActionForm form, HttpServletRequest request, @SuppressWarnings("unused") HttpServletResponse response) throws Exception { return mapping.findForward("loadgroupadjustment_success"); } @TransactionDemarcate(joinToken = true) public ActionForward listPossibleAdjustments(ActionMapping mapping, ActionForm form, HttpServletRequest request, @SuppressWarnings("unused") HttpServletResponse response) throws Exception { ApplyAdjustmentActionForm appAdjustActionForm = (ApplyAdjustmentActionForm) form; this.resetActionFormFields(appAdjustActionForm); AccountBO accnt = getBizService().findBySystemId(appAdjustActionForm.getGlobalAccountNum()); boolean decliningRecalculation = false; if (accnt instanceof LoanBO) { LoanBO loan = (LoanBO)accnt; if (loan.getInterestType().getId().equals(InterestType.DECLINING_PB.getValue())) { decliningRecalculation = true; } } List<AccountPaymentEntity> payments = accnt.getAccountPayments(); ArrayList<AdjustablePaymentDto> adjustablePayments = new ArrayList<AdjustablePaymentDto>(); int i = 1; for (AccountPaymentEntity payment : payments) { //ommit disbursal payment if (!payment.getAmount().equals(Money.zero()) && i != payments.size()) { AdjustablePaymentDto adjustablePaymentDto = new AdjustablePaymentDto(payment.getPaymentId(), payment.getAmount(), payment.getPaymentType().getName(), payment.getPaymentDate(), payment.getReceiptDate(), payment.getReceiptNumber()); adjustablePayments.add(adjustablePaymentDto); if (decliningRecalculation) { break; //only last payment } } i++; } SessionUtils.setAttribute(Constants.BUSINESS_KEY, accnt, request); SessionUtils.setAttribute(Constants.POSSIBLE_ADJUSTMENTS, adjustablePayments, request); request.setAttribute("method", "loadAdjustment"); return mapping.findForward("loadadjustments_success"); } /* * This method do the same thing as loadAdjustment, but added to allow * handling permission : can adjust payment when account is closed * obligation met */ @TransactionDemarcate(joinToken = true) public ActionForward loadAdjustmentWhenObligationMet(ActionMapping mapping, ActionForm form, HttpServletRequest request, @SuppressWarnings("unused") HttpServletResponse response) throws Exception { ApplyAdjustmentActionForm appAdjustActionForm = (ApplyAdjustmentActionForm) form; AccountBO accnt = getBizService().findBySystemId(appAdjustActionForm.getGlobalAccountNum()); SessionUtils.setAttribute(Constants.BUSINESS_KEY, accnt, request); request.setAttribute("method", "loadAdjustmentWhenObligationMet"); AccountPaymentEntity payment = null; if (request.getParameter(Constants.ADJ_TYPE_KEY) != null && request.getParameter(Constants.ADJ_TYPE_KEY).equals(Constants.ADJ_SPECIFIC)) { Integer paymentId = appAdjustActionForm.getPaymentId(); payment = accnt.findPaymentById(paymentId); SessionUtils.setAttribute(Constants.ADJUSTED_AMOUNT, payment.getAmount().getAmount(), request); } else { payment = accnt.getLastPmntToBeAdjusted(); appAdjustActionForm.setPaymentId(null); SessionUtils.setAttribute(Constants.ADJUSTED_AMOUNT, accnt.getLastPmntAmntToBeAdjusted(), request); } appAdjustActionForm.setAdjustData(false); populateForm(appAdjustActionForm, payment); return mapping.findForward("loadadjustment_success"); } @TransactionDemarcate(joinToken = true) public ActionForward previewAdjustment(ActionMapping mapping, @SuppressWarnings("unused") ActionForm form, HttpServletRequest request, @SuppressWarnings("unused") HttpServletResponse response) throws Exception { ApplyAdjustmentActionForm appAdjustActionForm = (ApplyAdjustmentActionForm) form; appAdjustActionForm.setAdjustData(!appAdjustActionForm.getAdjustcheckbox()); if (appAdjustActionForm.isAdjustData()) { @SuppressWarnings("unchecked") List<ListItem<Short>> paymentTypes = (List<ListItem<Short>>)SessionUtils.getAttribute(MasterConstants.PAYMENT_TYPE, request); Short elementType = Short.valueOf(appAdjustActionForm.getPaymentType()); for (ListItem<Short> item : paymentTypes) { if (item.getId().equals(elementType)) { SessionUtils.setAttribute(Constants.ADJUSTMENT_PAYMENT_TYPE, item.getDisplayValue(), request); } } } if ( appAdjustActionForm.getNewAmounts() != null && !appAdjustActionForm.getNewAmounts().isEmpty()){ BigDecimal newAmount = BigDecimal.ZERO; for (String memberNewAmountString : appAdjustActionForm.getNewAmounts().values()){ BigDecimal memberNewAmount = BigDecimal.ZERO; if (!StringUtils.isBlank(memberNewAmountString)) { memberNewAmount = new BigDecimal(memberNewAmountString); } newAmount = newAmount.add(memberNewAmount); } appAdjustActionForm.setAmount(newAmount.toString()); } request.setAttribute("method", "previewAdjustment"); return mapping.findForward("previewadj_success"); } @TransactionDemarcate(joinToken = true) public ActionForward divide(ActionMapping mapping, ActionForm form, HttpServletRequest request, @SuppressWarnings("unused") HttpServletResponse response) throws Exception { ApplyAdjustmentActionForm applyAdjustmentActionForm = (ApplyAdjustmentActionForm) form; Integer parentAccountId = getBizService().findBySystemId(applyAdjustmentActionForm.getGlobalAccountNum()).getAccountId(); Integer parentPaymentId = applyAdjustmentActionForm.getPaymentId(); BigDecimal newAmount = new BigDecimal(applyAdjustmentActionForm.getAmount()); if (applyAdjustmentActionForm.getAdjustcheckbox()){ newAmount = BigDecimal.ZERO; } List<GroupLoanMemberAdjustmentDto> memberAdjustmentDtoList = this.groupLoanService.retrieveMemberAdjustmentDtos(parentAccountId, parentPaymentId, newAmount); applyAdjustmentActionForm.setMemberAdjustmentDtoList(memberAdjustmentDtoList); return mapping.findForward("divideadjustment_success"); } @TransactionDemarcate(validateAndResetToken = true) @CloseSession public ActionForward applyAdjustment(ActionMapping mapping, ActionForm form, HttpServletRequest request, @SuppressWarnings("unused") HttpServletResponse response) throws Exception { request.setAttribute("method", "applyAdjustment"); ApplyAdjustmentActionForm appAdjustActionForm = (ApplyAdjustmentActionForm) form; Integer paymentId = appAdjustActionForm.getPaymentId(); checkVersionMismatchForAccountBO(request, appAdjustActionForm); UserContext userContext = (UserContext) SessionUtils.getAttribute(Constants.USER_CONTEXT_KEY, request.getSession()); try { if (paymentId == null) { accountServiceFacade.applyAdjustment(appAdjustActionForm.getGlobalAccountNum(), appAdjustActionForm.getAdjustmentNote(), userContext.getId()); } else { AdjustedPaymentDto adjustedPaymentDto = appAdjustActionForm.getPaymentData(); if (appAdjustActionForm.isGroupLoanMember()){ accountServiceFacade.applyMemberAccountHistoricalAdjustment(appAdjustActionForm.getGlobalAccountNum(), paymentId, appAdjustActionForm.getAdjustmentNote(), userContext.getId(), adjustedPaymentDto); } else { accountServiceFacade.applyHistoricalAdjustment(appAdjustActionForm.getGlobalAccountNum(), paymentId, appAdjustActionForm.getAdjustmentNote(), userContext.getId(), adjustedPaymentDto); } } } catch (MifosRuntimeException e) { request.setAttribute("method", "previewAdjustment"); throw (Exception) e.getCause(); } resetActionFormFields(appAdjustActionForm); return mapping.findForward("applyadj_success"); } private void checkVersionMismatchForAccountBO(HttpServletRequest request, ApplyAdjustmentActionForm appAdjustActionForm) throws ApplicationException { AccountBO accountBOInSession = (AccountBO) SessionUtils.getAttribute(Constants.BUSINESS_KEY, request); AccountBO accountBO = getBizService().findBySystemId(appAdjustActionForm.getGlobalAccountNum()); checkVersionMismatch(accountBOInSession.getVersionNo(), accountBO.getVersionNo()); } @TransactionDemarcate(validateAndResetToken = true) public ActionForward cancelAdjustment(ActionMapping mapping, ActionForm form, @SuppressWarnings("unused") HttpServletRequest request, @SuppressWarnings("unused") HttpServletResponse response) throws Exception { ApplyAdjustmentActionForm appAdjustActionForm = (ApplyAdjustmentActionForm) form; resetActionFormFields(appAdjustActionForm); return mapping.findForward("canceladj_success"); } /** * This method resets action form fields after successfully applying payment * or on cancel. */ private void resetActionFormFields(ApplyAdjustmentActionForm appAdjustActionForm) { appAdjustActionForm.setAdjustmentNote(null); appAdjustActionForm.setPaymentId(null); appAdjustActionForm.setGroupLoanMember(Boolean.FALSE); } @Override protected boolean isNewBizRequired(HttpServletRequest request) throws ServiceException { if (request.getAttribute(Constants.BUSINESS_KEY) != null) { return false; } return true; } private AccountBusinessService getBizService() { return new AccountBusinessService(); } private void populateForm(ApplyAdjustmentActionForm form, AccountPaymentEntity payment) { if (payment != null) { form.setPaymentType(String.valueOf(payment.getPaymentType().getId())); form.setAmount(payment.getAmount().toString()); form.setTrxnDate(payment.getPaymentDate()); form.setAccountId(payment.getAccount().getAccountId()); } if (form.getMemberAdjustmentDtoList()!= null){ form.getMemberAdjustmentDtoList().clear(); } form.getNewAmounts().clear(); } }