resolve merge conflict
This commit is contained in:
@@ -16,6 +16,7 @@ import org.example.petshopdesktop.api.endpoints.AdoptionApi;
|
||||
import org.example.petshopdesktop.controllers.dialogcontrollers.AdoptionDialogController;
|
||||
import org.example.petshopdesktop.models.Adoption;
|
||||
import org.example.petshopdesktop.util.ActivityLogger;
|
||||
import org.example.petshopdesktop.util.TableViewSupport;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Comparator;
|
||||
@@ -34,6 +35,12 @@ public class AdoptionController {
|
||||
@FXML
|
||||
private Button btnEdit;
|
||||
|
||||
@FXML
|
||||
private Button btnRefresh;
|
||||
|
||||
@FXML
|
||||
private Label lblStatus;
|
||||
|
||||
@FXML
|
||||
private TableColumn<Adoption, Integer> colAdoptionId;
|
||||
|
||||
@@ -78,8 +85,10 @@ public class AdoptionController {
|
||||
colAdoptionDate.setCellValueFactory(new PropertyValueFactory<>("adoptionDate"));
|
||||
colAdoptionFee.setCellValueFactory(new PropertyValueFactory<>("adoptionFee"));
|
||||
colAdoptionStatus.setCellValueFactory(new PropertyValueFactory<>("adoptionStatus"));
|
||||
TableViewSupport.applyCurrencyColumn(colAdoptionFee);
|
||||
|
||||
displayAdoptions();
|
||||
TableViewSupport.installDoubleClickAction(tvAdoptions, selected -> openDialog(selected, "Edit"));
|
||||
|
||||
tvAdoptions.getSelectionModel().selectedItemProperty().addListener(
|
||||
(observable, oldValue, newValue) -> {
|
||||
@@ -101,6 +110,14 @@ public class AdoptionController {
|
||||
});
|
||||
}
|
||||
|
||||
@FXML
|
||||
void btnRefresh(ActionEvent event) {
|
||||
txtSearch.clear();
|
||||
tvAdoptions.getSortOrder().clear();
|
||||
displayAdoptions();
|
||||
TableViewSupport.flashStatus(lblStatus, "Refreshed");
|
||||
}
|
||||
|
||||
@FXML
|
||||
void btnAddClicked(ActionEvent event) {
|
||||
mode = "Add";
|
||||
|
||||
@@ -6,6 +6,8 @@ import javafx.fxml.FXML;
|
||||
import javafx.scene.chart.*;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.Tab;
|
||||
import javafx.scene.control.TabPane;
|
||||
import org.example.petshopdesktop.api.dto.analytics.DailySales;
|
||||
import org.example.petshopdesktop.api.dto.analytics.DashboardResponse;
|
||||
import org.example.petshopdesktop.api.dto.analytics.TopProduct;
|
||||
@@ -15,6 +17,7 @@ import org.example.petshopdesktop.api.endpoints.AnalyticsApi;
|
||||
import org.example.petshopdesktop.api.endpoints.SaleApi;
|
||||
import org.example.petshopdesktop.auth.UserSession;
|
||||
import org.example.petshopdesktop.util.ActivityLogger;
|
||||
import org.example.petshopdesktop.util.TableViewSupport;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.RoundingMode;
|
||||
@@ -32,6 +35,9 @@ public class AnalyticsController {
|
||||
@FXML
|
||||
private Button btnRefresh;
|
||||
|
||||
@FXML
|
||||
private Label lblStatus;
|
||||
|
||||
@FXML
|
||||
private Label lblError;
|
||||
|
||||
@@ -65,6 +71,9 @@ public class AnalyticsController {
|
||||
@FXML
|
||||
private BarChart<String, Number> chartEmployeePerformance;
|
||||
|
||||
@FXML
|
||||
private TabPane tabPane;
|
||||
|
||||
private static final String SALES_COLOR = "#ff6b35";
|
||||
private static final String REVENUE_COLOR = "#4ecdc4";
|
||||
private static final String QUANTITY_COLOR = "#ff9f1c";
|
||||
@@ -79,6 +88,13 @@ public class AnalyticsController {
|
||||
@FXML
|
||||
public void initialize() {
|
||||
configureCharts();
|
||||
if (tabPane != null) {
|
||||
tabPane.getSelectionModel().selectedItemProperty().addListener((obs, oldTab, newTab) -> {
|
||||
if (oldTab != newTab && newTab != null) {
|
||||
loadAnalyticsData();
|
||||
}
|
||||
});
|
||||
}
|
||||
loadAnalyticsData();
|
||||
}
|
||||
|
||||
@@ -126,6 +142,9 @@ public class AnalyticsController {
|
||||
|
||||
private void loadAnalyticsData() {
|
||||
lblError.setVisible(false);
|
||||
if (lblStatus != null) {
|
||||
lblStatus.setVisible(false);
|
||||
}
|
||||
new Thread(() -> {
|
||||
try {
|
||||
DashboardResponse dashboard = AnalyticsApi.getInstance().getDashboard(30, 10);
|
||||
@@ -472,5 +491,6 @@ public class AnalyticsController {
|
||||
@FXML
|
||||
void handleRefresh(ActionEvent event) {
|
||||
loadAnalyticsData();
|
||||
TableViewSupport.flashStatus(lblStatus, "Refreshed");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ import org.example.petshopdesktop.api.dto.appointment.AppointmentResponse;
|
||||
import org.example.petshopdesktop.api.endpoints.AppointmentApi;
|
||||
import org.example.petshopdesktop.controllers.dialogcontrollers.AppointmentDialogController;
|
||||
import org.example.petshopdesktop.util.ActivityLogger;
|
||||
import org.example.petshopdesktop.util.TableViewSupport;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Comparator;
|
||||
@@ -39,6 +40,9 @@ public class AppointmentController {
|
||||
@FXML private Button btnAdd;
|
||||
@FXML private Button btnEdit;
|
||||
@FXML private Button btnDelete;
|
||||
@FXML private Button btnRefresh;
|
||||
|
||||
@FXML private Label lblStatus;
|
||||
|
||||
@FXML private TextField txtSearch;
|
||||
|
||||
@@ -61,7 +65,8 @@ public class AppointmentController {
|
||||
colAppointmentStatus.setCellValueFactory(new PropertyValueFactory<>("appointmentStatus"));
|
||||
|
||||
filtered = new FilteredList<>(appointments, a -> true);
|
||||
tvAppointments.setItems(filtered);
|
||||
TableViewSupport.bindSortedItems(tvAppointments, filtered);
|
||||
TableViewSupport.installDoubleClickAction(tvAppointments, selected -> openDialog(selected, "Edit"));
|
||||
|
||||
if (txtSearch != null) {
|
||||
txtSearch.textProperty().addListener((obs, o, n) -> applyFilter(n));
|
||||
@@ -133,6 +138,14 @@ public class AppointmentController {
|
||||
}).start();
|
||||
}
|
||||
|
||||
@FXML
|
||||
void btnRefresh(ActionEvent event) {
|
||||
txtSearch.clear();
|
||||
tvAppointments.getSortOrder().clear();
|
||||
loadAppointments();
|
||||
TableViewSupport.flashStatus(lblStatus, "Refreshed");
|
||||
}
|
||||
|
||||
@FXML
|
||||
void btnAddClicked(ActionEvent event){
|
||||
openDialog(null, "Add");
|
||||
@@ -250,7 +263,20 @@ public class AppointmentController {
|
||||
response.getEmployeeName() != null ? response.getEmployeeName() : "",
|
||||
response.getAppointmentDate() != null ? response.getAppointmentDate().toString() : "",
|
||||
response.getAppointmentTime() != null ? response.getAppointmentTime().toString() : "",
|
||||
response.getAppointmentStatus() != null ? response.getAppointmentStatus() : ""
|
||||
normalizeAppointmentStatus(response.getAppointmentStatus())
|
||||
);
|
||||
}
|
||||
|
||||
private String normalizeAppointmentStatus(String status) {
|
||||
if (status == null) {
|
||||
return "Booked";
|
||||
}
|
||||
return switch (status.trim().toLowerCase()) {
|
||||
case "booked" -> "Booked";
|
||||
case "completed" -> "Completed";
|
||||
case "missed" -> "Missed";
|
||||
case "cancelled", "canceled" -> "Cancelled";
|
||||
default -> "Booked";
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ import org.example.petshopdesktop.api.endpoints.InventoryApi;
|
||||
import org.example.petshopdesktop.controllers.dialogcontrollers.InventoryDialogController;
|
||||
import org.example.petshopdesktop.models.Inventory;
|
||||
import org.example.petshopdesktop.util.ActivityLogger;
|
||||
import org.example.petshopdesktop.util.TableViewSupport;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
@@ -34,6 +35,12 @@ public class InventoryController {
|
||||
@FXML
|
||||
private Button btnEdit;
|
||||
|
||||
@FXML
|
||||
private Button btnRefresh;
|
||||
|
||||
@FXML
|
||||
private Label lblStatus;
|
||||
|
||||
@FXML
|
||||
private TableColumn<Inventory, Integer> colInventoryId;
|
||||
|
||||
@@ -70,6 +77,7 @@ public class InventoryController {
|
||||
colQuantity.setCellValueFactory(new PropertyValueFactory<>("quantity"));
|
||||
|
||||
displayInventory();
|
||||
TableViewSupport.installDoubleClickAction(tvInventory, selected -> openDialog(selected, "Edit"));
|
||||
|
||||
tvInventory.getSelectionModel().selectedItemProperty().addListener(
|
||||
(observable, oldValue, newValue) -> {
|
||||
@@ -92,6 +100,14 @@ public class InventoryController {
|
||||
}
|
||||
|
||||
//Opens dialog in add mode
|
||||
@FXML
|
||||
void btnRefresh(ActionEvent event) {
|
||||
txtSearch.clear();
|
||||
tvInventory.getSortOrder().clear();
|
||||
displayInventory();
|
||||
TableViewSupport.flashStatus(lblStatus, "Refreshed");
|
||||
}
|
||||
|
||||
@FXML
|
||||
void btnAddClicked(ActionEvent event) {
|
||||
mode = "Add";
|
||||
|
||||
@@ -22,6 +22,7 @@ import org.example.petshopdesktop.controllers.dialogcontrollers.PetDialogControl
|
||||
import org.example.petshopdesktop.models.Pet;
|
||||
import org.example.petshopdesktop.util.ActivityLogger;
|
||||
import org.example.petshopdesktop.util.DesktopImageSupport;
|
||||
import org.example.petshopdesktop.util.TableViewSupport;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
@@ -39,6 +40,12 @@ public class PetController {
|
||||
@FXML
|
||||
private Button btnEdit;
|
||||
|
||||
@FXML
|
||||
private Button btnRefresh;
|
||||
|
||||
@FXML
|
||||
private Label lblStatus;
|
||||
|
||||
@FXML
|
||||
private TableColumn<Pet, Integer> colPetAge;
|
||||
|
||||
@@ -81,6 +88,20 @@ public class PetController {
|
||||
@FXML
|
||||
private TextField txtSearch;
|
||||
|
||||
@FXML
|
||||
void btnRefresh(ActionEvent event) {
|
||||
txtSearch.clear();
|
||||
if (cbSpeciesFilter != null) {
|
||||
cbSpeciesFilter.getSelectionModel().selectFirst();
|
||||
}
|
||||
if (cbStatusFilter != null) {
|
||||
cbStatusFilter.getSelectionModel().selectFirst();
|
||||
}
|
||||
tvPets.getSortOrder().clear();
|
||||
displayPets();
|
||||
TableViewSupport.flashStatus(lblStatus, "Refreshed");
|
||||
}
|
||||
|
||||
@FXML
|
||||
void btnAddClicked(ActionEvent event) {
|
||||
mode = "Add";
|
||||
@@ -162,6 +183,7 @@ public class PetController {
|
||||
colPetAge.setCellValueFactory(new PropertyValueFactory<Pet,Integer>("petAge"));
|
||||
colPetStatus.setCellValueFactory(new PropertyValueFactory<Pet,String>("petStatus"));
|
||||
colPetPrice.setCellValueFactory(new PropertyValueFactory<Pet,Double>("petPrice"));
|
||||
TableViewSupport.applyCurrencyColumn(colPetPrice);
|
||||
colCustomerName.setCellValueFactory(new PropertyValueFactory<Pet,String>("customerName"));
|
||||
colStoreName.setCellValueFactory(new PropertyValueFactory<Pet,String>("storeName"));
|
||||
configureImageColumn(colPetImage);
|
||||
@@ -172,6 +194,7 @@ public class PetController {
|
||||
cbStatusFilter.getSelectionModel().selectFirst();
|
||||
|
||||
displayPets();
|
||||
TableViewSupport.installDoubleClickAction(tvPets, selected -> openDialog(selected, "Edit"));
|
||||
|
||||
tvPets.getSelectionModel().selectedItemProperty().addListener(
|
||||
(observable, oldValue, newValue) -> {
|
||||
@@ -357,7 +380,7 @@ public class PetController {
|
||||
setGraphic(null);
|
||||
return;
|
||||
}
|
||||
DesktopImageSupport.loadImageInto(imageView, item, 48, 48);
|
||||
DesktopImageSupport.loadImageInto(imageView, item, 24, 24);
|
||||
setGraphic(container);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -22,6 +22,7 @@ import org.example.petshopdesktop.api.endpoints.ProductApi;
|
||||
import org.example.petshopdesktop.controllers.dialogcontrollers.ProductDialogController;
|
||||
import org.example.petshopdesktop.util.ActivityLogger;
|
||||
import org.example.petshopdesktop.util.DesktopImageSupport;
|
||||
import org.example.petshopdesktop.util.TableViewSupport;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
@@ -43,6 +44,12 @@ public class ProductController {
|
||||
@FXML
|
||||
private Button btnEdit;
|
||||
|
||||
@FXML
|
||||
private Button btnRefresh;
|
||||
|
||||
@FXML
|
||||
private Label lblStatus;
|
||||
|
||||
@FXML
|
||||
private TableColumn<ProductDTO, String> colProductCategory;
|
||||
|
||||
@@ -91,10 +98,12 @@ public class ProductController {
|
||||
colProductPrice.setCellValueFactory(new PropertyValueFactory<ProductDTO,Double>("prodPrice"));
|
||||
colProductCategory.setCellValueFactory(new PropertyValueFactory<ProductDTO,String>("categoryName"));
|
||||
colProductDesc.setCellValueFactory(new PropertyValueFactory<ProductDTO,String>("prodDesc"));
|
||||
TableViewSupport.applyCurrencyColumn(colProductPrice);
|
||||
configureImageColumn(colProductImage);
|
||||
loadCategoryFilter();
|
||||
|
||||
displayProduct();
|
||||
TableViewSupport.installDoubleClickAction(tvProducts, selected -> openDialog(selected, "Edit"));
|
||||
|
||||
//EventListener to Enable buttons when a row is selected
|
||||
tvProducts.getSelectionModel().selectedItemProperty().addListener(
|
||||
@@ -154,6 +163,17 @@ public class ProductController {
|
||||
* open a new dialog for adding a product
|
||||
* @param event click event for button
|
||||
*/
|
||||
@FXML
|
||||
void btnRefresh(ActionEvent event) {
|
||||
txtSearch.clear();
|
||||
if (cbCategoryFilter != null) {
|
||||
cbCategoryFilter.getSelectionModel().selectFirst();
|
||||
}
|
||||
tvProducts.getSortOrder().clear();
|
||||
displayProduct();
|
||||
TableViewSupport.flashStatus(lblStatus, "Refreshed");
|
||||
}
|
||||
|
||||
@FXML
|
||||
void btnAddClicked(ActionEvent event) {
|
||||
mode = "Add";
|
||||
|
||||
@@ -16,6 +16,7 @@ import org.example.petshopdesktop.api.dto.productsupplier.ProductSupplierRespons
|
||||
import org.example.petshopdesktop.api.endpoints.ProductSupplierApi;
|
||||
import org.example.petshopdesktop.controllers.dialogcontrollers.ProductSupplierDialogController;
|
||||
import org.example.petshopdesktop.util.ActivityLogger;
|
||||
import org.example.petshopdesktop.util.TableViewSupport;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
@@ -33,6 +34,12 @@ public class ProductSupplierController {
|
||||
@FXML
|
||||
private Button btnEdit;
|
||||
|
||||
@FXML
|
||||
private Button btnRefresh;
|
||||
|
||||
@FXML
|
||||
private Label lblStatus;
|
||||
|
||||
@FXML
|
||||
private TableColumn<ProductSupplierDTO, Double> colCost;
|
||||
|
||||
@@ -76,6 +83,7 @@ public class ProductSupplierController {
|
||||
colCost.setCellValueFactory(new PropertyValueFactory<ProductSupplierDTO,Double>("cost"));
|
||||
|
||||
displayProductSupplier();
|
||||
TableViewSupport.installDoubleClickAction(tvProductSuppliers, selected -> openDialog(selected, "Edit"));
|
||||
|
||||
//EventListener to Enable buttons when a row is selected
|
||||
tvProductSuppliers.getSelectionModel().selectedItemProperty().addListener(
|
||||
@@ -165,6 +173,14 @@ public class ProductSupplierController {
|
||||
* open a new dialog for adding a productSupplier
|
||||
* @param event click event for button
|
||||
*/
|
||||
@FXML
|
||||
void btnRefresh(ActionEvent event) {
|
||||
txtSearch.clear();
|
||||
tvProductSuppliers.getSortOrder().clear();
|
||||
displayProductSupplier();
|
||||
TableViewSupport.flashStatus(lblStatus, "Refreshed");
|
||||
}
|
||||
|
||||
@FXML
|
||||
void btnAddClicked(ActionEvent event) {
|
||||
mode = "Add";
|
||||
|
||||
@@ -5,13 +5,21 @@ import javafx.collections.FXCollections;
|
||||
import javafx.collections.ObservableList;
|
||||
import javafx.collections.transformation.FilteredList;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.fxml.FXMLLoader;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.scene.control.*;
|
||||
import javafx.scene.control.cell.PropertyValueFactory;
|
||||
import org.example.petshopdesktop.DTOs.PurchaseOrderDTO;
|
||||
import org.example.petshopdesktop.api.dto.purchaseorder.PurchaseOrderResponse;
|
||||
import org.example.petshopdesktop.api.endpoints.PurchaseOrderApi;
|
||||
import org.example.petshopdesktop.controllers.dialogcontrollers.PurchaseOrderDetailsDialogController;
|
||||
import org.example.petshopdesktop.util.ActivityLogger;
|
||||
import org.example.petshopdesktop.util.TableViewSupport;
|
||||
|
||||
import javafx.stage.Modality;
|
||||
import javafx.stage.Stage;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Comparator;
|
||||
import java.util.stream.Collectors;
|
||||
@@ -20,6 +28,8 @@ public class PurchaseOrderController {
|
||||
|
||||
@FXML private Button btnRefresh;
|
||||
|
||||
@FXML private Label lblStatus;
|
||||
|
||||
@FXML
|
||||
private TextField txtSearch;
|
||||
|
||||
@@ -49,7 +59,8 @@ public class PurchaseOrderController {
|
||||
new PropertyValueFactory<>("status"));
|
||||
|
||||
filtered = new FilteredList<>(purchaseOrders, p -> true);
|
||||
tvPurchaseOrders.setItems(filtered);
|
||||
TableViewSupport.bindSortedItems(tvPurchaseOrders, filtered);
|
||||
TableViewSupport.installDoubleClickAction(tvPurchaseOrders, this::openDetailsDialog);
|
||||
|
||||
if (txtSearch != null) {
|
||||
txtSearch.textProperty().addListener((obs, o, n) -> applyFilter(n));
|
||||
@@ -69,7 +80,6 @@ public class PurchaseOrderController {
|
||||
|
||||
Platform.runLater(() -> {
|
||||
purchaseOrders.setAll(dtos);
|
||||
tvPurchaseOrders.setItems(filtered);
|
||||
});
|
||||
} catch (Exception e) {
|
||||
Platform.runLater(() -> {
|
||||
@@ -109,7 +119,34 @@ public class PurchaseOrderController {
|
||||
|
||||
@FXML
|
||||
void btnRefresh() {
|
||||
if (txtSearch != null) {
|
||||
txtSearch.clear();
|
||||
}
|
||||
TableViewSupport.clearSort(tvPurchaseOrders);
|
||||
loadPurchaseOrders();
|
||||
TableViewSupport.flashStatus(lblStatus, "Refreshed");
|
||||
}
|
||||
|
||||
private void openDetailsDialog(PurchaseOrderDTO selected) {
|
||||
try {
|
||||
FXMLLoader loader = new FXMLLoader(getClass().getResource("/org/example/petshopdesktop/dialogviews/purchase-order-details-dialog-view.fxml"));
|
||||
Stage dialog = new Stage();
|
||||
dialog.initModality(Modality.APPLICATION_MODAL);
|
||||
dialog.setTitle("Purchase Order Details");
|
||||
dialog.setScene(new Scene(loader.load()));
|
||||
PurchaseOrderDetailsDialogController controller = loader.getController();
|
||||
controller.displayPurchaseOrder(selected);
|
||||
controller.setCloseAction(() -> dialog.close());
|
||||
dialog.initOwner(tvPurchaseOrders.getScene().getWindow());
|
||||
dialog.setResizable(false);
|
||||
dialog.showAndWait();
|
||||
} catch (IOException e) {
|
||||
ActivityLogger.getInstance().logException(
|
||||
"PurchaseOrderController.openDetailsDialog",
|
||||
e,
|
||||
"Opening purchase order details");
|
||||
new Alert(Alert.AlertType.ERROR, "Unable to open purchase order details").showAndWait();
|
||||
}
|
||||
}
|
||||
|
||||
private PurchaseOrderDTO mapToPurchaseOrderDTO(PurchaseOrderResponse response) {
|
||||
|
||||
@@ -7,7 +7,6 @@ import javafx.event.ActionEvent;
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.fxml.FXMLLoader;
|
||||
import javafx.application.Platform;
|
||||
import javafx.scene.input.MouseButton;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.scene.control.Alert;
|
||||
import javafx.scene.control.Button;
|
||||
@@ -37,6 +36,7 @@ import org.example.petshopdesktop.models.SaleCartItem;
|
||||
import org.example.petshopdesktop.models.SaleDetail;
|
||||
import org.example.petshopdesktop.models.SaleLineItem;
|
||||
import org.example.petshopdesktop.util.ActivityLogger;
|
||||
import org.example.petshopdesktop.util.TableViewSupport;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.text.NumberFormat;
|
||||
@@ -51,6 +51,9 @@ public class SaleController {
|
||||
@FXML
|
||||
private Button btnRefresh;
|
||||
|
||||
@FXML
|
||||
private Label lblStatus;
|
||||
|
||||
@FXML
|
||||
private Button btnRefund;
|
||||
|
||||
@@ -153,10 +156,12 @@ public class SaleController {
|
||||
colCartQty.setCellValueFactory(new PropertyValueFactory<>("quantity"));
|
||||
colCartUnitPrice.setCellValueFactory(new PropertyValueFactory<>("unitPrice"));
|
||||
colCartTotal.setCellValueFactory(new PropertyValueFactory<>("total"));
|
||||
TableViewSupport.applyCurrencyColumn(colCartUnitPrice);
|
||||
TableViewSupport.applyCurrencyColumn(colCartTotal);
|
||||
tvCart.setItems(cartItems);
|
||||
tvCart.getSelectionModel().setSelectionMode(SelectionMode.SINGLE);
|
||||
|
||||
tvSales.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY);
|
||||
tvSales.setColumnResizePolicy(TableView.UNCONSTRAINED_RESIZE_POLICY);
|
||||
tvSales.setFixedCellSize(34);
|
||||
colSaleId.setCellValueFactory(new PropertyValueFactory<>("saleId"));
|
||||
colSaleDate.setCellValueFactory(new PropertyValueFactory<>("saleDate"));
|
||||
@@ -166,18 +171,12 @@ public class SaleController {
|
||||
colSaleUnitPrice.setCellValueFactory(new PropertyValueFactory<>("unitPrice"));
|
||||
colSaleTotal.setCellValueFactory(new PropertyValueFactory<>("total"));
|
||||
colSalePaymentType.setCellValueFactory(new PropertyValueFactory<>("paymentMethod"));
|
||||
TableViewSupport.applyCurrencyColumn(colSaleUnitPrice);
|
||||
TableViewSupport.applyCurrencyColumn(colSaleTotal);
|
||||
|
||||
filteredSales = new FilteredList<>(saleItems, s -> true);
|
||||
tvSales.setItems(filteredSales);
|
||||
|
||||
tvSales.setOnMouseClicked(event -> {
|
||||
if (event.getButton() == MouseButton.PRIMARY && event.getClickCount() == 2) {
|
||||
SaleLineItem selected = tvSales.getSelectionModel().getSelectedItem();
|
||||
if (selected != null) {
|
||||
openSaleDetailDialog(selected.getSaleId());
|
||||
}
|
||||
}
|
||||
});
|
||||
TableViewSupport.bindSortedItems(tvSales, filteredSales);
|
||||
TableViewSupport.installDoubleClickAction(tvSales, selected -> openSaleDetailDialog(selected.getSaleId()));
|
||||
|
||||
txtSearch.textProperty().addListener((obs, oldVal, newVal) -> applySalesFilter(newVal));
|
||||
}
|
||||
@@ -300,7 +299,10 @@ public class SaleController {
|
||||
|
||||
@FXML
|
||||
void btnRefresh(ActionEvent event) {
|
||||
refreshSales(true);
|
||||
txtSearch.clear();
|
||||
TableViewSupport.clearSort(tvSales);
|
||||
refreshSales(false);
|
||||
TableViewSupport.flashStatus(lblStatus, "Refreshed");
|
||||
}
|
||||
|
||||
@FXML
|
||||
@@ -433,10 +435,11 @@ public class SaleController {
|
||||
|
||||
@FXML
|
||||
void btnRefund(ActionEvent event) {
|
||||
openRefundDialog();
|
||||
SaleLineItem selectedSale = tvSales.getSelectionModel().getSelectedItem();
|
||||
openRefundDialog(selectedSale != null ? (long) selectedSale.getSaleId() : null);
|
||||
}
|
||||
|
||||
private void openRefundDialog() {
|
||||
private void openRefundDialog(Long saleId) {
|
||||
try {
|
||||
SaleLineItem selectedSale = tvSales.getSelectionModel().getSelectedItem();
|
||||
if (selectedSale != null && selectedSale.isRefund()) {
|
||||
@@ -452,8 +455,8 @@ public class SaleController {
|
||||
dialog.setTitle("Process Refund");
|
||||
dialog.setScene(new Scene(loader.load()));
|
||||
var controller = loader.<org.example.petshopdesktop.controllers.dialogcontrollers.RefundDialogController>getController();
|
||||
if (selectedSale != null) {
|
||||
controller.prefillSale((long) selectedSale.getSaleId());
|
||||
if (saleId != null) {
|
||||
controller.prefillSale(saleId);
|
||||
}
|
||||
dialog.setMinWidth(860);
|
||||
dialog.setMinHeight(680);
|
||||
@@ -485,6 +488,8 @@ public class SaleController {
|
||||
dialog.setTitle("Sale Details");
|
||||
dialog.setScene(new Scene(loader.load()));
|
||||
var controller = (org.example.petshopdesktop.controllers.dialogcontrollers.SaleDetailDialogController) loader.getController();
|
||||
controller.setSaleId((long) sale.getSaleId());
|
||||
controller.setRefundAction(this::openRefundDialog);
|
||||
controller.displaySaleDetails(mapToSaleDetail(sale));
|
||||
dialog.setResizable(false);
|
||||
dialog.showAndWait();
|
||||
@@ -528,6 +533,7 @@ public class SaleController {
|
||||
sale.getTotalAmount() != null ? sale.getTotalAmount().doubleValue() : 0.0,
|
||||
sale.getPaymentMethod(),
|
||||
sale.getEmployeeName(),
|
||||
Boolean.TRUE.equals(sale.getIsRefund()),
|
||||
items
|
||||
);
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ import org.example.petshopdesktop.api.dto.service.ServiceResponse;
|
||||
import org.example.petshopdesktop.api.endpoints.ServiceApi;
|
||||
import org.example.petshopdesktop.controllers.dialogcontrollers.ServiceDialogController;
|
||||
import org.example.petshopdesktop.util.ActivityLogger;
|
||||
import org.example.petshopdesktop.util.TableViewSupport;
|
||||
import javafx.stage.Modality;
|
||||
|
||||
import java.util.List;
|
||||
@@ -27,6 +28,9 @@ public class ServiceController {
|
||||
@FXML private Button btnAdd;
|
||||
@FXML private Button btnDelete;
|
||||
@FXML private Button btnEdit;
|
||||
@FXML private Button btnRefresh;
|
||||
|
||||
@FXML private Label lblStatus;
|
||||
|
||||
@FXML private TableColumn<ServiceDTO, Integer> colServiceId;
|
||||
@FXML private TableColumn<ServiceDTO, String> colServiceName;
|
||||
@@ -52,8 +56,10 @@ public class ServiceController {
|
||||
colServiceDesc.setCellValueFactory(new PropertyValueFactory<>("serviceDesc"));
|
||||
colServiceDuration.setCellValueFactory(new PropertyValueFactory<>("serviceDuration"));
|
||||
colServicePrice.setCellValueFactory(new PropertyValueFactory<>("servicePrice"));
|
||||
TableViewSupport.applyCurrencyColumn(colServicePrice);
|
||||
|
||||
displayServices();
|
||||
TableViewSupport.installDoubleClickAction(tvServices, selected -> openDialog(selected, "Edit"));
|
||||
|
||||
tvServices.getSelectionModel().selectedItemProperty().addListener(
|
||||
(observable, oldValue, newValue) -> {
|
||||
@@ -129,6 +135,14 @@ public class ServiceController {
|
||||
}
|
||||
|
||||
|
||||
@FXML
|
||||
void btnRefresh(ActionEvent event) {
|
||||
txtSearch.clear();
|
||||
tvServices.getSortOrder().clear();
|
||||
displayServices();
|
||||
TableViewSupport.flashStatus(lblStatus, "Refreshed");
|
||||
}
|
||||
|
||||
@FXML
|
||||
void btnAddClicked(ActionEvent event) {
|
||||
mode = "Add";
|
||||
|
||||
@@ -20,6 +20,7 @@ import org.example.petshopdesktop.api.endpoints.UserApi;
|
||||
import org.example.petshopdesktop.api.endpoints.CustomerApi;
|
||||
import org.example.petshopdesktop.auth.UserSession;
|
||||
import org.example.petshopdesktop.util.ActivityLogger;
|
||||
import org.example.petshopdesktop.util.TableViewSupport;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Comparator;
|
||||
@@ -57,6 +58,12 @@ public class StaffAccountsController {
|
||||
@FXML
|
||||
private Label lblError;
|
||||
|
||||
@FXML
|
||||
private Label lblStatus;
|
||||
|
||||
@FXML
|
||||
private Button btnRefresh;
|
||||
|
||||
@FXML
|
||||
private Button btnCreateAccount;
|
||||
|
||||
@@ -77,7 +84,8 @@ public class StaffAccountsController {
|
||||
colCreated.setCellValueFactory(data -> new javafx.beans.property.SimpleObjectProperty<>(data.getValue().getCreatedAt()));
|
||||
|
||||
filtered = new FilteredList<>(staffAccounts, a -> true);
|
||||
tvStaff.setItems(filtered);
|
||||
TableViewSupport.bindSortedItems(tvStaff, filtered);
|
||||
TableViewSupport.installDoubleClickAction(tvStaff, this::openEditDialog);
|
||||
|
||||
txtSearch.textProperty().addListener((obs, o, n) -> applyFilter(n));
|
||||
|
||||
@@ -96,7 +104,10 @@ public class StaffAccountsController {
|
||||
|
||||
@FXML
|
||||
void btnRefreshClicked(ActionEvent event) {
|
||||
txtSearch.clear();
|
||||
TableViewSupport.clearSort(tvStaff);
|
||||
refresh();
|
||||
TableViewSupport.flashStatus(lblStatus, "Refreshed");
|
||||
}
|
||||
|
||||
@FXML
|
||||
@@ -122,6 +133,10 @@ public class StaffAccountsController {
|
||||
void btnEditAccountClicked(ActionEvent event) {
|
||||
lblError.setText("");
|
||||
UserResponse selected = tvStaff.getSelectionModel().getSelectedItem();
|
||||
openEditDialog(selected);
|
||||
}
|
||||
|
||||
private void openEditDialog(UserResponse selected) {
|
||||
if (selected == null) {
|
||||
lblError.setText("Select a user account to edit.");
|
||||
return;
|
||||
|
||||
@@ -16,6 +16,7 @@ import org.example.petshopdesktop.api.endpoints.SupplierApi;
|
||||
import org.example.petshopdesktop.controllers.dialogcontrollers.SupplierDialogController;
|
||||
import org.example.petshopdesktop.models.Supplier;
|
||||
import org.example.petshopdesktop.util.ActivityLogger;
|
||||
import org.example.petshopdesktop.util.TableViewSupport;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
@@ -36,6 +37,12 @@ public class SupplierController {
|
||||
@FXML
|
||||
private Button btnEdit;
|
||||
|
||||
@FXML
|
||||
private Button btnRefresh;
|
||||
|
||||
@FXML
|
||||
private Label lblStatus;
|
||||
|
||||
@FXML
|
||||
private TableColumn<Supplier, String> colContactPerson;
|
||||
|
||||
@@ -78,6 +85,7 @@ public class SupplierController {
|
||||
colSupplierPhone.setCellValueFactory(new PropertyValueFactory<Supplier, String>("supPhone"));
|
||||
|
||||
displaySupplier();
|
||||
TableViewSupport.installDoubleClickAction(tvSuppliers, selected -> openDialog(selected, "Edit"));
|
||||
|
||||
//EventListener to Enable buttons when a row is selected
|
||||
tvSuppliers.getSelectionModel().selectedItemProperty().addListener(
|
||||
@@ -168,6 +176,14 @@ public class SupplierController {
|
||||
* open a new dialog for adding a supplier
|
||||
* @param event click event for button
|
||||
*/
|
||||
@FXML
|
||||
void btnRefresh(ActionEvent event) {
|
||||
txtSearch.clear();
|
||||
tvSuppliers.getSortOrder().clear();
|
||||
displaySupplier();
|
||||
TableViewSupport.flashStatus(lblStatus, "Refreshed");
|
||||
}
|
||||
|
||||
@FXML
|
||||
void btnAddClicked(ActionEvent event) {
|
||||
mode = "Add";
|
||||
|
||||
@@ -265,6 +265,7 @@ public class AdoptionDialogController {
|
||||
if (adoption != null) {
|
||||
selectedAdoption = adoption;
|
||||
lblAdoptionId.setText("ID: " + adoption.getAdoptionId());
|
||||
ensureSelectedEmployeeOption(cbEmployee.getItems());
|
||||
applySelectedPet();
|
||||
applySelectedCustomer();
|
||||
applySelectedEmployee();
|
||||
|
||||
@@ -49,7 +49,7 @@ public class AppointmentDialogController {
|
||||
|
||||
private ObservableList<String> statusList =
|
||||
FXCollections.observableArrayList(
|
||||
"Booked", "Completed", "Cancelled", "Missed"
|
||||
"Booked", "Completed", "Missed", "Cancelled"
|
||||
);
|
||||
|
||||
public void setMode(String mode) {
|
||||
@@ -83,6 +83,36 @@ public class AppointmentDialogController {
|
||||
|
||||
cbMinute.getItems().addAll(0, 15, 30, 45);
|
||||
|
||||
cbHour.setCellFactory(param -> new ListCell<>() {
|
||||
@Override
|
||||
protected void updateItem(Integer option, boolean empty) {
|
||||
super.updateItem(option, empty);
|
||||
setText(empty || option == null ? null : String.valueOf(option));
|
||||
}
|
||||
});
|
||||
cbHour.setButtonCell(new ListCell<>() {
|
||||
@Override
|
||||
protected void updateItem(Integer option, boolean empty) {
|
||||
super.updateItem(option, empty);
|
||||
setText(empty || option == null ? null : String.valueOf(option));
|
||||
}
|
||||
});
|
||||
|
||||
cbMinute.setCellFactory(param -> new ListCell<>() {
|
||||
@Override
|
||||
protected void updateItem(Integer option, boolean empty) {
|
||||
super.updateItem(option, empty);
|
||||
setText(empty || option == null ? null : String.format("%02d", option));
|
||||
}
|
||||
});
|
||||
cbMinute.setButtonCell(new ListCell<>() {
|
||||
@Override
|
||||
protected void updateItem(Integer option, boolean empty) {
|
||||
super.updateItem(option, empty);
|
||||
setText(empty || option == null ? null : String.format("%02d", option));
|
||||
}
|
||||
});
|
||||
|
||||
cbService.setCellFactory(param -> new ListCell<>() {
|
||||
@Override
|
||||
protected void updateItem(DropdownOption option, boolean empty) {
|
||||
@@ -182,7 +212,7 @@ public class AppointmentDialogController {
|
||||
"Parsing appointment date");
|
||||
}
|
||||
|
||||
cbAppointmentStatus.setValue(appt.getAppointmentStatus());
|
||||
cbAppointmentStatus.setValue(normalizeAppointmentStatus(appt.getAppointmentStatus()));
|
||||
|
||||
try {
|
||||
LocalTime time = LocalTime.parse(appt.getAppointmentTime());
|
||||
@@ -230,7 +260,7 @@ public class AppointmentDialogController {
|
||||
request.setEmployeeId(cbEmployee.getValue().getId());
|
||||
request.setAppointmentDate(dpAppointmentDate.getValue());
|
||||
request.setAppointmentTime(appointmentTime);
|
||||
request.setAppointmentStatus(cbAppointmentStatus.getValue());
|
||||
request.setAppointmentStatus(normalizeAppointmentStatus(cbAppointmentStatus.getValue()));
|
||||
|
||||
new Thread(() -> {
|
||||
try {
|
||||
@@ -451,4 +481,17 @@ public class AppointmentDialogController {
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
private String normalizeAppointmentStatus(String status) {
|
||||
if (status == null) {
|
||||
return "Booked";
|
||||
}
|
||||
return switch (status.trim().toLowerCase()) {
|
||||
case "booked" -> "Booked";
|
||||
case "completed" -> "Completed";
|
||||
case "missed" -> "Missed";
|
||||
case "cancelled", "canceled" -> "Cancelled";
|
||||
default -> "Booked";
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,9 @@ import org.example.petshopdesktop.api.endpoints.ProductSupplierApi;
|
||||
import org.example.petshopdesktop.util.ActivityLogger;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class ProductSupplierDialogController {
|
||||
|
||||
@@ -49,6 +51,10 @@ public class ProductSupplierDialogController {
|
||||
private int selectedProdId = -1;
|
||||
private Long pendingSupplierId = null;
|
||||
private Long pendingProductId = null;
|
||||
private boolean updatingChoices = false;
|
||||
private ObservableList<DropdownOption> baseSuppliers = FXCollections.observableArrayList();
|
||||
private ObservableList<DropdownOption> baseProducts = FXCollections.observableArrayList();
|
||||
private List<ProductSupplierResponse> relations = List.of();
|
||||
|
||||
/**
|
||||
* add event listeners to buttons and set up combobox
|
||||
@@ -115,20 +121,39 @@ public class ProductSupplierDialogController {
|
||||
}
|
||||
});
|
||||
|
||||
cbProduct.valueProperty().addListener((obs, oldValue, newValue) -> {
|
||||
if (updatingChoices) {
|
||||
return;
|
||||
}
|
||||
filterSuppliersByProduct(newValue != null ? newValue.getId() : null);
|
||||
});
|
||||
|
||||
cbSupplier.valueProperty().addListener((obs, oldValue, newValue) -> {
|
||||
if (updatingChoices) {
|
||||
return;
|
||||
}
|
||||
filterProductsBySupplier(newValue != null ? newValue.getId() : null);
|
||||
});
|
||||
|
||||
new Thread(() -> {
|
||||
try {
|
||||
var productSupplierLinks = ProductSupplierApi.getInstance().listProductSuppliers(null);
|
||||
var suppliers = DropdownApi.getInstance().getSuppliers();
|
||||
var products = DropdownApi.getInstance().getProducts();
|
||||
|
||||
Platform.runLater(() -> {
|
||||
relations = productSupplierLinks != null ? productSupplierLinks : List.of();
|
||||
if (suppliers != null) {
|
||||
cbSupplier.setItems(FXCollections.observableArrayList(suppliers));
|
||||
baseSuppliers = FXCollections.observableArrayList(suppliers);
|
||||
cbSupplier.setItems(FXCollections.observableArrayList(baseSuppliers));
|
||||
applyPendingSupplierSelection();
|
||||
}
|
||||
if (products != null) {
|
||||
cbProduct.setItems(FXCollections.observableArrayList(products));
|
||||
baseProducts = FXCollections.observableArrayList(products);
|
||||
cbProduct.setItems(FXCollections.observableArrayList(baseProducts));
|
||||
applyPendingProductSelection();
|
||||
}
|
||||
applyCurrentFilters();
|
||||
});
|
||||
} catch (Exception e) {
|
||||
Platform.runLater(() -> {
|
||||
@@ -271,7 +296,10 @@ public class ProductSupplierDialogController {
|
||||
}
|
||||
DropdownOption product = findOptionById(cbProduct.getItems(), pendingProductId);
|
||||
if (product != null) {
|
||||
updatingChoices = true;
|
||||
cbProduct.getSelectionModel().select(product);
|
||||
updatingChoices = false;
|
||||
filterSuppliersByProduct(product.getId());
|
||||
pendingProductId = null;
|
||||
}
|
||||
}
|
||||
@@ -282,11 +310,73 @@ public class ProductSupplierDialogController {
|
||||
}
|
||||
DropdownOption supplier = findOptionById(cbSupplier.getItems(), pendingSupplierId);
|
||||
if (supplier != null) {
|
||||
updatingChoices = true;
|
||||
cbSupplier.getSelectionModel().select(supplier);
|
||||
updatingChoices = false;
|
||||
filterProductsBySupplier(supplier.getId());
|
||||
pendingSupplierId = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void applyCurrentFilters() {
|
||||
DropdownOption selectedProduct = cbProduct.getSelectionModel().getSelectedItem();
|
||||
DropdownOption selectedSupplier = cbSupplier.getSelectionModel().getSelectedItem();
|
||||
filterSuppliersByProduct(selectedProduct != null ? selectedProduct.getId() : null);
|
||||
filterProductsBySupplier(selectedSupplier != null ? selectedSupplier.getId() : null);
|
||||
}
|
||||
|
||||
private void filterSuppliersByProduct(Long productId) {
|
||||
updatingChoices = true;
|
||||
try {
|
||||
if (productId == null) {
|
||||
cbSupplier.setItems(FXCollections.observableArrayList(baseSuppliers));
|
||||
return;
|
||||
}
|
||||
Set<Long> allowedSupplierIds = new HashSet<>();
|
||||
for (ProductSupplierResponse relation : relations) {
|
||||
if (relation.getProductId() != null && relation.getProductId().equals(productId) && relation.getSupplierId() != null) {
|
||||
allowedSupplierIds.add(relation.getSupplierId());
|
||||
}
|
||||
}
|
||||
ObservableList<DropdownOption> filtered = FXCollections.observableArrayList(
|
||||
baseSuppliers.stream().filter(option -> option.getId() != null && allowedSupplierIds.contains(option.getId())).toList()
|
||||
);
|
||||
cbSupplier.setItems(filtered);
|
||||
DropdownOption selectedSupplier = cbSupplier.getSelectionModel().getSelectedItem();
|
||||
if (selectedSupplier != null && !allowedSupplierIds.contains(selectedSupplier.getId())) {
|
||||
cbSupplier.getSelectionModel().clearSelection();
|
||||
}
|
||||
} finally {
|
||||
updatingChoices = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void filterProductsBySupplier(Long supplierId) {
|
||||
updatingChoices = true;
|
||||
try {
|
||||
if (supplierId == null) {
|
||||
cbProduct.setItems(FXCollections.observableArrayList(baseProducts));
|
||||
return;
|
||||
}
|
||||
Set<Long> allowedProductIds = new HashSet<>();
|
||||
for (ProductSupplierResponse relation : relations) {
|
||||
if (relation.getSupplierId() != null && relation.getSupplierId().equals(supplierId) && relation.getProductId() != null) {
|
||||
allowedProductIds.add(relation.getProductId());
|
||||
}
|
||||
}
|
||||
ObservableList<DropdownOption> filtered = FXCollections.observableArrayList(
|
||||
baseProducts.stream().filter(option -> option.getId() != null && allowedProductIds.contains(option.getId())).toList()
|
||||
);
|
||||
cbProduct.setItems(filtered);
|
||||
DropdownOption selectedProduct = cbProduct.getSelectionModel().getSelectedItem();
|
||||
if (selectedProduct != null && !allowedProductIds.contains(selectedProduct.getId())) {
|
||||
cbProduct.getSelectionModel().clearSelection();
|
||||
}
|
||||
} finally {
|
||||
updatingChoices = false;
|
||||
}
|
||||
}
|
||||
|
||||
private DropdownOption findOptionById(List<DropdownOption> options, Long id) {
|
||||
if (options == null || id == null) {
|
||||
return null;
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
package org.example.petshopdesktop.controllers.dialogcontrollers;
|
||||
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.stage.Stage;
|
||||
import org.example.petshopdesktop.DTOs.PurchaseOrderDTO;
|
||||
|
||||
public class PurchaseOrderDetailsDialogController {
|
||||
|
||||
@FXML private Label lblOrderId;
|
||||
@FXML private Label lblSupplier;
|
||||
@FXML private Label lblOrderDate;
|
||||
@FXML private Label lblStatus;
|
||||
|
||||
private Runnable closeAction;
|
||||
|
||||
public void displayPurchaseOrder(PurchaseOrderDTO order) {
|
||||
if (order == null) {
|
||||
return;
|
||||
}
|
||||
lblOrderId.setText(String.valueOf(order.getPurchaseOrderId()));
|
||||
lblSupplier.setText(order.getSupplierName() != null ? order.getSupplierName() : "");
|
||||
lblOrderDate.setText(order.getOrderDate() != null ? order.getOrderDate() : "");
|
||||
lblStatus.setText(order.getStatus() != null ? order.getStatus() : "");
|
||||
}
|
||||
|
||||
public void setCloseAction(Runnable closeAction) {
|
||||
this.closeAction = closeAction;
|
||||
}
|
||||
|
||||
@FXML
|
||||
void btnCloseClicked() {
|
||||
if (closeAction != null) {
|
||||
closeAction.run();
|
||||
return;
|
||||
}
|
||||
Stage stage = (Stage) lblOrderId.getScene().getWindow();
|
||||
stage.close();
|
||||
}
|
||||
}
|
||||
@@ -2,11 +2,19 @@ package org.example.petshopdesktop.controllers.dialogcontrollers;
|
||||
|
||||
import javafx.fxml.FXML;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.Button;
|
||||
import javafx.scene.control.TableColumn;
|
||||
import javafx.scene.control.TableView;
|
||||
import javafx.scene.control.cell.PropertyValueFactory;
|
||||
import javafx.stage.Stage;
|
||||
import org.example.petshopdesktop.models.SaleDetail;
|
||||
import org.example.petshopdesktop.controllers.dialogcontrollers.RefundDialogController;
|
||||
import javafx.fxml.FXMLLoader;
|
||||
import javafx.scene.Scene;
|
||||
import javafx.stage.Modality;
|
||||
import org.example.petshopdesktop.util.ActivityLogger;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
import java.text.NumberFormat;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
@@ -19,6 +27,7 @@ public class SaleDetailDialogController {
|
||||
@FXML private Label lblEmployee;
|
||||
@FXML private Label lblPayment;
|
||||
@FXML private Label lblTotal;
|
||||
@FXML private Button btnRefund;
|
||||
@FXML private TableView<SaleDetail.SaleDetailItem> tvItems;
|
||||
@FXML private TableColumn<SaleDetail.SaleDetailItem, String> colProduct;
|
||||
@FXML private TableColumn<SaleDetail.SaleDetailItem, Integer> colQuantity;
|
||||
@@ -27,6 +36,8 @@ public class SaleDetailDialogController {
|
||||
|
||||
private final NumberFormat currency = NumberFormat.getCurrencyInstance(Locale.CANADA);
|
||||
private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
|
||||
private Long saleId;
|
||||
private Consumer<Long> refundAction;
|
||||
|
||||
@FXML
|
||||
public void initialize() {
|
||||
@@ -38,12 +49,48 @@ public class SaleDetailDialogController {
|
||||
}
|
||||
|
||||
public void displaySaleDetails(SaleDetail sale) {
|
||||
saleId = (long) sale.getSaleId();
|
||||
lblSaleId.setText(String.valueOf(sale.getSaleId()));
|
||||
lblSaleDate.setText(sale.getSaleDate() != null ? sale.getSaleDate().format(DATE_FORMATTER) : "");
|
||||
lblEmployee.setText(sale.getEmployeeName() != null ? sale.getEmployeeName() : "");
|
||||
lblPayment.setText(sale.getPaymentMethod() != null ? sale.getPaymentMethod() : "");
|
||||
lblTotal.setText(currency.format(sale.getTotalAmount()));
|
||||
tvItems.setItems(sale.getItems());
|
||||
if (btnRefund != null) {
|
||||
btnRefund.setDisable(sale.isRefund());
|
||||
}
|
||||
}
|
||||
|
||||
public void setSaleId(Long saleId) {
|
||||
this.saleId = saleId;
|
||||
}
|
||||
|
||||
public void setRefundAction(Consumer<Long> refundAction) {
|
||||
this.refundAction = refundAction;
|
||||
}
|
||||
|
||||
@FXML
|
||||
void btnRefundClicked() {
|
||||
if (saleId == null) {
|
||||
return;
|
||||
}
|
||||
if (refundAction != null) {
|
||||
refundAction.accept(saleId);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
FXMLLoader loader = new FXMLLoader(getClass().getResource("/org/example/petshopdesktop/dialogviews/refund-dialog-view.fxml"));
|
||||
Stage dialog = new Stage();
|
||||
dialog.initOwner(tvItems.getScene().getWindow());
|
||||
dialog.initModality(Modality.APPLICATION_MODAL);
|
||||
dialog.setTitle("Process Refund");
|
||||
dialog.setScene(new Scene(loader.load()));
|
||||
RefundDialogController controller = loader.getController();
|
||||
controller.prefillSale(saleId);
|
||||
dialog.showAndWait();
|
||||
} catch (Exception e) {
|
||||
ActivityLogger.getInstance().logException("SaleDetailDialogController.btnRefundClicked", e, "Opening refund dialog");
|
||||
}
|
||||
}
|
||||
|
||||
@FXML
|
||||
|
||||
@@ -9,14 +9,16 @@ public class SaleDetail {
|
||||
private final double totalAmount;
|
||||
private final String paymentMethod;
|
||||
private final String employeeName;
|
||||
private final boolean refund;
|
||||
private final ObservableList<SaleDetailItem> items;
|
||||
|
||||
public SaleDetail(int saleId, LocalDateTime saleDate, double totalAmount, String paymentMethod, String employeeName, ObservableList<SaleDetailItem> items) {
|
||||
public SaleDetail(int saleId, LocalDateTime saleDate, double totalAmount, String paymentMethod, String employeeName, boolean refund, ObservableList<SaleDetailItem> items) {
|
||||
this.saleId = saleId;
|
||||
this.saleDate = saleDate;
|
||||
this.totalAmount = totalAmount;
|
||||
this.paymentMethod = paymentMethod;
|
||||
this.employeeName = employeeName;
|
||||
this.refund = refund;
|
||||
this.items = items;
|
||||
}
|
||||
|
||||
@@ -40,6 +42,10 @@ public class SaleDetail {
|
||||
return employeeName;
|
||||
}
|
||||
|
||||
public boolean isRefund() {
|
||||
return refund;
|
||||
}
|
||||
|
||||
public ObservableList<SaleDetailItem> getItems() {
|
||||
return items;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
package org.example.petshopdesktop.util;
|
||||
|
||||
import javafx.collections.transformation.FilteredList;
|
||||
import javafx.collections.transformation.SortedList;
|
||||
import javafx.animation.PauseTransition;
|
||||
import javafx.scene.control.TableCell;
|
||||
import javafx.scene.control.TableColumn;
|
||||
import javafx.scene.control.Label;
|
||||
import javafx.scene.control.TableRow;
|
||||
import javafx.scene.control.TableView;
|
||||
import javafx.scene.input.MouseButton;
|
||||
import javafx.util.Duration;
|
||||
|
||||
import java.text.NumberFormat;
|
||||
import java.util.Locale;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public final class TableViewSupport {
|
||||
|
||||
private TableViewSupport() {
|
||||
}
|
||||
|
||||
public static <T> void bindSortedItems(TableView<T> tableView, FilteredList<T> filteredItems) {
|
||||
SortedList<T> sortedItems = new SortedList<>(filteredItems);
|
||||
sortedItems.comparatorProperty().bind(tableView.comparatorProperty());
|
||||
tableView.setItems(sortedItems);
|
||||
}
|
||||
|
||||
public static void clearSort(TableView<?> tableView) {
|
||||
tableView.getSortOrder().clear();
|
||||
}
|
||||
|
||||
public static void flashStatus(Label label, String message) {
|
||||
if (label == null) {
|
||||
return;
|
||||
}
|
||||
label.setText(message);
|
||||
label.setVisible(true);
|
||||
PauseTransition delay = new PauseTransition(Duration.seconds(1.5));
|
||||
delay.setOnFinished(event -> {
|
||||
label.setVisible(false);
|
||||
});
|
||||
delay.playFromStart();
|
||||
}
|
||||
|
||||
public static <S, T extends Number> void applyCurrencyColumn(TableColumn<S, T> column) {
|
||||
if (column == null) {
|
||||
return;
|
||||
}
|
||||
column.setCellFactory(col -> new TableCell<>() {
|
||||
private final NumberFormat currency = NumberFormat.getCurrencyInstance(Locale.CANADA);
|
||||
|
||||
@Override
|
||||
protected void updateItem(T value, boolean empty) {
|
||||
super.updateItem(value, empty);
|
||||
setText(empty || value == null ? null : currency.format(value.doubleValue()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public static <T> void installDoubleClickAction(TableView<T> tableView, Consumer<T> action) {
|
||||
tableView.setRowFactory(tv -> {
|
||||
TableRow<T> row = new TableRow<>();
|
||||
row.setOnMouseClicked(event -> {
|
||||
if (event.getButton() == MouseButton.PRIMARY && event.getClickCount() == 2 && !row.isEmpty()) {
|
||||
action.accept(row.getItem());
|
||||
}
|
||||
});
|
||||
return row;
|
||||
});
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user