Merge pull request #13 from RecentRunner/CURDProductSupplier
Added CRUD to productSuppliers
This commit is contained in:
@@ -85,6 +85,7 @@ CREATE TABLE product (
|
||||
CREATE TABLE productSupplier (
|
||||
supId INT NOT NULL,
|
||||
prodId INT NOT NULL,
|
||||
cost DECIMAL(10, 2) NOT NULL,
|
||||
PRIMARY KEY (supId, prodId),
|
||||
FOREIGN KEY (supId) REFERENCES supplier(supId),
|
||||
FOREIGN KEY (prodId) REFERENCES product(prodId)
|
||||
@@ -234,16 +235,16 @@ VALUES
|
||||
('Hamster Wheel', 15.00, 5, 'Exercise wheel for small pets'),
|
||||
('Organic Dog Treats', 25.00, 1, 'Natural dog treats');
|
||||
|
||||
INSERT INTO productSupplier (supId, prodId)
|
||||
INSERT INTO productSupplier (supId, prodId, cost)
|
||||
VALUES
|
||||
(1, 1),
|
||||
(1, 2),
|
||||
(2, 2),
|
||||
(3, 3),
|
||||
(3, 4),
|
||||
(4, 5),
|
||||
(5, 6),
|
||||
(1, 6);
|
||||
(1, 1, 35.00),
|
||||
(1, 2, 6.50),
|
||||
(2, 2, 7.00),
|
||||
(3, 3, 90.00),
|
||||
(3, 4, 60.00),
|
||||
(4, 5, 10.00),
|
||||
(5, 6, 18.00),
|
||||
(1, 6, 17.50);
|
||||
|
||||
INSERT INTO inventory (prodId, quantity)
|
||||
VALUES
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
package org.example.petshopdesktop.DTOs;
|
||||
|
||||
import javafx.beans.property.SimpleDoubleProperty;
|
||||
import javafx.beans.property.SimpleIntegerProperty;
|
||||
import javafx.beans.property.SimpleStringProperty;
|
||||
|
||||
public class ProductSupplierDTO {
|
||||
private SimpleIntegerProperty supId;
|
||||
private SimpleIntegerProperty prodId;
|
||||
private SimpleStringProperty supCompany;
|
||||
private SimpleStringProperty prodName;
|
||||
private SimpleDoubleProperty cost;
|
||||
|
||||
//constructor
|
||||
public ProductSupplierDTO(int supId, int prodId, String supCompany, String prodName, double cost) {
|
||||
this.supId = new SimpleIntegerProperty(supId);
|
||||
this.prodId = new SimpleIntegerProperty(prodId);
|
||||
this.supCompany = new SimpleStringProperty(supCompany);
|
||||
this.prodName = new SimpleStringProperty(prodName);
|
||||
this.cost = new SimpleDoubleProperty(cost);
|
||||
}
|
||||
|
||||
//getter and setters
|
||||
public int getSupId() {
|
||||
return supId.get();
|
||||
}
|
||||
|
||||
public SimpleIntegerProperty supIdProperty() {
|
||||
return supId;
|
||||
}
|
||||
|
||||
public void setSupId(int supId) {
|
||||
this.supId.set(supId);
|
||||
}
|
||||
|
||||
public int getProdId() {
|
||||
return prodId.get();
|
||||
}
|
||||
|
||||
public SimpleIntegerProperty prodIdProperty() {
|
||||
return prodId;
|
||||
}
|
||||
|
||||
public void setProdId(int prodId) {
|
||||
this.prodId.set(prodId);
|
||||
}
|
||||
|
||||
public String getSupCompany() {
|
||||
return supCompany.get();
|
||||
}
|
||||
|
||||
public SimpleStringProperty supCompanyProperty() {
|
||||
return supCompany;
|
||||
}
|
||||
|
||||
public void setSupCompany(String supCompany) {
|
||||
this.supCompany.set(supCompany);
|
||||
}
|
||||
|
||||
public String getProdName() {
|
||||
return prodName.get();
|
||||
}
|
||||
|
||||
public SimpleStringProperty prodNameProperty() {
|
||||
return prodName;
|
||||
}
|
||||
|
||||
public void setProdName(String prodName) {
|
||||
this.prodName.set(prodName);
|
||||
}
|
||||
|
||||
public double getCost() {
|
||||
return cost.get();
|
||||
}
|
||||
|
||||
public SimpleDoubleProperty costProperty() {
|
||||
return cost;
|
||||
}
|
||||
|
||||
public void setCost(double cost) {
|
||||
this.cost.set(cost);
|
||||
}
|
||||
}
|
||||
@@ -105,7 +105,7 @@ public class ProductController {
|
||||
try{
|
||||
data = ProductDB.getProductDTO();
|
||||
} catch (SQLException e) {
|
||||
System.out.println(e.getMessage());
|
||||
System.out.println("Error while fetching table data: " + e.getMessage());
|
||||
}
|
||||
|
||||
//put data in the table
|
||||
@@ -114,7 +114,7 @@ public class ProductController {
|
||||
|
||||
/**
|
||||
* open a new dialog for adding a product
|
||||
* @param event
|
||||
* @param event click event for button
|
||||
*/
|
||||
@FXML
|
||||
void btnAddClicked(ActionEvent event) {
|
||||
@@ -211,7 +211,7 @@ public class ProductController {
|
||||
tvProducts.setItems(data);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
System.out.println("Error while fetching table data: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +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.DTOs.ProductDTO;
|
||||
import org.example.petshopdesktop.DTOs.ProductSupplierDTO;
|
||||
import org.example.petshopdesktop.controllers.dialogcontrollers.ProductDialogController;
|
||||
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 java.io.IOException;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.SQLIntegrityConstraintViolationException;
|
||||
import java.util.Optional;
|
||||
|
||||
public class ProductSupplierController {
|
||||
|
||||
@@ -19,39 +35,222 @@ public class ProductSupplierController {
|
||||
private Button btnEdit;
|
||||
|
||||
@FXML
|
||||
private TableColumn<?, ?> colCost;
|
||||
private TableColumn<ProductSupplierDTO, Double> colCost;
|
||||
|
||||
@FXML
|
||||
private TableColumn<?, ?> colProductId;
|
||||
private TableColumn<ProductSupplierDTO, Integer> colProductId;
|
||||
|
||||
@FXML
|
||||
private TableColumn<?, ?> colProductName;
|
||||
private TableColumn<ProductSupplierDTO, String> colProductName;
|
||||
|
||||
@FXML
|
||||
private TableColumn<?, ?> colSupplierId;
|
||||
private TableColumn<ProductSupplierDTO, Integer> colSupplierId;
|
||||
|
||||
@FXML
|
||||
private TableColumn<?, ?> colSupplierName;
|
||||
private TableColumn<ProductSupplierDTO, String> colSupplierName;
|
||||
|
||||
@FXML
|
||||
private TableView<?> tvProductSuppliers;
|
||||
private TableView<ProductSupplierDTO> tvProductSuppliers;
|
||||
|
||||
@FXML
|
||||
private TextField txtSearch;
|
||||
|
||||
//data declaration
|
||||
private ObservableList<ProductSupplierDTO> data = FXCollections.observableArrayList();
|
||||
private String mode = null;
|
||||
|
||||
/**
|
||||
* Set up the table view for table and display it when starting up
|
||||
*/
|
||||
@FXML
|
||||
void btnAddClicked(ActionEvent event) {
|
||||
public void initialize() {
|
||||
//Disable buttons until a row is selected
|
||||
btnEdit.setDisable(true);
|
||||
btnDelete.setDisable(true);
|
||||
//set up table columns
|
||||
colProductId.setCellValueFactory(new PropertyValueFactory<ProductSupplierDTO,Integer>("prodId"));
|
||||
colProductName.setCellValueFactory(new PropertyValueFactory<ProductSupplierDTO,String>("prodName"));
|
||||
colSupplierId.setCellValueFactory(new PropertyValueFactory<ProductSupplierDTO,Integer>("supId"));
|
||||
colSupplierName.setCellValueFactory(new PropertyValueFactory<ProductSupplierDTO,String>("supCompany"));
|
||||
colCost.setCellValueFactory(new PropertyValueFactory<ProductSupplierDTO,Double>("cost"));
|
||||
|
||||
displayProductSupplier();
|
||||
|
||||
//EventListener to Enable buttons when a row is selected
|
||||
tvProductSuppliers.getSelectionModel().selectedItemProperty().addListener(
|
||||
(observable, oldValue, newValue) -> {
|
||||
btnEdit.setDisable(false);
|
||||
btnDelete.setDisable(false);
|
||||
}
|
||||
);
|
||||
|
||||
//EventListener to search when text is changed on searchbar
|
||||
txtSearch.textProperty().addListener((observable, oldValue, newValue) -> {
|
||||
displayFilteredProductSupplier(newValue);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the ProductSupplierDTO to table view
|
||||
*/
|
||||
private void displayProductSupplier() {
|
||||
//Erase old content
|
||||
data.clear();
|
||||
|
||||
//get ProductSupplier from database
|
||||
try{
|
||||
data = ProductSupplierDB.getProductSupplierDTO();
|
||||
} catch (SQLException e) {
|
||||
System.out.println("Error while fetching table data: " + e.getMessage());
|
||||
}
|
||||
|
||||
//put data in the table
|
||||
tvProductSuppliers.setItems(data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter the table given the string from the searchbar
|
||||
* @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) {
|
||||
System.out.println("Error while fetching table data: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* open a new dialog for adding a productSupplier
|
||||
* @param event click event for button
|
||||
*/
|
||||
@FXML
|
||||
void btnAddClicked(ActionEvent event) {
|
||||
mode = "Add";
|
||||
openDialog(null,mode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a selected productSupplier when delete is clicked
|
||||
* @param event click event for button
|
||||
*/
|
||||
@FXML
|
||||
void btnDeleteClicked(ActionEvent event) {
|
||||
int numRows = 0;
|
||||
//set selected item
|
||||
ProductSupplierDTO selectedProductSupplier = tvProductSuppliers.getSelectionModel().getSelectedItem();
|
||||
|
||||
//ask user to confirm
|
||||
Alert question = new Alert(Alert.AlertType.CONFIRMATION);
|
||||
question.setHeaderText("Please confirm delete");
|
||||
question.setContentText("Are you sure you want to delete this product-supplier?");
|
||||
Optional<ButtonType> result = question.showAndWait(); //show alert and wait for response
|
||||
|
||||
//if confirmed,start deletion
|
||||
if (result.isPresent() && result.get() == ButtonType.OK) {
|
||||
int supId = selectedProductSupplier.getSupId();
|
||||
int prodId = selectedProductSupplier.getProdId();
|
||||
|
||||
//try deleting
|
||||
try{
|
||||
numRows = ProductSupplierDB.deleteProductSupplier(supId, prodId);
|
||||
}
|
||||
catch (SQLIntegrityConstraintViolationException e){
|
||||
Alert alert = new Alert(Alert.AlertType.ERROR);
|
||||
alert.setHeaderText("Database Operation Error");
|
||||
alert.setContentText("Delete failed\n" +
|
||||
"the selected product-supplier is being referred in another table");
|
||||
alert.showAndWait();
|
||||
return;
|
||||
}
|
||||
catch (SQLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
//prompt user of any errors
|
||||
if (numRows == 0){
|
||||
Alert alert = new Alert(Alert.AlertType.ERROR);
|
||||
alert.setHeaderText("Database Operation Error");
|
||||
alert.setContentText("Delete failed");
|
||||
alert.showAndWait();
|
||||
}
|
||||
else{
|
||||
//prompt user of delete conformation
|
||||
Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
|
||||
alert.setHeaderText("Database Operation Confirmed");
|
||||
alert.setContentText("Delete successful");
|
||||
alert.showAndWait();
|
||||
//refresh display and reset inputs
|
||||
displayProductSupplier();
|
||||
btnDelete.setDisable(true);
|
||||
btnEdit.setDisable(true);
|
||||
txtSearch.setText("");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@FXML
|
||||
void btnEditClicked(ActionEvent event) {
|
||||
//set selected item
|
||||
ProductSupplierDTO selectedProductSupplier = tvProductSuppliers.getSelectionModel().getSelectedItem();
|
||||
|
||||
if (selectedProductSupplier != null) {
|
||||
mode = "Edit";
|
||||
openDialog(selectedProductSupplier,mode);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Function to open the new Dialog for edit or adding
|
||||
* depending on the mode given
|
||||
* @param productSupplier the productSupplier entity for editing, null if adding
|
||||
* @param mode the mode the dialog should be in
|
||||
*/
|
||||
private void openDialog(ProductSupplierDTO productSupplier, String mode){
|
||||
//Get new view
|
||||
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/org/example/petshopdesktop/dialogviews/product-supplier-dialog-view.fxml"));
|
||||
Scene scene = null;
|
||||
try{
|
||||
scene = new Scene(fxmlLoader.load());
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
ProductSupplierDialogController dialogController = fxmlLoader.getController(); //controller associated with this view
|
||||
dialogController.setMode(mode);
|
||||
if (productSupplier != null) {
|
||||
dialogController.setSelectedIds(productSupplier.getSupId(), productSupplier.getProdId());
|
||||
}
|
||||
|
||||
//Open the dialog depending on the mode
|
||||
if(mode.equals("Edit")){
|
||||
//Make it display suppliers details in dialog
|
||||
dialogController.displayProductSupplierDetails(productSupplier);
|
||||
}
|
||||
Stage dialogStage = new Stage();
|
||||
dialogStage.initModality(Modality.APPLICATION_MODAL); //make it modal
|
||||
if(mode.equals("Add")){
|
||||
dialogStage.setTitle("Add Product-Supplier");
|
||||
}
|
||||
else {
|
||||
dialogStage.setTitle("Edit Product-Supplier");
|
||||
}
|
||||
dialogStage.setScene(scene);
|
||||
dialogStage.showAndWait();
|
||||
|
||||
//When dialog closes update table view and disable edit and delete buttons, and reset search bar
|
||||
displayProductSupplier();
|
||||
btnDelete.setDisable(true);
|
||||
btnEdit.setDisable(true);
|
||||
txtSearch.setText("");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -99,7 +99,7 @@ public class SupplierController {
|
||||
try{
|
||||
data = SupplierDB.getSuppliers();
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e);
|
||||
System.out.println("Error while fetching table data: " + e.getMessage());
|
||||
}
|
||||
|
||||
tvSuppliers.setItems(data);
|
||||
@@ -121,7 +121,7 @@ public class SupplierController {
|
||||
tvSuppliers.setItems(data);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
System.out.println("Error while fetching table data: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -79,6 +79,11 @@ public class ProductDialogController {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the inputs, then add or update the database depending
|
||||
* on the mode
|
||||
* @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
|
||||
@@ -164,7 +169,7 @@ public class ProductDialogController {
|
||||
|
||||
/**
|
||||
* Display the product data in text fields and combobox
|
||||
* @param product the supplier entity containing data to display
|
||||
* @param product the product entity containing data to display
|
||||
*/
|
||||
public void displayProductDetails(ProductDTO product){
|
||||
if (product!=null){
|
||||
@@ -176,7 +181,7 @@ public class ProductDialogController {
|
||||
//get the right combobox selection
|
||||
for (Category category : cbProdCategory.getItems()) {
|
||||
if(category.getCategoryId() == product.getCategoryId()){
|
||||
cbProdCategory.setValue(category);
|
||||
cbProdCategory.getSelectionModel().select(category);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,245 @@
|
||||
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.*;
|
||||
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 java.sql.SQLException;
|
||||
import java.sql.SQLIntegrityConstraintViolationException;
|
||||
|
||||
public class ProductSupplierDialogController {
|
||||
|
||||
@FXML
|
||||
private Button btnCancel;
|
||||
|
||||
@FXML
|
||||
private Button btnSave;
|
||||
|
||||
@FXML
|
||||
private ComboBox<Product> cbProduct;
|
||||
|
||||
@FXML
|
||||
private ComboBox<Supplier> cbSupplier;
|
||||
|
||||
@FXML
|
||||
private Label lblMode;
|
||||
|
||||
@FXML
|
||||
private Label lblProductSupplierId;
|
||||
|
||||
@FXML
|
||||
private TextField txtCost;
|
||||
|
||||
private String mode = null;
|
||||
private int selectedSupId = -1;
|
||||
private int selectedProdId = -1;
|
||||
|
||||
/**
|
||||
* add event listeners to buttons and set up combobox
|
||||
*/
|
||||
@FXML
|
||||
void initialize() { //Set up mouse handlers for buttons
|
||||
btnSave.setOnMouseClicked(new EventHandler<MouseEvent>() {
|
||||
@Override
|
||||
public void handle(MouseEvent mouseEvent) {
|
||||
buttonSaveClicked(mouseEvent);
|
||||
}
|
||||
});
|
||||
|
||||
btnCancel.setOnMouseClicked(new EventHandler<MouseEvent>() {
|
||||
@Override
|
||||
public void handle(MouseEvent mouseEvent) {
|
||||
closeStage(mouseEvent);
|
||||
}
|
||||
});
|
||||
|
||||
//Set up combobox for selecting product and supplier
|
||||
try{
|
||||
ObservableList<Supplier> suppliers = FXCollections.observableArrayList(); //empty list
|
||||
ObservableList<Product> products = FXCollections.observableArrayList(); //empty list
|
||||
|
||||
//get suppliers and products from DB
|
||||
suppliers = SupplierDB.getSuppliers();
|
||||
products = ProductDB.getProducts();
|
||||
|
||||
//Populate combobox
|
||||
cbSupplier.setItems(suppliers);
|
||||
cbProduct.setItems(products);
|
||||
}
|
||||
catch(SQLException e){
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the inputs, then add or update the database depending
|
||||
* on the mode
|
||||
* @param mouseEvent click event for save button
|
||||
*/
|
||||
private void buttonSaveClicked(MouseEvent mouseEvent) {
|
||||
int numRows = 0;
|
||||
String errorMsg = ""; //error message for validation
|
||||
|
||||
//Check Validation (input required)
|
||||
errorMsg += Validator.isPresent(txtCost.getText(), "Cost");
|
||||
if (cbProduct.getSelectionModel().getSelectedItem() == null) {
|
||||
errorMsg += "Product is required \n";
|
||||
}
|
||||
if (cbSupplier.getSelectionModel().getSelectedItem() == null) {
|
||||
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){
|
||||
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){
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
else { //edit
|
||||
try{
|
||||
numRows = ProductSupplierDB.updateProductSupplier(selectedSupId, selectedProdId, productSupplier);
|
||||
}
|
||||
catch(SQLIntegrityConstraintViolationException e){
|
||||
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){
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
//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();
|
||||
closeStage(mouseEvent);
|
||||
}
|
||||
else if (numRows > 0){
|
||||
//tell the user operation was successful
|
||||
Alert alert = new Alert(Alert.AlertType.CONFIRMATION);
|
||||
alert.setHeaderText("Database Operation Confirmed");
|
||||
alert.setContentText(mode + " succeeded");
|
||||
alert.showAndWait();
|
||||
closeStage(mouseEvent);
|
||||
}
|
||||
}
|
||||
else { //Display validation errors
|
||||
Alert alert = new Alert(Alert.AlertType.ERROR);
|
||||
alert.setHeaderText("Input Error");
|
||||
alert.setContentText(errorMsg);
|
||||
alert.showAndWait();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* collect the data for new/updated productSupplier
|
||||
* @return productSupplier entity 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the productsupplier data in text fields and combobox
|
||||
* @param productSupplier
|
||||
*/
|
||||
public void displayProductSupplierDetails(ProductSupplierDTO productSupplier){
|
||||
if(productSupplier != null){
|
||||
txtCost.setText(productSupplier.getCost() + "");
|
||||
}
|
||||
|
||||
//Get the right combobox selection (product)
|
||||
for (Product product : cbProduct.getItems()) {
|
||||
if(product.getProdId() == productSupplier.getProdId()){
|
||||
cbProduct.getSelectionModel().select(product);
|
||||
}
|
||||
}
|
||||
|
||||
//Get the right combobox selection (supplier)
|
||||
for (Supplier supplier : cbSupplier.getItems()) {
|
||||
if (supplier.getSupId() == productSupplier.getSupId()) {
|
||||
cbSupplier.getSelectionModel().select(supplier);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the window
|
||||
* @param mouseEvent mouse event to close
|
||||
*/
|
||||
private void closeStage(MouseEvent mouseEvent) {
|
||||
Node node = (Node) mouseEvent.getSource();
|
||||
Stage stage = (Stage) node.getScene().getWindow();
|
||||
stage.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the mode of the dialog
|
||||
* @param mode the mode for the dialog
|
||||
*/
|
||||
public void setMode(String mode) {
|
||||
this.mode = mode;
|
||||
lblMode.setText(mode + " Product");
|
||||
lblProductSupplierId.setVisible(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* set the current supplier and productId for (needed for update since compound primary key)
|
||||
* @param supId supplier id
|
||||
* @param prodId product id
|
||||
*/
|
||||
public void setSelectedIds(int supId, int prodId){
|
||||
this.selectedSupId = supId;
|
||||
this.selectedProdId = prodId;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -67,6 +67,11 @@ public class SupplierDialogController {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the inputs, then add or update the database depending
|
||||
* on the mode
|
||||
* @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
|
||||
|
||||
@@ -0,0 +1,197 @@
|
||||
package org.example.petshopdesktop.database;
|
||||
|
||||
import javafx.collections.FXCollections;
|
||||
import javafx.collections.ObservableList;
|
||||
import org.example.petshopdesktop.DTOs.ProductDTO;
|
||||
import org.example.petshopdesktop.DTOs.ProductSupplierDTO;
|
||||
import org.example.petshopdesktop.models.Product;
|
||||
import org.example.petshopdesktop.models.ProductSupplier;
|
||||
|
||||
import java.sql.*;
|
||||
|
||||
public class ProductSupplierDB {
|
||||
/**
|
||||
* gets all the productSupplier into an observable list
|
||||
* @return a list of all the productSupplierDTOs
|
||||
* @throws SQLException if failed to find productSupplier in the database
|
||||
*/
|
||||
public static ObservableList<ProductSupplierDTO> getProductSupplierDTO() throws SQLException{
|
||||
//Connect to the database
|
||||
ObservableList<ProductSupplierDTO> productSuppliers = FXCollections.observableArrayList();
|
||||
Connection conn = ConnectionDB.getConnection();
|
||||
|
||||
//Execute Query
|
||||
Statement stmt = conn.createStatement();
|
||||
String sql = "SELECT ps.supId, ps.prodId, s.supCompany, p.prodName, ps.cost " +
|
||||
"FROM productsupplier ps " +
|
||||
"LEFT JOIN product p " +
|
||||
"ON p.prodId = ps.prodId " +
|
||||
"LEFT JOIN supplier s " +
|
||||
"ON s.supId = ps.supId";
|
||||
ResultSet rs = stmt.executeQuery(sql);
|
||||
|
||||
//While there is still data add productSupplier to list
|
||||
while(rs.next()){
|
||||
ProductSupplierDTO productSupplier = new ProductSupplierDTO(
|
||||
rs.getInt(1),
|
||||
rs.getInt(2),
|
||||
rs.getString(3),
|
||||
rs.getString(4),
|
||||
rs.getDouble(5)
|
||||
);
|
||||
productSuppliers.add(productSupplier);
|
||||
}
|
||||
|
||||
//close connection and return products
|
||||
conn.close();
|
||||
return productSuppliers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a list of ProductSupplierDTOs that is filtered by a given string
|
||||
* @param filter the word to filter table
|
||||
* @return ObservableList of ProductSupplierDTOs with the filtered data
|
||||
* @throws SQLException if getting productSuppliers failed
|
||||
*/
|
||||
public static ObservableList<ProductSupplierDTO> getFilteredProductSupplierDTO (String filter) throws SQLException {
|
||||
//connect to the database
|
||||
ObservableList<ProductSupplierDTO> productSuppliers = FXCollections.observableArrayList();
|
||||
Connection conn = ConnectionDB.getConnection();
|
||||
|
||||
//Get SQL query for filter word
|
||||
String sql =
|
||||
"SELECT ps.supId, ps.prodId, s.supCompany, p.prodName, ps.cost " +
|
||||
"FROM product p " +
|
||||
"LEFT JOIN productsupplier ps " +
|
||||
"ON p.prodId = ps.prodId " +
|
||||
"LEFT JOIN supplier s " +
|
||||
"ON s.supId = ps.supId " +
|
||||
"WHERE " +
|
||||
"prodName LIKE ? OR " +
|
||||
"supCompany LIKE ? OR " +
|
||||
"cost LIKE ?";
|
||||
|
||||
//add % wildcard so query can use LIKE to filter data
|
||||
String filteredString = "%" + filter + "%";
|
||||
|
||||
PreparedStatement stmt = conn.prepareStatement(sql);
|
||||
stmt.setString(1, filteredString);
|
||||
stmt.setString(2, filteredString);
|
||||
stmt.setString(3, filteredString);
|
||||
|
||||
//execute query
|
||||
ResultSet rs = stmt.executeQuery();
|
||||
|
||||
//While there is still data add productSupplier to the list
|
||||
while(rs.next()){
|
||||
ProductSupplierDTO productSupplier = new ProductSupplierDTO(
|
||||
rs.getInt(1),
|
||||
rs.getInt(2),
|
||||
rs.getString(3),
|
||||
rs.getString(4),
|
||||
rs.getDouble(5)
|
||||
);
|
||||
productSuppliers.add(productSupplier);
|
||||
}
|
||||
|
||||
conn.close();
|
||||
return productSuppliers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a new productSupplier to the database
|
||||
* @param productSupplier productSupplier entity to be inserted
|
||||
* @return number of rows affected
|
||||
* @throws SQLException if insert failed
|
||||
*/
|
||||
public static int insertProductSupplier(ProductSupplier productSupplier) throws SQLException{
|
||||
int numRows = 0;
|
||||
|
||||
Connection conn = ConnectionDB.getConnection();
|
||||
String sql = "INSERT INTO productsupplier (prodId, supId, cost) " +
|
||||
"VALUES (?, ?, ?)";
|
||||
|
||||
//These are the values from productSupplier to put into query above
|
||||
PreparedStatement stmt = conn.prepareStatement(sql);
|
||||
stmt.setInt(1, productSupplier.getProdId());
|
||||
stmt.setInt(2, productSupplier.getSupId());
|
||||
stmt.setDouble(3, productSupplier.getCost());
|
||||
|
||||
//update number of rows affected, return and close connection
|
||||
numRows = stmt.executeUpdate();
|
||||
conn.close();
|
||||
|
||||
return numRows;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a productSupplier by deleting old productSupplier and inserting new one
|
||||
* @param oldProdId old product id (used to change primary compound key)
|
||||
* @param oldSupId old supplier id (used to change primary compound key)
|
||||
* @param productSupplier productSupplier entity with new info to update (including new primary compound key)
|
||||
* @return number of rows affected in database
|
||||
* @throws SQLException if update failed
|
||||
*/
|
||||
public static int updateProductSupplier(int oldSupId, int oldProdId, ProductSupplier productSupplier) throws SQLException{
|
||||
int numRows = 0;
|
||||
Connection conn = ConnectionDB.getConnection();
|
||||
|
||||
//Make transaction so update can be rolled back if insert failed
|
||||
conn.setAutoCommit(false);
|
||||
|
||||
try{
|
||||
//Delete old data first
|
||||
String sql = "DELETE FROM productsupplier WHERE supId = ? AND prodId = ?";
|
||||
PreparedStatement stmt = conn.prepareStatement(sql);
|
||||
stmt.setInt(1, oldSupId);
|
||||
stmt.setInt(2, oldProdId);
|
||||
numRows = stmt.executeUpdate();
|
||||
|
||||
//Then change the data by inserting a new relation with given keys (only if delete worked)
|
||||
if(numRows > 0){
|
||||
sql = "INSERT INTO productsupplier (prodId, supId, cost) " +
|
||||
"VALUES (?, ?, ?)";
|
||||
stmt = conn.prepareStatement(sql);
|
||||
stmt.setInt(1, productSupplier.getProdId());
|
||||
stmt.setInt(2, productSupplier.getSupId());
|
||||
stmt.setDouble(3, productSupplier.getCost());
|
||||
numRows = stmt.executeUpdate();
|
||||
}
|
||||
//Commit changes if both delete and insert worked
|
||||
conn.commit();
|
||||
}
|
||||
catch(SQLException e){
|
||||
//Rollback CRUD failed
|
||||
conn.rollback();
|
||||
throw e;
|
||||
}
|
||||
finally {
|
||||
//Set auto commit back to true before closing connection
|
||||
conn.setAutoCommit(true);
|
||||
conn.close();
|
||||
}
|
||||
return numRows;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a productSupplier from the database
|
||||
* @param prodId id of the product
|
||||
* @param supId id of the supplier
|
||||
* @return number of rows affected in the database
|
||||
* @throws SQLException if delete failed
|
||||
*/
|
||||
public static int deleteProductSupplier(int supId, int prodId) throws SQLException{
|
||||
int numRows = 0;
|
||||
Connection conn = ConnectionDB.getConnection();
|
||||
|
||||
String sql = "DELETE FROM productsupplier WHERE supId = ? AND prodId = ?";
|
||||
PreparedStatement stmt = conn.prepareStatement(sql);
|
||||
stmt.setInt(1, supId);
|
||||
stmt.setInt(2, prodId);
|
||||
|
||||
numRows = stmt.executeUpdate();
|
||||
conn.close();
|
||||
|
||||
return numRows;
|
||||
}
|
||||
}
|
||||
@@ -83,4 +83,9 @@ public class Product {
|
||||
public void setProdDesc(String prodDesc) {
|
||||
this.prodDesc.set(prodDesc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getProdName();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
package org.example.petshopdesktop.models;
|
||||
|
||||
import javafx.beans.property.SimpleDoubleProperty;
|
||||
import javafx.beans.property.SimpleIntegerProperty;
|
||||
|
||||
public class ProductSupplier {
|
||||
private SimpleIntegerProperty supId;
|
||||
private SimpleIntegerProperty prodId;
|
||||
private SimpleDoubleProperty cost;
|
||||
|
||||
//constructor
|
||||
public ProductSupplier(int supId, int prodId, double cost) {
|
||||
this.supId = new SimpleIntegerProperty(supId);
|
||||
this.prodId = new SimpleIntegerProperty(prodId);
|
||||
this.cost = new SimpleDoubleProperty(cost);
|
||||
}
|
||||
|
||||
//getter and setters
|
||||
public int getSupId() {
|
||||
return supId.get();
|
||||
}
|
||||
|
||||
public SimpleIntegerProperty supIdProperty() {
|
||||
return supId;
|
||||
}
|
||||
|
||||
public void setSupId(int supId) {
|
||||
this.supId.set(supId);
|
||||
}
|
||||
|
||||
public int getProdId() {
|
||||
return prodId.get();
|
||||
}
|
||||
|
||||
public SimpleIntegerProperty prodIdProperty() {
|
||||
return prodId;
|
||||
}
|
||||
|
||||
public void setProdId(int prodId) {
|
||||
this.prodId.set(prodId);
|
||||
}
|
||||
|
||||
public double getCost() {
|
||||
return cost.get();
|
||||
}
|
||||
|
||||
public SimpleDoubleProperty costProperty() {
|
||||
return cost;
|
||||
}
|
||||
|
||||
public void setCost(double cost) {
|
||||
this.cost.set(cost);
|
||||
}
|
||||
}
|
||||
@@ -106,4 +106,9 @@ public class Supplier {
|
||||
public String getSupFullName() {
|
||||
return getSupContactFirstName() + " " + getSupContactLastName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getSupCompany();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,136 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<?import javafx.geometry.Insets?>
|
||||
<?import javafx.scene.control.Button?>
|
||||
<?import javafx.scene.control.ComboBox?>
|
||||
<?import javafx.scene.control.Label?>
|
||||
<?import javafx.scene.control.TextField?>
|
||||
<?import javafx.scene.layout.ColumnConstraints?>
|
||||
<?import javafx.scene.layout.GridPane?>
|
||||
<?import javafx.scene.layout.HBox?>
|
||||
<?import javafx.scene.layout.Region?>
|
||||
<?import javafx.scene.layout.RowConstraints?>
|
||||
<?import javafx.scene.layout.VBox?>
|
||||
<?import javafx.scene.text.Font?>
|
||||
|
||||
<VBox minHeight="-Infinity" minWidth="-Infinity" prefHeight="523.0" prefWidth="790.0" spacing="20.0" style="-fx-font-size: 14px;" xmlns="http://javafx.com/javafx/25" xmlns:fx="http://javafx.com/fxml/1" fx:controller="org.example.petshopdesktop.controllers.dialogcontrollers.ProductSupplierDialogController">
|
||||
<children>
|
||||
<HBox alignment="CENTER_LEFT" prefHeight="79.0" prefWidth="727.0" spacing="20.0" style="-fx-background-color: #2C3E50; -fx-background-radius: 14;">
|
||||
<children>
|
||||
<VBox alignment="CENTER_LEFT" prefHeight="93.0" prefWidth="358.0">
|
||||
<children>
|
||||
<Label fx:id="lblMode" prefHeight="42.0" prefWidth="351.0" text="Mode Product-Supplier" textFill="WHITE">
|
||||
<font>
|
||||
<Font name="Comic Sans MS Bold" size="30.0" />
|
||||
</font>
|
||||
</Label>
|
||||
<Label fx:id="lblProductSupplierId" text="ID: 1" textFill="#ffe66d">
|
||||
<font>
|
||||
<Font size="14.0" />
|
||||
</font>
|
||||
<VBox.margin>
|
||||
<Insets top="10.0" />
|
||||
</VBox.margin>
|
||||
</Label>
|
||||
</children>
|
||||
<padding>
|
||||
<Insets bottom="10.0" left="10.0" right="10.0" top="10.0" />
|
||||
</padding>
|
||||
<HBox.margin>
|
||||
<Insets />
|
||||
</HBox.margin>
|
||||
</VBox>
|
||||
<Region prefHeight="93.0" prefWidth="98.0" HBox.hgrow="ALWAYS" />
|
||||
<Button fx:id="btnCancel" layoutX="391.0" layoutY="38.0" mnemonicParsing="false" style="-fx-background-color: #E74c3c; -fx-cursor: hand; -fx-background-radius: 8;" text="Cancel" textFill="WHITE">
|
||||
<font>
|
||||
<Font name="System Bold" size="14.0" />
|
||||
</font>
|
||||
<padding>
|
||||
<Insets bottom="12.0" left="24.0" right="24.0" top="12.0" />
|
||||
</padding>
|
||||
</Button>
|
||||
<Button fx:id="btnSave" layoutX="520.0" layoutY="38.0" mnemonicParsing="false" style="-fx-background-color: #3fe06a; -fx-cursor: hand; -fx-background-radius: 8;" text="Save" textFill="WHITE">
|
||||
<font>
|
||||
<Font name="System Bold" size="14.0" />
|
||||
</font>
|
||||
<padding>
|
||||
<Insets bottom="12.0" left="24.0" right="24.0" top="12.0" />
|
||||
</padding>
|
||||
</Button>
|
||||
</children>
|
||||
<padding>
|
||||
<Insets left="15.0" right="15.0" />
|
||||
</padding>
|
||||
</HBox>
|
||||
<VBox prefHeight="370.0" prefWidth="750.0" style="-fx-background-color: white; -fx-background-radius: 14; -fx-border-width: 2; -fx-border-color: #5580b5; -fx-border-radius: 14;">
|
||||
<children>
|
||||
<GridPane hgap="25.0" VBox.vgrow="ALWAYS">
|
||||
<columnConstraints>
|
||||
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
|
||||
<ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
|
||||
</columnConstraints>
|
||||
<rowConstraints>
|
||||
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
||||
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
||||
<RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
|
||||
</rowConstraints>
|
||||
<children>
|
||||
<VBox prefHeight="200.0" prefWidth="100.0" spacing="8.0">
|
||||
<children>
|
||||
<Label text="Product:" textFill="#2c3e50">
|
||||
<font>
|
||||
<Font name="System Bold" size="16.0" />
|
||||
</font>
|
||||
</Label>
|
||||
<ComboBox fx:id="cbProduct" prefHeight="29.0" prefWidth="336.0" promptText="Select Category" style="-fx-border-color: #E8EBED; -fx-border-width: 2; -fx-border-radius: 10; -fx-background-radius: 10; -fx-background-color: white;">
|
||||
<padding>
|
||||
<Insets bottom="3.0" left="10.0" right="10.0" top="3.0" />
|
||||
</padding>
|
||||
</ComboBox>
|
||||
</children>
|
||||
</VBox>
|
||||
<VBox prefHeight="200.0" prefWidth="100.0" spacing="8.0" GridPane.columnIndex="1">
|
||||
<children>
|
||||
<Label text="Supplier:" textFill="#2c3e50">
|
||||
<font>
|
||||
<Font name="System Bold" size="16.0" />
|
||||
</font>
|
||||
</Label>
|
||||
<ComboBox fx:id="cbSupplier" prefHeight="29.0" prefWidth="336.0" promptText="Select Category" style="-fx-border-color: #E8EBED; -fx-border-width: 2; -fx-border-radius: 10; -fx-background-radius: 10; -fx-background-color: white;">
|
||||
<padding>
|
||||
<Insets bottom="3.0" left="10.0" right="10.0" top="3.0" />
|
||||
</padding>
|
||||
</ComboBox>
|
||||
</children>
|
||||
</VBox>
|
||||
<VBox prefHeight="200.0" prefWidth="100.0" spacing="8.0" GridPane.rowIndex="1">
|
||||
<children>
|
||||
<Label text="Cost" textFill="#2c3e50">
|
||||
<font>
|
||||
<Font name="System Bold" size="16.0" />
|
||||
</font>
|
||||
</Label>
|
||||
<TextField fx:id="txtCost" style="-fx-border-color: #E8EBED; -fx-border-width: 2; -fx-border-radius: 10; -fx-background-radius: 10;">
|
||||
<padding>
|
||||
<Insets bottom="7.0" left="10.0" right="10.0" top="7.0" />
|
||||
</padding>
|
||||
</TextField>
|
||||
</children>
|
||||
</VBox>
|
||||
<VBox prefHeight="200.0" prefWidth="100.0" spacing="8.0" GridPane.columnIndex="1" GridPane.rowIndex="1" />
|
||||
<VBox prefHeight="200.0" prefWidth="100.0" spacing="8.0" GridPane.rowIndex="2" />
|
||||
</children>
|
||||
<VBox.margin>
|
||||
<Insets bottom="15.0" left="15.0" right="15.0" top="15.0" />
|
||||
</VBox.margin>
|
||||
</GridPane>
|
||||
</children>
|
||||
<padding>
|
||||
<Insets bottom="15.0" left="15.0" right="15.0" top="15.0" />
|
||||
</padding>
|
||||
</VBox>
|
||||
</children>
|
||||
<padding>
|
||||
<Insets bottom="20.0" left="20.0" right="20.0" top="20.0" />
|
||||
</padding>
|
||||
</VBox>
|
||||
Reference in New Issue
Block a user