nl.strohalm.cyclos.services.elements.CommissionServiceImpl.java Source code

Java tutorial

Introduction

Here is the source code for nl.strohalm.cyclos.services.elements.CommissionServiceImpl.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.services.elements;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;

import nl.strohalm.cyclos.access.AdminMemberPermission;
import nl.strohalm.cyclos.access.BrokerPermission;
import nl.strohalm.cyclos.dao.members.brokerings.BrokerCommissionContractDAO;
import nl.strohalm.cyclos.dao.members.brokerings.BrokeringCommissionStatusDAO;
import nl.strohalm.cyclos.dao.members.brokerings.DefaultBrokerCommissionDAO;
import nl.strohalm.cyclos.entities.Relationship;
import nl.strohalm.cyclos.entities.accounts.AccountType.Nature;
import nl.strohalm.cyclos.entities.accounts.fees.transaction.BrokerCommission;
import nl.strohalm.cyclos.entities.accounts.fees.transaction.TransactionFeeQuery;
import nl.strohalm.cyclos.entities.groups.BrokerGroup;
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.members.BrokeringQuery;
import nl.strohalm.cyclos.entities.members.Element;
import nl.strohalm.cyclos.entities.members.Member;
import nl.strohalm.cyclos.entities.members.brokerings.BrokerCommissionContract;
import nl.strohalm.cyclos.entities.members.brokerings.BrokerCommissionContract.Status;
import nl.strohalm.cyclos.entities.members.brokerings.BrokerCommissionContractQuery;
import nl.strohalm.cyclos.entities.members.brokerings.Brokering;
import nl.strohalm.cyclos.entities.members.brokerings.BrokeringCommissionStatus;
import nl.strohalm.cyclos.entities.members.brokerings.BrokeringCommissionStatusQuery;
import nl.strohalm.cyclos.entities.members.brokerings.DefaultBrokerCommission;
import nl.strohalm.cyclos.entities.members.brokerings.DefaultBrokerCommissionQuery;
import nl.strohalm.cyclos.entities.settings.LocalSettings;
import nl.strohalm.cyclos.services.InitializingService;
import nl.strohalm.cyclos.services.fetch.FetchServiceLocal;
import nl.strohalm.cyclos.services.groups.GroupServiceLocal;
import nl.strohalm.cyclos.services.permissions.PermissionServiceLocal;
import nl.strohalm.cyclos.services.settings.SettingsServiceLocal;
import nl.strohalm.cyclos.services.transactions.TransactionSummaryVO;
import nl.strohalm.cyclos.services.transfertypes.TransactionFeeServiceLocal;
import nl.strohalm.cyclos.utils.Amount;
import nl.strohalm.cyclos.utils.CacheCleaner;
import nl.strohalm.cyclos.utils.DataIteratorHelper;
import nl.strohalm.cyclos.utils.DateHelper;
import nl.strohalm.cyclos.utils.Period;
import nl.strohalm.cyclos.utils.TimePeriod;
import nl.strohalm.cyclos.utils.TimePeriod.Field;
import nl.strohalm.cyclos.utils.access.LoggedUser;
import nl.strohalm.cyclos.utils.notifications.MemberNotificationHandler;
import nl.strohalm.cyclos.utils.query.IteratorList;
import nl.strohalm.cyclos.utils.query.PageHelper;
import nl.strohalm.cyclos.utils.query.QueryParameters.ResultType;
import nl.strohalm.cyclos.utils.validation.GeneralValidation;
import nl.strohalm.cyclos.utils.validation.PropertyValidation;
import nl.strohalm.cyclos.utils.validation.ValidationError;
import nl.strohalm.cyclos.utils.validation.ValidationException;
import nl.strohalm.cyclos.utils.validation.Validator;

import org.apache.commons.collections.CollectionUtils;

/**
 * Implementation for commission service
 * @author Jefferson Magno
 */
public class CommissionServiceImpl implements CommissionServiceLocal, InitializingService {

    /**
     * Validates if there is an active or pending contract with conflicting period
     * @author Jefferson Magno
     */
    public class ConflictingContractValidation implements GeneralValidation {

        private static final long serialVersionUID = -2265778870845933590L;

        @Override
        public ValidationError validate(final Object object) {
            final BrokerCommissionContract brokerCommissionContract = (BrokerCommissionContract) object;
            if (brokerCommissionContractDao.isConflictingContract(brokerCommissionContract)) {
                return new ValidationError("brokerCommissionContract.error.conflictingContract");
            }
            return null;
        }
    }

    /**
     * Validates the default broker commission
     * @author Jefferson Magno
     */
    public class DefaultBrokerCommissionValidation implements GeneralValidation {

        private static final long serialVersionUID = -7493901526206665521L;

        @Override
        public ValidationError validate(final Object object) {
            final DefaultBrokerCommission defaultBrokerCommission = (DefaultBrokerCommission) object;

            if (defaultBrokerCommission.getBrokerCommission() != null) {
                final BrokerCommission brokerCommission = fetchService
                        .fetch(defaultBrokerCommission.getBrokerCommission());
                final Amount defaultAmount = defaultBrokerCommission.getAmount();
                final Amount.Type type = defaultAmount.getType();
                final BigDecimal defaultValue = defaultAmount.getValue();

                BigDecimal feeValue = null;
                if (type == Amount.Type.FIXED) {
                    feeValue = brokerCommission.getMaxFixedValue();
                } else {
                    feeValue = brokerCommission.getMaxPercentageValue();
                }
                if (defaultValue != null && feeValue != null && defaultValue.compareTo(feeValue) > 0) {
                    final LocalSettings localSettings = settingsService.getLocalSettings();
                    final String brokerCommissionName = brokerCommission.getName();
                    final Amount feeAmount = new Amount(feeValue, type);
                    final String formattedFeeAmount = localSettings.getAmountConverter().toString(feeAmount);
                    return new ValidationError("defaultBrokerCommission.error.maxValueExceeded",
                            brokerCommissionName, formattedFeeAmount);
                }
            }
            return null;
        }
    }

    /**
     * Validates if the status of the contract is pending before saving it
     * @author Jefferson Magno
     */
    public class StatusValidation implements PropertyValidation {

        private static final long serialVersionUID = 1390235157926363221L;

        @Override
        public ValidationError validate(final Object object, final Object property, final Object value) {
            final BrokerCommissionContract.Status status = (BrokerCommissionContract.Status) value;
            if (status != BrokerCommissionContract.Status.PENDING) {
                return new ValidationError("brokerCommissionContract.error.notPendingStatus");
            }
            return null;
        }
    }

    private PermissionServiceLocal permissionService;

    private BrokerCommissionContractDAO brokerCommissionContractDao;

    private BrokeringCommissionStatusDAO brokeringCommissionStatusDao;
    private BrokeringServiceLocal brokeringService;
    private DefaultBrokerCommissionDAO defaultBrokerCommissionDao;
    private FetchServiceLocal fetchService;
    private GroupServiceLocal groupService;
    private MemberServiceLocal memberService;
    private SettingsServiceLocal settingsService;
    private TransactionFeeServiceLocal transactionFeeService;
    private MemberNotificationHandler memberNotificationHandler;

    @Override
    public BrokerCommissionContract acceptBrokerCommissionContract(final Long brokerCommissionContractId) {
        BrokerCommissionContract brokerCommissionContract = loadBrokerCommissionContract(
                brokerCommissionContractId);
        final Period period = brokerCommissionContract.getPeriod();
        final boolean alreadyActive = period != null && period.includes(Calendar.getInstance());
        brokerCommissionContract.setStatus(alreadyActive ? Status.ACTIVE : Status.ACCEPTED);
        brokerCommissionContract = brokerCommissionContractDao.update(brokerCommissionContract);
        memberNotificationHandler.commissionContractAcceptedNotification(brokerCommissionContract);
        return brokerCommissionContract;
    }

    @Override
    public void activateAcceptedBrokerCommissionContracts(final Calendar time) {
        final Period today = Period.endingAt(DateHelper.truncate(time));

        // Activate accepted contracts that begin today
        final BrokerCommissionContractQuery query = new BrokerCommissionContractQuery();
        query.setResultType(ResultType.ITERATOR);
        query.setStatus(BrokerCommissionContract.Status.ACCEPTED);
        query.setStartPeriod(today);
        final List<BrokerCommissionContract> contractsToActivate = brokerCommissionContractDao.search(query);
        try {
            for (final BrokerCommissionContract contractToActivate : contractsToActivate) {
                contractToActivate.setStatus(BrokerCommissionContract.Status.ACTIVE);
                brokerCommissionContractDao.update(contractToActivate);
            }
        } finally {
            DataIteratorHelper.close(contractsToActivate);
        }
    }

    @Override
    public BrokerCommissionContract cancelBrokerCommissionContract(final Long brokerCommissionContractId) {
        final Element cancelledBy = LoggedUser.element();
        BrokerCommissionContract brokerCommissionContract = loadBrokerCommissionContract(
                brokerCommissionContractId);
        brokerCommissionContract.setStatus(Status.CANCELLED);
        brokerCommissionContract.setCancelledBy(cancelledBy);
        brokerCommissionContract = brokerCommissionContractDao.update(brokerCommissionContract);
        memberNotificationHandler.commissionContractCancelledNotification(brokerCommissionContract);
        return brokerCommissionContract;
    }

    @Override
    public BrokeringCommissionStatus closeBrokeringCommissionStatus(
            BrokeringCommissionStatus brokeringCommissionStatus) {
        brokeringCommissionStatus.getPeriod().setEnd(Calendar.getInstance());
        brokeringCommissionStatus = brokeringCommissionStatusDao.update(brokeringCommissionStatus);
        return brokeringCommissionStatus;
    }

    @Override
    @SuppressWarnings("unchecked")
    public void createBrokeringCommissionStatus(final BrokerCommission brokerCommission) {
        Collection<BrokerGroup> brokerGroups = null;
        if (brokerCommission.isAllBrokerGroups()) {
            final GroupQuery query = new GroupQuery();
            query.setNature(Group.Nature.BROKER);
            query.setStatus(Group.Status.NORMAL);
            query.setOnlyActive(true);
            brokerGroups = (Collection<BrokerGroup>) groupService.search(query);
        } else {
            brokerGroups = fetchService.fetch(brokerCommission.getBrokerGroups());
        }
        for (final BrokerGroup brokerGroup : brokerGroups) {
            createBrokeringCommissionStatus(brokerGroup, brokerCommission);
        }
    }

    @Override
    public BrokeringCommissionStatus createBrokeringCommissionStatus(final Brokering brokering,
            final BrokerCommission brokerCommission) {
        // Create new instance
        final BrokeringCommissionStatus brokeringCommissionStatus = new BrokeringCommissionStatus();
        brokeringCommissionStatus.setBrokering(brokering);
        brokeringCommissionStatus.setBrokerCommission(brokerCommission);
        brokeringCommissionStatus.setCreationDate(Calendar.getInstance());
        boolean fillFromCommission = true;

        if (brokerCommission.isFromMember()) {
            // Get the data from the default broker commission
            final DefaultBrokerCommission defaultBrokerCommission = getDefaultBrokerCommission(
                    brokering.getBroker(), brokerCommission);
            if (defaultBrokerCommission != null) {
                brokeringCommissionStatus.setAmount(defaultBrokerCommission.getAmount());
                brokeringCommissionStatus.setWhen(defaultBrokerCommission.getWhen());
                brokeringCommissionStatus.setMaxCount(defaultBrokerCommission.getCount());
                fillFromCommission = false;
            }
        }
        if (fillFromCommission) {
            // Get the data from the broker commission
            brokeringCommissionStatus.setAmount(brokerCommission.getAmount());
            brokeringCommissionStatus.setWhen(brokerCommission.getWhen());
            brokeringCommissionStatus.setMaxCount(brokerCommission.getCount());
        }

        // Set total
        final TransactionSummaryVO total = new TransactionSummaryVO();
        total.setCount(0);
        total.setAmount(new BigDecimal(0));
        brokeringCommissionStatus.setTotal(total);

        // Period
        final Period period = new Period();
        period.setBegin(brokering.getStartDate());

        // If the commission has a validity (number of days), set expiration date on the commission status and check if it is not expired
        if (brokeringCommissionStatus.getWhen() == BrokerCommission.When.DAYS) {

            // Calculate and set expiration date
            final Calendar brokeringStartDate = brokering.getStartDate();
            final int daysCount = brokeringCommissionStatus.getMaxCount();
            final Calendar expirationDate = new TimePeriod(daysCount, Field.DAYS).add(brokeringStartDate);
            brokeringCommissionStatus.setExpiryDate(expirationDate);

            // Check if the brokering commission status is expired
            final Calendar now = Calendar.getInstance();
            if (now.compareTo(expirationDate) >= 0) {
                period.setEnd(expirationDate);
            }
        }

        // Set period
        brokeringCommissionStatus.setPeriod(period);

        return brokeringCommissionStatusDao.insert(brokeringCommissionStatus);
    }

    @Override
    @SuppressWarnings("unchecked")
    public void createDefaultBrokerCommissions(final BrokerCommission brokerCommission) {
        Collection<BrokerGroup> brokerGroups = null;
        if (brokerCommission.isAllBrokerGroups()) {
            final GroupQuery query = new GroupQuery();
            query.setNature(Group.Nature.BROKER);
            query.setStatus(Group.Status.NORMAL);
            query.setOnlyActive(true);
            brokerGroups = (Collection<BrokerGroup>) groupService.search(query);
        } else {
            brokerGroups = fetchService.fetch(brokerCommission.getBrokerGroups());
        }
        for (final BrokerGroup brokerGroup : brokerGroups) {
            createDefaultBrokerCommissions(brokerCommission, brokerGroup);
        }
    }

    @Override
    public BrokerCommissionContract denyBrokerCommissionContract(final Long brokerCommissionContractId) {
        BrokerCommissionContract brokerCommissionContract = loadBrokerCommissionContract(
                brokerCommissionContractId);
        brokerCommissionContract.setStatus(Status.DENIED);
        brokerCommissionContract = brokerCommissionContractDao.update(brokerCommissionContract);
        memberNotificationHandler.commissionContractDeniedNotification(brokerCommissionContract);
        return brokerCommissionContract;
    }

    @Override
    public void expireBrokerCommissionContracts(final Calendar time) {
        final Period endOfYesterday = Period.endingAt(DateHelper.truncatePreviosDay(time));

        // Close contracts that expired at the end of yesterday
        BrokerCommissionContractQuery query = new BrokerCommissionContractQuery();
        query.setResultType(ResultType.ITERATOR);
        query.setStatus(BrokerCommissionContract.Status.ACTIVE);
        query.setEndPeriod(endOfYesterday);
        final List<BrokerCommissionContract> contractsToClose = brokerCommissionContractDao.search(query);
        try {
            for (final BrokerCommissionContract contractToClose : contractsToClose) {
                contractToClose.setStatus(BrokerCommissionContract.Status.CLOSED);
                brokerCommissionContractDao.update(contractToClose);
            }
        } finally {
            DataIteratorHelper.close(contractsToClose);
        }

        // Expire contracts that were not accepted until its beginning
        query = new BrokerCommissionContractQuery();
        query.setResultType(ResultType.ITERATOR);
        query.setStatus(BrokerCommissionContract.Status.PENDING);
        query.setStartPeriod(endOfYesterday);
        final List<BrokerCommissionContract> contractsToExpire = brokerCommissionContractDao.search(query);
        try {
            for (final BrokerCommissionContract contractToExpire : contractsToExpire) {
                contractToExpire.setStatus(BrokerCommissionContract.Status.EXPIRED);
                brokerCommissionContractDao.update(contractToExpire);
            }
        } finally {
            DataIteratorHelper.close(contractsToExpire);
        }
    }

    @Override
    public void expireBrokeringCommissionStatus(final Calendar date) {
        brokeringCommissionStatusDao.expireBrokeringCommissionStatus(date);
    }

    @Override
    public BrokerCommissionContract getActiveBrokerCommissionContract(final Brokering brokering,
            final BrokerCommission brokerCommission) {
        final BrokerCommissionContractQuery query = new BrokerCommissionContractQuery();
        query.setBroker(brokering.getBroker());
        query.setMember(brokering.getBrokered());
        query.setBrokerCommission(brokerCommission);
        query.setStatus(Status.ACTIVE);
        query.setUniqueResult();
        final List<BrokerCommissionContract> contracts = brokerCommissionContractDao.search(query);
        if (CollectionUtils.isEmpty(contracts)) {
            return null;
        } else {
            return contracts.iterator().next();
        }
    }

    @Override
    public BrokeringCommissionStatus getBrokeringCommissionStatus(final Brokering brokering,
            final BrokerCommission brokerCommission) {
        return brokeringCommissionStatusDao.load(brokering, brokerCommission);
    }

    @Override
    @SuppressWarnings("unchecked")
    public List<CommissionChargeStatusDTO> getCommissionChargeStatus(final Member member) {
        final List<CommissionChargeStatusDTO> commissionChargeStatusList = new ArrayList<CommissionChargeStatusDTO>();

        final Brokering brokering = brokeringService.getActiveBrokering(member);

        if (brokering != null) {
            final Member broker = fetchService.fetch(brokering.getBroker(), Element.Relationships.GROUP);

            // Get broker commission transaction fees related to the member group and to the broker group
            final TransactionFeeQuery transactionFeeQuery = new TransactionFeeQuery();
            transactionFeeQuery.setGeneratedTransferTypeFromNature(Nature.MEMBER);
            transactionFeeQuery.setEntityType(BrokerCommission.class);
            transactionFeeQuery.setBrokerGroup((BrokerGroup) broker.getGroup());
            transactionFeeQuery.setMemberGroup((MemberGroup) member.getGroup());
            final List<BrokerCommission> brokerCommissions = (List<BrokerCommission>) transactionFeeService
                    .search(transactionFeeQuery);

            // For each broker commission get the commission charge status dto
            for (final BrokerCommission brokerCommission : brokerCommissions) {
                final CommissionChargeStatusDTO commissionChargeStatusDto = new CommissionChargeStatusDTO();
                commissionChargeStatusDto.setBrokerCommission(brokerCommission);
                final BrokerCommissionContract contract = getBrokerCommissionContract(member, broker,
                        brokerCommission);
                if (contract != null) {
                    commissionChargeStatusDto.setBrokerCommissionContract(contract);
                    commissionChargeStatusDto.setChargeStatus(CommissionChargeStatusDTO.ChargeStatus.CONTRACT);
                } else {
                    final BrokeringCommissionStatus status = getBrokeringCommissionStatus(brokering,
                            brokerCommission);
                    final DefaultBrokerCommission defaultBrokerCommission = getDefaultBrokerCommission(broker,
                            brokerCommission);
                    if (defaultBrokerCommission != null && status.getPeriod().getEnd() == null) {
                        commissionChargeStatusDto.setBrokeringCommissionStatus(status);
                        commissionChargeStatusDto
                                .setChargeStatus(CommissionChargeStatusDTO.ChargeStatus.DEFAULT_COMMISSION);
                    } else {
                        commissionChargeStatusDto.setChargeStatus(CommissionChargeStatusDTO.ChargeStatus.NONE);
                    }
                }
                commissionChargeStatusList.add(commissionChargeStatusDto);
            }
        }
        return commissionChargeStatusList;
    }

    @Override
    public DefaultBrokerCommission getDefaultBrokerCommission(final Member broker,
            final BrokerCommission brokerCommission) {
        final DefaultBrokerCommissionQuery query = new DefaultBrokerCommissionQuery();
        query.setBroker(broker);
        query.setBrokerCommission(brokerCommission);
        query.setUniqueResult();
        final List<DefaultBrokerCommission> defaultBrokerCommissions = defaultBrokerCommissionDao.search(query);
        if (CollectionUtils.isEmpty(defaultBrokerCommissions)) {
            return null;
        } else {
            return defaultBrokerCommissions.iterator().next();
        }
    }

    @Override
    public BrokeringCommissionStatus getOrUpdateBrokeringCommissionStatus(final Brokering brokering,
            final BrokerCommission brokerCommission) {
        return getOrUpdateBrokeringCommissionStatus(brokering, brokerCommission, brokerCommission.getAmount(),
                brokerCommission.getWhen(), brokerCommission.getCount());
    }

    @Override
    public boolean hasAllPermissions() {
        return permissionService.permission().admin(AdminMemberPermission.BROKERINGS_MANAGE_COMMISSIONS)
                .broker(BrokerPermission.MEMBERS_MANAGE_CONTRACTS).member().hasPermission();
    }

    @Override
    public boolean hasBrokerCommissionContracts() {
        if (!hasAllPermissions()) {
            return false;
        }
        final BrokerCommissionContractQuery commissionQuery = new BrokerCommissionContractQuery();
        commissionQuery.setPageForCount();
        commissionQuery.setMember(LoggedUser.member());
        return PageHelper.hasResults(brokerCommissionContractDao.search(commissionQuery));
    }

    @Override
    public void initializeService() {
        Calendar now = Calendar.getInstance();
        activateAcceptedBrokerCommissionContracts(now);
        expireBrokerCommissionContracts(now);
        expireBrokeringCommissionStatus(now);
    }

    @Override
    public List<BrokerCommission> listPossibleCommissionsForNewContract(Member brokered) {
        brokered = fetchService.fetch(brokered, Element.Relationships.GROUP);
        final BrokerGroup brokerGroup = LoggedUser.group();
        final MemberGroup memberGroup = brokered.getMemberGroup();

        // Get broker commission transaction fees related to the broker group
        final TransactionFeeQuery transactionFeeQuery = new TransactionFeeQuery();
        transactionFeeQuery.setGeneratedTransferTypeFromNature(Nature.MEMBER);
        transactionFeeQuery.setEntityType(BrokerCommission.class);
        transactionFeeQuery.setBrokerGroup(brokerGroup);
        transactionFeeQuery.setMemberGroup(memberGroup);

        @SuppressWarnings("unchecked")
        final List<BrokerCommission> brokerCommissions = new ArrayList<BrokerCommission>(
                (List<BrokerCommission>) transactionFeeService.search(transactionFeeQuery));

        // Get the existing contracts
        BrokerCommissionContractQuery query = new BrokerCommissionContractQuery();
        query.setBroker(LoggedUser.member());
        query.setMember(brokered);
        query.setStatusList(Arrays.asList(BrokerCommissionContract.Status.ACCEPTED,
                BrokerCommissionContract.Status.ACTIVE, BrokerCommissionContract.Status.PENDING));
        List<BrokerCommissionContract> contracts = searchBrokerCommissionContracts(query);

        // Filter out the commissions
        for (Iterator<BrokerCommission> it = brokerCommissions.iterator(); it.hasNext();) {
            BrokerCommission brokerCommission = it.next();
            // Commissions already used by existing contracts are not returned
            for (BrokerCommissionContract contract : contracts) {
                if (contract.getBrokerCommission().equals(brokerCommission)) {
                    it.remove();
                    break;
                }
            }
        }

        return brokerCommissions;
    }

    @Override
    public BrokerCommissionContract loadBrokerCommissionContract(final Long id, final Relationship... fetch) {
        return brokerCommissionContractDao.load(id, fetch);
    }

    public BrokeringCommissionStatus loadBrokeringCommissionStatus(final Long id, final Relationship... fetch) {
        return brokeringCommissionStatusDao.load(id, fetch);
    }

    @Override
    public List<DefaultBrokerCommission> loadDefaultBrokerCommissions(final Member broker,
            final Relationship... fetch) {
        return defaultBrokerCommissionDao.load(broker, fetch);
    }

    @Override
    public int removeBrokerCommissionContracts(final Long... ids) {
        return brokerCommissionContractDao.delete(ids);
    }

    @Override
    public BrokerCommissionContract saveBrokerCommissionContract(
            BrokerCommissionContract brokerCommissionContract) {
        validateBrokerCommissionContract(brokerCommissionContract);
        if (brokerCommissionContract.isTransient()) {
            brokerCommissionContract = brokerCommissionContractDao.insert(brokerCommissionContract);
            memberNotificationHandler.newCommissionContractNotification(brokerCommissionContract);
            return brokerCommissionContract;
        } else {
            return brokerCommissionContractDao.update(brokerCommissionContract);
        }
    }

    @Override
    public List<DefaultBrokerCommission> saveDefaultBrokerCommissions(
            final List<DefaultBrokerCommission> commissions) {
        final List<DefaultBrokerCommission> savedList = new ArrayList<DefaultBrokerCommission>();
        for (DefaultBrokerCommission defaultBrokerCommission : commissions) {
            // Skip suspended default broker commissions
            if (!defaultBrokerCommission.isSuspended()) {
                defaultBrokerCommission.setSetByBroker(true);
                defaultBrokerCommission = saveDefaultBrokerCommission(defaultBrokerCommission);
                savedList.add(defaultBrokerCommission);
            }
        }
        return savedList;
    }

    @Override
    public List<BrokerCommissionContract> searchBrokerCommissionContracts(
            final BrokerCommissionContractQuery query) {
        return brokerCommissionContractDao.search(query);
    }

    public void setBrokerCommissionContractDao(final BrokerCommissionContractDAO brokerCommissionContractDao) {
        this.brokerCommissionContractDao = brokerCommissionContractDao;
    }

    public void setBrokeringCommissionStatusDao(final BrokeringCommissionStatusDAO brokeringCommissionStatusDao) {
        this.brokeringCommissionStatusDao = brokeringCommissionStatusDao;
    }

    public void setBrokeringServiceLocal(final BrokeringServiceLocal brokeringService) {
        this.brokeringService = brokeringService;
    }

    public void setDefaultBrokerCommissionDao(final DefaultBrokerCommissionDAO defaultBrokerCommissionDao) {
        this.defaultBrokerCommissionDao = defaultBrokerCommissionDao;
    }

    public void setFetchServiceLocal(final FetchServiceLocal fetchService) {
        this.fetchService = fetchService;
    }

    public void setGroupServiceLocal(final GroupServiceLocal groupService) {
        this.groupService = groupService;
    }

    public void setMemberNotificationHandler(final MemberNotificationHandler memberNotificationHandler) {
        this.memberNotificationHandler = memberNotificationHandler;
    }

    public void setMemberServiceLocal(final MemberServiceLocal memberService) {
        this.memberService = memberService;
    }

    public void setPermissionServiceLocal(final PermissionServiceLocal permissionService) {
        this.permissionService = permissionService;
    }

    public void setSettingsServiceLocal(final SettingsServiceLocal settingsService) {
        this.settingsService = settingsService;
    }

    public void setTransactionFeeServiceLocal(final TransactionFeeServiceLocal transactionFeeService) {
        this.transactionFeeService = transactionFeeService;
    }

    public void stopCommissions(final BrokerCommission brokerCommission, final BrokerGroup brokerGroup) {
        CacheCleaner cacheCleaner = new CacheCleaner(fetchService);
        final IteratorList<Member> brokers = memberService.iterateByGroup(brokerGroup);
        try {
            for (final Member broker : brokers) {
                stopCommissions(brokerCommission, broker, true);
                cacheCleaner.clearCache();
            }
        } finally {
            DataIteratorHelper.close(brokers);
        }
    }

    @Override
    public void stopCommissions(BrokerCommission brokerCommission, final Member broker,
            final boolean removeDefaultBrokerCommission) {
        brokerCommission = fetchService.fetch(brokerCommission);
        if (brokerCommission.isFromMember()) {
            final DefaultBrokerCommission defaultBrokerCommission = getDefaultBrokerCommission(broker,
                    brokerCommission);

            if (defaultBrokerCommission != null) {
                if (removeDefaultBrokerCommission) {
                    // Remove default broker commission
                    defaultBrokerCommissionDao.delete(defaultBrokerCommission.getId());
                } else {
                    // Set default broker commission value to 0
                    final Amount zeroAmount = new Amount();
                    zeroAmount.setType(defaultBrokerCommission.getAmount().getType());
                    zeroAmount.setValue(new BigDecimal(0));
                    defaultBrokerCommission.setAmount(zeroAmount);
                    defaultBrokerCommissionDao.update(defaultBrokerCommission);
                }
            }

            // Close broker commission contracts
            closeBrokerCommissionContracts(broker, brokerCommission);
        }

        // Close brokering commission status
        closeBrokeringCommissionStatus(broker, brokerCommission);
    }

    @Override
    public void suspendCommissions(BrokerCommission brokerCommission, final Member broker) {
        brokerCommission = fetchService.fetch(brokerCommission);
        if (brokerCommission.isFromMember()) {
            final DefaultBrokerCommission defaultBrokerCommission = getDefaultBrokerCommission(broker,
                    brokerCommission);

            // Suspend default broker commission
            if (defaultBrokerCommission != null) {
                defaultBrokerCommission.setSuspended(true);
                defaultBrokerCommissionDao.update(defaultBrokerCommission);
            }

            // Suspend broker commission contracts
            suspendBrokerCommissionContracts(broker, brokerCommission);
        }
    }

    @Override
    public void unsuspendCommissions(BrokerCommission brokerCommission, final Member broker) {
        brokerCommission = fetchService.fetch(brokerCommission);
        if (brokerCommission.isFromMember()) {
            final DefaultBrokerCommission defaultBrokerCommission = getDefaultBrokerCommission(broker,
                    brokerCommission);

            // Unsuspend default broker commission
            if (defaultBrokerCommission != null) {
                defaultBrokerCommission.setSuspended(false);
                defaultBrokerCommissionDao.update(defaultBrokerCommission);
            }

            // Unsuspend broker commission contracts
            unsuspendBrokerCommissionContracts(broker, brokerCommission);
        }
    }

    @Override
    @SuppressWarnings("unchecked")
    public void updateBrokerCommissions(final Member broker, final MemberGroup oldGroup,
            final MemberGroup newGroup) {
        List<BrokerCommission> oldBrokerCommissions = new ArrayList<BrokerCommission>();
        List<BrokerCommission> newBrokerCommissions = new ArrayList<BrokerCommission>();

        if (oldGroup instanceof BrokerGroup) {
            final BrokerGroup oldBrokerGroup = (BrokerGroup) oldGroup;
            final TransactionFeeQuery query = new TransactionFeeQuery();
            query.setEntityType(BrokerCommission.class);
            query.setBrokerGroup(oldBrokerGroup);
            query.setReturnDisabled(true);
            oldBrokerCommissions = (List<BrokerCommission>) transactionFeeService.search(query);
        }

        if (newGroup instanceof BrokerGroup) {
            final BrokerGroup newBrokerGroup = (BrokerGroup) newGroup;
            final TransactionFeeQuery query = new TransactionFeeQuery();
            query.setEntityType(BrokerCommission.class);
            query.setBrokerGroup(newBrokerGroup);
            query.setReturnDisabled(true);
            newBrokerCommissions = (List<BrokerCommission>) transactionFeeService.search(query);
        }

        // Stop charging commissions that are not applicable anymore and remove default broker commissions
        for (final BrokerCommission oldBrokerCommission : oldBrokerCommissions) {
            if (!newBrokerCommissions.contains(oldBrokerCommission)) {
                stopCommissions(oldBrokerCommission, broker, true);
            }
        }

        // Create commissions that now are applicable
        for (final BrokerCommission newBrokerCommission : newBrokerCommissions) {
            if (!oldBrokerCommissions.contains(newBrokerCommission)) {
                if (newBrokerCommission.isFromMember()) {
                    createDefaultBrokerCommission(newBrokerCommission, broker);
                }
                createBrokeringCommissionStatus(broker, newBrokerCommission);
            }
        }
    }

    @Override
    @SuppressWarnings("unchecked")
    public void updateBrokeringCommissionStatus(final BrokerCommission brokerCommission,
            final BrokerCommission savedBrokerCommission) {

        Collection<BrokerGroup> allBrokerGroups = null;
        if (brokerCommission.isAllBrokerGroups() || savedBrokerCommission.isAllBrokerGroups()) {
            final GroupQuery query = new GroupQuery();
            query.setNature(Group.Nature.BROKER);
            query.setStatus(Group.Status.NORMAL);
            query.setOnlyActive(true);
            allBrokerGroups = (Collection<BrokerGroup>) groupService.search(query);
        }

        Collection<BrokerGroup> brokerGroups = null;
        Collection<BrokerGroup> savedBrokerGroups = null;

        // Current groups of brokers
        if (brokerCommission.isAllBrokerGroups()) {
            brokerGroups = allBrokerGroups;
        } else {
            brokerGroups = fetchService.fetch(brokerCommission.getBrokerGroups());
        }

        // Previous groups of brokers
        if (savedBrokerCommission.isAllBrokerGroups()) {
            savedBrokerGroups = allBrokerGroups;
        } else {
            savedBrokerGroups = savedBrokerCommission.getBrokerGroups();
        }

        // Create brokering commission status for groups added to the commission
        for (final BrokerGroup brokerGroup : brokerGroups) {
            if (!savedBrokerGroups.contains(brokerGroup)) {
                createBrokeringCommissionStatus(brokerGroup, brokerCommission);
            } else {
                updateBrokeringCommissionStatus(brokerGroup, brokerCommission);
            }
        }

        // Stop commissions charging for groups removed from the commission
        for (final BrokerGroup savedBrokerGroup : savedBrokerGroups) {
            if (!brokerGroups.contains(savedBrokerGroup)) {
                stopCommissions(brokerCommission, savedBrokerGroup);
            }
        }
    }

    @Override
    public BrokeringCommissionStatus updateBrokeringCommissionStatus(
            final BrokeringCommissionStatus brokeringCommissionStatus) {
        return brokeringCommissionStatusDao.update(brokeringCommissionStatus);
    }

    @Override
    @SuppressWarnings("unchecked")
    public void updateDefaultBrokerCommissions(final BrokerCommission brokerCommission,
            final BrokerCommission savedBrokerCommission) {

        Collection<BrokerGroup> allBrokerGroups = null;
        if (brokerCommission.isAllBrokerGroups() || savedBrokerCommission.isAllBrokerGroups()) {
            final GroupQuery query = new GroupQuery();
            query.setNature(Group.Nature.BROKER);
            query.setStatus(Group.Status.NORMAL);
            query.setOnlyActive(true);
            allBrokerGroups = (Collection<BrokerGroup>) groupService.search(query);
        }

        Collection<BrokerGroup> brokerGroups = null;
        Collection<BrokerGroup> savedBrokerGroups = null;

        // Current groups of brokers
        if (brokerCommission.isAllBrokerGroups()) {
            brokerGroups = allBrokerGroups;
        } else {
            brokerGroups = fetchService.fetch(brokerCommission.getBrokerGroups());
        }

        // Previous groups of brokers
        if (savedBrokerCommission.isAllBrokerGroups()) {
            savedBrokerGroups = allBrokerGroups;
        } else {
            savedBrokerGroups = savedBrokerCommission.getBrokerGroups();
        }

        for (final BrokerGroup brokerGroup : brokerGroups) {
            if (!savedBrokerGroups.contains(brokerGroup)) {
                // Create default broker commissions for groups added to the commission
                createDefaultBrokerCommissions(brokerCommission, brokerGroup);
            } else {
                // If the broker commission was already applicable to the broker group, update default broker commissions that were not customized by
                // the broker and that had not been charged yet
                updateDefaultBrokerCommissions(brokerCommission, brokerGroup);
            }
        }

        // Stop commissions charging for groups removed from the commission
        for (final BrokerGroup savedBrokerGroup : savedBrokerGroups) {
            if (!brokerGroups.contains(savedBrokerGroup)) {
                stopCommissions(brokerCommission, savedBrokerGroup);
            }
        }
    }

    @Override
    public void validateBrokerCommissionContract(final BrokerCommissionContract brokerCommissionContract)
            throws ValidationException {
        getBrokerCommissionContractValidator().validate(brokerCommissionContract);
    }

    @Override
    public void validateDefaultBrokerCommissions(final List<DefaultBrokerCommission> defaultBrokerCommissions)
            throws ValidationException {
        final Validator defaultBrokerCommissionValidator = getDefaultBrokerCommissionValidator();
        for (final DefaultBrokerCommission defaultBrokerCommission : defaultBrokerCommissions) {
            defaultBrokerCommissionValidator.validate(defaultBrokerCommission);
        }
    }

    private void closeBrokerCommissionContracts(final Member broker, final BrokerCommission brokerCommission) {
        final List<BrokerCommissionContract.Status> statusList = new ArrayList<BrokerCommissionContract.Status>();
        statusList.add(BrokerCommissionContract.Status.PENDING);
        statusList.add(BrokerCommissionContract.Status.ACTIVE);

        final BrokerCommissionContractQuery query = new BrokerCommissionContractQuery();
        query.setBroker(broker);
        query.setBrokerCommission(brokerCommission);
        query.setStatusList(statusList);
        final List<BrokerCommissionContract> brokerCommissionContracts = brokerCommissionContractDao.search(query);
        for (final BrokerCommissionContract brokerCommissionContract : brokerCommissionContracts) {
            brokerCommissionContract.setStatus(BrokerCommissionContract.Status.CLOSED);
            brokerCommissionContractDao.update(brokerCommissionContract);
        }
    }

    private void closeBrokeringCommissionStatus(final Member broker, final BrokerCommission brokerCommission) {
        final Calendar now = Calendar.getInstance();
        final BrokeringCommissionStatusQuery query = new BrokeringCommissionStatusQuery();
        query.setBroker(broker);
        query.setBrokerCommission(brokerCommission);
        query.setOnlyActive(true);
        final List<BrokeringCommissionStatus> statusList = brokeringCommissionStatusDao.search(query);
        for (final BrokeringCommissionStatus status : statusList) {
            status.getPeriod().setEnd(now);
            brokeringCommissionStatusDao.update(status);
        }
    }

    private void createBrokeringCommissionStatus(final BrokerGroup brokerGroup,
            final BrokerCommission brokerCommission) {
        CacheCleaner cacheCleaner = new CacheCleaner(fetchService);
        final IteratorList<Member> brokers = memberService.iterateByGroup(brokerGroup);
        try {
            for (final Member broker : brokers) {
                createBrokeringCommissionStatus(broker, brokerCommission);
                cacheCleaner.clearCache();
            }
        } finally {
            DataIteratorHelper.close(brokers);
        }
    }

    private void createBrokeringCommissionStatus(final Member broker, final BrokerCommission brokerCommission) {
        final BrokeringQuery brokeringQuery = new BrokeringQuery();
        brokeringQuery.setBroker(broker);
        final List<Brokering> brokerings = brokeringService.search(brokeringQuery);
        for (final Brokering brokering : brokerings) {
            getOrUpdateBrokeringCommissionStatus(brokering, brokerCommission);
        }
    }

    private DefaultBrokerCommission createDefaultBrokerCommission(final BrokerCommission brokerCommission,
            final Member broker) {
        final DefaultBrokerCommission defaultBrokerCommission = new DefaultBrokerCommission();
        defaultBrokerCommission.setBroker(broker);
        defaultBrokerCommission.setBrokerCommission(brokerCommission);
        defaultBrokerCommission.setAmount(brokerCommission.getAmount());
        defaultBrokerCommission.setWhen(brokerCommission.getWhen());
        defaultBrokerCommission.setCount(brokerCommission.getCount());
        saveDefaultBrokerCommission(defaultBrokerCommission);
        return defaultBrokerCommission;
    }

    private void createDefaultBrokerCommissions(final BrokerCommission brokerCommission,
            final BrokerGroup brokerGroup) {
        CacheCleaner cacheCleaner = new CacheCleaner(fetchService);
        final IteratorList<Member> brokers = memberService.iterateByGroup(brokerGroup);
        try {
            for (final Member broker : brokers) {
                createDefaultBrokerCommission(brokerCommission, broker);
                cacheCleaner.clearCache();
            }
        } finally {
            DataIteratorHelper.close(brokers);
        }
    }

    private BrokerCommissionContract getBrokerCommissionContract(final Member member, final Member broker,
            final BrokerCommission brokerCommission) {
        // First, check if there is an active contract ...
        final BrokerCommissionContractQuery query = new BrokerCommissionContractQuery();
        query.setMember(member);
        query.setBroker(broker);
        query.setBrokerCommission(brokerCommission);
        query.setStatus(BrokerCommissionContract.Status.ACTIVE);
        query.setUniqueResult();
        Collection<BrokerCommissionContract> contracts = searchBrokerCommissionContracts(query);
        if (CollectionUtils.isNotEmpty(contracts)) {
            return contracts.iterator().next();
        }

        // ... if there is not, check if there is a pending contract ...
        query.setStatus(BrokerCommissionContract.Status.PENDING);
        contracts = searchBrokerCommissionContracts(query);
        if (CollectionUtils.isNotEmpty(contracts)) {
            return contracts.iterator().next();
        }

        // ... else, return null
        return null;
    }

    private Validator getBrokerCommissionContractValidator() {
        final Validator brokerCommissionContractValidator = new Validator("brokerCommissionContract");
        brokerCommissionContractValidator.property("brokering").required();
        brokerCommissionContractValidator.property("brokerCommission").required();
        brokerCommissionContractValidator.property("period.begin").key("brokerCommissionContract.startDate")
                .required().futureOrToday();
        brokerCommissionContractValidator.property("amount.type").key("brokerCommissionContract.amount").required();
        brokerCommissionContractValidator.property("amount.value").key("brokerCommissionContract.amount")
                .required();
        brokerCommissionContractValidator.property("status").required().add(new StatusValidation());
        brokerCommissionContractValidator.general(new ConflictingContractValidation());
        return brokerCommissionContractValidator;
    }

    private Validator getDefaultBrokerCommissionValidator() {
        final Validator defaultBrokerCommissionValidator = new Validator("defaultBrokerCommission");
        defaultBrokerCommissionValidator.property("broker").required();
        defaultBrokerCommissionValidator.property("brokerCommission").required();
        defaultBrokerCommissionValidator.property("amount.type").key("transactionFee.amount").required();
        defaultBrokerCommissionValidator.property("amount.value").key("transactionFee.amount").required();
        defaultBrokerCommissionValidator.property("when").required();
        defaultBrokerCommissionValidator.general(new DefaultBrokerCommissionValidation());
        return defaultBrokerCommissionValidator;
    }

    private BrokeringCommissionStatus getOrUpdateBrokeringCommissionStatus(final Brokering brokering,
            final BrokerCommission brokerCommission, final Amount amount, final BrokerCommission.When when,
            final Integer count) {
        BrokeringCommissionStatus brokeringCommissionStatus = getBrokeringCommissionStatus(brokering,
                brokerCommission);
        if (brokeringCommissionStatus == null) {
            brokeringCommissionStatus = createBrokeringCommissionStatus(brokering, brokerCommission);
        } else {
            // If the commission had not been charged yet and the brokering commission status is not closed, the brokering commission status can be
            // updated
            if (brokeringCommissionStatus.getTotal().getCount() == 0
                    && brokeringCommissionStatus.getPeriod().getEnd() == null) {
                brokeringCommissionStatus.setAmount(amount);
                brokeringCommissionStatus.setWhen(when);
                brokeringCommissionStatus.setMaxCount(count);
                brokeringCommissionStatus = brokeringCommissionStatusDao.update(brokeringCommissionStatus);
            }
        }
        return brokeringCommissionStatus;
    }

    /**
     * Saves the default broker commission, returning the updated instance
     */
    private DefaultBrokerCommission saveDefaultBrokerCommission(DefaultBrokerCommission defaultBrokerCommission) {
        if (defaultBrokerCommission.getWhen() == BrokerCommission.When.ALWAYS) {
            defaultBrokerCommission.setCount(null);
        }
        if (defaultBrokerCommission.isTransient()) {
            defaultBrokerCommission = defaultBrokerCommissionDao.insert(defaultBrokerCommission);
        } else {
            defaultBrokerCommission = defaultBrokerCommissionDao.update(defaultBrokerCommission);
        }
        updateBrokeringCommissionStatus(defaultBrokerCommission);
        return defaultBrokerCommission;
    }

    private void suspendBrokerCommissionContracts(final Member broker, final BrokerCommission brokerCommission) {
        final BrokerCommissionContractQuery query = new BrokerCommissionContractQuery();
        query.setBroker(broker);
        query.setBrokerCommission(brokerCommission);
        query.setStatusList(Arrays.asList(BrokerCommissionContract.Status.PENDING,
                BrokerCommissionContract.Status.ACCEPTED, BrokerCommissionContract.Status.ACTIVE));
        final List<BrokerCommissionContract> brokerCommissionContracts = brokerCommissionContractDao.search(query);
        for (final BrokerCommissionContract brokerCommissionContract : brokerCommissionContracts) {
            brokerCommissionContract.setStatusBeforeSuspension(brokerCommissionContract.getStatus());
            brokerCommissionContract.setStatus(BrokerCommissionContract.Status.SUSPENDED);
            brokerCommissionContractDao.update(brokerCommissionContract);
        }
    }

    private void unsuspendBrokerCommissionContracts(final Member broker, final BrokerCommission brokerCommission) {
        final Calendar today = DateHelper.truncate(Calendar.getInstance());
        final BrokerCommissionContractQuery query = new BrokerCommissionContractQuery();
        query.setBroker(broker);
        query.setBrokerCommission(brokerCommission);
        query.setStatus(BrokerCommissionContract.Status.SUSPENDED);
        final List<BrokerCommissionContract> brokerCommissionContracts = brokerCommissionContractDao.search(query);
        for (final BrokerCommissionContract brokerCommissionContract : brokerCommissionContracts) {
            final BrokerCommissionContract.Status statusBeforeSuspension = brokerCommissionContract
                    .getStatusBeforeSuspension();
            final Calendar beginOfContract = brokerCommissionContract.getPeriod().getBegin();
            final Calendar endOfContract = brokerCommissionContract.getPeriod().getEnd();
            if (statusBeforeSuspension == BrokerCommissionContract.Status.ACTIVE) {
                // If the contract is expired (ends before the beginning of today), close it
                if (endOfContract.compareTo(today) < 0) {
                    brokerCommissionContract.setStatus(BrokerCommissionContract.Status.CLOSED);
                } else {
                    brokerCommissionContract.setStatus(BrokerCommissionContract.Status.ACTIVE);
                }
            } else if (statusBeforeSuspension == BrokerCommissionContract.Status.ACCEPTED) {
                // If the contract is expired (ends before the beginning of today), close it
                if (endOfContract.compareTo(today) < 0) {
                    brokerCommissionContract.setStatus(BrokerCommissionContract.Status.CLOSED);
                } else if (beginOfContract.compareTo(today) <= 0) {
                    // If the contract begins before today and it was already accepted, activate it
                    brokerCommissionContract.setStatus(BrokerCommissionContract.Status.ACTIVE);
                } else {
                    // The contract goes back to "ACCEPTED" status
                    brokerCommissionContract.setStatus(BrokerCommissionContract.Status.ACCEPTED);
                }
            } else {
                // If the contract begins before today and was not accepted yet, expire it
                if (beginOfContract.compareTo(today) <= 0) {
                    brokerCommissionContract.setStatus(BrokerCommissionContract.Status.EXPIRED);
                } else {
                    brokerCommissionContract.setStatus(BrokerCommissionContract.Status.PENDING);
                }
            }
            brokerCommissionContract.setStatusBeforeSuspension(null);
            brokerCommissionContractDao.update(brokerCommissionContract);
        }
    }

    private void updateBrokeringCommissionStatus(final BrokerGroup brokerGroup,
            final BrokerCommission brokerCommission) {
        CacheCleaner cacheCleaner = new CacheCleaner(fetchService);
        final IteratorList<Member> brokers = memberService.iterateByGroup(brokerGroup);
        try {
            for (final Member broker : brokers) {
                updateBrokeringCommissionStatus(broker, brokerCommission);
                cacheCleaner.clearCache();
            }
        } finally {
            DataIteratorHelper.close(brokers);
        }
    }

    /*
     * Create a new brokering commission status (for each brokering) if it does not exist and update the existing ones
     */
    private void updateBrokeringCommissionStatus(final DefaultBrokerCommission defaultBrokerCommission) {
        final Member broker = defaultBrokerCommission.getBroker();
        final BrokerCommission brokerCommission = defaultBrokerCommission.getBrokerCommission();

        final BrokeringQuery brokeringQuery = new BrokeringQuery();
        brokeringQuery.setBroker(broker);
        final List<Brokering> brokerings = brokeringService.search(brokeringQuery);
        for (final Brokering brokering : brokerings) {
            getOrUpdateBrokeringCommissionStatus(brokering, brokerCommission, defaultBrokerCommission.getAmount(),
                    defaultBrokerCommission.getWhen(), defaultBrokerCommission.getCount());
        }
    }

    private void updateBrokeringCommissionStatus(final Member broker, final BrokerCommission brokerCommission) {
        final BrokeringQuery brokeringQuery = new BrokeringQuery();
        brokeringQuery.setBroker(broker);
        final List<Brokering> brokerings = brokeringService.search(brokeringQuery);
        for (final Brokering brokering : brokerings) {
            getOrUpdateBrokeringCommissionStatus(brokering, brokerCommission);
        }
    }

    private void updateDefaultBrokerCommission(final BrokerCommission brokerCommission, final Member broker) {
        DefaultBrokerCommission defaultBrokerCommission = getDefaultBrokerCommission(broker, brokerCommission);
        if (defaultBrokerCommission == null) {
            defaultBrokerCommission = createDefaultBrokerCommission(brokerCommission, broker);
        }
        if (!defaultBrokerCommission.isSetByBroker()) {
            final BrokeringCommissionStatusQuery query = new BrokeringCommissionStatusQuery();
            query.setBroker(broker);
            query.setBrokerCommission(brokerCommission);
            final List<BrokeringCommissionStatus> statusList = brokeringCommissionStatusDao.search(query);
            boolean canUpdate = true;
            for (final BrokeringCommissionStatus status : statusList) {
                if (status.getTotal().getAmount().compareTo(new BigDecimal(0)) > 0) {
                    canUpdate = false;
                    break;
                }
            }
            if (canUpdate) {
                defaultBrokerCommission.setAmount(brokerCommission.getAmount());
                defaultBrokerCommissionDao.update(defaultBrokerCommission);
                updateBrokeringCommissionStatus(defaultBrokerCommission);
            }
        }
    }

    private void updateDefaultBrokerCommissions(final BrokerCommission brokerCommission,
            final BrokerGroup brokerGroup) {
        CacheCleaner cacheCleaner = new CacheCleaner(fetchService);
        final IteratorList<Member> brokers = memberService.iterateByGroup(brokerGroup);
        try {
            for (final Member broker : brokers) {
                updateDefaultBrokerCommission(brokerCommission, broker);
                cacheCleaner.clearCache();
            }
        } finally {
            DataIteratorHelper.close(brokers);
        }
    }

}