Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
alina-z7 committed Dec 6, 2024
2 parents 3a7c47f + 6f3b206 commit 32131d7
Show file tree
Hide file tree
Showing 10 changed files with 456 additions and 24 deletions.
21 changes: 21 additions & 0 deletions .idea/inspectionProfiles/Project_Default.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

72 changes: 53 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,20 @@
- [Technologies Used](#technologies-used)
- [Implementation Details](#implementation-details)
- [Known Bugs](#known-bugs)
- [Setup and Installation](#setup-and-installation)
- [About the Team](#about-the-team)
- [Contact Information](#contact-information)

## About the App
The SoftEng Health Club is known for its commitment to member satisfaction. It aims to enhance its services with a new membership management system. As the club grows, it seeks to streamline operations and improve communication with its members. This system will help SoftEng efficiently manage memberships, handle renewals, and support better member engagement. With a focus on maintaining its reputation for excellent service. This new system will ensure both staff and members enjoy a smooth experience. The system will be designed to handle various membership durations, notify members of upcoming renewals, and allow for on-the-spot membership renewals and sign-up. Additionally, it will offer tools for the club’s management to monitor member activity and generate reports for operational decisions. The following document outlines the complete design needed to meet these objectives and ensure smooth operation for both members and staff. The SoftEng Health Club's suggested membership management system is made to specifically address the demands of both the club and its customers. This solution will increase membership satisfaction by emphasizing automation, user experience, and data insights through specialized latent tasks.
The SoftEng Health Club is known for its commitment to member satisfaction. It aims to enhance its services with a new membership management system. As the club grows, it seeks to streamline operations and improve communication with its members. This system will help SoftEng efficiently manage memberships, handle renewals, and support better member engagement. With a focus on maintaining its reputation for excellent service, this new system will ensure both staff and members enjoy a smooth experience.

The system is designed to:
- Handle various membership durations.
- Notify members of upcoming renewals.
- Allow on-the-spot membership renewals and sign-ups.
- Provide tools for management to monitor member activity and generate reports for informed decision-making.

This document outlines the complete design needed to meet these objectives, ensuring seamless operation for both members and staff. The SoftEng Health Club's membership management system is crafted to address the demands of both the club and its members, emphasizing automation, user experience, and data insights.

## Technologies Used
- **Java**: Primary programming language for backend development.
Expand All @@ -18,32 +27,57 @@ The SoftEng Health Club is known for its commitment to member satisfaction. It a

## Implementation Details

The SoftEng Health Club Membership Management System comprises several Java classes and interfaces, each responsible for specific functionalities that ensure robust operation and maintainability. Here's an overview of the key components:

### Database Integration:

- Utilizes MySQL for data storage, managing members' data, session logs, and authentication details.
- Connection and query executions are managed through standard JDBC API calls, ensuring reliable data transactions and security against SQL injection via prepared statements.
- Connection and queries are handled through the JDBC API, ensuring reliable data transactions.
- Uses prepared statements to safeguard against SQL injection.

### User Interface:
- Designed using Java Swing, providing a familiar native look and feel.
- The login page and other UI components utilize a `GridLayoutManager` to ensure responsive and user-friendly design on various screen resolutions.

- Designed using Java Swing, providing a native look and feel that is familiar to users.
- The login page is created with a combination of labels, text fields, and buttons laid out using a `GridLayoutManager` to ensure a responsive layout across different screen resolutions.
## Known Bugs
- **Selection Issue After Sorting**: Selecting a member after sorting the table by a column currently selects the member previously at that row before sorting. This causes incorrect member actions.
- **Array Out of Bounds Error**: Clicking the delete button without selecting a member results in an ArrayOutOfBoundsException, potentially causing application crashes and data loss.

## Setup and Installation
1. **Install IntelliJ IDEA**
Download and install IntelliJ IDEA from [JetBrains](https://www.jetbrains.com/idea/download/).

## Known Bugs
- **Selection Issue After Sorting**: Selecting a member after sorting the table by column selects the member that was in the row before sorting. This can lead to incorrect member actions and needs attention to ensure accurate data manipulation.
- **Array Out of Bounds Error**: An array out of bounds error occurs when the delete button is clicked without selecting a member. This error can crash the application, leading to potential data loss and reduced system stability.
2. **Install JavaFX Plugin**
In IntelliJ, go to `File > Settings > Plugins` and search for "JavaFX" to install the required plugin.

3. **Configure Source Directories**
After cloning the repository, right-click on the `src` and `res` directories in the Project pane and select:
`Mark Directory as > Source Directory`
This ensures IntelliJ recognizes them as part of the project's source structure.

4. **Set JDK to Temurin 17**
Go to `File > Project Structure > Project` and set the "Project SDK" to `temurin-17` (or another JDK 17 distribution you have installed).

## About the Team
This project is developed by a dedicated team of software engineering students from the COMP330 course. The team has embraced the challenge of developing a robust membership management system and has shown exceptional commitment to continuous improvement and clear communication.
This project is developed by a dedicated team of software engineering students from the COMP330 course, who have demonstrated commitment to building a reliable membership management system, emphasizing continuous improvement and open communication.

## Contact Information
For more details about the project, or to reach out with questions or suggestions, please contact the following team members:
- **Nahum Gessesse** - Developer - Email: [[email protected]](mailto:[email protected])
- **Xander Estevez** - Developer - Email: [[email protected]](mailto:[email protected])
- **Manali Deb** - QA/Technical Writer - Email: [[email protected]](mailto:[email protected])
- **Alina Zacaria** - Tech Lead - Email: [[email protected]](mailto:[email protected])
- **Andrew Do** - Developer - Email: [[email protected]](mailto:[email protected])
- **Nick Calhoun** - Developer - Email: [[email protected]](mailto:[email protected])
- **Jai Fischer** - Developer - Email: [[email protected]](mailto:[email protected])
For more details or inquiries, please contact:

- **Nahum Gessesse** - Developer
Email: [[email protected]](mailto:[email protected])

- **Xander Estevez** - Developer
Email: [[email protected]](mailto:[email protected])

- **Manali Deb** - QA/Technical Writer
Email: [[email protected]](mailto:[email protected])

- **Alina Zacaria** - Tech Lead
Email: [[email protected]](mailto:[email protected])

- **Andrew Do** - Developer
Email: [[email protected]](mailto:[email protected])

- **Nick Calhoun** - Developer
Email: [[email protected]](mailto:[email protected])

- **Jai Fischer** - Developer
Email: [[email protected]](mailto:[email protected])
13 changes: 13 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,19 @@
<artifactId>javafaker</artifactId>
<version>1.0.2</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.1</version>
<scope>compile</scope>
</dependency>

<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>3.12.4</version>
<scope>compile</scope>
</dependency>
</dependencies>

<build>
Expand Down
47 changes: 43 additions & 4 deletions src/main/project/pages/CreateForm.java
Original file line number Diff line number Diff line change
Expand Up @@ -110,18 +110,57 @@ public int checkIfMemberExists(Member member, Connection conn) {

public Long createUniqueID(Connection conn) {
long id = 10000000000L;
try{
while(true){
try {
while (true) {
String query = "SELECT * FROM members WHERE id_number=?";
PreparedStatement preparedStatement = conn.prepareStatement(query);
preparedStatement.setLong(1, id);
ResultSet rs = preparedStatement.executeQuery();
if(!rs.next()) break;
else id = (long)(Math.random() * (99999999999L - 10000000000L)) + 10000000000L;
if (!rs.next()) break;
else id = (long) (Math.random() * (99999999999L - 10000000000L)) + 10000000000L;
}
} catch (Exception e) {
e.printStackTrace();
}
return id;
}



// Implement the getter methods
public JTextField getFirstNameField() {
return tfFirstName;
}

public JTextField getLastNameField() {
return tfLastName;
}

public JTextField getEmailField() {
return tfEmail;
}

public JTextField getPhoneNumberField() {
return tfPhoneNumber;
}

public JTextField getBdMonthField() {
return bdMonth;
}

public JTextField getBdDayField() {
return bdDay;
}

public JTextField getBdYearField() {
return bdYear;
}

public JTextField getMembershipDurationField() {
return MembershipDuration;
}

public JButton getCreateButton() {
return createButton;
}
}
1 change: 0 additions & 1 deletion src/main/project/pages/HealthClubHomePage.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import main.project.modules.Guest;
import main.project.modules.Member;
import main.project.modules.Status;
import modules.*;
import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import java.awt.*;
Expand Down
141 changes: 141 additions & 0 deletions src/test/TestCreateForm.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
package test;

import com.github.javafaker.Faker;
import main.project.modules.Member;
import main.project.pages.CreateForm;
import org.junit.Before;
import org.junit.Test;
import javax.swing.*;
import java.sql.*;
import static org.junit.Assert.*;
import static org.mockito.Mockito.*;

public class TestCreateForm {

private CreateForm createForm;
private Member memberMock;
private Connection connMock;
private Faker faker;

private JTextField tfFirstName;
private JTextField tfLastName;
private JTextField tfEmail;
private JTextField tfPhoneNumber;
private JTextField tfBdMonth;
private JTextField tfBdDay;
private JTextField tfBdYear;
private JTextField tfMembershipDuration;
private JButton createButton;

@Before
public void setUp() {
faker = new Faker();

tfFirstName = mock(JTextField.class);
tfLastName = mock(JTextField.class);
tfEmail = mock(JTextField.class);
tfPhoneNumber = mock(JTextField.class);
tfBdMonth = mock(JTextField.class);
tfBdDay = mock(JTextField.class);
tfBdYear = mock(JTextField.class);
tfMembershipDuration = mock(JTextField.class);
createButton = mock(JButton.class);
createForm = mock(CreateForm.class);
doReturn(tfFirstName).when(createForm).getFirstNameField();
doReturn(tfLastName).when(createForm).getLastNameField();
doReturn(tfEmail).when(createForm).getEmailField();
doReturn(tfPhoneNumber).when(createForm).getPhoneNumberField();
doReturn(tfBdMonth).when(createForm).getBdMonthField();
doReturn(tfBdDay).when(createForm).getBdDayField();
doReturn(tfBdYear).when(createForm).getBdYearField();
doReturn(tfMembershipDuration).when(createForm).getMembershipDurationField();
doReturn(createButton).when(createForm).getCreateButton();

connMock = mock(Connection.class);
}

@Test
public void testCreateMember_Success() throws Exception {
String firstName = faker.name().firstName();
String lastName = faker.name().lastName();
String email = faker.internet().emailAddress();
long phoneNumber = 4151234567L;
int membershipDuration = faker.number().numberBetween(6, 24);

when(tfFirstName.getText()).thenReturn(firstName);
when(tfLastName.getText()).thenReturn(lastName);
when(tfEmail.getText()).thenReturn(email);
when(tfPhoneNumber.getText()).thenReturn(String.valueOf(phoneNumber));
when(tfBdMonth.getText()).thenReturn("12");
when(tfBdDay.getText()).thenReturn("15");
when(tfBdYear.getText()).thenReturn("1990");
when(tfMembershipDuration.getText()).thenReturn(String.valueOf(membershipDuration));


Member member = new Member(firstName, lastName, email, faker.date().birthday().toInstant().atZone(java.time.ZoneId.systemDefault()).toLocalDate(), phoneNumber);
when(connMock.prepareStatement(anyString())).thenReturn(mock(PreparedStatement.class));

assertTrue(createForm.checkIfMemberExists(member, connMock) == 0);
}

@Test
public void testCreateMember_EmailAlreadyExists() throws Exception {
String firstName = faker.name().firstName();
String lastName = faker.name().lastName();
String email = faker.internet().emailAddress();
long phoneNumber = 6265552349L;
int membershipDuration = faker.number().numberBetween(6, 24);

Member member = new Member(firstName, lastName, email, faker.date().birthday().toInstant().atZone(java.time.ZoneId.systemDefault()).toLocalDate(), phoneNumber);
when(createForm.checkIfMemberExists(any(), eq(connMock))).thenReturn(1);

long res = createForm.createMember(member, membershipDuration);
assertEquals(0, res);
}

@Test
public void testCreateMember_PhoneAlreadyExists() throws Exception {
String firstName = faker.name().firstName();
String lastName = faker.name().lastName();
String email = faker.internet().emailAddress();
long phoneNumber = 8325678901L;
int membershipDuration = faker.number().numberBetween(6, 24);

Member member = new Member(firstName, lastName, email, faker.date().birthday().toInstant().atZone(java.time.ZoneId.systemDefault()).toLocalDate(), phoneNumber);
when(createForm.checkIfMemberExists(any(), eq(connMock))).thenReturn(2); // 2 means phone number exists

long res = createForm.createMember(member, membershipDuration);
assertEquals(0, res);
}

@Test
public void testCreateMember_GenerateMetrics() throws Exception {
String firstName = faker.name().firstName();
String lastName = faker.name().lastName();
String email = faker.internet().emailAddress();
long phoneNumber = 3214509876L;
int membershipDuration = faker.number().numberBetween(6, 24);

Member member = new Member(firstName, lastName, email, faker.date().birthday().toInstant().atZone(java.time.ZoneId.systemDefault()).toLocalDate(), phoneNumber);

long startTime = System.nanoTime();

when(createForm.createMember(any(), anyInt())).thenReturn(12345L);
long memberId = createForm.createMember(member, membershipDuration);

long endTime = System.nanoTime();
long execTime = endTime - startTime;

Runtime runtime = Runtime.getRuntime();
long memBefore = runtime.totalMemory() - runtime.freeMemory();

long memAfter = runtime.totalMemory() - runtime.freeMemory();
long memUsage = memAfter - memBefore;

assertEquals(12345L, memberId);
System.out.println("Execution Time: "+execTime+" ns");
System.out.println("Memory Usage: "+memUsage+ " bytes");
assertTrue("Execution time is too long", execTime < 1000000000L); // 1 second max
verify(createForm, times(1)).createMember(any(), anyInt());
}
}
2 changes: 2 additions & 0 deletions target/checkstyle-cachefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#Thu Dec 05 15:45:49 CST 2024
configuration*?=E3A0464A86BDB5AD0445F393F4DB4760762F386E
Loading

0 comments on commit 32131d7

Please sign in to comment.