Merge pull request #12 from RecentRunner/CRUDProducts
Added CRUD to Products and added Validation to dialog
This commit is contained in:
215
Petstoredata.sql
215
Petstoredata.sql
@@ -7,24 +7,24 @@ USE Petstoredb;
|
|||||||
CREATE TABLE storeLocation (
|
CREATE TABLE storeLocation (
|
||||||
storeId INT AUTO_INCREMENT PRIMARY KEY,
|
storeId INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
storeName VARCHAR(100) NOT NULL,
|
storeName VARCHAR(100) NOT NULL,
|
||||||
address VARCHAR(255),
|
address VARCHAR(255) NOT NULL,
|
||||||
phone VARCHAR(20),
|
phone VARCHAR(20) NOT NULL,
|
||||||
email VARCHAR(100)
|
email VARCHAR(100) NOT NULL
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE employee (
|
CREATE TABLE employee (
|
||||||
employeeId INT AUTO_INCREMENT PRIMARY KEY,
|
employeeId INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
firstName VARCHAR(50) NOT NULL,
|
firstName VARCHAR(50) NOT NULL,
|
||||||
lastName VARCHAR(50) NOT NULL,
|
lastName VARCHAR(50) NOT NULL,
|
||||||
email VARCHAR(100),
|
email VARCHAR(100) NOT NULL,
|
||||||
phone VARCHAR(20),
|
phone VARCHAR(20) NOT NULL,
|
||||||
role VARCHAR(50),
|
role VARCHAR(50) NOT NULL,
|
||||||
isActive BOOLEAN DEFAULT TRUE
|
isActive BOOLEAN DEFAULT TRUE NOT NULL
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE employeeStore (
|
CREATE TABLE employeeStore (
|
||||||
employeeId INT,
|
employeeId INT NOT NULL,
|
||||||
storeId INT,
|
storeId INT NOT NULL,
|
||||||
PRIMARY KEY (employeeId, storeId),
|
PRIMARY KEY (employeeId, storeId),
|
||||||
FOREIGN KEY (employeeId) REFERENCES employee(employeeId),
|
FOREIGN KEY (employeeId) REFERENCES employee(employeeId),
|
||||||
FOREIGN KEY (storeId) REFERENCES storeLocation(storeId)
|
FOREIGN KEY (storeId) REFERENCES storeLocation(storeId)
|
||||||
@@ -34,26 +34,26 @@ CREATE TABLE customer (
|
|||||||
customerId INT AUTO_INCREMENT PRIMARY KEY,
|
customerId INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
firstName VARCHAR(50) NOT NULL,
|
firstName VARCHAR(50) NOT NULL,
|
||||||
lastName VARCHAR(50) NOT NULL,
|
lastName VARCHAR(50) NOT NULL,
|
||||||
email VARCHAR(100),
|
email VARCHAR(100) NOT NULL,
|
||||||
phone VARCHAR(20)
|
phone VARCHAR(20) NOT NULL
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE pet (
|
CREATE TABLE pet (
|
||||||
petId INT AUTO_INCREMENT PRIMARY KEY,
|
petId INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
petName VARCHAR(50),
|
petName VARCHAR(50) NOT NULL,
|
||||||
petSpecies VARCHAR(50),
|
petSpecies VARCHAR(50) NOT NULL,
|
||||||
petBreed VARCHAR(50),
|
petBreed VARCHAR(50) NOT NULL,
|
||||||
petAge INT,
|
petAge INT NOT NULL,
|
||||||
petStatus VARCHAR(20),
|
petStatus VARCHAR(20) NOT NULL,
|
||||||
petPrice DECIMAL(10, 2)
|
petPrice DECIMAL(10, 2) NOT NULL
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE adoption (
|
CREATE TABLE adoption (
|
||||||
adoptionId INT AUTO_INCREMENT PRIMARY KEY,
|
adoptionId INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
petId INT,
|
petId INT NOT NULL,
|
||||||
customerId INT,
|
customerId INT NOT NULL,
|
||||||
adoptionDate DATE,
|
adoptionDate DATE NOT NULL,
|
||||||
adoptionStatus VARCHAR(20),
|
adoptionStatus VARCHAR(20) NOT NULL,
|
||||||
FOREIGN KEY (petId) REFERENCES pet(petId),
|
FOREIGN KEY (petId) REFERENCES pet(petId),
|
||||||
FOREIGN KEY (customerId) REFERENCES customer(customerId)
|
FOREIGN KEY (customerId) REFERENCES customer(customerId)
|
||||||
);
|
);
|
||||||
@@ -61,31 +61,30 @@ CREATE TABLE adoption (
|
|||||||
CREATE TABLE supplier (
|
CREATE TABLE supplier (
|
||||||
supId INT AUTO_INCREMENT PRIMARY KEY,
|
supId INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
supCompany VARCHAR(100) NOT NULL,
|
supCompany VARCHAR(100) NOT NULL,
|
||||||
supContactFirstName VARCHAR(50),
|
supContactFirstName VARCHAR(50) NOT NULL,
|
||||||
supContactLastName VARCHAR(50),
|
supContactLastName VARCHAR(50) NOT NULL,
|
||||||
supEmail VARCHAR(100),
|
supEmail VARCHAR(100) NOT NULL,
|
||||||
supPhone VARCHAR(20)
|
supPhone VARCHAR(20) NOT NULL
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE category (
|
CREATE TABLE category (
|
||||||
categoryId INT AUTO_INCREMENT PRIMARY KEY,
|
categoryId INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
categoryName VARCHAR(100) NOT NULL,
|
categoryName VARCHAR(100) NOT NULL,
|
||||||
categoryType VARCHAR(50)
|
categoryType VARCHAR(50) NOT NULL
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE product (
|
CREATE TABLE product (
|
||||||
prodId INT AUTO_INCREMENT PRIMARY KEY,
|
prodId INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
prodName VARCHAR(100) NOT NULL,
|
prodName VARCHAR(100) NOT NULL,
|
||||||
prodSku VARCHAR(50) UNIQUE,
|
prodPrice DECIMAL(10, 2) NOT NULL,
|
||||||
prodPrice DECIMAL(10, 2),
|
categoryId INT NOT NULL,
|
||||||
categoryId INT,
|
|
||||||
prodDesc TEXT,
|
prodDesc TEXT,
|
||||||
FOREIGN KEY (categoryId) REFERENCES category(categoryId)
|
FOREIGN KEY (categoryId) REFERENCES category(categoryId)
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE productSupplier (
|
CREATE TABLE productSupplier (
|
||||||
supId INT,
|
supId INT NOT NULL,
|
||||||
prodId INT,
|
prodId INT NOT NULL,
|
||||||
PRIMARY KEY (supId, prodId),
|
PRIMARY KEY (supId, prodId),
|
||||||
FOREIGN KEY (supId) REFERENCES supplier(supId),
|
FOREIGN KEY (supId) REFERENCES supplier(supId),
|
||||||
FOREIGN KEY (prodId) REFERENCES product(prodId)
|
FOREIGN KEY (prodId) REFERENCES product(prodId)
|
||||||
@@ -93,8 +92,8 @@ CREATE TABLE productSupplier (
|
|||||||
|
|
||||||
CREATE TABLE inventory (
|
CREATE TABLE inventory (
|
||||||
inventoryId INT AUTO_INCREMENT PRIMARY KEY,
|
inventoryId INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
prodId INT,
|
prodId INT NOT NULL,
|
||||||
quantity INT DEFAULT 0,
|
quantity INT DEFAULT 0 NOT NULL,
|
||||||
FOREIGN KEY (prodId) REFERENCES product(prodId)
|
FOREIGN KEY (prodId) REFERENCES product(prodId)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -102,24 +101,24 @@ CREATE TABLE service (
|
|||||||
serviceId INT AUTO_INCREMENT PRIMARY KEY,
|
serviceId INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
serviceName VARCHAR(100) NOT NULL,
|
serviceName VARCHAR(100) NOT NULL,
|
||||||
serviceDesc TEXT,
|
serviceDesc TEXT,
|
||||||
serviceDuration INT,
|
serviceDuration INT NOT NULL,
|
||||||
servicePrice DECIMAL(10, 2)
|
servicePrice DECIMAL(10, 2) NOT NULL
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE appointment (
|
CREATE TABLE appointment (
|
||||||
appointmentId INT AUTO_INCREMENT PRIMARY KEY,
|
appointmentId INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
serviceId INT,
|
serviceId INT NOT NULL,
|
||||||
customerId INT,
|
customerId INT NOT NULL,
|
||||||
appointmentDate DATE,
|
appointmentDate DATE NOT NULL,
|
||||||
appointmentTime TIME,
|
appointmentTime TIME NOT NULL,
|
||||||
appointmentStatus VARCHAR(20),
|
appointmentStatus VARCHAR(20) NOT NULL,
|
||||||
FOREIGN KEY (serviceId) REFERENCES service(serviceId),
|
FOREIGN KEY (serviceId) REFERENCES service(serviceId),
|
||||||
FOREIGN KEY (customerId) REFERENCES customer(customerId)
|
FOREIGN KEY (customerId) REFERENCES customer(customerId)
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE appointmentPet (
|
CREATE TABLE appointmentPet (
|
||||||
appointmentId INT,
|
appointmentId INT NOT NULL,
|
||||||
petId INT,
|
petId INT NOT NULL,
|
||||||
PRIMARY KEY (appointmentId, petId),
|
PRIMARY KEY (appointmentId, petId),
|
||||||
FOREIGN KEY (appointmentId) REFERENCES appointment(appointmentId),
|
FOREIGN KEY (appointmentId) REFERENCES appointment(appointmentId),
|
||||||
FOREIGN KEY (petId) REFERENCES pet(petId)
|
FOREIGN KEY (petId) REFERENCES pet(petId)
|
||||||
@@ -127,30 +126,30 @@ CREATE TABLE appointmentPet (
|
|||||||
|
|
||||||
CREATE TABLE sale (
|
CREATE TABLE sale (
|
||||||
saleId INT AUTO_INCREMENT PRIMARY KEY,
|
saleId INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
saleDate DATETIME,
|
saleDate DATETIME NOT NULL,
|
||||||
totalAmount DECIMAL(10, 2),
|
totalAmount DECIMAL(10, 2) NOT NULL,
|
||||||
paymentMethod VARCHAR(50),
|
paymentMethod VARCHAR(50) NOT NULL,
|
||||||
employeeId INT,
|
employeeId INT NOT NULL,
|
||||||
storeId INT,
|
storeId INT NOT NULL,
|
||||||
FOREIGN KEY (employeeId) REFERENCES employee(employeeId),
|
FOREIGN KEY (employeeId) REFERENCES employee(employeeId),
|
||||||
FOREIGN KEY (storeId) REFERENCES storeLocation(storeId)
|
FOREIGN KEY (storeId) REFERENCES storeLocation(storeId)
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE saleItem (
|
CREATE TABLE saleItem (
|
||||||
saleItemId INT AUTO_INCREMENT PRIMARY KEY,
|
saleItemId INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
saleId INT,
|
saleId INT NOT NULL,
|
||||||
prodId INT,
|
prodId INT NOT NULL,
|
||||||
quantity INT,
|
quantity INT NOT NULL,
|
||||||
unitPrice DECIMAL(10, 2),
|
unitPrice DECIMAL(10, 2) NOT NULL,
|
||||||
FOREIGN KEY (saleId) REFERENCES sale(saleId),
|
FOREIGN KEY (saleId) REFERENCES sale(saleId),
|
||||||
FOREIGN KEY (prodId) REFERENCES product(prodId)
|
FOREIGN KEY (prodId) REFERENCES product(prodId)
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE TABLE activityLog (
|
CREATE TABLE activityLog (
|
||||||
logId INT AUTO_INCREMENT PRIMARY KEY,
|
logId INT AUTO_INCREMENT PRIMARY KEY,
|
||||||
employeeId INT,
|
employeeId INT NOT NULL,
|
||||||
activity TEXT,
|
activity TEXT NOT NULL,
|
||||||
logTimestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
logTimestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
|
||||||
FOREIGN KEY (employeeId) REFERENCES employee(employeeId)
|
FOREIGN KEY (employeeId) REFERENCES employee(employeeId)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -159,78 +158,148 @@ CREATE TABLE activityLog (
|
|||||||
INSERT INTO storeLocation (storeName, address, phone, email)
|
INSERT INTO storeLocation (storeName, address, phone, email)
|
||||||
VALUES
|
VALUES
|
||||||
('Downtown Branch', '123 Main St', '123-456-7890', 'downtown@petshop.com'),
|
('Downtown Branch', '123 Main St', '123-456-7890', 'downtown@petshop.com'),
|
||||||
('North Branch', '456 North Ave', '987-654-3210', 'north@petshop.com');
|
('North Branch', '456 North Ave', '987-654-3210', 'north@petshop.com'),
|
||||||
|
('West Side Store', '789 West Blvd', '555-123-4567', 'westside@petshop.com'),
|
||||||
|
('East End Shop', '321 East Road', '555-987-6543', 'eastend@petshop.com'),
|
||||||
|
('South Mall Location', '654 South Plaza', '555-246-8135', 'southmall@petshop.com');
|
||||||
|
|
||||||
INSERT INTO employee (firstName, lastName, email, phone, role, isActive)
|
INSERT INTO employee (firstName, lastName, email, phone, role, isActive)
|
||||||
VALUES
|
VALUES
|
||||||
('John', 'Doe', 'john@petshop.com', '111-222-3333', 'Manager', TRUE),
|
('John', 'Doe', 'john@petshop.com', '111-222-3333', 'Manager', TRUE),
|
||||||
('Sara', 'Smith', 'sara@petshop.com', '444-555-6666', 'Staff', TRUE);
|
('Sara', 'Smith', 'sara@petshop.com', '444-555-6666', 'Staff', TRUE),
|
||||||
|
('Michael', 'Johnson', 'michael@petshop.com', '222-333-4444', 'Groomer', TRUE),
|
||||||
|
('Lisa', 'Williams', 'lisa@petshop.com', '333-444-5555', 'Staff', TRUE),
|
||||||
|
('David', 'Brown', 'david@petshop.com', '555-666-7777', 'Veterinarian', TRUE),
|
||||||
|
('Emma', 'Davis', 'emma@petshop.com', '666-777-8888', 'Manager', FALSE);
|
||||||
|
|
||||||
INSERT INTO employeeStore (employeeId, storeId)
|
INSERT INTO employeeStore (employeeId, storeId)
|
||||||
VALUES
|
VALUES
|
||||||
(1, 1),
|
(1, 1),
|
||||||
(2, 1),
|
(2, 1),
|
||||||
(2, 2);
|
(2, 2),
|
||||||
|
(3, 2),
|
||||||
|
(4, 3),
|
||||||
|
(5, 1),
|
||||||
|
(5, 4),
|
||||||
|
(6, 5);
|
||||||
|
|
||||||
INSERT INTO customer (firstName, lastName, email, phone)
|
INSERT INTO customer (firstName, lastName, email, phone)
|
||||||
VALUES
|
VALUES
|
||||||
('Alex', 'Brown', 'alex@gmail.com', '777-888-9999'),
|
('Alex', 'Brown', 'alex@gmail.com', '777-888-9999'),
|
||||||
('Emily', 'Clark', 'emily@gmail.com', '666-555-4444');
|
('Emily', 'Clark', 'emily@gmail.com', '666-555-4444'),
|
||||||
|
('James', 'Wilson', 'james@gmail.com', '888-999-0000'),
|
||||||
|
('Olivia', 'Martinez', 'olivia@gmail.com', '999-000-1111'),
|
||||||
|
('William', 'Anderson', 'william@gmail.com', '000-111-2222'),
|
||||||
|
('Sophia', 'Taylor', 'sophia@gmail.com', '111-222-3333');
|
||||||
|
|
||||||
INSERT INTO pet (petName, petSpecies, petBreed, petAge, petStatus, petPrice)
|
INSERT INTO pet (petName, petSpecies, petBreed, petAge, petStatus, petPrice)
|
||||||
VALUES
|
VALUES
|
||||||
('Buddy', 'Dog', 'Labrador', 2, 'Available', 500.00),
|
('Buddy', 'Dog', 'Labrador', 2, 'Available', 500.00),
|
||||||
('Milo', 'Cat', 'Persian', 1, 'Available', 300.00);
|
('Milo', 'Cat', 'Persian', 1, 'Available', 300.00),
|
||||||
|
('Charlie', 'Dog', 'Golden Retriever', 3, 'Available', 550.00),
|
||||||
|
('Luna', 'Cat', 'Siamese', 2, 'Adopted', 350.00),
|
||||||
|
('Max', 'Dog', 'Beagle', 1, 'Available', 450.00),
|
||||||
|
('Bella', 'Cat', 'Maine Coon', 4, 'Available', 400.00);
|
||||||
|
|
||||||
INSERT INTO adoption (petId, customerId, adoptionDate, adoptionStatus)
|
INSERT INTO adoption (petId, customerId, adoptionDate, adoptionStatus)
|
||||||
VALUES
|
VALUES
|
||||||
(1, 1, '2026-01-15', 'Completed');
|
(1, 1, '2026-01-15', 'Completed'),
|
||||||
|
(4, 3, '2026-01-20', 'Completed'),
|
||||||
|
(2, 2, '2026-01-25', 'Pending'),
|
||||||
|
(5, 4, '2026-02-01', 'Completed'),
|
||||||
|
(6, 5, '2026-02-02', 'Pending');
|
||||||
|
|
||||||
INSERT INTO supplier (supCompany, supContactFirstName, supContactLastName, supEmail, supPhone)
|
INSERT INTO supplier (supCompany, supContactFirstName, supContactLastName, supEmail, supPhone)
|
||||||
VALUES
|
VALUES
|
||||||
('PetFood Inc', 'Robert', 'King', 'contact@petfood.com', '888-111-2222');
|
('PetFood Inc', 'Robert', 'King', 'contact@petfood.com', '888-111-2222'),
|
||||||
|
('Toy World', 'Jennifer', 'Lee', 'sales@toyworld.com', '888-222-3333'),
|
||||||
|
('Pet Supplies Co', 'Kevin', 'White', 'info@petsupplies.com', '888-333-4444'),
|
||||||
|
('Animal Care Products', 'Nancy', 'Green', 'orders@animalcare.com', '888-444-5555'),
|
||||||
|
('Premium Pet Goods', 'Tom', 'Black', 'support@premiumpet.com', '888-555-6666');
|
||||||
|
|
||||||
INSERT INTO category (categoryName, categoryType)
|
INSERT INTO category (categoryName, categoryType)
|
||||||
VALUES
|
VALUES
|
||||||
('Dog Food', 'Product'),
|
('Dog Food', 'Product'),
|
||||||
('Cat Toys', 'Product');
|
('Cat Toys', 'Product'),
|
||||||
|
('Bird Supplies', 'Product'),
|
||||||
|
('Aquarium', 'Product'),
|
||||||
|
('Small Animals', 'Product');
|
||||||
|
|
||||||
INSERT INTO product (prodName, prodSku, prodPrice, categoryId, prodDesc)
|
INSERT INTO product (prodName, prodPrice, categoryId, prodDesc)
|
||||||
VALUES
|
VALUES
|
||||||
('Premium Dog Food', 'DF001', 50.00, 1, 'High quality dog food'),
|
('Premium Dog Food', 50.00, 1, 'High quality dog food'),
|
||||||
('Cat Toy Ball', 'CT001', 10.00, 2, 'Colorful toy for cats');
|
('Cat Toy Ball', 10.00, 2, 'Colorful toy for cats'),
|
||||||
|
('Bird Cage Large', 120.00, 3, 'Spacious bird cage'),
|
||||||
|
('Fish Tank 20 Gallon', 80.00, 4, 'Complete aquarium kit'),
|
||||||
|
('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)
|
||||||
VALUES
|
VALUES
|
||||||
(1, 1),
|
(1, 1),
|
||||||
(1, 2);
|
(1, 2),
|
||||||
|
(2, 2),
|
||||||
|
(3, 3),
|
||||||
|
(3, 4),
|
||||||
|
(4, 5),
|
||||||
|
(5, 6),
|
||||||
|
(1, 6);
|
||||||
|
|
||||||
INSERT INTO inventory (prodId, quantity)
|
INSERT INTO inventory (prodId, quantity)
|
||||||
VALUES
|
VALUES
|
||||||
(1, 100),
|
(1, 100),
|
||||||
(2, 200);
|
(2, 200),
|
||||||
|
(3, 50),
|
||||||
|
(4, 30),
|
||||||
|
(5, 150),
|
||||||
|
(6, 75);
|
||||||
|
|
||||||
INSERT INTO service (serviceName, serviceDesc, serviceDuration, servicePrice)
|
INSERT INTO service (serviceName, serviceDesc, serviceDuration, servicePrice)
|
||||||
VALUES
|
VALUES
|
||||||
('Pet Grooming', 'Full grooming service', 60, 40.00);
|
('Pet Grooming', 'Full grooming service', 60, 40.00),
|
||||||
|
('Nail Trimming', 'Quick nail trim', 15, 10.00),
|
||||||
|
('Bath and Brush', 'Bathing and brushing service', 45, 30.00),
|
||||||
|
('Veterinary Checkup', 'Complete health examination', 30, 75.00),
|
||||||
|
('Teeth Cleaning', 'Professional dental cleaning', 90, 100.00);
|
||||||
|
|
||||||
INSERT INTO appointment (serviceId, customerId, appointmentDate, appointmentTime, appointmentStatus)
|
INSERT INTO appointment (serviceId, customerId, appointmentDate, appointmentTime, appointmentStatus)
|
||||||
VALUES
|
VALUES
|
||||||
(1, 2, '2026-02-01', '10:30:00', 'Booked');
|
(1, 2, '2026-02-01', '10:30:00', 'Booked'),
|
||||||
|
(2, 1, '2026-02-03', '14:00:00', 'Booked'),
|
||||||
|
(3, 3, '2026-02-05', '09:00:00', 'Completed'),
|
||||||
|
(4, 4, '2026-02-07', '11:30:00', 'Booked'),
|
||||||
|
(5, 5, '2026-02-10', '15:00:00', 'Cancelled');
|
||||||
|
|
||||||
INSERT INTO appointmentPet (appointmentId, petId)
|
INSERT INTO appointmentPet (appointmentId, petId)
|
||||||
VALUES
|
VALUES
|
||||||
(1, 2);
|
(1, 2),
|
||||||
|
(2, 1),
|
||||||
|
(3, 3),
|
||||||
|
(4, 5),
|
||||||
|
(5, 6);
|
||||||
|
|
||||||
INSERT INTO sale (saleDate, totalAmount, paymentMethod, employeeId, storeId)
|
INSERT INTO sale (saleDate, totalAmount, paymentMethod, employeeId, storeId)
|
||||||
VALUES
|
VALUES
|
||||||
(NOW(), 60.00, 'Card', 2, 1);
|
(NOW(), 60.00, 'Card', 2, 1),
|
||||||
|
('2026-01-28 10:30:00', 50.00, 'Cash', 1, 1),
|
||||||
|
('2026-01-29 14:15:00', 120.00, 'Card', 4, 3),
|
||||||
|
('2026-01-30 16:45:00', 80.00, 'Card', 2, 2),
|
||||||
|
('2026-02-01 11:20:00', 150.00, 'Cash', 5, 4);
|
||||||
|
|
||||||
INSERT INTO saleItem (saleId, prodId, quantity, unitPrice)
|
INSERT INTO saleItem (saleId, prodId, quantity, unitPrice)
|
||||||
VALUES
|
VALUES
|
||||||
(1, 2, 2, 10.00);
|
(1, 2, 2, 10.00),
|
||||||
|
(2, 1, 1, 50.00),
|
||||||
|
(3, 3, 1, 120.00),
|
||||||
|
(4, 4, 1, 80.00),
|
||||||
|
(5, 6, 6, 25.00),
|
||||||
|
(2, 2, 3, 10.00);
|
||||||
|
|
||||||
INSERT INTO activityLog (employeeId, activity)
|
INSERT INTO activityLog (employeeId, activity)
|
||||||
VALUES
|
VALUES
|
||||||
(1, 'Created new sale'),
|
(1, 'Created new sale'),
|
||||||
(2, 'Booked appointment');
|
(2, 'Booked appointment'),
|
||||||
|
(3, 'Completed grooming service'),
|
||||||
|
(4, 'Processed inventory order'),
|
||||||
|
(5, 'Conducted health checkup'),
|
||||||
|
(1, 'Updated customer information');
|
||||||
@@ -11,17 +11,15 @@ import org.example.petshopdesktop.models.Product;
|
|||||||
public class ProductDTO {
|
public class ProductDTO {
|
||||||
private SimpleIntegerProperty prodId;
|
private SimpleIntegerProperty prodId;
|
||||||
private SimpleStringProperty prodName;
|
private SimpleStringProperty prodName;
|
||||||
private SimpleStringProperty prodSku;
|
|
||||||
private SimpleDoubleProperty prodPrice;
|
private SimpleDoubleProperty prodPrice;
|
||||||
private SimpleIntegerProperty categoryId; //used for edit and delete
|
private SimpleIntegerProperty categoryId; //used for edit and delete
|
||||||
private SimpleStringProperty categoryName;
|
private SimpleStringProperty categoryName;
|
||||||
private SimpleStringProperty prodDesc;
|
private SimpleStringProperty prodDesc;
|
||||||
|
|
||||||
//constructor
|
//constructor
|
||||||
public ProductDTO(int prodId, String prodName, String prodSku, double prodPrice, int categoryId, String categoryName, String prodDesc) {
|
public ProductDTO(int prodId, String prodName, double prodPrice, int categoryId, String categoryName, String prodDesc) {
|
||||||
this.prodId = new SimpleIntegerProperty(prodId);
|
this.prodId = new SimpleIntegerProperty(prodId);
|
||||||
this.prodName = new SimpleStringProperty(prodName);
|
this.prodName = new SimpleStringProperty(prodName);
|
||||||
this.prodSku = new SimpleStringProperty(prodSku);
|
|
||||||
this.prodPrice = new SimpleDoubleProperty(prodPrice);
|
this.prodPrice = new SimpleDoubleProperty(prodPrice);
|
||||||
this.categoryId = new SimpleIntegerProperty(categoryId);
|
this.categoryId = new SimpleIntegerProperty(categoryId);
|
||||||
this.categoryName = new SimpleStringProperty(categoryName);
|
this.categoryName = new SimpleStringProperty(categoryName);
|
||||||
@@ -53,18 +51,6 @@ public class ProductDTO {
|
|||||||
this.prodName.set(prodName);
|
this.prodName.set(prodName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getProdSku() {
|
|
||||||
return prodSku.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
public SimpleStringProperty prodSkuProperty() {
|
|
||||||
return prodSku;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setProdSku(String prodSku) {
|
|
||||||
this.prodSku.set(prodSku);
|
|
||||||
}
|
|
||||||
|
|
||||||
public double getProdPrice() {
|
public double getProdPrice() {
|
||||||
return prodPrice.get();
|
return prodPrice.get();
|
||||||
}
|
}
|
||||||
@@ -121,7 +107,6 @@ public class ProductDTO {
|
|||||||
Product product = new Product(
|
Product product = new Product(
|
||||||
getProdId(),
|
getProdId(),
|
||||||
getProdName(),
|
getProdName(),
|
||||||
getProdSku(),
|
|
||||||
getProdPrice(),
|
getProdPrice(),
|
||||||
getCategoryId(),
|
getCategoryId(),
|
||||||
getProdDesc()
|
getProdDesc()
|
||||||
|
|||||||
131
src/main/java/org/example/petshopdesktop/Validator.java
Normal file
131
src/main/java/org/example/petshopdesktop/Validator.java
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
package org.example.petshopdesktop;
|
||||||
|
|
||||||
|
public class Validator {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if string is not empty
|
||||||
|
* @param value string to check
|
||||||
|
* @param name name of the input
|
||||||
|
* @return error msg if string is not empty, otherwise empty
|
||||||
|
*/
|
||||||
|
public static String isPresent(String value, String name){
|
||||||
|
String msg =""; //OK so far
|
||||||
|
if(value.isEmpty() || name.isBlank()){
|
||||||
|
msg += name + " is required. \n";
|
||||||
|
}
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the input is a non-negative double
|
||||||
|
* @param value input of string
|
||||||
|
* @param name name of input
|
||||||
|
* @return error msg if input is not a number or negative, otherwise empty
|
||||||
|
*/
|
||||||
|
public static String isNonNegativeDouble(String value, String name){
|
||||||
|
String msg =""; //OK so far
|
||||||
|
double result;
|
||||||
|
try{
|
||||||
|
result = Double.parseDouble(value);
|
||||||
|
if (result < 0){
|
||||||
|
msg += name + " must be greater than or equal 0. \n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (NumberFormatException e){
|
||||||
|
msg += name + " must be a number.\n";
|
||||||
|
}
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the input is a double in 2 different range
|
||||||
|
* @param value input of string
|
||||||
|
* @param name name of inpt
|
||||||
|
* @param minValue min value of range
|
||||||
|
* @param maxValue max value of range
|
||||||
|
* @return error msg if input is out of range, otherwise empty
|
||||||
|
*/
|
||||||
|
public static String isDoubleInRange(String value, String name, double minValue, double maxValue){
|
||||||
|
String msg =""; //OK so far
|
||||||
|
double result;
|
||||||
|
try{
|
||||||
|
result = Double.parseDouble(value);
|
||||||
|
if (result < minValue || result > maxValue){
|
||||||
|
msg += name + " must be between " + minValue + " and " + maxValue + "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (NumberFormatException e){
|
||||||
|
msg += name + " must be a number.\n";
|
||||||
|
}
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the input is a non-negative integer
|
||||||
|
* @param value input of string
|
||||||
|
* @param name name of input
|
||||||
|
* @return error msg if input is not a number or negative, otherwise empty
|
||||||
|
*/
|
||||||
|
public static String isNonNegativeInteger(String value, String name){
|
||||||
|
String msg =""; //OK so far
|
||||||
|
int result;
|
||||||
|
try{
|
||||||
|
result = Integer.parseInt(value);
|
||||||
|
if (result < 0){
|
||||||
|
msg += name + " must be greater than or equal 0. \n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (NumberFormatException e){
|
||||||
|
msg += name + " must be a whole number.\n";
|
||||||
|
}
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* check if the string is a given amount of characters or fewer
|
||||||
|
* @param value input of string
|
||||||
|
* @param name name of input
|
||||||
|
* @return error msg if input is more than given characters length
|
||||||
|
*/
|
||||||
|
public static String isLessThanVarChars(String value, String name, int length){
|
||||||
|
String msg ="";
|
||||||
|
if (value.length() > length){
|
||||||
|
msg += name + " must be less than " + length + " characters. \n";
|
||||||
|
}
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the input is a valid email format
|
||||||
|
* @param value input of string
|
||||||
|
* @param name name of input
|
||||||
|
* @return error msg if input is not a valid email format, otherwise empty
|
||||||
|
*/
|
||||||
|
public static String isValidEmail(String value, String name){
|
||||||
|
String msg = ""; //OK so far
|
||||||
|
// Email regex
|
||||||
|
String regex = "^[A-Za-z0-9+_.-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,}$";
|
||||||
|
|
||||||
|
if (!value.matches(regex)){
|
||||||
|
msg += name + " is not in a valid format. \n";
|
||||||
|
}
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the input is a valid phone number in format XXX-XXX-XXXX
|
||||||
|
* @param value input of string
|
||||||
|
* @param name name of input
|
||||||
|
* @return error msg if input is not in valid phone format, otherwise empty
|
||||||
|
*/
|
||||||
|
public static String isValidPhoneNumber(String value, String name){
|
||||||
|
String msg = ""; //OK so far
|
||||||
|
// Phone regex
|
||||||
|
String regex = "^\\d{3}-\\d{3}-\\d{4}$";
|
||||||
|
|
||||||
|
if (!value.matches(regex)){
|
||||||
|
msg += name + " must be in format XXX-XXX-XXXX. \n";
|
||||||
|
}
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,16 +4,24 @@ import javafx.collections.FXCollections;
|
|||||||
import javafx.collections.ObservableList;
|
import javafx.collections.ObservableList;
|
||||||
import javafx.event.ActionEvent;
|
import javafx.event.ActionEvent;
|
||||||
import javafx.fxml.FXML;
|
import javafx.fxml.FXML;
|
||||||
import javafx.scene.control.Button;
|
import javafx.fxml.FXMLLoader;
|
||||||
import javafx.scene.control.TableColumn;
|
import javafx.scene.Scene;
|
||||||
import javafx.scene.control.TableView;
|
import javafx.scene.control.*;
|
||||||
import javafx.scene.control.TextField;
|
|
||||||
import javafx.scene.control.cell.PropertyValueFactory;
|
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.ProductDTO;
|
||||||
|
import org.example.petshopdesktop.controllers.dialogcontrollers.ProductDialogController;
|
||||||
|
import org.example.petshopdesktop.controllers.dialogcontrollers.SupplierDialogController;
|
||||||
import org.example.petshopdesktop.database.ProductDB;
|
import org.example.petshopdesktop.database.ProductDB;
|
||||||
|
import org.example.petshopdesktop.database.SupplierDB;
|
||||||
import org.example.petshopdesktop.models.Product;
|
import org.example.petshopdesktop.models.Product;
|
||||||
|
import org.example.petshopdesktop.models.Supplier;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.sql.SQLException;
|
import java.sql.SQLException;
|
||||||
|
import java.sql.SQLIntegrityConstraintViolationException;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The controller for any operations in the products view
|
* The controller for any operations in the products view
|
||||||
@@ -44,9 +52,6 @@ public class ProductController {
|
|||||||
@FXML
|
@FXML
|
||||||
private TableColumn<ProductDTO, Double> colProductPrice;
|
private TableColumn<ProductDTO, Double> colProductPrice;
|
||||||
|
|
||||||
@FXML
|
|
||||||
private TableColumn<ProductDTO, String> colProductSKU;
|
|
||||||
|
|
||||||
@FXML
|
@FXML
|
||||||
private TableView<ProductDTO> tvProducts;
|
private TableView<ProductDTO> tvProducts;
|
||||||
|
|
||||||
@@ -68,19 +73,31 @@ public class ProductController {
|
|||||||
//set up table columns
|
//set up table columns
|
||||||
colProductId.setCellValueFactory(new PropertyValueFactory<ProductDTO,Integer>("prodId"));
|
colProductId.setCellValueFactory(new PropertyValueFactory<ProductDTO,Integer>("prodId"));
|
||||||
colProductName.setCellValueFactory(new PropertyValueFactory<ProductDTO,String>("prodName"));
|
colProductName.setCellValueFactory(new PropertyValueFactory<ProductDTO,String>("prodName"));
|
||||||
colProductSKU.setCellValueFactory(new PropertyValueFactory<ProductDTO,String>("prodSku"));
|
|
||||||
colProductPrice.setCellValueFactory(new PropertyValueFactory<ProductDTO,Double>("prodPrice"));
|
colProductPrice.setCellValueFactory(new PropertyValueFactory<ProductDTO,Double>("prodPrice"));
|
||||||
colProductCategory.setCellValueFactory(new PropertyValueFactory<ProductDTO,String>("categoryName"));
|
colProductCategory.setCellValueFactory(new PropertyValueFactory<ProductDTO,String>("categoryName"));
|
||||||
colProductDesc.setCellValueFactory(new PropertyValueFactory<ProductDTO,String>("prodDesc"));
|
colProductDesc.setCellValueFactory(new PropertyValueFactory<ProductDTO,String>("prodDesc"));
|
||||||
|
|
||||||
displayProducts();
|
displayProduct();
|
||||||
|
|
||||||
|
//EventListener to Enable buttons when a row is selected
|
||||||
|
tvProducts.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) -> {
|
||||||
|
displayFilteredProduct(newValue);
|
||||||
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Display the productDTO to table view
|
* Display the productDTO to table view
|
||||||
*/
|
*/
|
||||||
private void displayProducts(){
|
private void displayProduct(){
|
||||||
//Erase old content
|
//Erase old content
|
||||||
data.clear();
|
data.clear();
|
||||||
|
|
||||||
@@ -95,20 +112,148 @@ public class ProductController {
|
|||||||
tvProducts.setItems(data);
|
tvProducts.setItems(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* open a new dialog for adding a product
|
||||||
|
* @param event
|
||||||
|
*/
|
||||||
@FXML
|
@FXML
|
||||||
void btnAddClicked(ActionEvent event) {
|
void btnAddClicked(ActionEvent event) {
|
||||||
|
mode = "Add";
|
||||||
|
openDialog(null,mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete a selected product when delete is clicked
|
||||||
|
* @param event click event for button
|
||||||
|
*/
|
||||||
@FXML
|
@FXML
|
||||||
void btnDeleteClicked(ActionEvent event) {
|
void btnDeleteClicked(ActionEvent event) {
|
||||||
|
int numRows = 0;
|
||||||
|
//set selected product
|
||||||
|
ProductDTO selectedProduct = tvProducts.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?");
|
||||||
|
Optional<ButtonType> result = question.showAndWait(); //show alert and wait for response
|
||||||
|
|
||||||
|
//if confirmed,start deletion
|
||||||
|
if (result.isPresent() && result.get() == ButtonType.OK) {
|
||||||
|
int prodId = selectedProduct.getProdId();
|
||||||
|
|
||||||
|
//try deleting
|
||||||
|
try{
|
||||||
|
numRows = ProductDB.deleteProduct(prodId);
|
||||||
|
}
|
||||||
|
catch (SQLIntegrityConstraintViolationException e){
|
||||||
|
Alert alert = new Alert(Alert.AlertType.ERROR);
|
||||||
|
alert.setHeaderText("Database Operation Error");
|
||||||
|
alert.setContentText("Delete failed\n" +
|
||||||
|
"the selected product 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
|
||||||
|
displayProduct();
|
||||||
|
btnDelete.setDisable(true);
|
||||||
|
btnEdit.setDisable(true);
|
||||||
|
txtSearch.setText("");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open a new dialog for editing a product
|
||||||
|
* @param event click event for button
|
||||||
|
*/
|
||||||
@FXML
|
@FXML
|
||||||
void btnEditClicked(ActionEvent event) {
|
void btnEditClicked(ActionEvent event) {
|
||||||
|
//set selected product
|
||||||
|
ProductDTO selectedProduct = tvProducts.getSelectionModel().getSelectedItem();
|
||||||
|
|
||||||
|
if (selectedProduct != null) {
|
||||||
|
mode = "Edit";
|
||||||
|
openDialog(selectedProduct, mode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filter the table given the string from the searchbar
|
||||||
|
* @param filter word to filter table
|
||||||
|
*/
|
||||||
|
private void displayFilteredProduct(String filter){
|
||||||
|
data.clear();
|
||||||
|
try{
|
||||||
|
if (txtSearch.getText() == null || txtSearch.getText().isEmpty()){
|
||||||
|
displayProduct(); //If search bar is empty just display everything
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
//Filter the using the keyword
|
||||||
|
data = ProductDB.getFilteredProductDTOs(filter);
|
||||||
|
tvProducts.setItems(data);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function to open the new Dialog for edit or adding
|
||||||
|
* depending on the mode given
|
||||||
|
* @param product the product entity for editing, null if adding
|
||||||
|
* @param mode the mode the dialog should be in
|
||||||
|
*/
|
||||||
|
private void openDialog(ProductDTO product, String mode){
|
||||||
|
//Get new view
|
||||||
|
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/org/example/petshopdesktop/dialogviews/product-dialog-view.fxml"));
|
||||||
|
Scene scene = null;
|
||||||
|
try{
|
||||||
|
scene = new Scene(fxmlLoader.load());
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
ProductDialogController dialogController = fxmlLoader.getController(); //controller associated with this view
|
||||||
|
dialogController.setMode(mode);
|
||||||
|
|
||||||
|
//Open the dialog depending on the mode
|
||||||
|
if(mode.equals("Edit")){
|
||||||
|
//Make it display suppliers details in dialog
|
||||||
|
dialogController.displayProductDetails(product);
|
||||||
|
}
|
||||||
|
Stage dialogStage = new Stage();
|
||||||
|
dialogStage.initModality(Modality.APPLICATION_MODAL); //make it modal
|
||||||
|
if(mode.equals("Add")){
|
||||||
|
dialogStage.setTitle("Add Product");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
dialogStage.setTitle("Edit Product");
|
||||||
|
}
|
||||||
|
dialogStage.setScene(scene);
|
||||||
|
dialogStage.showAndWait();
|
||||||
|
|
||||||
|
//When dialog closes update table view and disable edit and delete buttons, and reset search bar
|
||||||
|
displayProduct();
|
||||||
|
btnDelete.setDisable(true);
|
||||||
|
btnEdit.setDisable(true);
|
||||||
|
txtSearch.setText("");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ public class SupplierController {
|
|||||||
|
|
||||||
displaySupplier();
|
displaySupplier();
|
||||||
|
|
||||||
// Enable buttons when a row is selected
|
//EventListener to Enable buttons when a row is selected
|
||||||
tvSuppliers.getSelectionModel().selectedItemProperty().addListener(
|
tvSuppliers.getSelectionModel().selectedItemProperty().addListener(
|
||||||
(observable, oldValue, newValue) -> {
|
(observable, oldValue, newValue) -> {
|
||||||
btnEdit.setDisable(false);
|
btnEdit.setDisable(false);
|
||||||
@@ -82,6 +82,11 @@ public class SupplierController {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
//EventListener to search when text is changed on searchbar
|
||||||
|
txtSearch.textProperty().addListener((observable, oldValue, newValue) -> {
|
||||||
|
displayFilteredSupplier(newValue);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -100,10 +105,30 @@ public class SupplierController {
|
|||||||
tvSuppliers.setItems(data);
|
tvSuppliers.setItems(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filter the table given the string from the searchbar
|
||||||
|
* @param filter word to filter table
|
||||||
|
*/
|
||||||
|
private void displayFilteredSupplier(String filter){
|
||||||
|
data.clear();
|
||||||
|
try{
|
||||||
|
if (txtSearch.getText() == null || txtSearch.getText().isEmpty()){
|
||||||
|
displaySupplier(); //If search bar is empty just display everything
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
//Filter the using the keyword
|
||||||
|
data = SupplierDB.getFilteredSuppliers(filter);
|
||||||
|
tvSuppliers.setItems(data);
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* open a new dialog for adding a supplier
|
* open a new dialog for adding a supplier
|
||||||
* @param event
|
* @param event click event for button
|
||||||
*/
|
*/
|
||||||
@FXML
|
@FXML
|
||||||
void btnAddClicked(ActionEvent event) {
|
void btnAddClicked(ActionEvent event) {
|
||||||
@@ -112,8 +137,8 @@ public class SupplierController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Delete a selected supplier when delete is clicked
|
||||||
* @param event
|
* @param event click event for button
|
||||||
*/
|
*/
|
||||||
@FXML
|
@FXML
|
||||||
void btnDeleteClicked(ActionEvent event) {
|
void btnDeleteClicked(ActionEvent event) {
|
||||||
@@ -162,13 +187,16 @@ public class SupplierController {
|
|||||||
alert.showAndWait();
|
alert.showAndWait();
|
||||||
//refresh display
|
//refresh display
|
||||||
displaySupplier();
|
displaySupplier();
|
||||||
|
btnDelete.setDisable(true);
|
||||||
|
btnEdit.setDisable(true);
|
||||||
|
txtSearch.setText("");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Open a new dialog for editing a supplier
|
* Open a new dialog for editing a supplier
|
||||||
* @param event click event
|
* @param event click event for button
|
||||||
*/
|
*/
|
||||||
@FXML
|
@FXML
|
||||||
void btnEditClicked(ActionEvent event) {
|
void btnEditClicked(ActionEvent event) {
|
||||||
@@ -184,12 +212,12 @@ public class SupplierController {
|
|||||||
/**
|
/**
|
||||||
* Function to open the new Dialog for edit or adding
|
* Function to open the new Dialog for edit or adding
|
||||||
* depending on the mode given
|
* depending on the mode given
|
||||||
* @param supplier the supplier entity fo editing, null if adding
|
* @param supplier the supplier entity for editing, null if adding
|
||||||
* @param mode the mode the dialog should be in
|
* @param mode the mode the dialog should be in
|
||||||
*/
|
*/
|
||||||
private void openDialog(Supplier supplier, String mode){
|
private void openDialog(Supplier supplier, String mode){
|
||||||
//Get new view
|
//Get new view
|
||||||
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/org/example/petshopdesktop/dialogviews/supplier-dialog-view.fxml")); //CHECK
|
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("/org/example/petshopdesktop/dialogviews/supplier-dialog-view.fxml"));
|
||||||
Scene scene = null;
|
Scene scene = null;
|
||||||
try{
|
try{
|
||||||
scene = new Scene(fxmlLoader.load());
|
scene = new Scene(fxmlLoader.load());
|
||||||
@@ -215,10 +243,11 @@ public class SupplierController {
|
|||||||
dialogStage.setScene(scene);
|
dialogStage.setScene(scene);
|
||||||
dialogStage.showAndWait();
|
dialogStage.showAndWait();
|
||||||
|
|
||||||
//When dialog closes update table view and disable edit and delete buttons
|
//When dialog closes update table view and disable edit and delete buttons, and reset search bar
|
||||||
displaySupplier();
|
displaySupplier();
|
||||||
btnDelete.setDisable(true);
|
btnDelete.setDisable(true);
|
||||||
btnEdit.setDisable(true);
|
btnEdit.setDisable(true);
|
||||||
|
txtSearch.setText("");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,211 @@
|
|||||||
|
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.ProductDTO;
|
||||||
|
import org.example.petshopdesktop.Validator;
|
||||||
|
import org.example.petshopdesktop.database.CategoryDB;
|
||||||
|
import org.example.petshopdesktop.database.ProductDB;
|
||||||
|
import org.example.petshopdesktop.models.Category;
|
||||||
|
import org.example.petshopdesktop.models.Product;
|
||||||
|
import org.example.petshopdesktop.models.Supplier;
|
||||||
|
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
public class ProductDialogController {
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private Button btnCancel;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private Button btnSave;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private ComboBox<Category> cbProdCategory;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private Label lblMode;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private Label lblProdId;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private TextField txtProdDesc;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private TextField txtProdName;
|
||||||
|
|
||||||
|
@FXML
|
||||||
|
private TextField txtProdPrice;
|
||||||
|
|
||||||
|
private String mode = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add event listeners to buttons when dialog loads
|
||||||
|
*/
|
||||||
|
@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 category
|
||||||
|
try {
|
||||||
|
//set up combobox
|
||||||
|
ObservableList<Category> categories = FXCollections.observableArrayList(); //empty list
|
||||||
|
categories = CategoryDB.getCategories();
|
||||||
|
cbProdCategory.setItems(categories);
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void buttonSaveClicked(MouseEvent mouseEvent) {
|
||||||
|
int numRow = 0; //how many rows affected
|
||||||
|
String errorMsg = ""; //error message for validation
|
||||||
|
|
||||||
|
//Check Validation (input required)
|
||||||
|
errorMsg += Validator.isPresent(txtProdName.getText(), "Product Name");
|
||||||
|
errorMsg += Validator.isPresent(txtProdPrice.getText(), "Product Price");
|
||||||
|
if (cbProdCategory.getSelectionModel().getSelectedItem() == null) {
|
||||||
|
errorMsg += "Category is required \n";
|
||||||
|
}
|
||||||
|
|
||||||
|
//Check validation (length size)
|
||||||
|
errorMsg += Validator.isLessThanVarChars(txtProdName.getText(), "Product Name", 100);
|
||||||
|
errorMsg += Validator.isLessThanVarChars(txtProdDesc.getText(), "Description", 100);
|
||||||
|
errorMsg += Validator.isLessThanVarChars(txtProdPrice.getText(), "Product Price", 12);
|
||||||
|
|
||||||
|
//Check Validation (format)
|
||||||
|
errorMsg += Validator.isNonNegativeDouble(txtProdPrice.getText(), "Product Price");
|
||||||
|
|
||||||
|
if (errorMsg.isEmpty()) { //no validation errors detected
|
||||||
|
Product product = collectProduct(); //get product info
|
||||||
|
if (mode.equals("Add")){ //add mode
|
||||||
|
try{
|
||||||
|
numRow = ProductDB.insertProduct(product);
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else { //edit
|
||||||
|
try{
|
||||||
|
numRow = ProductDB.updateProduct(product.getProdId(),product);
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//if no rows were affected then there was an error (prompt user of error)
|
||||||
|
if (numRow == 0){
|
||||||
|
Alert alert = new Alert(Alert.AlertType.ERROR);
|
||||||
|
alert.setHeaderText("Database Operation Error");
|
||||||
|
alert.setContentText(mode + " failed");
|
||||||
|
alert.showAndWait();
|
||||||
|
closeStage(mouseEvent);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
//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 product info
|
||||||
|
* @return product info with the id or the new product
|
||||||
|
*/
|
||||||
|
private Product collectProduct(){
|
||||||
|
int prodId = 0;
|
||||||
|
Product product = null;
|
||||||
|
|
||||||
|
if(lblProdId.isVisible()){ //Edit mode
|
||||||
|
//get product id from lblId (split the string so we only get the int)
|
||||||
|
prodId = Integer.parseInt(lblProdId.getText().split(": ")[1]);
|
||||||
|
}
|
||||||
|
product = new Product(
|
||||||
|
prodId,
|
||||||
|
txtProdName.getText(),
|
||||||
|
Double.parseDouble(txtProdPrice.getText()),
|
||||||
|
cbProdCategory.getSelectionModel().getSelectedItem().getCategoryId(),
|
||||||
|
txtProdDesc.getText()
|
||||||
|
);
|
||||||
|
return product;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Display the product data in text fields and combobox
|
||||||
|
* @param product the supplier entity containing data to display
|
||||||
|
*/
|
||||||
|
public void displayProductDetails(ProductDTO product){
|
||||||
|
if (product!=null){
|
||||||
|
lblProdId.setText("ID: " + product.getProdId());
|
||||||
|
txtProdName.setText(product.getProdName());
|
||||||
|
txtProdDesc.setText(product.getProdDesc());
|
||||||
|
txtProdPrice.setText(product.getProdPrice() + "");
|
||||||
|
|
||||||
|
//get the right combobox selection
|
||||||
|
for (Category category : cbProdCategory.getItems()) {
|
||||||
|
if(category.getCategoryId() == product.getCategoryId()){
|
||||||
|
cbProdCategory.setValue(category);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 to for the dialog
|
||||||
|
*/
|
||||||
|
public void setMode(String mode) {
|
||||||
|
this.mode = mode;
|
||||||
|
lblMode.setText(mode + " Product");
|
||||||
|
if(mode.equals("Add")) {
|
||||||
|
lblProdId.setVisible(false);
|
||||||
|
}
|
||||||
|
else if(mode.equals("Edit")) {
|
||||||
|
lblProdId.setVisible(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -9,6 +9,7 @@ import javafx.scene.control.Label;
|
|||||||
import javafx.scene.control.TextField;
|
import javafx.scene.control.TextField;
|
||||||
import javafx.scene.input.MouseEvent;
|
import javafx.scene.input.MouseEvent;
|
||||||
import javafx.stage.Stage;
|
import javafx.stage.Stage;
|
||||||
|
import org.example.petshopdesktop.Validator;
|
||||||
import org.example.petshopdesktop.database.SupplierDB;
|
import org.example.petshopdesktop.database.SupplierDB;
|
||||||
import org.example.petshopdesktop.models.Supplier;
|
import org.example.petshopdesktop.models.Supplier;
|
||||||
|
|
||||||
@@ -45,6 +46,9 @@ public class SupplierDialogController {
|
|||||||
|
|
||||||
private String mode = null;
|
private String mode = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add event listeners to buttons when dialog loads
|
||||||
|
*/
|
||||||
@FXML
|
@FXML
|
||||||
void initialize() {
|
void initialize() {
|
||||||
//Set up mouse handlers for buttons
|
//Set up mouse handlers for buttons
|
||||||
@@ -67,7 +71,22 @@ public class SupplierDialogController {
|
|||||||
int numRow = 0; //how many rows affected
|
int numRow = 0; //how many rows affected
|
||||||
String errorMsg = ""; //error message for validation
|
String errorMsg = ""; //error message for validation
|
||||||
|
|
||||||
//TODO: Import validation class and validate text fields here
|
//Check validation (input required)
|
||||||
|
errorMsg += Validator.isPresent(txtCompanyName.getText(), "Company Name");
|
||||||
|
errorMsg += Validator.isPresent(txtContactFirstName.getText(), "Contact First Name");
|
||||||
|
errorMsg += Validator.isPresent(txtContactLastName.getText(), "Contact Last Name");
|
||||||
|
errorMsg += Validator.isPresent(txtEmail.getText(), "Email Address");
|
||||||
|
errorMsg += Validator.isPresent(txtPhone.getText(), "Phone Number");
|
||||||
|
|
||||||
|
//Check validation (Length size)
|
||||||
|
errorMsg += Validator.isLessThanVarChars(txtCompanyName.getText(),"Company Name", 100);
|
||||||
|
errorMsg += Validator.isLessThanVarChars(txtContactFirstName.getText(), "Contact First Name", 50);
|
||||||
|
errorMsg += Validator.isLessThanVarChars(txtContactLastName.getText(), "Contact Last Name", 50);
|
||||||
|
errorMsg += Validator.isLessThanVarChars(txtEmail.getText(), "Email Address", 100);
|
||||||
|
|
||||||
|
//Check validation (format)
|
||||||
|
errorMsg += Validator.isValidEmail(txtEmail.getText(), "Email Address");
|
||||||
|
errorMsg += Validator.isValidPhoneNumber(txtPhone.getText(), "Phone Number");
|
||||||
|
|
||||||
if(errorMsg.isEmpty()){ //no validation errors detected
|
if(errorMsg.isEmpty()){ //no validation errors detected
|
||||||
Supplier supplier = collectSupplier(); //get supplier info
|
Supplier supplier = collectSupplier(); //get supplier info
|
||||||
|
|||||||
@@ -0,0 +1,41 @@
|
|||||||
|
package org.example.petshopdesktop.database;
|
||||||
|
|
||||||
|
import javafx.collections.FXCollections;
|
||||||
|
import javafx.collections.ObservableList;
|
||||||
|
import org.example.petshopdesktop.models.Category;
|
||||||
|
import org.example.petshopdesktop.models.Product;
|
||||||
|
|
||||||
|
import java.sql.Connection;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.sql.Statement;
|
||||||
|
|
||||||
|
public class CategoryDB {
|
||||||
|
/**
|
||||||
|
* gets all the category into an observable list
|
||||||
|
* @return a list of all the category
|
||||||
|
* @throws SQLException if failed to find categories in the database
|
||||||
|
*/
|
||||||
|
public static ObservableList<Category> getCategories() throws SQLException{
|
||||||
|
//Connect to the database
|
||||||
|
ObservableList<Category> categories = FXCollections.observableArrayList();
|
||||||
|
Connection conn = ConnectionDB.getConnection();
|
||||||
|
|
||||||
|
//Execute Query
|
||||||
|
Statement stmt = conn.createStatement();
|
||||||
|
ResultSet rs = stmt.executeQuery("SELECT * FROM category");
|
||||||
|
|
||||||
|
//While there is still data add categories to the list
|
||||||
|
while(rs.next()){
|
||||||
|
Category category = new Category(
|
||||||
|
rs.getInt(1),
|
||||||
|
rs.getString(2),
|
||||||
|
rs.getString(3));
|
||||||
|
categories.add(category);
|
||||||
|
}
|
||||||
|
|
||||||
|
//close connection and return categories
|
||||||
|
conn.close();
|
||||||
|
return categories;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,11 +4,9 @@ import javafx.collections.FXCollections;
|
|||||||
import javafx.collections.ObservableList;
|
import javafx.collections.ObservableList;
|
||||||
import org.example.petshopdesktop.DTOs.ProductDTO;
|
import org.example.petshopdesktop.DTOs.ProductDTO;
|
||||||
import org.example.petshopdesktop.models.Product;
|
import org.example.petshopdesktop.models.Product;
|
||||||
|
import org.example.petshopdesktop.models.Supplier;
|
||||||
|
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.sql.*;
|
import java.sql.*;
|
||||||
import java.util.Properties;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A class containing all the methods relating to CRUD on Products table
|
* A class containing all the methods relating to CRUD on Products table
|
||||||
@@ -34,10 +32,9 @@ public class ProductDB {
|
|||||||
Product product = new Product(
|
Product product = new Product(
|
||||||
rs.getInt(1),
|
rs.getInt(1),
|
||||||
rs.getString(2),
|
rs.getString(2),
|
||||||
rs.getString(3),
|
rs.getDouble(3),
|
||||||
rs.getDouble(4),
|
rs.getInt(4),
|
||||||
rs.getInt(5),
|
rs.getString(5));
|
||||||
rs.getString(6));
|
|
||||||
products.add(product);
|
products.add(product);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,7 +55,7 @@ public class ProductDB {
|
|||||||
|
|
||||||
//Execute Query
|
//Execute Query
|
||||||
Statement stmt = conn.createStatement();
|
Statement stmt = conn.createStatement();
|
||||||
String sql = "SELECT p.prodId, p.prodName, p.prodSku, p.prodPrice, p.categoryId, c.categoryName, p.prodDesc " +
|
String sql = "SELECT p.prodId, p.prodName, p.prodPrice, p.categoryId, c.categoryName, p.prodDesc " +
|
||||||
"FROM product p " +
|
"FROM product p " +
|
||||||
"LEFT JOIN category c ON p.categoryId = c.categoryId";
|
"LEFT JOIN category c ON p.categoryId = c.categoryId";
|
||||||
ResultSet rs = stmt.executeQuery(sql);
|
ResultSet rs = stmt.executeQuery(sql);
|
||||||
@@ -68,11 +65,10 @@ public class ProductDB {
|
|||||||
ProductDTO product = new ProductDTO(
|
ProductDTO product = new ProductDTO(
|
||||||
rs.getInt(1),
|
rs.getInt(1),
|
||||||
rs.getString(2),
|
rs.getString(2),
|
||||||
rs.getString(3),
|
rs.getDouble(3),
|
||||||
rs.getDouble(4),
|
rs.getInt(4),
|
||||||
rs.getInt(5),
|
rs.getString(5),
|
||||||
rs.getString(6),
|
rs.getString(6));
|
||||||
rs.getString(7));
|
|
||||||
products.add(product);
|
products.add(product);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,4 +76,137 @@ public class ProductDB {
|
|||||||
conn.close();
|
conn.close();
|
||||||
return products;
|
return products;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Inserts a new product to the database
|
||||||
|
* @param product product entity to be inserted
|
||||||
|
* @return number of rows affected in the database
|
||||||
|
* @throws SQLException if insertion failed
|
||||||
|
*/
|
||||||
|
public static int insertProduct(Product product) throws SQLException {
|
||||||
|
int numRows = 0;
|
||||||
|
|
||||||
|
Connection conn = ConnectionDB.getConnection();
|
||||||
|
String sql = "INSERT INTO product (prodId, prodName, prodPrice, categoryId, prodDesc)" +
|
||||||
|
"VALUES (?, ?, ?, ?, ?)";
|
||||||
|
|
||||||
|
//These are the values from product to put into the query above
|
||||||
|
PreparedStatement stmt = conn.prepareStatement(sql);
|
||||||
|
stmt.setInt(1, product.getProdId());
|
||||||
|
stmt.setString(2, product.getProdName());
|
||||||
|
stmt.setDouble(3, product.getProdPrice());
|
||||||
|
stmt.setInt(4, product.getCategoryId());
|
||||||
|
stmt.setString(5, product.getProdDesc());
|
||||||
|
|
||||||
|
//update the number of rows affected, return and close connection
|
||||||
|
numRows = stmt.executeUpdate();
|
||||||
|
conn.close();
|
||||||
|
|
||||||
|
return numRows;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update an existing product to the database
|
||||||
|
* @param prodId id of product
|
||||||
|
* @param product new product data
|
||||||
|
* @return number of rows affected in the database
|
||||||
|
* @throws SQLException if update failed
|
||||||
|
*/
|
||||||
|
public static int updateProduct(int prodId, Product product) throws SQLException {
|
||||||
|
int numRows = 0;
|
||||||
|
|
||||||
|
Connection conn = ConnectionDB.getConnection();
|
||||||
|
String sql = "UPDATE product SET " +
|
||||||
|
" prodName = ?, " +
|
||||||
|
" prodPrice = ?, " +
|
||||||
|
" categoryId = ?, " +
|
||||||
|
" prodDesc = ? " +
|
||||||
|
" WHERE prodId = ?";
|
||||||
|
|
||||||
|
//update values to query
|
||||||
|
PreparedStatement stmt = conn.prepareStatement(sql);
|
||||||
|
stmt.setString(1, product.getProdName());
|
||||||
|
stmt.setDouble(2, product.getProdPrice());
|
||||||
|
stmt.setInt(3, product.getCategoryId());
|
||||||
|
stmt.setString(4, product.getProdDesc());
|
||||||
|
stmt.setInt(5, prodId);
|
||||||
|
|
||||||
|
//Update rows and close connection
|
||||||
|
numRows = stmt.executeUpdate();
|
||||||
|
conn.close();
|
||||||
|
|
||||||
|
return numRows;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete a product from the database
|
||||||
|
* @param prodId product id to be deleted
|
||||||
|
* @return number of rows affected in the database
|
||||||
|
* @throws SQLException if delete failed
|
||||||
|
*/
|
||||||
|
public static int deleteProduct(int prodId) throws SQLException {
|
||||||
|
int numRows = 0;
|
||||||
|
Connection conn = ConnectionDB.getConnection();
|
||||||
|
|
||||||
|
String sql = "DELETE FROM product WHERE prodId = ?";
|
||||||
|
PreparedStatement stmt = conn.prepareStatement(sql);
|
||||||
|
|
||||||
|
stmt.setInt(1, prodId);
|
||||||
|
|
||||||
|
//close connection and update rows affected
|
||||||
|
numRows = stmt.executeUpdate();
|
||||||
|
conn.close();
|
||||||
|
|
||||||
|
return numRows;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a list of productDTOs that is filtered by a given string
|
||||||
|
* @param filter the word to filter table
|
||||||
|
* @return ObservableList of ProductDTOs with the filtered data
|
||||||
|
* @throws SQLException if getting products failed
|
||||||
|
*/
|
||||||
|
public static ObservableList<ProductDTO> getFilteredProductDTOs(String filter) throws SQLException {
|
||||||
|
//Connect to the database
|
||||||
|
ObservableList<ProductDTO> products = FXCollections.observableArrayList();
|
||||||
|
Connection conn = ConnectionDB.getConnection();
|
||||||
|
|
||||||
|
//Get SQL query for filtered word
|
||||||
|
String sql =
|
||||||
|
"SELECT p.prodId, p.prodName, p.prodPrice, p.categoryId, c.categoryName, p.prodDesc" +
|
||||||
|
" FROM product p" +
|
||||||
|
" LEFT JOIN category c ON p.categoryId = c.categoryId" +
|
||||||
|
" WHERE " +
|
||||||
|
"prodName LIKE ? OR " +
|
||||||
|
"prodPrice LIKE ? OR " +
|
||||||
|
"categoryName LIKE ? OR " +
|
||||||
|
"prodDesc LIKE ?";
|
||||||
|
|
||||||
|
//add % wildcard so the 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);
|
||||||
|
stmt.setString(4, filteredString);
|
||||||
|
|
||||||
|
//execute query
|
||||||
|
ResultSet rs = stmt.executeQuery();
|
||||||
|
|
||||||
|
//While there is still data add products to the list
|
||||||
|
while(rs.next()){
|
||||||
|
ProductDTO product = new ProductDTO(
|
||||||
|
rs.getInt(1),
|
||||||
|
rs.getString(2),
|
||||||
|
rs.getDouble(3),
|
||||||
|
rs.getInt(4),
|
||||||
|
rs.getString(5),
|
||||||
|
rs.getString(6));
|
||||||
|
products.add(product);
|
||||||
|
}
|
||||||
|
|
||||||
|
conn.close();
|
||||||
|
return products;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ public class SupplierDB {
|
|||||||
Statement stmt = conn.createStatement();
|
Statement stmt = conn.createStatement();
|
||||||
ResultSet rs = stmt.executeQuery("SELECT * FROM supplier");
|
ResultSet rs = stmt.executeQuery("SELECT * FROM supplier");
|
||||||
|
|
||||||
//While there is still data add products to the list
|
//While there is still data add suppliers to the list
|
||||||
while(rs.next()){
|
while(rs.next()){
|
||||||
Supplier supplier = new Supplier(
|
Supplier supplier = new Supplier(
|
||||||
rs.getInt(1),
|
rs.getInt(1),
|
||||||
@@ -127,4 +127,54 @@ public class SupplierDB {
|
|||||||
|
|
||||||
return numRows;
|
return numRows;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a list of Suppliers that is filtered by a given string
|
||||||
|
* @param filter the word to filter table
|
||||||
|
* @return ObservableList of suppliers with the filtered data
|
||||||
|
* @throws SQLException if getting suppliers failed
|
||||||
|
*/
|
||||||
|
public static ObservableList<Supplier> getFilteredSuppliers(String filter) throws SQLException {
|
||||||
|
//Connect to the database
|
||||||
|
ObservableList<Supplier> suppliers = FXCollections.observableArrayList();
|
||||||
|
Connection conn = ConnectionDB.getConnection();
|
||||||
|
|
||||||
|
//Get SQL query for filtered word
|
||||||
|
String sql =
|
||||||
|
"SELECT * FROM supplier" +
|
||||||
|
" WHERE " +
|
||||||
|
"supCompany LIKE ? OR " +
|
||||||
|
"supContactFirstName LIKE ? OR " +
|
||||||
|
"supContactLastName LIKE ? OR " +
|
||||||
|
"supEmail LIKE ? OR " +
|
||||||
|
"supPhone LIKE ?";
|
||||||
|
|
||||||
|
//add % wildcard so the 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);
|
||||||
|
stmt.setString(4, filteredString);
|
||||||
|
stmt.setString(5, filteredString);
|
||||||
|
|
||||||
|
//execute query
|
||||||
|
ResultSet rs = stmt.executeQuery();
|
||||||
|
|
||||||
|
//While there is still data add suppliers to the list
|
||||||
|
while(rs.next()){
|
||||||
|
Supplier supplier = new Supplier(
|
||||||
|
rs.getInt(1),
|
||||||
|
rs.getString(2),
|
||||||
|
rs.getString(3),
|
||||||
|
rs.getString(4),
|
||||||
|
rs.getString(5),
|
||||||
|
rs.getString(6));
|
||||||
|
suppliers.add(supplier);
|
||||||
|
}
|
||||||
|
|
||||||
|
conn.close();
|
||||||
|
return suppliers;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,59 @@
|
|||||||
|
package org.example.petshopdesktop.models;
|
||||||
|
|
||||||
|
import javafx.beans.property.SimpleIntegerProperty;
|
||||||
|
import javafx.beans.property.SimpleStringProperty;
|
||||||
|
|
||||||
|
public class Category {
|
||||||
|
private SimpleIntegerProperty categoryId;
|
||||||
|
private SimpleStringProperty categoryName;
|
||||||
|
private SimpleStringProperty categoryType;
|
||||||
|
|
||||||
|
//Constrctor
|
||||||
|
public Category(int categoryId, String categoryName, String categoryType) {
|
||||||
|
this.categoryId = new SimpleIntegerProperty(categoryId);
|
||||||
|
this.categoryName = new SimpleStringProperty(categoryName);
|
||||||
|
this.categoryType = new SimpleStringProperty(categoryType);
|
||||||
|
}
|
||||||
|
|
||||||
|
//getters and setters
|
||||||
|
public int getCategoryId() {
|
||||||
|
return categoryId.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public SimpleIntegerProperty categoryIdProperty() {
|
||||||
|
return categoryId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCategoryId(int categoryId) {
|
||||||
|
this.categoryId.set(categoryId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCategoryName() {
|
||||||
|
return categoryName.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public SimpleStringProperty categoryNameProperty() {
|
||||||
|
return categoryName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCategoryName(String categoryName) {
|
||||||
|
this.categoryName.set(categoryName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getCategoryType() {
|
||||||
|
return categoryType.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
public SimpleStringProperty categoryTypeProperty() {
|
||||||
|
return categoryType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCategoryType(String categoryType) {
|
||||||
|
this.categoryType.set(categoryType);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return getCategoryName();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,16 +10,14 @@ import javafx.beans.property.SimpleStringProperty;
|
|||||||
public class Product {
|
public class Product {
|
||||||
private SimpleIntegerProperty prodId;
|
private SimpleIntegerProperty prodId;
|
||||||
private SimpleStringProperty prodName;
|
private SimpleStringProperty prodName;
|
||||||
private SimpleStringProperty prodSku;
|
|
||||||
private SimpleDoubleProperty prodPrice;
|
private SimpleDoubleProperty prodPrice;
|
||||||
private SimpleIntegerProperty categoryId;
|
private SimpleIntegerProperty categoryId;
|
||||||
private SimpleStringProperty prodDesc;
|
private SimpleStringProperty prodDesc;
|
||||||
|
|
||||||
//constructor
|
//constructor
|
||||||
public Product(int prodId, String prodName, String prodSku, double prodPrice, int categoryId, String prodDesc) {
|
public Product(int prodId, String prodName, double prodPrice, int categoryId, String prodDesc) {
|
||||||
this.prodId = new SimpleIntegerProperty(prodId);
|
this.prodId = new SimpleIntegerProperty(prodId);
|
||||||
this.prodName = new SimpleStringProperty(prodName);
|
this.prodName = new SimpleStringProperty(prodName);
|
||||||
this.prodSku = new SimpleStringProperty(prodSku);
|
|
||||||
this.prodPrice = new SimpleDoubleProperty(prodPrice);
|
this.prodPrice = new SimpleDoubleProperty(prodPrice);
|
||||||
this.categoryId = new SimpleIntegerProperty(categoryId);
|
this.categoryId = new SimpleIntegerProperty(categoryId);
|
||||||
this.prodDesc = new SimpleStringProperty(prodDesc);
|
this.prodDesc = new SimpleStringProperty(prodDesc);
|
||||||
@@ -50,18 +48,6 @@ public class Product {
|
|||||||
this.prodName.set(prodName);
|
this.prodName.set(prodName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getProdSku() {
|
|
||||||
return prodSku.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
public SimpleStringProperty prodSkuProperty() {
|
|
||||||
return prodSku;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setProdSku(String prodSku) {
|
|
||||||
this.prodSku.set(prodSku);
|
|
||||||
}
|
|
||||||
|
|
||||||
public double getProdPrice() {
|
public double getProdPrice() {
|
||||||
return prodPrice.get();
|
return prodPrice.get();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,149 @@
|
|||||||
|
<?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.ProductDialogController">
|
||||||
|
<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="79.0" prefWidth="246.0">
|
||||||
|
<children>
|
||||||
|
<Label fx:id="lblMode" prefHeight="54.0" prefWidth="246.0" text="Mode Product" textFill="WHITE">
|
||||||
|
<font>
|
||||||
|
<Font name="Comic Sans MS Bold" size="30.0" />
|
||||||
|
</font>
|
||||||
|
</Label>
|
||||||
|
<Label fx:id="lblProdId" 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="79.0" prefWidth="243.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 Name:" textFill="#2c3e50">
|
||||||
|
<font>
|
||||||
|
<Font name="System Bold" size="16.0" />
|
||||||
|
</font>
|
||||||
|
</Label>
|
||||||
|
<TextField fx:id="txtProdName" 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">
|
||||||
|
<children>
|
||||||
|
<Label text="Product Price:" textFill="#2c3e50">
|
||||||
|
<font>
|
||||||
|
<Font name="System Bold" size="16.0" />
|
||||||
|
</font>
|
||||||
|
</Label>
|
||||||
|
<TextField fx:id="txtProdPrice" 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.rowIndex="1">
|
||||||
|
<children>
|
||||||
|
<Label text="Category:" textFill="#2c3e50">
|
||||||
|
<font>
|
||||||
|
<Font name="System Bold" size="16.0" />
|
||||||
|
</font>
|
||||||
|
</Label>
|
||||||
|
<ComboBox fx:id="cbProdCategory" 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" GridPane.rowIndex="1">
|
||||||
|
<children>
|
||||||
|
<Label text="Description:" textFill="#2c3e50">
|
||||||
|
<font>
|
||||||
|
<Font name="System Bold" size="16.0" />
|
||||||
|
</font>
|
||||||
|
</Label>
|
||||||
|
<TextField fx:id="txtProdDesc" 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.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>
|
||||||
@@ -68,11 +68,10 @@
|
|||||||
<TableView fx:id="tvProducts" prefHeight="362.0" prefWidth="752.0" style="-fx-background-color: white; -fx-background-radius: 12;" VBox.vgrow="ALWAYS">
|
<TableView fx:id="tvProducts" prefHeight="362.0" prefWidth="752.0" style="-fx-background-color: white; -fx-background-radius: 12;" VBox.vgrow="ALWAYS">
|
||||||
<columns>
|
<columns>
|
||||||
<TableColumn fx:id="colProductId" prefWidth="60.0" text="ID" />
|
<TableColumn fx:id="colProductId" prefWidth="60.0" text="ID" />
|
||||||
<TableColumn fx:id="colProductName" prefWidth="150.0" text="Name" />
|
<TableColumn fx:id="colProductName" prefWidth="170.85714721679688" text="Name" />
|
||||||
<TableColumn fx:id="colProductCategory" prefWidth="150.0" text="Category" />
|
<TableColumn fx:id="colProductCategory" prefWidth="195.4285888671875" text="Category" />
|
||||||
<TableColumn fx:id="colProductDesc" prefWidth="220.0" text="Description" />
|
<TableColumn fx:id="colProductDesc" prefWidth="210.28570556640625" text="Description" />
|
||||||
<TableColumn fx:id="colProductPrice" prefWidth="100.0" text="Price" />
|
<TableColumn fx:id="colProductPrice" prefWidth="115.4285888671875" text="Price" />
|
||||||
<TableColumn fx:id="colProductSKU" prefWidth="70.2857666015625" text="SKU" />
|
|
||||||
</columns>
|
</columns>
|
||||||
</TableView>
|
</TableView>
|
||||||
</children>
|
</children>
|
||||||
|
|||||||
Reference in New Issue
Block a user