CartonItemRepositoryImpl.java

package com.tradecloud.repository.export.carton.impl;

import com.tradecloud.domain.base.utils.DateUtils;
import com.tradecloud.domain.document.invoice.ActualConsignment;
import com.tradecloud.domain.document.invoice.ActualLineItem;
import com.tradecloud.domain.document.invoice.ActualOrder;
import com.tradecloud.domain.document.invoice.CostsInvoice;
import com.tradecloud.domain.export.ExportInvoice;
import com.tradecloud.dto.order.ActualLineItemSearch;
import com.tradecloud.repository.SearchMetaParams;
import com.tradecloud.repository.base.impl.RepositoryBaseImpl;
import com.tradecloud.repository.export.carton.CartonItemRepository;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.hibernate.query.Query;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.*;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Repository(value = "cartonItemRepository")
@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT)
public class CartonItemRepositoryImpl extends RepositoryBaseImpl<ActualLineItem, ActualLineItemSearch> implements CartonItemRepository {

    @Override
    public List<ActualLineItem> search(ActualLineItemSearch itemSearch) {
        CriteriaBuilder builder = getSessionCustom().getCriteriaBuilder();
        CriteriaQuery criteria = builder.createQuery(ActualLineItem.class);
        Root root = criteria.from(ActualLineItem.class);
        root.fetch("exportCosting");

        criteria.select(root);
        buildPredicates(itemSearch, builder, criteria, root);
        SearchMetaParams metaParams = itemSearch.getSearchMetaParams();

        if (metaParams != null && metaParams.getOrderBy() != null) {
            if (metaParams.isAsc()) {
                criteria.orderBy(builder.asc(root.get(metaParams.getOrderBy())));
            } else {
                criteria.orderBy(builder.desc(root.get(metaParams.getOrderBy())));
            }
        } else {
            criteria.orderBy(builder.desc(root.get("created")));
        }
        Query query = getSessionCustom().createQuery(criteria);
        if (metaParams != null && metaParams.isPaged()) {
            query.setFirstResult(metaParams.getRowIndex());
            query.setMaxResults(metaParams.getRowCount());
        }
        List resultList = query.getResultList();
        return resultList;
    }

    @Override
    public long count(ActualLineItemSearch eventsSearch) {
        CriteriaBuilder builder = getSessionCustom().getCriteriaBuilder();
        CriteriaQuery criteria = builder.createQuery(Long.class);
        Root root = criteria.from(ActualLineItem.class);
        criteria.select(builder.count(root));
        buildPredicates(eventsSearch, builder, criteria, root);
        Query<Long> query = getSessionCustom().createQuery(criteria);
        return query.uniqueResult();
    }

    private void buildPredicates(ActualLineItemSearch itemSearch, CriteriaBuilder builder, CriteriaQuery criteria, Root root) {
        Join<ActualLineItem, ActualOrder> orderJoin = root.join("actualOrder", JoinType.LEFT);
        Join<ActualOrder, ActualConsignment> consignmentJoin = orderJoin.join("actualConsignment", JoinType.LEFT);
        Join<ActualConsignment, CostsInvoice> costsInvoiceJoin = consignmentJoin.join("costsInvoice", JoinType.LEFT);
        Join<ActualConsignment, ExportInvoice> exportInvoiceJoin = builder.treat(costsInvoiceJoin, ExportInvoice.class);

        List<Predicate> predicates = new ArrayList<>();
        predicates.add(builder.equal(costsInvoiceJoin.type(), ExportInvoice.class));

        if (StringUtils.isNotEmpty(itemSearch.getInvoiceReference())) {
            predicates.add(builder.like(exportInvoiceJoin.get("reference"), "%" + itemSearch.getInvoiceReference() + "%"));
        }
        if (itemSearch.getInvoiceId() != null) {
            predicates.add(builder.equal(exportInvoiceJoin.get("id"), itemSearch.getInvoiceId()));
        } else if (CollectionUtils.isNotEmpty(itemSearch.getInvoiceIds())) {
            predicates.add(exportInvoiceJoin.get("id").in(itemSearch.getInvoiceIds()));
        }
        if (itemSearch.getReference() != null && !itemSearch.getReference().isEmpty()) {
            predicates.add(builder.like(builder.lower(root.get("code")), "%" + itemSearch.getReference().toLowerCase() + "%"));
        }
        if (itemSearch.getDescription() != null && !itemSearch.getDescription().isEmpty()) {
            predicates.add(builder.like(builder.lower(root.get("description")), "%" + itemSearch.getDescription().toLowerCase() + "%"));
        }
        if (itemSearch.getStyleReference() != null && !itemSearch.getStyleReference().isEmpty()) {
            predicates.add(builder.like(builder.lower(root.get("styleReference")), "%" + itemSearch.getStyleReference().toLowerCase() + "%"));
        }
        if (itemSearch.getStyleDescription() != null && !itemSearch.getStyleDescription().isEmpty()) {
            predicates.add(builder.like(builder.lower(root.get("styleDescription")), "%" + itemSearch.getStyleDescription().toLowerCase() + "%"));
        }
        if (itemSearch.getTariffHeading() != null && !itemSearch.getTariffHeading().isEmpty()) {
            predicates.add(builder.like(builder.lower(root.get("tariffHeading")), "%" + itemSearch.getTariffHeading().toLowerCase() + "%"));
        }
        if (ArrayUtils.isNotEmpty(itemSearch.getStates())) {
            predicates.add(root.get("state").in(itemSearch.getStates()));
        }
        if (StringUtils.isNotEmpty(itemSearch.getShipmentNumber())) {
            predicates.add(builder.like(builder.lower(exportInvoiceJoin.get("export").get("shipmentNumber")), "%"
                    + itemSearch.getShipmentNumber().toLowerCase() + "%"));
        }
        if (itemSearch.getCreatedRange() != null && !itemSearch.getCreatedRange().isEmpty()) {
            Date createdFrom = DateUtils.getStartOfDay(itemSearch.getCreatedRange().get(0));
            Date createdTo = DateUtils.getEndOfDay(itemSearch.getCreatedRange().size() > 1 ? itemSearch.getCreatedRange().get(1) : new Date());

            predicates.add(builder.between(exportInvoiceJoin.get("export").get("created"), createdFrom, createdTo));
        }
        if (!predicates.isEmpty()) {
            Predicate[] toArray = predicates.stream().toArray(Predicate[]::new);
            criteria.where(toArray);
        }
    }
}