From 42c319af1c4a614525401348ba8fc0b8794b5015 Mon Sep 17 00:00:00 2001 From: Chris Mailloux Date: Mon, 13 Nov 2017 13:03:56 -0500 Subject: [PATCH 1/5] Begin implementation of view bill screen logic --- .../BookingDetailsScreenController.java | 32 ++++----- .../CustomerBillScreenController.java | 67 ++++++++++++++----- .../resort/controller/ScreenManager.java | 7 +- .../gitrekt/resort/model/entities/Guest.java | 3 +- .../resort/model/services/BillService.java | 18 ++--- .../resources/fxml/CustomerBillScreen.fxml | 10 +-- 6 files changed, 85 insertions(+), 52 deletions(-) diff --git a/src/main/java/com/gitrekt/resort/controller/BookingDetailsScreenController.java b/src/main/java/com/gitrekt/resort/controller/BookingDetailsScreenController.java index 9f5f38f..91438a8 100644 --- a/src/main/java/com/gitrekt/resort/controller/BookingDetailsScreenController.java +++ b/src/main/java/com/gitrekt/resort/controller/BookingDetailsScreenController.java @@ -1,10 +1,11 @@ package com.gitrekt.resort.controller; +import com.gitrekt.resort.model.entities.Booking; +import com.gitrekt.resort.model.services.BookingService; import java.net.URL; import java.util.ResourceBundle; import javafx.fxml.FXML; import javafx.fxml.Initializable; -import javafx.scene.control.Button; import javafx.scene.control.Label; import javafx.scene.control.TableView; @@ -12,15 +13,6 @@ * FXML Controller class for the booking details screen. */ public class BookingDetailsScreenController implements Initializable { - - @FXML - private Button backButton; - - @FXML - private Button cancelBookingButton; - - @FXML - private Button viewBillButton; // TODO fix rawtype @FXML @@ -39,27 +31,37 @@ public class BookingDetailsScreenController implements Initializable { @FXML private Label checkOutDateLabel; + private Booking booking; + /** * Initializes the controller class. */ @Override public void initialize(URL url, ResourceBundle rb) { - // TODO + // TODO: Remove test code + BookingService bookingService = new BookingService(); + this.booking = bookingService.getBookingById(1L); } - public void onBackButtonClicked() { + @FXML + private void onBackButtonClicked() { ScreenManager.getInstance().switchToScreen( "/fxml/GuestHomeScreen.fxml" ); } - public void onViewBillButtonClicked() { - ScreenManager.getInstance().switchToScreen( + @FXML + private void onViewBillButtonClicked() { + Object temp = ScreenManager.getInstance().switchToScreen( "/fxml/CustomerBillScreen.fxml" ); + CustomerBillScreenController controller; + controller = (CustomerBillScreenController) temp; + controller.initializeData(this.booking); } - public void onCancelBookingButtonClicked() { + @FXML + private void onCancelBookingButtonClicked() { // TODO } diff --git a/src/main/java/com/gitrekt/resort/controller/CustomerBillScreenController.java b/src/main/java/com/gitrekt/resort/controller/CustomerBillScreenController.java index 63be7ba..c8cd042 100644 --- a/src/main/java/com/gitrekt/resort/controller/CustomerBillScreenController.java +++ b/src/main/java/com/gitrekt/resort/controller/CustomerBillScreenController.java @@ -1,6 +1,8 @@ package com.gitrekt.resort.controller; import com.gitrekt.resort.model.entities.Bill; +import com.gitrekt.resort.model.entities.BillItem; +import com.gitrekt.resort.model.entities.Booking; import com.gitrekt.resort.model.services.BillService; import com.gitrekt.resort.model.services.BookingService; import java.awt.print.PrinterException; @@ -34,36 +36,45 @@ public class CustomerBillScreenController implements Initializable { @FXML private TableView billTable; - // TODO: Fix rawtype @FXML private TableColumn itemNameColumn; - // TODO: Fix rawtype @FXML private TableColumn qtyColumn; - // TODO: Fix rawtype @FXML private TableColumn priceColumn; - private Bill bill; - - private Long bookingNumber; - - private String customerName; + private Booking booking; /** * Initializes the controller class. */ @Override - public void initialize(URL url, ResourceBundle rb) { - String formattedPrice = String.format("%.2f", bill.getTotal()); - billTotalText.setText(formattedPrice); + public void initialize(URL url, ResourceBundle rb) { + // TODO } - public void initializeData(Long bookingNumber) { - this.bookingNumber = bookingNumber; - bookingNumberText.setText(String.valueOf(bookingNumber)); + /** + * Initializes the view bill screen with the data for the bill to display. + * Once this method is called, the proper data is displayed on the screen. + * + * It's not ideal to have to send the entire booking into this class to + * display just the bill, but we need several bits of extra information + * that the bill itself just doesn't contain (such as the guest name), and + * I don't have the time to implement a more robust solution, so for now, it + * works. + * + * @param booking The booking to display the bill for. + */ + public void initializeData(Booking booking) { + this.booking = booking; + + // TODO: Remove test code + booking.getBill().getCharges().add(new BillItem("Test bill item", 15.99, 1)); + + initializeInfoLabels(); + prepareTableView(); } @FXML @@ -73,12 +84,36 @@ private void onBackButtonClicked() { ); } + /** + * Prints the guest bill on a physical printer. The user is first prompted + * with a print options dialog. + * + * @throws IOException + * @throws PrinterException + */ @FXML private void onPrintBillButtonClicked() throws IOException, PrinterException { - // TODO: Replace with an actual bill, not an empty one. BillService billService = new BillService(); - billService.printBill(new Bill()); + billService.printBillForBooking(booking); + } + + /** + * Initializes the information displayed in the various labels displayed on + * this screen, such as the customer name label, the total price label, etc. + */ + private void initializeInfoLabels() { + bookingNumberText.setText(String.valueOf(booking.getId())); + String lastName = booking.getGuest().getFirstName(); + String firstName = booking.getGuest().getLastName(); + customerNameText.setText(lastName + ", " + firstName); + billTotalText.setText( + String.format("$%.2f", booking.getBill().getTotal()) + ); + } + + private void prepareTableView() { + // TODO } } diff --git a/src/main/java/com/gitrekt/resort/controller/ScreenManager.java b/src/main/java/com/gitrekt/resort/controller/ScreenManager.java index c317816..33fbf75 100644 --- a/src/main/java/com/gitrekt/resort/controller/ScreenManager.java +++ b/src/main/java/com/gitrekt/resort/controller/ScreenManager.java @@ -13,12 +13,12 @@ public class ScreenManager { private static Stage mainStage; - private final FXMLLoader fxmlLoader; + private FXMLLoader fxmlLoader; private static ScreenManager instance; private ScreenManager() { - fxmlLoader = new FXMLLoader(); + //fxmlLoader = new FXMLLoader(); } /** @@ -56,7 +56,8 @@ public Object switchToScreen(String fxmlPath) { try { URL pathToFxml = getClass().getResource(fxmlPath); - newScreenRoot = fxmlLoader.load(pathToFxml); + fxmlLoader = new FXMLLoader(pathToFxml); + newScreenRoot = fxmlLoader.load(); } catch (IOException e) { throw new IllegalArgumentException("Failed to load FXML", e); } diff --git a/src/main/java/com/gitrekt/resort/model/entities/Guest.java b/src/main/java/com/gitrekt/resort/model/entities/Guest.java index 239533d..00105b0 100644 --- a/src/main/java/com/gitrekt/resort/model/entities/Guest.java +++ b/src/main/java/com/gitrekt/resort/model/entities/Guest.java @@ -94,5 +94,6 @@ public boolean isCheckedIn() { public Long getId(){ return id; - } + } + } diff --git a/src/main/java/com/gitrekt/resort/model/services/BillService.java b/src/main/java/com/gitrekt/resort/model/services/BillService.java index 5125fc4..f2b37e4 100644 --- a/src/main/java/com/gitrekt/resort/model/services/BillService.java +++ b/src/main/java/com/gitrekt/resort/model/services/BillService.java @@ -3,6 +3,7 @@ import com.gitrekt.resort.model.entities.Bill; import com.gitrekt.resort.model.entities.BillItem; +import com.gitrekt.resort.model.entities.Booking; import java.awt.print.PrinterException; import java.awt.print.PrinterJob; import java.io.IOException; @@ -12,20 +13,21 @@ public class BillService { - public void printBill(Bill bill) throws IOException, PrinterException { + public void printBillForBooking(Booking booking) + throws IOException, PrinterException { // TODO: Remove test code; + Bill bill = booking.getBill(); for(int i = 0; i < 20; i++) { bill.getCharges().add(new BillItem("Test bill item name printed here", 15.52623, 3)); } BillPdfGenerator pdfGenerator = new BillPdfGenerator(bill); - PDDocument pdf = pdfGenerator.getBillAsPdf(); - - PrinterJob job = PrinterJob.getPrinterJob(); - job.setPrintService(choosePrinter()); - job.setPageable(new PDFPageable(pdf)); - job.print(); - pdf.close(); + try (PDDocument pdf = pdfGenerator.getBillAsPdf()) { + PrinterJob job = PrinterJob.getPrinterJob(); + job.setPrintService(choosePrinter()); + job.setPageable(new PDFPageable(pdf)); + job.print(); + } } public static PrintService choosePrinter() { diff --git a/src/main/resources/fxml/CustomerBillScreen.fxml b/src/main/resources/fxml/CustomerBillScreen.fxml index 6cc0a69..48f6aab 100644 --- a/src/main/resources/fxml/CustomerBillScreen.fxml +++ b/src/main/resources/fxml/CustomerBillScreen.fxml @@ -11,7 +11,7 @@ - + @@ -62,14 +62,6 @@ - - - From d45f909374994d1094efaae1292665a5e1a37470 Mon Sep 17 00:00:00 2001 From: Chris Mailloux Date: Mon, 13 Nov 2017 13:11:06 -0500 Subject: [PATCH 2/5] Fix LazyInitializationException --- .../java/com/gitrekt/resort/model/services/BookingService.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/main/java/com/gitrekt/resort/model/services/BookingService.java b/src/main/java/com/gitrekt/resort/model/services/BookingService.java index bf2ea53..ddf8b9c 100644 --- a/src/main/java/com/gitrekt/resort/model/services/BookingService.java +++ b/src/main/java/com/gitrekt/resort/model/services/BookingService.java @@ -13,7 +13,6 @@ import java.util.List; import javax.mail.MessagingException; import javax.persistence.EntityManager; -import javax.persistence.PersistenceContext; import javax.persistence.PersistenceException; import javax.persistence.Query; @@ -22,7 +21,6 @@ */ public class BookingService { - @PersistenceContext private final EntityManager entityManager; /** From 4cd8db12ed8a144af90d5beedd0972fb83b296ec Mon Sep 17 00:00:00 2001 From: Chris Mailloux Date: Mon, 13 Nov 2017 13:16:05 -0500 Subject: [PATCH 3/5] Actually fix the LazyInitializationException this time --- .../resort/controller/BookingDetailsScreenController.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/com/gitrekt/resort/controller/BookingDetailsScreenController.java b/src/main/java/com/gitrekt/resort/controller/BookingDetailsScreenController.java index 91438a8..788099e 100644 --- a/src/main/java/com/gitrekt/resort/controller/BookingDetailsScreenController.java +++ b/src/main/java/com/gitrekt/resort/controller/BookingDetailsScreenController.java @@ -57,6 +57,10 @@ private void onViewBillButtonClicked() { ); CustomerBillScreenController controller; controller = (CustomerBillScreenController) temp; + + // Fix LazyInitializationException by forcing initialization here. + this.booking.toString(); + controller.initializeData(this.booking); } From dce430a7a7c29a2917d6abb4bdd7feaae566dca7 Mon Sep 17 00:00:00 2001 From: Chris Mailloux Date: Mon, 13 Nov 2017 13:19:48 -0500 Subject: [PATCH 4/5] Okay, I fixed it for real. I swear. --- .../resort/controller/BookingDetailsScreenController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/gitrekt/resort/controller/BookingDetailsScreenController.java b/src/main/java/com/gitrekt/resort/controller/BookingDetailsScreenController.java index 788099e..7ac8de4 100644 --- a/src/main/java/com/gitrekt/resort/controller/BookingDetailsScreenController.java +++ b/src/main/java/com/gitrekt/resort/controller/BookingDetailsScreenController.java @@ -59,7 +59,7 @@ private void onViewBillButtonClicked() { controller = (CustomerBillScreenController) temp; // Fix LazyInitializationException by forcing initialization here. - this.booking.toString(); + System.out.println(this.booking.toString()); controller.initializeData(this.booking); } From 7b2b088fd93315bb058991c5bda5a589deb83321 Mon Sep 17 00:00:00 2001 From: Chris Mailloux Date: Mon, 13 Nov 2017 17:42:36 -0500 Subject: [PATCH 5/5] Implement view guest bill screen logic All business logic is implemented for this screen now. Note that the screen is currently populated with test data just for demo purposes. The actual logic to display the real bill items IS in place and working, but because the necessary driving logic is incomplete, the test logic has been left as well. It will be removed in time. Just know that the current implementation does show the actual bill items properly, in addition to generating a large number of 'fake' test items. --- .../CustomerBillScreenController.java | 47 ++++++++++++++----- .../model/services/BillPdfGenerator.java | 14 ++++++ .../resort/model/services/BillService.java | 34 ++++++++++---- .../resources/fxml/CustomerBillScreen.fxml | 10 ++-- 4 files changed, 79 insertions(+), 26 deletions(-) diff --git a/src/main/java/com/gitrekt/resort/controller/CustomerBillScreenController.java b/src/main/java/com/gitrekt/resort/controller/CustomerBillScreenController.java index c8cd042..6ace495 100644 --- a/src/main/java/com/gitrekt/resort/controller/CustomerBillScreenController.java +++ b/src/main/java/com/gitrekt/resort/controller/CustomerBillScreenController.java @@ -1,14 +1,17 @@ package com.gitrekt.resort.controller; -import com.gitrekt.resort.model.entities.Bill; import com.gitrekt.resort.model.entities.BillItem; import com.gitrekt.resort.model.entities.Booking; import com.gitrekt.resort.model.services.BillService; -import com.gitrekt.resort.model.services.BookingService; import java.awt.print.PrinterException; import java.io.IOException; import java.net.URL; import java.util.ResourceBundle; +import java.util.concurrent.ThreadLocalRandom; +import javafx.beans.property.SimpleIntegerProperty; +import javafx.beans.property.SimpleStringProperty; +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; import javafx.fxml.FXML; import javafx.fxml.Initializable; import javafx.scene.control.Label; @@ -26,33 +29,48 @@ public class CustomerBillScreenController implements Initializable { @FXML private Label customerNameText; - @FXML - private Label billingPeriodText; - @FXML private Label bookingNumberText; - // TODO: Fix rawtype @FXML - private TableView billTable; + private TableView billTable; @FXML - private TableColumn itemNameColumn; + private TableColumn itemNameColumn; @FXML - private TableColumn qtyColumn; + private TableColumn qtyColumn; @FXML - private TableColumn priceColumn; + private TableColumn priceColumn; private Booking booking; + private ObservableList billItems; + /** * Initializes the controller class. */ @Override public void initialize(URL url, ResourceBundle rb) { - // TODO + billItems = FXCollections.observableArrayList(); + + itemNameColumn.setCellValueFactory((param) -> { + return new SimpleStringProperty(param.getValue().getName()); + }); + + qtyColumn.setCellValueFactory((param) -> { + return new SimpleIntegerProperty(param.getValue().getQuantity()) + .asObject(); + }); + + priceColumn.setCellValueFactory((param) -> { + return new SimpleStringProperty( + String.format("%.2f", param.getValue().getTotalPrice()) + ); + }); + + billTable.setItems(billItems); } /** @@ -71,8 +89,13 @@ public void initializeData(Booking booking) { this.booking = booking; // TODO: Remove test code - booking.getBill().getCharges().add(new BillItem("Test bill item", 15.99, 1)); + for(int i = 0; i < 30; i++) { + double price = ThreadLocalRandom.current().nextDouble(0,500); + int qty = ThreadLocalRandom.current().nextInt(10); + booking.getBill().getCharges().add(new BillItem("Test bill item", price, qty)); + } + billItems.addAll(booking.getBill().getCharges()); initializeInfoLabels(); prepareTableView(); } diff --git a/src/main/java/com/gitrekt/resort/model/services/BillPdfGenerator.java b/src/main/java/com/gitrekt/resort/model/services/BillPdfGenerator.java index c043b58..5a12095 100644 --- a/src/main/java/com/gitrekt/resort/model/services/BillPdfGenerator.java +++ b/src/main/java/com/gitrekt/resort/model/services/BillPdfGenerator.java @@ -13,6 +13,12 @@ import org.apache.pdfbox.pdmodel.font.PDFont; import org.apache.pdfbox.pdmodel.font.PDType1Font; +/** + * Responsible for generating a PDF representation of the guest bill. + * + * Currently very crude and incomplete, although the most basic functionality + * is in place and usable. This class still needs a lot of work. + */ public class BillPdfGenerator { private static final String LINE_ITEM_FORMAT = "%-40s %11s %13s %13s"; @@ -105,6 +111,14 @@ private String getBillTotalLine() { ); } + /** + * Gathers the fields from the guest bill items and converts them into their + * formatted string representation to be displayed as a single line-item + * on the printed guest bill. + * + * @param item The bill item to format. + * @return The formatted bill item. + */ private String convertBillItemToLineItem(BillItem item) { String lineItem; double totalPrice = item.getPrice() * item.getQuantity(); diff --git a/src/main/java/com/gitrekt/resort/model/services/BillService.java b/src/main/java/com/gitrekt/resort/model/services/BillService.java index f2b37e4..9552003 100644 --- a/src/main/java/com/gitrekt/resort/model/services/BillService.java +++ b/src/main/java/com/gitrekt/resort/model/services/BillService.java @@ -1,8 +1,5 @@ - package com.gitrekt.resort.model.services; -import com.gitrekt.resort.model.entities.Bill; -import com.gitrekt.resort.model.entities.BillItem; import com.gitrekt.resort.model.entities.Booking; import java.awt.print.PrinterException; import java.awt.print.PrinterJob; @@ -11,17 +8,26 @@ import org.apache.pdfbox.pdmodel.PDDocument; import org.apache.pdfbox.printing.PDFPageable; +/** + * This class is responsible for handling all business logic related to bills. + * + * At the moment, the only real business logic that belongs here is printing + * related, though this may change in the future as features are implemented. + */ public class BillService { + /** + * Prints the bill associated with the provided booking on a printer. + * + * @param booking The booking to print the bill for. + * + * @throws IOException + * @throws PrinterException + */ public void printBillForBooking(Booking booking) throws IOException, PrinterException { - // TODO: Remove test code; - Bill bill = booking.getBill(); - for(int i = 0; i < 20; i++) { - bill.getCharges().add(new BillItem("Test bill item name printed here", 15.52623, 3)); - } - BillPdfGenerator pdfGenerator = new BillPdfGenerator(bill); + BillPdfGenerator pdfGenerator = new BillPdfGenerator(booking.getBill()); try (PDDocument pdf = pdfGenerator.getBillAsPdf()) { PrinterJob job = PrinterJob.getPrinterJob(); job.setPrintService(choosePrinter()); @@ -30,6 +36,16 @@ public void printBillForBooking(Booking booking) } } + /** + * Prompts the user to choose a printer to print from, using a standard + * dialog box. + * + * The user is also able to selected from other properties such as the + * number of copies to print, collation, etc., independently of our + * software. + * + * @return The PrintService (a.k.a the printer) selected by the user. + */ public static PrintService choosePrinter() { PrinterJob printJob = PrinterJob.getPrinterJob(); if(printJob.printDialog()) { diff --git a/src/main/resources/fxml/CustomerBillScreen.fxml b/src/main/resources/fxml/CustomerBillScreen.fxml index 48f6aab..80ab3d6 100644 --- a/src/main/resources/fxml/CustomerBillScreen.fxml +++ b/src/main/resources/fxml/CustomerBillScreen.fxml @@ -11,9 +11,9 @@ - + - + @@ -69,11 +69,11 @@ - + - - + +