Pushing adoption and inventory

This commit is contained in:
augmentedpotato
2026-02-24 16:12:48 -07:00
parent 168400a6b3
commit dc538776c1
11 changed files with 1512 additions and 22 deletions

View File

@@ -1,11 +1,23 @@
package org.example.petshopdesktop.controllers;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.stage.Modality;
import javafx.stage.Stage;
import org.example.petshopdesktop.controllers.dialogcontrollers.AdoptionDialogController;
import org.example.petshopdesktop.database.AdoptionDB;
import org.example.petshopdesktop.models.Adoption;
import java.io.IOException;
import java.sql.SQLException;
import java.sql.SQLIntegrityConstraintViolationException;
import java.util.Optional;
public class AdoptionController {
@@ -19,42 +31,167 @@ public class AdoptionController {
private Button btnEdit;
@FXML
private TableColumn<?, ?> colAdoptionDate;
private TableColumn<Adoption, Integer> colAdoptionId;
@FXML
private TableColumn<?, ?> colAdoptionFee;
private TableColumn<Adoption, Integer> colPetId;
@FXML
private TableColumn<?, ?> colAdoptionId;
private TableColumn<Adoption, String> colCustomerName;
@FXML
private TableColumn<?, ?> colAdoptionStatus;
private TableColumn<Adoption, String> colAdoptionDate;
@FXML
private TableColumn<?, ?> colCustomerName;
private TableColumn<Adoption, Double> colAdoptionFee;
@FXML
private TableColumn<?, ?> colPetId;
private TableColumn<Adoption, String> colAdoptionStatus;
@FXML
private TableView<?> tvAdoptions;
private TableView<Adoption> tvAdoptions;
@FXML
private TextField txtSearch;
private ObservableList<Adoption> data = FXCollections.observableArrayList();
private String mode = null;
@FXML
void initialize() {
btnEdit.setDisable(true);
btnDelete.setDisable(true);
colAdoptionId.setCellValueFactory(new PropertyValueFactory<>("adoptionId"));
colPetId.setCellValueFactory(new PropertyValueFactory<>("petId"));
colCustomerName.setCellValueFactory(new PropertyValueFactory<>("customerName"));
colAdoptionDate.setCellValueFactory(new PropertyValueFactory<>("adoptionDate"));
colAdoptionFee.setCellValueFactory(new PropertyValueFactory<>("adoptionFee"));
colAdoptionStatus.setCellValueFactory(new PropertyValueFactory<>("adoptionStatus"));
displayAdoptions();
tvAdoptions.getSelectionModel().selectedItemProperty().addListener(
(observable, oldValue, newValue) -> {
btnEdit.setDisable(false);
btnDelete.setDisable(false);
});
txtSearch.textProperty().addListener((observable, oldValue, newValue) -> {
displayFilteredAdoptions(newValue);
});
}
@FXML
void btnAddClicked(ActionEvent event) {
mode = "Add";
openDialog(null, mode);
}
@FXML
void btnDeleteClicked(ActionEvent event) {
int numRows = 0;
Adoption selectedAdoption = tvAdoptions.getSelectionModel().getSelectedItem();
Alert question = new Alert(Alert.AlertType.CONFIRMATION);
question.setHeaderText("Please confirm delete");
question.setContentText("Are you sure you want to delete this adoption record?");
Optional<ButtonType> result = question.showAndWait();
if (result.isPresent() && result.get() == ButtonType.OK) {
int adoptionId = selectedAdoption.getAdoptionId();
try {
numRows = AdoptionDB.deleteAdoption(adoptionId);
}
catch (SQLIntegrityConstraintViolationException e) {
Alert alert = new Alert(Alert.AlertType.ERROR);
alert.setHeaderText("Database Operation Error");
alert.setContentText("Delete failed\nThe selected adoption is being referred in another table");
alert.showAndWait();
return;
} catch (SQLException e) {
throw new RuntimeException(e);
}
if (numRows == 0) {
Alert alert = new Alert(Alert.AlertType.ERROR);
alert.setHeaderText("Database Operation Error");
alert.setContentText("Delete failed");
alert.showAndWait();
} else {
Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
alert.setHeaderText("Database Operation Confirmed");
alert.setContentText("Delete successful");
alert.showAndWait();
displayAdoptions();
btnDelete.setDisable(true);
btnEdit.setDisable(true);
txtSearch.setText("");
}
}
}
@FXML
void btnEditClicked(ActionEvent event) {
Adoption selectedAdoption = tvAdoptions.getSelectionModel().getSelectedItem();
if (selectedAdoption != null) {
mode = "Edit";
openDialog(selectedAdoption, mode);
}
}
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) {
System.out.println("Error while fetching table data: " + e.getMessage());
}
}
private void displayAdoptions() {
data.clear();
try {
data = AdoptionDB.getAdoptions();
} catch (SQLException e) {
System.out.println("Error while fetching table data: " + e.getMessage());
}
tvAdoptions.setItems(data);
}
private void openDialog(Adoption adoption, String mode) {
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource(
"/org/example/petshopdesktop/dialogviews/adoption-dialog-view.fxml"));
Scene scene = null;
try {
scene = new Scene(fxmlLoader.load());
} catch (IOException e) {
throw new RuntimeException(e);
}
AdoptionDialogController dialogController = fxmlLoader.getController();
dialogController.setMode(mode);
if (mode.equals("Edit")) {
dialogController.displayAdoptionDetails(adoption);
}
Stage dialogStage = new Stage();
dialogStage.initModality(Modality.APPLICATION_MODAL);
dialogStage.setTitle(mode.equals("Add") ? "Add Adoption" : "Edit Adoption");
dialogStage.setScene(scene);
dialogStage.showAndWait();
displayAdoptions();
btnDelete.setDisable(true);
btnEdit.setDisable(true);
txtSearch.setText("");
}
}

View File

@@ -1,14 +1,27 @@
package org.example.petshopdesktop.controllers;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.Button;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.control.*;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.stage.Modality;
import javafx.stage.Stage;
import org.example.petshopdesktop.controllers.dialogcontrollers.InventoryDialogController;
import org.example.petshopdesktop.database.InventoryDB;
import org.example.petshopdesktop.models.Inventory;
import java.io.IOException;
import java.sql.SQLException;
import java.sql.SQLIntegrityConstraintViolationException;
import java.util.Optional;
public class InventoryController {
//FXML elements
@FXML
private Button btnAdd;
@@ -19,36 +32,193 @@ public class InventoryController {
private Button btnEdit;
@FXML
private TableColumn<?, ?> colInventoryId;
private TableColumn<Inventory, Integer> colInventoryId;
@FXML
private TableColumn<?, ?> colProductId;
private TableColumn<Inventory, Integer> colProductId;
@FXML
private TableColumn<?, ?> colProductName;
private TableColumn<Inventory, String> colProductName;
@FXML
private TableColumn<?, ?> colQuantity;
private TableColumn<Inventory, Integer> colQuantity;
@FXML
private TableView<?> tvInventory;
private TableView<Inventory> tvInventory;
@FXML
private TextField txtSearch;
private ObservableList<Inventory> data = FXCollections.observableArrayList();
//Determines if in add/edit mode
private String mode = null;
//Loads upon view bootup
@FXML
void initialize() {
//Buttons disabled until row is selected
btnEdit.setDisable(true);
btnDelete.setDisable(true);
colInventoryId.setCellValueFactory(new PropertyValueFactory<>("inventoryId"));
colProductId.setCellValueFactory(new PropertyValueFactory<>("prodId"));
colProductName.setCellValueFactory(new PropertyValueFactory<>("prodName"));
colQuantity.setCellValueFactory(new PropertyValueFactory<>("quantity"));
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);
});
}
//Opens dialog in add mode
@FXML
void btnAddClicked(ActionEvent event) {
mode = "Add";
openDialog(null, mode);
}
//Prompts user for confirmation prior to deletion
@FXML
void btnDeleteClicked(ActionEvent event) {
int numRows = 0;
Inventory selectedInventory = tvInventory.getSelectionModel().getSelectedItem();
//Confirmation popup
Alert question = new Alert(Alert.AlertType.CONFIRMATION);
question.setHeaderText("Please confirm delete");
question.setContentText("Are you sure you want to delete this inventory record?");
Optional<ButtonType> result = question.showAndWait();
//If user confirms, proceed with trying to delete...
if (result.isPresent() && result.get() == ButtonType.OK) {
int inventoryId = selectedInventory.getInventoryId();
try {
numRows = InventoryDB.deleteInventory(inventoryId);
}
catch (SQLIntegrityConstraintViolationException e) {
Alert alert = new Alert(Alert.AlertType.ERROR);
alert.setHeaderText("Database Operation Error");
alert.setContentText("Delete failed\nThe selected inventory record is being referred in another table");
alert.showAndWait();
return;
}
catch (SQLException e) {
throw new RuntimeException(e);
}
//Checks if deletion succeeded
if (numRows == 0) {
Alert alert = new Alert(Alert.AlertType.ERROR);
alert.setHeaderText("Database Operation Error");
alert.setContentText("Delete failed");
alert.showAndWait();
}
else {
Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
alert.setHeaderText("Database Operation Confirmed");
alert.setContentText("Delete successful");
alert.showAndWait();
//Refresh UI
displayInventory();
btnDelete.setDisable(true);
btnEdit.setDisable(true);
txtSearch.setText("");
}
}
}
//Editing a record
@FXML
void btnEditClicked(ActionEvent event) {
Inventory selectedInventory = tvInventory.getSelectionModel().getSelectedItem();
if (selectedInventory != null) {
mode = "Edit";
openDialog(selectedInventory, mode);
}
}
//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();
}
else {
data = InventoryDB.getFilteredInventory(filter);
tvInventory.setItems(data);
}
}
catch (Exception e) {
System.out.println("Error while fetching table data: " + e.getMessage());
}
}
//Displays all records from DB
private void displayInventory() {
data.clear();
try {
data = InventoryDB.getInventory();
}
catch (SQLException e) {
System.out.println("Error while fetching table data: " + e.getMessage());
}
tvInventory.setItems(data);
}
//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) {
throw new RuntimeException(e);
}
//Passes data and mode to the view
InventoryDialogController dialogController = fxmlLoader.getController();
dialogController.setMode(mode);
if (mode.equals("Edit")) {
dialogController.displayInventoryDetails(inventory);
}
Stage dialogStage = new Stage();
dialogStage.initModality(Modality.APPLICATION_MODAL);
dialogStage.setTitle(mode.equals("Add") ? "Add Inventory" : "Edit Inventory");
dialogStage.setScene(scene);
dialogStage.showAndWait();
//Refresh inventory
displayInventory();
btnDelete.setDisable(true);
btnEdit.setDisable(true);
txtSearch.setText("");
}
}

View File

@@ -0,0 +1,266 @@
package org.example.petshopdesktop.controllers.dialogcontrollers;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.event.EventHandler;
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.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.models.Adoption;
import org.example.petshopdesktop.models.Customer;
import org.example.petshopdesktop.models.Pet;
import java.sql.SQLException;
import java.time.LocalDate;
public class AdoptionDialogController {
//FXML elements
@FXML
private Button btnCancel;
@FXML
private Button btnSave;
@FXML
private ComboBox<String> cbAdoptionStatus;
@FXML
private ComboBox<Customer> cbCustomer;
@FXML
private ComboBox<Pet> cbPet;
@FXML
private DatePicker dpAdoptionDate;
@FXML
private Label lblAdoptionId;
@FXML
private Label lblMode;
//Stores if the dialog view is in add/edit mode
private String mode = null;
//Adoption statuses
private ObservableList<String> statusList = FXCollections.observableArrayList(
"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<Pet>() {
@Override
public String toString(Pet pet) {
return pet == null ? "" : pet.getPetId() + ": " + pet.getPetName();
}
//Not used
@Override
public Pet fromString(String string) { return null; }
});
//Load pets from DB into pet combobox
try {
cbPet.setItems(PetDB.getPets());
}
catch (SQLException e) {
System.out.println("Error loading pets: " + e.getMessage());
}
//Load customers from DB into customer combobox
try {
cbCustomer.setItems(AdoptionDB.getCustomers());
}
catch (SQLException e) {
System.out.println("Error loading customers: " + e.getMessage());
}
//Save button handler
btnSave.setOnMouseClicked(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent mouseEvent) {
buttonSaveClicked(mouseEvent);
}
});
//Cancel button handler, closes dialog view
btnCancel.setOnMouseClicked(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent mouseEvent) {
closeStage(mouseEvent);
}
});
}
//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";
}
if (cbCustomer.getSelectionModel().getSelectedItem() == null) {
errorMsg += "Customer is required.\n";
}
if (dpAdoptionDate.getValue() == null) {
errorMsg += "Adoption Date is required.\n";
}
if (cbAdoptionStatus.getSelectionModel().getSelectedItem() == null) {
errorMsg += "Status is required.\n";
}
//If no errors, attempt DB operation
if (errorMsg.isEmpty()) {
Adoption adoption = collectAdoption();
//Try inserting into DB
if (mode.equals("Add")) {
try {
numRow = AdoptionDB.insertAdoption(adoption);
}
catch (SQLException e) {
throw new RuntimeException(e);
}
}
//Try updating adoption
else {
try {
numRow = AdoptionDB.updateAdoption(adoption.getAdoptionId(), adoption);
}
catch (SQLException e) {
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();
closeStage(mouseEvent);
}
//DB operation worked!
else {
Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
alert.setHeaderText("Database Operation Confirmed");
alert.setContentText(mode + " succeeded");
alert.showAndWait();
closeStage(mouseEvent);
}
}
//If there are errors, display them
else {
Alert alert = new Alert(Alert.AlertType.ERROR);
alert.setHeaderText("Input Error");
alert.setContentText(errorMsg);
alert.showAndWait();
}
}
//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();
Stage stage = (Stage) node.getScene().getWindow();
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()) {
cbPet.getSelectionModel().select(pet);
break;
}
}
//Select customer
for (Customer customer : cbCustomer.getItems()) {
if (customer.getCustomerId() == adoption.getCustomerId()) {
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);
break;
}
}
}
}
//Sets dialog mode
//Also updates label and adoption ID visibility
public void setMode(String mode) {
this.mode = mode;
lblMode.setText(mode + " Adoption");
lblAdoptionId.setVisible(mode.equals("Edit"));
}
}

View File

@@ -0,0 +1,228 @@
package org.example.petshopdesktop.controllers.dialogcontrollers;
import javafx.event.EventHandler;
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 javafx.util.StringConverter;
import org.example.petshopdesktop.Validator;
import org.example.petshopdesktop.database.InventoryDB;
import org.example.petshopdesktop.database.ProductDB;
import org.example.petshopdesktop.models.Inventory;
import org.example.petshopdesktop.models.Product;
import java.sql.SQLException;
public class InventoryDialogController {
//FXML elements
@FXML
private Button btnCancel;
@FXML
private Button btnSave;
@FXML
private ComboBox<Product> cbProduct;
@FXML
private Label lblInventoryId;
@FXML
private Label lblMode;
@FXML
private TextField txtQuantity;
//Determines if the mode is add or edit
private String mode = null;
//Loads upon .FXML boot
@FXML
void initialize() {
cbProduct.setConverter(new StringConverter<Product>() {
//Displays product in combobox (prodID + name)
@Override
public String toString(Product product) {
return product == null ? "" : product.getProdId() + ": " + product.getProdName();
}
//Not needed
@Override
public Product fromString(String string) { return null; }
});
//Load product list from DB into combobox
try {
cbProduct.setItems(ProductDB.getProducts());
}
catch (SQLException e) {
System.out.println("Error loading products: " + e.getMessage());
}
//Save button handler
btnSave.setOnMouseClicked(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent mouseEvent) {
buttonSaveClicked(mouseEvent);
}
});
//Cancel button handler
btnCancel.setOnMouseClicked(new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent mouseEvent) {
closeStage(mouseEvent);
}
});
}
//Handles save button click event
private void buttonSaveClicked(MouseEvent mouseEvent) {
int numRow = 0;
String errorMsg = "";
if (cbProduct.getSelectionModel().getSelectedItem() == null) {
errorMsg += "Product is required.\n";
}
//Validate inputs
errorMsg += Validator.isPresent(txtQuantity.getText(), "Quantity");
errorMsg += Validator.isLessThanVarChars(txtQuantity.getText(), "Quantity", 11);
errorMsg += Validator.isNonNegativeInteger(txtQuantity.getText(), "Quantity");
//Operation only occurs if there are no errors
if (errorMsg.isEmpty()) {
//Ensures duplicate entries aren't possible
if (mode.equals("Add")) {
Product selectedProduct = cbProduct.getSelectionModel().getSelectedItem();
try {
if (InventoryDB.productExistsInInventory(selectedProduct.getProdId())) {
Alert alert = new Alert(Alert.AlertType.ERROR);
alert.setHeaderText("Duplicate Entry");
alert.setContentText("An inventory record for \"" + selectedProduct.getProdName() + "\" already exists.");
alert.showAndWait();
return;
}
}
catch (SQLException e) {
throw new RuntimeException(e);
}
}
Inventory inventory = collectInventory();
//Adding inventory
if (mode.equals("Add")) {
try {
numRow = InventoryDB.insertInventory(inventory);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
//Updating inventory
else {
try {
numRow = InventoryDB.updateInventory(inventory.getInventoryId(), inventory);
}
catch (SQLException e) {
throw new RuntimeException(e);
}
}
//Display database operation result
if (numRow == 0) {
Alert alert = new Alert(Alert.AlertType.ERROR);
alert.setHeaderText("Database Operation Error");
alert.setContentText(mode + " failed");
alert.showAndWait();
closeStage(mouseEvent);
}
else {
Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
alert.setHeaderText("Database Operation Confirmed");
alert.setContentText(mode + " succeeded");
alert.showAndWait();
closeStage(mouseEvent);
}
}
//Displays validation errors
else {
Alert alert = new Alert(Alert.AlertType.ERROR);
alert.setHeaderText("Input Error");
alert.setContentText(errorMsg);
alert.showAndWait();
}
}
//Create Inventory object using values entered by user
private Inventory collectInventory() {
int inventoryId = 0;
//Grab inventory ID when editing pre-existing record
if (lblInventoryId.isVisible()) {
inventoryId = Integer.parseInt(lblInventoryId.getText().split(": ")[1]);
}
//Get selected product
Product selectedProduct = cbProduct.getSelectionModel().getSelectedItem();
//Build and returns Inventory object
return new Inventory(
inventoryId,
selectedProduct.getProdId(),
selectedProduct.getProdName(),
Integer.parseInt(txtQuantity.getText())
);
}
//Close dialog view
private void closeStage(MouseEvent mouseEvent) {
Node node = (Node) mouseEvent.getSource();
Stage stage = (Stage) node.getScene().getWindow();
stage.close();
}
//Editing
//Displays fields with existing inventory data
public void displayInventoryDetails(Inventory inventory) {
if (inventory != null) {
//Displays inventory ID
lblInventoryId.setText("ID: " + inventory.getInventoryId());
//Selecting matching product in combobox
for (Product product : cbProduct.getItems()) {
if (product.getProdId() == inventory.getProdId()) {
cbProduct.getSelectionModel().select(product);
break;
}
}
txtQuantity.setText(String.valueOf(inventory.getQuantity()));
}
}
//Sets dialog view to add/edit. Updates UI labels
public void setMode(String mode) {
this.mode = mode;
lblMode.setText(mode + " Inventory");
lblInventoryId.setVisible(mode.equals("Edit"));
}
}

View File

@@ -0,0 +1,140 @@
package org.example.petshopdesktop.database;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import org.example.petshopdesktop.models.Adoption;
import org.example.petshopdesktop.models.Customer;
import org.example.petshopdesktop.models.Pet;
import java.sql.*;
public class AdoptionDB {
//Select query
private static final String BASE_SELECT =
"SELECT a.adoptionId, a.petId, a.customerId, " +
"CONCAT(c.firstName, ' ', c.lastName) AS customerName, " +
"a.adoptionDate, p.petPrice AS adoptionFee, a.adoptionStatus " +
"FROM adoption a " +
"JOIN customer c ON a.customerId = c.customerId " +
"JOIN pet p ON a.petId = p.petId";
//Retrieve all adoption records from DB
public static ObservableList<Adoption> getAdoptions() throws SQLException {
ObservableList<Adoption> adoptions = FXCollections.observableArrayList();
Connection conn = ConnectionDB.getConnection();
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(BASE_SELECT);
//Map results
while (rs.next()) {
adoptions.add(mapRow(rs));
}
conn.close();
return adoptions;
}
//Returns data depending on search query
public static ObservableList<Adoption> getFilteredAdoptions(String filter) throws SQLException {
ObservableList<Adoption> adoptions = FXCollections.observableArrayList();
Connection conn = ConnectionDB.getConnection();
String sql = BASE_SELECT +
" WHERE a.adoptionId LIKE '%" + filter + "%' OR " +
"a.petId LIKE '%" + filter + "%' OR " +
"CONCAT(c.firstName, ' ', c.lastName) LIKE '%" + filter + "%' OR " +
"a.adoptionDate LIKE '%" + filter + "%' OR " +
"p.petPrice LIKE '%" + filter + "%' OR " +
"a.adoptionStatus LIKE '%" + filter + "%'";
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(sql);
//Map results
while (rs.next()) {
adoptions.add(mapRow(rs));
}
conn.close();
return adoptions;
}
//Add new adoption
public static int insertAdoption(Adoption adoption) throws SQLException {
Connection conn = ConnectionDB.getConnection();
String sql = "INSERT INTO adoption (petId, customerId, adoptionDate, adoptionStatus) VALUES (?, ?, ?, ?)";
PreparedStatement stmt = conn.prepareStatement(sql);
//Put data in Adoption object
stmt.setInt(1, adoption.getPetId());
stmt.setInt(2, adoption.getCustomerId());
stmt.setString(3, adoption.getAdoptionDate());
stmt.setString(4, adoption.getAdoptionStatus());
int numRows = stmt.executeUpdate();
conn.close();
return numRows;
}
//Updating pre-existing adoption
public static int updateAdoption(int adoptionId, Adoption adoption) throws SQLException {
Connection conn = ConnectionDB.getConnection();
String sql = "UPDATE adoption SET petId = ?, customerId = ?, adoptionDate = ?, adoptionStatus = ? WHERE adoptionId = ?";
PreparedStatement stmt = conn.prepareStatement(sql);
stmt.setInt(1, adoption.getPetId());
stmt.setInt(2, adoption.getCustomerId());
stmt.setString(3, adoption.getAdoptionDate());
stmt.setString(4, adoption.getAdoptionStatus());
stmt.setInt(5, adoptionId);
int numRows = stmt.executeUpdate();
conn.close();
return numRows;
}
//Delete adoption
public static int deleteAdoption(int adoptionId) throws SQLException {
Connection conn = ConnectionDB.getConnection();
String sql = "DELETE FROM adoption WHERE adoptionId = ?";
PreparedStatement stmt = conn.prepareStatement(sql);
stmt.setInt(1, adoptionId);
int numRows = stmt.executeUpdate();
conn.close();
return numRows;
}
//Grab list of customers from DB for comboboxes
public static ObservableList<Customer> getCustomers() throws SQLException {
ObservableList<Customer> customers = FXCollections.observableArrayList();
Connection conn = ConnectionDB.getConnection();
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT customerId, firstName, lastName FROM customer");
while (rs.next()) {
customers.add(new Customer(rs.getInt(1), rs.getString(2), rs.getString(3)));
}
conn.close();
return customers;
}
//DRY: converts DB data into usable Java object
private static Adoption mapRow(ResultSet rs) throws SQLException {
return new Adoption(
rs.getInt("adoptionId"),
rs.getInt("petId"),
rs.getInt("customerId"),
rs.getString("customerName"),
rs.getString("adoptionDate"),
rs.getDouble("adoptionFee"),
rs.getString("adoptionStatus")
);
}
}

View File

@@ -0,0 +1,133 @@
package org.example.petshopdesktop.database;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import org.example.petshopdesktop.models.Inventory;
import java.sql.*;
public class InventoryDB {
//Base selection query
//Returns invID, ProdID, Quantity from Inventory table
//Returns ProdName from Product table
private static final String BASE_SELECT =
"SELECT i.inventoryId, i.prodId, p.prodName, i.quantity " +
"FROM inventory i " +
"JOIN product p ON i.prodId = p.prodId";
//Retrieves inventory records from DB
public static ObservableList<Inventory> getInventory() throws SQLException {
ObservableList<Inventory> inventoryList = FXCollections.observableArrayList();
Connection conn = ConnectionDB.getConnection();
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(BASE_SELECT);
while (rs.next()) {
inventoryList.add(mapRow(rs));
}
conn.close();
return inventoryList;
}
//Returns records depending on search
public static ObservableList<Inventory> getFilteredInventory(String filter) throws SQLException {
ObservableList<Inventory> inventoryList = FXCollections.observableArrayList();
Connection conn = ConnectionDB.getConnection();
String sql = BASE_SELECT +
" WHERE i.inventoryId LIKE ? OR " +
"i.prodId LIKE ? OR " +
"p.prodName LIKE ? OR " +
"i.quantity LIKE ?";
String filteredString = "%" + filter + "%";
PreparedStatement stmt = conn.prepareStatement(sql);
for (int i = 1; i <= 4; i++) {
stmt.setString(i, filteredString);
}
ResultSet rs = stmt.executeQuery();
while (rs.next()) {
inventoryList.add(mapRow(rs));
}
conn.close();
return inventoryList;
}
//Checks if the product already has an inventory entry
public static boolean productExistsInInventory(int prodId) throws SQLException {
Connection conn = ConnectionDB.getConnection();
String sql = "SELECT COUNT(*) FROM inventory WHERE prodId = ?";
PreparedStatement stmt = conn.prepareStatement(sql);
stmt.setInt(1, prodId);
ResultSet rs = stmt.executeQuery();
boolean exists = rs.next() && rs.getInt(1) > 0;
conn.close();
return exists;
}
//Inserting new inventory record
public static int insertInventory(Inventory inventory) throws SQLException {
Connection conn = ConnectionDB.getConnection();
String sql = "INSERT INTO inventory (prodId, quantity) VALUES (?, ?)";
PreparedStatement stmt = conn.prepareStatement(sql);
stmt.setInt(1, inventory.getProdId());
stmt.setInt(2, inventory.getQuantity());
int numRows = stmt.executeUpdate();
conn.close();
return numRows;
}
//Updating inventory record
public static int updateInventory(int inventoryId, Inventory inventory) throws SQLException {
Connection conn = ConnectionDB.getConnection();
String sql = "UPDATE inventory SET prodId = ?, quantity = ? WHERE inventoryId = ?";
PreparedStatement stmt = conn.prepareStatement(sql);
stmt.setInt(1, inventory.getProdId());
stmt.setInt(2, inventory.getQuantity());
stmt.setInt(3, inventoryId);
int numRows = stmt.executeUpdate();
conn.close();
return numRows;
}
//Deleting inventory record
public static int deleteInventory(int inventoryId) throws SQLException {
Connection conn = ConnectionDB.getConnection();
String sql = "DELETE FROM inventory WHERE inventoryId = ?";
PreparedStatement stmt = conn.prepareStatement(sql);
stmt.setInt(1, inventoryId);
int numRows = stmt.executeUpdate();
conn.close();
return numRows;
}
//DRY: converts DB data into usable Java object
private static Inventory mapRow(ResultSet rs) throws SQLException {
return new Inventory(
rs.getInt("inventoryId"),
rs.getInt("prodId"),
rs.getString("prodName"),
rs.getInt("quantity")
);
}
}

View File

@@ -0,0 +1,68 @@
package org.example.petshopdesktop.models;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;
public class Adoption {
private SimpleIntegerProperty adoptionId;
private SimpleIntegerProperty petId;
private SimpleIntegerProperty customerId;
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) {
this.adoptionId = new SimpleIntegerProperty(adoptionId);
this.petId = new SimpleIntegerProperty(petId);
this.customerId = new SimpleIntegerProperty(customerId);
this.customerName = new SimpleStringProperty(customerName);
this.adoptionDate = new SimpleStringProperty(adoptionDate);
this.adoptionFee = new SimpleDoubleProperty(adoptionFee);
this.adoptionStatus = new SimpleStringProperty(adoptionStatus);
}
public int getAdoptionId() { return adoptionId.get(); }
public void setAdoptionId(int adoptionId) { this.adoptionId.set(adoptionId); }
public SimpleIntegerProperty adoptionIdProperty() { return adoptionId; }
public int getPetId() { return petId.get(); }
public void setPetId(int petId) { this.petId.set(petId); }
public SimpleIntegerProperty petIdProperty() { return petId; }
public int getCustomerId() { return customerId.get(); }
public void setCustomerId(int customerId) { this.customerId.set(customerId); }
public SimpleIntegerProperty customerIdProperty() { return customerId; }
public String getCustomerName() { return customerName.get(); }
public void setCustomerName(String customerName) { this.customerName.set(customerName); }
public SimpleStringProperty customerNameProperty() { return customerName; }
public String getAdoptionDate() { return adoptionDate.get(); }
public void setAdoptionDate(String adoptionDate) { this.adoptionDate.set(adoptionDate); }
public SimpleStringProperty adoptionDateProperty() { return adoptionDate; }
public double getAdoptionFee() { return adoptionFee.get(); }
public void setAdoptionFee(double adoptionFee) { this.adoptionFee.set(adoptionFee); }
public SimpleDoubleProperty adoptionFeeProperty() { return adoptionFee; }
public String getAdoptionStatus() { return adoptionStatus.get(); }
public void setAdoptionStatus(String adoptionStatus) { this.adoptionStatus.set(adoptionStatus); }
public SimpleStringProperty adoptionStatusProperty() { return adoptionStatus; }
}

View File

@@ -0,0 +1,35 @@
package org.example.petshopdesktop.models;
public class Customer {
private int customerId;
private String firstName;
private String lastName;
//Constructor
public Customer(int customerId, String firstName, String lastName) {
this.customerId = customerId;
this.firstName = firstName;
this.lastName = lastName;
}
//Returns customer ID
public int getCustomerId() {
return customerId;
}
//Returns first name
public String getFirstName() {
return firstName;
}
//Returns last name
public String getLastName() {
return lastName;
}
//Returns first + last name
@Override
public String toString() {
return firstName + " " + lastName;
}
}

View File

@@ -0,0 +1,43 @@
package org.example.petshopdesktop.models;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.property.SimpleStringProperty;
public class Inventory {
private SimpleIntegerProperty inventoryId;
private SimpleIntegerProperty prodId;
private SimpleStringProperty prodName;
private SimpleIntegerProperty quantity;
//Constructor
public Inventory(int inventoryId, int prodId, String prodName, int quantity) {
this.inventoryId = new SimpleIntegerProperty(inventoryId);
this.prodId = new SimpleIntegerProperty(prodId);
this.prodName = new SimpleStringProperty(prodName);
this.quantity = new SimpleIntegerProperty(quantity);
}
public int getInventoryId() { return inventoryId.get(); }
public void setInventoryId(int inventoryId) { this.inventoryId.set(inventoryId); }
public SimpleIntegerProperty inventoryIdProperty() { return inventoryId; }
public int getProdId() { return prodId.get(); }
public void setProdId(int prodId) { this.prodId.set(prodId); }
public SimpleIntegerProperty prodIdProperty() { return prodId; }
public String getProdName() { return prodName.get(); }
public void setProdName(String prodName) { this.prodName.set(prodName); }
public SimpleStringProperty prodNameProperty() { return prodName; }
public int getQuantity() { return quantity.get(); }
public void setQuantity(int quantity) { this.quantity.set(quantity); }
public SimpleIntegerProperty quantityProperty() { return quantity; }
}