/** * Copyright [2015] [Christian Loehnert] * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.ks.idnadrev.cost.bookingview; import de.ks.datasource.DataSource; import de.ks.i18n.Localized; import de.ks.idnadrev.entity.cost.Account; import de.ks.idnadrev.entity.cost.Booking; import de.ks.persistence.PersistentWork; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.persistence.criteria.CriteriaBuilder; import javax.persistence.criteria.CriteriaQuery; import javax.persistence.criteria.Predicate; import javax.persistence.criteria.Root; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import java.util.function.Consumer; public class BookingViewDS implements DataSource<BookingViewModel> { private static final Logger log = LoggerFactory.getLogger(BookingViewDS.class); private BookingLoadingHint loadingHint; @Override public BookingViewModel loadModel(Consumer<BookingViewModel> furtherProcessing) { if (loadingHint == null) { return new BookingViewModel(); } else { List<Booking> bookings = PersistentWork.from(Booking.class, (root, query, builder) -> { loadingHint.applyFilter(query, builder, root, true); }, null); if (!bookings.isEmpty()) { Booking totalBefore = getTotalBefore(bookings.get(0).getBookingTime()); bookings = new ArrayList<>(bookings); Booking totalAfter = getTotalBeforeIncluding(bookings.get(bookings.size() - 1).getBookingTime()); double sum = bookings.stream().mapToDouble(Booking::getAmount).sum(); Account account = PersistentWork.forName(Account.class, loadingHint.getAccountName()); Booking sumBooking = new Booking(account, sum, false).setBookingTime(totalAfter.getBookingTime()).setDescription(Localized.get("sum")); bookings.add(0, totalBefore); bookings.add(sumBooking); bookings.add(totalAfter); } return new BookingViewModel(0D, bookings); } } private Booking getTotalBeforeIncluding(LocalDateTime date) { return getTotal(date, true); } private Booking getTotalBefore(LocalDateTime date) { return getTotal(date, false); } private Booking getTotal(LocalDateTime date, boolean includeDate) { return PersistentWork.read(em -> { CriteriaBuilder builder = em.getCriteriaBuilder(); CriteriaQuery<Double> query = builder.createQuery(Double.class); Root<Booking> from = query.from(Booking.class); loadingHint.applyFilter(query, builder, from, false); query.select(builder.sum(from.get(BookingLoadingHint.KEY_AMOUNT))); List<Predicate> restriction = new LinkedList<>(); restriction.add(query.getRestriction()); if (includeDate) { restriction.add(builder.lessThanOrEqualTo(from.get(BookingLoadingHint.KEY_TIME), date)); } else { restriction.add(builder.lessThan(from.get(BookingLoadingHint.KEY_TIME), date)); } query.where(restriction.toArray(new Predicate[2])); Double result = em.createQuery(query).getSingleResult(); log.debug("Sum of bookins before {}: {}", date, result); Account account = PersistentWork.forName(Account.class, loadingHint.getAccountName()); return new Booking(account, result == null ? 0D : result, false).setBookingTime(date).setDescription(Localized.get("total")); }); } @Override public void saveModel(BookingViewModel model, Consumer<BookingViewModel> beforeSaving) { } @Override public void setLoadingHint(Object dataSourceHint) { if (dataSourceHint instanceof BookingLoadingHint) { loadingHint = ((BookingLoadingHint) dataSourceHint); } else { loadingHint = null; } } }