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

Java tutorial

Introduction

Here is the source code for com.github.drbookings.ui.controller.BookingDetailsController.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.LocalDates;
import com.github.drbookings.model.Payment;
import com.github.drbookings.model.data.BookingBean;
import com.github.drbookings.model.data.manager.MainManager;
import com.github.drbookings.model.settings.SettingsManager;
import com.github.drbookings.ui.CleaningEntry;
import com.github.drbookings.ui.Styles;
import com.github.drbookings.ui.beans.RoomBean;
import com.github.drbookings.ui.dialogs.ModifyBookingDialogFactory;
import com.github.drbookings.ui.selection.RoomBeanSelectionManager;
import javafx.application.Platform;
import javafx.beans.binding.Bindings;
import javafx.collections.ListChangeListener;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.control.*;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Pane;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.scene.text.Text;
import javafx.scene.text.TextFlow;
import javafx.util.converter.NumberStringConverter;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

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

public class BookingDetailsController implements Initializable {

    private static final DecimalFormat decimalFormat = new DecimalFormat("#,##0.00");
    private static final int prefTextInputFieldWidth = 80;
    private static final int boxSpacing = 4;
    private static final Insets boxPadding = new Insets(boxSpacing);
    private static final Logger logger = LoggerFactory.getLogger(BookingDetailsController.class);
    private final Map<BookingBean, TextInputControl> booking2CheckInNote = new HashMap<>();
    private final Map<BookingBean, TextInputControl> booking2CheckOutNote = new HashMap<>();
    private final Map<BookingBean, TextInputControl> booking2SpecialRequestNote = new HashMap<>();
    private final Map<BookingBean, TextInputControl> booking2GrossEarnings = new HashMap<>();
    private final Map<BookingBean, CheckBox> booking2WelcomeMail = new HashMap<>();
    private final Map<BookingBean, CheckBox> booking2Payment = new HashMap<>();
    private final Map<BookingBean, DatePicker> booking2PaymentDate = new HashMap<>();
    @FXML
    private VBox content;
    private MainManager manager;
    private ModifyBookingDialogFactory modifyBookingDialogFactory;
    private final ListChangeListener<RoomBean> roomListener = c -> Platform.runLater(() -> update(c.getList()));

    private static void addDates(final HBox content, final BookingBean be) {
        final TextFlow checkIn = LocalDates.getDateText(be.getCheckIn());
        final TextFlow checkOut = LocalDates.getDateText(be.getCheckOut());
        final TextFlow year = LocalDates.getYearText(be.getCheckOut());
        final TextFlow tf = new TextFlow();
        tf.getChildren().addAll(checkIn, new Text("\n"), checkOut, new Text("\n"), year);
        // tf.getChildren().addAll(checkIn, new Text("  "), checkOut);
        // HBox.setHgrow(tf, Priority.SOMETIMES);
        content.getChildren().add(tf);

    }

    private static void addName(final HBox content, final BookingBean be) {
        final Label label = new Label(be.getGuest().getName() + "\n" + be.getBookingOrigin().getName());
        label.setWrapText(true);
        content.getChildren().add(label);
        HBox.setHgrow(label, Priority.ALWAYS);

    }

    private static void addNights(final HBox content, final BookingBean be) {
        final Text label = new Text(be.getNumberOfNights() + " nights");
        content.getChildren().add(label);
        // HBox.setHgrow(label, Priority.SOMETIMES);
    }

    private static void addRow0(final Pane content, final BookingBean be) {
        final HBox box = new HBox();
        final HBox boxName = new HBox();
        final HBox boxDates = new HBox();
        final HBox boxNights = new HBox();
        box.setAlignment(Pos.CENTER);
        boxName.getStyleClass().add("first-line");
        boxDates.getStyleClass().add("first-line");
        boxNights.getStyleClass().add("first-line");
        boxName.setPadding(boxPadding);
        boxDates.setPadding(boxPadding);
        boxNights.setPadding(boxPadding);
        boxName.setAlignment(Pos.CENTER);
        boxDates.setAlignment(Pos.CENTER);
        boxNights.setAlignment(Pos.CENTER);
        HBox.setHgrow(boxName, Priority.ALWAYS);
        HBox.setHgrow(boxDates, Priority.ALWAYS);
        HBox.setHgrow(boxNights, Priority.ALWAYS);
        addName(boxName, be);
        // box.getChildren().add(new Separator(Orientation.VERTICAL));
        addDates(boxDates, be);
        // box.getChildren().add(new Separator(Orientation.VERTICAL));
        addNights(boxNights, be);
        box.getChildren().addAll(boxName, boxDates, boxNights);
        box.getStyleClass().add(Styles.getBackgroundStyleSource(be.getBookingOrigin().getName()));
        content.getChildren().add(box);

    }

    private static void addRow2(final Pane content, final BookingBean be) {

    }

    private static void addRow4(final Pane content, final BookingBean be) {
        final HBox box = new HBox();
        box.setPadding(new Insets(4));
        box.setAlignment(Pos.CENTER_LEFT);
        box.setFillHeight(true);
        final TextFlow tf = new TextFlow();
        final Text t0 = new Text("Net Earnings: \t");
        final Text netEarnings = new Text(String.format("%3.2f", be.getNetEarnings()));
        final Text t1 = new Text(" total \t");
        final Text netEarningsDay = new Text(String.format("%3.2f", be.getNetEarnings() / be.getNumberOfNights()));
        final Text t2 = new Text(" /night");
        tf.getChildren().addAll(t0, netEarnings, t1, netEarningsDay, t2);
        box.getChildren().addAll(tf);
        if (be.getNetEarnings() <= 0) {
            box.getStyleClass().addAll("warning", "warning-bg");
        }
        content.getChildren().add(box);

    }

    static void addNewPayment(String paymentString, BookingBean be) {
        if (StringUtils.isBlank(paymentString)) {
            return;
        }
        double paymentAmount = Double.parseDouble(paymentString);
        LocalDate paymentDate = LocalDate.now();
        Payment payment = new Payment(paymentDate, paymentAmount);
        be.getPayments().add(payment);

    }

    public MainManager getManager() {
        return manager;
    }

    private void addCheckInNote(final Pane content, final BookingBean be) {
        final VBox b = new VBox();
        b.getChildren().add(new Text("Check-in Note"));
        final TextArea ta0 = new TextArea(be.getCheckInNote());
        ta0.setWrapText(true);
        ta0.setPrefHeight(80);
        b.getChildren().add(ta0);
        booking2CheckInNote.put(be, ta0);
        content.getChildren().add(b);

    }

    private void addCheckOutNote(final Pane content, final BookingBean be) {
        final VBox b = new VBox();
        b.getChildren().add(new Text("Check-out Note"));
        final TextArea ta0 = new TextArea(be.getCheckOutNote());
        ta0.setWrapText(true);
        ta0.setPrefHeight(80);
        b.getChildren().add(ta0);
        booking2CheckOutNote.put(be, ta0);
        content.getChildren().add(b);

    }

    public void setManager(final MainManager manager) {
        this.manager = manager;
    }

    private void addRow1(final Pane content, final BookingBean be) {
        final VBox box = new VBox();
        final HBox box0 = new HBox();
        final HBox box1 = new HBox();
        final HBox box2 = new HBox();
        box.setFillWidth(true);
        box0.setFillHeight(true);
        box1.setFillHeight(true);
        box2.setFillHeight(true);
        addCheckInNote(box0, be);
        addCheckOutNote(box1, be);
        addSpecialRequestNote(box2, be);
        box.getChildren().addAll(box0, box1, box2);
        final TitledPane pane = new TitledPane("Notes", box);
        pane.setExpanded(false);
        content.getChildren().add(pane);

    }

    private void addRowNetEarnings(final Pane content, final BookingBean be) {
        final HBox box = new HBox();
        box.setSpacing(boxSpacing);
        box.setPadding(boxPadding);
        box.setAlignment(Pos.CENTER_LEFT);
        box.setFillHeight(true);
        final TextField grossEarningsExpression = new TextField(be.getGrossEarningsExpression());
        grossEarningsExpression.setPrefWidth(prefTextInputFieldWidth * 1.5);
        booking2GrossEarnings.put(be, grossEarningsExpression);
        final Text grossEarnings = new Text(decimalFormat.format(be.getGrossEarnings()));
        final TextFlow tf = new TextFlow(new Text("Gross Earnings: "), grossEarningsExpression, new Text(" = "),
                grossEarnings, new Text(""));
        box.getChildren().addAll(tf);
        if (be.getGrossEarnings() <= 0) {
            box.getStyleClass().addAll("warning", "warning-bg");
        }

        final HBox box2 = new HBox();
        box2.setSpacing(boxSpacing);
        box2.setPadding(boxPadding);
        box2.setAlignment(Pos.CENTER_LEFT);
        box2.setFillHeight(true);

        Text text = new Text("Amount received: ");
        TextField textField = new TextField();
        textField.setText(new NumberStringConverter().toString(be.getPaymentSoFar()));
        textField.setEditable(false);
        be.paymentSoFarProperty().addListener((c, o, n) -> {
            textField.setText(new NumberStringConverter().toString(n));
        });
        box2.getChildren().addAll(text, textField);
        content.getChildren().addAll(box, box2);

    }

    private void addRowFees(final Pane content, final BookingBean be) {
        final HBox box = new HBox();

        // configure box
        box.setSpacing(8);
        box.setPadding(boxPadding);
        box.setAlignment(Pos.CENTER);
        box.setFillHeight(true);

        // add cleaning fees
        final TextField cleaningFeesTextField = new TextField();
        Bindings.bindBidirectional(cleaningFeesTextField.textProperty(), be.cleaningFeesProperty(),
                new NumberStringConverter(decimalFormat));
        cleaningFeesTextField.setPrefWidth(prefTextInputFieldWidth);
        final TextFlow cleaningFeesTextFlow = new TextFlow(new Text("Cleaning Fees: "), cleaningFeesTextField,
                new Text(" "));
        box.getChildren().add(cleaningFeesTextFlow);

        // add cleaning costs

        final CleaningEntry ce = be.getCleaning();
        if (ce != null) {
            final TextField cleaningCostsTextField = new TextField();
            Bindings.bindBidirectional(cleaningCostsTextField.textProperty(), ce.cleaningCostsProperty(),
                    new NumberStringConverter(decimalFormat));
            cleaningCostsTextField.setPrefWidth(prefTextInputFieldWidth);
            final TextFlow cleaningCostsTextFlow = new TextFlow(new Text("Cleaning Costs: "),
                    cleaningCostsTextField, new Text(" "));
            box.getChildren().add(cleaningCostsTextFlow);
        } else {
            final TextField cleaningCostsTextField = new TextField("No Cleaning");
            cleaningCostsTextField.setEditable(false);
            cleaningCostsTextField.setPrefWidth(prefTextInputFieldWidth);
            final TextFlow cleaningCostsTextFlow = new TextFlow(new Text("Cleaning Costs: "),
                    cleaningCostsTextField);
            cleaningCostsTextField.getStyleClass().add("warning");
            box.getChildren().add(cleaningCostsTextFlow);
        }

        // add service fees
        final TextField serviceFeesTextField = new TextField();
        Bindings.bindBidirectional(serviceFeesTextField.textProperty(), be.serviceFeeProperty(),
                new NumberStringConverter(decimalFormat));
        serviceFeesTextField.setPrefWidth(prefTextInputFieldWidth);
        final TextFlow serviceFeesAbsTextFlow = new TextFlow(new Text("Service Fees: "), serviceFeesTextField,
                new Text(" "));
        box.getChildren().add(serviceFeesAbsTextFlow);

        // add service fees percent
        final TextField serviceFeesPercentTextField = new TextField();
        Bindings.bindBidirectional(serviceFeesPercentTextField.textProperty(), be.serviceFeesPercentProperty(),
                new NumberStringConverter(decimalFormat));
        serviceFeesPercentTextField.setPrefWidth(prefTextInputFieldWidth);
        final TextFlow serviceFeesPercentTextFlow = new TextFlow(new Text("Service Fees: "),
                serviceFeesPercentTextField, new Text(" %"));

        box.getChildren().add(serviceFeesPercentTextFlow);

        // add box to parent
        content.getChildren().add(box);

    }

    private void addRow5(final Pane content, final BookingBean be) {
        final HBox box = new HBox();
        box.setPadding(new Insets(4));
        box.setFillHeight(true);
        final Text text = new Text("Welcome Mail sent: ");
        final CheckBox checkBox = new CheckBox();
        checkBox.setSelected(be.isWelcomeMailSend());
        booking2WelcomeMail.put(be, checkBox);
        final Text t1 = new Text(" \tPayment done: ");

        final CheckBox cb1 = new CheckBox();
        cb1.setSelected(be.isPaymentDone());

        //if (logger.isDebugEnabled()) {
        //   logger.debug("DateOfPayment for " + be + "(" + be.hashCode() + ") is " + be.getDateOfPayment());
        //}

        final DatePicker dp = new DatePicker();
        dp.setValue(be.getDateOfPayment());

        dp.setPrefWidth(140);
        booking2PaymentDate.put(be, dp);

        booking2Payment.put(be, cb1);
        final TextFlow tf = new TextFlow();
        tf.getChildren().addAll(text, checkBox, t1, cb1, dp);
        box.getChildren().add(tf);
        if (!be.isWelcomeMailSend() || !be.isPaymentDone()) {
            box.getStyleClass().addAll("warning", "warning-bg");
        } else {
            box.getStyleClass().removeAll("warning", "warning-bg");
        }

        HBox box2 = new HBox();
        box2.setPadding(new Insets(4));
        box2.setFillHeight(true);
        TextField newPayment = new TextField();
        Button addNewPaymentButton = new Button("Add payment");
        addNewPaymentButton.setOnAction(e -> {
            addNewPayment(newPayment.getText(), be);
        });
        box2.getChildren().addAll(newPayment, addNewPaymentButton);

        content.getChildren().addAll(box, box2);

    }

    private void addSeparator() {
        final HBox bb = new HBox();
        bb.setPrefHeight(20);
        bb.setAlignment(Pos.CENTER);
        final Separator s = new Separator();
        s.getStyleClass().add("large-separator");
        bb.getChildren().add(s);
        HBox.setHgrow(s, Priority.ALWAYS);
        content.getChildren().add(bb);
    }

    private void addSpecialRequestNote(final Pane content, final BookingBean be) {
        final VBox b = new VBox();
        b.getChildren().add(new Text("Special Requests"));
        final TextArea ta0 = new TextArea(be.getSpecialRequestNote());
        ta0.setWrapText(true);
        ta0.setPrefHeight(80);
        b.getChildren().add(ta0);
        booking2SpecialRequestNote.put(be, ta0);
        content.getChildren().add(b);

    }

    private void clearAll() {
        booking2CheckInNote.clear();
        booking2CheckOutNote.clear();
        booking2SpecialRequestNote.clear();
        booking2GrossEarnings.clear();
        booking2Payment.clear();
        booking2WelcomeMail.clear();
        content.getChildren().clear();
    }

    @FXML
    public void handleActionSaveBookingDetails(final ActionEvent e) {
        for (final Entry<BookingBean, TextInputControl> en : booking2CheckInNote.entrySet()) {
            en.getKey().setCheckInNote(en.getValue().getText());
        }
        for (final Entry<BookingBean, TextInputControl> en : booking2CheckOutNote.entrySet()) {
            en.getKey().setCheckOutNote(en.getValue().getText());
        }
        for (final Entry<BookingBean, TextInputControl> en : booking2SpecialRequestNote.entrySet()) {
            en.getKey().setSpecialRequestNote(en.getValue().getText());
        }
        for (final Entry<BookingBean, TextInputControl> en : booking2GrossEarnings.entrySet()) {
            en.getKey().setGrossEarningsExpression(en.getValue().getText());
        }

        for (final Entry<BookingBean, CheckBox> en : booking2WelcomeMail.entrySet()) {
            en.getKey().setWelcomeMailSend(en.getValue().isSelected());
        }
        // first date, then flag! Wont work otherwise
        for (final Entry<BookingBean, DatePicker> en : booking2PaymentDate.entrySet()) {
            en.getKey().setDateOfPayment(en.getValue().getValue());
        }
        for (final Entry<BookingBean, CheckBox> en : booking2Payment.entrySet()) {
            en.getKey().setPaymentDone(en.getValue().isSelected());
        }
        // final Stage stage = (Stage) content.getScene().getWindow();
        // stage.close();
    }

    @Override
    public void initialize(final URL location, final ResourceBundle resources) {
        RoomBeanSelectionManager.getInstance().selectionProperty().addListener(roomListener);
        SettingsManager.getInstance().cleaningFeesProperty().addListener(
                (observable, oldValue, newValue) -> update(RoomBeanSelectionManager.getInstance().getSelection()));
        update(RoomBeanSelectionManager.getInstance().getSelection());

    }

    private void update(final Collection<? extends RoomBean> rooms) {
        clearAll();
        final List<BookingBean> bookings = new ArrayList<>(
                rooms.stream().flatMap(r -> r.getFilteredBookingEntries().stream().map(b -> b.getElement()))
                        .collect(Collectors.toSet()));
        Collections.sort(bookings);
        for (final Iterator<BookingBean> it = bookings.iterator(); it.hasNext();) {
            final BookingBean be = it.next();
            addBookingEntry(be);
            if (it.hasNext()) {
                addSeparator();
            }
        }
    }

    private void addBookingEntry(final BookingBean be) {
        // System.err.println("Adding entry for " + be);
        final VBox box = new VBox(4);
        // box.setPadding(new Insets(4));
        addRow0(box, be);
        box.getChildren().add(new Separator());
        addRowNetEarnings(box, be);
        box.getChildren().add(new Separator());
        addRowFees(box, be);
        box.getChildren().add(new Separator());
        addRow4(box, be);
        box.getChildren().add(new Separator());
        addRow5(box, be);
        box.getChildren().add(new Separator());
        addRow1(box, be);
        addRow2(box, be);
        addModifyButton(box, be);
        content.getChildren().add(box);

    }

    private void addModifyButton(final VBox box, final BookingBean be) {
        final Button b = new Button();
        b.setText("Modify");
        b.setPrefWidth(100);
        b.setOnAction(e -> {
            if (modifyBookingDialogFactory == null) {
                modifyBookingDialogFactory = new ModifyBookingDialogFactory(getManager());
            }
            modifyBookingDialogFactory.showDialog();
        });
        box.getChildren().add(b);

    }

    public void shutDown() {

    }

}