PaymentRepositoryImpl.java
package com.tradecloud.repository.impl;
import com.tradecloud.domain.document.invoice.CommercialInvoice;
import com.tradecloud.domain.model.ordermanagement.Order;
import com.tradecloud.domain.settlement.Payment;
import com.tradecloud.domain.settlement.PlannedSettlement;
import com.tradecloud.repository.PaymentRepository;
import com.tradecloud.repository.base.impl.RepositoryBaseImpl;
import org.hibernate.Criteria;
import org.hibernate.FetchMode;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Property;
import org.hibernate.criterion.Restrictions;
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.math.BigDecimal;
import java.util.List;
/**
* Default implementation of the {@code PaymentRepository} interface.
*/
@Repository
@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT)
public class PaymentRepositoryImpl extends RepositoryBaseImpl<Payment, Object> implements PaymentRepository {
private static final long serialVersionUID = 1L;
@Override
public List<Payment> findByPlannedSettlement(PlannedSettlement plannedSettlement) {
@SuppressWarnings("unchecked")
List<Payment> results =
(List<Payment>) getNamedQueryAndNamedParam("payment.findByPlannedSettlement",
"plannedSettlement", plannedSettlement);
return results;
}
@Override
public List<Payment> findByOrdersLinkedToInvoice(List<Order> orders) {
if (orders == null || orders.isEmpty()) {
throw new IllegalArgumentException("At least one order is required");
}
Long[] ids = new Long[orders.size()];
int i = 0;
for (Order order : orders) {
ids[i++] = order.getId();
}
/*
* This sub-query retrieves the IDs of all PlannedSettlements associated to any ID of the Orders supplied. The resulting list will be used in
* the actual query to find payments, next.
*/
DetachedCriteria orderSubQuery =
DetachedCriteria.forClass(Order.class, "order").createAlias("plannedSettlements", "ps").add(Restrictions.in("order.id", ids))
.setProjection(Projections.projectionList().add(Projections.property("ps.id")));
/**
* This query finds all payments associated with planned settlements whose IDs are in the list retrieved in the previous sub-query.
*
* Note: The setFetchMode("paymentMethod") is to make that association lazy-loaded as we don't need to load it here. The Hibernate docs for
* FetchMode.SELECT are ambiguous though. They say "Fetch eagerly, using a separate select.". But in the docs for, the now deprecated,
* FetchMode.LAZY it says "Fetch lazily. Deprecated, use FetchMode.SELECT". See: https://hibernate.atlassian.net/browse/HHH-980
*/
Criteria paymentCriteria =
getSessionCustom().createCriteria(Payment.class, "payment").createAlias("plannedSettlement", "pst")
.setFetchMode("paymentMethod", FetchMode.SELECT).add(Property.forName("pst.id").in(orderSubQuery));
@SuppressWarnings("unchecked")
List<Payment> results = paymentCriteria.list();
return results;
}
@Override
public BigDecimal getTotalAmountPaidOnPlannedSettlement(PlannedSettlement plannedSettlement) {
Object uniqueResult =
getCurrentSession().createCriteria(Payment.class).add(Restrictions.eq("plannedSettlement", plannedSettlement))
.setProjection(Projections.projectionList().add(Projections.sum("amount").as("value"))).uniqueResult();
if (uniqueResult == null) {
return BigDecimal.ZERO.setScale(4);
}
return (BigDecimal) uniqueResult;
}
@Override
public Order getOrderForPayment(Payment payment) {
CriteriaBuilder criteriaBuilder = getSession().getCriteriaBuilder();
CriteriaQuery<Order> criteriaQuery = criteriaBuilder.createQuery(Order.class);
Root<Order> root = criteriaQuery.from(Order.class);
Join<Order, PlannedSettlement> join = root.join("plannedSettlements");
Path path = join.get("id");
Predicate predicate = criteriaBuilder.equal(path, payment.getPlannedSettlement().getId());
criteriaQuery.where(predicate);
org.hibernate.query.Query<Order> q = getSession().createQuery(criteriaQuery);
return q.uniqueResult();
}
@Override
public CommercialInvoice getCIForPayment(Payment payment) {
CriteriaBuilder criteriaBuilder = getSession().getCriteriaBuilder();
CriteriaQuery<CommercialInvoice> criteriaQuery = criteriaBuilder.createQuery(CommercialInvoice.class);
Root<CommercialInvoice> root = criteriaQuery.from(CommercialInvoice.class);
Join<CommercialInvoice, PlannedSettlement> join = root.join("plannedSettlements");
Path path = join.get("id");
Predicate predicate = criteriaBuilder.equal(path, payment.getPlannedSettlement().getId());
criteriaQuery.where(predicate);
org.hibernate.query.Query<CommercialInvoice> q = getSession().createQuery(criteriaQuery);
return q.uniqueResult();
}
@Override
public Payment findByERPPaymentId(String erpPaymentId) {
CriteriaBuilder criteriaBuilder = getSession().getCriteriaBuilder();
CriteriaQuery<Payment> criteriaQuery = criteriaBuilder.createQuery(Payment.class);
Root<Payment> c = criteriaQuery.from(Payment.class);
criteriaQuery = criteriaQuery.select(c).where(criteriaBuilder.equal(c.get("erpPaymentId"), erpPaymentId));
org.hibernate.query.Query<Payment> q = getSession().createQuery(criteriaQuery);
return q.uniqueResult();
}
@Override
public boolean alreadyReversed(Payment payment) {
CriteriaBuilder criteriaBuilder = getSession().getCriteriaBuilder();
CriteriaQuery<Payment> criteriaQuery = criteriaBuilder.createQuery(Payment.class);
Root<Payment> c = criteriaQuery.from(Payment.class);
Predicate reallocationDestinationId = criteriaBuilder.equal(c.get("reallocationDestinationId"), payment.getId());
Predicate andType = criteriaBuilder.equal(c.get("type"), Payment.Type.REALLOCATION_REVERSAL);
Predicate finalQuery = criteriaBuilder.and(reallocationDestinationId, andType);
criteriaQuery = criteriaQuery.select(c).where(finalQuery);
org.hibernate.query.Query<Payment> q = getSession().createQuery(criteriaQuery);
List<Payment> list = q.list();
if (list == null || list.isEmpty())
return false;
return true;
}
}