/*
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.List;
import javax.servlet.http.HttpServletRequest;
import nl.strohalm.cyclos.annotations.Inject;
import nl.strohalm.cyclos.controls.ActionContext;
import nl.strohalm.cyclos.controls.BaseAction;
import nl.strohalm.cyclos.entities.Relationship;
import nl.strohalm.cyclos.entities.accounts.AccountType;
import nl.strohalm.cyclos.entities.accounts.transactions.Invoice;
import nl.strohalm.cyclos.entities.accounts.transactions.Payment;
import nl.strohalm.cyclos.entities.accounts.transactions.ScheduledPayment;
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.groups.MemberGroup;
import nl.strohalm.cyclos.entities.members.Administrator;
import nl.strohalm.cyclos.entities.members.Element;
import nl.strohalm.cyclos.entities.members.Member;
import nl.strohalm.cyclos.entities.members.Operator;
import nl.strohalm.cyclos.services.customization.PaymentCustomFieldService;
import nl.strohalm.cyclos.services.transactions.InvoiceService;
import nl.strohalm.cyclos.services.transfertypes.TransferTypeService;
import nl.strohalm.cyclos.utils.CustomFieldHelper;
import nl.strohalm.cyclos.utils.CustomFieldHelper.Entry;
import nl.strohalm.cyclos.utils.RelationshipHelper;
import nl.strohalm.cyclos.utils.validation.ValidationException;
import org.apache.struts.action.ActionForward;
/**
* Action used to show an invoice details
* @author luis
*/
public class InvoiceDetailsAction extends BaseAction {
private static final Relationship[] FETCH = { Invoice.Relationships.CUSTOM_VALUES, RelationshipHelper.nested(Invoice.Relationships.FROM_MEMBER, Element.Relationships.USER), RelationshipHelper.nested(Invoice.Relationships.TO_MEMBER, Element.Relationships.USER), RelationshipHelper.nested(Invoice.Relationships.SENT_BY, Element.Relationships.USER), RelationshipHelper.nested(Invoice.Relationships.PERFORMED_BY, Element.Relationships.USER), RelationshipHelper.nested(Invoice.Relationships.DESTINATION_ACCOUNT_TYPE, AccountType.Relationships.CURRENCY), Invoice.Relationships.TRANSFER, RelationshipHelper.nested(Invoice.Relationships.TRANSFER_TYPE, TransferType.Relationships.TO), Invoice.Relationships.PAYMENTS };
private InvoiceService invoiceService;
private TransferTypeService transferTypeService;
private PaymentCustomFieldService paymentCustomFieldService;
private CustomFieldHelper customFieldHelper;
public InvoiceService getInvoiceService() {
return invoiceService;
}
public TransferTypeService getTransferTypeService() {
return transferTypeService;
}
@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 setTransferTypeService(final TransferTypeService transferTypeService) {
this.transferTypeService = transferTypeService;
}
@Override
protected ActionForward executeAction(final ActionContext context) throws Exception {
final HttpServletRequest request = context.getRequest();
final InvoiceDetailsForm form = context.getForm();
final long id = form.getInvoiceId();
if (id <= 0) {
throw new ValidationException();
}
long memberId;
if (context.isBroker() || context.isAdmin()) {
memberId = form.getMemberId();
} else { // member or operator
memberId = ((Member) context.getAccountOwner()).getId();
}
final Member member = (Member) (memberId <= 0 ? null : elementService.load(memberId));
final Invoice invoice = invoiceService.load(id, FETCH);
if (member != null && !member.equals(invoice.getFromMember()) && !member.equals(invoice.getToMember())) {
// The passed member id is not related to the invoice
throw new ValidationException();
}
// Get the custom values
final List<TransferType> possibleTransferTypes = invoiceService.getPossibleTransferTypes(invoice);
if (possibleTransferTypes.size() == 1) {
final TransferType transferType = possibleTransferTypes.iterator().next();
final List<PaymentCustomField> customFields = paymentCustomFieldService.list(transferType, false);
final Collection<Entry> entries = customFieldHelper.buildEntries(customFields, invoice.getCustomValues());
request.setAttribute("customFields", entries);
}
final TransferType transferType = invoice.getTransferType();
AccountType accountType = invoice.getDestinationAccountType();
if (accountType == null && transferType != null) {
accountType = transferType.getTo();
}
final boolean toMe = context.getAccountOwner().equals(invoice.getTo());
final boolean fromMe = context.getAccountOwner().equals(invoice.getFrom());
// Only show the destination account type when not logged as the invoice to and the invoice sender has more than one accounts
boolean showDestinationAccountType = false;
if (!context.getElement().equals(invoice.getToMember()) && transferType == null && invoice.getDestinationAccountType() != null) {
final Member fromMember = elementService.load(invoice.getFromMember().getId(), RelationshipHelper.nested(Element.Relationships.GROUP, MemberGroup.Relationships.ACCOUNT_SETTINGS));
final int accounts = fromMember.getMemberGroup().getAccountSettings().size();
showDestinationAccountType = accounts > 1;
}
final boolean showSentBy = shouldShowSentBy(context, invoice);
final boolean showPerformedBy = shouldShowPerformedBy(context, invoice);
final Payment payment = invoice.getPayment();
if (payment instanceof Transfer) {
request.setAttribute("transferId", payment.getId());
} else if (payment instanceof ScheduledPayment) {
request.setAttribute("paymentId", payment.getId());
}
final boolean canAccept = invoiceService.canAccept(invoice);
final boolean canDeny = invoiceService.canDeny(invoice);
final boolean canCancel = invoiceService.canCancel(invoice);
request.setAttribute("invoice", invoice);
request.setAttribute("member", member);
request.setAttribute("unitsPattern", accountType.getCurrency().getPattern());
request.setAttribute("transferTypes", possibleTransferTypes);
request.setAttribute("toMe", toMe);
request.setAttribute("fromMe", fromMe);
request.setAttribute("canAccept", canAccept);
request.setAttribute("canDeny", canDeny);
request.setAttribute("canCancel", canCancel);
request.setAttribute("showDestinationAccountType", showDestinationAccountType);
request.setAttribute("showPerformedBy", showPerformedBy);
request.setAttribute("showSentBy", showSentBy);
return context.getInputForward();
}
/**
* Returns whether the 'performed by' should be shown to the user
*/
private boolean shouldShowPerformedBy(final ActionContext context, final Invoice invoice) {
boolean showPerformedBy = false;
final HttpServletRequest request = context.getRequest();
final Element performedBy = invoice.getPerformedBy();
if (performedBy != null) {
if (performedBy instanceof Administrator) {
if (context.isAdmin()) {
request.setAttribute("performedByAdmin", performedBy);
showPerformedBy = true;
} else {
// Don't disclose to member which admin performed the action
request.setAttribute("performedBySystem", true);
// Only show performed by if invoice was not performed by the normal owner
final boolean shouldBeFromSystem = invoice.getStatus() == Invoice.Status.CANCELLED;
showPerformedBy = shouldBeFromSystem && !invoice.isFromSystem();
}
} else {
Member shouldHavePerformed = null;
switch (invoice.getStatus()) {
case ACCEPTED:
case DENIED:
shouldHavePerformed = invoice.getToMember();
break;
case CANCELLED:
shouldHavePerformed = invoice.getFromMember();
break;
}
if (performedBy.equals(shouldHavePerformed)) {
showPerformedBy = false;
} else if ((performedBy instanceof Operator) && (context.isMemberOf((Operator) performedBy) || context.isOperator())) {
request.setAttribute("performedByOperator", performedBy);
showPerformedBy = true;
} else {
request.setAttribute("performedByMember", performedBy.getAccountOwner());
showPerformedBy = true;
}
}
}
return showPerformedBy;
}
/**
* Returns whether the 'sent by' should be shown to the user
*/
private boolean shouldShowSentBy(final ActionContext context, final Invoice invoice) {
boolean showSentBy = false;
final HttpServletRequest request = context.getRequest();
final Element sentBy = invoice.getSentBy();
if (sentBy != null) {
if (sentBy instanceof Administrator) {
if (context.isAdmin()) {
request.setAttribute("sentByAdmin", sentBy);
showSentBy = true;
} else {
// Don't disclose to member which admin sent the invoice
request.setAttribute("sentBySystem", true);
showSentBy = !invoice.isFromSystem(); // Only show sent by if not a regular system -> member invoice,
}
} else if ((sentBy instanceof Operator) && (context.isMemberOf((Operator) sentBy) || context.isOperator())) {
request.setAttribute("sentByOperator", sentBy);
showSentBy = true;
} else if (!invoice.getFromMember().equals(sentBy)) {
final Member member = (Member) sentBy.getAccountOwner();
request.setAttribute("sentByMember", member);
showSentBy = !invoice.getFrom().equals(member);
}
}
return showSentBy;
}
}