From 7de73d0cde145775307930483b8279d1c5dd6835 Mon Sep 17 00:00:00 2001 From: lukaceli Date: Tue, 7 Apr 2026 15:11:07 +0200 Subject: [PATCH 1/6] Added javadoc to DonationDao and UserStatistics --- .../java/application/user/UserStatistics.java | 35 ++++++++ src/main/java/persistence/DonationDao.java | 87 ++++++++++++++++++- 2 files changed, 121 insertions(+), 1 deletion(-) diff --git a/src/main/java/application/user/UserStatistics.java b/src/main/java/application/user/UserStatistics.java index 64333f1..5fe67d4 100644 --- a/src/main/java/application/user/UserStatistics.java +++ b/src/main/java/application/user/UserStatistics.java @@ -5,28 +5,63 @@ import java.util.List; import persistence.DonationDao; +/** + * Provides statistical information about a user's donation activity. + * Acts as a service layer between the application and {@link DonationDao}, + * exposing user-friendly methods for retrieving donation history, + * total amounts, and favorite organizations. + */ public class UserStatistics { private DonationDao donationDao; + /** + * Constructs a new {@code UserStatistics} instance with a default {@link DonationDao}. + */ public UserStatistics() { this.donationDao = new DonationDao(); } + /** + * Returns the top three organizations that the user has donated to most frequently. + * + * @param user the user whose favorite organizations are to be retrieved; must not be null + * @return a list of up to three formatted strings, each representing an organization + * and its donation count; empty list if the user has no donations + */ public List userFavoriteOrganizations(User user) { List favoriteOrganizations = donationDao.getFavoriteOrganizations(user.getID()); return favoriteOrganizations; } + /** + * Returns a formatted list of all donations made by the user. + * Each entry contains the donation amount, date, and organization. + * + * @param user the user whose donation history is to be retrieved; must not be null + * @return a list of formatted donation strings; empty list if the user has no donations + */ public List userDonations(User user) { List userDonationList = donationDao.getUserDonations(user.getID()); return userDonationList; } + /** + * Returns the total amount donated by the user across all donations. + * + * @param user the user whose total donation amount is to be calculated; must not be null + * @return a string representation of the total donated amount; {@code "0"} if no donations exist + */ public String userTotalDonationAmount(User user) { String totalDonations = donationDao.getTotalDonationAmount(user.getID()); return totalDonations; } + /** + * Returns the total number of donations made by the user. + * + * @param user the user whose donation count is to be retrieved; must not be null + * @return a string representation of the total number of donations; {@code "0"} if none exist + */ public String getTotalDonationsMade(User user) { String totalDonationsMade = donationDao.getTotalDonationsMade(user.getID()); return totalDonationsMade; diff --git a/src/main/java/persistence/DonationDao.java b/src/main/java/persistence/DonationDao.java index 646dba5..d7737b1 100644 --- a/src/main/java/persistence/DonationDao.java +++ b/src/main/java/persistence/DonationDao.java @@ -13,8 +13,20 @@ import java.util.List; import persistence.db.Database; +/** + * Data Access Object for donation-related database operations. + * Provides methods for inserting donations and retrieving donation statistics + * such as history, total amounts, and favorite organizations for a given user. + */ public class DonationDao { - + /** + * Inserts a new donation record into the database. + * Upon successful insertion, the generated database ID is set on the donation object. + * + * @param donation the {@link Donation} to insert; must not be null and must have + * a valid amount, user, and organization + * @throws RuntimeException if a database error occurs during the insert + */ public void insert(Donation donation) { String sql = "INSERT INTO donation(amount, donation_date" + ", user_id, organization_id) VALUES(?, ?, ?, ?)"; @@ -38,6 +50,15 @@ public void insert(Donation donation) { } } + /** + * Maps a single row from the provided {@code ResultSet} into a {@link Donation} object. + * The method extracts information about the donation, user, and organization + * from the {@code ResultSet} and constructs corresponding objects. + * + * @param rs the {@code ResultSet} containing the data for a single row; must not be null + * @return a {@code Donation} object populated with data from the row in the {@code ResultSet} + * @throws SQLException if a database access error occurs or if the column labels cannot be found + */ private Donation mapRow(ResultSet rs) throws SQLException { User user = new User( rs.getString("user_name"), @@ -63,6 +84,15 @@ private Donation mapRow(ResultSet rs) throws SQLException { return donation; } + /** + * Retrieves a list of donations made by a specific user, based on the user ID. + * The donations include details such as the donation amount, date, associated user, + * and organization. + * + * @param userId the unique identifier of the user whose donations are to be retrieved + * @return a list of {@code Donation} objects representing donations made by the user + * @throws RuntimeException if an error occurs during the database operation + */ public List findByUser(long userId) { String sql = """ SELECT d.id, d.amount, d.donation_date, @@ -87,6 +117,14 @@ public List findByUser(long userId) { } } + /** + * Retrieves a formatted list of donations made by a specific user. + * Each entry is a string on the form {@code "Amount: X, Date: Y, Organization: Z"}. + * + * @param userId the unique identifier of the user whose donations are to be retrieved + * @return a list of formatted strings, one per donation; empty list if none found + * @throws RuntimeException if a database error occurs during the query + */ public List getUserDonations(long userId) { String sql = """ SELECT amount, donation_date, organization_id @@ -107,6 +145,16 @@ public List getUserDonations(long userId) { } } + /** + * Retrieves a list of the user's favorite organizations based on donation history. + * The method queries the database to find the organizations the user has donated to most frequently + * and limits the result to the top three organizations. + * + * @param userId the unique identifier of the user whose favorite organizations are to be retrieved + * @return a list of strings representing the top three organizations donated to by the user, + * ordered by the number of donations in descending order + * @throws RuntimeException if an error occurs while querying the database + */ public List getFavoriteOrganizations(long userId) { String sql = """ SELECT organization_id, COUNT(*) AS donation_count @@ -130,6 +178,15 @@ SELECT organization_id, COUNT(*) AS donation_count } } + /** + * Retrieves the total donation amount made by a specific user. + * The method calculates the sum of all donations associated with the given user ID. + * + * @param userId the unique identifier of the user whose total donation amount is to be retrieved + * @return a string representing the total donation amount made by the user; if no donations exist, + * the method returns "0" + * @throws RuntimeException if an error occurs during database access + */ public String getTotalDonationAmount(long userId) { String sql = """ SELECT SUM(CAST(amount as REAL)) @@ -152,6 +209,17 @@ SELECT SUM(CAST(amount as REAL)) } } + /** + * Retrieves the total number of donations made by a specific user. + * The method counts the number of donation records associated with the provided user ID + * in the database and returns the total count as a string. + * + * @param userId the unique identifier of the user whose total number of donations + * is to be retrieved + * @return a string representing the total count of donations made by the user; + * returns "0" if no donations exist + * @throws RuntimeException if a database access error occurs + */ public String getTotalDonationsMade(long userId) { String sql = """ SELECT COUNT(*) @@ -176,12 +244,29 @@ SELECT COUNT(*) } + /** + * Maps a single row from the provided {@code ResultSet} into a string representation + * consisting of the donation amount, date, and organization ID. + * + * @param rs the {@code ResultSet} containing the data for a single row; must not be null + * @return a string representing the donation with details such as amount, date, + * and organization ID + * @throws SQLException if a database access error occurs or if the column labels cannot be found + */ private String mapRowSimple(ResultSet rs) throws SQLException { return "Amount: " + rs.getString("amount") + ", Date: " + rs.getString("donation_date") + ", Organization: " + rs.getString("organization_id"); } + /** + * Maps a single row from the provided {@code ResultSet} into a formatted string + * combining the organization ID and its donation count. + * + * @param rs the {@code ResultSet} containing the data for a single row; must not be null + * @return a string on the form {@code "organization_id (N donations)"} + * @throws SQLException if a database access error occurs or a column label cannot be found + */ private String mapRowFavorite(ResultSet rs) throws SQLException { return rs.getString("organization_id") + " (" + rs.getInt("donation_count") + " donasjoner)"; From 7ae6ae58e8ea5753f83a74ea2c0cbaa31be699da Mon Sep 17 00:00:00 2001 From: lukaceli Date: Fri, 10 Apr 2026 10:51:52 +0200 Subject: [PATCH 2/6] Mde changes to FavoriteOrganization, so that the statistcs page shows organization name instead of org ID. --- src/main/java/persistence/DonationDao.java | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/main/java/persistence/DonationDao.java b/src/main/java/persistence/DonationDao.java index d7737b1..d467e99 100644 --- a/src/main/java/persistence/DonationDao.java +++ b/src/main/java/persistence/DonationDao.java @@ -155,14 +155,15 @@ public List getUserDonations(long userId) { * ordered by the number of donations in descending order * @throws RuntimeException if an error occurs while querying the database */ - public List getFavoriteOrganizations(long userId) { + public List getFavoriteOrganization(long userId) { String sql = """ - SELECT organization_id, COUNT(*) AS donation_count - FROM donation - WHERE user_Id = ? - GROUP BY organization_id + SELECT o.name, COUNT(*) AS donation_count + FROM donation d + JOIN organization o ON d.organization_id = o.org_number + WHERE d.user_id = ? + GROUP BY d.organization_id ORDER BY donation_count DESC - LIMIT 3 + LIMIT 1 """; try (Connection conn = Database.getConnection()) { @@ -268,7 +269,7 @@ private String mapRowSimple(ResultSet rs) throws SQLException { * @throws SQLException if a database access error occurs or a column label cannot be found */ private String mapRowFavorite(ResultSet rs) throws SQLException { - return rs.getString("organization_id") + return rs.getString("name") + " (" + rs.getInt("donation_count") + " donasjoner)"; } From 3a6839ba5ad4504fb3524c6304e36789750c1a9c Mon Sep 17 00:00:00 2001 From: lukaceli Date: Fri, 10 Apr 2026 10:52:22 +0200 Subject: [PATCH 3/6] Added addTestData function to add test date for testing implemented features --- src/main/java/app/Main.java | 38 +++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/src/main/java/app/Main.java b/src/main/java/app/Main.java index c30aa59..a1c0d3e 100644 --- a/src/main/java/app/Main.java +++ b/src/main/java/app/Main.java @@ -8,6 +8,7 @@ import domain.user.User; import integration.security.Sha256PasswordHasher; import java.math.BigDecimal; +import java.sql.SQLException; import java.util.List; import persistence.DonationDao; import persistence.OrganizationDao; @@ -35,6 +36,8 @@ public void start(Stage stage) throws Exception { orgDao.insert(org); } + addTestdata(); + Parent root = FXMLLoader.load(getClass().getResource("/view/MainView.fxml")); Scene scene = new Scene(root, 1275, 725); @@ -42,4 +45,39 @@ public void start(Stage stage) throws Exception { stage.setScene(scene); stage.show(); } + + private void addTestdata() throws SQLException { + UserDao userDao = new UserDao(); + DonationDao donationDao = new DonationDao(); + OrganizationDao orgDao = new OrganizationDao(); + + if (userDao.existsByEmail("test@test.no")) return; + + PasswordHasher hasher = new Sha256PasswordHasher(); + String hashedPassword = hasher.hash("test"); + User user = new User("test", "12345678", hashedPassword, "test@test.no"); + userDao.insert(user); + + Organization org = orgDao.getAll().get(0); + + donationDao.insert(new Donation(new BigDecimal(100), user, org)); + donationDao.insert(new Donation(new BigDecimal(250), user, org)); + donationDao.insert(new Donation(new BigDecimal(500), user, org)); + donationDao.insert(new Donation(new BigDecimal(300), user, org)); + donationDao.insert(new Donation(new BigDecimal(1000), user, org)); + donationDao.insert(new Donation(new BigDecimal(700), user, org)); + donationDao.insert(new Donation(new BigDecimal(250), user, org)); + + if (!userDao.existsByEmail("test2@test.no")) { + String hashedPassword2 = hasher.hash("test2"); + User user2 = new User("test2", "87654321", hashedPassword2, "test2@test.no"); + userDao.insert(user2); + + Organization org2 = orgDao.getAll().get(1); + + donationDao.insert(new Donation(new BigDecimal(150), user2, org2)); + donationDao.insert(new Donation(new BigDecimal(400), user2, org2)); + donationDao.insert(new Donation(new BigDecimal(600), user2, org2)); + } + } } From 8d6adb9fa2a2d792eb855cc6a2283a0bb51fc38a Mon Sep 17 00:00:00 2001 From: lukaceli Date: Fri, 10 Apr 2026 10:53:44 +0200 Subject: [PATCH 4/6] Made changes to labeling, design and size of parts of MyProfile page --- src/main/resources/view/MyProfile.fxml | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/main/resources/view/MyProfile.fxml b/src/main/resources/view/MyProfile.fxml index 2d28b05..40ec2de 100644 --- a/src/main/resources/view/MyProfile.fxml +++ b/src/main/resources/view/MyProfile.fxml @@ -39,22 +39,22 @@