/* 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.invoices; import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.servlet.http.HttpServletRequest; import nl.strohalm.cyclos.annotations.Inject; import nl.strohalm.cyclos.controls.ActionContext; import nl.strohalm.cyclos.controls.BaseFormAction; import nl.strohalm.cyclos.entities.accounts.AccountOwner; import nl.strohalm.cyclos.entities.accounts.AccountType; import nl.strohalm.cyclos.entities.accounts.transactions.Invoice; import nl.strohalm.cyclos.entities.accounts.transactions.Transfer; import nl.strohalm.cyclos.entities.accounts.transactions.TransferType; import nl.strohalm.cyclos.entities.customization.fields.PaymentCustomField; import nl.strohalm.cyclos.entities.exceptions.UnexpectedEntityException; import nl.strohalm.cyclos.entities.members.Member; import nl.strohalm.cyclos.services.customization.PaymentCustomFieldService; import nl.strohalm.cyclos.services.transactions.InvoiceService; import nl.strohalm.cyclos.services.transactions.PaymentService; import nl.strohalm.cyclos.services.transactions.exceptions.CreditsException; import nl.strohalm.cyclos.services.transfertypes.TransactionFeePreviewDTO; import nl.strohalm.cyclos.services.transfertypes.TransactionFeeService; import nl.strohalm.cyclos.services.transfertypes.TransferTypeService; import nl.strohalm.cyclos.utils.ActionHelper; import nl.strohalm.cyclos.utils.CustomFieldHelper; import nl.strohalm.cyclos.utils.CustomFieldHelper.Entry; import nl.strohalm.cyclos.utils.RelationshipHelper; import nl.strohalm.cyclos.utils.binding.BeanBinder; import nl.strohalm.cyclos.utils.binding.DataBinder; import nl.strohalm.cyclos.utils.binding.PropertyBinder; import nl.strohalm.cyclos.utils.conversion.IdConverter; import nl.strohalm.cyclos.utils.conversion.ReferenceConverter; import nl.strohalm.cyclos.utils.validation.RequiredError; import nl.strohalm.cyclos.utils.validation.ValidationException; import org.apache.commons.lang.StringUtils; import org.apache.struts.action.ActionForward; /** * Action used to accept an invoice * @author luis */ public class AcceptInvoiceAction extends BaseFormAction { private DataBinder<Invoice> dataBinder; private InvoiceService invoiceService; private TransactionFeeService transactionFeeService; private PaymentService paymentService; private PaymentCustomFieldService paymentCustomFieldService; private TransferTypeService transferTypeService; private CustomFieldHelper customFieldHelper; public DataBinder<Invoice> getDataBinder() { if (dataBinder == null) { final BeanBinder<Invoice> binder = BeanBinder.instance(Invoice.class); binder.registerBinder("id", PropertyBinder.instance(Long.class, "invoiceId", IdConverter.instance())); binder.registerBinder("transferType", PropertyBinder.instance(TransferType.class, "transferTypeId", ReferenceConverter.instance(TransferType.class))); dataBinder = binder; } return dataBinder; } public InvoiceService getInvoiceService() { return invoiceService; } public TransactionFeeService getTransactionFeeService() { return transactionFeeService; } @Inject public void setCustomFieldHelper(final CustomFieldHelper customFieldHelper) { this.customFieldHelper = customFieldHelper; } @Inject public void setInvoiceService(final InvoiceService invoiceService) { this.invoiceService = invoiceService; } @Inject public void setPaymentCustomFieldService(final PaymentCustomFieldService paymentCustomFieldService) { this.paymentCustomFieldService = paymentCustomFieldService; } @Inject public void setPaymentService(final PaymentService paymentService) { this.paymentService = paymentService; } @Inject public void setTransactionFeeService(final TransactionFeeService transactionFeeService) { this.transactionFeeService = transactionFeeService; } @Inject public void setTransferTypeService(final TransferTypeService transferTypeService) { this.transferTypeService = transferTypeService; } @Override protected ActionForward handleSubmit(final ActionContext context) throws Exception { try { final AcceptInvoiceForm form = context.getForm(); Invoice invoice = getDataBinder().readFromString(form); final boolean requestTransactionPassword = shouldValidateTransactionPassword(context, invoice, invoice.getTransferType()); if (requestTransactionPassword) { context.checkTransactionPassword(form.getTransactionPassword()); } invoice = invoiceService.accept(invoice); final Transfer transfer = invoice.getTransfer(); if (transfer != null && transfer.getProcessDate() == null) { context.sendMessage("invoice.accepted.withAuthorization"); } else { context.sendMessage("invoice.accepted"); } final Map<String, Object> params = new HashMap<String, Object>(); params.put("invoiceId", invoice.getId()); params.put("memberId", form.getMemberId()); params.put("accountFeeLogId", form.getAccountFeeLogId()); return ActionHelper.redirectWithParams(context.getRequest(), context.getSuccessForward(), params); } catch (final CreditsException e) { return context.sendError(actionHelper.resolveErrorKey(e), actionHelper.resolveParameters(e)); } catch (final UnexpectedEntityException e) { return context.sendError("payment.error.invalidTransferType"); } } @Override protected void prepareForm(final ActionContext context) throws Exception { final HttpServletRequest request = context.getRequest(); final AcceptInvoiceForm form = context.getForm(); Invoice invoice = getDataBinder().readFromString(form); // Get the selected transfer type TransferType transferType = invoice.getTransferType(); if (transferType != null) { transferType = transferTypeService.load(transferType.getId(), RelationshipHelper.nested(TransferType.Relationships.FROM, AccountType.Relationships.CURRENCY), TransferType.Relationships.TO); } invoice = invoiceService.load(invoice.getId(), Invoice.Relationships.FROM_MEMBER, Invoice.Relationships.TO_MEMBER); // Check if there are multiple transfer type choices - used to show or hide the transfer type final List<TransferType> transferTypes = invoiceService.getPossibleTransferTypes(invoice); // Get the custom values if (transferTypes.size() == 1) { transferType = transferTypes.iterator().next(); invoice.setTransferType(transferType); final List<PaymentCustomField> customFields = paymentCustomFieldService.list(transferType, false); final Collection<Entry> entries = customFieldHelper.buildEntries(customFields, invoice.getCustomValues()); request.setAttribute("customFields", entries); } // When the invoice was already associated with a transfer type, use it final boolean preSelectedTransferType = invoice.getTransferType() != null; if (preSelectedTransferType) { transferType = transferTypeService.load(invoice.getTransferType().getId(), RelationshipHelper.nested(TransferType.Relationships.FROM, AccountType.Relationships.CURRENCY), TransferType.Relationships.TO); } // Check for transaction password final boolean requestTransactionPassword = shouldValidateTransactionPassword(context, invoice, transferType); if (requestTransactionPassword) { context.validateTransactionPassword(); } request.setAttribute("invoice", invoice); request.setAttribute("transferType", transferType); request.setAttribute("requestTransactionPassword", requestTransactionPassword); request.setAttribute("unitsPattern", transferType.getFrom().getCurrency().getPattern()); // Check whether authorization would be required final Invoice clone = (Invoice) invoice.clone(); clone.setId(null); clone.setTransferType(transferType); final boolean wouldRequireAuthorization = paymentService.wouldRequireAuthorization(clone); request.setAttribute("wouldRequireAuthorization", wouldRequireAuthorization); if (!preSelectedTransferType) { if (transferTypes.isEmpty()) { throw new ValidationException(); } request.setAttribute("showTransferType", transferTypes.size() > 1); } final AccountOwner from = invoice.getTo(); final AccountOwner to = invoice.getFrom(); if (from instanceof Member) { request.setAttribute("fromMember", from); } if (to instanceof Member) { request.setAttribute("toMember", to); } // Store the transaction fees final TransactionFeePreviewDTO preview = transactionFeeService.preview(clone); request.setAttribute("finalAmount", preview.getFinalAmount()); request.setAttribute("fees", preview.getFees()); } @Override protected void validateForm(final ActionContext context) { final AcceptInvoiceForm form = context.getForm(); final Invoice invoice = getDataBinder().readFromString(form); invoiceService.validateForAccept(invoice); if (shouldValidateTransactionPassword(context, invoice, invoice.getTransferType())) { if (StringUtils.isEmpty(form.getTransactionPassword())) { throw new ValidationException("_transactionPassword", "login.transactionPassword", new RequiredError()); } } } private boolean shouldValidateTransactionPassword(final ActionContext context, Invoice invoice, TransferType transferType) { final AccountOwner loggedOwner = context.getAccountOwner(); invoice = invoiceService.load(invoice.getId(), Invoice.Relationships.TO_MEMBER); if (loggedOwner.equals(invoice.getToMember())) { // When a logged member accepting an invoice to himself transferType = transferTypeService.load(transferType.getId(), TransferType.Relationships.FROM); return context.isTransactionPasswordEnabled(transferType.getFrom()); } else { return context.isTransactionPasswordEnabled(); } } }