package de.rwth.idsg.bikeman.app.repository; import de.rwth.idsg.bikeman.app.dto.ViewTransactionDTO; import de.rwth.idsg.bikeman.app.exception.AppErrorCode; import de.rwth.idsg.bikeman.app.exception.AppException; import de.rwth.idsg.bikeman.domain.*; import de.rwth.idsg.bikeman.domain.CardAccount_; import de.rwth.idsg.bikeman.domain.StationSlot_; import de.rwth.idsg.bikeman.domain.Station_; import de.rwth.idsg.bikeman.domain.Transaction_; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Repository; import javax.persistence.EntityManager; import javax.persistence.PersistenceContext; import javax.persistence.criteria.*; import java.util.List; @Repository @Slf4j public class AppTransactionRepositoryImpl implements AppTransactionRepository { @PersistenceContext private EntityManager em; public List<ViewTransactionDTO> findByCustomerPaginated(Customer customer, Integer page) throws AppException { CriteriaBuilder builder = em.getCriteriaBuilder(); CriteriaQuery<ViewTransactionDTO> criteria = builder.createQuery(ViewTransactionDTO.class); Root<Transaction> transaction = criteria.from(Transaction.class); Join<Transaction, CardAccount> cardAccount = transaction.join(Transaction_.cardAccount, JoinType.LEFT); Join<Transaction, StationSlot> fromStationSlot = transaction.join(Transaction_.fromSlot, JoinType.LEFT); Join<StationSlot, Station> fromStation = fromStationSlot.join(StationSlot_.station, JoinType.LEFT); Join<Transaction, StationSlot> toStationSlot = transaction.join(Transaction_.toSlot, JoinType.LEFT); Join<StationSlot, Station> toStation = toStationSlot.join(StationSlot_.station, JoinType.LEFT); criteria.select( builder.construct( ViewTransactionDTO.class, transaction.get(Transaction_.transactionId), transaction.get(Transaction_.startDateTime), transaction.get(Transaction_.endDateTime), transaction.get(Transaction_.fees), fromStation.get(Station_.stationId), fromStation.get(Station_.name), toStation.get(Station_.stationId), toStation.get(Station_.name) ) ).where( builder.and( builder.isNotNull(transaction.get(Transaction_.toSlot)), builder.isNotNull(transaction.get(Transaction_.endDateTime)), builder.equal(cardAccount.get(CardAccount_.ownerType), CustomerType.CUSTOMER), builder.equal(cardAccount.get(CardAccount_.cardAccountId), customer.getCardAccount().getCardAccountId()) ) ).orderBy( builder.desc(transaction.get(Transaction_.endDateTime)) ); try { return em.createQuery(criteria).setMaxResults(20).setFirstResult(20*page).getResultList(); } catch (Exception e) { throw new AppException("Failed during database operation.", AppErrorCode.DATABASE_OPERATION_FAILED); } } public List<ViewTransactionDTO> findOpenByCustomer(Customer customer) throws AppException { CriteriaBuilder builder = em.getCriteriaBuilder(); CriteriaQuery<ViewTransactionDTO> criteria = builder.createQuery(ViewTransactionDTO.class); Root<Transaction> transaction = criteria.from(Transaction.class); Join<Transaction, CardAccount> cardAccount = transaction.join(Transaction_.cardAccount, JoinType.LEFT); Join<Transaction, StationSlot> fromStationSlot = transaction.join(Transaction_.fromSlot, JoinType.LEFT); Join<StationSlot, Station> fromStation = fromStationSlot.join(StationSlot_.station, JoinType.LEFT); criteria.select( builder.construct( ViewTransactionDTO.class, transaction.get(Transaction_.transactionId), transaction.get(Transaction_.startDateTime), fromStation.get(Station_.stationId), fromStation.get(Station_.name) ) ).where( builder.and( builder.isNull(transaction.get(Transaction_.toSlot)), builder.isNull(transaction.get(Transaction_.endDateTime)), builder.equal(cardAccount.get(CardAccount_.ownerType), CustomerType.CUSTOMER), builder.equal(cardAccount.get(CardAccount_.cardAccountId), customer.getCardAccount().getCardAccountId()) ) ).orderBy( builder.asc(transaction.get(Transaction_.startDateTime)) ); try { return em.createQuery(criteria).getResultList(); } catch (Exception e) { throw new AppException("Failed during database operation.", AppErrorCode.DATABASE_OPERATION_FAILED); } } public Long numberOfOpenTransactionsByCustomer(Customer customer) { final String openTransactionsQuery = "SELECT COUNT(t) FROM Transaction t " + "WHERE t.cardAccount.cardAccountId = :cardAccountId " + "AND t.endDateTime IS NULL " + "AND t.toSlot IS NULL"; return em.createQuery(openTransactionsQuery, Long.class) .setParameter("cardAccountId", customer.getCardAccount().getCardAccountId()) .getSingleResult(); } }