From cbed5e4e0cf2a54c067ce7919bdc4d4cac943a09 Mon Sep 17 00:00:00 2001 From: Harkamal Randhawa Date: Sat, 28 Feb 2026 19:28:25 -0700 Subject: [PATCH] Implement refund system for sales --- Petstoredata.sql | 5 +- refund_migration.sql | 14 + .../controllers/SaleController.java | 31 ++ .../RefundDialogController.java | 329 ++++++++++++++++++ .../petshopdesktop/database/SaleDB.java | 176 +++++++++- .../petshopdesktop/models/SaleDetail.java | 82 +++++ .../petshopdesktop/models/SaleLineItem.java | 8 +- .../dialogviews/refund-dialog-view.fxml | 192 ++++++++++ .../petshopdesktop/modelviews/sale-view.fxml | 8 + 9 files changed, 841 insertions(+), 4 deletions(-) create mode 100644 refund_migration.sql create mode 100644 src/main/java/org/example/petshopdesktop/controllers/dialogcontrollers/RefundDialogController.java create mode 100644 src/main/java/org/example/petshopdesktop/models/SaleDetail.java create mode 100644 src/main/resources/org/example/petshopdesktop/dialogviews/refund-dialog-view.fxml diff --git a/Petstoredata.sql b/Petstoredata.sql index 4d50c46a..8c7c1576 100644 --- a/Petstoredata.sql +++ b/Petstoredata.sql @@ -132,8 +132,11 @@ CREATE TABLE sale ( paymentMethod VARCHAR(50) NOT NULL, employeeId INT NOT NULL, storeId INT NOT NULL, + isRefund BOOLEAN DEFAULT FALSE NOT NULL, + originalSaleId INT NULL, FOREIGN KEY (employeeId) REFERENCES employee(employeeId), - FOREIGN KEY (storeId) REFERENCES storeLocation(storeId) + FOREIGN KEY (storeId) REFERENCES storeLocation(storeId), + FOREIGN KEY (originalSaleId) REFERENCES sale(saleId) ); CREATE TABLE saleItem ( diff --git a/refund_migration.sql b/refund_migration.sql new file mode 100644 index 00000000..70212c81 --- /dev/null +++ b/refund_migration.sql @@ -0,0 +1,14 @@ +-- Database Migration Script for Refund System +-- Run this on existing Petstoredb to add refund functionality + +USE Petstoredb; + +-- Add refund columns to sale table +ALTER TABLE sale + ADD COLUMN isRefund BOOLEAN DEFAULT FALSE NOT NULL, + ADD COLUMN originalSaleId INT NULL, + ADD CONSTRAINT fk_original_sale + FOREIGN KEY (originalSaleId) REFERENCES sale(saleId); + +-- Verify the changes +DESCRIBE sale; diff --git a/src/main/java/org/example/petshopdesktop/controllers/SaleController.java b/src/main/java/org/example/petshopdesktop/controllers/SaleController.java index 753dbd81..4d17a0b2 100644 --- a/src/main/java/org/example/petshopdesktop/controllers/SaleController.java +++ b/src/main/java/org/example/petshopdesktop/controllers/SaleController.java @@ -5,6 +5,8 @@ import javafx.collections.ObservableList; import javafx.collections.transformation.FilteredList; import javafx.event.ActionEvent; import javafx.fxml.FXML; +import javafx.fxml.FXMLLoader; +import javafx.scene.Scene; import javafx.scene.control.Alert; import javafx.scene.control.Button; import javafx.scene.control.ComboBox; @@ -17,6 +19,8 @@ import javafx.scene.control.TableView; import javafx.scene.control.TextField; import javafx.scene.control.cell.PropertyValueFactory; 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; @@ -38,6 +42,9 @@ public class SaleController { @FXML private Button btnRefresh; + @FXML + private Button btnRefund; + @FXML private Label lblModeNote; @@ -319,6 +326,30 @@ public class SaleController { } } + @FXML + void btnRefund(ActionEvent event) { + openRefundDialog(); + } + + private void openRefundDialog() { + try { + FXMLLoader loader = new FXMLLoader(getClass().getResource( + "/org/example/petshopdesktop/dialogviews/refund-dialog-view.fxml")); + Stage dialog = new Stage(); + dialog.initOwner(btnRefund.getScene().getWindow()); + dialog.initModality(Modality.APPLICATION_MODAL); + dialog.setTitle("Process Refund"); + dialog.setScene(new Scene(loader.load())); + dialog.setResizable(false); + dialog.showAndWait(); + + refreshInventory(); + refreshSales(true); + } catch (Exception e) { + ActivityLogger.getInstance().logException("SaleController.openRefundDialog", e, "Opening refund dialog"); + } + } + private void updateCartTotal() { double total = cartItems.stream().mapToDouble(SaleCartItem::getTotal).sum(); lblCartTotal.setText(currency.format(total)); diff --git a/src/main/java/org/example/petshopdesktop/controllers/dialogcontrollers/RefundDialogController.java b/src/main/java/org/example/petshopdesktop/controllers/dialogcontrollers/RefundDialogController.java new file mode 100644 index 00000000..85ebfc6d --- /dev/null +++ b/src/main/java/org/example/petshopdesktop/controllers/dialogcontrollers/RefundDialogController.java @@ -0,0 +1,329 @@ +package org.example.petshopdesktop.controllers.dialogcontrollers; + +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; +import javafx.event.ActionEvent; +import javafx.fxml.FXML; +import javafx.scene.control.*; +import javafx.scene.control.cell.PropertyValueFactory; +import javafx.stage.Stage; +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.text.NumberFormat; +import java.time.format.DateTimeFormatter; +import java.util.Locale; +import java.util.Optional; + +public class RefundDialogController { + + @FXML + private TextField txtSaleId; + + @FXML + private Button btnLoadSale; + + @FXML + private Label lblSaleInfo; + + @FXML + private TableView tvOriginalItems; + + @FXML + private TableColumn colOriginalProduct; + + @FXML + private TableColumn colOriginalQuantity; + + @FXML + private TableColumn colOriginalUnitPrice; + + @FXML + private TableColumn colOriginalTotal; + + @FXML + private Button btnAddToRefund; + + @FXML + private TableView tvRefundItems; + + @FXML + private TableColumn colRefundProduct; + + @FXML + private TableColumn colRefundQuantity; + + @FXML + private TableColumn colRefundUnitPrice; + + @FXML + private TableColumn colRefundTotal; + + @FXML + private Button btnRemoveFromRefund; + + @FXML + private ComboBox cbPaymentMethod; + + @FXML + private Label lblRefundTotal; + + @FXML + private Button btnProcessRefund; + + @FXML + private Button btnCancel; + + private SaleDetail currentSale; + private final ObservableList refundItems = FXCollections.observableArrayList(); + private final NumberFormat currency = NumberFormat.getCurrencyInstance(Locale.CANADA); + + @FXML + public void initialize() { + setupTables(); + cbPaymentMethod.setItems(FXCollections.observableArrayList("Cash", "Card", "Debit")); + cbPaymentMethod.getSelectionModel().selectFirst(); + updateRefundTotal(); + } + + private void setupTables() { + colOriginalProduct.setCellValueFactory(new PropertyValueFactory<>("productName")); + colOriginalQuantity.setCellValueFactory(new PropertyValueFactory<>("quantity")); + colOriginalUnitPrice.setCellValueFactory(new PropertyValueFactory<>("unitPrice")); + colOriginalTotal.setCellValueFactory(new PropertyValueFactory<>("total")); + tvOriginalItems.getSelectionModel().setSelectionMode(SelectionMode.SINGLE); + + colRefundProduct.setCellValueFactory(new PropertyValueFactory<>("productName")); + colRefundQuantity.setCellValueFactory(new PropertyValueFactory<>("quantity")); + colRefundUnitPrice.setCellValueFactory(new PropertyValueFactory<>("unitPrice")); + colRefundTotal.setCellValueFactory(new PropertyValueFactory<>("total")); + tvRefundItems.setItems(refundItems); + tvRefundItems.getSelectionModel().setSelectionMode(SelectionMode.SINGLE); + } + + @FXML + void btnLoadSaleClicked(ActionEvent event) { + String saleIdText = txtSaleId.getText().trim(); + if (saleIdText.isEmpty()) { + showError("Load Sale", "Enter a transaction ID."); + return; + } + + int saleId; + try { + saleId = Integer.parseInt(saleIdText); + } catch (NumberFormatException e) { + showError("Load Sale", "Invalid transaction ID."); + return; + } + + try { + if (SaleDB.isRefunded(saleId)) { + showError("Load Sale", "This sale has already been refunded."); + return; + } + + currentSale = SaleDB.getSaleById(saleId); + + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"); + String saleInfo = String.format("Sale Date: %s | Employee: %s | Original Total: %s | Payment: %s", + currentSale.getSaleDate().format(formatter), + currentSale.getEmployeeName(), + currency.format(currentSale.getTotalAmount()), + currentSale.getPaymentMethod()); + lblSaleInfo.setText(saleInfo); + + tvOriginalItems.setItems(currentSale.getItems()); + cbPaymentMethod.getSelectionModel().select(currentSale.getPaymentMethod()); + + refundItems.clear(); + updateRefundTotal(); + + } catch (SQLException e) { + ActivityLogger.getInstance().logException("RefundDialogController.btnLoadSaleClicked", e, "Loading sale"); + showError("Load Sale", e.getMessage() != null ? e.getMessage() : "Could not load sale."); + } + } + + @FXML + void btnAddToRefundClicked(ActionEvent event) { + if (currentSale == null) { + showError("Add to Refund", "Load a sale first."); + return; + } + + SaleDetail.SaleDetailItem 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()) + .mapToInt(RefundItem::getQuantity) + .sum(); + + int available = selected.getQuantity() - alreadyRefunded; + if (available <= 0) { + showError("Add to Refund", "All items of this product are already in the refund list."); + return; + } + + TextInputDialog dialog = new TextInputDialog(String.valueOf(available)); + dialog.setTitle("Refund Quantity"); + dialog.setHeaderText("Product: " + selected.getProductName()); + dialog.setContentText("Enter quantity to refund (max " + available + "):"); + + Optional result = dialog.showAndWait(); + if (result.isPresent()) { + try { + int quantity = Integer.parseInt(result.get().trim()); + if (quantity <= 0) { + showError("Add to Refund", "Quantity must be at least 1."); + return; + } + if (quantity > available) { + showError("Add to Refund", "Cannot refund more than " + available + " items."); + return; + } + + refundItems.add(new RefundItem( + selected.getProdId(), + selected.getProductName(), + quantity, + selected.getUnitPrice() + )); + updateRefundTotal(); + + } catch (NumberFormatException e) { + showError("Add to Refund", "Invalid quantity."); + } + } + } + + @FXML + void btnRemoveFromRefundClicked(ActionEvent event) { + RefundItem selected = tvRefundItems.getSelectionModel().getSelectedItem(); + if (selected != null) { + refundItems.remove(selected); + updateRefundTotal(); + } + } + + @FXML + void btnProcessRefundClicked(ActionEvent event) { + if (currentSale == null) { + showError("Process Refund", "Load a sale first."); + return; + } + + if (refundItems.isEmpty()) { + showError("Process Refund", "Add at least one item to refund."); + return; + } + + Integer employeeId = UserSession.getInstance().getEmployeeId(); + if (employeeId == null || employeeId <= 0) { + showError("Process Refund", "Employee is not set for this account."); + return; + } + + String payment = cbPaymentMethod.getSelectionModel().getSelectedItem(); + if (payment == null || payment.isBlank()) { + showError("Process Refund", "Select a payment method."); + return; + } + + Alert confirm = new Alert(Alert.AlertType.CONFIRMATION); + confirm.setTitle("Confirm Refund"); + confirm.setHeaderText("Process refund for sale ID " + currentSale.getSaleId() + "?"); + confirm.setContentText("Refund amount: " + lblRefundTotal.getText()); + + Optional confirmResult = confirm.showAndWait(); + if (confirmResult.isEmpty() || confirmResult.get() != ButtonType.OK) { + return; + } + + try { + ObservableList cartItems = FXCollections.observableArrayList(); + for (RefundItem item : refundItems) { + cartItems.add(new SaleCartItem(item.getProdId(), item.getProductName(), item.getQuantity(), item.getUnitPrice())); + } + + int refundId = SaleDB.createRefund(currentSale.getSaleId(), employeeId, payment, cartItems); + + Alert success = new Alert(Alert.AlertType.INFORMATION); + success.setTitle("Refund Processed"); + success.setHeaderText(null); + success.setContentText("Refund ID " + refundId + " was created successfully."); + success.showAndWait(); + + closeDialog(); + + } catch (SQLException e) { + ActivityLogger.getInstance().logException("RefundDialogController.btnProcessRefundClicked", e, "Processing refund"); + showError("Process Refund", e.getMessage() != null ? e.getMessage() : "Could not process refund."); + } + } + + @FXML + void btnCancelClicked(ActionEvent event) { + closeDialog(); + } + + private void updateRefundTotal() { + double total = refundItems.stream().mapToDouble(RefundItem::getTotal).sum(); + lblRefundTotal.setText(currency.format(total)); + } + + private void closeDialog() { + Stage stage = (Stage) btnCancel.getScene().getWindow(); + stage.close(); + } + + private void showError(String title, String message) { + Alert alert = new Alert(Alert.AlertType.ERROR); + alert.setTitle(title); + alert.setHeaderText(null); + alert.setContentText(message); + alert.showAndWait(); + } + + public static class RefundItem { + private final int prodId; + private final String productName; + private final int quantity; + private final double unitPrice; + + public RefundItem(int prodId, String productName, int quantity, double unitPrice) { + this.prodId = prodId; + this.productName = productName; + this.quantity = quantity; + this.unitPrice = unitPrice; + } + + public int getProdId() { + return prodId; + } + + public String getProductName() { + return productName; + } + + public int getQuantity() { + return quantity; + } + + public double getUnitPrice() { + return unitPrice; + } + + public double getTotal() { + return quantity * unitPrice; + } + } +} diff --git a/src/main/java/org/example/petshopdesktop/database/SaleDB.java b/src/main/java/org/example/petshopdesktop/database/SaleDB.java index bedd6566..0fe0f30f 100644 --- a/src/main/java/org/example/petshopdesktop/database/SaleDB.java +++ b/src/main/java/org/example/petshopdesktop/database/SaleDB.java @@ -4,6 +4,7 @@ import javafx.collections.FXCollections; import javafx.collections.ObservableList; import org.example.petshopdesktop.DTOs.SaleDTO; import org.example.petshopdesktop.models.SaleCartItem; +import org.example.petshopdesktop.models.SaleDetail; import org.example.petshopdesktop.models.SaleLineItem; import org.example.petshopdesktop.models.analytics.*; import org.example.petshopdesktop.util.ActivityLogger; @@ -129,7 +130,8 @@ public class SaleDB { si.quantity, si.unitPrice, (si.quantity * si.unitPrice) as total, - s.paymentMethod + s.paymentMethod, + s.isRefund FROM sale s JOIN saleItem si ON s.saleId = si.saleId JOIN product p ON si.prodId = p.prodId @@ -149,7 +151,8 @@ public class SaleDB { rs.getInt("quantity"), rs.getDouble("unitPrice"), rs.getDouble("total"), - rs.getString("paymentMethod") + rs.getString("paymentMethod"), + rs.getBoolean("isRefund") )); } @@ -397,4 +400,173 @@ public class SaleDB { conn.close(); return summary; } + + public static SaleDetail getSaleById(int saleId) throws SQLException { + Connection conn = ConnectionDB.getConnection(); + + String saleSql = """ + SELECT s.saleId, s.saleDate, s.totalAmount, s.paymentMethod, + CONCAT(e.firstName, ' ', e.lastName) as employeeName, + s.isRefund + FROM sale s + JOIN employee e ON s.employeeId = e.employeeId + WHERE s.saleId = ? + """; + + PreparedStatement saleStmt = conn.prepareStatement(saleSql); + saleStmt.setInt(1, saleId); + ResultSet saleRs = saleStmt.executeQuery(); + + if (!saleRs.next()) { + conn.close(); + throw new SQLException("Sale not found with ID: " + saleId); + } + + boolean isRefund = saleRs.getBoolean("isRefund"); + if (isRefund) { + conn.close(); + throw new SQLException("Cannot refund a refund transaction"); + } + + SaleDetail detail = new SaleDetail( + saleRs.getInt("saleId"), + saleRs.getTimestamp("saleDate").toLocalDateTime(), + saleRs.getDouble("totalAmount"), + saleRs.getString("paymentMethod"), + saleRs.getString("employeeName"), + FXCollections.observableArrayList() + ); + + String itemsSql = """ + SELECT si.prodId, p.prodName, si.quantity, si.unitPrice, + (si.quantity * si.unitPrice) as total + FROM saleItem si + JOIN product p ON si.prodId = p.prodId + WHERE si.saleId = ? + """; + + PreparedStatement itemsStmt = conn.prepareStatement(itemsSql); + itemsStmt.setInt(1, saleId); + ResultSet itemsRs = itemsStmt.executeQuery(); + + while (itemsRs.next()) { + detail.getItems().add(new SaleDetail.SaleDetailItem( + itemsRs.getInt("prodId"), + itemsRs.getString("prodName"), + itemsRs.getInt("quantity"), + itemsRs.getDouble("unitPrice"), + itemsRs.getDouble("total") + )); + } + + conn.close(); + return detail; + } + + public static boolean isRefunded(int saleId) throws SQLException { + Connection conn = ConnectionDB.getConnection(); + + String sql = """ + SELECT COUNT(*) as refundCount + FROM sale + WHERE originalSaleId = ? AND isRefund = TRUE + """; + + PreparedStatement pstmt = conn.prepareStatement(sql); + pstmt.setInt(1, saleId); + ResultSet rs = pstmt.executeQuery(); + + boolean refunded = false; + if (rs.next()) { + refunded = rs.getInt("refundCount") > 0; + } + + conn.close(); + return refunded; + } + + public static int createRefund(int originalSaleId, int employeeId, String paymentMethod, ObservableList refundItems) throws SQLException { + if (refundItems.isEmpty()) { + throw new SQLException("Cannot create refund with empty items"); + } + + Connection conn = ConnectionDB.getConnection(); + + SaleDetail originalSale = getSaleById(originalSaleId); + conn = ConnectionDB.getConnection(); + + if (isRefunded(originalSaleId)) { + throw new SQLException("This sale has already been refunded"); + } + + conn.setAutoCommit(false); + + try { + double totalAmount = -refundItems.stream().mapToDouble(SaleCartItem::getTotal).sum(); + + String insertSale = """ + INSERT INTO sale (saleDate, totalAmount, paymentMethod, employeeId, storeId, isRefund, originalSaleId) + VALUES (NOW(), ?, ?, ?, 1, TRUE, ?) + """; + + PreparedStatement saleStmt = conn.prepareStatement(insertSale, Statement.RETURN_GENERATED_KEYS); + saleStmt.setDouble(1, totalAmount); + saleStmt.setString(2, paymentMethod); + saleStmt.setInt(3, employeeId); + saleStmt.setInt(4, originalSaleId); + saleStmt.executeUpdate(); + + ResultSet rs = saleStmt.getGeneratedKeys(); + if (!rs.next()) { + throw new SQLException("Failed to get generated refund ID"); + } + int refundId = rs.getInt(1); + + String insertItem = """ + INSERT INTO saleItem (saleId, prodId, quantity, unitPrice) + VALUES (?, ?, ?, ?) + """; + + String updateInventory = """ + UPDATE inventory + SET quantity = quantity + ? + WHERE prodId = ? + """; + + PreparedStatement itemStmt = conn.prepareStatement(insertItem); + PreparedStatement invStmt = conn.prepareStatement(updateInventory); + + for (SaleCartItem item : refundItems) { + itemStmt.setInt(1, refundId); + itemStmt.setInt(2, item.getProdId()); + itemStmt.setInt(3, -item.getQuantity()); + itemStmt.setDouble(4, item.getUnitPrice()); + itemStmt.executeUpdate(); + + invStmt.setInt(1, item.getQuantity()); + invStmt.setInt(2, item.getProdId()); + int updated = invStmt.executeUpdate(); + + if (updated == 0) { + throw new SQLException("Failed to update inventory for product ID " + item.getProdId()); + } + } + + conn.commit(); + + ActivityLogger.getInstance().logInsert("sale", + String.format("Refund ID: %d", refundId), + String.format("Created refund for sale ID %d with %d items, total: $%.2f", originalSaleId, refundItems.size(), Math.abs(totalAmount))); + + return refundId; + + } catch (SQLException e) { + conn.rollback(); + ActivityLogger.getInstance().logException("SaleDB.createRefund", e, "Creating refund"); + throw e; + } finally { + conn.setAutoCommit(true); + conn.close(); + } + } } diff --git a/src/main/java/org/example/petshopdesktop/models/SaleDetail.java b/src/main/java/org/example/petshopdesktop/models/SaleDetail.java new file mode 100644 index 00000000..8ed6e291 --- /dev/null +++ b/src/main/java/org/example/petshopdesktop/models/SaleDetail.java @@ -0,0 +1,82 @@ +package org.example.petshopdesktop.models; + +import javafx.collections.ObservableList; +import java.time.LocalDateTime; + +public class SaleDetail { + private final int saleId; + private final LocalDateTime saleDate; + private final double totalAmount; + private final String paymentMethod; + private final String employeeName; + private final ObservableList items; + + public SaleDetail(int saleId, LocalDateTime saleDate, double totalAmount, String paymentMethod, String employeeName, ObservableList items) { + this.saleId = saleId; + this.saleDate = saleDate; + this.totalAmount = totalAmount; + this.paymentMethod = paymentMethod; + this.employeeName = employeeName; + this.items = items; + } + + public int getSaleId() { + return saleId; + } + + public LocalDateTime getSaleDate() { + return saleDate; + } + + public double getTotalAmount() { + return totalAmount; + } + + public String getPaymentMethod() { + return paymentMethod; + } + + public String getEmployeeName() { + return employeeName; + } + + public ObservableList getItems() { + return items; + } + + public static class SaleDetailItem { + private final int prodId; + private final String productName; + private final int quantity; + private final double unitPrice; + private final double total; + + public SaleDetailItem(int prodId, String productName, int quantity, double unitPrice, double total) { + this.prodId = prodId; + this.productName = productName; + this.quantity = quantity; + this.unitPrice = unitPrice; + this.total = total; + } + + public int getProdId() { + return prodId; + } + + public String getProductName() { + return productName; + } + + public int getQuantity() { + return quantity; + } + + public double getUnitPrice() { + return unitPrice; + } + + public double getTotal() { + return total; + } + } +} diff --git a/src/main/java/org/example/petshopdesktop/models/SaleLineItem.java b/src/main/java/org/example/petshopdesktop/models/SaleLineItem.java index d44e3662..a8a3d134 100644 --- a/src/main/java/org/example/petshopdesktop/models/SaleLineItem.java +++ b/src/main/java/org/example/petshopdesktop/models/SaleLineItem.java @@ -9,8 +9,9 @@ public class SaleLineItem { private final double unitPrice; private final double total; private final String paymentMethod; + private final boolean isRefund; - public SaleLineItem(int saleId, String saleDate, String employeeName, String itemName, int quantity, double unitPrice, double total, String paymentMethod) { + public SaleLineItem(int saleId, String saleDate, String employeeName, String itemName, int quantity, double unitPrice, double total, String paymentMethod, boolean isRefund) { this.saleId = saleId; this.saleDate = saleDate; this.employeeName = employeeName; @@ -19,6 +20,7 @@ public class SaleLineItem { this.unitPrice = unitPrice; this.total = total; this.paymentMethod = paymentMethod; + this.isRefund = isRefund; } public int getSaleId() { @@ -52,4 +54,8 @@ public class SaleLineItem { public String getPaymentMethod() { return paymentMethod; } + + public boolean isRefund() { + return isRefund; + } } diff --git a/src/main/resources/org/example/petshopdesktop/dialogviews/refund-dialog-view.fxml b/src/main/resources/org/example/petshopdesktop/dialogviews/refund-dialog-view.fxml new file mode 100644 index 00000000..b349a1d9 --- /dev/null +++ b/src/main/resources/org/example/petshopdesktop/dialogviews/refund-dialog-view.fxml @@ -0,0 +1,192 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/org/example/petshopdesktop/modelviews/sale-view.fxml b/src/main/resources/org/example/petshopdesktop/modelviews/sale-view.fxml index 3bcfa9a9..64903a04 100644 --- a/src/main/resources/org/example/petshopdesktop/modelviews/sale-view.fxml +++ b/src/main/resources/org/example/petshopdesktop/modelviews/sale-view.fxml @@ -38,6 +38,14 @@ +