Remove database package and references
This commit is contained in:
@@ -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
|
||||
api.baseUrl=http://localhost:8080
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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<Adoption> getAdoptions() throws SQLException {
|
||||
ObservableList<Adoption> adoptions = FXCollections.observableArrayList();
|
||||
Connection conn = ConnectionDB.getConnection();
|
||||
|
||||
Statement stmt = conn.createStatement();
|
||||
ResultSet rs = stmt.executeQuery(BASE_SELECT);
|
||||
|
||||
//Map results
|
||||
while (rs.next()) {
|
||||
adoptions.add(mapRow(rs));
|
||||
}
|
||||
|
||||
conn.close();
|
||||
return adoptions;
|
||||
}
|
||||
|
||||
//Returns data depending on search query
|
||||
public static ObservableList<Adoption> getFilteredAdoptions(String filter) throws SQLException {
|
||||
ObservableList<Adoption> adoptions = FXCollections.observableArrayList();
|
||||
Connection conn = ConnectionDB.getConnection();
|
||||
|
||||
String sql = BASE_SELECT +
|
||||
" WHERE a.adoptionId LIKE '%" + filter + "%' OR " +
|
||||
"a.petId LIKE '%" + filter + "%' OR " +
|
||||
"CONCAT(c.firstName, ' ', c.lastName) LIKE '%" + filter + "%' OR " +
|
||||
"a.adoptionDate LIKE '%" + filter + "%' OR " +
|
||||
"p.petPrice LIKE '%" + filter + "%' OR " +
|
||||
"a.adoptionStatus LIKE '%" + filter + "%'";
|
||||
|
||||
Statement stmt = conn.createStatement();
|
||||
ResultSet rs = stmt.executeQuery(sql);
|
||||
|
||||
//Map results
|
||||
while (rs.next()) {
|
||||
adoptions.add(mapRow(rs));
|
||||
}
|
||||
|
||||
conn.close();
|
||||
return adoptions;
|
||||
}
|
||||
|
||||
//Add new adoption
|
||||
public static int insertAdoption(Adoption adoption) throws SQLException {
|
||||
Connection conn = ConnectionDB.getConnection();
|
||||
String sql = "INSERT INTO adoption (petId, customerId, adoptionDate, adoptionStatus) VALUES (?, ?, ?, ?)";
|
||||
|
||||
PreparedStatement stmt = conn.prepareStatement(sql);
|
||||
|
||||
//Put data in Adoption object
|
||||
stmt.setInt(1, adoption.getPetId());
|
||||
stmt.setInt(2, adoption.getCustomerId());
|
||||
stmt.setString(3, adoption.getAdoptionDate());
|
||||
stmt.setString(4, adoption.getAdoptionStatus());
|
||||
|
||||
int numRows = stmt.executeUpdate();
|
||||
conn.close();
|
||||
|
||||
// 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<Customer> getCustomers() throws SQLException {
|
||||
ObservableList<Customer> customers = FXCollections.observableArrayList();
|
||||
Connection conn = ConnectionDB.getConnection();
|
||||
|
||||
Statement stmt = conn.createStatement();
|
||||
ResultSet rs = stmt.executeQuery("SELECT customerId, firstName, lastName, 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")
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -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<AppointmentDTO> getAppointmentDTOs()
|
||||
throws SQLException {
|
||||
|
||||
ObservableList<AppointmentDTO> 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;
|
||||
}
|
||||
}
|
||||
@@ -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<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;
|
||||
}
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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<Customer> getCustomers()
|
||||
throws SQLException {
|
||||
|
||||
ObservableList<Customer> 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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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<Inventory> getInventory() throws SQLException {
|
||||
ObservableList<Inventory> inventoryList = FXCollections.observableArrayList();
|
||||
|
||||
Connection conn = ConnectionDB.getConnection();
|
||||
|
||||
Statement stmt = conn.createStatement();
|
||||
ResultSet rs = stmt.executeQuery(BASE_SELECT);
|
||||
|
||||
while (rs.next()) {
|
||||
inventoryList.add(mapRow(rs));
|
||||
}
|
||||
|
||||
conn.close();
|
||||
|
||||
return inventoryList;
|
||||
}
|
||||
|
||||
//Returns records depending on search
|
||||
public static ObservableList<Inventory> getFilteredInventory(String filter) throws SQLException {
|
||||
ObservableList<Inventory> inventoryList = FXCollections.observableArrayList();
|
||||
Connection conn = ConnectionDB.getConnection();
|
||||
|
||||
String sql = BASE_SELECT +
|
||||
" WHERE i.inventoryId LIKE ? OR " +
|
||||
"i.prodId LIKE ? OR " +
|
||||
"p.prodName LIKE ? OR " +
|
||||
"i.quantity LIKE ?";
|
||||
|
||||
String filteredString = "%" + filter + "%";
|
||||
PreparedStatement stmt = conn.prepareStatement(sql);
|
||||
|
||||
for (int i = 1; i <= 4; i++) {
|
||||
stmt.setString(i, filteredString);
|
||||
}
|
||||
|
||||
ResultSet rs = stmt.executeQuery();
|
||||
|
||||
while (rs.next()) {
|
||||
inventoryList.add(mapRow(rs));
|
||||
}
|
||||
|
||||
conn.close();
|
||||
|
||||
return inventoryList;
|
||||
}
|
||||
|
||||
//Checks if the product already has an inventory entry
|
||||
public static boolean productExistsInInventory(int prodId) throws SQLException {
|
||||
Connection conn = ConnectionDB.getConnection();
|
||||
String sql = "SELECT COUNT(*) FROM inventory WHERE prodId = ?";
|
||||
|
||||
PreparedStatement stmt = conn.prepareStatement(sql);
|
||||
stmt.setInt(1, prodId);
|
||||
ResultSet rs = stmt.executeQuery();
|
||||
|
||||
boolean exists = rs.next() && rs.getInt(1) > 0;
|
||||
conn.close();
|
||||
|
||||
return exists;
|
||||
}
|
||||
|
||||
//Inserting new inventory record
|
||||
public static int insertInventory(Inventory inventory) throws SQLException {
|
||||
Connection conn = ConnectionDB.getConnection();
|
||||
String sql = "INSERT INTO inventory (prodId, quantity) VALUES (?, ?)";
|
||||
|
||||
PreparedStatement stmt = conn.prepareStatement(sql);
|
||||
stmt.setInt(1, inventory.getProdId());
|
||||
stmt.setInt(2, inventory.getQuantity());
|
||||
|
||||
int numRows = stmt.executeUpdate();
|
||||
conn.close();
|
||||
|
||||
// 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
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -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<Pet> getPets() throws SQLException {
|
||||
//Connect to the database
|
||||
ObservableList<Pet> 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<Pet> getFilteredPets(String filter) throws SQLException {
|
||||
//Connect to the database
|
||||
ObservableList<Pet> 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;
|
||||
}
|
||||
}
|
||||
@@ -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<Product> getProducts() throws SQLException{
|
||||
//Connect to the database
|
||||
ObservableList<Product> 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<ProductDTO> getProductDTO() throws SQLException{
|
||||
//Connect to the database
|
||||
ObservableList<ProductDTO> 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<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;
|
||||
}
|
||||
}
|
||||
@@ -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<ProductSupplierDTO> getProductSupplierDTO() throws SQLException{
|
||||
//Connect to the database
|
||||
ObservableList<ProductSupplierDTO> productSuppliers = FXCollections.observableArrayList();
|
||||
Connection conn = ConnectionDB.getConnection();
|
||||
|
||||
//Execute Query
|
||||
Statement stmt = conn.createStatement();
|
||||
String sql = "SELECT ps.supId, ps.prodId, s.supCompany, p.prodName, ps.cost " +
|
||||
"FROM productSupplier ps " +
|
||||
"LEFT JOIN product p " +
|
||||
"ON p.prodId = ps.prodId " +
|
||||
"LEFT JOIN supplier s " +
|
||||
"ON s.supId = ps.supId";
|
||||
ResultSet rs = stmt.executeQuery(sql);
|
||||
|
||||
//While there is still data add productSupplier to list
|
||||
while(rs.next()){
|
||||
ProductSupplierDTO productSupplier = new ProductSupplierDTO(
|
||||
rs.getInt(1),
|
||||
rs.getInt(2),
|
||||
rs.getString(3),
|
||||
rs.getString(4),
|
||||
rs.getDouble(5)
|
||||
);
|
||||
productSuppliers.add(productSupplier);
|
||||
}
|
||||
|
||||
//close connection and return products
|
||||
conn.close();
|
||||
return productSuppliers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a list of ProductSupplierDTOs that is filtered by a given string
|
||||
* @param filter the word to filter table
|
||||
* @return ObservableList of ProductSupplierDTOs with the filtered data
|
||||
* @throws SQLException if getting productSuppliers failed
|
||||
*/
|
||||
public static ObservableList<ProductSupplierDTO> getFilteredProductSupplierDTO (String filter) throws SQLException {
|
||||
//connect to the database
|
||||
ObservableList<ProductSupplierDTO> productSuppliers = FXCollections.observableArrayList();
|
||||
Connection conn = ConnectionDB.getConnection();
|
||||
|
||||
//Get SQL query for filter word
|
||||
String sql =
|
||||
"SELECT ps.supId, ps.prodId, s.supCompany, p.prodName, ps.cost " +
|
||||
"FROM product p " +
|
||||
"LEFT JOIN productSupplier ps " +
|
||||
"ON p.prodId = ps.prodId " +
|
||||
"LEFT JOIN supplier s " +
|
||||
"ON s.supId = ps.supId " +
|
||||
"WHERE " +
|
||||
"prodName LIKE ? OR " +
|
||||
"supCompany LIKE ? OR " +
|
||||
"cost LIKE ?";
|
||||
|
||||
//add % wildcard so query can use LIKE to filter data
|
||||
String filteredString = "%" + filter + "%";
|
||||
|
||||
PreparedStatement stmt = conn.prepareStatement(sql);
|
||||
stmt.setString(1, filteredString);
|
||||
stmt.setString(2, filteredString);
|
||||
stmt.setString(3, filteredString);
|
||||
|
||||
//execute query
|
||||
ResultSet rs = stmt.executeQuery();
|
||||
|
||||
//While there is still data add productSupplier to the list
|
||||
while(rs.next()){
|
||||
ProductSupplierDTO productSupplier = new ProductSupplierDTO(
|
||||
rs.getInt(1),
|
||||
rs.getInt(2),
|
||||
rs.getString(3),
|
||||
rs.getString(4),
|
||||
rs.getDouble(5)
|
||||
);
|
||||
productSuppliers.add(productSupplier);
|
||||
}
|
||||
|
||||
conn.close();
|
||||
return productSuppliers;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inserts a new productSupplier to the database
|
||||
* @param productSupplier productSupplier entity to be inserted
|
||||
* @return number of rows affected
|
||||
* @throws SQLException if insert failed
|
||||
*/
|
||||
public static int insertProductSupplier(ProductSupplier productSupplier) throws SQLException{
|
||||
int numRows = 0;
|
||||
|
||||
Connection conn = ConnectionDB.getConnection();
|
||||
String sql = "INSERT INTO productSupplier (prodId, supId, cost) " +
|
||||
"VALUES (?, ?, ?)";
|
||||
|
||||
//These are the values from productSupplier to put into query above
|
||||
PreparedStatement stmt = conn.prepareStatement(sql);
|
||||
stmt.setInt(1, productSupplier.getProdId());
|
||||
stmt.setInt(2, productSupplier.getSupId());
|
||||
stmt.setDouble(3, productSupplier.getCost());
|
||||
|
||||
//update number of rows affected, return and close connection
|
||||
numRows = stmt.executeUpdate();
|
||||
conn.close();
|
||||
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
@@ -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<PurchaseOrderDTO> getPurchaseOrders()
|
||||
throws SQLException {
|
||||
|
||||
ObservableList<PurchaseOrderDTO> 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;
|
||||
}
|
||||
}
|
||||
@@ -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<SaleDTO> getSales() throws SQLException {
|
||||
ObservableList<SaleDTO> 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<SaleDTO> getFilteredSales(String filter) throws SQLException {
|
||||
ObservableList<SaleDTO> 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<SaleLineItem> getSaleLineItems() throws SQLException {
|
||||
ObservableList<SaleLineItem> 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<SaleCartItem> 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<DailySalesData> getDailySalesRevenue() throws SQLException {
|
||||
ObservableList<DailySalesData> 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<ProductSalesData> getTopProductsByRevenue(int limit) throws SQLException {
|
||||
ObservableList<ProductSalesData> 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<ProductSalesData> getTopProductsByQuantity(int limit) throws SQLException {
|
||||
ObservableList<ProductSalesData> 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<PaymentMethodData> getPaymentMethodDistribution() throws SQLException {
|
||||
ObservableList<PaymentMethodData> 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<EmployeeSalesData> getEmployeeSalesPerformance() throws SQLException {
|
||||
ObservableList<EmployeeSalesData> 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<SaleCartItem> 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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<Service> getServices() throws SQLException {
|
||||
|
||||
ObservableList<Service> 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;
|
||||
}
|
||||
}
|
||||
@@ -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<Supplier> getSuppliers() throws SQLException {
|
||||
//Connect to the database
|
||||
ObservableList<Supplier> 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<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;
|
||||
}
|
||||
}
|
||||
@@ -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<StaffAccount> 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<StaffAccount> 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");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user