From e2760fbb7f9f8fe35a7087523f2591976f9f12b4 Mon Sep 17 00:00:00 2001 From: haavajor Date: Thu, 5 Mar 2026 11:36:45 +0100 Subject: [PATCH 1/2] Unit tests for Donation, User, and Organization classes --- .../domain/organization/Organization.java | 4 + src/main/java/persistence/UserDao.java | 2 +- src/test/java/domain/DonationTest.java | 115 ++++++++++ src/test/java/domain/OrganizationTest.java | 202 ++++++++++++++++++ src/test/java/domain/UserTest.java | 132 ++++++++++++ 5 files changed, 454 insertions(+), 1 deletion(-) diff --git a/src/main/java/domain/organization/Organization.java b/src/main/java/domain/organization/Organization.java index c4d5d3c..611e18a 100644 --- a/src/main/java/domain/organization/Organization.java +++ b/src/main/java/domain/organization/Organization.java @@ -21,6 +21,8 @@ public Organization(String name, String orgNr, Cause cause, String description, if (orgNr == null || !orgNr.matches("\\d{9}")) { throw new IllegalArgumentException("Organization number must be 9 digits"); } + + //Legg til exception for contactEmail == null if (contactEmail != null) { contactEmail = contactEmail.trim(); @@ -35,6 +37,7 @@ public Organization(String name, String orgNr, Cause cause, String description, } } + //Legg til exception for website == null if (website != null) { website = website.trim(); @@ -42,6 +45,7 @@ public Organization(String name, String orgNr, Cause cause, String description, throw new IllegalArgumentException("Website cannot be blank"); } + //Legg til feil for domain extension (.com f.eks) if (!website.matches("^https?://.+")) { //Got help from ChatGPT for regex throw new IllegalArgumentException("Website must start with http:// or https://"); } diff --git a/src/main/java/persistence/UserDao.java b/src/main/java/persistence/UserDao.java index 5a77341..bf9edc4 100644 --- a/src/main/java/persistence/UserDao.java +++ b/src/main/java/persistence/UserDao.java @@ -4,7 +4,7 @@ import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; -import model.User; +import domain.user.User; public class UserDao { diff --git a/src/test/java/domain/DonationTest.java b/src/test/java/domain/DonationTest.java index bb9c875..ea73049 100644 --- a/src/test/java/domain/DonationTest.java +++ b/src/test/java/domain/DonationTest.java @@ -1,5 +1,120 @@ package domain; +import domain.donation.Cause; +import domain.donation.Donation; +import domain.organization.Organization; +import domain.user.User; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.math.BigDecimal; +import java.time.Duration; +import java.time.LocalDateTime; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + class DonationTest { + //User Variables + private final String testUserName = "testUser"; + private final String testPhoneNumber = "90909090"; + private final String testEmail = "test@email.com"; + private final String testPassword = "password"; + + //Organization Variables + private final String testName = "Name"; + private final String testOrgNr = "123456789"; + private final Cause testCause = Cause.HEALTH; + private final String testDescription = "Description"; + private final String testContactEmail = "test@mail.com"; + private final String testWebsite = "https://test.com"; + private final boolean testVerified = true; + + //Donation Variables + private Long testID = 123L; + private BigDecimal testAmount = new BigDecimal("1500"); + private LocalDateTime testDateTime = LocalDateTime.of(2026, 3, 5, 8, 30, 0); + private User testUser; + private Organization testOrganization; + + @BeforeEach + public void init() { + testUser = new User(testUserName, testPhoneNumber, testPassword, testEmail); + testOrganization = new Organization(testName, testOrgNr, testCause, testDescription, testContactEmail, testWebsite, testVerified); + } + + + @Test + public void DonationTestPositive(){ + Donation donation = new Donation(testAmount, testUser, testOrganization); + } + + @Test + public void DonationTestUserNull(){ + testUser = null; + NullPointerException Exception = assertThrows(NullPointerException.class, + () -> new Donation (testAmount, testUser, testOrganization)); + + assertEquals("User cannot be null", Exception.getMessage()); + } + + @Test + public void DonationOrganizationNull(){ + testOrganization = null; + NullPointerException Exception = assertThrows(NullPointerException.class, + () -> new Donation (testAmount, testUser, testOrganization)); + + assertEquals("Organization cannot be null", Exception.getMessage()); + } + + @Test + public void DonationTestAmountNegative(){ + testAmount = new BigDecimal("-23"); + IllegalArgumentException Exception = assertThrows(IllegalArgumentException.class, + () -> new Donation (testAmount, testUser, testOrganization)); + + assertEquals("Amount must be greater than 0", Exception.getMessage()); + } + + //Getter tests + /* id is never set, getter makes a NullPointerException + @Test + public void DonationTestIdGet(){ + Donation donation = new Donation(testAmount, testUser, testOrganization); + assertEquals(0L, donation.getId()); + + } + */ + + @Test + public void DonationTestAmountGet(){ + Donation donation = new Donation(testAmount, testUser, testOrganization); + assertEquals(testAmount, donation.getAmount()); + + } + + @Test + public void DonationTestDateTimeGet(){ + LocalDateTime now = LocalDateTime.now(); + Donation donation = new Donation(testAmount, testUser, testOrganization); + + assertTrue(Duration.between(now, donation.getDateTime()).abs().toMillis() < 1000); + + } + + @Test + public void DonationTestUserGet(){ + Donation donation = new Donation(testAmount, testUser, testOrganization); + assertEquals(testUser, donation.getUser()); + + } + + @Test + public void DonationTestOrganizationGet(){ + Donation donation = new Donation(testAmount, testUser, testOrganization); + assertEquals(testOrganization, donation.getOrganization()); + + } } \ No newline at end of file diff --git a/src/test/java/domain/OrganizationTest.java b/src/test/java/domain/OrganizationTest.java index 815aa53..47c8024 100644 --- a/src/test/java/domain/OrganizationTest.java +++ b/src/test/java/domain/OrganizationTest.java @@ -1,5 +1,207 @@ package domain; +import domain.donation.Cause; +import domain.organization.Organization; +import domain.user.User; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + class OrganizationTest { + private String testName = "Name"; + private String testOrgNr = "123456789"; + private Cause testCause = Cause.HEALTH; + private String testDescription = "Description"; + private String testContactEmail = "test@mail.com"; + private String testWebsite = "https://test.com"; + private boolean testVerified = true; + + //Positive tests + @Test + public void organizationTestPositive(){ + Organization organization = new Organization(testName, testOrgNr, testCause, testDescription, testContactEmail, testWebsite, testVerified); + } + + //Negative tests + @Test + public void organizationTestNameBlank(){ + testName = ""; + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, + () -> new Organization("", testOrgNr, testCause, testDescription, testContactEmail, testWebsite, testVerified)); + + assertEquals("Name cannot be null or blank", exception.getMessage()); + } + + @Test + public void organizationTestNameNull(){ + testName = null; + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, + () -> new Organization(testName, testOrgNr, testCause, testDescription, testContactEmail, testWebsite, testVerified)); + + assertEquals("Name cannot be null or blank", exception.getMessage()); + } + + @Test + public void organizationTestOrgNrNull(){ + testOrgNr = null; + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, + () -> new Organization(testName, testOrgNr, testCause, testDescription, testContactEmail, testWebsite, testVerified)); + + assertEquals("Organization number must be 9 digits", exception.getMessage()); + } + + @Test + public void organizationTestOrgNrLetters(){ + testOrgNr = "12345678a"; + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, + () -> new Organization(testName, testOrgNr, testCause, testDescription, testContactEmail, testWebsite, testVerified)); + + assertEquals("Organization number must be 9 digits", exception.getMessage()); + } + + @Test + public void organizationTestOrgNrShort(){ + testOrgNr = "12345"; + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, + () -> new Organization(testName, testOrgNr, testCause, testDescription, testContactEmail, testWebsite, testVerified)); + + assertEquals("Organization number must be 9 digits", exception.getMessage()); + } + + /* Mangler exception for når email er null + @Test + public void organizationTestContactEmailNull(){ + testContactEmail = null; + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, + () -> new Organization(testName, testOrgNr, testCause, testDescription, testContactEmail, testWebsite, testVerified)); + } + */ + + @Test + public void organizationTestContactEmailTrim(){ + testContactEmail = "test@mail.com "; + Organization organization = new Organization(testName, testOrgNr, testCause, testDescription, testContactEmail, testWebsite, testVerified); + } + + @Test + public void organizationTestContactEmailBlank(){ + testContactEmail = ""; + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, + () -> new Organization(testName, testOrgNr, testCause, testDescription, testContactEmail, testWebsite, testVerified)); + + assertEquals("Email cannot be blank", exception.getMessage()); + } + + @Test + public void organizationTestContactEmailMissingAt(){ + testContactEmail = "test.com"; + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, + () -> new Organization(testName, testOrgNr, testCause, testDescription, testContactEmail, testWebsite, testVerified)); + + assertEquals("Invalid email format", exception.getMessage()); + } + + @Test + public void organizationTestContactEmailDoubleAt(){ + testContactEmail = "test@@mail.com"; + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, + () -> new Organization(testName, testOrgNr, testCause, testDescription, testContactEmail, testWebsite, testVerified)); + + assertEquals("Invalid email format", exception.getMessage()); + } + + @Test + public void organizationTestContactEmailMisplacedAt(){ + testContactEmail = "@testmail.com"; + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, + () -> new Organization(testName, testOrgNr, testCause, testDescription, testContactEmail, testWebsite, testVerified)); + + assertEquals("Invalid email format", exception.getMessage()); + } + + @Test + public void organizationTestContactEmailMissingDot(){ + testContactEmail = "test@mailcom"; + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, + () -> new Organization(testName, testOrgNr, testCause, testDescription, testContactEmail, testWebsite, testVerified)); + + assertEquals("Invalid email format", exception.getMessage()); + } + + @Test + public void organizationTestWebsiteMissingHttps(){ + testWebsite = "test.com"; + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, + () -> new Organization(testName, testOrgNr, testCause, testDescription, testContactEmail, testWebsite, testVerified)); + + assertEquals("Website must start with http:// or https://", exception.getMessage()); + } + + /* Mangler exception når url mangler domain extension (.com f.eks) + @Test + public void organizationTestWebsiteMissingDot(){ + testWebsite = "https://testcom"; + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, + () -> new Organization(testName, testOrgNr, testCause, testDescription, testContactEmail, testWebsite, testVerified)); + + assertEquals("Website must start with http:// or https://", exception.getMessage()); + } + */ + + /* Mangler exception når website er null + @Test + public void organizationTestWebsiteMissingDot(){ + testWebsite = null; + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, + () -> new Organization(testName, testOrgNr, testCause, testDescription, testContactEmail, testWebsite, testVerified)); + + assertEquals("Website must start with http:// or https://", exception.getMessage()); + } + */ + + + + //Getter tests + @Test + public void organizationTestNameGet(){ + Organization Organization = new Organization(testName, testOrgNr, testCause, testDescription, testContactEmail, testWebsite, testVerified); + assertEquals(testName, Organization.getName()); + } + + @Test + public void organizationTestOrgNrGet(){ + Organization Organization = new Organization(testName, testOrgNr, testCause, testDescription, testContactEmail, testWebsite, testVerified); + assertEquals(testOrgNr, Organization.getOrgNr()); + } + + @Test + public void organizationTestCauseGet(){ + Organization Organization = new Organization(testName, testOrgNr, testCause, testDescription, testContactEmail, testWebsite, testVerified); + assertEquals(testCause, Organization.getCause()); + } + + @Test + public void organizationDescriptionGet(){ + Organization Organization = new Organization(testName, testOrgNr, testCause, testDescription, testContactEmail, testWebsite, testVerified); + assertEquals(testDescription, Organization.getDescription()); + } + + @Test + public void organizationTestContactEmailGet(){ + Organization Organization = new Organization(testName, testOrgNr, testCause, testDescription, testContactEmail, testWebsite, testVerified); + assertEquals(testContactEmail, Organization.getContactEmail()); + } + + @Test + public void organizationTestWebsiteGet(){ + Organization Organization = new Organization(testName, testOrgNr, testCause, testDescription, testContactEmail, testWebsite, testVerified); + assertEquals(testWebsite, Organization.getWebsite()); + } + @Test + public void organizationTestIsVerifiedGet(){ + Organization Organization = new Organization(testName, testOrgNr, testCause, testDescription, testContactEmail, testWebsite, testVerified); + assertEquals(testVerified, Organization.isVerified()); + } } \ No newline at end of file diff --git a/src/test/java/domain/UserTest.java b/src/test/java/domain/UserTest.java index c21aa90..b1c8f14 100644 --- a/src/test/java/domain/UserTest.java +++ b/src/test/java/domain/UserTest.java @@ -1,5 +1,137 @@ package domain; +import domain.user.User; +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + class UserTest { + private String testUserName = "testUser"; + private String testPhoneNumber = "90909090"; + private String testEmail = "test@email.com"; + private final String testPassword = "password"; + + //Positive tests + @Test + public void userTestPositive(){ + User User = new User(testUserName, testPhoneNumber, testPassword, testEmail); + } + + //Negative tests + @Test + public void userTestUserNameBlank(){ + testUserName = ""; + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, + () -> new User(testUserName, testPhoneNumber, testPassword, testEmail)); + + assertEquals("Username has to be filled in", exception.getMessage()); + } + + @Test + public void userTestUserNameNull(){ + testUserName = null; + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, + () -> new User(testUserName, testPhoneNumber, testPassword, testEmail)); + + assertEquals("Username has to be filled in", exception.getMessage()); + } + + @Test + public void userTestPhoneNumberBlank(){ + testPhoneNumber = ""; + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, + () -> new User(testUserName, testPhoneNumber, testPassword, testEmail)); + + assertEquals("Phonenumber has to be filled in", exception.getMessage()); + } + + @Test + public void userTestPhoneNumberNull(){ + testPhoneNumber = null; + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, + () -> new User(testUserName, testPhoneNumber, testPassword, testEmail)); + + assertEquals("Phonenumber has to be filled in", exception.getMessage()); + } + + @Test + public void userTestPhoneNumberShort() { + testPhoneNumber = "909090"; + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, + () -> new User(testUserName, testPhoneNumber, testPassword, testEmail)); + + assertEquals("Fill in a phonenumber with 8 digits", exception.getMessage()); + } + + @Test + public void userTestEmailBlank(){ + testEmail = ""; + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, + () -> new User(testUserName, testPhoneNumber, testPassword, testEmail)); + + assertEquals("E-mail has to be filled in", exception.getMessage()); + } + + @Test + public void userTestEmailNull(){ + testEmail = null; + IllegalArgumentException exception = assertThrows(IllegalArgumentException.class, + () -> new User(testUserName, testPhoneNumber, testPassword, testEmail)); + + assertEquals("E-mail has to be filled in", exception.getMessage()); + } + + //Getter tests + @Test + public void userTestUserNameGet(){ + User User = new User(testUserName, testPhoneNumber, testPassword, testEmail); + assertEquals(User.getUsername(), testUserName); + } + + @Test + public void userTestPhoneNumberGet(){ + User User = new User(testUserName, testPhoneNumber, testPassword, testEmail); + assertEquals(User.getPhoneNumber(), testPhoneNumber); + } + + @Test + public void userTestEmailGet(){ + User User = new User(testUserName, testPhoneNumber, testPassword, testEmail); + assertEquals(User.getEMail(), testEmail); + } + + @Test + public void userTestPasswordGet(){ + User User = new User(testUserName, testPhoneNumber, testPassword, testEmail); + assertEquals(User.getPassword(), testPassword); + } + + //Setter tests + @Test + public void userTestPasswordSet(){ + User User = new User(testUserName, testPhoneNumber, testPassword, testEmail); + String newPassword = "NewPassoword"; + User.setPassword(newPassword); + assertEquals(newPassword, User.getPassword()); + } + + @Test + public void userTestUserNameSet(){ + User User = new User(testUserName, testPhoneNumber, testPassword, testEmail); + String newUserName = "NewUsername"; + User.setUsername(newUserName); + assertEquals(newUserName, User.getUsername()); + } + + @Test + public void userTestPhoneNumberSet(){ + User User = new User(testUserName, testPhoneNumber, testPassword, testEmail); + String newPhoneNumber = "123456asdsad7"; //Trenger input validering + User.setPhonenumber(newPhoneNumber); + assertEquals(newPhoneNumber, User.getPhoneNumber()); + } + + + } \ No newline at end of file From ea5cf76b6b06b0eb66aba9c4ae992f5c831be7c1 Mon Sep 17 00:00:00 2001 From: lukaceli Date: Tue, 7 Apr 2026 15:11:07 +0200 Subject: [PATCH 2/2] 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 70ddba6..0361f2b 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"), @@ -64,6 +85,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, @@ -88,6 +118,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 @@ -108,6 +146,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 @@ -131,6 +179,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)) @@ -153,6 +210,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(*) @@ -177,12 +245,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)";