diff --git a/connectionpetstore.properties b/connectionpetstore.properties index 00ffda7d..bdee2f8d 100644 --- a/connectionpetstore.properties +++ b/connectionpetstore.properties @@ -1,4 +1 @@ -url=jdbc:mysql://127.0.0.1:3306/Petstoredb?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC -user=petapp -password=petapppass -api.baseUrl=http://localhost:8080 \ No newline at end of file +api.baseUrl=http://localhost:8080 diff --git a/src/main/java/org/example/petshopdesktop/PetShopApplication.java b/src/main/java/org/example/petshopdesktop/PetShopApplication.java index 06def37b..0127e42c 100644 --- a/src/main/java/org/example/petshopdesktop/PetShopApplication.java +++ b/src/main/java/org/example/petshopdesktop/PetShopApplication.java @@ -4,18 +4,12 @@ import javafx.application.Application; import javafx.fxml.FXMLLoader; import javafx.scene.Scene; import javafx.stage.Stage; -import org.example.petshopdesktop.database.UserDB; import java.io.IOException; public class PetShopApplication extends Application { @Override public void start(Stage stage) throws IOException { - try { - UserDB.initializeTable(); - } catch (Exception e) { - System.err.println("Warning: could not initialize users table: " + e.getMessage()); - } FXMLLoader fxmlLoader = new FXMLLoader(PetShopApplication.class.getResource("login-view.fxml")); Scene scene = new Scene(fxmlLoader.load()); stage.setTitle("Pet Shop Manager - Login"); diff --git a/src/main/java/org/example/petshopdesktop/database/AdoptionDB.java b/src/main/java/org/example/petshopdesktop/database/AdoptionDB.java deleted file mode 100644 index dee46805..00000000 --- a/src/main/java/org/example/petshopdesktop/database/AdoptionDB.java +++ /dev/null @@ -1,166 +0,0 @@ -package org.example.petshopdesktop.database; - -import javafx.collections.FXCollections; -import javafx.collections.ObservableList; -import org.example.petshopdesktop.models.Adoption; -import org.example.petshopdesktop.models.Customer; -import org.example.petshopdesktop.models.Pet; -import org.example.petshopdesktop.util.ActivityLogger; - -import java.sql.*; - -public class AdoptionDB { - - //Select query - private static final String BASE_SELECT = - "SELECT a.adoptionId, a.petId, a.customerId, " + - "CONCAT(c.firstName, ' ', c.lastName) AS customerName, " + - "a.adoptionDate, p.petPrice AS adoptionFee, a.adoptionStatus " + - "FROM adoption a " + - "JOIN customer c ON a.customerId = c.customerId " + - "JOIN pet p ON a.petId = p.petId"; - - //Retrieve all adoption records from DB - public static ObservableList getAdoptions() throws SQLException { - ObservableList adoptions = FXCollections.observableArrayList(); - Connection conn = ConnectionDB.getConnection(); - - Statement stmt = conn.createStatement(); - ResultSet rs = stmt.executeQuery(BASE_SELECT); - - //Map results - while (rs.next()) { - adoptions.add(mapRow(rs)); - } - - conn.close(); - return adoptions; - } - - //Returns data depending on search query - public static ObservableList getFilteredAdoptions(String filter) throws SQLException { - ObservableList adoptions = FXCollections.observableArrayList(); - Connection conn = ConnectionDB.getConnection(); - - String sql = BASE_SELECT + - " WHERE a.adoptionId LIKE '%" + filter + "%' OR " + - "a.petId LIKE '%" + filter + "%' OR " + - "CONCAT(c.firstName, ' ', c.lastName) LIKE '%" + filter + "%' OR " + - "a.adoptionDate LIKE '%" + filter + "%' OR " + - "p.petPrice LIKE '%" + filter + "%' OR " + - "a.adoptionStatus LIKE '%" + filter + "%'"; - - Statement stmt = conn.createStatement(); - ResultSet rs = stmt.executeQuery(sql); - - //Map results - while (rs.next()) { - adoptions.add(mapRow(rs)); - } - - conn.close(); - return adoptions; - } - - //Add new adoption - public static int insertAdoption(Adoption adoption) throws SQLException { - Connection conn = ConnectionDB.getConnection(); - String sql = "INSERT INTO adoption (petId, customerId, adoptionDate, adoptionStatus) VALUES (?, ?, ?, ?)"; - - PreparedStatement stmt = conn.prepareStatement(sql); - - //Put data in Adoption object - stmt.setInt(1, adoption.getPetId()); - stmt.setInt(2, adoption.getCustomerId()); - stmt.setString(3, adoption.getAdoptionDate()); - stmt.setString(4, adoption.getAdoptionStatus()); - - int numRows = stmt.executeUpdate(); - conn.close(); - - // Log the operation - if (numRows > 0) { - ActivityLogger.getInstance().logInsert("adoption", - "N/A", - String.format("Adoption record added for Pet ID %d, Customer ID %d", adoption.getPetId(), adoption.getCustomerId())); - } - - return numRows; - } - - //Updating pre-existing adoption - public static int updateAdoption(int adoptionId, Adoption adoption) throws SQLException { - Connection conn = ConnectionDB.getConnection(); - String sql = "UPDATE adoption SET petId = ?, customerId = ?, adoptionDate = ?, adoptionStatus = ? WHERE adoptionId = ?"; - - PreparedStatement stmt = conn.prepareStatement(sql); - stmt.setInt(1, adoption.getPetId()); - stmt.setInt(2, adoption.getCustomerId()); - stmt.setString(3, adoption.getAdoptionDate()); - stmt.setString(4, adoption.getAdoptionStatus()); - stmt.setInt(5, adoptionId); - - int numRows = stmt.executeUpdate(); - conn.close(); - - // Log the operation - if (numRows > 0) { - ActivityLogger.getInstance().logUpdate("adoption", - String.valueOf(adoptionId), - String.format("Adoption ID %d updated", adoptionId)); - } - - return numRows; - } - - //Delete adoption - public static int deleteAdoption(int adoptionId) throws SQLException { - Connection conn = ConnectionDB.getConnection(); - String sql = "DELETE FROM adoption WHERE adoptionId = ?"; - - PreparedStatement stmt = conn.prepareStatement(sql); - stmt.setInt(1, adoptionId); - - int numRows = stmt.executeUpdate(); - conn.close(); - - // Log the operation - if (numRows > 0) { - ActivityLogger.getInstance().logDelete("adoption", - String.valueOf(adoptionId), - String.format("Adoption ID %d deleted", adoptionId)); - } - - return numRows; - } - - //Grab list of customers from DB for comboboxes - public static ObservableList getCustomers() throws SQLException { - ObservableList customers = FXCollections.observableArrayList(); - Connection conn = ConnectionDB.getConnection(); - - Statement stmt = conn.createStatement(); - ResultSet rs = stmt.executeQuery("SELECT customerId, firstName, lastName, email, phone FROM customer"); - - while (rs.next()) { - customers.add(new Customer(rs.getInt(1), rs.getString(2), rs.getString(3), rs.getString(4), rs.getString(5))); - } - - conn.close(); - return customers; - } - - //DRY: converts DB data into usable Java object - private static Adoption mapRow(ResultSet rs) throws SQLException { - return new Adoption( - rs.getInt("adoptionId"), - rs.getInt("petId"), - rs.getInt("customerId"), - "", - rs.getString("customerName"), - rs.getString("adoptionDate"), - rs.getDouble("adoptionFee"), - rs.getString("adoptionStatus") - ); - } -} diff --git a/src/main/java/org/example/petshopdesktop/database/AppointmentDB.java b/src/main/java/org/example/petshopdesktop/database/AppointmentDB.java deleted file mode 100644 index 747dd0f3..00000000 --- a/src/main/java/org/example/petshopdesktop/database/AppointmentDB.java +++ /dev/null @@ -1,223 +0,0 @@ -package org.example.petshopdesktop.database; - -import javafx.collections.FXCollections; -import javafx.collections.ObservableList; - -import org.example.petshopdesktop.DTOs.AppointmentDTO; -import org.example.petshopdesktop.models.Appointment; -import org.example.petshopdesktop.util.ActivityLogger; - -import java.sql.*; - -public class AppointmentDB { - - // ============================ - // GET ALL APPOINTMENTS - // ============================ - public static ObservableList getAppointmentDTOs() - throws SQLException { - - ObservableList list = - FXCollections.observableArrayList(); - - Connection conn = ConnectionDB.getConnection(); - - String sql = """ - SELECT a.appointmentId, - c.customerId, - CONCAT(c.firstName,' ',c.lastName) AS customerName, - p.petId, - p.petName, - s.serviceId, - s.serviceName, - a.appointmentDate, - a.appointmentTime, - a.appointmentStatus - FROM appointment a - JOIN customer c ON a.customerId = c.customerId - JOIN appointmentPet ap ON a.appointmentId = ap.appointmentId - JOIN pet p ON ap.petId = p.petId - JOIN service s ON a.serviceId = s.serviceId - """; - - Statement stmt = conn.createStatement(); - ResultSet rs = stmt.executeQuery(sql); - - while (rs.next()) { - - AppointmentDTO dto = new AppointmentDTO( - rs.getInt("appointmentId"), - - rs.getInt("customerId"), - rs.getString("customerName"), - - rs.getInt("petId"), - rs.getString("petName"), - - rs.getInt("serviceId"), - rs.getString("serviceName"), - - rs.getString("appointmentDate"), - rs.getString("appointmentTime"), - rs.getString("appointmentStatus") - ); - - list.add(dto); - } - - conn.close(); - return list; - } - - // ============================ - // INSERT APPOINTMENT - // ============================ - public static int insertAppointment(Appointment appt) - throws SQLException { - - Connection conn = ConnectionDB.getConnection(); - - String sql = """ - INSERT INTO appointment - (serviceId, customerId, appointmentDate, - appointmentTime, appointmentStatus) - VALUES (?,?,?,?,?) - """; - - PreparedStatement ps = - conn.prepareStatement(sql, - Statement.RETURN_GENERATED_KEYS); - - ps.setInt(1, appt.getServiceId()); - ps.setInt(2, appt.getCustomerId()); - ps.setString(3, appt.getAppointmentDate()); - ps.setString(4, appt.getAppointmentTime()); - ps.setString(5, appt.getAppointmentStatus()); - - ps.executeUpdate(); - - ResultSet keys = ps.getGeneratedKeys(); - int newId = 0; - - if (keys.next()) { - newId = keys.getInt(1); - } - - conn.close(); - - // Log the operation - if (newId > 0) { - ActivityLogger.getInstance().logInsert("appointment", - String.valueOf(newId), - String.format("Appointment created for Customer ID %d, Service ID %d", appt.getCustomerId(), appt.getServiceId())); - } - - return newId; - } - - // - // LINK PET TO APPOINTMENT - // - public static void insertAppointmentPet(int appointmentId, - int petId) - throws SQLException { - - Connection conn = ConnectionDB.getConnection(); - - String sql = - "INSERT INTO appointmentPet (appointmentId, petId) VALUES (?,?)"; - - PreparedStatement ps = conn.prepareStatement(sql); - ps.setInt(1, appointmentId); - ps.setInt(2, petId); - int numRows = ps.executeUpdate(); - - conn.close(); - - // Log the operation - if (numRows > 0) { - ActivityLogger.getInstance().logInsert("appointmentPet", - String.valueOf(appointmentId), - String.format("Pet ID %d linked to Appointment ID %d", petId, appointmentId)); - } - } - - // - // UPDATE APPOINTMENT - // - public static int updateAppointment(int id, - Appointment appt, - int petId) - throws SQLException { - - Connection conn = ConnectionDB.getConnection(); - - String sql = - "UPDATE appointment SET serviceId=?, customerId=?, " + - "appointmentDate=?, appointmentTime=?, appointmentStatus=? " + - "WHERE appointmentId=?"; - - PreparedStatement ps = conn.prepareStatement(sql); - - ps.setInt(1, appt.getServiceId()); - ps.setInt(2, appt.getCustomerId()); - ps.setString(3, appt.getAppointmentDate()); - ps.setString(4, appt.getAppointmentTime()); - ps.setString(5, appt.getAppointmentStatus()); - ps.setInt(6, id); - - ps.executeUpdate(); - - String sql2 = - "UPDATE appointmentPet SET petId=? WHERE appointmentId=?"; - - PreparedStatement ps2 = conn.prepareStatement(sql2); - ps2.setInt(1, petId); - ps2.setInt(2, id); - ps2.executeUpdate(); - - conn.close(); - - // Log the operation - ActivityLogger.getInstance().logUpdate("appointment", - String.valueOf(id), - String.format("Appointment ID %d updated", id)); - - return 1; - } - - // - // DELETE APPOINTMENT - // - public static int deleteAppointment(int id) - throws SQLException { - - Connection conn = ConnectionDB.getConnection(); - - PreparedStatement ps1 = - conn.prepareStatement( - "DELETE FROM appointmentPet WHERE appointmentId=?" - ); - ps1.setInt(1, id); - ps1.executeUpdate(); - - PreparedStatement ps2 = - conn.prepareStatement( - "DELETE FROM appointment WHERE appointmentId=?" - ); - ps2.setInt(1, id); - - int rows = ps2.executeUpdate(); - - conn.close(); - - // Log the operation - if (rows > 0) { - ActivityLogger.getInstance().logDelete("appointment", - String.valueOf(id), - String.format("Appointment ID %d deleted", id)); - } - - return rows; - } -} \ No newline at end of file diff --git a/src/main/java/org/example/petshopdesktop/database/CategoryDB.java b/src/main/java/org/example/petshopdesktop/database/CategoryDB.java deleted file mode 100644 index f9a2a434..00000000 --- a/src/main/java/org/example/petshopdesktop/database/CategoryDB.java +++ /dev/null @@ -1,41 +0,0 @@ -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 getCategories() throws SQLException{ - //Connect to the database - ObservableList 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; - } -} diff --git a/src/main/java/org/example/petshopdesktop/database/ConnectionDB.java b/src/main/java/org/example/petshopdesktop/database/ConnectionDB.java deleted file mode 100644 index 09209c3e..00000000 --- a/src/main/java/org/example/petshopdesktop/database/ConnectionDB.java +++ /dev/null @@ -1,66 +0,0 @@ -package org.example.petshopdesktop.database; - -import org.example.petshopdesktop.util.ActivityLogger; - -import java.io.FileInputStream; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.sql.Connection; -import java.sql.DriverManager; -import java.sql.SQLException; -import java.util.Properties; - -public class ConnectionDB { - /** - * Method to try and connect to the database using connectionpetstore.properties. - * @return Connection to the database - */ - public static Connection getConnection(){ - String url = ""; - String user = ""; - String password = ""; - - Properties prop = new Properties(); - Path propsPath; - - String explicitPath = System.getenv("PETSTORE_DB_PROPS"); - if (explicitPath != null && !explicitPath.isBlank()) { - propsPath = Paths.get(explicitPath); - } else { - Path cwd = Paths.get(System.getProperty("user.dir"), "connectionpetstore.properties"); - Path xdg = Paths.get(System.getProperty("user.home"), ".config", "petstore", "connectionpetstore.properties"); - Path legacyWindows = Paths.get("./connectionpetstore.properties"); - - if (Files.exists(cwd)) propsPath = cwd; - else if (Files.exists(xdg)) propsPath = xdg; - else propsPath = legacyWindows; - } - - try (FileInputStream fis = new FileInputStream(propsPath.toString())) { - prop.load(fis); - url = prop.getProperty("url"); - user = prop.getProperty("user"); - password = prop.getProperty("password"); - } - catch(IOException e){ - ActivityLogger.getInstance().logException( - "ConnectionDB.getConnection", - e, - "Reading connection properties file"); - throw new RuntimeException("Problem with reading connection info: "+e.getMessage()); - } - - try{ - return DriverManager.getConnection(url,user,password); - } - catch (SQLException e) { - ActivityLogger.getInstance().logException( - "ConnectionDB.getConnection", - e, - "Establishing database connection"); - throw new RuntimeException("Problem with database connection: "+e.getMessage()); - } - } -} diff --git a/src/main/java/org/example/petshopdesktop/database/CustomerDB.java b/src/main/java/org/example/petshopdesktop/database/CustomerDB.java deleted file mode 100644 index abe47004..00000000 --- a/src/main/java/org/example/petshopdesktop/database/CustomerDB.java +++ /dev/null @@ -1,43 +0,0 @@ -package org.example.petshopdesktop.database; - -import javafx.collections.FXCollections; -import javafx.collections.ObservableList; -import org.example.petshopdesktop.models.Customer; - -import java.sql.*; - -public class CustomerDB { - - // - // GET ALL CUSTOMERS - // - public static ObservableList getCustomers() - throws SQLException { - - ObservableList list = - FXCollections.observableArrayList(); - - Connection conn = ConnectionDB.getConnection(); - - String sql = "SELECT * FROM customer"; - - Statement stmt = conn.createStatement(); - ResultSet rs = stmt.executeQuery(sql); - - while(rs.next()) { - - Customer c = new Customer( - rs.getInt("customerId"), - rs.getString("firstName"), - rs.getString("lastName"), - rs.getString("email"), - rs.getString("phone") - ); - - list.add(c); - } - - conn.close(); - return list; - } -} \ No newline at end of file diff --git a/src/main/java/org/example/petshopdesktop/database/EmployeeDB.java b/src/main/java/org/example/petshopdesktop/database/EmployeeDB.java deleted file mode 100644 index 18cd2167..00000000 --- a/src/main/java/org/example/petshopdesktop/database/EmployeeDB.java +++ /dev/null @@ -1,132 +0,0 @@ -package org.example.petshopdesktop.database; - -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; - -public class EmployeeDB { - - public static int ensureDefaultEmployee(String firstName, String lastName, String email, String phone, String role, boolean isActive) throws SQLException { - Integer existingId = findEmployeeIdByEmail(email); - if (existingId != null) { - return existingId; - } - - try (Connection conn = ConnectionDB.getConnection()) { - conn.setAutoCommit(false); - try { - int storeId = getDefaultStoreId(conn); - int employeeId = createEmployee(conn, firstName, lastName, email, phone, role, isActive); - assignEmployeeToStore(conn, employeeId, storeId); - conn.commit(); - return employeeId; - } catch (SQLException e) { - conn.rollback(); - throw e; - } finally { - conn.setAutoCommit(true); - } - } - } - - public static Integer findEmployeeIdByEmail(String email) throws SQLException { - String sql = "SELECT employeeId FROM employee WHERE email = ? LIMIT 1"; - try (Connection conn = ConnectionDB.getConnection(); - PreparedStatement ps = conn.prepareStatement(sql)) { - ps.setString(1, email); - try (ResultSet rs = ps.executeQuery()) { - if (rs.next()) { - return rs.getInt("employeeId"); - } - } - } - return null; - } - - public static int createEmployee(Connection conn, String firstName, String lastName, String email, String phone, String role, boolean isActive) throws SQLException { - String sql = "INSERT INTO employee (firstName, lastName, email, phone, role, isActive) VALUES (?, ?, ?, ?, ?, ?)"; - try (PreparedStatement ps = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) { - ps.setString(1, firstName); - ps.setString(2, lastName); - ps.setString(3, email); - ps.setString(4, phone); - ps.setString(5, role); - ps.setBoolean(6, isActive); - ps.executeUpdate(); - - try (ResultSet keys = ps.getGeneratedKeys()) { - if (keys.next()) { - return keys.getInt(1); - } - } - } - - throw new SQLException("Could not create employee."); - } - - public static void assignEmployeeToStore(Connection conn, int employeeId, int storeId) throws SQLException { - String sql = "INSERT IGNORE INTO employeeStore (employeeId, storeId) VALUES (?, ?)"; - try (PreparedStatement ps = conn.prepareStatement(sql)) { - ps.setInt(1, employeeId); - ps.setInt(2, storeId); - ps.executeUpdate(); - } - } - - public static int getDefaultStoreId() throws SQLException { - try (Connection conn = ConnectionDB.getConnection()) { - return getDefaultStoreId(conn); - } - } - - public static int getDefaultStoreId(Connection conn) throws SQLException { - Integer existing = firstStoreId(conn); - if (existing != null) { - return existing; - } - - String insert = "INSERT INTO storeLocation (storeName, address, phone, email) VALUES ('Main Store', 'N/A', '000-000-0000', 'main@petshop.com')"; - try (PreparedStatement ps = conn.prepareStatement(insert, Statement.RETURN_GENERATED_KEYS)) { - ps.executeUpdate(); - try (ResultSet keys = ps.getGeneratedKeys()) { - if (keys.next()) { - return keys.getInt(1); - } - } - } - - Integer after = firstStoreId(conn); - if (after != null) { - return after; - } - - return 1; - } - - public static Integer getPrimaryStoreId(int employeeId) throws SQLException { - String sql = "SELECT storeId FROM employeeStore WHERE employeeId = ? ORDER BY storeId ASC LIMIT 1"; - try (Connection conn = ConnectionDB.getConnection(); - PreparedStatement ps = conn.prepareStatement(sql)) { - ps.setInt(1, employeeId); - try (ResultSet rs = ps.executeQuery()) { - if (rs.next()) { - return rs.getInt("storeId"); - } - } - } - return null; - } - - private static Integer firstStoreId(Connection conn) throws SQLException { - String sql = "SELECT storeId FROM storeLocation ORDER BY storeId ASC LIMIT 1"; - try (PreparedStatement ps = conn.prepareStatement(sql); - ResultSet rs = ps.executeQuery()) { - if (rs.next()) { - return rs.getInt("storeId"); - } - } - return null; - } -} diff --git a/src/main/java/org/example/petshopdesktop/database/InventoryDB.java b/src/main/java/org/example/petshopdesktop/database/InventoryDB.java deleted file mode 100644 index 792f9e6d..00000000 --- a/src/main/java/org/example/petshopdesktop/database/InventoryDB.java +++ /dev/null @@ -1,162 +0,0 @@ -package org.example.petshopdesktop.database; - -import javafx.collections.FXCollections; -import javafx.collections.ObservableList; -import org.example.petshopdesktop.models.Inventory; -import org.example.petshopdesktop.util.ActivityLogger; - -import java.sql.*; - -public class InventoryDB { - - //Base selection query - //Returns invID, ProdID, Quantity from Inventory table - //Returns ProdName from Product table - private static final String BASE_SELECT = - "SELECT i.inventoryId, i.prodId, p.prodName, i.quantity " + - "FROM inventory i " + - "JOIN product p ON i.prodId = p.prodId"; - - - //Retrieves inventory records from DB - public static ObservableList getInventory() throws SQLException { - ObservableList inventoryList = FXCollections.observableArrayList(); - - Connection conn = ConnectionDB.getConnection(); - - Statement stmt = conn.createStatement(); - ResultSet rs = stmt.executeQuery(BASE_SELECT); - - while (rs.next()) { - inventoryList.add(mapRow(rs)); - } - - conn.close(); - - return inventoryList; - } - - //Returns records depending on search - public static ObservableList getFilteredInventory(String filter) throws SQLException { - ObservableList inventoryList = FXCollections.observableArrayList(); - Connection conn = ConnectionDB.getConnection(); - - String sql = BASE_SELECT + - " WHERE i.inventoryId LIKE ? OR " + - "i.prodId LIKE ? OR " + - "p.prodName LIKE ? OR " + - "i.quantity LIKE ?"; - - String filteredString = "%" + filter + "%"; - PreparedStatement stmt = conn.prepareStatement(sql); - - for (int i = 1; i <= 4; i++) { - stmt.setString(i, filteredString); - } - - ResultSet rs = stmt.executeQuery(); - - while (rs.next()) { - inventoryList.add(mapRow(rs)); - } - - conn.close(); - - return inventoryList; - } - - //Checks if the product already has an inventory entry - public static boolean productExistsInInventory(int prodId) throws SQLException { - Connection conn = ConnectionDB.getConnection(); - String sql = "SELECT COUNT(*) FROM inventory WHERE prodId = ?"; - - PreparedStatement stmt = conn.prepareStatement(sql); - stmt.setInt(1, prodId); - ResultSet rs = stmt.executeQuery(); - - boolean exists = rs.next() && rs.getInt(1) > 0; - conn.close(); - - return exists; - } - - //Inserting new inventory record - public static int insertInventory(Inventory inventory) throws SQLException { - Connection conn = ConnectionDB.getConnection(); - String sql = "INSERT INTO inventory (prodId, quantity) VALUES (?, ?)"; - - PreparedStatement stmt = conn.prepareStatement(sql); - stmt.setInt(1, inventory.getProdId()); - stmt.setInt(2, inventory.getQuantity()); - - int numRows = stmt.executeUpdate(); - conn.close(); - - // Log the operation - if (numRows > 0) { - ActivityLogger.getInstance().logInsert("inventory", - "N/A", - String.format("Inventory added for Product ID %d, Quantity %d", inventory.getProdId(), inventory.getQuantity())); - } - - return numRows; - } - - //Updating inventory record - public static int updateInventory(int inventoryId, Inventory inventory) throws SQLException { - Connection conn = ConnectionDB.getConnection(); - String sql = "UPDATE inventory SET prodId = ?, quantity = ? WHERE inventoryId = ?"; - - PreparedStatement stmt = conn.prepareStatement(sql); - stmt.setInt(1, inventory.getProdId()); - stmt.setInt(2, inventory.getQuantity()); - stmt.setInt(3, inventoryId); - - int numRows = stmt.executeUpdate(); - conn.close(); - - // Log the operation - if (numRows > 0) { - ActivityLogger.getInstance().logUpdate("inventory", - String.valueOf(inventoryId), - String.format("Inventory ID %d updated", inventoryId)); - } - - return numRows; - } - - //Deleting inventory record - public static int deleteInventory(int inventoryId) throws SQLException { - Connection conn = ConnectionDB.getConnection(); - String sql = "DELETE FROM inventory WHERE inventoryId = ?"; - - PreparedStatement stmt = conn.prepareStatement(sql); - stmt.setInt(1, inventoryId); - - int numRows = stmt.executeUpdate(); - conn.close(); - - // Log the operation - if (numRows > 0) { - ActivityLogger.getInstance().logDelete("inventory", - String.valueOf(inventoryId), - String.format("Inventory ID %d deleted", inventoryId)); - } - - return numRows; - } - - //DRY: converts DB data into usable Java object - private static Inventory mapRow(ResultSet rs) throws SQLException { - return new Inventory( - rs.getInt("inventoryId"), - rs.getInt("prodId"), - rs.getString("prodName"), - "", - 0, - "", - rs.getInt("quantity"), - 0 - ); - } -} \ No newline at end of file diff --git a/src/main/java/org/example/petshopdesktop/database/PetDB.java b/src/main/java/org/example/petshopdesktop/database/PetDB.java deleted file mode 100644 index 5a748c4d..00000000 --- a/src/main/java/org/example/petshopdesktop/database/PetDB.java +++ /dev/null @@ -1,167 +0,0 @@ -package org.example.petshopdesktop.database; - -import javafx.collections.FXCollections; -import javafx.collections.ObservableList; -import org.example.petshopdesktop.models.Pet; -import org.example.petshopdesktop.util.ActivityLogger; - -import java.sql.*; - -public class PetDB { - public static ObservableList getPets() throws SQLException { - //Connect to the database - ObservableList pets = FXCollections.observableArrayList(); - Connection conn = ConnectionDB.getConnection(); - - //Execute Query - Statement stmt = conn.createStatement(); - ResultSet rs = stmt.executeQuery("SELECT * FROM pet"); - - //While there is still data add pets to the list - while(rs.next()){ - Pet pet = new Pet( - rs.getInt(1), - rs.getString(2), - rs.getString(3), - rs.getString(4), - rs.getInt(5), - rs.getString(6), - rs.getDouble(7) - ); - pets.add(pet); - } - - //close connection and return pets - conn.close(); - return pets; - } - - public static ObservableList getFilteredPets(String filter) throws SQLException { - //Connect to the database - ObservableList pets = FXCollections.observableArrayList(); - Connection conn = ConnectionDB.getConnection(); - - //Get SQL query for filtered word - String sql = "SELECT * FROM pet " + - " WHERE " + - "petName LIKE ? OR " + - "petSpecies LIKE ? OR " + - "petBreed LIKE ? OR " + - "petAge LIKE ? OR " + - "petStatus LIKE ? OR " + - "petPrice LIKE ?"; - - 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); - stmt.setString(6, filteredString); - - ResultSet rs = stmt.executeQuery(); - - while(rs.next()){ - Pet pet = new Pet( - rs.getInt(1), - rs.getString(2), - rs.getString(3), - rs.getString(4), - rs.getInt(5), - rs.getString(6), - rs.getDouble(7) - ); - pets.add(pet); - } - - conn.close(); - return pets; - } - - public static int insertPet(Pet pet) throws SQLException { - int numRows = 0; - - Connection conn = ConnectionDB.getConnection(); - String sql = "INSERT INTO pet (petId, petName, petSpecies, petBreed, petAge, petStatus, petPrice)" + - " VALUES (?, ?, ?, ?, ?, ?, ?)"; - - PreparedStatement stmt = conn.prepareStatement(sql); - stmt.setInt(1, pet.getPetId()); - stmt.setString(2, pet.getPetName()); - stmt.setString(3, pet.getPetSpecies()); - stmt.setString(4, pet.getPetBreed()); - stmt.setInt(5, pet.getPetAge()); - stmt.setString(6, pet.getPetStatus()); - stmt.setDouble(7, pet.getPetPrice()); - - numRows = stmt.executeUpdate(); - conn.close(); - - // Log the operation - if (numRows > 0) { - ActivityLogger.getInstance().logInsert("pet", - String.valueOf(pet.getPetId()), - String.format("Pet '%s' added", pet.getPetName())); - } - - return numRows; - } - - public static int updatePet(int petId, Pet pet) throws SQLException { - int numRows = 0; - - Connection conn = ConnectionDB.getConnection(); - String sql = "UPDATE pet SET " + - " petName = ?, " + - " petSpecies = ?, " + - " petBreed = ?, " + - " petAge = ?, " + - " petStatus = ?, " + - " petPrice = ? " + - " WHERE petId = ?"; - PreparedStatement stmt = conn.prepareStatement(sql); - stmt.setString(1, pet.getPetName()); - stmt.setString(2, pet.getPetSpecies()); - stmt.setString(3, pet.getPetBreed()); - stmt.setInt(4, pet.getPetAge()); - stmt.setString(5, pet.getPetStatus()); - stmt.setDouble(6, pet.getPetPrice()); - stmt.setInt(7, petId); - - numRows = stmt.executeUpdate(); - conn.close(); - - // Log the operation - if (numRows > 0) { - ActivityLogger.getInstance().logUpdate("pet", - String.valueOf(petId), - String.format("Pet '%s' updated", pet.getPetName())); - } - - return numRows; - } - - public static int deletePet(int petId) throws SQLException { - int numRows = 0; - Connection conn = ConnectionDB.getConnection(); - - String sql = "DELETE FROM pet WHERE petId = ?"; - PreparedStatement stmt = conn.prepareStatement(sql); - - stmt.setInt(1, petId); - - numRows = stmt.executeUpdate(); - conn.close(); - - // Log the operation - if (numRows > 0) { - ActivityLogger.getInstance().logDelete("pet", - String.valueOf(petId), - String.format("Pet ID %d deleted", petId)); - } - - return numRows; - } -} diff --git a/src/main/java/org/example/petshopdesktop/database/ProductDB.java b/src/main/java/org/example/petshopdesktop/database/ProductDB.java deleted file mode 100644 index d8aa4da1..00000000 --- a/src/main/java/org/example/petshopdesktop/database/ProductDB.java +++ /dev/null @@ -1,234 +0,0 @@ -package org.example.petshopdesktop.database; - -import javafx.collections.FXCollections; -import javafx.collections.ObservableList; -import org.example.petshopdesktop.DTOs.ProductDTO; -import org.example.petshopdesktop.models.Product; -import org.example.petshopdesktop.models.Supplier; -import org.example.petshopdesktop.util.ActivityLogger; - -import java.sql.*; - -/** - * A class containing all the methods relating to CRUD on Products table - */ -public class ProductDB { - - /** - * gets all the products into an observable list - * @return a list of all the products - * @throws SQLException if failed to find products in the database - */ - public static ObservableList getProducts() throws SQLException{ - //Connect to the database - ObservableList products = FXCollections.observableArrayList(); - Connection conn = ConnectionDB.getConnection(); - - //Execute Query - Statement stmt = conn.createStatement(); - ResultSet rs = stmt.executeQuery("SELECT * FROM product"); - - //While there is still data add products to the list - while(rs.next()){ - Product product = new Product( - rs.getInt(1), - rs.getString(2), - rs.getDouble(3), - rs.getInt(4), - rs.getString(5)); - products.add(product); - } - - //close connection and return products - conn.close(); - return products; - } - - /** - * gets all the ProductDTOs into an observable list for display (displays categoryName instead of categoryId) - * @return the list of all the ProductDTOs - * @throws SQLException if failed to find products in the database - */ - public static ObservableList getProductDTO() throws SQLException{ - //Connect to the database - ObservableList products = FXCollections.observableArrayList(); - Connection conn = ConnectionDB.getConnection(); - - //Execute Query - Statement stmt = conn.createStatement(); - 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"; - ResultSet rs = stmt.executeQuery(sql); - - //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); - } - - //close connection and return products - conn.close(); - 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(); - - // Log the operation - if (numRows > 0) { - ActivityLogger.getInstance().logInsert("product", - String.valueOf(product.getProdId()), - String.format("Product '%s' added", product.getProdName())); - } - - 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(); - - // Log the operation - if (numRows > 0) { - ActivityLogger.getInstance().logUpdate("product", - String.valueOf(prodId), - String.format("Product '%s' updated", product.getProdName())); - } - - 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(); - - // Log the operation - if (numRows > 0) { - ActivityLogger.getInstance().logDelete("product", - String.valueOf(prodId), - String.format("Product ID %d deleted", prodId)); - } - - 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 getFilteredProductDTOs(String filter) throws SQLException { - //Connect to the database - ObservableList 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; - } -} diff --git a/src/main/java/org/example/petshopdesktop/database/ProductSupplierDB.java b/src/main/java/org/example/petshopdesktop/database/ProductSupplierDB.java deleted file mode 100644 index 146cbc6c..00000000 --- a/src/main/java/org/example/petshopdesktop/database/ProductSupplierDB.java +++ /dev/null @@ -1,219 +0,0 @@ -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 org.example.petshopdesktop.util.ActivityLogger; - -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 getProductSupplierDTO() throws SQLException{ - //Connect to the database - ObservableList 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 getFilteredProductSupplierDTO (String filter) throws SQLException { - //connect to the database - ObservableList 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(); - - // Log the operation - if (numRows > 0) { - ActivityLogger.getInstance().logInsert("productSupplier", - String.format("ProdID:%d-SupID:%d", productSupplier.getProdId(), productSupplier.getSupId()), - String.format("Product-Supplier relation added for Product ID %d, Supplier ID %d", productSupplier.getProdId(), productSupplier.getSupId())); - } - - 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(); - - // Log the operation - if (numRows > 0) { - ActivityLogger.getInstance().logUpdate("productSupplier", - String.format("ProdID:%d-SupID:%d", productSupplier.getProdId(), productSupplier.getSupId()), - String.format("Product-Supplier relation updated from ProdID:%d-SupID:%d to ProdID:%d-SupID:%d", oldProdId, oldSupId, productSupplier.getProdId(), productSupplier.getSupId())); - } - } - 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(); - - // Log the operation - if (numRows > 0) { - ActivityLogger.getInstance().logDelete("productSupplier", - String.format("ProdID:%d-SupID:%d", prodId, supId), - String.format("Product-Supplier relation deleted for Product ID %d, Supplier ID %d", prodId, supId)); - } - - return numRows; - } -} diff --git a/src/main/java/org/example/petshopdesktop/database/PurchaseOrderDB.java b/src/main/java/org/example/petshopdesktop/database/PurchaseOrderDB.java deleted file mode 100644 index 2dea4de4..00000000 --- a/src/main/java/org/example/petshopdesktop/database/PurchaseOrderDB.java +++ /dev/null @@ -1,45 +0,0 @@ -package org.example.petshopdesktop.database; - -import javafx.collections.FXCollections; -import javafx.collections.ObservableList; -import org.example.petshopdesktop.DTOs.PurchaseOrderDTO; - -import java.sql.*; - -public class PurchaseOrderDB { - - public static ObservableList getPurchaseOrders() - throws SQLException { - - ObservableList list = - FXCollections.observableArrayList(); - - Connection conn = ConnectionDB.getConnection(); - - String sql = """ - SELECT po.purchaseOrderId, - s.supCompany, - po.orderDate, - po.status - FROM purchaseOrder po - JOIN supplier s ON po.supId = s.supId - ORDER BY po.purchaseOrderId - """; - - Statement stmt = conn.createStatement(); - ResultSet rs = stmt.executeQuery(sql); - - while (rs.next()) { - - list.add(new PurchaseOrderDTO( - rs.getInt("purchaseOrderId"), - rs.getString("supCompany"), - rs.getString("orderDate"), - rs.getString("status") - )); - } - - conn.close(); - return list; - } -} \ No newline at end of file diff --git a/src/main/java/org/example/petshopdesktop/database/SaleDB.java b/src/main/java/org/example/petshopdesktop/database/SaleDB.java deleted file mode 100644 index 0fe0f30f..00000000 --- a/src/main/java/org/example/petshopdesktop/database/SaleDB.java +++ /dev/null @@ -1,572 +0,0 @@ -package org.example.petshopdesktop.database; - -import javafx.collections.FXCollections; -import javafx.collections.ObservableList; -import org.example.petshopdesktop.DTOs.SaleDTO; -import org.example.petshopdesktop.models.SaleCartItem; -import org.example.petshopdesktop.models.SaleDetail; -import org.example.petshopdesktop.models.SaleLineItem; -import org.example.petshopdesktop.models.analytics.*; -import org.example.petshopdesktop.util.ActivityLogger; - -import java.sql.*; -import java.time.LocalDate; - -public class SaleDB { - - /** - * Get all sale items with details - * @return ObservableList of SaleDTOs - * @throws SQLException if database operation fails - */ - public static ObservableList getSales() throws SQLException { - ObservableList sales = FXCollections.observableArrayList(); - Connection conn = ConnectionDB.getConnection(); - - String sql = """ - SELECT - s.saleId, - DATE_FORMAT(s.saleDate, '%Y-%m-%d %H:%i') as saleDate, - CONCAT(e.firstName, ' ', e.lastName) as employeeName, - p.prodName, - si.quantity, - si.unitPrice, - (si.quantity * si.unitPrice) as lineTotal, - s.paymentMethod - FROM sale s - JOIN saleItem si ON s.saleId = si.saleId - JOIN product p ON si.prodId = p.prodId - JOIN employee e ON s.employeeId = e.employeeId - ORDER BY s.saleDate DESC, s.saleId, si.saleItemId - """; - - Statement stmt = conn.createStatement(); - ResultSet rs = stmt.executeQuery(sql); - - while (rs.next()) { - sales.add(new SaleDTO( - rs.getInt("saleId"), - rs.getString("saleDate"), - rs.getString("employeeName"), - rs.getString("prodName"), - rs.getInt("quantity"), - rs.getDouble("unitPrice"), - rs.getDouble("lineTotal"), - rs.getString("paymentMethod") - )); - } - - conn.close(); - return sales; - } - - /** - * Get filtered sale items - * @param filter search term - * @return ObservableList of SaleDTOs matching the filter - * @throws SQLException if database operation fails - */ - public static ObservableList getFilteredSales(String filter) throws SQLException { - ObservableList sales = FXCollections.observableArrayList(); - Connection conn = ConnectionDB.getConnection(); - - String sql = """ - SELECT - s.saleId, - DATE_FORMAT(s.saleDate, '%Y-%m-%d %H:%i') as saleDate, - CONCAT(e.firstName, ' ', e.lastName) as employeeName, - p.prodName, - si.quantity, - si.unitPrice, - (si.quantity * si.unitPrice) as lineTotal, - s.paymentMethod - FROM sale s - JOIN saleItem si ON s.saleId = si.saleId - JOIN product p ON si.prodId = p.prodId - JOIN employee e ON s.employeeId = e.employeeId - WHERE s.saleId LIKE ? - OR p.prodName LIKE ? - OR CONCAT(e.firstName, ' ', e.lastName) LIKE ? - OR s.paymentMethod LIKE ? - ORDER BY s.saleDate DESC, s.saleId, si.saleItemId - """; - - PreparedStatement pstmt = conn.prepareStatement(sql); - String searchPattern = "%" + filter + "%"; - pstmt.setString(1, searchPattern); - pstmt.setString(2, searchPattern); - pstmt.setString(3, searchPattern); - pstmt.setString(4, searchPattern); - - ResultSet rs = pstmt.executeQuery(); - - while (rs.next()) { - sales.add(new SaleDTO( - rs.getInt("saleId"), - rs.getString("saleDate"), - rs.getString("employeeName"), - rs.getString("prodName"), - rs.getInt("quantity"), - rs.getDouble("unitPrice"), - rs.getDouble("lineTotal"), - rs.getString("paymentMethod") - )); - } - - conn.close(); - return sales; - } - - public static ObservableList getSaleLineItems() throws SQLException { - ObservableList saleItems = FXCollections.observableArrayList(); - Connection conn = ConnectionDB.getConnection(); - - String sql = """ - SELECT - s.saleId, - DATE_FORMAT(s.saleDate, '%Y-%m-%d %H:%i') as saleDate, - CONCAT(e.firstName, ' ', e.lastName) as employeeName, - p.prodName, - si.quantity, - si.unitPrice, - (si.quantity * si.unitPrice) as total, - s.paymentMethod, - s.isRefund - FROM sale s - JOIN saleItem si ON s.saleId = si.saleId - JOIN product p ON si.prodId = p.prodId - JOIN employee e ON s.employeeId = e.employeeId - ORDER BY s.saleDate DESC, s.saleId, si.saleItemId - """; - - Statement stmt = conn.createStatement(); - ResultSet rs = stmt.executeQuery(sql); - - while (rs.next()) { - saleItems.add(new SaleLineItem( - rs.getInt("saleId"), - rs.getString("saleDate"), - rs.getString("employeeName"), - rs.getString("prodName"), - rs.getInt("quantity"), - rs.getDouble("unitPrice"), - rs.getDouble("total"), - rs.getString("paymentMethod"), - rs.getBoolean("isRefund") - )); - } - - conn.close(); - return saleItems; - } - - public static int createSale(int employeeId, String paymentMethod, ObservableList cartItems) throws SQLException { - if (cartItems.isEmpty()) { - throw new SQLException("Cannot create sale with empty cart"); - } - - Connection conn = ConnectionDB.getConnection(); - conn.setAutoCommit(false); - - try { - double totalAmount = cartItems.stream().mapToDouble(SaleCartItem::getTotal).sum(); - - String insertSale = """ - INSERT INTO sale (saleDate, totalAmount, paymentMethod, employeeId, storeId) - VALUES (NOW(), ?, ?, ?, 1) - """; - - PreparedStatement saleStmt = conn.prepareStatement(insertSale, Statement.RETURN_GENERATED_KEYS); - saleStmt.setDouble(1, totalAmount); - saleStmt.setString(2, paymentMethod); - saleStmt.setInt(3, employeeId); - saleStmt.executeUpdate(); - - ResultSet rs = saleStmt.getGeneratedKeys(); - if (!rs.next()) { - throw new SQLException("Failed to get generated sale ID"); - } - int saleId = rs.getInt(1); - - String insertItem = """ - INSERT INTO saleItem (saleId, prodId, quantity, unitPrice) - VALUES (?, ?, ?, ?) - """; - - String updateInventory = """ - UPDATE inventory - SET quantity = quantity - ? - WHERE prodId = ? - """; - - PreparedStatement itemStmt = conn.prepareStatement(insertItem); - PreparedStatement invStmt = conn.prepareStatement(updateInventory); - - for (SaleCartItem item : cartItems) { - itemStmt.setInt(1, saleId); - itemStmt.setInt(2, item.getProdId()); - itemStmt.setInt(3, item.getQuantity()); - itemStmt.setDouble(4, item.getUnitPrice()); - itemStmt.executeUpdate(); - - invStmt.setInt(1, item.getQuantity()); - invStmt.setInt(2, item.getProdId()); - int updated = invStmt.executeUpdate(); - - if (updated == 0) { - throw new SQLException("Failed to update inventory for product ID " + item.getProdId()); - } - } - - conn.commit(); - - ActivityLogger.getInstance().logInsert("sale", - String.format("Sale ID: %d", saleId), - String.format("Created sale with %d items, total: $%.2f", cartItems.size(), totalAmount)); - - return saleId; - - } catch (SQLException e) { - conn.rollback(); - ActivityLogger.getInstance().logException("SaleDB.createSale", e, "Creating sale"); - throw e; - } finally { - conn.setAutoCommit(true); - conn.close(); - } - } - - public static ObservableList getDailySalesRevenue() throws SQLException { - ObservableList dailySales = FXCollections.observableArrayList(); - Connection conn = ConnectionDB.getConnection(); - - String sql = """ - SELECT DATE(s.saleDate) as saleDate, SUM(s.totalAmount) as revenue - FROM sale s - GROUP BY DATE(s.saleDate) - ORDER BY saleDate ASC - """; - - Statement stmt = conn.createStatement(); - ResultSet rs = stmt.executeQuery(sql); - - while (rs.next()) { - LocalDate date = rs.getDate("saleDate").toLocalDate(); - double revenue = rs.getDouble("revenue"); - dailySales.add(new DailySalesData(date, revenue)); - } - - conn.close(); - return dailySales; - } - - public static ObservableList getTopProductsByRevenue(int limit) throws SQLException { - ObservableList products = FXCollections.observableArrayList(); - Connection conn = ConnectionDB.getConnection(); - - String sql = """ - SELECT p.prodName, SUM(si.quantity * si.unitPrice) as totalRevenue - FROM saleItem si - JOIN product p ON si.prodId = p.prodId - GROUP BY p.prodId, p.prodName - ORDER BY totalRevenue DESC - LIMIT ? - """; - - PreparedStatement pstmt = conn.prepareStatement(sql); - pstmt.setInt(1, limit); - ResultSet rs = pstmt.executeQuery(); - - while (rs.next()) { - String productName = rs.getString("prodName"); - double totalRevenue = rs.getDouble("totalRevenue"); - products.add(new ProductSalesData(productName, 0, totalRevenue)); - } - - conn.close(); - return products; - } - - public static ObservableList getTopProductsByQuantity(int limit) throws SQLException { - ObservableList products = FXCollections.observableArrayList(); - Connection conn = ConnectionDB.getConnection(); - - String sql = """ - SELECT p.prodName, SUM(si.quantity) as totalQuantity, - SUM(si.quantity * si.unitPrice) as totalRevenue - FROM saleItem si - JOIN product p ON si.prodId = p.prodId - GROUP BY p.prodId, p.prodName - ORDER BY totalQuantity DESC - LIMIT ? - """; - - PreparedStatement pstmt = conn.prepareStatement(sql); - pstmt.setInt(1, limit); - ResultSet rs = pstmt.executeQuery(); - - while (rs.next()) { - String productName = rs.getString("prodName"); - int totalQuantity = rs.getInt("totalQuantity"); - double totalRevenue = rs.getDouble("totalRevenue"); - products.add(new ProductSalesData(productName, totalQuantity, totalRevenue)); - } - - conn.close(); - return products; - } - - public static ObservableList getPaymentMethodDistribution() throws SQLException { - ObservableList paymentMethods = FXCollections.observableArrayList(); - Connection conn = ConnectionDB.getConnection(); - - String sql = """ - SELECT s.paymentMethod, COUNT(*) as transactionCount, - SUM(s.totalAmount) as totalRevenue - FROM sale s - GROUP BY s.paymentMethod - ORDER BY totalRevenue DESC - """; - - Statement stmt = conn.createStatement(); - ResultSet rs = stmt.executeQuery(sql); - - while (rs.next()) { - String paymentMethod = rs.getString("paymentMethod"); - int transactionCount = rs.getInt("transactionCount"); - double totalRevenue = rs.getDouble("totalRevenue"); - paymentMethods.add(new PaymentMethodData(paymentMethod, transactionCount, totalRevenue)); - } - - conn.close(); - return paymentMethods; - } - - public static ObservableList getEmployeeSalesPerformance() throws SQLException { - ObservableList employees = FXCollections.observableArrayList(); - Connection conn = ConnectionDB.getConnection(); - - String sql = """ - SELECT CONCAT(e.firstName, ' ', e.lastName) as employeeName, - COUNT(DISTINCT s.saleId) as transactionCount, - SUM(s.totalAmount) as totalRevenue, - COALESCE(SUM(si.quantity), 0) as totalItemsSold - FROM sale s - JOIN employee e ON s.employeeId = e.employeeId - LEFT JOIN saleItem si ON s.saleId = si.saleId - GROUP BY e.employeeId, e.firstName, e.lastName - ORDER BY totalRevenue DESC - """; - - Statement stmt = conn.createStatement(); - ResultSet rs = stmt.executeQuery(sql); - - while (rs.next()) { - String employeeName = rs.getString("employeeName"); - int transactionCount = rs.getInt("transactionCount"); - double totalRevenue = rs.getDouble("totalRevenue"); - int totalItemsSold = rs.getInt("totalItemsSold"); - employees.add(new EmployeeSalesData(employeeName, transactionCount, totalRevenue, totalItemsSold)); - } - - conn.close(); - return employees; - } - - public static SalesSummary getSalesSummary() throws SQLException { - Connection conn = ConnectionDB.getConnection(); - - String sql = """ - SELECT COUNT(DISTINCT s.saleId) as totalTransactions, - COALESCE(SUM(s.totalAmount), 0) as totalRevenue, - COALESCE(AVG(s.totalAmount), 0) as avgTransactionValue, - COALESCE(SUM(si.quantity), 0) as totalItemsSold - FROM sale s - LEFT JOIN saleItem si ON s.saleId = si.saleId - """; - - Statement stmt = conn.createStatement(); - ResultSet rs = stmt.executeQuery(sql); - - SalesSummary summary = null; - if (rs.next()) { - int totalTransactions = rs.getInt("totalTransactions"); - double totalRevenue = rs.getDouble("totalRevenue"); - double avgTransactionValue = rs.getDouble("avgTransactionValue"); - int totalItemsSold = rs.getInt("totalItemsSold"); - summary = new SalesSummary(totalTransactions, totalRevenue, avgTransactionValue, totalItemsSold); - } - - conn.close(); - return summary; - } - - public static SaleDetail getSaleById(int saleId) throws SQLException { - Connection conn = ConnectionDB.getConnection(); - - String saleSql = """ - SELECT s.saleId, s.saleDate, s.totalAmount, s.paymentMethod, - CONCAT(e.firstName, ' ', e.lastName) as employeeName, - s.isRefund - FROM sale s - JOIN employee e ON s.employeeId = e.employeeId - WHERE s.saleId = ? - """; - - PreparedStatement saleStmt = conn.prepareStatement(saleSql); - saleStmt.setInt(1, saleId); - ResultSet saleRs = saleStmt.executeQuery(); - - if (!saleRs.next()) { - conn.close(); - throw new SQLException("Sale not found with ID: " + saleId); - } - - boolean isRefund = saleRs.getBoolean("isRefund"); - if (isRefund) { - conn.close(); - throw new SQLException("Cannot refund a refund transaction"); - } - - SaleDetail detail = new SaleDetail( - saleRs.getInt("saleId"), - saleRs.getTimestamp("saleDate").toLocalDateTime(), - saleRs.getDouble("totalAmount"), - saleRs.getString("paymentMethod"), - saleRs.getString("employeeName"), - FXCollections.observableArrayList() - ); - - String itemsSql = """ - SELECT si.prodId, p.prodName, si.quantity, si.unitPrice, - (si.quantity * si.unitPrice) as total - FROM saleItem si - JOIN product p ON si.prodId = p.prodId - WHERE si.saleId = ? - """; - - PreparedStatement itemsStmt = conn.prepareStatement(itemsSql); - itemsStmt.setInt(1, saleId); - ResultSet itemsRs = itemsStmt.executeQuery(); - - while (itemsRs.next()) { - detail.getItems().add(new SaleDetail.SaleDetailItem( - itemsRs.getInt("prodId"), - itemsRs.getString("prodName"), - itemsRs.getInt("quantity"), - itemsRs.getDouble("unitPrice"), - itemsRs.getDouble("total") - )); - } - - conn.close(); - return detail; - } - - public static boolean isRefunded(int saleId) throws SQLException { - Connection conn = ConnectionDB.getConnection(); - - String sql = """ - SELECT COUNT(*) as refundCount - FROM sale - WHERE originalSaleId = ? AND isRefund = TRUE - """; - - PreparedStatement pstmt = conn.prepareStatement(sql); - pstmt.setInt(1, saleId); - ResultSet rs = pstmt.executeQuery(); - - boolean refunded = false; - if (rs.next()) { - refunded = rs.getInt("refundCount") > 0; - } - - conn.close(); - return refunded; - } - - public static int createRefund(int originalSaleId, int employeeId, String paymentMethod, ObservableList refundItems) throws SQLException { - if (refundItems.isEmpty()) { - throw new SQLException("Cannot create refund with empty items"); - } - - Connection conn = ConnectionDB.getConnection(); - - SaleDetail originalSale = getSaleById(originalSaleId); - conn = ConnectionDB.getConnection(); - - if (isRefunded(originalSaleId)) { - throw new SQLException("This sale has already been refunded"); - } - - conn.setAutoCommit(false); - - try { - double totalAmount = -refundItems.stream().mapToDouble(SaleCartItem::getTotal).sum(); - - String insertSale = """ - INSERT INTO sale (saleDate, totalAmount, paymentMethod, employeeId, storeId, isRefund, originalSaleId) - VALUES (NOW(), ?, ?, ?, 1, TRUE, ?) - """; - - PreparedStatement saleStmt = conn.prepareStatement(insertSale, Statement.RETURN_GENERATED_KEYS); - saleStmt.setDouble(1, totalAmount); - saleStmt.setString(2, paymentMethod); - saleStmt.setInt(3, employeeId); - saleStmt.setInt(4, originalSaleId); - saleStmt.executeUpdate(); - - ResultSet rs = saleStmt.getGeneratedKeys(); - if (!rs.next()) { - throw new SQLException("Failed to get generated refund ID"); - } - int refundId = rs.getInt(1); - - String insertItem = """ - INSERT INTO saleItem (saleId, prodId, quantity, unitPrice) - VALUES (?, ?, ?, ?) - """; - - String updateInventory = """ - UPDATE inventory - SET quantity = quantity + ? - WHERE prodId = ? - """; - - PreparedStatement itemStmt = conn.prepareStatement(insertItem); - PreparedStatement invStmt = conn.prepareStatement(updateInventory); - - for (SaleCartItem item : refundItems) { - itemStmt.setInt(1, refundId); - itemStmt.setInt(2, item.getProdId()); - itemStmt.setInt(3, -item.getQuantity()); - itemStmt.setDouble(4, item.getUnitPrice()); - itemStmt.executeUpdate(); - - invStmt.setInt(1, item.getQuantity()); - invStmt.setInt(2, item.getProdId()); - int updated = invStmt.executeUpdate(); - - if (updated == 0) { - throw new SQLException("Failed to update inventory for product ID " + item.getProdId()); - } - } - - conn.commit(); - - ActivityLogger.getInstance().logInsert("sale", - String.format("Refund ID: %d", refundId), - String.format("Created refund for sale ID %d with %d items, total: $%.2f", originalSaleId, refundItems.size(), Math.abs(totalAmount))); - - return refundId; - - } catch (SQLException e) { - conn.rollback(); - ActivityLogger.getInstance().logException("SaleDB.createRefund", e, "Creating refund"); - throw e; - } finally { - conn.setAutoCommit(true); - conn.close(); - } - } -} diff --git a/src/main/java/org/example/petshopdesktop/database/ServiceDB.java b/src/main/java/org/example/petshopdesktop/database/ServiceDB.java deleted file mode 100644 index efa629cc..00000000 --- a/src/main/java/org/example/petshopdesktop/database/ServiceDB.java +++ /dev/null @@ -1,129 +0,0 @@ -package org.example.petshopdesktop.database; - -import javafx.collections.FXCollections; -import javafx.collections.ObservableList; -import org.example.petshopdesktop.models.Service; -import org.example.petshopdesktop.util.ActivityLogger; - -import java.sql.*; - -public class ServiceDB { - - // - // GET ALL SERVICES - // - public static ObservableList getServices() throws SQLException { - - ObservableList list = FXCollections.observableArrayList(); - Connection conn = ConnectionDB.getConnection(); - - String sql = "SELECT * FROM service"; - Statement stmt = conn.createStatement(); - ResultSet rs = stmt.executeQuery(sql); - - while (rs.next()) { - - Service service = new Service( - rs.getInt("serviceId"), - rs.getString("serviceName"), - rs.getString("serviceDesc"), - rs.getInt("serviceDuration"), - rs.getDouble("servicePrice") - ); - - list.add(service); - } - - conn.close(); - return list; - } - - // - // INSERT SERVICE - // - public static int insertService(Service service) throws SQLException { - - Connection conn = ConnectionDB.getConnection(); - - String sql = - "INSERT INTO service (serviceName, serviceDesc, serviceDuration, servicePrice) " + - "VALUES (?, ?, ?, ?)"; - - PreparedStatement stmt = conn.prepareStatement(sql); - - stmt.setString(1, service.getServiceName()); - stmt.setString(2, service.getServiceDesc()); - stmt.setInt(3, service.getServiceDuration()); - stmt.setDouble(4, service.getServicePrice()); - - int rows = stmt.executeUpdate(); - conn.close(); - - // Log the operation - if (rows > 0) { - ActivityLogger.getInstance().logInsert("service", - "N/A", - String.format("Service '%s' added", service.getServiceName())); - } - - return rows; - } - - // - // UPDATE SERVICE - // - public static int updateService(int id, Service service) throws SQLException { - - Connection conn = ConnectionDB.getConnection(); - - String sql = - "UPDATE service SET " + - "serviceName=?, serviceDesc=?, serviceDuration=?, servicePrice=? " + - "WHERE serviceId=?"; - - PreparedStatement stmt = conn.prepareStatement(sql); - - stmt.setString(1, service.getServiceName()); - stmt.setString(2, service.getServiceDesc()); - stmt.setInt(3, service.getServiceDuration()); - stmt.setDouble(4, service.getServicePrice()); - stmt.setInt(5, id); - - int rows = stmt.executeUpdate(); - conn.close(); - - // Log the operation - if (rows > 0) { - ActivityLogger.getInstance().logUpdate("service", - String.valueOf(id), - String.format("Service '%s' updated", service.getServiceName())); - } - - return rows; - } - - // - // DELETE SERVICE - // - public static int deleteService(int id) throws SQLException { - - Connection conn = ConnectionDB.getConnection(); - - String sql = "DELETE FROM service WHERE serviceId=?"; - - PreparedStatement stmt = conn.prepareStatement(sql); - stmt.setInt(1, id); - - int rows = stmt.executeUpdate(); - conn.close(); - - // Log the operation - if (rows > 0) { - ActivityLogger.getInstance().logDelete("service", - String.valueOf(id), - String.format("Service ID %d deleted", id)); - } - - return rows; - } -} \ No newline at end of file diff --git a/src/main/java/org/example/petshopdesktop/database/SupplierDB.java b/src/main/java/org/example/petshopdesktop/database/SupplierDB.java deleted file mode 100644 index 2d03cde4..00000000 --- a/src/main/java/org/example/petshopdesktop/database/SupplierDB.java +++ /dev/null @@ -1,202 +0,0 @@ -package org.example.petshopdesktop.database; - -import javafx.collections.FXCollections; -import javafx.collections.ObservableList; -import org.example.petshopdesktop.models.Product; -import org.example.petshopdesktop.models.Supplier; -import org.example.petshopdesktop.util.ActivityLogger; - -import java.sql.*; - -/** - * A class containing all the methods relating to CRUD on Suppliers table - */ -public class SupplierDB { - - /** - * gets all the suppliers into an observable list - * @return a list of all the suppliers - * @throws SQLException if failed to find suppliers in the database - */ - public static ObservableList getSuppliers() throws SQLException { - //Connect to the database - ObservableList suppliers = FXCollections.observableArrayList(); - Connection conn = ConnectionDB.getConnection(); - - //Execute Query - Statement stmt = conn.createStatement(); - ResultSet rs = stmt.executeQuery("SELECT * FROM supplier"); - - //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; - } - - /** - * Inserts a new supplier to the database - * @param supplier supplier entity to be inserted - * @return number of rows affected in the database - * @throws SQLException if insertion failed - */ - public static int insertSupplier(Supplier supplier) throws SQLException { - int numRows = 0; - - Connection conn = ConnectionDB.getConnection(); - String sql = "INSERT INTO supplier (supId, supCompany, supContactFirstName, supContactLastName, supEmail, supPhone)" + - "VALUES (?, ?, ?, ?, ?, ?)"; - - //These are the values from supplier to put into the query above - PreparedStatement stmt = conn.prepareStatement(sql); - stmt.setInt(1, supplier.getSupId()); - stmt.setString(2, supplier.getSupCompany()); - stmt.setString(3, supplier.getSupContactFirstName()); - stmt.setString(4, supplier.getSupContactLastName()); - stmt.setString(5, supplier.getSupEmail()); - stmt.setString(6, supplier.getSupPhone()); - - //update the number of rows affected, return and close connection - numRows = stmt.executeUpdate(); - conn.close(); - - // Log the operation - if (numRows > 0) { - ActivityLogger.getInstance().logInsert("supplier", - String.valueOf(supplier.getSupId()), - String.format("Supplier '%s' added", supplier.getSupCompany())); - } - - return numRows; - } - - /** - * Update an existing supplier to the database - * @param supId id of supplier - * @param supplier new supplier data - * @return number of rows affected in the database - * @throws SQLException if update failed - */ - public static int updateSupplier(int supId, Supplier supplier) throws SQLException { - int numRows = 0; - - Connection conn = ConnectionDB.getConnection(); - String sql = "UPDATE supplier SET " + - " supCompany = ?, " + - " supContactFirstName = ?, " + - " supContactLastName = ?, " + - " supEmail = ?, " + - " supPhone = ? " + - " WHERE supId = ?"; - - //updated values to update the supplier with the query above - PreparedStatement stmt = conn.prepareStatement(sql); - stmt.setString(1, supplier.getSupCompany()); - stmt.setString(2, supplier.getSupContactFirstName()); - stmt.setString(3, supplier.getSupContactLastName()); - stmt.setString(4, supplier.getSupEmail()); - stmt.setString(5, supplier.getSupPhone()); - stmt.setInt(6, supId); - - //Update the rows and close connection - numRows = stmt.executeUpdate(); - conn.close(); - - // Log the operation - if (numRows > 0) { - ActivityLogger.getInstance().logUpdate("supplier", - String.valueOf(supId), - String.format("Supplier '%s' updated", supplier.getSupCompany())); - } - - return numRows; - } - - /** - * Delete a supplier form the database - * @param supId supplier id to be deleted - * @return number of rows affected in the database - * @throws SQLException if delete failed - */ - public static int deleteSupplier(int supId) throws SQLException { - int numRows = 0; - Connection conn = ConnectionDB.getConnection(); - - String sql = "DELETE FROM supplier WHERE supId = ?"; - PreparedStatement stmt = conn.prepareStatement(sql); - //The supplier id to be deleted for the query above - stmt.setInt(1, supId); - - //close connection and update rows affected - numRows = stmt.executeUpdate(); - conn.close(); - - // Log the operation - if (numRows > 0) { - ActivityLogger.getInstance().logDelete("supplier", - String.valueOf(supId), - String.format("Supplier ID %d deleted", supId)); - } - - 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 getFilteredSuppliers(String filter) throws SQLException { - //Connect to the database - ObservableList 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; - } -} diff --git a/src/main/java/org/example/petshopdesktop/database/UserDB.java b/src/main/java/org/example/petshopdesktop/database/UserDB.java deleted file mode 100644 index ca4d8a78..00000000 --- a/src/main/java/org/example/petshopdesktop/database/UserDB.java +++ /dev/null @@ -1,198 +0,0 @@ -package org.example.petshopdesktop.database; - -import org.example.petshopdesktop.auth.Role; -import org.example.petshopdesktop.models.StaffAccount; -import org.example.petshopdesktop.models.User; -import org.example.petshopdesktop.util.ActivityLogger; - -import java.sql.Connection; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.sql.Statement; -import java.util.ArrayList; -import java.util.List; - -public class UserDB { - - public static User authenticate(String username, String password) throws SQLException { - String sql = "SELECT u.user_id, u.employee_id, u.username, u.role, e.firstName, e.lastName " - + "FROM users u " - + "JOIN employee e ON u.employee_id = e.employeeId " - + "WHERE u.username = ? AND u.password_hash = SHA2(?, 256) AND e.isActive = TRUE"; - - try (Connection conn = ConnectionDB.getConnection(); - PreparedStatement ps = conn.prepareStatement(sql)) { - - ps.setString(1, username); - ps.setString(2, password); - - try (ResultSet rs = ps.executeQuery()) { - if (rs.next()) { - int userId = rs.getInt("user_id"); - int employeeId = rs.getInt("employee_id"); - String uname = rs.getString("username"); - Role role = Role.valueOf(rs.getString("role").toUpperCase()); - String firstName = rs.getString("firstName"); - String lastName = rs.getString("lastName"); - - return new User(userId, employeeId, uname, firstName, lastName, role); - } - } - } - - return null; - } - - public static void initializeTable() throws SQLException { - String createTable = """ - CREATE TABLE IF NOT EXISTS users ( - user_id INT AUTO_INCREMENT PRIMARY KEY, - employee_id INT NOT NULL, - username VARCHAR(100) NOT NULL UNIQUE, - password_hash CHAR(64) NOT NULL, - role ENUM('ADMIN','STAFF') NOT NULL, - created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL, - FOREIGN KEY (employee_id) REFERENCES employee(employeeId) - ) - """; - - try (Connection conn = ConnectionDB.getConnection(); - Statement st = conn.createStatement()) { - st.executeUpdate(createTable); - } - - ensureCompatibleSchema(); - - int adminEmployeeId = EmployeeDB.ensureDefaultEmployee("John", "Doe", "john@petshop.com", "111-222-3333", "Manager", true); - int staffEmployeeId = EmployeeDB.ensureDefaultEmployee("Sara", "Smith", "sara@petshop.com", "444-555-6666", "Staff", true); - - ensureDefaultUser(adminEmployeeId, "admin", "admin123", Role.ADMIN); - ensureDefaultUser(staffEmployeeId, "staff", "staff123", Role.STAFF); - } - - public static int createStaffAccount(String firstName, String lastName, String email, String phone, String username, String password) throws SQLException { - if (username == null || username.isBlank()) { - throw new SQLException("Username is required."); - } - if (password == null || password.isBlank()) { - throw new SQLException("Password is required."); - } - - int storeId = EmployeeDB.getDefaultStoreId(); - - try (Connection conn = ConnectionDB.getConnection()) { - conn.setAutoCommit(false); - try { - int employeeId = EmployeeDB.createEmployee(conn, firstName, lastName, email, phone, "Staff", true); - EmployeeDB.assignEmployeeToStore(conn, employeeId, storeId); - - String insertUser = "INSERT INTO users (employee_id, username, password_hash, role) VALUES (?, ?, SHA2(?, 256), 'STAFF')"; - try (PreparedStatement ps = conn.prepareStatement(insertUser, Statement.RETURN_GENERATED_KEYS)) { - ps.setInt(1, employeeId); - ps.setString(2, username); - ps.setString(3, password); - ps.executeUpdate(); - - try (ResultSet keys = ps.getGeneratedKeys()) { - if (keys.next()) { - int userId = keys.getInt(1); - conn.commit(); - ActivityLogger.getInstance().logInsert("users", String.valueOf(userId), "Created staff account: " + username); - return userId; - } - } - } - - conn.rollback(); - throw new SQLException("Could not create staff account."); - } catch (SQLException e) { - conn.rollback(); - throw e; - } catch (RuntimeException e) { - conn.rollback(); - throw e; - } finally { - conn.setAutoCommit(true); - } - } - } - - public static List getStaffAccounts() throws SQLException { - String sql = "SELECT u.user_id, u.username, u.created_at, e.employeeId, e.firstName, e.lastName, e.email, e.phone, e.isActive " - + "FROM users u " - + "JOIN employee e ON u.employee_id = e.employeeId " - + "WHERE u.role = 'STAFF' " - + "ORDER BY u.created_at DESC"; - - List accounts = new ArrayList<>(); - - try (Connection conn = ConnectionDB.getConnection(); - PreparedStatement ps = conn.prepareStatement(sql); - ResultSet rs = ps.executeQuery()) { - - while (rs.next()) { - accounts.add(new StaffAccount( - rs.getInt("user_id"), - rs.getInt("employeeId"), - rs.getString("username"), - rs.getString("firstName"), - rs.getString("lastName"), - rs.getString("email"), - rs.getString("phone"), - rs.getBoolean("isActive"), - rs.getTimestamp("created_at") - )); - } - } - - return accounts; - } - - private static void ensureCompatibleSchema() throws SQLException { - try (Connection conn = ConnectionDB.getConnection(); - Statement st = conn.createStatement()) { - - try { - st.executeUpdate("ALTER TABLE users ADD COLUMN employee_id INT NULL"); - } catch (SQLException ignored) { - } - - try { - st.executeUpdate("ALTER TABLE users ADD COLUMN created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL"); - } catch (SQLException ignored) { - } - - try { - st.executeUpdate("ALTER TABLE users ADD CONSTRAINT fk_users_employee FOREIGN KEY (employee_id) REFERENCES employee(employeeId)"); - } catch (SQLException ignored) { - } - } - } - - private static void ensureDefaultUser(int employeeId, String username, String password, Role role) throws SQLException { - String insert = "INSERT IGNORE INTO users (employee_id, username, password_hash, role) VALUES (?, ?, SHA2(?, 256), ?)"; - String updateIfMissingEmployeeId = "UPDATE users SET employee_id = ? WHERE username = ? AND (employee_id IS NULL OR employee_id = 0)"; - - try (Connection conn = ConnectionDB.getConnection()) { - int rows; - try (PreparedStatement ps = conn.prepareStatement(insert)) { - ps.setInt(1, employeeId); - ps.setString(2, username); - ps.setString(3, password); - ps.setString(4, role.name()); - rows = ps.executeUpdate(); - } - - try (PreparedStatement ps = conn.prepareStatement(updateIfMissingEmployeeId)) { - ps.setInt(1, employeeId); - ps.setString(2, username); - ps.executeUpdate(); - } - - if (rows > 0) { - ActivityLogger.getInstance().logInsert("users", username, "Default " + role.name().toLowerCase() + " user created"); - } - } - } -}