FECRequestRepositoryImpl.java

package com.tradecloud.repository.impl;

import com.tradecloud.domain.base.utils.DateUtils;
import com.tradecloud.domain.infrastructure.persistence.CriteriaBuilder;
import com.tradecloud.domain.model.BuySellIndicator;
import com.tradecloud.domain.model.ForexGroup;
import com.tradecloud.domain.model.deal.BuySellDealType;
import com.tradecloud.domain.model.fecrequest.FECRequest;
import com.tradecloud.domain.model.fecrequest.FECRequestStatusType;
import com.tradecloud.domain.model.organisationalunit.OrganisationalUnit;
import com.tradecloud.dto.treasury.DefaultDTO;
import com.tradecloud.dto.treasury.FECRequestSearchDTO;
import com.tradecloud.repository.FECRequestRepository;
import com.tradecloud.repository.GeneralRepository;
import com.tradecloud.repository.base.impl.RepositoryBaseImpl;
import org.hibernate.Criteria;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Property;
import org.hibernate.criterion.Restrictions;
import org.joda.time.LocalDate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Currency;
import java.util.List;

@Repository(value = "fecRequestRepository")
@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT)
public class FECRequestRepositoryImpl extends RepositoryBaseImpl<FECRequest, Object> implements FECRequestRepository {

    @Autowired
    private GeneralRepository generalRepository;

    @Override
    public void store(FECRequest fecRequest) {
        saveOrUpdate(fecRequest);
        flush();
    }

    @Override
    public List<FECRequest> findAll() {
        return getBaseCriteria().list();
    }

    @Override
    public FECRequest find(long fecRequestReference) {
        Criteria criteria = getBaseCriteria();
        criteria.add(Restrictions.eq("id", fecRequestReference));
        return (FECRequest) criteria.uniqueResult();
    }

    private Criteria getBaseCriteria() {
        Criteria criteria = getSessionCustom().createCriteria(FECRequest.class);
        criteria.add(Restrictions.or(Restrictions.eq("status", FECRequestStatusType.AUTHORISED),
                Restrictions.eq("status", FECRequestStatusType.REQUESTED)));
        return criteria;
    }

    private DetachedCriteria getDetachedCriteria(FECRequestStatusType status, LocalDate startMaturityDate, LocalDate endMaturityDate,
                                                 Currency currency, BuySellIndicator buySellIndicator, OrganisationalUnit organisationalUnit,
                                                 ForexGroup forexGroup) {
        DetachedCriteria criteria = DetachedCriteria.forClass(FECRequest.class);
        if (currency != null) {
            criteria.add(Restrictions.eq("amount.currency", currency));
        }
        if (organisationalUnit != null) {
            criteria.add(Restrictions.eq("organisationalUnit", organisationalUnit));
        }
        if (forexGroup != null) {
            criteria.add(Restrictions.eq("forexGroup", forexGroup));
        }
        CriteriaBuilder.addDateRangeCriteria(criteria, "maturityDate", startMaturityDate, endMaturityDate);
        if (status != null) {
            criteria.add(Restrictions.eq("status", status));
        }
        if (buySellIndicator != null) {
            if (buySellIndicator.equals(BuySellIndicator.BUY)) {
                criteria.add(Restrictions.ge("amount.value", BigDecimal.ZERO));
            } else {
                criteria.add(Restrictions.lt("amount.value", BigDecimal.ZERO));
            }
        }

        criteria.add(Restrictions.or(Restrictions.eq("status", FECRequestStatusType.AUTHORISED),
                Restrictions.eq("status", FECRequestStatusType.REQUESTED)));

        return criteria;
    }

    @Override
    public long count(FECRequestSearchDTO search) {
        DetachedCriteria detachedCriteria = getCriteria(search);
        return getExecutableCriteriaCount(detachedCriteria);
    }

    private DetachedCriteria getCriteria(FECRequestSearchDTO search) {
        LocalDate maturityDateFrom = DateUtils.toLocalDate(search.getMaturityDate().getFrom());
        LocalDate maturityDateTo = DateUtils.toLocalDate(search.getMaturityDate().getTo());
        Currency currency = search.getCurrency() != null ? Currency.getInstance(search.getCurrency().getCode()) : null;
        BuySellIndicator indicator = null;
        if (search.getBuySellDealType() != null) {
            indicator = search.getBuySellDealType() == BuySellDealType.BUY ? BuySellIndicator.BUY : BuySellIndicator.SELL;
        }
        DefaultDTO organisationalUnit1 = search.getOrganisationalUnit();
        OrganisationalUnit organisationalUnit = organisationalUnit1 != null ?
                generalRepository.retrieve(OrganisationalUnit.class, organisationalUnit1.getId()) : null;
        DefaultDTO forexGroup1 = search.getForexGroup();
        ForexGroup forexGroup = forexGroup1 != null ? generalRepository.retrieve(ForexGroup.class, forexGroup1.getId()) : null;
        return getDetachedCriteria(search.getStatus(), maturityDateFrom, maturityDateTo, currency, indicator, organisationalUnit,
                forexGroup);
    }

    @Override
    public List<FECRequest> search(FECRequestSearchDTO search) {
        DetachedCriteria detachedCriteria = getCriteria(search);
        if (search.getFecRequestSortBy() != null) {
            detachedCriteria.addOrder(Property.forName(search.getFecRequestSortBy().getPropertyName()).asc());
            //This will resolve paging issue when two records have the same sortBy date.
            detachedCriteria.addOrder(Property.forName("created").asc());
        }
        return getExecutableCriteriaList(detachedCriteria, search.getSearchMetaParams());
    }
}