/* 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.accounts.accountfees; import java.math.BigDecimal; import java.util.Arrays; import java.util.Calendar; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks.ReentrantReadWriteLock; 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.MemberAccountType; import nl.strohalm.cyclos.entities.accounts.fees.account.AccountFee; import nl.strohalm.cyclos.entities.accounts.fees.account.AccountFee.ChargeMode; import nl.strohalm.cyclos.entities.accounts.fees.account.AccountFee.InvoiceMode; import nl.strohalm.cyclos.entities.accounts.fees.account.AccountFee.PaymentDirection; import nl.strohalm.cyclos.entities.accounts.fees.account.AccountFee.RunMode; import nl.strohalm.cyclos.entities.accounts.fees.account.AccountFeeLogQuery; import nl.strohalm.cyclos.entities.accounts.transactions.TransferType; import nl.strohalm.cyclos.entities.groups.Group; import nl.strohalm.cyclos.entities.groups.GroupQuery; import nl.strohalm.cyclos.entities.groups.MemberGroup; import nl.strohalm.cyclos.entities.settings.LocalSettings; import nl.strohalm.cyclos.entities.settings.events.LocalSettingsChangeListener; import nl.strohalm.cyclos.entities.settings.events.LocalSettingsEvent; import nl.strohalm.cyclos.services.accountfees.AccountFeeService; import nl.strohalm.cyclos.services.accounts.AccountTypeService; import nl.strohalm.cyclos.services.transfertypes.TransferTypeService; import nl.strohalm.cyclos.utils.ActionHelper; import nl.strohalm.cyclos.utils.RequestHelper; import nl.strohalm.cyclos.utils.TimePeriod; import nl.strohalm.cyclos.utils.WeekDay; import nl.strohalm.cyclos.utils.binding.BeanBinder; import nl.strohalm.cyclos.utils.binding.DataBinder; import nl.strohalm.cyclos.utils.binding.DataBinderHelper; import nl.strohalm.cyclos.utils.binding.PropertyBinder; import nl.strohalm.cyclos.utils.binding.SimpleCollectionBinder; import nl.strohalm.cyclos.utils.conversion.IdConverter; import nl.strohalm.cyclos.utils.conversion.ReferenceConverter; import nl.strohalm.cyclos.utils.query.PageHelper; import nl.strohalm.cyclos.utils.validation.ValidationException; import org.apache.struts.action.ActionForward; /** * Action used to edit an account fee * @author luis */ public class EditAccountFeeAction extends BaseFormAction implements LocalSettingsChangeListener { private AccountFeeService accountFeeService; private AccountTypeService accountTypeService; private TransferTypeService transferTypeService; private DataBinder<AccountFee> dataBinder; private ReadWriteLock lock = new ReentrantReadWriteLock(true); public AccountFeeService getAccountFeeService() { return accountFeeService; } public AccountTypeService getAccountTypeService() { return accountTypeService; } public DataBinder<AccountFee> getDataBinder() { try { lock.readLock().lock(); if (dataBinder == null) { final LocalSettings localSettings = settingsService.getLocalSettings(); final BeanBinder<AccountFee> binder = BeanBinder.instance(AccountFee.class); binder.registerBinder("id", PropertyBinder.instance(Long.class, "id", IdConverter.instance())); binder.registerBinder("accountType", PropertyBinder.instance(MemberAccountType.class, "accountType", ReferenceConverter.instance(MemberAccountType.class))); binder.registerBinder("name", PropertyBinder.instance(String.class, "name")); binder.registerBinder("description", PropertyBinder.instance(String.class, "description")); binder.registerBinder("paymentDirection", PropertyBinder.instance(PaymentDirection.class, "paymentDirection")); binder.registerBinder("chargeMode", PropertyBinder.instance(ChargeMode.class, "chargeMode")); binder.registerBinder("enabled", PropertyBinder.instance(Boolean.TYPE, "enabled")); binder.registerBinder("enabledSince", PropertyBinder.instance(Calendar.class, "enabledSince", localSettings.getRawDateConverter())); binder.registerBinder("runMode", PropertyBinder.instance(RunMode.class, "runMode")); binder.registerBinder("recurrence", DataBinderHelper.timePeriodBinder("recurrence")); binder.registerBinder("day", PropertyBinder.instance(Byte.class, "day")); binder.registerBinder("hour", PropertyBinder.instance(Byte.class, "hour")); binder.registerBinder("invoiceMode", PropertyBinder.instance(InvoiceMode.class, "invoiceMode")); binder.registerBinder("amount", PropertyBinder.instance(BigDecimal.class, "amount", localSettings.getNumberConverter())); binder.registerBinder("freeBase", PropertyBinder.instance(BigDecimal.class, "freeBase", localSettings.getNumberConverter())); binder.registerBinder("transferType", PropertyBinder.instance(TransferType.class, "transferType", ReferenceConverter.instance(TransferType.class))); binder.registerBinder("groups", SimpleCollectionBinder.instance(Group.class, "groups")); dataBinder = binder; } return dataBinder; } finally { lock.readLock().unlock(); } } public TransferTypeService getTransferTypeService() { return transferTypeService; } @Override public void onLocalSettingsUpdate(final LocalSettingsEvent event) { try { lock.writeLock().lock(); dataBinder = null; } finally { lock.writeLock().unlock(); } } @Inject public void setAccountFeeService(final AccountFeeService accountFeeService) { this.accountFeeService = accountFeeService; } @Inject public void setAccountTypeService(final AccountTypeService accountTypeService) { this.accountTypeService = accountTypeService; } @Inject public void setTransferTypeService(final TransferTypeService transferTypeService) { this.transferTypeService = transferTypeService; } @Override protected ActionForward handleSubmit(final ActionContext context) throws Exception { final EditAccountFeeForm form = context.getForm(); AccountFee accountFee = getDataBinder().readFromString(form.getAccountFee()); final boolean isInsert = accountFee.getId() == null; accountFee = accountFeeService.save(accountFee); context.sendMessage(isInsert ? "accountFee.inserted" : "accountFee.modified"); final Map<String, Object> params = new HashMap<String, Object>(); params.put("accountTypeId", form.getAccountTypeId()); params.put("accountFeeId", accountFee.getId()); return ActionHelper.redirectWithParams(context.getRequest(), context.getSuccessForward(), params); } @SuppressWarnings("unchecked") @Override protected void prepareForm(final ActionContext context) throws Exception { final HttpServletRequest request = context.getRequest(); final EditAccountFeeForm form = context.getForm(); final long accountTypeId = form.getAccountTypeId(); MemberAccountType accountType; try { accountType = (MemberAccountType) accountTypeService.load(accountTypeId); } catch (final Exception e) { throw new ValidationException(); } final long id = form.getAccountFeeId(); final boolean isInsert = id <= 0L; AccountFee accountFee; boolean alreadyRan; if (isInsert) { accountFee = new AccountFee(); alreadyRan = false; } else { accountFee = accountFeeService.load(id, AccountFee.Relationships.GROUPS, AccountFee.Relationships.TRANSFER_TYPE); final List<TransferType> transferTypes = transferTypeService.getPosibleTTsForAccountFee(accountType, accountFee.getPaymentDirection()); request.setAttribute("transferTypes", transferTypes); final AccountFeeLogQuery query = new AccountFeeLogQuery(); query.setPageForCount(); query.setAccountFee(accountFee); alreadyRan = PageHelper.hasResults(accountFeeService.searchLogs(query)); } getDataBinder().writeAsString(form.getAccountFee(), accountFee); final GroupQuery groupQuery = new GroupQuery(); groupQuery.setNatures(Group.Nature.MEMBER, Group.Nature.BROKER); groupQuery.setStatus(Group.Status.NORMAL); groupQuery.setMemberAccountType(accountType); final List<? extends MemberGroup> groups = (List<? extends MemberGroup>) groupService.search(groupQuery); request.setAttribute("accountFee", accountFee); request.setAttribute("isInsert", isInsert); request.setAttribute("alreadyRan", alreadyRan); request.setAttribute("accountType", accountType); request.setAttribute("groups", groups); request.setAttribute("recurrenceFields", Arrays.asList(TimePeriod.Field.MONTHS, TimePeriod.Field.WEEKS, TimePeriod.Field.DAYS)); RequestHelper.storeEnum(request, AccountFee.ChargeMode.class, "chargeModes"); RequestHelper.storeEnum(request, AccountFee.PaymentDirection.class, "paymentDirections"); RequestHelper.storeEnum(request, AccountFee.RunMode.class, "runModes"); RequestHelper.storeEnum(request, AccountFee.InvoiceMode.class, "invoiceModes"); RequestHelper.storeEnum(request, WeekDay.class, "weekDays"); } @Override protected void validateForm(final ActionContext context) { final EditAccountFeeForm form = context.getForm(); final AccountFee accountFee = getDataBinder().readFromString(form.getAccountFee()); accountFeeService.validate(accountFee); } }