com.github.drbookings.ui.controller.StatsViewController.java Source code

Java tutorial

Introduction

Here is the source code for com.github.drbookings.ui.controller.StatsViewController.java

Source

/*
 * DrBookings
 *
 * Copyright (C) 2016 - 2018 Alexander Kerner
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as
 * published by the Free Software Foundation, either version 2 of the
 * License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public
 * License along with this program.  If not, see
 * <http://www.gnu.org/licenses/gpl-2.0.html>.
 */

package com.github.drbookings.ui.controller;

import com.github.drbookings.*;
import com.github.drbookings.model.data.BookingEntries;
import com.github.drbookings.model.data.BookingOrigin;
import com.github.drbookings.model.data.Guest;
import com.github.drbookings.model.data.manager.MainManager;
import com.github.drbookings.model.settings.SettingsManager;
import com.github.drbookings.ui.BookingEntry;
import com.github.drbookings.ui.BookingsByOrigin;
import com.github.drbookings.ui.CurrencyCellValueFactory;
import com.github.drbookings.ui.IntegerCellValueFactory;
import com.github.drbookings.ui.beans.StatisticsTableBean;
import com.github.drbookings.ui.selection.BookingSelectionManager;
import com.google.common.collect.Range;
import javafx.collections.FXCollections;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.URL;
import java.time.LocalDate;
import java.util.*;
import java.util.Map.Entry;
import java.util.stream.Collectors;

public class StatsViewController implements Initializable {

    private final static Logger logger = LoggerFactory.getLogger(StatsViewController.class);

    @FXML
    private TableColumn<StatisticsTableBean, Number> cCleaningCosts;
    @FXML
    private TableColumn<StatisticsTableBean, Number> cCleaningFees;
    @FXML
    private TableColumn<StatisticsTableBean, Number> cNumberOfCleanings;
    @FXML
    private TableColumn<StatisticsTableBean, Number> cNumberOfPayedNights;
    @FXML
    private TableColumn<StatisticsTableBean, Number> cNumberOfAllNights;
    @FXML
    private TableColumn<StatisticsTableBean, Number> cNumberOfAllBookings;
    @FXML
    private TableColumn<StatisticsTableBean, Number> cNumberOfPayedBookings;
    @FXML
    private TableColumn<StatisticsTableBean, Number> cNightsPercent;
    @FXML
    private TableColumn<StatisticsTableBean, Number> cRelativeFixCosts;
    @FXML
    private TableColumn<StatisticsTableBean, Number> cEarnings;
    @FXML
    private TableColumn<StatisticsTableBean, Number> cNetEarnings;
    @FXML
    private TableColumn<StatisticsTableBean, Number> cEarningsPayout;
    @FXML
    private TableColumn<StatisticsTableBean, Number> cGrossIncome;
    @FXML
    private TableColumn<StatisticsTableBean, Number> cNetIncome;
    @FXML
    private TableColumn<StatisticsTableBean, Number> cServiceFees;

    //   private final ObjectProperty<Range<LocalDate>> dateRange = new SimpleObjectProperty<>();

    // @FXML
    // private Label totalEarningsPayout;
    // @FXML
    // private Label totalCleaningCosts;

    private final ObservableList<StatisticsTableBean> data = FXCollections.observableArrayList();

    private MainManager mainManager;

    @FXML
    private TableView<StatisticsTableBean> tableView;

    public StatsViewController() {

    }

    public MainManager getMainManager() {
        return mainManager;
    }

    @Override
    public void initialize(final URL location, final ResourceBundle resources) {
        cCleaningCosts.setCellFactory(new CurrencyCellValueFactory<>());
        cCleaningFees.setCellFactory(new CurrencyCellValueFactory<>());
        cNumberOfAllBookings.setCellFactory(new IntegerCellValueFactory<>());
        cNumberOfPayedBookings.setCellFactory(new IntegerCellValueFactory<>());
        cNumberOfPayedNights.setCellFactory(new IntegerCellValueFactory<>());
        cNumberOfAllNights.setCellFactory(new IntegerCellValueFactory<>());
        cNumberOfCleanings.setCellFactory(new IntegerCellValueFactory<>());
        cNightsPercent.setCellFactory(new CurrencyCellValueFactory<>());
        cRelativeFixCosts.setCellFactory(new CurrencyCellValueFactory<>());
        cEarnings.setCellFactory(new CurrencyCellValueFactory<>());
        cNetEarnings.setCellFactory(new CurrencyCellValueFactory<>());
        cEarningsPayout.setCellFactory(new CurrencyCellValueFactory<>());
        cGrossIncome.setCellFactory(new CurrencyCellValueFactory<>());
        cNetIncome.setCellFactory(new CurrencyCellValueFactory<>());
        cServiceFees.setCellFactory(new CurrencyCellValueFactory<>());

        FXUtils.makeHeaderWrappable(cCleaningCosts);
        FXUtils.makeHeaderWrappable(cCleaningFees);
        FXUtils.makeHeaderWrappable(cNumberOfPayedBookings);
        FXUtils.makeHeaderWrappable(cNumberOfAllBookings);
        FXUtils.makeHeaderWrappable(cNumberOfPayedNights);
        FXUtils.makeHeaderWrappable(cNumberOfAllNights);
        FXUtils.makeHeaderWrappable(cNumberOfCleanings);
        FXUtils.makeHeaderWrappable(cNightsPercent);
        FXUtils.makeHeaderWrappable(cRelativeFixCosts);
        FXUtils.makeHeaderWrappable(cEarnings);
        FXUtils.makeHeaderWrappable(cNetEarnings);
        FXUtils.makeHeaderWrappable(cEarningsPayout);
        FXUtils.makeHeaderWrappable(cGrossIncome);
        FXUtils.makeHeaderWrappable(cNetIncome);
        FXUtils.makeHeaderWrappable(cServiceFees);

        tableView.setOnContextMenuRequested(e -> System.out.println("Context menu requested " + e));
        tableView.setTableMenuButtonVisible(true);
        tableView.setItems(data);

        BookingSelectionManager.getInstance().selectionProperty()
                .addListener((ListChangeListener<BookingEntry>) c -> {
                    while (c.next()) {

                    }
                    updateUI(c.getList());
                });

        updateUI(BookingSelectionManager.getInstance().selectionProperty());

        // setHideCleaningStatistics(SettingsManager.getInstance().isHideCleaningStatistics());
        // SettingsManager.getInstance().hideCleaningStatisticsProperty()
        // .addListener((ChangeListener<Boolean>) (v, o, n) ->
        // setHideCleaningStatistics(n));
    }

    // private void setHideCleaningStatistics(final boolean hide) {
    // if (hide) {
    // hideCleaningStatistics();
    // } else {
    // showCleaningStatistics();
    // }
    // }

    // private void hideCleaningStatistics() {
    // tableView.getColumns().remove(cCleaningCosts);
    // tableView.getColumns().remove(cCleaningFees);
    // tableView.getColumns().remove(cNumberOfCleanings);
    // }

    // private void showCleaningStatistics() {
    // if (!tableView.getColumns().contains(cCleaningCosts)) {
    // tableView.getColumns().add(cCleaningCosts);
    // }
    // if (!tableView.getColumns().contains(cCleaningFees)) {
    // tableView.getColumns().add(cCleaningFees);
    // }
    // if (!tableView.getColumns().contains(cNumberOfCleanings)) {
    // tableView.getColumns().add(cNumberOfCleanings);
    // }
    // }

    public void setMainManager(final MainManager mainManager) {
        this.mainManager = mainManager;

    }

    public void shutDown() {

    }

    private void updateUI(final BookingsByOrigin<BookingEntry> bookings, final Range<LocalDate> dateRange) {
        if (logger.isDebugEnabled()) {
            logger.debug("Statistics for\n" + BookingEntries.toBookings(bookings.getAllBookings()).stream()
                    .map(i -> i.toString()).collect(Collectors.joining("\n")));
        }
        final float allAllNigths = BookingEntries.countNights(bookings, false);
        final NavigableSet<LocalDate> allDates = bookings.getAllBookings(true).stream().map(b -> b.getDate())
                .collect(Collectors.toCollection(TreeSet::new));
        long monthCount = TemporalQueries.countOccurrences(allDates,
                SettingsManager.getInstance().getFixCostsPaymentDay());
        if (logger.isDebugEnabled()) {
            logger.debug("Month count: " + monthCount);
        }
        if (monthCount < 1) {
            monthCount = 1;
            if (logger.isDebugEnabled()) {
                logger.debug("Month count (corrected): " + monthCount);
            }
        }
        final float additionalCosts = SettingsManager.getInstance().getAdditionalCosts() * monthCount;
        final float numberOfRooms = SettingsManager.getInstance().getNumberOfRooms();
        final float totalAdditionalCosts = additionalCosts * numberOfRooms;
        if (logger.isDebugEnabled()) {
            logger.debug("Fix costs total: " + totalAdditionalCosts);
        }
        for (final Entry<BookingOrigin, Collection<BookingEntry>> e : bookings.getMap().entrySet()) {

            final Collection<? extends BookingEntry> bookingsFilteredByPaymentDate = e.getValue().stream()
                    .filter(new PaymentDateFilter(dateRange)).collect(Collectors.toList());

            final Collection<? extends BookingEntry> bookingsFilteredByCleaningDate = e.getValue().stream()
                    .filter(new CleaningDateFilter(dateRange)).collect(Collectors.toList());

            final int numberOfAllBookings = (int) BookingEntries.countBookings(new BookingsByOrigin<>(e.getValue()),
                    false);

            final int numberOfPayedBookings = (int) BookingEntries
                    .countBookings(new BookingsByOrigin<>(e.getValue()), false);

            final int numberOfAllNights = (int) BookingEntries.countNights(new BookingsByOrigin<>(e.getValue()),
                    false);

            final int numberOfPayedNights = (int) BookingEntries
                    .countNights(new BookingsByOrigin<>(bookingsFilteredByPaymentDate), false);

            final float percentage;

            if (StringUtils.isBlank(e.getKey().getName())) {
                percentage = 0;
            } else {
                percentage = numberOfAllNights / allAllNigths * 100f;
            }
            if (logger.isDebugEnabled()) {
                logger.debug(e.getKey() + " percentage of all nights: " + percentage);
            }
            final double relativeFixCosts = totalAdditionalCosts * percentage / 100;
            if (logger.isDebugEnabled()) {
                logger.debug(e.getKey() + " relative fix costs " + relativeFixCosts);
            }
            if (logger.isDebugEnabled()) {
                logger.debug(e.getKey() + " number of bookings (all/payed): " + numberOfAllBookings + "/"
                        + numberOfPayedBookings);
            }
            if (logger.isDebugEnabled()) {
                logger.debug(e.getKey() + ": Number of nights (all/payed): " + numberOfAllNights + "/"
                        + numberOfPayedNights);
            }

            if (logger.isDebugEnabled()) {
                Set<Guest> set = e.getValue().stream().map(b -> b.getElement().getGuest())
                        .collect(Collectors.toCollection(LinkedHashSet::new));
                List<Guest> list = e.getValue().stream().filter(b -> !b.isCheckOut())
                        .map(b -> b.getElement().getGuest()).collect(Collectors.toCollection(ArrayList::new));
                StringBuilder sb = new StringBuilder(e.getKey() + " guest and nights (all):");
                int cnt = 1;
                int cnt2 = 0;
                for (final Guest guest : set) {
                    final int cnt3 = Collections.frequency(list, guest);

                    sb.append(String.format("%n%4d%20s%4d", cnt++, guest.getName(), cnt3));
                    cnt2 += cnt3;
                }
                sb.append(String.format("%n%24s%4d", "Total", cnt2));

                logger.debug(sb.toString());

                set = bookingsFilteredByPaymentDate.stream().map(b -> b.getElement().getGuest())
                        .collect(Collectors.toCollection(LinkedHashSet::new));
                list = bookingsFilteredByPaymentDate.stream().filter(b -> !b.isCheckOut())
                        .map(b -> b.getElement().getGuest()).collect(Collectors.toCollection(ArrayList::new));
                sb = new StringBuilder(e.getKey() + " guest and nights (payed):");
                cnt = 1;
                cnt2 = 0;
                for (final Guest guest : set) {
                    final int cnt3 = Collections.frequency(list, guest);

                    sb.append(String.format("%n%4d%20s%4d", cnt++, guest.getName(), cnt3));
                    cnt2 += cnt3;
                }
                sb.append(String.format("%n%24s%4d", "Total", cnt2));

                logger.debug(sb.toString());

            }

            final StatisticsTableBean b = StatisticsTableBean.build(e.getKey().getName(),
                    bookingsFilteredByPaymentDate);
            StatisticsTableBean.applyCleaningStuff(b, bookingsFilteredByCleaningDate);
            b.setFixCosts((float) relativeFixCosts);
            b.setNightsPercent(percentage);
            b.setNumberOfPayedNights(numberOfPayedNights);
            b.setNumberOfAllNights(numberOfAllNights);
            b.setNumberOfPayedBookings(numberOfPayedBookings);
            b.setNumberOfAllBookings(numberOfAllBookings);
            data.add(b);
        }
        // add a total row

        final float relativeFixCosts = totalAdditionalCosts;
        final StatisticsTableBean b = StatisticsTableBean.buildSum(data);
        b.setFixCosts(relativeFixCosts);
        b.setNightsPercent(100);
        data.add(b);
    }

    private void updateUI(final Collection<? extends BookingEntry> bookings) {
        data.clear();
        if (bookings == null || bookings.isEmpty()) {
            return;
        }

        final BookingsByOrigin<BookingEntry> bo = new BookingsByOrigin<>(bookings);
        updateUI(bo, LocalDates.getDateRange(bookings.stream().map(e -> e.getDate()).collect(Collectors.toList())));
        // updateTotals();
    }

    // private void updateTotals() {
    // final double sumTotalEarningsPayout = data.stream().mapToDouble(b ->
    // b.getEarningsPayout()).sum();
    // final double sumTotalCleaningCosts = data.stream().mapToDouble(b ->
    // b.getCleaningCosts()).sum();
    // totalEarningsPayout.setText(NumberFormat.getIntegerInstance().format(sumTotalEarningsPayout));
    // totalCleaningCosts.setText(NumberFormat.getIntegerInstance().format(sumTotalCleaningCosts));
    //
    // }

}