From 2b8cd222048c6374787f98284753fefc2e248cbd Mon Sep 17 00:00:00 2001 From: Harkamal Randhawa Date: Sat, 7 Mar 2026 17:02:53 -0700 Subject: [PATCH] Migrate all controllers to REST API --- .../petshopdesktop/DTOs/PurchaseOrderDTO.java | 8 +- .../ProductSupplierResponse.java | 18 ++ .../controllers/AdoptionController.java | 148 +++++----- .../controllers/AnalyticsController.java | 124 ++++++--- .../controllers/AppointmentController.java | 134 +++++---- .../controllers/InventoryController.java | 179 ++++++------ .../ProductSupplierController.java | 155 +++++------ .../controllers/PurchaseOrderController.java | 51 +++- .../controllers/SaleController.java | 153 ++++++---- .../controllers/ServiceController.java | 262 +++++++++--------- .../controllers/StaffAccountsController.java | 64 ++++- .../controllers/SupplierController.java | 150 +++++----- .../AdoptionDialogController.java | 197 +++++-------- .../AppointmentDialogController.java | 172 +++++++----- .../ProductSupplierDialogController.java | 241 ++++++++-------- .../RefundDialogController.java | 81 +++--- .../ServiceDialogController.java | 19 +- .../StaffRegisterDialogController.java | 69 ++--- .../SupplierDialogController.java | 82 ++---- .../petshopdesktop/models/Adoption.java | 11 +- .../petshopdesktop/models/Inventory.java | 35 ++- .../petshopdesktop/models/PurchaseOrder.java | 41 ++- .../petshopdesktop/models/StaffAccount.java | 10 +- 23 files changed, 1308 insertions(+), 1096 deletions(-) diff --git a/src/main/java/org/example/petshopdesktop/DTOs/PurchaseOrderDTO.java b/src/main/java/org/example/petshopdesktop/DTOs/PurchaseOrderDTO.java index 11c5d330..acc28e2a 100644 --- a/src/main/java/org/example/petshopdesktop/DTOs/PurchaseOrderDTO.java +++ b/src/main/java/org/example/petshopdesktop/DTOs/PurchaseOrderDTO.java @@ -4,21 +4,21 @@ import javafx.beans.property.*; public class PurchaseOrderDTO { - private IntegerProperty purchaseOrderId; + private LongProperty purchaseOrderId; private StringProperty supplierName; private StringProperty orderDate; private StringProperty status; - public PurchaseOrderDTO(int id, String supplierName, + public PurchaseOrderDTO(long id, String supplierName, String orderDate, String status) { - this.purchaseOrderId = new SimpleIntegerProperty(id); + this.purchaseOrderId = new SimpleLongProperty(id); this.supplierName = new SimpleStringProperty(supplierName); this.orderDate = new SimpleStringProperty(orderDate); this.status = new SimpleStringProperty(status); } - public int getPurchaseOrderId() { return purchaseOrderId.get(); } + public long getPurchaseOrderId() { return purchaseOrderId.get(); } public String getSupplierName() { return supplierName.get(); } public String getOrderDate() { return orderDate.get(); } public String getStatus() { return status.get(); } diff --git a/src/main/java/org/example/petshopdesktop/api/dto/productsupplier/ProductSupplierResponse.java b/src/main/java/org/example/petshopdesktop/api/dto/productsupplier/ProductSupplierResponse.java index 4f4ed246..55478763 100644 --- a/src/main/java/org/example/petshopdesktop/api/dto/productsupplier/ProductSupplierResponse.java +++ b/src/main/java/org/example/petshopdesktop/api/dto/productsupplier/ProductSupplierResponse.java @@ -4,6 +4,8 @@ import java.math.BigDecimal; public class ProductSupplierResponse { private Long id; + private Long productId; + private Long supplierId; private String productName; private String supplierName; private BigDecimal supplierPrice; @@ -16,6 +18,22 @@ public class ProductSupplierResponse { this.id = id; } + public Long getProductId() { + return productId; + } + + public void setProductId(Long productId) { + this.productId = productId; + } + + public Long getSupplierId() { + return supplierId; + } + + public void setSupplierId(Long supplierId) { + this.supplierId = supplierId; + } + public String getProductName() { return productName; } diff --git a/src/main/java/org/example/petshopdesktop/controllers/AdoptionController.java b/src/main/java/org/example/petshopdesktop/controllers/AdoptionController.java index c60ddf83..611d88f1 100644 --- a/src/main/java/org/example/petshopdesktop/controllers/AdoptionController.java +++ b/src/main/java/org/example/petshopdesktop/controllers/AdoptionController.java @@ -1,5 +1,6 @@ package org.example.petshopdesktop.controllers; +import javafx.application.Platform; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.event.ActionEvent; @@ -10,15 +11,16 @@ import javafx.scene.control.*; import javafx.scene.control.cell.PropertyValueFactory; import javafx.stage.Modality; import javafx.stage.Stage; +import org.example.petshopdesktop.api.dto.adoption.AdoptionResponse; +import org.example.petshopdesktop.api.endpoints.AdoptionApi; import org.example.petshopdesktop.controllers.dialogcontrollers.AdoptionDialogController; -import org.example.petshopdesktop.database.AdoptionDB; import org.example.petshopdesktop.models.Adoption; import org.example.petshopdesktop.util.ActivityLogger; import java.io.IOException; -import java.sql.SQLException; -import java.sql.SQLIntegrityConstraintViolationException; +import java.util.List; import java.util.Optional; +import java.util.stream.Collectors; public class AdoptionController { @@ -35,7 +37,7 @@ public class AdoptionController { private TableColumn colAdoptionId; @FXML - private TableColumn colPetId; + private TableColumn colPetId; @FXML private TableColumn colCustomerName; @@ -66,7 +68,7 @@ public class AdoptionController { tvAdoptions.getSelectionModel().setSelectionMode(javafx.scene.control.SelectionMode.MULTIPLE); colAdoptionId.setCellValueFactory(new PropertyValueFactory<>("adoptionId")); - colPetId.setCellValueFactory(new PropertyValueFactory<>("petId")); + colPetId.setCellValueFactory(new PropertyValueFactory<>("petName")); colCustomerName.setCellValueFactory(new PropertyValueFactory<>("customerName")); colAdoptionDate.setCellValueFactory(new PropertyValueFactory<>("adoptionDate")); colAdoptionFee.setCellValueFactory(new PropertyValueFactory<>("adoptionFee")); @@ -118,47 +120,24 @@ public class AdoptionController { //if confirmed, start deletion if (result.isPresent() && result.get() == ButtonType.OK) { - int successCount = 0; - int failCount = 0; - StringBuilder errors = new StringBuilder(); + List ids = selectedAdoptions.stream() + .map(a -> (long) a.getAdoptionId()) + .collect(Collectors.toList()); - for (Adoption adoption : selectedAdoptions) { - try { - int numRows = AdoptionDB.deleteAdoption(adoption.getAdoptionId()); - if (numRows > 0) { - successCount++; - } else { - failCount++; - } - } - catch (SQLIntegrityConstraintViolationException e) { - ActivityLogger.getInstance().logException( - "AdoptionController.btnDeleteClicked", - e, - String.format("Attempting to delete adoption ID %d - foreign key constraint", adoption.getAdoptionId())); - failCount++; - errors.append("Adoption ID ").append(adoption.getAdoptionId()).append(" is referenced in another table\n"); - } catch (SQLException e) { - ActivityLogger.getInstance().logException( - "AdoptionController.btnDeleteClicked", - e, - String.format("Attempting to delete adoption ID %d", adoption.getAdoptionId())); - failCount++; - errors.append("Failed to delete adoption ID ").append(adoption.getAdoptionId()).append("\n"); - } - } - - //show results - if (failCount > 0) { - Alert alert = new Alert(Alert.AlertType.WARNING); - alert.setHeaderText("Delete Operation Completed with Errors"); - alert.setContentText(String.format("Deleted: %d\nFailed: %d\n\n%s", - successCount, failCount, errors.toString())); - alert.showAndWait(); - } else if (successCount > 0) { + try { + AdoptionApi.getInstance().deleteAdoptions(ids); Alert alert = new Alert(Alert.AlertType.INFORMATION); alert.setHeaderText("Database Operation Confirmed"); - alert.setContentText("Successfully deleted " + successCount + " adoption record(s)"); + alert.setContentText("Successfully deleted " + ids.size() + " adoption record(s)"); + alert.showAndWait(); + } catch (Exception e) { + ActivityLogger.getInstance().logException( + "AdoptionController.btnDeleteClicked", + e, + "Deleting adoptions"); + Alert alert = new Alert(Alert.AlertType.ERROR); + alert.setHeaderText("Delete Operation Failed"); + alert.setContentText(e.getMessage()); alert.showAndWait(); } @@ -181,35 +160,55 @@ public class AdoptionController { } private void displayFilteredAdoptions(String filter) { - data.clear(); - try { - if (txtSearch.getText() == null || txtSearch.getText().isEmpty()) { - displayAdoptions(); - } else { - data = AdoptionDB.getFilteredAdoptions(filter); - tvAdoptions.setItems(data); - } - } catch (Exception e) { - ActivityLogger.getInstance().logException( - "AdoptionController.displayFilteredAdoptions", - e, - "Filtering adoptions with filter: " + filter); - System.out.println("Error while fetching table data: " + e.getMessage()); + if (txtSearch.getText() == null || txtSearch.getText().isEmpty()) { + displayAdoptions(); + } else { + new Thread(() -> { + try { + List adoptions = AdoptionApi.getInstance().listAdoptions(filter); + List adoptionList = adoptions.stream() + .map(this::mapToAdoption) + .collect(Collectors.toList()); + + Platform.runLater(() -> { + data.setAll(adoptionList); + tvAdoptions.setItems(data); + }); + } catch (Exception e) { + Platform.runLater(() -> { + System.out.println("Error while fetching table data: " + e.getMessage()); + ActivityLogger.getInstance().logException( + "AdoptionController.displayFilteredAdoptions", + e, + "Filtering adoptions with filter: " + filter); + }); + } + }).start(); } } private void displayAdoptions() { - data.clear(); - try { - data = AdoptionDB.getAdoptions(); - } catch (SQLException e) { - ActivityLogger.getInstance().logException( - "AdoptionController.displayAdoptions", - e, - "Fetching adoption data for table display"); - System.out.println("Error while fetching table data: " + e.getMessage()); - } - tvAdoptions.setItems(data); + new Thread(() -> { + try { + List adoptions = AdoptionApi.getInstance().listAdoptions(null); + List adoptionList = adoptions.stream() + .map(this::mapToAdoption) + .collect(Collectors.toList()); + + Platform.runLater(() -> { + data.setAll(adoptionList); + tvAdoptions.setItems(data); + }); + } catch (Exception e) { + Platform.runLater(() -> { + System.out.println("Error while fetching table data: " + e.getMessage()); + ActivityLogger.getInstance().logException( + "AdoptionController.displayAdoptions", + e, + "Fetching adoption data for table display"); + }); + } + }).start(); } private void openDialog(Adoption adoption, String mode) { @@ -244,4 +243,17 @@ public class AdoptionController { btnEdit.setDisable(true); txtSearch.setText(""); } + + private Adoption mapToAdoption(AdoptionResponse response) { + return new Adoption( + response.getId().intValue(), + 0, + 0, + response.getPetName(), + response.getCustomerName(), + response.getAdoptionDate() != null ? response.getAdoptionDate().toString() : "", + 0.0, + response.getAdoptionStatus() + ); + } } diff --git a/src/main/java/org/example/petshopdesktop/controllers/AnalyticsController.java b/src/main/java/org/example/petshopdesktop/controllers/AnalyticsController.java index 6bb2a28a..b0637ab0 100644 --- a/src/main/java/org/example/petshopdesktop/controllers/AnalyticsController.java +++ b/src/main/java/org/example/petshopdesktop/controllers/AnalyticsController.java @@ -1,19 +1,25 @@ package org.example.petshopdesktop.controllers; -import javafx.collections.ObservableList; +import javafx.application.Platform; import javafx.event.ActionEvent; import javafx.fxml.FXML; import javafx.scene.chart.*; import javafx.scene.control.Button; import javafx.scene.control.Label; -import org.example.petshopdesktop.auth.UserSession; -import org.example.petshopdesktop.database.SaleDB; -import org.example.petshopdesktop.models.analytics.*; +import org.example.petshopdesktop.api.dto.analytics.DailySales; +import org.example.petshopdesktop.api.dto.analytics.DashboardResponse; +import org.example.petshopdesktop.api.dto.analytics.TopProduct; +import org.example.petshopdesktop.api.dto.sale.SaleResponse; +import org.example.petshopdesktop.api.endpoints.AnalyticsApi; +import org.example.petshopdesktop.api.endpoints.SaleApi; import org.example.petshopdesktop.util.ActivityLogger; +import java.math.BigDecimal; +import java.math.RoundingMode; import java.text.NumberFormat; import java.time.format.DateTimeFormatter; -import java.util.Locale; +import java.util.*; +import java.util.stream.Collectors; public class AnalyticsController { @@ -78,79 +84,111 @@ public class AnalyticsController { private void loadAnalyticsData() { lblError.setVisible(false); - try { - loadSummaryData(); - loadSalesOverTime(); - loadTopProductsByRevenue(); - loadTopProductsByQuantity(); - loadPaymentMethodDistribution(); - loadEmployeePerformance(); - } catch (Exception e) { - ActivityLogger.getInstance().logException("AnalyticsController.loadAnalyticsData", e, "Loading analytics data"); - lblError.setText("Error loading analytics data. Please try again."); - lblError.setVisible(true); + new Thread(() -> { + try { + DashboardResponse dashboard = AnalyticsApi.getInstance().getDashboard(30, 10); + List sales = SaleApi.getInstance().listSales(0, Integer.MAX_VALUE, null); + + Platform.runLater(() -> { + try { + loadSummaryData(dashboard); + loadSalesOverTime(dashboard); + loadTopProductsByRevenue(dashboard); + loadTopProductsByQuantity(dashboard); + loadPaymentMethodDistribution(sales); + loadEmployeePerformance(sales); + } catch (Exception e) { + ActivityLogger.getInstance().logException("AnalyticsController.loadAnalyticsData", e, "Loading analytics data"); + lblError.setText("Error loading analytics data. Please try again."); + lblError.setVisible(true); + } + }); + } catch (Exception e) { + Platform.runLater(() -> { + ActivityLogger.getInstance().logException("AnalyticsController.loadAnalyticsData", e, "Loading analytics data"); + lblError.setText("Error loading analytics data. Please try again."); + lblError.setVisible(true); + }); + } + }).start(); + } + + private void loadSummaryData(DashboardResponse dashboard) throws Exception { + if (dashboard != null) { + BigDecimal totalRevenue = dashboard.getTotalRevenue() != null ? dashboard.getTotalRevenue() : BigDecimal.ZERO; + Long totalSales = dashboard.getTotalSales() != null ? dashboard.getTotalSales() : 0L; + Long totalProducts = dashboard.getTotalProducts() != null ? dashboard.getTotalProducts() : 0L; + + lblTotalRevenue.setText(currency.format(totalRevenue)); + lblTotalTransactions.setText(wholeNumber.format(totalSales)); + + BigDecimal avgTransaction = BigDecimal.ZERO; + if (totalSales > 0) { + avgTransaction = totalRevenue.divide(BigDecimal.valueOf(totalSales), 2, RoundingMode.HALF_UP); + } + lblAvgTransaction.setText(currency.format(avgTransaction)); + lblTotalItems.setText(wholeNumber.format(totalProducts)); } } - private void loadSummaryData() throws Exception { - SalesSummary summary = SaleDB.getSalesSummary(); - if (summary != null) { - lblTotalRevenue.setText(currency.format(summary.getTotalRevenue())); - lblTotalTransactions.setText(wholeNumber.format(summary.getTotalTransactions())); - lblAvgTransaction.setText(currency.format(summary.getAvgTransactionValue())); - lblTotalItems.setText(wholeNumber.format(summary.getTotalItemsSold())); - } - } - - private void loadSalesOverTime() throws Exception { - ObservableList data = SaleDB.getDailySalesRevenue(); + private void loadSalesOverTime(DashboardResponse dashboard) throws Exception { + List dailySales = dashboard.getDailySales() != null ? dashboard.getDailySales() : new ArrayList<>(); XYChart.Series series = new XYChart.Series<>(); series.setName("Daily Revenue"); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MMM dd"); - for (DailySalesData dailySale : data) { + for (DailySales dailySale : dailySales) { String dateStr = dailySale.getDate().format(formatter); - series.getData().add(new XYChart.Data<>(dateStr, dailySale.getRevenue())); + BigDecimal totalSales = dailySale.getTotalSales() != null ? dailySale.getTotalSales() : BigDecimal.ZERO; + series.getData().add(new XYChart.Data<>(dateStr, totalSales)); } chartSalesOverTime.getData().clear(); chartSalesOverTime.getData().add(series); } - private void loadTopProductsByRevenue() throws Exception { - ObservableList data = SaleDB.getTopProductsByRevenue(10); + private void loadTopProductsByRevenue(DashboardResponse dashboard) throws Exception { + List topProducts = dashboard.getTopProducts() != null ? dashboard.getTopProducts() : new ArrayList<>(); XYChart.Series series = new XYChart.Series<>(); series.setName("Revenue"); - for (ProductSalesData product : data) { - series.getData().add(new XYChart.Data<>(product.getTotalRevenue(), product.getProductName())); + for (TopProduct product : topProducts) { + BigDecimal totalRevenue = product.getTotalRevenue() != null ? product.getTotalRevenue() : BigDecimal.ZERO; + series.getData().add(new XYChart.Data<>(totalRevenue, product.getProductName())); } chartTopRevenue.getData().clear(); chartTopRevenue.getData().add(series); } - private void loadTopProductsByQuantity() throws Exception { - ObservableList data = SaleDB.getTopProductsByQuantity(10); + private void loadTopProductsByQuantity(DashboardResponse dashboard) throws Exception { + List topProducts = dashboard.getTopProducts() != null ? dashboard.getTopProducts() : new ArrayList<>(); XYChart.Series series = new XYChart.Series<>(); series.setName("Quantity"); - for (ProductSalesData product : data) { - series.getData().add(new XYChart.Data<>(product.getTotalQuantity(), product.getProductName())); + for (TopProduct product : topProducts) { + Integer quantitySold = product.getQuantitySold() != null ? product.getQuantitySold() : 0; + series.getData().add(new XYChart.Data<>(quantitySold, product.getProductName())); } chartTopQuantity.getData().clear(); chartTopQuantity.getData().add(series); } - private void loadPaymentMethodDistribution() throws Exception { - ObservableList data = SaleDB.getPaymentMethodDistribution(); + private void loadPaymentMethodDistribution(List sales) throws Exception { + Map paymentMethodCount = sales.stream() + .filter(sale -> sale.getIsRefund() == null || !sale.getIsRefund()) + .collect(Collectors.groupingBy( + sale -> sale.getPaymentMethod() != null ? sale.getPaymentMethod() : "Unknown", + Collectors.counting() + )); + chartPaymentMethods.getData().clear(); - for (PaymentMethodData payment : data) { + for (Map.Entry entry : paymentMethodCount.entrySet()) { PieChart.Data slice = new PieChart.Data( - payment.getPaymentMethod() + " (" + payment.getTransactionCount() + ")", - payment.getTransactionCount() + entry.getKey() + " (" + entry.getValue() + ")", + entry.getValue() ); chartPaymentMethods.getData().add(slice); } diff --git a/src/main/java/org/example/petshopdesktop/controllers/AppointmentController.java b/src/main/java/org/example/petshopdesktop/controllers/AppointmentController.java index ac1a2c35..430804ae 100644 --- a/src/main/java/org/example/petshopdesktop/controllers/AppointmentController.java +++ b/src/main/java/org/example/petshopdesktop/controllers/AppointmentController.java @@ -1,5 +1,6 @@ package org.example.petshopdesktop.controllers; +import javafx.application.Platform; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.collections.transformation.FilteredList; @@ -13,10 +14,14 @@ import javafx.stage.Modality; import javafx.stage.Stage; import org.example.petshopdesktop.DTOs.AppointmentDTO; +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.database.AppointmentDB; import org.example.petshopdesktop.util.ActivityLogger; +import java.util.List; +import java.util.stream.Collectors; + public class AppointmentController { @FXML private TableView tvAppointments; @@ -71,41 +76,50 @@ public class AppointmentController { } private void loadAppointments(){ - try{ - appointments.setAll(AppointmentDB.getAppointmentDTOs()); - }catch(Exception e){ - ActivityLogger.getInstance().logException( - "AppointmentController.loadAppointments", - e, - "Loading appointments for table display"); - e.printStackTrace(); - } + new Thread(() -> { + try{ + List responses = AppointmentApi.getInstance().listAppointments(null); + List appointmentDTOs = responses.stream() + .map(this::mapToAppointmentDTO) + .collect(Collectors.toList()); + + Platform.runLater(() -> { + appointments.setAll(appointmentDTOs); + }); + }catch(Exception e){ + Platform.runLater(() -> { + ActivityLogger.getInstance().logException( + "AppointmentController.loadAppointments", + e, + "Loading appointments for table display"); + e.printStackTrace(); + }); + } + }).start(); } private void applyFilter(String text) { - if (filtered == null) { - return; - } + String query = text == null || text.trim().isEmpty() ? null : text.trim(); + new Thread(() -> { + try { + List responses = AppointmentApi.getInstance().listAppointments(query); + List appointmentDTOs = responses.stream() + .map(this::mapToAppointmentDTO) + .collect(Collectors.toList()); - String q = text == null ? "" : text.trim().toLowerCase(); - if (q.isEmpty()) { - filtered.setPredicate(a -> true); - return; - } - - filtered.setPredicate(a -> - String.valueOf(a.getAppointmentId()).contains(q) - || safe(a.getPetName()).contains(q) - || safe(a.getServiceName()).contains(q) - || safe(a.getAppointmentDate()).contains(q) - || safe(a.getAppointmentTime()).contains(q) - || safe(a.getCustomerName()).contains(q) - || safe(a.getAppointmentStatus()).contains(q) - ); - } - - private static String safe(String v) { - return v == null ? "" : v.toLowerCase(); + Platform.runLater(() -> { + appointments.setAll(appointmentDTOs); + }); + } catch (Exception e) { + Platform.runLater(() -> { + ActivityLogger.getInstance().logException( + "AppointmentController.applyFilter", + e, + String.format("Filtering appointments with query: %s", query)); + e.printStackTrace(); + }); + } + }).start(); } @FXML @@ -145,35 +159,24 @@ public class AppointmentController { //if confirmed, start deletion if (result.isPresent() && result.get() == ButtonType.OK) { - int successCount = 0; - int failCount = 0; - StringBuilder errors = new StringBuilder(); + List ids = selectedAppointments.stream() + .map(a -> (long) a.getAppointmentId()) + .collect(Collectors.toList()); - for (AppointmentDTO appointment : selectedAppointments) { - try{ - AppointmentDB.deleteAppointment(appointment.getAppointmentId()); - successCount++; - }catch(Exception e){ - ActivityLogger.getInstance().logException( - "AppointmentController.btnDeleteClicked", - e, - String.format("Attempting to delete appointment ID %d", appointment.getAppointmentId())); - failCount++; - errors.append("Failed to delete appointment ID ").append(appointment.getAppointmentId()).append("\n"); - } - } - - //show results - if (failCount > 0) { - Alert alert = new Alert(Alert.AlertType.WARNING); - alert.setHeaderText("Delete Operation Completed with Errors"); - alert.setContentText(String.format("Deleted: %d\nFailed: %d\n\n%s", - successCount, failCount, errors.toString())); - alert.showAndWait(); - } else if (successCount > 0) { + try { + AppointmentApi.getInstance().deleteAppointments(ids); Alert alert = new Alert(Alert.AlertType.INFORMATION); alert.setHeaderText("Database Operation Confirmed"); - alert.setContentText("Successfully deleted " + successCount + " appointment(s)"); + alert.setContentText("Successfully deleted " + ids.size() + " appointment(s)"); + alert.showAndWait(); + } catch (Exception e) { + ActivityLogger.getInstance().logException( + "AppointmentController.btnDeleteClicked", + e, + "Deleting appointments"); + Alert alert = new Alert(Alert.AlertType.ERROR); + alert.setHeaderText("Delete Operation Failed"); + alert.setContentText(e.getMessage()); alert.showAndWait(); } @@ -225,4 +228,19 @@ public class AppointmentController { alert.setContentText(msg); alert.showAndWait(); } + + private AppointmentDTO mapToAppointmentDTO(AppointmentResponse response) { + return new AppointmentDTO( + response.getId().intValue(), + 0, + response.getCustomerName(), + 0, + response.getPetNames(), + 0, + response.getServiceName(), + response.getAppointmentDate().toString(), + response.getAppointmentTime().toString(), + response.getAppointmentStatus() + ); + } } diff --git a/src/main/java/org/example/petshopdesktop/controllers/InventoryController.java b/src/main/java/org/example/petshopdesktop/controllers/InventoryController.java index 3a7d9bcd..2dc87162 100644 --- a/src/main/java/org/example/petshopdesktop/controllers/InventoryController.java +++ b/src/main/java/org/example/petshopdesktop/controllers/InventoryController.java @@ -1,5 +1,6 @@ package org.example.petshopdesktop.controllers; +import javafx.application.Platform; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.event.ActionEvent; @@ -10,15 +11,16 @@ import javafx.scene.control.*; import javafx.scene.control.cell.PropertyValueFactory; import javafx.stage.Modality; import javafx.stage.Stage; +import org.example.petshopdesktop.api.dto.inventory.InventoryResponse; +import org.example.petshopdesktop.api.endpoints.InventoryApi; import org.example.petshopdesktop.controllers.dialogcontrollers.InventoryDialogController; -import org.example.petshopdesktop.database.InventoryDB; import org.example.petshopdesktop.models.Inventory; import org.example.petshopdesktop.util.ActivityLogger; import java.io.IOException; -import java.sql.SQLException; -import java.sql.SQLIntegrityConstraintViolationException; +import java.util.List; import java.util.Optional; +import java.util.stream.Collectors; public class InventoryController { @@ -58,11 +60,9 @@ public class InventoryController { //Loads upon view bootup @FXML void initialize() { - //Buttons disabled until row is selected btnEdit.setDisable(true); btnDelete.setDisable(true); - //Enable multiple selection - tvInventory.getSelectionModel().setSelectionMode(javafx.scene.control.SelectionMode.MULTIPLE); + tvInventory.getSelectionModel().setSelectionMode(javafx.scene.control.SelectionMode.SINGLE); colInventoryId.setCellValueFactory(new PropertyValueFactory<>("inventoryId")); colProductId.setCellValueFactory(new PropertyValueFactory<>("prodId")); @@ -71,19 +71,16 @@ public class InventoryController { displayInventory(); - //Enables buttons when row is selected tvInventory.getSelectionModel().selectedItemProperty().addListener( (observable, oldValue, newValue) -> { btnEdit.setDisable(false); btnDelete.setDisable(false); }); - //Filter as user types txtSearch.textProperty().addListener((observable, oldValue, newValue) -> { displayFilteredInventory(newValue); }); - //EventListener for DELETE key tvInventory.setOnKeyPressed(event -> { if (event.getCode() == javafx.scene.input.KeyCode.DELETE) { if (tvInventory.getSelectionModel().getSelectedItem() != null) { @@ -100,71 +97,35 @@ public class InventoryController { openDialog(null, mode); } - //Prompts user for confirmation prior to deletion @FXML void btnDeleteClicked(ActionEvent event) { - //get selected inventory records - var selectedInventory = tvInventory.getSelectionModel().getSelectedItems(); - if (selectedInventory.isEmpty()) return; + Inventory selectedInventory = tvInventory.getSelectionModel().getSelectedItem(); + if (selectedInventory == null) return; - //ask user to confirm Alert question = new Alert(Alert.AlertType.CONFIRMATION); question.setHeaderText("Please confirm delete"); - String message = selectedInventory.size() == 1 - ? "Are you sure you want to delete this inventory record?" - : "Are you sure you want to delete " + selectedInventory.size() + " inventory records?"; - question.setContentText(message); + question.setContentText("Are you sure you want to delete this inventory record?"); question.getDialogPane().lookupButton(ButtonType.OK).requestFocus(); Optional result = question.showAndWait(); - //if confirmed, start deletion if (result.isPresent() && result.get() == ButtonType.OK) { - int successCount = 0; - int failCount = 0; - StringBuilder errors = new StringBuilder(); - - for (Inventory inventory : selectedInventory) { - try { - int numRows = InventoryDB.deleteInventory(inventory.getInventoryId()); - if (numRows > 0) { - successCount++; - } else { - failCount++; - } - } - catch (SQLIntegrityConstraintViolationException e) { - ActivityLogger.getInstance().logException( - "InventoryController.btnDeleteClicked", - e, - String.format("Attempting to delete inventory ID %d - foreign key constraint", inventory.getInventoryId())); - failCount++; - errors.append("Inventory record '").append(inventory.getProdName()).append("' is referenced in another table\n"); - } - catch (SQLException e) { - ActivityLogger.getInstance().logException( - "InventoryController.btnDeleteClicked", - e, - String.format("Attempting to delete inventory ID %d", inventory.getInventoryId())); - failCount++; - errors.append("Failed to delete '").append(inventory.getProdName()).append("'\n"); - } - } - - //show results - if (failCount > 0) { - Alert alert = new Alert(Alert.AlertType.WARNING); - alert.setHeaderText("Delete Operation Completed with Errors"); - alert.setContentText(String.format("Deleted: %d\nFailed: %d\n\n%s", - successCount, failCount, errors.toString())); - alert.showAndWait(); - } else if (successCount > 0) { + try { + InventoryApi.getInstance().deleteInventory((long) selectedInventory.getInventoryId()); Alert alert = new Alert(Alert.AlertType.INFORMATION); alert.setHeaderText("Database Operation Confirmed"); - alert.setContentText("Successfully deleted " + successCount + " inventory record(s)"); + alert.setContentText("Successfully deleted inventory record"); + alert.showAndWait(); + } catch (Exception e) { + ActivityLogger.getInstance().logException( + "InventoryController.btnDeleteClicked", + e, + "Deleting inventory"); + Alert alert = new Alert(Alert.AlertType.ERROR); + alert.setHeaderText("Delete Operation Failed"); + alert.setContentText(e.getMessage()); alert.showAndWait(); } - //refresh display and reset inputs displayInventory(); btnDelete.setDisable(true); btnEdit.setDisable(true); @@ -183,66 +144,72 @@ public class InventoryController { } } - //Search filter private void displayFilteredInventory(String filter) { - data.clear(); - try { - //If search box is empty, display all inventory - if (txtSearch.getText() == null || txtSearch.getText().isEmpty()) { - displayInventory(); - } + if (txtSearch.getText() == null || txtSearch.getText().isEmpty()) { + displayInventory(); + } else { + new Thread(() -> { + try { + List inventories = InventoryApi.getInstance().listInventory(filter); + List inventoryList = inventories.stream() + .map(this::mapToInventory) + .collect(Collectors.toList()); - else { - data = InventoryDB.getFilteredInventory(filter); - tvInventory.setItems(data); - } - } - - catch (Exception e) { - ActivityLogger.getInstance().logException( - "InventoryController.displayFilteredInventory", - e, - "Filtering inventory with filter: " + filter); - System.out.println("Error while fetching table data: " + e.getMessage()); + Platform.runLater(() -> { + data.setAll(inventoryList); + tvInventory.setItems(data); + }); + } catch (Exception e) { + Platform.runLater(() -> { + System.out.println("Error while fetching table data: " + e.getMessage()); + ActivityLogger.getInstance().logException( + "InventoryController.displayFilteredInventory", + e, + String.format("Filtering inventory with keyword: %s", filter)); + }); + } + }).start(); } } - //Displays all records from DB private void displayInventory() { - data.clear(); - try { - data = InventoryDB.getInventory(); - } + new Thread(() -> { + try { + List inventories = InventoryApi.getInstance().listInventory(null); + List inventoryList = inventories.stream() + .map(this::mapToInventory) + .collect(Collectors.toList()); - catch (SQLException e) { - ActivityLogger.getInstance().logException( - "InventoryController.displayInventory", - e, - "Fetching inventory data for table display"); - System.out.println("Error while fetching table data: " + e.getMessage()); - } - tvInventory.setItems(data); + Platform.runLater(() -> { + data.setAll(inventoryList); + tvInventory.setItems(data); + }); + } catch (Exception e) { + Platform.runLater(() -> { + System.out.println("Error while fetching table data: " + e.getMessage()); + ActivityLogger.getInstance().logException( + "InventoryController.displayInventory", + e, + "Fetching inventory data for table display"); + }); + } + }).start(); } - //Opens inventory-dialog-view private void openDialog(Inventory inventory, String mode) { - //Opens FXML FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/org/example/petshopdesktop/dialogviews/inventory-dialog-view.fxml")); Scene scene = null; try { scene = new Scene(fxmlLoader.load()); - } - - catch (IOException e) { + } catch (IOException e) { ActivityLogger.getInstance().logException( "InventoryController.openDialog", e, - "Loading inventory dialog in " + mode + " mode"); + String.format("Loading inventory dialog view in %s mode", mode)); throw new RuntimeException(e); } - //Passes data and mode to the view InventoryDialogController dialogController = fxmlLoader.getController(); dialogController.setMode(mode); @@ -256,10 +223,22 @@ public class InventoryController { dialogStage.setScene(scene); dialogStage.showAndWait(); - //Refresh inventory displayInventory(); btnDelete.setDisable(true); btnEdit.setDisable(true); txtSearch.setText(""); } + + private Inventory mapToInventory(InventoryResponse response) { + return new Inventory( + response.getId().intValue(), + 0, + response.getProductName(), + response.getCategoryName() != null ? response.getCategoryName() : "", + 0, + response.getStoreName() != null ? response.getStoreName() : "", + response.getStockQuantity() != null ? response.getStockQuantity() : 0, + response.getReorderLevel() != null ? response.getReorderLevel() : 0 + ); + } } diff --git a/src/main/java/org/example/petshopdesktop/controllers/ProductSupplierController.java b/src/main/java/org/example/petshopdesktop/controllers/ProductSupplierController.java index ff5b3009..e3e50d09 100644 --- a/src/main/java/org/example/petshopdesktop/controllers/ProductSupplierController.java +++ b/src/main/java/org/example/petshopdesktop/controllers/ProductSupplierController.java @@ -1,5 +1,6 @@ package org.example.petshopdesktop.controllers; +import javafx.application.Platform; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.event.ActionEvent; @@ -10,19 +11,16 @@ import javafx.scene.control.*; import javafx.scene.control.cell.PropertyValueFactory; import javafx.stage.Modality; import javafx.stage.Stage; -import org.example.petshopdesktop.DTOs.ProductDTO; import org.example.petshopdesktop.DTOs.ProductSupplierDTO; -import org.example.petshopdesktop.controllers.dialogcontrollers.ProductDialogController; +import org.example.petshopdesktop.api.dto.productsupplier.ProductSupplierResponse; +import org.example.petshopdesktop.api.endpoints.ProductSupplierApi; import org.example.petshopdesktop.controllers.dialogcontrollers.ProductSupplierDialogController; -import org.example.petshopdesktop.database.ProductDB; -import org.example.petshopdesktop.database.ProductSupplierDB; -import org.example.petshopdesktop.models.ProductSupplier; import org.example.petshopdesktop.util.ActivityLogger; import java.io.IOException; -import java.sql.SQLException; -import java.sql.SQLIntegrityConstraintViolationException; +import java.util.List; import java.util.Optional; +import java.util.stream.Collectors; public class ProductSupplierController { @@ -107,22 +105,27 @@ public class ProductSupplierController { * Display the ProductSupplierDTO to table view */ private void displayProductSupplier() { - //Erase old content - data.clear(); + new Thread(() -> { + try { + List productSuppliers = ProductSupplierApi.getInstance().listProductSuppliers(null); + List productSupplierDTOs = productSuppliers.stream() + .map(this::mapToProductSupplierDTO) + .collect(Collectors.toList()); - //get ProductSupplier from database - try{ - data = ProductSupplierDB.getProductSupplierDTO(); - } catch (SQLException e) { - ActivityLogger.getInstance().logException( - "ProductSupplierController.displayProductSupplier", - e, - "Fetching product-supplier data for table display"); - System.out.println("Error while fetching table data: " + e.getMessage()); - } - - //put data in the table - tvProductSuppliers.setItems(data); + Platform.runLater(() -> { + data.setAll(productSupplierDTOs); + tvProductSuppliers.setItems(data); + }); + } catch (Exception e) { + Platform.runLater(() -> { + System.out.println("Error while fetching table data: " + e.getMessage()); + ActivityLogger.getInstance().logException( + "ProductSupplierController.displayProductSupplier", + e, + "Fetching product-supplier data for table display"); + }); + } + }).start(); } /** @@ -130,22 +133,30 @@ public class ProductSupplierController { * @param filter word to filter table */ private void displayFilteredProductSupplier(String filter){ - data.clear(); - try{ - if (txtSearch.getText() == null || txtSearch.getText().isEmpty()){ - displayProductSupplier(); //If search bar is empty just display everything - } - else{ - //Filter the using the keyword - data = ProductSupplierDB.getFilteredProductSupplierDTO(filter); - tvProductSuppliers.setItems(data); - } - } catch (Exception e) { - ActivityLogger.getInstance().logException( - "ProductSupplierController.displayFilteredProductSupplier", - e, - "Filtering product-supplier data with filter: " + filter); - System.out.println("Error while fetching table data: " + e.getMessage()); + if (txtSearch.getText() == null || txtSearch.getText().isEmpty()){ + displayProductSupplier(); + } else { + new Thread(() -> { + try { + List productSuppliers = ProductSupplierApi.getInstance().listProductSuppliers(filter); + List productSupplierDTOs = productSuppliers.stream() + .map(this::mapToProductSupplierDTO) + .collect(Collectors.toList()); + + Platform.runLater(() -> { + data.setAll(productSupplierDTOs); + tvProductSuppliers.setItems(data); + }); + } catch (Exception e) { + Platform.runLater(() -> { + System.out.println("Error while fetching table data: " + e.getMessage()); + ActivityLogger.getInstance().logException( + "ProductSupplierController.displayFilteredProductSupplier", + e, + "Filtering product-supplier data with filter: " + filter); + }); + } + }).start(); } } @@ -181,52 +192,24 @@ public class ProductSupplierController { //if confirmed, start deletion if (result.isPresent() && result.get() == ButtonType.OK) { - int successCount = 0; - int failCount = 0; - StringBuilder errors = new StringBuilder(); + List ids = selectedProductSuppliers.stream() + .map(ps -> (long) ps.getSupId()) + .collect(Collectors.toList()); - for (ProductSupplierDTO productSupplier : selectedProductSuppliers) { - try{ - int numRows = ProductSupplierDB.deleteProductSupplier(productSupplier.getSupId(), productSupplier.getProdId()); - if (numRows > 0) { - successCount++; - } else { - failCount++; - } - } - catch (SQLIntegrityConstraintViolationException e){ - ActivityLogger.getInstance().logException( - "ProductSupplierController.btnDeleteClicked", - e, - String.format("Attempting to delete product-supplier - SupID: %d, ProdID: %d - foreign key constraint", - productSupplier.getSupId(), productSupplier.getProdId())); - failCount++; - errors.append(String.format("Product-Supplier '%s - %s' is referenced in another table\n", - productSupplier.getProdName(), productSupplier.getSupCompany())); - } - catch (SQLException e) { - ActivityLogger.getInstance().logException( - "ProductSupplierController.btnDeleteClicked", - e, - String.format("Attempting to delete product-supplier - SupID: %d, ProdID: %d", - productSupplier.getSupId(), productSupplier.getProdId())); - failCount++; - errors.append(String.format("Failed to delete '%s - %s'\n", - productSupplier.getProdName(), productSupplier.getSupCompany())); - } - } - - //show results - if (failCount > 0) { - Alert alert = new Alert(Alert.AlertType.WARNING); - alert.setHeaderText("Delete Operation Completed with Errors"); - alert.setContentText(String.format("Deleted: %d\nFailed: %d\n\n%s", - successCount, failCount, errors.toString())); - alert.showAndWait(); - } else if (successCount > 0) { + try { + ProductSupplierApi.getInstance().deleteProductSuppliers(ids); Alert alert = new Alert(Alert.AlertType.INFORMATION); alert.setHeaderText("Database Operation Confirmed"); - alert.setContentText("Successfully deleted " + successCount + " product-supplier(s)"); + alert.setContentText("Successfully deleted " + ids.size() + " product-supplier(s)"); + alert.showAndWait(); + } catch (Exception e) { + ActivityLogger.getInstance().logException( + "ProductSupplierController.btnDeleteClicked", + e, + "Deleting product-suppliers"); + Alert alert = new Alert(Alert.AlertType.ERROR); + alert.setHeaderText("Delete Operation Failed"); + alert.setContentText(e.getMessage()); alert.showAndWait(); } @@ -297,4 +280,14 @@ public class ProductSupplierController { txtSearch.setText(""); } + private ProductSupplierDTO mapToProductSupplierDTO(ProductSupplierResponse response) { + return new ProductSupplierDTO( + response.getSupplierId().intValue(), + response.getProductId().intValue(), + response.getSupplierName(), + response.getProductName(), + response.getSupplierPrice().doubleValue() + ); + } + } diff --git a/src/main/java/org/example/petshopdesktop/controllers/PurchaseOrderController.java b/src/main/java/org/example/petshopdesktop/controllers/PurchaseOrderController.java index 58082dee..c0caeff9 100644 --- a/src/main/java/org/example/petshopdesktop/controllers/PurchaseOrderController.java +++ b/src/main/java/org/example/petshopdesktop/controllers/PurchaseOrderController.java @@ -1,5 +1,6 @@ package org.example.petshopdesktop.controllers; +import javafx.application.Platform; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.collections.transformation.FilteredList; @@ -7,9 +8,13 @@ import javafx.fxml.FXML; import javafx.scene.control.*; import javafx.scene.control.cell.PropertyValueFactory; import org.example.petshopdesktop.DTOs.PurchaseOrderDTO; -import org.example.petshopdesktop.database.PurchaseOrderDB; +import org.example.petshopdesktop.api.dto.purchaseorder.PurchaseOrderResponse; +import org.example.petshopdesktop.api.endpoints.PurchaseOrderApi; import org.example.petshopdesktop.util.ActivityLogger; +import java.util.List; +import java.util.stream.Collectors; + public class PurchaseOrderController { @FXML private Button btnRefresh; @@ -19,7 +24,7 @@ public class PurchaseOrderController { @FXML private TableView tvPurchaseOrders; - @FXML private TableColumn colOrderId; + @FXML private TableColumn colOrderId; @FXML private TableColumn colSupplier; @FXML private TableColumn colOrderDate; @FXML private TableColumn colStatus; @@ -53,17 +58,28 @@ public class PurchaseOrderController { } private void loadPurchaseOrders() { - try { - purchaseOrders.setAll(PurchaseOrderDB.getPurchaseOrders()); - } catch (Exception e) { - ActivityLogger.getInstance().logException( - "PurchaseOrderController.loadPurchaseOrders", - e, - "Loading purchase orders for table display"); - e.printStackTrace(); - new Alert(Alert.AlertType.ERROR, - "Unable to load purchase orders").showAndWait(); - } + new Thread(() -> { + try { + List responses = PurchaseOrderApi.getInstance().listPurchaseOrders(null); + List dtos = responses.stream() + .map(this::mapToPurchaseOrderDTO) + .collect(Collectors.toList()); + + Platform.runLater(() -> { + purchaseOrders.setAll(dtos); + tvPurchaseOrders.setItems(filtered); + }); + } catch (Exception e) { + Platform.runLater(() -> { + ActivityLogger.getInstance().logException( + "PurchaseOrderController.loadPurchaseOrders", + e, + "Loading purchase orders for table display"); + new Alert(Alert.AlertType.ERROR, + "Unable to load purchase orders").showAndWait(); + }); + } + }).start(); } private void applyFilter(String text) { @@ -93,4 +109,13 @@ public class PurchaseOrderController { void btnRefresh() { loadPurchaseOrders(); } + + private PurchaseOrderDTO mapToPurchaseOrderDTO(PurchaseOrderResponse response) { + return new PurchaseOrderDTO( + response.getId(), + response.getSupplierName(), + response.getOrderDate() != null ? response.getOrderDate().toString() : "", + response.getOrderStatus() + ); + } } \ No newline at end of file diff --git a/src/main/java/org/example/petshopdesktop/controllers/SaleController.java b/src/main/java/org/example/petshopdesktop/controllers/SaleController.java index 4d17a0b2..0e2041a2 100644 --- a/src/main/java/org/example/petshopdesktop/controllers/SaleController.java +++ b/src/main/java/org/example/petshopdesktop/controllers/SaleController.java @@ -22,20 +22,25 @@ import javafx.scene.layout.VBox; import javafx.stage.Modality; import javafx.stage.Stage; import org.example.petshopdesktop.auth.UserSession; -import org.example.petshopdesktop.database.InventoryDB; -import org.example.petshopdesktop.database.ProductDB; -import org.example.petshopdesktop.database.SaleDB; -import org.example.petshopdesktop.models.Inventory; +import javafx.concurrent.Task; +import org.example.petshopdesktop.api.endpoints.ProductApi; +import org.example.petshopdesktop.api.endpoints.SaleApi; +import org.example.petshopdesktop.api.dto.product.ProductResponse; +import org.example.petshopdesktop.api.dto.sale.SaleItemRequest; +import org.example.petshopdesktop.api.dto.sale.SaleItemResponse; +import org.example.petshopdesktop.api.dto.sale.SaleRequest; +import org.example.petshopdesktop.api.dto.sale.SaleResponse; import org.example.petshopdesktop.models.Product; import org.example.petshopdesktop.models.SaleCartItem; import org.example.petshopdesktop.models.SaleLineItem; import org.example.petshopdesktop.util.ActivityLogger; -import java.sql.SQLException; +import java.math.BigDecimal; import java.text.NumberFormat; -import java.util.HashMap; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; import java.util.Locale; -import java.util.Map; public class SaleController { @@ -124,8 +129,8 @@ public class SaleController { private final ObservableList saleItems = FXCollections.observableArrayList(); private FilteredList filteredSales; - private final Map inventoryByProdId = new HashMap<>(); private final NumberFormat currency = NumberFormat.getCurrencyInstance(Locale.CANADA); + private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"); @FXML public void initialize() { @@ -133,7 +138,6 @@ public class SaleController { setupCreateSale(); applyRoleMode(); - refreshInventory(); refreshSales(); } @@ -170,11 +174,20 @@ public class SaleController { updateCartTotal(); try { - cbProduct.setItems(ProductDB.getProducts()); - } catch (SQLException e) { + List productResponses = ProductApi.getInstance().listProducts(null); + ObservableList products = FXCollections.observableArrayList(); + for (ProductResponse pr : productResponses) { + products.add(new Product( + pr.getId().intValue(), + pr.getProductName(), + pr.getPrice().doubleValue(), + 0, + pr.getDescription() + )); + } + cbProduct.setItems(products); + } catch (Exception e) { ActivityLogger.getInstance().logException("SaleController.setupCreateSale", e, "Loading products"); - } catch (RuntimeException e) { - ActivityLogger.getInstance().logException("SaleController.setupCreateSale", e, "Database connection"); } } @@ -185,42 +198,59 @@ public class SaleController { lblModeNote.setText(isAdmin ? "(View only)" : "(Staff can create sales)"); } - private void refreshInventory() { - inventoryByProdId.clear(); - try { - for (Inventory inv : InventoryDB.getInventory()) { - inventoryByProdId.put(inv.getProdId(), inv.getQuantity()); - } - } catch (SQLException e) { - ActivityLogger.getInstance().logException("SaleController.refreshInventory", e, "Loading inventory"); - } catch (RuntimeException e) { - ActivityLogger.getInstance().logException("SaleController.refreshInventory", e, "Database connection"); - } - } - private void refreshSales() { refreshSales(false); } private void refreshSales(boolean showErrorDialog) { - try { - saleItems.setAll(SaleDB.getSaleLineItems()); - } catch (SQLException e) { + Task> task = new Task>() { + @Override + protected List call() throws Exception { + List sales = SaleApi.getInstance().listSales(0, 1000, null); + List lineItems = new ArrayList<>(); + + for (SaleResponse sale : sales) { + String saleDate = sale.getSaleDate() != null + ? sale.getSaleDate().format(DATE_FORMATTER) + : ""; + + if (sale.getItems() != null && !sale.getItems().isEmpty()) { + for (SaleItemResponse item : sale.getItems()) { + lineItems.add(new SaleLineItem( + sale.getId().intValue(), + saleDate, + sale.getEmployeeName(), + item.getProductName(), + item.getQuantity(), + item.getUnitPrice().doubleValue(), + item.getLineTotal().doubleValue(), + sale.getPaymentMethod(), + sale.getIsRefund() != null && sale.getIsRefund() + )); + } + } + } + return lineItems; + } + }; + + task.setOnSucceeded(event -> { + saleItems.setAll(task.getValue()); + }); + + task.setOnFailed(event -> { + Throwable e = task.getException(); ActivityLogger.getInstance().logException("SaleController.refreshSales", e, "Loading sales"); if (showErrorDialog) { - showError("Sales", "Could not load sales."); + showError("Sales", "Could not load sales: " + e.getMessage()); } - } catch (RuntimeException e) { - ActivityLogger.getInstance().logException("SaleController.refreshSales", e, "Database connection"); - if (showErrorDialog) { - showError("Sales", "Database is not connected."); - } - } + }); + + new Thread(task).start(); } @FXML void btnRefresh(ActionEvent event) { - refreshInventory(); refreshSales(true); } @@ -244,18 +274,6 @@ public class SaleController { return; } - int stock = inventoryByProdId.getOrDefault(product.getProdId(), 0); - int alreadyInCart = cartItems.stream() - .filter(i -> i.getProdId() == product.getProdId()) - .mapToInt(SaleCartItem::getQuantity) - .sum(); - - int available = stock - alreadyInCart; - if (requestedQty > available) { - showError("Create Sale", "Not enough stock. Available: " + Math.max(0, available)); - return; - } - for (SaleCartItem item : cartItems) { if (item.getProdId() == product.getProdId()) { item.setQuantity(item.getQuantity() + requestedQty); @@ -291,9 +309,9 @@ public class SaleController { return; } - Integer employeeId = UserSession.getInstance().getEmployeeId(); - if (employeeId == null || employeeId <= 0) { - showError("Create Sale", "Employee is not set for this account."); + Long storeId = UserSession.getInstance().getStoreId(); + if (storeId == null || storeId <= 0) { + showError("Create Sale", "Store is not set for this account."); return; } @@ -309,20 +327,35 @@ public class SaleController { } try { - int saleId = SaleDB.createSale(employeeId, payment, cartItems); - showInfo("Sale saved", "Sale ID " + saleId + " was created."); + SaleRequest request = new SaleRequest(); + request.setStoreId(storeId); + request.setPaymentMethod(payment); + + List itemRequests = new ArrayList<>(); + for (SaleCartItem cartItem : cartItems) { + SaleItemRequest itemRequest = new SaleItemRequest(); + itemRequest.setProductId((long) cartItem.getProdId()); + itemRequest.setQuantity(cartItem.getQuantity()); + itemRequest.setUnitPrice(BigDecimal.valueOf(cartItem.getUnitPrice())); + itemRequests.add(itemRequest); + } + request.setItems(itemRequests); + + SaleResponse response = SaleApi.getInstance().createSale(request); + showInfo("Sale saved", "Sale ID " + response.getId() + " was created."); cartItems.clear(); updateCartTotal(); - refreshInventory(); refreshSales(true); - } catch (SQLException e) { + } catch (Exception e) { ActivityLogger.getInstance().logException("SaleController.btnSaveSale", e, "Creating sale"); - showError("Create Sale", e.getMessage() == null ? "Could not save the sale." : e.getMessage()); - } catch (RuntimeException e) { - ActivityLogger.getInstance().logException("SaleController.btnSaveSale", e, "Database connection"); - showError("Create Sale", "Database is not connected."); + String errorMsg = e.getMessage(); + if (errorMsg != null && errorMsg.contains("Insufficient inventory")) { + showError("Create Sale", "Insufficient stock for one or more items."); + } else { + showError("Create Sale", errorMsg != null ? errorMsg : "Could not save the sale."); + } } } diff --git a/src/main/java/org/example/petshopdesktop/controllers/ServiceController.java b/src/main/java/org/example/petshopdesktop/controllers/ServiceController.java index 2f5ae849..493d893b 100644 --- a/src/main/java/org/example/petshopdesktop/controllers/ServiceController.java +++ b/src/main/java/org/example/petshopdesktop/controllers/ServiceController.java @@ -1,8 +1,8 @@ package org.example.petshopdesktop.controllers; +import javafx.application.Platform; import javafx.collections.FXCollections; import javafx.collections.ObservableList; -import javafx.collections.transformation.FilteredList; import javafx.event.ActionEvent; import javafx.fxml.FXML; import javafx.fxml.FXMLLoader; @@ -10,12 +10,17 @@ import javafx.scene.Scene; import javafx.scene.control.*; import javafx.scene.control.cell.PropertyValueFactory; import javafx.stage.Stage; -import org.example.petshopdesktop.database.ServiceDB; -import org.example.petshopdesktop.models.Service; +import org.example.petshopdesktop.DTOs.ServiceDTO; +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 javafx.stage.Modality; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + public class ServiceController { @@ -23,22 +28,23 @@ public class ServiceController { @FXML private Button btnDelete; @FXML private Button btnEdit; - @FXML private TableColumn colServiceId; - @FXML private TableColumn colServiceName; - @FXML private TableColumn colServiceDesc; - @FXML private TableColumn colServiceDuration; - @FXML private TableColumn colServicePrice; + @FXML private TableColumn colServiceId; + @FXML private TableColumn colServiceName; + @FXML private TableColumn colServiceDesc; + @FXML private TableColumn colServiceDuration; + @FXML private TableColumn colServicePrice; - @FXML private TableView tvServices; + @FXML private TableView tvServices; @FXML private TextField txtSearch; - private final ObservableList services = FXCollections.observableArrayList(); - private FilteredList filtered; + private ObservableList data = FXCollections.observableArrayList(); + private String mode = null; @FXML public void initialize() { - //Enable multiple selection + btnEdit.setDisable(true); + btnDelete.setDisable(true); tvServices.getSelectionModel().setSelectionMode(javafx.scene.control.SelectionMode.MULTIPLE); colServiceId.setCellValueFactory(new PropertyValueFactory<>("serviceId")); @@ -47,14 +53,19 @@ public class ServiceController { colServiceDuration.setCellValueFactory(new PropertyValueFactory<>("serviceDuration")); colServicePrice.setCellValueFactory(new PropertyValueFactory<>("servicePrice")); - filtered = new FilteredList<>(services, s -> true); - tvServices.setItems(filtered); + displayServices(); - if (txtSearch != null) { - txtSearch.textProperty().addListener((obs, o, n) -> applyFilter(n)); - } + tvServices.getSelectionModel().selectedItemProperty().addListener( + (observable, oldValue, newValue) -> { + btnEdit.setDisable(false); + btnDelete.setDisable(false); + } + ); + + txtSearch.textProperty().addListener((observable, oldValue, newValue) -> { + displayFilteredServices(newValue); + }); - //EventListener for DELETE key tvServices.setOnKeyPressed(event -> { if (event.getCode() == javafx.scene.input.KeyCode.DELETE) { if (tvServices.getSelectionModel().getSelectedItem() != null) { @@ -62,75 +73,82 @@ public class ServiceController { } } }); - - loadServices(); } - private void loadServices() { - try { - services.setAll(ServiceDB.getServices()); - } catch (Exception e) { - ActivityLogger.getInstance().logException( - "ServiceController.loadServices", - e, - "Loading services for table display"); - showAlert("Database Error", "Unable to load services."); - e.printStackTrace(); - } + private void displayServices() { + new Thread(() -> { + try { + List services = ServiceApi.getInstance().listServices(null); + List serviceDTOs = services.stream() + .map(this::mapToServiceDTO) + .collect(Collectors.toList()); + + Platform.runLater(() -> { + data.setAll(serviceDTOs); + tvServices.setItems(data); + }); + } catch (Exception e) { + Platform.runLater(() -> { + System.out.println("Error while fetching table data: " + e.getMessage()); + ActivityLogger.getInstance().logException( + "ServiceController.displayServices", + e, + "Fetching service data for table display"); + }); + } + }).start(); } - private void applyFilter(String text) { - if (filtered == null) { - return; + private void displayFilteredServices(String filter) { + if (txtSearch.getText() == null || txtSearch.getText().isEmpty()) { + displayServices(); + } else { + new Thread(() -> { + try { + List services = ServiceApi.getInstance().listServices(filter); + List serviceDTOs = services.stream() + .map(this::mapToServiceDTO) + .collect(Collectors.toList()); + + Platform.runLater(() -> { + data.setAll(serviceDTOs); + tvServices.setItems(data); + }); + } catch (Exception e) { + Platform.runLater(() -> { + System.out.println("Error while fetching table data: " + e.getMessage()); + ActivityLogger.getInstance().logException( + "ServiceController.displayFilteredServices", + e, + String.format("Filtering services with keyword: %s", filter)); + }); + } + }).start(); } - - String q = text == null ? "" : text.trim().toLowerCase(); - if (q.isEmpty()) { - filtered.setPredicate(s -> true); - return; - } - - filtered.setPredicate(s -> - String.valueOf(s.getServiceId()).contains(q) - || safe(s.getServiceName()).contains(q) - || safe(s.getServiceDesc()).contains(q) - || String.valueOf(s.getServiceDuration()).contains(q) - || String.valueOf(s.getServicePrice()).contains(q) - ); - } - - private static String safe(String v) { - return v == null ? "" : v.toLowerCase(); } @FXML void btnAddClicked(ActionEvent event) { - openDialog(null, "Add"); - loadServices(); + mode = "Add"; + openDialog(null, mode); } @FXML void btnEditClicked(ActionEvent event) { + ServiceDTO selected = tvServices.getSelectionModel().getSelectedItem(); - Service selected = tvServices.getSelectionModel().getSelectedItem(); - - if (selected == null) { - showAlert("Select Service", "Please select a service to edit."); - return; + if (selected != null) { + mode = "Edit"; + openDialog(selected, mode); } - - openDialog(selected, "Edit"); - loadServices(); } @FXML - void btnDeleteClicked(ActionEvent e) { - //get selected services + void btnDeleteClicked(ActionEvent event) { var selectedServices = tvServices.getSelectionModel().getSelectedItems(); if (selectedServices.isEmpty()) return; - //ask user to confirm Alert question = new Alert(Alert.AlertType.CONFIRMATION); question.setHeaderText("Please confirm delete"); String message = selectedServices.size() == 1 @@ -138,82 +156,78 @@ public class ServiceController { : "Are you sure you want to delete " + selectedServices.size() + " services?"; question.setContentText(message); question.getDialogPane().lookupButton(ButtonType.OK).requestFocus(); - java.util.Optional result = question.showAndWait(); + Optional result = question.showAndWait(); - //if confirmed, start deletion if (result.isPresent() && result.get() == ButtonType.OK) { - int successCount = 0; - int failCount = 0; - StringBuilder errors = new StringBuilder(); + List ids = selectedServices.stream() + .map(s -> (long) s.getServiceId()) + .collect(Collectors.toList()); - for (Service service : selectedServices) { - try { - ServiceDB.deleteService(service.getServiceId()); - successCount++; - } catch (Exception ex) { - ActivityLogger.getInstance().logException( - "ServiceController.btnDeleteClicked", - ex, - String.format("Attempting to delete service ID %d", service.getServiceId())); - failCount++; - errors.append("Failed to delete '").append(service.getServiceName()).append("'\n"); - } - } - - //show results - if (failCount > 0) { - Alert alert = new Alert(Alert.AlertType.WARNING); - alert.setHeaderText("Delete Operation Completed with Errors"); - alert.setContentText(String.format("Deleted: %d\nFailed: %d\n\n%s", - successCount, failCount, errors.toString())); - alert.showAndWait(); - } else if (successCount > 0) { + try { + ServiceApi.getInstance().deleteServices(ids); Alert alert = new Alert(Alert.AlertType.INFORMATION); alert.setHeaderText("Database Operation Confirmed"); - alert.setContentText("Successfully deleted " + successCount + " service(s)"); + alert.setContentText("Successfully deleted " + ids.size() + " service(s)"); + alert.showAndWait(); + } catch (Exception e) { + ActivityLogger.getInstance().logException( + "ServiceController.btnDeleteClicked", + e, + "Deleting services"); + Alert alert = new Alert(Alert.AlertType.ERROR); + alert.setHeaderText("Delete Operation Failed"); + alert.setContentText(e.getMessage()); alert.showAndWait(); } - //refresh display - loadServices(); + displayServices(); + btnDelete.setDisable(true); + btnEdit.setDisable(true); + txtSearch.setText(""); } } - private void openDialog(Service service, String mode) { - + private void openDialog(ServiceDTO service, String mode) { + FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/org/example/petshopdesktop/dialogviews/service-dialog-view.fxml")); + Scene scene = null; try { - FXMLLoader loader = new FXMLLoader( - getClass().getResource("/org/example/petshopdesktop/dialogviews/service-dialog-view.fxml") - ); - - Stage stage = new Stage(); - stage.setScene(new Scene(loader.load())); - - ServiceDialogController controller = loader.getController(); - controller.setMode(mode); - - if (mode.equals("Edit")) { - controller.setService(service); - } - - stage.initModality(Modality.APPLICATION_MODAL); - stage.showAndWait(); - - loadServices(); - + scene = new Scene(fxmlLoader.load()); } catch (Exception e) { ActivityLogger.getInstance().logException( "ServiceController.openDialog", e, - "Opening service dialog in " + mode + " mode"); - e.printStackTrace(); + String.format("Loading service dialog view in %s mode", mode)); + throw new RuntimeException(e); } + ServiceDialogController dialogController = fxmlLoader.getController(); + dialogController.setMode(mode); + + if (mode.equals("Edit")) { + dialogController.setService(service); + } + Stage dialogStage = new Stage(); + dialogStage.initModality(Modality.APPLICATION_MODAL); + if (mode.equals("Add")) { + dialogStage.setTitle("Add Service"); + } else { + dialogStage.setTitle("Edit Service"); + } + dialogStage.setScene(scene); + dialogStage.showAndWait(); + + displayServices(); + btnDelete.setDisable(true); + btnEdit.setDisable(true); + txtSearch.setText(""); } - private void showAlert(String title, String msg) { - Alert alert = new Alert(Alert.AlertType.INFORMATION); - alert.setTitle(title); - alert.setHeaderText(null); - alert.setContentText(msg); - alert.showAndWait(); + + private ServiceDTO mapToServiceDTO(ServiceResponse response) { + return new ServiceDTO( + response.getId().intValue(), + response.getServiceName(), + response.getDescription(), + 0, + response.getPrice().doubleValue() + ); } } \ No newline at end of file diff --git a/src/main/java/org/example/petshopdesktop/controllers/StaffAccountsController.java b/src/main/java/org/example/petshopdesktop/controllers/StaffAccountsController.java index 6006bb15..eefcb73d 100644 --- a/src/main/java/org/example/petshopdesktop/controllers/StaffAccountsController.java +++ b/src/main/java/org/example/petshopdesktop/controllers/StaffAccountsController.java @@ -1,5 +1,6 @@ package org.example.petshopdesktop.controllers; +import javafx.application.Platform; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.collections.transformation.FilteredList; @@ -15,12 +16,16 @@ import javafx.scene.control.TextField; import javafx.scene.control.cell.PropertyValueFactory; import javafx.stage.Modality; import javafx.stage.Stage; +import org.example.petshopdesktop.api.dto.user.UserResponse; +import org.example.petshopdesktop.api.endpoints.UserApi; import org.example.petshopdesktop.auth.UserSession; -import org.example.petshopdesktop.database.UserDB; import org.example.petshopdesktop.models.StaffAccount; import org.example.petshopdesktop.util.ActivityLogger; -import java.sql.SQLException; +import java.sql.Timestamp; +import java.time.ZoneId; +import java.util.List; +import java.util.stream.Collectors; public class StaffAccountsController { @@ -107,15 +112,54 @@ public class StaffAccountsController { private void refresh() { lblError.setText(""); - try { - staffAccounts.setAll(UserDB.getStaffAccounts()); - } catch (SQLException e) { - ActivityLogger.getInstance().logException("StaffAccountsController.refresh", e, "Loading staff accounts"); - lblError.setText("Could not load staff accounts."); - } catch (RuntimeException e) { - ActivityLogger.getInstance().logException("StaffAccountsController.refresh", e, "Database connection"); - lblError.setText("Database is not connected."); + tvStaff.setDisable(true); + + new Thread(() -> { + try { + List users = UserApi.getInstance().listUsers(null); + List accounts = users.stream() + .map(this::mapToStaffAccount) + .collect(Collectors.toList()); + + Platform.runLater(() -> { + staffAccounts.setAll(accounts); + tvStaff.setDisable(false); + }); + } catch (Exception e) { + ActivityLogger.getInstance().logException("StaffAccountsController.refresh", e, "Loading staff accounts"); + Platform.runLater(() -> { + lblError.setText("Could not load staff accounts."); + tvStaff.setDisable(false); + }); + } + }).start(); + } + + private StaffAccount mapToStaffAccount(UserResponse user) { + long id = user.getId() != null ? user.getId() : 0L; + String username = user.getUsername(); + String fullName = user.getFullName() != null ? user.getFullName() : ""; + String[] names = splitFullName(fullName); + String firstName = names[0]; + String lastName = names[1]; + String email = ""; + String phone = ""; + boolean active = user.getActive() != null ? user.getActive() : false; + Timestamp createdAt = user.getCreatedAt() != null + ? Timestamp.from(user.getCreatedAt().atZone(ZoneId.systemDefault()).toInstant()) + : null; + + return new StaffAccount(id, id, username, firstName, lastName, email, phone, active, createdAt); + } + + private String[] splitFullName(String fullName) { + if (fullName == null || fullName.trim().isEmpty()) { + return new String[]{"", ""}; } + String[] parts = fullName.trim().split("\\s+", 2); + String firstName = parts.length > 0 ? parts[0] : ""; + String lastName = parts.length > 1 ? parts[1] : ""; + return new String[]{firstName, lastName}; } private void applyFilter(String text) { diff --git a/src/main/java/org/example/petshopdesktop/controllers/SupplierController.java b/src/main/java/org/example/petshopdesktop/controllers/SupplierController.java index 049bddbd..144c85ea 100644 --- a/src/main/java/org/example/petshopdesktop/controllers/SupplierController.java +++ b/src/main/java/org/example/petshopdesktop/controllers/SupplierController.java @@ -1,5 +1,6 @@ package org.example.petshopdesktop.controllers; +import javafx.application.Platform; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.event.ActionEvent; @@ -10,15 +11,16 @@ import javafx.scene.control.*; import javafx.scene.control.cell.PropertyValueFactory; import javafx.stage.Modality; import javafx.stage.Stage; +import org.example.petshopdesktop.api.dto.supplier.SupplierResponse; +import org.example.petshopdesktop.api.endpoints.SupplierApi; import org.example.petshopdesktop.controllers.dialogcontrollers.SupplierDialogController; -import org.example.petshopdesktop.database.SupplierDB; import org.example.petshopdesktop.models.Supplier; import org.example.petshopdesktop.util.ActivityLogger; import java.io.IOException; -import java.sql.SQLException; -import java.sql.SQLIntegrityConstraintViolationException; +import java.util.List; import java.util.Optional; +import java.util.stream.Collectors; /** * The controller for any operations in the supplier view @@ -105,19 +107,27 @@ public class SupplierController { * Display the suppliers to table view */ private void displaySupplier(){ - data.clear(); + new Thread(() -> { + try { + List suppliers = SupplierApi.getInstance().listSuppliers(null); + List supplierList = suppliers.stream() + .map(this::mapToSupplier) + .collect(Collectors.toList()); - try{ - data = SupplierDB.getSuppliers(); - } catch (SQLException e) { - ActivityLogger.getInstance().logException( - "SupplierController.displaySupplier", - e, - "Fetching supplier data for table display"); - System.out.println("Error while fetching table data: " + e.getMessage()); - } - - tvSuppliers.setItems(data); + Platform.runLater(() -> { + data.setAll(supplierList); + tvSuppliers.setItems(data); + }); + } catch (Exception e) { + Platform.runLater(() -> { + System.out.println("Error while fetching table data: " + e.getMessage()); + ActivityLogger.getInstance().logException( + "SupplierController.displaySupplier", + e, + "Fetching supplier data for table display"); + }); + } + }).start(); } /** @@ -125,22 +135,30 @@ public class SupplierController { * @param filter word to filter table */ private void displayFilteredSupplier(String filter){ - data.clear(); - try{ - if (txtSearch.getText() == null || txtSearch.getText().isEmpty()){ - displaySupplier(); //If search bar is empty just display everything - } - else{ - //Filter the using the keyword - data = SupplierDB.getFilteredSuppliers(filter); - tvSuppliers.setItems(data); - } - } catch (Exception e) { - ActivityLogger.getInstance().logException( - "SupplierController.displayFilteredSupplier", - e, - "Filtering suppliers with filter: " + filter); - System.out.println("Error while fetching table data: " + e.getMessage()); + if (txtSearch.getText() == null || txtSearch.getText().isEmpty()){ + displaySupplier(); + } else { + new Thread(() -> { + try { + List suppliers = SupplierApi.getInstance().listSuppliers(filter); + List supplierList = suppliers.stream() + .map(this::mapToSupplier) + .collect(Collectors.toList()); + + Platform.runLater(() -> { + data.setAll(supplierList); + tvSuppliers.setItems(data); + }); + } catch (Exception e) { + Platform.runLater(() -> { + System.out.println("Error while fetching table data: " + e.getMessage()); + ActivityLogger.getInstance().logException( + "SupplierController.displayFilteredSupplier", + e, + "Filtering suppliers with filter: " + filter); + }); + } + }).start(); } } @@ -177,48 +195,24 @@ public class SupplierController { //if confirmed, start deletion if (result.isPresent() && result.get() == ButtonType.OK) { - int successCount = 0; - int failCount = 0; - StringBuilder errors = new StringBuilder(); + List ids = selectedSuppliers.stream() + .map(s -> (long) s.getSupId()) + .collect(Collectors.toList()); - for (Supplier supplier : selectedSuppliers) { - try{ - int numRows = SupplierDB.deleteSupplier(supplier.getSupId()); - if (numRows > 0) { - successCount++; - } else { - failCount++; - } - } - catch (SQLIntegrityConstraintViolationException e){ - ActivityLogger.getInstance().logException( - "SupplierController.btnDeleteClicked", - e, - String.format("Attempting to delete supplier ID %d - foreign key constraint", supplier.getSupId())); - failCount++; - errors.append("Supplier '").append(supplier.getSupCompany()).append("' is referenced in another table\n"); - } - catch (SQLException e) { - ActivityLogger.getInstance().logException( - "SupplierController.btnDeleteClicked", - e, - String.format("Attempting to delete supplier ID %d", supplier.getSupId())); - failCount++; - errors.append("Failed to delete '").append(supplier.getSupCompany()).append("'\n"); - } - } - - //show results - if (failCount > 0) { - Alert alert = new Alert(Alert.AlertType.WARNING); - alert.setHeaderText("Delete Operation Completed with Errors"); - alert.setContentText(String.format("Deleted: %d\nFailed: %d\n\n%s", - successCount, failCount, errors.toString())); - alert.showAndWait(); - } else if (successCount > 0) { + try { + SupplierApi.getInstance().deleteSuppliers(ids); Alert alert = new Alert(Alert.AlertType.INFORMATION); alert.setHeaderText("Database Operation Confirmed"); - alert.setContentText("Successfully deleted " + successCount + " supplier(s)"); + alert.setContentText("Successfully deleted " + ids.size() + " supplier(s)"); + alert.showAndWait(); + } catch (Exception e) { + ActivityLogger.getInstance().logException( + "SupplierController.btnDeleteClicked", + e, + "Deleting suppliers"); + Alert alert = new Alert(Alert.AlertType.ERROR); + alert.setHeaderText("Delete Operation Failed"); + alert.setContentText(e.getMessage()); alert.showAndWait(); } @@ -290,4 +284,20 @@ public class SupplierController { txtSearch.setText(""); } + private Supplier mapToSupplier(SupplierResponse response) { + String contactPerson = response.getContactPerson() != null ? response.getContactPerson() : ""; + String[] nameParts = contactPerson.split(" ", 2); + String firstName = nameParts.length > 0 ? nameParts[0] : ""; + String lastName = nameParts.length > 1 ? nameParts[1] : ""; + + return new Supplier( + response.getId().intValue(), + response.getSupplierName(), + firstName, + lastName, + response.getEmail(), + response.getPhone() + ); + } + } \ No newline at end of file diff --git a/src/main/java/org/example/petshopdesktop/controllers/dialogcontrollers/AdoptionDialogController.java b/src/main/java/org/example/petshopdesktop/controllers/dialogcontrollers/AdoptionDialogController.java index 213426f9..ed1fca7c 100644 --- a/src/main/java/org/example/petshopdesktop/controllers/dialogcontrollers/AdoptionDialogController.java +++ b/src/main/java/org/example/petshopdesktop/controllers/dialogcontrollers/AdoptionDialogController.java @@ -1,5 +1,6 @@ package org.example.petshopdesktop.controllers.dialogcontrollers; +import javafx.application.Platform; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.event.EventHandler; @@ -12,16 +13,15 @@ import javafx.scene.control.DatePicker; import javafx.scene.control.Label; import javafx.scene.input.MouseEvent; import javafx.stage.Stage; -import javafx.util.StringConverter; -import org.example.petshopdesktop.database.AdoptionDB; -import org.example.petshopdesktop.database.PetDB; +import org.example.petshopdesktop.api.dto.adoption.AdoptionRequest; +import org.example.petshopdesktop.api.dto.common.DropdownOption; +import org.example.petshopdesktop.api.endpoints.AdoptionApi; +import org.example.petshopdesktop.api.endpoints.DropdownApi; import org.example.petshopdesktop.models.Adoption; -import org.example.petshopdesktop.models.Customer; -import org.example.petshopdesktop.models.Pet; import org.example.petshopdesktop.util.ActivityLogger; -import java.sql.SQLException; import java.time.LocalDate; +import java.util.List; public class AdoptionDialogController { @@ -36,10 +36,10 @@ public class AdoptionDialogController { private ComboBox cbAdoptionStatus; @FXML - private ComboBox cbCustomer; + private ComboBox cbCustomer; @FXML - private ComboBox cbPet; + private ComboBox cbPet; @FXML private DatePicker dpAdoptionDate; @@ -58,52 +58,47 @@ public class AdoptionDialogController { "Pending", "Completed", "Cancelled" ); - //Loads upon boot @FXML void initialize() { - //Loads statusList into combo box cbAdoptionStatus.setItems(statusList); - //Pet objects are converted into readable text for combobox (PetID + PetName) - cbPet.setConverter(new StringConverter() { - @Override - public String toString(Pet pet) { - return pet == null ? "" : pet.getPetId() + ": " + pet.getPetName(); + new Thread(() -> { + try { + List pets = DropdownApi.getInstance().getPets(); + Platform.runLater(() -> { + ObservableList petsObs = FXCollections.observableArrayList(pets); + cbPet.setItems(petsObs); + }); + } catch (Exception e) { + Platform.runLater(() -> { + ActivityLogger.getInstance().logException( + "AdoptionDialogController.initialize", + e, + "Loading pets for combo box"); + System.out.println("Error loading pets: " + e.getMessage()); + }); } + }).start(); - //Not used - @Override - public Pet fromString(String string) { return null; } - }); + new Thread(() -> { + try { + List customers = DropdownApi.getInstance().getCustomers(); + Platform.runLater(() -> { + ObservableList customersObs = FXCollections.observableArrayList(customers); + cbCustomer.setItems(customersObs); + }); + } catch (Exception e) { + Platform.runLater(() -> { + ActivityLogger.getInstance().logException( + "AdoptionDialogController.initialize", + e, + "Loading customers for combo box"); + System.out.println("Error loading customers: " + e.getMessage()); + }); + } + }).start(); - //Load pets from DB into pet combobox - try { - cbPet.setItems(PetDB.getPets()); - } - - catch (SQLException e) { - ActivityLogger.getInstance().logException( - "AdoptionDialogController.initialize", - e, - "Loading pets for combo box"); - System.out.println("Error loading pets: " + e.getMessage()); - } - - //Load customers from DB into customer combobox - try { - cbCustomer.setItems(AdoptionDB.getCustomers()); - } - - catch (SQLException e) { - ActivityLogger.getInstance().logException( - "AdoptionDialogController.initialize", - e, - "Loading customers for combo box"); - System.out.println("Error loading customers: " + e.getMessage()); - } - - //Save button handler btnSave.setOnMouseClicked(new EventHandler() { @Override public void handle(MouseEvent mouseEvent) { @@ -111,7 +106,6 @@ public class AdoptionDialogController { } }); - //Cancel button handler, closes dialog view btnCancel.setOnMouseClicked(new EventHandler() { @Override public void handle(MouseEvent mouseEvent) { @@ -120,12 +114,9 @@ public class AdoptionDialogController { }); } - //Handles logic when clicking Save private void buttonSaveClicked(MouseEvent mouseEvent) { - int numRow = 0; String errorMsg = ""; - //Validation: checks if anything is missing if (cbPet.getSelectionModel().getSelectedItem() == null) { errorMsg += "Pet is required.\n"; } @@ -142,60 +133,37 @@ public class AdoptionDialogController { errorMsg += "Status is required.\n"; } - //If no errors, attempt DB operation if (errorMsg.isEmpty()) { - Adoption adoption = collectAdoption(); + try { + AdoptionRequest request = new AdoptionRequest(); + request.setPetId(cbPet.getSelectionModel().getSelectedItem().getId()); + request.setCustomerId(cbCustomer.getSelectionModel().getSelectedItem().getId()); + request.setAdoptionDate(dpAdoptionDate.getValue()); + request.setAdoptionStatus(cbAdoptionStatus.getValue()); - //Try inserting into DB - if (mode.equals("Add")) { - try { - numRow = AdoptionDB.insertAdoption(adoption); + if (mode.equals("Add")) { + AdoptionApi.getInstance().createAdoption(request); + } else { + Long adoptionId = Long.parseLong(lblAdoptionId.getText().split(": ")[1]); + AdoptionApi.getInstance().updateAdoption(adoptionId, request); } - catch (SQLException e) { - ActivityLogger.getInstance().logException( - "AdoptionDialogController.buttonSaveClicked", - e, - "Inserting new adoption record"); - throw new RuntimeException(e); - } - } - - //Try updating adoption - else { - try { - numRow = AdoptionDB.updateAdoption(adoption.getAdoptionId(), adoption); - } - - catch (SQLException e) { - ActivityLogger.getInstance().logException( - "AdoptionDialogController.buttonSaveClicked", - e, - "Updating adoption with ID: " + adoption.getAdoptionId()); - throw new RuntimeException(e); - } - } - - //If no rows are affected, an issue has occurred - if (numRow == 0) { - Alert alert = new Alert(Alert.AlertType.ERROR); - alert.setHeaderText("Database Operation Error"); - alert.setContentText(mode + " failed"); - alert.showAndWait(); - } - - //DB operation worked! - else { Alert alert = new Alert(Alert.AlertType.INFORMATION); alert.setHeaderText("Saved"); alert.setContentText(mode + " succeeded"); alert.showAndWait(); closeStage(mouseEvent); + } catch (Exception e) { + ActivityLogger.getInstance().logException( + "AdoptionDialogController.buttonSaveClicked", + e, + mode + " adoption"); + Alert alert = new Alert(Alert.AlertType.ERROR); + alert.setHeaderText("Database Operation Error"); + alert.setContentText(e.getMessage()); + alert.showAndWait(); } - } - - //If there are errors, display them - else { + } else { Alert alert = new Alert(Alert.AlertType.ERROR); alert.setHeaderText("Input Error"); alert.setContentText(errorMsg); @@ -203,30 +171,6 @@ public class AdoptionDialogController { } } - //Collects user input, builds an Adoption object - private Adoption collectAdoption() { - int adoptionId = 0; - - //Only grab adoption ID if in edit mode - if (lblAdoptionId.isVisible()) { - adoptionId = Integer.parseInt(lblAdoptionId.getText().split(": ")[1]); - } - - Pet selectedPet = cbPet.getSelectionModel().getSelectedItem(); - Customer selectedCustomer = cbCustomer.getSelectionModel().getSelectedItem(); - String date = dpAdoptionDate.getValue().toString(); - String status = cbAdoptionStatus.getValue(); - - return new Adoption( - adoptionId, - selectedPet.getPetId(), - selectedCustomer.getCustomerId(), - selectedCustomer.toString(), - date, - selectedPet.getPetPrice(), - status - ); - } private void closeStage(MouseEvent mouseEvent) { Node node = (Node) mouseEvent.getSource(); @@ -234,35 +178,28 @@ public class AdoptionDialogController { stage.close(); } - //Edit mode - //Inserts data into fields public void displayAdoptionDetails(Adoption adoption) { if (adoption != null) { - //Displays adoption ID lblAdoptionId.setText("ID: " + adoption.getAdoptionId()); - //Select pet - for (Pet pet : cbPet.getItems()) { - if (pet.getPetId() == adoption.getPetId()) { + for (DropdownOption pet : cbPet.getItems()) { + if (pet.getLabel().equals(adoption.getPetName())) { cbPet.getSelectionModel().select(pet); break; } } - //Select customer - for (Customer customer : cbCustomer.getItems()) { - if (customer.getCustomerId() == adoption.getCustomerId()) { + for (DropdownOption customer : cbCustomer.getItems()) { + if (customer.getLabel().equals(adoption.getCustomerName())) { cbCustomer.getSelectionModel().select(customer); break; } } - //Select adoption date if (adoption.getAdoptionDate() != null && !adoption.getAdoptionDate().isEmpty()) { dpAdoptionDate.setValue(LocalDate.parse(adoption.getAdoptionDate())); } - //Select adoption status for (String status : cbAdoptionStatus.getItems()) { if (status.equals(adoption.getAdoptionStatus())) { cbAdoptionStatus.getSelectionModel().select(status); @@ -272,8 +209,6 @@ public class AdoptionDialogController { } } - //Sets dialog mode - //Also updates label and adoption ID visibility public void setMode(String mode) { this.mode = mode; lblMode.setText(mode + " Adoption"); diff --git a/src/main/java/org/example/petshopdesktop/controllers/dialogcontrollers/AppointmentDialogController.java b/src/main/java/org/example/petshopdesktop/controllers/dialogcontrollers/AppointmentDialogController.java index 411e230b..ecefa73c 100644 --- a/src/main/java/org/example/petshopdesktop/controllers/dialogcontrollers/AppointmentDialogController.java +++ b/src/main/java/org/example/petshopdesktop/controllers/dialogcontrollers/AppointmentDialogController.java @@ -1,5 +1,6 @@ package org.example.petshopdesktop.controllers.dialogcontrollers; +import javafx.application.Platform; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.fxml.FXML; @@ -10,11 +11,16 @@ import javafx.stage.Stage; import javafx.scene.control.ListCell; import org.example.petshopdesktop.DTOs.AppointmentDTO; -import org.example.petshopdesktop.database.*; -import org.example.petshopdesktop.models.*; +import org.example.petshopdesktop.api.dto.appointment.AppointmentRequest; +import org.example.petshopdesktop.api.dto.appointment.AppointmentResponse; +import org.example.petshopdesktop.api.dto.common.DropdownOption; +import org.example.petshopdesktop.api.endpoints.AppointmentApi; +import org.example.petshopdesktop.api.endpoints.DropdownApi; import org.example.petshopdesktop.util.ActivityLogger; -import java.sql.Time; +import java.time.LocalTime; +import java.util.Collections; +import java.util.List; public class AppointmentDialogController { @@ -25,9 +31,9 @@ public class AppointmentDialogController { @FXML private Button btnCancel; @FXML private Button btnSave; - @FXML private ComboBox cbService; - @FXML private ComboBox cbCustomer; - @FXML private ComboBox cbPet; + @FXML private ComboBox cbService; + @FXML private ComboBox cbCustomer; + @FXML private ComboBox cbPet; @FXML private ComboBox cbHour; @FXML private ComboBox cbMinute; @@ -67,17 +73,27 @@ public class AppointmentDialogController { @FXML public void initialize() { - try { - cbService.setItems(ServiceDB.getServices()); - cbCustomer.setItems(CustomerDB.getCustomers()); - cbPet.setItems(PetDB.getPets()); - } catch (Exception e) { - ActivityLogger.getInstance().logException( - "AppointmentDialogController.initialize", - e, - "Loading combo box data for services, customers, and pets"); - e.printStackTrace(); - } + new Thread(() -> { + try { + List services = DropdownApi.getInstance().getServices(); + List customers = DropdownApi.getInstance().getCustomers(); + List pets = DropdownApi.getInstance().getPets(); + + Platform.runLater(() -> { + cbService.setItems(FXCollections.observableArrayList(services)); + cbCustomer.setItems(FXCollections.observableArrayList(customers)); + cbPet.setItems(FXCollections.observableArrayList(pets)); + }); + } catch (Exception e) { + Platform.runLater(() -> { + ActivityLogger.getInstance().logException( + "AppointmentDialogController.initialize", + e, + "Loading combo box data for services, customers, and pets"); + e.printStackTrace(); + }); + } + }).start(); cbAppointmentStatus.setItems(statusList); @@ -88,20 +104,49 @@ public class AppointmentDialogController { cbMinute.getItems().addAll(0, 15, 30, 45); - // Show pet name - cbPet.setCellFactory(param -> new ListCell<>() { + // Show dropdown labels + cbService.setCellFactory(param -> new ListCell<>() { @Override - protected void updateItem(Pet pet, boolean empty) { - super.updateItem(pet, empty); - setText(empty || pet == null ? null : pet.getPetName()); + protected void updateItem(DropdownOption option, boolean empty) { + super.updateItem(option, empty); + setText(empty || option == null ? null : option.getLabel()); + } + }); + cbService.setButtonCell(new ListCell<>() { + @Override + protected void updateItem(DropdownOption option, boolean empty) { + super.updateItem(option, empty); + setText(empty || option == null ? null : option.getLabel()); } }); + cbCustomer.setCellFactory(param -> new ListCell<>() { + @Override + protected void updateItem(DropdownOption option, boolean empty) { + super.updateItem(option, empty); + setText(empty || option == null ? null : option.getLabel()); + } + }); + cbCustomer.setButtonCell(new ListCell<>() { + @Override + protected void updateItem(DropdownOption option, boolean empty) { + super.updateItem(option, empty); + setText(empty || option == null ? null : option.getLabel()); + } + }); + + cbPet.setCellFactory(param -> new ListCell<>() { + @Override + protected void updateItem(DropdownOption option, boolean empty) { + super.updateItem(option, empty); + setText(empty || option == null ? null : option.getLabel()); + } + }); cbPet.setButtonCell(new ListCell<>() { @Override - protected void updateItem(Pet pet, boolean empty) { - super.updateItem(pet, empty); - setText(empty || pet == null ? null : pet.getPetName()); + protected void updateItem(DropdownOption option, boolean empty) { + super.updateItem(option, empty); + setText(empty || option == null ? null : option.getLabel()); } }); @@ -124,20 +169,20 @@ public class AppointmentDialogController { cbAppointmentStatus.setValue(appt.getAppointmentStatus()); - Time time = Time.valueOf(appt.getAppointmentTime()); - cbHour.setValue(time.toLocalTime().getHour()); - cbMinute.setValue(time.toLocalTime().getMinute()); + LocalTime time = LocalTime.parse(appt.getAppointmentTime()); + cbHour.setValue(time.getHour()); + cbMinute.setValue(time.getMinute()); cbService.getItems().forEach(s -> { - if (s.getServiceId() == appt.getServiceId()) cbService.setValue(s); + if (s.getId() == appt.getServiceId()) cbService.setValue(s); }); cbCustomer.getItems().forEach(c -> { - if (c.getCustomerId() == appt.getCustomerId()) cbCustomer.setValue(c); + if (c.getId() == appt.getCustomerId()) cbCustomer.setValue(c); }); cbPet.getItems().forEach(p -> { - if (p.getPetId() == appt.getPetId()) cbPet.setValue(p); + if (p.getId() == appt.getPetId()) cbPet.setValue(p); }); } @@ -159,45 +204,40 @@ public class AppointmentDialogController { return; } - Time appointmentTime = - Time.valueOf(String.format( - "%02d:%02d:00", - cbHour.getValue(), - cbMinute.getValue() - )); + LocalTime appointmentTime = LocalTime.of(cbHour.getValue(), cbMinute.getValue()); - Appointment appt = new Appointment( - selectedAppointment == null ? 0 : selectedAppointment.getAppointmentId(), - cbService.getValue().getServiceId(), - cbCustomer.getValue().getCustomerId(), - dpAppointmentDate.getValue().toString(), - appointmentTime.toString(), - cbAppointmentStatus.getValue() - ); + AppointmentRequest request = new AppointmentRequest(); + request.setPetIds(Collections.singletonList(cbPet.getValue().getId())); + request.setCustomerId(cbCustomer.getValue().getId()); + request.setServiceId(cbService.getValue().getId()); + request.setAppointmentDate(dpAppointmentDate.getValue()); + request.setAppointmentTime(appointmentTime); + request.setAppointmentStatus(cbAppointmentStatus.getValue()); - try { + new Thread(() -> { + try { + if (mode.equals("Add")) { + AppointmentApi.getInstance().createAppointment(request); + } else { + AppointmentApi.getInstance().updateAppointment( + (long) selectedAppointment.getAppointmentId(), + request + ); + } - if (mode.equals("Add")) { - int newId = AppointmentDB.insertAppointment(appt); - AppointmentDB.insertAppointmentPet(newId, cbPet.getValue().getPetId()); - } else { - AppointmentDB.updateAppointment( - selectedAppointment.getAppointmentId(), - appt, - cbPet.getValue().getPetId() - ); + Platform.runLater(() -> closeStage(e)); + + } catch (Exception ex) { + Platform.runLater(() -> { + ActivityLogger.getInstance().logException( + "AppointmentDialogController.buttonSaveClicked", + ex, + "Saving appointment in " + mode + " mode"); + ex.printStackTrace(); + showError("Error saving appointment: " + ex.getMessage()); + }); } - - closeStage(e); - - } catch (Exception ex) { - ActivityLogger.getInstance().logException( - "AppointmentDialogController.buttonSaveClicked", - ex, - "Saving appointment in " + mode + " mode"); - ex.printStackTrace(); - showError("Error saving appointment"); - } + }).start(); } // diff --git a/src/main/java/org/example/petshopdesktop/controllers/dialogcontrollers/ProductSupplierDialogController.java b/src/main/java/org/example/petshopdesktop/controllers/dialogcontrollers/ProductSupplierDialogController.java index 154c62fd..a94a6012 100644 --- a/src/main/java/org/example/petshopdesktop/controllers/dialogcontrollers/ProductSupplierDialogController.java +++ b/src/main/java/org/example/petshopdesktop/controllers/dialogcontrollers/ProductSupplierDialogController.java @@ -1,5 +1,6 @@ package org.example.petshopdesktop.controllers.dialogcontrollers; +import javafx.application.Platform; import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.event.EventHandler; @@ -10,16 +11,14 @@ import javafx.scene.input.MouseEvent; import javafx.stage.Stage; import org.example.petshopdesktop.DTOs.ProductSupplierDTO; import org.example.petshopdesktop.Validator; -import org.example.petshopdesktop.database.ProductDB; -import org.example.petshopdesktop.database.ProductSupplierDB; -import org.example.petshopdesktop.database.SupplierDB; -import org.example.petshopdesktop.models.Product; -import org.example.petshopdesktop.models.ProductSupplier; -import org.example.petshopdesktop.models.Supplier; +import org.example.petshopdesktop.api.dto.common.DropdownOption; +import org.example.petshopdesktop.api.dto.productsupplier.ProductSupplierRequest; +import org.example.petshopdesktop.api.dto.productsupplier.ProductSupplierResponse; +import org.example.petshopdesktop.api.endpoints.DropdownApi; +import org.example.petshopdesktop.api.endpoints.ProductSupplierApi; import org.example.petshopdesktop.util.ActivityLogger; -import java.sql.SQLException; -import java.sql.SQLIntegrityConstraintViolationException; +import java.math.BigDecimal; public class ProductSupplierDialogController { @@ -30,10 +29,10 @@ public class ProductSupplierDialogController { private Button btnSave; @FXML - private ComboBox cbProduct; + private ComboBox cbProduct; @FXML - private ComboBox cbSupplier; + private ComboBox cbSupplier; @FXML private Label lblMode; @@ -47,6 +46,7 @@ public class ProductSupplierDialogController { private String mode = null; private int selectedSupId = -1; private int selectedProdId = -1; + private Long selectedId = null; /** * add event listeners to buttons and set up combobox @@ -67,26 +67,74 @@ public class ProductSupplierDialogController { } }); - //Set up combobox for selecting product and supplier - try{ - ObservableList suppliers = FXCollections.observableArrayList(); //empty list - ObservableList products = FXCollections.observableArrayList(); //empty list + cbSupplier.setButtonCell(new ListCell() { + @Override + protected void updateItem(DropdownOption item, boolean empty) { + super.updateItem(item, empty); + if (empty || item == null) { + setText(null); + } else { + setText(item.getLabel()); + } + } + }); + cbSupplier.setCellFactory(lv -> new ListCell() { + @Override + protected void updateItem(DropdownOption item, boolean empty) { + super.updateItem(item, empty); + if (empty || item == null) { + setText(null); + } else { + setText(item.getLabel()); + } + } + }); - //get suppliers and products from DB - suppliers = SupplierDB.getSuppliers(); - products = ProductDB.getProducts(); + cbProduct.setButtonCell(new ListCell() { + @Override + protected void updateItem(DropdownOption item, boolean empty) { + super.updateItem(item, empty); + if (empty || item == null) { + setText(null); + } else { + setText(item.getLabel()); + } + } + }); + cbProduct.setCellFactory(lv -> new ListCell() { + @Override + protected void updateItem(DropdownOption item, boolean empty) { + super.updateItem(item, empty); + if (empty || item == null) { + setText(null); + } else { + setText(item.getLabel()); + } + } + }); - //Populate combobox - cbSupplier.setItems(suppliers); - cbProduct.setItems(products); - } - catch(SQLException e){ - ActivityLogger.getInstance().logException( - "ProductSupplierDialogController.initialize", - e, - "Loading suppliers and products for combo boxes"); - throw new RuntimeException(e); - } + new Thread(() -> { + try { + var suppliers = DropdownApi.getInstance().getSuppliers(); + var products = DropdownApi.getInstance().getProducts(); + + Platform.runLater(() -> { + cbSupplier.setItems(FXCollections.observableArrayList(suppliers)); + cbProduct.setItems(FXCollections.observableArrayList(products)); + }); + } catch (Exception e) { + Platform.runLater(() -> { + ActivityLogger.getInstance().logException( + "ProductSupplierDialogController.initialize", + e, + "Loading suppliers and products for combo boxes"); + Alert alert = new Alert(Alert.AlertType.ERROR); + alert.setHeaderText("Initialization Error"); + alert.setContentText("Failed to load dropdown data: " + e.getMessage()); + alert.showAndWait(); + }); + } + }).start(); } @@ -96,10 +144,8 @@ public class ProductSupplierDialogController { * @param mouseEvent click event for save button */ private void buttonSaveClicked(MouseEvent mouseEvent) { - int numRows = 0; - String errorMsg = ""; //error message for validation + String errorMsg = ""; - //Check Validation (input required) errorMsg += Validator.isPresent(txtCost.getText(), "Cost"); if (cbProduct.getSelectionModel().getSelectedItem() == null) { errorMsg += "Product is required \n"; @@ -108,82 +154,41 @@ public class ProductSupplierDialogController { errorMsg += "Supplier is required \n"; } - //Check validation (length size) errorMsg += Validator.isLessThanVarChars(txtCost.getText(), "Cost", 12); - - //Check validation (format) errorMsg += Validator.isNonNegativeDouble(txtCost.getText(), "Cost"); - if(errorMsg.isEmpty()){ //no validation errors - ProductSupplier productSupplier = collectProductSupplier(); //get productSupplier info - if (mode.equals("Add")) { //add mode - try{ - numRows = ProductSupplierDB.insertProductSupplier(productSupplier); - } - catch(SQLIntegrityConstraintViolationException e){ - ActivityLogger.getInstance().logException( - "ProductSupplierDialogController.buttonSaveClicked", - e, - "Inserting product-supplier (integrity constraint violation)"); - Alert alert = new Alert(Alert.AlertType.ERROR); - alert.setHeaderText("Database Operation Error"); - alert.setContentText("Add failed \n" + - "the product-supplier link is already in the database"); - alert.showAndWait(); - numRows = -1; //Update numRow so alert only shows once - closeStage(mouseEvent); - } - catch(SQLException e){ - ActivityLogger.getInstance().logException( - "ProductSupplierDialogController.buttonSaveClicked", - e, - "Inserting new product-supplier record"); - throw new RuntimeException(e); - } - } - else { //edit - try{ - numRows = ProductSupplierDB.updateProductSupplier(selectedSupId, selectedProdId, productSupplier); - } - catch(SQLIntegrityConstraintViolationException e){ - ActivityLogger.getInstance().logException( - "ProductSupplierDialogController.buttonSaveClicked", - e, - "Updating product-supplier (integrity constraint violation) - SupID: " + selectedSupId + ", ProdID: " + selectedProdId); - Alert alert = new Alert(Alert.AlertType.ERROR); - alert.setHeaderText("Database Operation Error"); - alert.setContentText("Edit failed \n" + - "the product-supplier link is already in the database"); - alert.showAndWait(); - numRows = -1; //Update numRow so alert only shows once - closeStage(mouseEvent); - } - catch(SQLException e){ - ActivityLogger.getInstance().logException( - "ProductSupplierDialogController.buttonSaveClicked", - e, - "Updating product-supplier - SupID: " + selectedSupId + ", ProdID: " + selectedProdId); - throw new RuntimeException(e); - } - } + if(errorMsg.isEmpty()){ + ProductSupplierRequest request = collectProductSupplierRequest(); - //if no rows were affected then there was an error (prompt user of error) - if (numRows == 0){ - Alert alert = new Alert(Alert.AlertType.ERROR); - alert.setHeaderText("Database Operation Error"); - alert.setContentText(mode + " failed"); - alert.showAndWait(); - } - else if (numRows > 0){ - //tell the user operation was successful - Alert alert = new Alert(Alert.AlertType.INFORMATION); - alert.setHeaderText("Saved"); - alert.setContentText(mode + " succeeded"); - alert.showAndWait(); - closeStage(mouseEvent); - } - } - else { //Display validation errors + new Thread(() -> { + try { + if (mode.equals("Add")) { + ProductSupplierApi.getInstance().createProductSupplier(request); + } else { + ProductSupplierApi.getInstance().updateProductSupplier(selectedId, request); + } + + Platform.runLater(() -> { + Alert alert = new Alert(Alert.AlertType.INFORMATION); + alert.setHeaderText("Saved"); + alert.setContentText(mode + " succeeded"); + alert.showAndWait(); + closeStage(mouseEvent); + }); + } catch (Exception e) { + Platform.runLater(() -> { + ActivityLogger.getInstance().logException( + "ProductSupplierDialogController.buttonSaveClicked", + e, + mode + " product-supplier"); + Alert alert = new Alert(Alert.AlertType.ERROR); + alert.setHeaderText("Database Operation Error"); + alert.setContentText(mode + " failed: " + e.getMessage()); + alert.showAndWait(); + }); + } + }).start(); + } else { Alert alert = new Alert(Alert.AlertType.ERROR); alert.setHeaderText("Input Error"); alert.setContentText(errorMsg); @@ -193,18 +198,14 @@ public class ProductSupplierDialogController { /** * collect the data for new/updated productSupplier - * @return productSupplier entity with data + * @return productSupplier request with data */ - private ProductSupplier collectProductSupplier() { - ProductSupplier productSupplier = null; - - productSupplier = new ProductSupplier( - cbSupplier.getSelectionModel().getSelectedItem().getSupId(), - cbProduct.getSelectionModel().getSelectedItem().getProdId(), - Double.parseDouble(txtCost.getText()) - ); - - return productSupplier; + private ProductSupplierRequest collectProductSupplierRequest() { + ProductSupplierRequest request = new ProductSupplierRequest(); + request.setSupplierId(cbSupplier.getSelectionModel().getSelectedItem().getId()); + request.setProductId(cbProduct.getSelectionModel().getSelectedItem().getId()); + request.setSupplierPrice(new BigDecimal(txtCost.getText())); + return request; } /** @@ -216,20 +217,17 @@ public class ProductSupplierDialogController { txtCost.setText(productSupplier.getCost() + ""); } - //Get the right combobox selection (product) - for (Product product : cbProduct.getItems()) { - if(product.getProdId() == productSupplier.getProdId()){ + for (DropdownOption product : cbProduct.getItems()) { + if(product.getId() == productSupplier.getProdId()){ cbProduct.getSelectionModel().select(product); } } - //Get the right combobox selection (supplier) - for (Supplier supplier : cbSupplier.getItems()) { - if (supplier.getSupId() == productSupplier.getSupId()) { + for (DropdownOption supplier : cbSupplier.getItems()) { + if (supplier.getId() == productSupplier.getSupId()) { cbSupplier.getSelectionModel().select(supplier); } } - } /** @@ -260,6 +258,7 @@ public class ProductSupplierDialogController { public void setSelectedIds(int supId, int prodId){ this.selectedSupId = supId; this.selectedProdId = prodId; + this.selectedId = (long) supId; } } diff --git a/src/main/java/org/example/petshopdesktop/controllers/dialogcontrollers/RefundDialogController.java b/src/main/java/org/example/petshopdesktop/controllers/dialogcontrollers/RefundDialogController.java index 85ebfc6d..2ec52b78 100644 --- a/src/main/java/org/example/petshopdesktop/controllers/dialogcontrollers/RefundDialogController.java +++ b/src/main/java/org/example/petshopdesktop/controllers/dialogcontrollers/RefundDialogController.java @@ -7,15 +7,19 @@ import javafx.fxml.FXML; import javafx.scene.control.*; import javafx.scene.control.cell.PropertyValueFactory; import javafx.stage.Stage; +import org.example.petshopdesktop.api.dto.sale.SaleItemRequest; +import org.example.petshopdesktop.api.dto.sale.SaleItemResponse; +import org.example.petshopdesktop.api.dto.sale.SaleRequest; +import org.example.petshopdesktop.api.dto.sale.SaleResponse; +import org.example.petshopdesktop.api.endpoints.SaleApi; import org.example.petshopdesktop.auth.UserSession; -import org.example.petshopdesktop.database.SaleDB; -import org.example.petshopdesktop.models.SaleCartItem; -import org.example.petshopdesktop.models.SaleDetail; import org.example.petshopdesktop.util.ActivityLogger; -import java.sql.SQLException; +import java.math.BigDecimal; import java.text.NumberFormat; import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; import java.util.Locale; import java.util.Optional; @@ -31,19 +35,19 @@ public class RefundDialogController { private Label lblSaleInfo; @FXML - private TableView tvOriginalItems; + private TableView tvOriginalItems; @FXML - private TableColumn colOriginalProduct; + private TableColumn colOriginalProduct; @FXML - private TableColumn colOriginalQuantity; + private TableColumn colOriginalQuantity; @FXML - private TableColumn colOriginalUnitPrice; + private TableColumn colOriginalUnitPrice; @FXML - private TableColumn colOriginalTotal; + private TableColumn colOriginalTotal; @FXML private Button btnAddToRefund; @@ -78,7 +82,7 @@ public class RefundDialogController { @FXML private Button btnCancel; - private SaleDetail currentSale; + private SaleResponse currentSale; private final ObservableList refundItems = FXCollections.observableArrayList(); private final NumberFormat currency = NumberFormat.getCurrencyInstance(Locale.CANADA); @@ -94,7 +98,7 @@ public class RefundDialogController { colOriginalProduct.setCellValueFactory(new PropertyValueFactory<>("productName")); colOriginalQuantity.setCellValueFactory(new PropertyValueFactory<>("quantity")); colOriginalUnitPrice.setCellValueFactory(new PropertyValueFactory<>("unitPrice")); - colOriginalTotal.setCellValueFactory(new PropertyValueFactory<>("total")); + colOriginalTotal.setCellValueFactory(new PropertyValueFactory<>("lineTotal")); tvOriginalItems.getSelectionModel().setSelectionMode(SelectionMode.SINGLE); colRefundProduct.setCellValueFactory(new PropertyValueFactory<>("productName")); @@ -113,21 +117,25 @@ public class RefundDialogController { return; } - int saleId; + Long saleId; try { - saleId = Integer.parseInt(saleIdText); + saleId = Long.parseLong(saleIdText); } catch (NumberFormatException e) { showError("Load Sale", "Invalid transaction ID."); return; } try { - if (SaleDB.isRefunded(saleId)) { + List allSales = SaleApi.getInstance().listSales(0, 1000, null); + boolean alreadyRefunded = allSales.stream() + .anyMatch(s -> Boolean.TRUE.equals(s.getIsRefund()) && saleId.equals(s.getOriginalSaleId())); + + if (alreadyRefunded) { showError("Load Sale", "This sale has already been refunded."); return; } - currentSale = SaleDB.getSaleById(saleId); + currentSale = SaleApi.getInstance().getSale(saleId); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"); String saleInfo = String.format("Sale Date: %s | Employee: %s | Original Total: %s | Payment: %s", @@ -137,13 +145,13 @@ public class RefundDialogController { currentSale.getPaymentMethod()); lblSaleInfo.setText(saleInfo); - tvOriginalItems.setItems(currentSale.getItems()); + tvOriginalItems.setItems(FXCollections.observableArrayList(currentSale.getItems())); cbPaymentMethod.getSelectionModel().select(currentSale.getPaymentMethod()); refundItems.clear(); updateRefundTotal(); - } catch (SQLException e) { + } catch (Exception e) { ActivityLogger.getInstance().logException("RefundDialogController.btnLoadSaleClicked", e, "Loading sale"); showError("Load Sale", e.getMessage() != null ? e.getMessage() : "Could not load sale."); } @@ -156,14 +164,14 @@ public class RefundDialogController { return; } - SaleDetail.SaleDetailItem selected = tvOriginalItems.getSelectionModel().getSelectedItem(); + SaleItemResponse selected = tvOriginalItems.getSelectionModel().getSelectedItem(); if (selected == null) { showError("Add to Refund", "Select an item from the original sale."); return; } int alreadyRefunded = refundItems.stream() - .filter(r -> r.getProdId() == selected.getProdId()) + .filter(r -> r.getProductId().equals(selected.getId())) .mapToInt(RefundItem::getQuantity) .sum(); @@ -192,7 +200,7 @@ public class RefundDialogController { } refundItems.add(new RefundItem( - selected.getProdId(), + selected.getId(), selected.getProductName(), quantity, selected.getUnitPrice() @@ -226,9 +234,9 @@ public class RefundDialogController { return; } - Integer employeeId = UserSession.getInstance().getEmployeeId(); - if (employeeId == null || employeeId <= 0) { - showError("Process Refund", "Employee is not set for this account."); + Long storeId = UserSession.getInstance().getStoreId(); + if (storeId == null || storeId <= 0) { + showError("Process Refund", "Store is not set for this account."); return; } @@ -240,7 +248,7 @@ public class RefundDialogController { Alert confirm = new Alert(Alert.AlertType.CONFIRMATION); confirm.setTitle("Confirm Refund"); - confirm.setHeaderText("Process refund for sale ID " + currentSale.getSaleId() + "?"); + confirm.setHeaderText("Process refund for sale ID " + currentSale.getId() + "?"); confirm.setContentText("Refund amount: " + lblRefundTotal.getText()); Optional confirmResult = confirm.showAndWait(); @@ -249,22 +257,33 @@ public class RefundDialogController { } try { - ObservableList cartItems = FXCollections.observableArrayList(); - for (RefundItem item : refundItems) { - cartItems.add(new SaleCartItem(item.getProdId(), item.getProductName(), item.getQuantity(), item.getUnitPrice())); - } + SaleRequest request = new SaleRequest(); + request.setStoreId(storeId); + request.setPaymentMethod(payment); + request.setIsRefund(true); + request.setOriginalSaleId(currentSale.getId()); - int refundId = SaleDB.createRefund(currentSale.getSaleId(), employeeId, payment, cartItems); + List items = new ArrayList<>(); + for (RefundItem item : refundItems) { + SaleItemRequest saleItem = new SaleItemRequest(); + saleItem.setProductId(item.getProductId()); + saleItem.setQuantity(-item.getQuantity()); + saleItem.setUnitPrice(item.getUnitPrice()); + items.add(saleItem); + } + request.setItems(items); + + SaleResponse refundResponse = SaleApi.getInstance().createSale(request); Alert success = new Alert(Alert.AlertType.INFORMATION); success.setTitle("Refund Processed"); success.setHeaderText(null); - success.setContentText("Refund ID " + refundId + " was created successfully."); + success.setContentText("Refund ID " + refundResponse.getId() + " was created successfully."); success.showAndWait(); closeDialog(); - } catch (SQLException e) { + } catch (Exception e) { ActivityLogger.getInstance().logException("RefundDialogController.btnProcessRefundClicked", e, "Processing refund"); showError("Process Refund", e.getMessage() != null ? e.getMessage() : "Could not process refund."); } diff --git a/src/main/java/org/example/petshopdesktop/controllers/dialogcontrollers/ServiceDialogController.java b/src/main/java/org/example/petshopdesktop/controllers/dialogcontrollers/ServiceDialogController.java index 8bc80252..5b067c16 100644 --- a/src/main/java/org/example/petshopdesktop/controllers/dialogcontrollers/ServiceDialogController.java +++ b/src/main/java/org/example/petshopdesktop/controllers/dialogcontrollers/ServiceDialogController.java @@ -1,18 +1,19 @@ package org.example.petshopdesktop.controllers.dialogcontrollers; - +import javafx.application.Platform; import javafx.fxml.FXML; -import javafx.scene.Node; +import javafx.scene.control.Alert; import javafx.scene.control.Button; +import javafx.scene.control.ComboBox; import javafx.scene.control.Label; import javafx.scene.control.TextField; -import javafx.scene.input.MouseEvent; import javafx.stage.Stage; -import org.example.petshopdesktop.database.ServiceDB; -import org.example.petshopdesktop.models.Service; +import org.example.petshopdesktop.DTOs.ServiceDTO; +import org.example.petshopdesktop.api.dto.service.ServiceRequest; +import org.example.petshopdesktop.api.endpoints.ServiceApi; import org.example.petshopdesktop.util.ActivityLogger; -import javafx.scene.control.Alert; -import javafx.scene.control.ComboBox; + +import java.math.BigDecimal; public class ServiceDialogController { @@ -45,7 +46,7 @@ public class ServiceDialogController { private ComboBox cbMinutes; private String mode; - private Service selectedService; + private ServiceDTO selectedService; @@ -68,7 +69,7 @@ public class ServiceDialogController { } } - public void setService(Service service) { + public void setService(ServiceDTO service) { this.selectedService = service; lblServiceId.setText("ID: " + service.getServiceId()); diff --git a/src/main/java/org/example/petshopdesktop/controllers/dialogcontrollers/StaffRegisterDialogController.java b/src/main/java/org/example/petshopdesktop/controllers/dialogcontrollers/StaffRegisterDialogController.java index 2c3bd479..5f9a4a59 100644 --- a/src/main/java/org/example/petshopdesktop/controllers/dialogcontrollers/StaffRegisterDialogController.java +++ b/src/main/java/org/example/petshopdesktop/controllers/dialogcontrollers/StaffRegisterDialogController.java @@ -1,5 +1,6 @@ package org.example.petshopdesktop.controllers.dialogcontrollers; +import javafx.application.Platform; import javafx.event.ActionEvent; import javafx.fxml.FXML; import javafx.scene.control.Alert; @@ -8,11 +9,10 @@ import javafx.scene.control.Label; import javafx.scene.control.PasswordField; import javafx.scene.control.TextField; import javafx.stage.Stage; -import org.example.petshopdesktop.database.UserDB; +import org.example.petshopdesktop.api.dto.user.UserRequest; +import org.example.petshopdesktop.api.endpoints.UserApi; import org.example.petshopdesktop.util.ActivityLogger; -import java.sql.SQLException; - public class StaffRegisterDialogController { @FXML @@ -48,8 +48,6 @@ public class StaffRegisterDialogController { String firstName = value(txtFirstName); String lastName = value(txtLastName); - String email = value(txtEmail); - String phone = value(txtPhone); String username = value(txtUsername); String password = txtPassword.getText() == null ? "" : txtPassword.getText(); String confirm = txtPasswordConfirm.getText() == null ? "" : txtPasswordConfirm.getText(); @@ -58,14 +56,6 @@ public class StaffRegisterDialogController { lblError.setText("First name and last name are required."); return; } - if (email.isBlank()) { - lblError.setText("Email is required."); - return; - } - if (phone.isBlank()) { - lblError.setText("Phone is required."); - return; - } if (username.isBlank()) { lblError.setText("Username is required."); return; @@ -79,26 +69,41 @@ public class StaffRegisterDialogController { return; } - try { - UserDB.createStaffAccount(firstName, lastName, email, phone, username, password); - Alert alert = new Alert(Alert.AlertType.INFORMATION); - alert.setTitle("Staff Account"); - alert.setHeaderText(null); - alert.setContentText("Staff account created. You can log in now."); - alert.showAndWait(); - close(); - } catch (SQLException e) { - ActivityLogger.getInstance().logException("StaffRegisterDialogController.btnCreateClicked", e, "Creating staff account"); - String msg = e.getMessage() == null ? "Could not create staff account." : e.getMessage(); - if (msg.toLowerCase().contains("duplicate") || msg.toLowerCase().contains("unique")) { - lblError.setText("Username already exists."); - } else { - lblError.setText(msg); + btnCreate.setDisable(true); + + new Thread(() -> { + try { + UserRequest request = new UserRequest(); + request.setUsername(username); + request.setPassword(password); + request.setFirstName(firstName); + request.setLastName(lastName); + request.setRole("STAFF"); + request.setActive(true); + + UserApi.getInstance().createUser(request); + + Platform.runLater(() -> { + Alert alert = new Alert(Alert.AlertType.INFORMATION); + alert.setTitle("Staff Account"); + alert.setHeaderText(null); + alert.setContentText("Staff account created. You can log in now."); + alert.showAndWait(); + close(); + }); + } catch (Exception e) { + ActivityLogger.getInstance().logException("StaffRegisterDialogController.btnCreateClicked", e, "Creating staff account"); + String msg = e.getMessage() == null ? "Could not create staff account." : e.getMessage(); + Platform.runLater(() -> { + if (msg.toLowerCase().contains("duplicate") || msg.toLowerCase().contains("unique")) { + lblError.setText("Username already exists."); + } else { + lblError.setText(msg); + } + btnCreate.setDisable(false); + }); } - } catch (RuntimeException e) { - ActivityLogger.getInstance().logException("StaffRegisterDialogController.btnCreateClicked", e, "Database connection"); - lblError.setText("Database is not connected."); - } + }).start(); } @FXML diff --git a/src/main/java/org/example/petshopdesktop/controllers/dialogcontrollers/SupplierDialogController.java b/src/main/java/org/example/petshopdesktop/controllers/dialogcontrollers/SupplierDialogController.java index 836b5e6c..18dab623 100644 --- a/src/main/java/org/example/petshopdesktop/controllers/dialogcontrollers/SupplierDialogController.java +++ b/src/main/java/org/example/petshopdesktop/controllers/dialogcontrollers/SupplierDialogController.java @@ -10,12 +10,12 @@ import javafx.scene.control.TextField; import javafx.scene.input.MouseEvent; import javafx.stage.Stage; import org.example.petshopdesktop.Validator; -import org.example.petshopdesktop.database.SupplierDB; +import org.example.petshopdesktop.api.dto.supplier.SupplierRequest; +import org.example.petshopdesktop.api.dto.supplier.SupplierResponse; +import org.example.petshopdesktop.api.endpoints.SupplierApi; import org.example.petshopdesktop.models.Supplier; import org.example.petshopdesktop.util.ActivityLogger; -import java.sql.SQLException; - public class SupplierDialogController { @FXML @@ -74,7 +74,6 @@ public class SupplierDialogController { * @param mouseEvent click event for save button */ private void buttonSaveClicked(MouseEvent mouseEvent) { - int numRow = 0; //how many rows affected String errorMsg = ""; //error message for validation //Check validation (input required) @@ -95,44 +94,29 @@ public class SupplierDialogController { errorMsg += Validator.isValidPhoneNumber(txtPhone.getText(), "Phone Number"); if(errorMsg.isEmpty()){ //no validation errors detected - Supplier supplier = collectSupplier(); //get supplier info - if (mode.equals("Add")) { //add mode - try{ - numRow = SupplierDB.insertSupplier(supplier); - } catch (SQLException e) { - ActivityLogger.getInstance().logException( - "SupplierDialogController.buttonSaveClicked", - e, - "Inserting new supplier record"); - throw new RuntimeException(e); + SupplierRequest request = createSupplierRequest(); + try { + if (mode.equals("Add")) { + SupplierApi.getInstance().createSupplier(request); + } else { + Long supplierId = Long.parseLong(lblSupId.getText().split(": ")[1]); + SupplierApi.getInstance().updateSupplier(supplierId, request); } - } - else{ //edit mode - try{ - numRow = SupplierDB.updateSupplier(supplier.getSupId(),supplier); - } catch (SQLException e) { - ActivityLogger.getInstance().logException( - "SupplierDialogController.buttonSaveClicked", - e, - "Updating supplier with ID: " + supplier.getSupId()); - throw new RuntimeException(e); - } - } - //if no rows were affected then there was an error (prompt user of error) - if (numRow == 0){ - Alert alert = new Alert(Alert.AlertType.ERROR); - alert.setHeaderText("Database Operation Error"); - alert.setContentText(mode + " failed"); - alert.showAndWait(); - } - else { - //tell the user operation was successful Alert alert = new Alert(Alert.AlertType.INFORMATION); alert.setHeaderText("Saved"); alert.setContentText(mode + " succeeded"); alert.showAndWait(); closeStage(mouseEvent); + } catch (Exception e) { + ActivityLogger.getInstance().logException( + "SupplierDialogController.buttonSaveClicked", + e, + mode.equals("Add") ? "Inserting new supplier record" : "Updating supplier record"); + Alert alert = new Alert(Alert.AlertType.ERROR); + alert.setHeaderText("Database Operation Error"); + alert.setContentText(mode + " failed: " + e.getMessage()); + alert.showAndWait(); } } else{ //Display validation errors @@ -154,26 +138,16 @@ public class SupplierDialogController { } /** - * Collect the supplier info - * @return supplier info with the id or the new supplier + * Create a supplier request from the form inputs + * @return supplier request for API call */ - private Supplier collectSupplier(){ - int supId = 0; - Supplier supplier = null; - - if(lblSupId.isVisible()){ //Edit mode - //get supplier id from lblId (split the string so we only get the int) - supId = Integer.parseInt(lblSupId.getText().split(": ")[1]); - } - supplier = new Supplier( - supId, - txtCompanyName.getText(), - txtContactFirstName.getText(), - txtContactLastName.getText(), - txtEmail.getText(), - txtPhone.getText() - ); - return supplier; + private SupplierRequest createSupplierRequest(){ + SupplierRequest request = new SupplierRequest(); + request.setSupplierName(txtCompanyName.getText()); + request.setContactPerson(txtContactFirstName.getText() + " " + txtContactLastName.getText()); + request.setEmail(txtEmail.getText()); + request.setPhone(txtPhone.getText()); + return request; } /** diff --git a/src/main/java/org/example/petshopdesktop/models/Adoption.java b/src/main/java/org/example/petshopdesktop/models/Adoption.java index d424ff72..c5c02f63 100644 --- a/src/main/java/org/example/petshopdesktop/models/Adoption.java +++ b/src/main/java/org/example/petshopdesktop/models/Adoption.java @@ -8,16 +8,17 @@ public class Adoption { private SimpleIntegerProperty adoptionId; private SimpleIntegerProperty petId; private SimpleIntegerProperty customerId; + private SimpleStringProperty petName; private SimpleStringProperty customerName; private SimpleStringProperty adoptionDate; private SimpleDoubleProperty adoptionFee; private SimpleStringProperty adoptionStatus; - //Constructor - public Adoption(int adoptionId, int petId, int customerId, String customerName, String adoptionDate, double adoptionFee, String adoptionStatus) { + public Adoption(int adoptionId, int petId, int customerId, String petName, String customerName, String adoptionDate, double adoptionFee, String adoptionStatus) { this.adoptionId = new SimpleIntegerProperty(adoptionId); this.petId = new SimpleIntegerProperty(petId); this.customerId = new SimpleIntegerProperty(customerId); + this.petName = new SimpleStringProperty(petName); this.customerName = new SimpleStringProperty(customerName); this.adoptionDate = new SimpleStringProperty(adoptionDate); this.adoptionFee = new SimpleDoubleProperty(adoptionFee); @@ -42,6 +43,12 @@ public class Adoption { public SimpleIntegerProperty customerIdProperty() { return customerId; } + public String getPetName() { return petName.get(); } + + public void setPetName(String petName) { this.petName.set(petName); } + + public SimpleStringProperty petNameProperty() { return petName; } + public String getCustomerName() { return customerName.get(); } public void setCustomerName(String customerName) { this.customerName.set(customerName); } diff --git a/src/main/java/org/example/petshopdesktop/models/Inventory.java b/src/main/java/org/example/petshopdesktop/models/Inventory.java index ce6ec5e2..53f77543 100644 --- a/src/main/java/org/example/petshopdesktop/models/Inventory.java +++ b/src/main/java/org/example/petshopdesktop/models/Inventory.java @@ -7,14 +7,21 @@ public class Inventory { private SimpleIntegerProperty inventoryId; private SimpleIntegerProperty prodId; private SimpleStringProperty prodName; + private SimpleStringProperty categoryName; + private SimpleIntegerProperty storeId; + private SimpleStringProperty storeName; private SimpleIntegerProperty quantity; + private SimpleIntegerProperty reorderLevel; - //Constructor - public Inventory(int inventoryId, int prodId, String prodName, int quantity) { + public Inventory(int inventoryId, int prodId, String prodName, String categoryName, int storeId, String storeName, int quantity, int reorderLevel) { this.inventoryId = new SimpleIntegerProperty(inventoryId); this.prodId = new SimpleIntegerProperty(prodId); this.prodName = new SimpleStringProperty(prodName); + this.categoryName = new SimpleStringProperty(categoryName); + this.storeId = new SimpleIntegerProperty(storeId); + this.storeName = new SimpleStringProperty(storeName); this.quantity = new SimpleIntegerProperty(quantity); + this.reorderLevel = new SimpleIntegerProperty(reorderLevel); } public int getInventoryId() { return inventoryId.get(); } @@ -35,9 +42,33 @@ public class Inventory { public SimpleStringProperty prodNameProperty() { return prodName; } + public String getCategoryName() { return categoryName.get(); } + + public void setCategoryName(String categoryName) { this.categoryName.set(categoryName); } + + public SimpleStringProperty categoryNameProperty() { return categoryName; } + + public int getStoreId() { return storeId.get(); } + + public void setStoreId(int storeId) { this.storeId.set(storeId); } + + public SimpleIntegerProperty storeIdProperty() { return storeId; } + + public String getStoreName() { return storeName.get(); } + + public void setStoreName(String storeName) { this.storeName.set(storeName); } + + public SimpleStringProperty storeNameProperty() { return storeName; } + public int getQuantity() { return quantity.get(); } public void setQuantity(int quantity) { this.quantity.set(quantity); } public SimpleIntegerProperty quantityProperty() { return quantity; } + + public int getReorderLevel() { return reorderLevel.get(); } + + public void setReorderLevel(int reorderLevel) { this.reorderLevel.set(reorderLevel); } + + public SimpleIntegerProperty reorderLevelProperty() { return reorderLevel; } } diff --git a/src/main/java/org/example/petshopdesktop/models/PurchaseOrder.java b/src/main/java/org/example/petshopdesktop/models/PurchaseOrder.java index 3b1cf838..c13afe50 100644 --- a/src/main/java/org/example/petshopdesktop/models/PurchaseOrder.java +++ b/src/main/java/org/example/petshopdesktop/models/PurchaseOrder.java @@ -1,35 +1,52 @@ package org.example.petshopdesktop.models; +import java.math.BigDecimal; +import java.time.LocalDate; + public class PurchaseOrder { - private int purchaseOrderId; - private int supId; - private String orderDate; + private long purchaseOrderId; + private String supplierName; + private LocalDate orderDate; + private LocalDate expectedDeliveryDate; private String status; + private BigDecimal totalAmount; - public PurchaseOrder(int purchaseOrderId, - int supId, - String orderDate, - String status) { + public PurchaseOrder(long purchaseOrderId, + String supplierName, + LocalDate orderDate, + LocalDate expectedDeliveryDate, + String status, + BigDecimal totalAmount) { this.purchaseOrderId = purchaseOrderId; - this.supId = supId; + this.supplierName = supplierName; this.orderDate = orderDate; + this.expectedDeliveryDate = expectedDeliveryDate; this.status = status; + this.totalAmount = totalAmount; } - public int getPurchaseOrderId() { + public long getPurchaseOrderId() { return purchaseOrderId; } - public int getSupId() { - return supId; + public String getSupplierName() { + return supplierName; } - public String getOrderDate() { + public LocalDate getOrderDate() { return orderDate; } + public LocalDate getExpectedDeliveryDate() { + return expectedDeliveryDate; + } + public String getStatus() { return status; } + + public BigDecimal getTotalAmount() { + return totalAmount; + } } \ No newline at end of file diff --git a/src/main/java/org/example/petshopdesktop/models/StaffAccount.java b/src/main/java/org/example/petshopdesktop/models/StaffAccount.java index c17d0472..e1b0ab62 100644 --- a/src/main/java/org/example/petshopdesktop/models/StaffAccount.java +++ b/src/main/java/org/example/petshopdesktop/models/StaffAccount.java @@ -3,8 +3,8 @@ package org.example.petshopdesktop.models; import java.sql.Timestamp; public class StaffAccount { - private final int userId; - private final int employeeId; + private final long userId; + private final long employeeId; private final String username; private final String firstName; private final String lastName; @@ -13,7 +13,7 @@ public class StaffAccount { private final boolean active; private final Timestamp createdAt; - public StaffAccount(int userId, int employeeId, String username, String firstName, String lastName, String email, String phone, boolean active, Timestamp createdAt) { + public StaffAccount(long userId, long employeeId, String username, String firstName, String lastName, String email, String phone, boolean active, Timestamp createdAt) { this.userId = userId; this.employeeId = employeeId; this.username = username; @@ -25,11 +25,11 @@ public class StaffAccount { this.createdAt = createdAt; } - public int getUserId() { + public long getUserId() { return userId; } - public int getEmployeeId() { + public long getEmployeeId() { return employeeId; }