nl.strohalm.cyclos.controls.loans.GrantLoanAction.java Source code

Java tutorial

Introduction

Here is the source code for nl.strohalm.cyclos.controls.loans.GrantLoanAction.java

Source

/*
This file is part of Cyclos (www.cyclos.org).
A project of the Social Trade Organisation (www.socialtrade.org).
    
Cyclos is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
    
Cyclos is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
    
You should have received a copy of the GNU General Public License
along with Cyclos; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
    
 */
package nl.strohalm.cyclos.controls.loans;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import nl.strohalm.cyclos.access.AdminMemberPermission;
import nl.strohalm.cyclos.annotations.Inject;
import nl.strohalm.cyclos.controls.ActionContext;
import nl.strohalm.cyclos.controls.BaseFormAction;
import nl.strohalm.cyclos.entities.accounts.AccountType;
import nl.strohalm.cyclos.entities.accounts.SystemAccountType;
import nl.strohalm.cyclos.entities.accounts.loans.Loan;
import nl.strohalm.cyclos.entities.accounts.loans.LoanGroup;
import nl.strohalm.cyclos.entities.accounts.loans.LoanGroupQuery;
import nl.strohalm.cyclos.entities.accounts.loans.LoanParameters;
import nl.strohalm.cyclos.entities.accounts.loans.LoanPayment;
import nl.strohalm.cyclos.entities.accounts.transactions.TransferType;
import nl.strohalm.cyclos.entities.accounts.transactions.TransferTypeQuery;
import nl.strohalm.cyclos.entities.customization.fields.PaymentCustomField;
import nl.strohalm.cyclos.entities.customization.fields.PaymentCustomFieldValue;
import nl.strohalm.cyclos.entities.groups.AdminGroup;
import nl.strohalm.cyclos.entities.groups.Group;
import nl.strohalm.cyclos.entities.members.Element;
import nl.strohalm.cyclos.entities.members.Member;
import nl.strohalm.cyclos.entities.settings.LocalSettings;
import nl.strohalm.cyclos.exceptions.PermissionDeniedException;
import nl.strohalm.cyclos.services.loangroups.LoanGroupService;
import nl.strohalm.cyclos.services.transactions.GrantLoanDTO;
import nl.strohalm.cyclos.services.transactions.GrantLoanWithInterestDTO;
import nl.strohalm.cyclos.services.transactions.GrantMultiPaymentLoanDTO;
import nl.strohalm.cyclos.services.transactions.GrantSinglePaymentLoanDTO;
import nl.strohalm.cyclos.services.transactions.LoanService;
import nl.strohalm.cyclos.services.transactions.TransactionContext;
import nl.strohalm.cyclos.services.transfertypes.TransferTypeService;
import nl.strohalm.cyclos.utils.ActionHelper;
import nl.strohalm.cyclos.utils.RelationshipHelper;
import nl.strohalm.cyclos.utils.binding.BeanBinder;
import nl.strohalm.cyclos.utils.binding.BeanCollectionBinder;
import nl.strohalm.cyclos.utils.binding.DataBinder;
import nl.strohalm.cyclos.utils.binding.PropertyBinder;
import nl.strohalm.cyclos.utils.conversion.CoercionHelper;
import nl.strohalm.cyclos.utils.conversion.HtmlConverter;
import nl.strohalm.cyclos.utils.conversion.ReferenceConverter;
import nl.strohalm.cyclos.utils.validation.InvalidError;
import nl.strohalm.cyclos.utils.validation.ValidationException;

import org.apache.commons.collections.CollectionUtils;
import org.apache.struts.action.ActionForward;

/**
 * Action used to grant a loan to a given member or loan group
 * @author luis
 */
public class GrantLoanAction extends BaseFormAction {

    private LoanGroupService loanGroupService;
    private LoanService loanService;
    private TransferTypeService transferTypeService;

    @Inject
    public void setLoanGroupService(final LoanGroupService loanGroupService) {
        this.loanGroupService = loanGroupService;
    }

    @Inject
    public void setLoanService(final LoanService loanService) {
        this.loanService = loanService;
    }

    @Inject
    public void setTransferTypeService(final TransferTypeService transferTypeService) {
        this.transferTypeService = transferTypeService;
    }

    @Override
    protected ActionForward handleDisplay(final ActionContext context) throws Exception {

        final HttpServletRequest request = context.getRequest();
        final GrantLoanForm form = context.getForm();
        Member member = null;
        LoanGroup loanGroup = null;
        if (form.getMemberId() > 0L) {
            final Element element = elementService.load(form.getMemberId(), Element.Relationships.USER);
            if (element instanceof Member) {
                member = (Member) element;
            }
        } else if (form.getLoanGroupId() > 0L) {
            loanGroup = loanGroupService.load(form.getLoanGroupId(), LoanGroup.Relationships.MEMBERS);
        }

        if (member == null && loanGroup == null) {
            throw new ValidationException();
        }
        request.setAttribute("member", member);
        request.setAttribute("loanGroup", loanGroup);

        if (member != null) {
            form.setLoan("member", member.getId());
            AdminGroup adminGroup = context.getGroup();
            adminGroup = groupService.load(adminGroup.getId(), AdminGroup.Relationships.VIEW_INFORMATION_OF,
                    Group.Relationships.TRANSFER_TYPES);

            // Get the possible transfer types
            List<TransferType> transferTypes;
            final ArrayList<SystemAccountType> systemAccounts = new ArrayList<SystemAccountType>(
                    adminGroup.getViewInformationOf());
            if (CollectionUtils.isEmpty(systemAccounts)) {
                transferTypes = Collections.emptyList();
            } else {
                final TransferTypeQuery ttQuery = new TransferTypeQuery();
                ttQuery.setContext(TransactionContext.LOAN);
                ttQuery.setToOwner(member);
                ttQuery.setUsePriority(true);
                ttQuery.setFromAccountTypes(systemAccounts);
                transferTypes = transferTypeService.search(ttQuery);
                // Remove transfer types without permission
                final Collection<TransferType> transferTypesWithPermission = adminGroup.getTransferTypes();
                for (final Iterator<TransferType> iter = transferTypes.iterator(); iter.hasNext();) {
                    final TransferType transferType = iter.next();
                    if (!transferTypesWithPermission.contains(transferType)) {
                        iter.remove();
                    }
                }
            }
            if (transferTypes.isEmpty()) {
                return context.sendError("loan.error.noTransferType");
            }
            request.setAttribute("transferTypes", transferTypes);

            if (permissionService.hasPermission(AdminMemberPermission.LOAN_GROUPS_VIEW)) {
                // Get the loan groups of this member
                final LoanGroupQuery lgQuery = new LoanGroupQuery();
                lgQuery.setMember(member);
                final List<LoanGroup> loanGroups = loanGroupService.search(lgQuery);
                request.setAttribute("loanGroups", loanGroups);
            }
        } else {
            form.setLoan("loanGroup", loanGroup.getId());
        }

        return context.getInputForward();
    }

    @Override
    protected ActionForward handleSubmit(final ActionContext context) throws Exception {
        final GrantLoanDTO dto = resolveDTO(context);
        final GrantLoanForm form = context.getForm();
        context.getSession().setAttribute("loan", dto);

        final Map<String, Object> params = new HashMap<String, Object>();
        params.put("memberId", form.getMemberId());
        params.put("loanGroupId", form.getLoanGroupId());
        return ActionHelper.redirectWithParams(context.getRequest(), context.getSuccessForward(), params);
    }

    @Override
    protected void validateForm(final ActionContext context) {
        final GrantLoanDTO dto = resolveDTO(context);
        loanService.validate(dto);
    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
    private DataBinder<GrantLoanDTO> getDataBinder(final Loan.Type type) {
        final LocalSettings settings = settingsService.getLocalSettings();

        final BeanBinder<PaymentCustomFieldValue> customValueBinder = BeanBinder
                .instance(PaymentCustomFieldValue.class);
        customValueBinder.registerBinder("field", PropertyBinder.instance(PaymentCustomField.class, "field",
                ReferenceConverter.instance(PaymentCustomField.class)));
        customValueBinder.registerBinder("value",
                PropertyBinder.instance(String.class, "value", HtmlConverter.instance()));

        final BeanBinder binder = new BeanBinder();
        binder.registerBinder("member",
                PropertyBinder.instance(Member.class, "member", ReferenceConverter.instance(Member.class)));
        binder.registerBinder("loanGroup", PropertyBinder.instance(LoanGroup.class, "loanGroup",
                ReferenceConverter.instance(LoanGroup.class)));
        binder.registerBinder("amount",
                PropertyBinder.instance(BigDecimal.class, "amount", settings.getNumberConverter()));
        binder.registerBinder("date",
                PropertyBinder.instance(Calendar.class, "date", settings.getRawDateConverter()));
        binder.registerBinder("description", PropertyBinder.instance(String.class, "description"));
        binder.registerBinder("transferType", PropertyBinder.instance(TransferType.class, "transferType",
                ReferenceConverter.instance(TransferType.class)));
        binder.registerBinder("customValues", BeanCollectionBinder.instance(customValueBinder, "customValues"));

        switch (type) {
        case SINGLE_PAYMENT:
            binder.setType(GrantSinglePaymentLoanDTO.class);
            binder.registerBinder("repaymentDate",
                    PropertyBinder.instance(Calendar.class, "repaymentDate", settings.getRawDateConverter()));
            break;
        case MULTI_PAYMENT:
            binder.setType(GrantMultiPaymentLoanDTO.class);
            final BeanBinder<LoanPayment> paymentBinder = BeanBinder.instance(LoanPayment.class);
            paymentBinder.registerBinder("expirationDate",
                    PropertyBinder.instance(Calendar.class, "expirationDate", settings.getRawDateConverter()));
            paymentBinder.registerBinder("amount",
                    PropertyBinder.instance(BigDecimal.class, "amount", settings.getNumberConverter()));
            binder.registerBinder("payments", BeanCollectionBinder.instance(paymentBinder, "payments"));
            break;
        case WITH_INTEREST:
            binder.setType(GrantLoanWithInterestDTO.class);
            binder.registerBinder("firstRepaymentDate",
                    PropertyBinder.instance(Calendar.class, "firstRepaymentDate", settings.getRawDateConverter()));
            binder.registerBinder("paymentCount", PropertyBinder.instance(Integer.TYPE, "paymentCount"));
            break;
        default:
            throw new IllegalArgumentException("Invalid loan type: " + type);
        }
        return binder;
    }

    /**
     * Resolve the GrantLoanDTO
     */
    private GrantLoanDTO resolveDTO(final ActionContext context) {
        final GrantLoanForm form = context.getForm();
        final long transferTypeId = CoercionHelper.coerce(Long.TYPE, form.getLoan("transferType"));
        if (transferTypeId <= 0L) {
            throw new ValidationException();
        }
        final TransferType transferType = transferTypeService.load(transferTypeId,
                RelationshipHelper.nested(TransferType.Relationships.TO, AccountType.Relationships.CURRENCY));
        final LoanParameters loanParameters = transferType.getLoan();
        if (loanParameters == null || loanParameters.getType() == null) {
            throw new ValidationException("transferType", "transfer.type", new InvalidError());
        }
        final GrantLoanDTO dto = getDataBinder(loanParameters.getType()).readFromString(form.getLoan());
        dto.setTransferType(transferType);
        if (dto.getLoanGroup() != null
                && !permissionService.hasPermission(AdminMemberPermission.LOAN_GROUPS_VIEW)) {
            throw new PermissionDeniedException();
        }
        return dto;
    }

}