Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 28 additions & 1 deletion API_DOCUMENTATION.md
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,33 @@ All API requests should be made to the following base URL (Spring Boot's default
- **Add a Member to a Team:** `POST /{teamMemberId}/team/{teamId}`
- **Description:** Adds a team member to a team.

- **Mass Assign to a Team:** `POST /team/{teamId}/mass-assign`
- **Request Body:**
```json
[1, 2, 3, 4]
```
- **Response Body:**
```json
[
{
"isMemberOfId": 101,
"teamMemberId": 1,
"teamId": 42
},
{
"isMemberOfId": 102,
"teamMemberId": 2,
"teamId": 42
},
{
"isMemberOfId": 103,
"teamMemberId": 3,
"teamId": 42
}
]
```
- **Description:** Adds multiple members to a team at once. If any member is already in the team they will be skipped. If any member does not exist, the entire request will fail with a 400 error.

- **Remove a Member from a Team:** `DELETE /{teamMemberId}/team/{teamId}`
- **Description:** Removes a team member from a team.

Expand Down Expand Up @@ -589,7 +616,7 @@ All API requests should be made to the following base URL (Spring Boot's default
- **Mass Assign Members to a Task:** `POST /{taskId}/mass-assign`
- **Request Body:**
```json
[1, 2, 3, 4]
[1, 2, 3, 4]
```
- **Response Body:**
```json
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package com.example.task_manager.controller;

import com.example.task_manager.DTO.IsMemberOfDTO;
import com.example.task_manager.service.IsMemberOfService;

import java.util.List;

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

Expand All @@ -25,6 +29,18 @@ public ResponseEntity<?> addMemberToTeam(@PathVariable int teamMemberId, @PathVa
}
}

//mass assign members to a team
@PostMapping("/team/{teamId}/mass-assign")
public ResponseEntity<?> massAssignToTeam(@PathVariable int teamId, @RequestBody List<Integer> teamMemberIds) {
try {
List<IsMemberOfDTO> isMemberOfDTOs = isMemberOfService.massAssignToTeam(teamId, teamMemberIds);
return ResponseEntity.ok(isMemberOfDTOs);
}
catch (RuntimeException e) {
return ResponseEntity.badRequest().body(e.getMessage());
}
}

// Remove Member from Team
@DeleteMapping("/{teamMemberId}/team/{teamId}")
public ResponseEntity<?> removeMemberFromTeam(@PathVariable int teamMemberId, @PathVariable int teamId) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,14 @@
import com.example.task_manager.DTO.TaskDTO;
import com.example.task_manager.DTO.TeamDTO;
import com.example.task_manager.service.TeamMemberService;

import java.util.List;

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import com.example.task_manager.service.IsMemberOfService;

@RestController
@RequestMapping("/api/members/actions")
public class TeamMemberController {
Expand Down Expand Up @@ -37,8 +40,7 @@ public ResponseEntity<?> massAssignToTask(@PathVariable int taskId, @RequestBody
try {
List<IsAssignedDTO> isAssignedDTOs = teamMemberService.massAssignToTask(taskId, teamMemberIds);
return ResponseEntity.ok(isAssignedDTOs);
}
catch (RuntimeException e) {
} catch (RuntimeException e) {
return ResponseEntity.badRequest().body(e.getMessage());
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package com.example.task_manager.service;

import java.util.ArrayList;
import java.util.List;

import org.springframework.stereotype.Service;

import com.example.task_manager.DTO.IsMemberOfDTO;
Expand Down Expand Up @@ -40,42 +43,69 @@ public IsMemberOfService(IsMemberOfRepository isMemberOfRepository,
* @param teamId The ID of the team to which the member should be added.
* @return
*/
public IsMemberOfDTO addMemberToTeam(int teamMemberId, int teamId) {
System.out.println("BELLO it is running yay");
public IsMemberOfDTO addMemberToTeam(int teamMemberId, int teamId) {
System.out.println("BELLO it is running yay");

Team team = teamRepository.findById(teamId)
.orElseThrow(() -> new RuntimeException("Team not found with ID: " + teamId));

TeamMember teamMember = teamMemberRepository.findById(teamMemberId)
.orElseThrow(() -> new RuntimeException("Team Member not found with ID: " + teamMemberId));
Team team = teamRepository.findById(teamId)
.orElseThrow(() -> new RuntimeException("Team not found with ID: " + teamId));

System.out.println("MINIONS");

// Check if the member is already in the team
boolean alreadyMember = isMemberOfRepository.existsByTeamMemberAccountIdAndTeamTeamId(teamMemberId, teamId);
if (alreadyMember) {
throw new RuntimeException("Team Member is already in this team. No action needed.");
}
TeamMember teamMember = teamMemberRepository.findById(teamMemberId)
.orElseThrow(() -> new RuntimeException("Team Member not found with ID: " + teamMemberId));

System.out.println("TONIGHT!!! WE! ARE GOING! TO STEAL! THE MOON!!");

System.out.println("MINIONS");

// Create membership
IsMemberOf isMemberOf = new IsMemberOf(teamMember, team);
isMemberOf = isMemberOfRepository.save(isMemberOf);
isMemberOfRepository.flush();
// Check if the member is already in the team
boolean alreadyMember = isMemberOfRepository.existsByTeamMemberAccountIdAndTeamTeamId(teamMemberId, teamId);
if (alreadyMember) {
throw new RuntimeException("Team Member is already in this team. No action needed.");
}

System.out.println("DOCTOR NEFARIO");
System.out.println("TONIGHT!!! WE! ARE GOING! TO STEAL! THE MOON!!");

team = teamRepository.findById(teamId).orElseThrow(() -> new RuntimeException("RAHHHH can't find it"));
System.out.println("bruh");
// Create membership
IsMemberOf isMemberOf = new IsMemberOf(teamMember, team);
isMemberOf = isMemberOfRepository.save(isMemberOf);
isMemberOfRepository.flush();

//call assigned to team notification method
notifService.notifyTeamAssignment(teamMember, team);
System.out.println("DOCTOR NEFARIO");

// Return DTO
return convertToDTO(isMemberOf);
}
team = teamRepository.findById(teamId).orElseThrow(() -> new RuntimeException("RAHHHH can't find it"));
System.out.println("bruh");

//call assigned to team notification method
notifService.notifyTeamAssignment(teamMember, team);

// Return DTO
return convertToDTO(isMemberOf);
}

//add multiple members to a team at once
public List<IsMemberOfDTO> massAssignToTeam(int teamId, List<Integer> teamMemberIds) {
Team team = teamRepository.findById(teamId)
.orElseThrow(() -> new RuntimeException("Team not found with ID: " + teamId));

List<IsMemberOfDTO> newMembers = new ArrayList<>();

for (Integer teamMemberId : teamMemberIds) {
TeamMember teamMember = teamMemberRepository.findById(teamMemberId)
.orElseThrow(() -> new RuntimeException("Team Member not found with ID: " + teamMemberId));

boolean alreadyMember = isMemberOfRepository.existsByTeamMemberAccountIdAndTeamTeamId(teamMemberId, teamId);

if (!alreadyMember) {
IsMemberOf isMemberOf = new IsMemberOf(teamMember, team);
isMemberOf = isMemberOfRepository.save(isMemberOf);

notifService.notifyTeamAssignment(teamMember, team);

newMembers.add(convertToDTO(isMemberOf));
}
}

isMemberOfRepository.flush();

return newMembers;
}

/**
* Removes a TeamMember from a Team.
Expand Down Expand Up @@ -122,8 +152,8 @@ public boolean isMemberOfTeam(int teamMemberId, int teamId) {
private IsMemberOfDTO convertToDTO(IsMemberOf isMemberOf) {
return new IsMemberOfDTO(
isMemberOf.getId(),
isMemberOf.getTeam().getTeamId(),
isMemberOf.getTeamMember().getAccountId()
isMemberOf.getTeamMember().getAccountId(),
isMemberOf.getTeam().getTeamId()
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@

import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;

@SpringBootTest
@ActiveProfiles("test")
class TaskManagerApplicationTests {

@Test
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
package com.example.task_manager.controller_tests;

import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;

import java.util.List;

import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;

import com.example.task_manager.DTO.IsMemberOfDTO;
Expand Down Expand Up @@ -44,6 +48,50 @@ void testAddMemberToTeam() throws Exception {
.andExpect(jsonPath("$.teamId").value(teamId));
}

/*
* Test adding multiple members to a team at once
*/
@Test
void testMassAssignToTeam() throws Exception {
int teamId = 100;
List<Integer> teamMemberIds = List.of(101, 102, 103);

List<IsMemberOfDTO> mockMemberships = List.of(
new IsMemberOfDTO(1, 101, teamId),
new IsMemberOfDTO(2, 102, teamId),
new IsMemberOfDTO(3, 103, teamId));

when(isMemberOfService.massAssignToTeam(eq(teamId), eq(teamMemberIds))).thenReturn(mockMemberships);

String jsonRequest = "[101, 102, 103]";

mockMvc.perform(post("/api/memberships/team/" + teamId + "/mass-assign")
.contentType("application/json")
.content(jsonRequest))
.andExpect(status().isOk())
.andExpect(jsonPath("$.length()").value(3))
.andExpect(jsonPath("$[0].teamMemberId").value(101))
.andExpect(jsonPath("$[1].teamMemberId").value(102))
.andExpect(jsonPath("$[2].teamMemberId").value(103));
}

@Test
void testMassAssignToTeam_TeamNotFound() throws Exception {
int teamId = 999;
List<Integer> teamMemberIds = List.of(101, 102, 103);

String jsonRequest = "[101, 102, 103]";

when(isMemberOfService.massAssignToTeam(eq(teamId), eq(teamMemberIds)))
.thenThrow(new RuntimeException("Team not found"));

mockMvc.perform(post("/api/memberships/team/" + teamId + "/mass-assign")
.contentType("application/json")
.content(jsonRequest))
.andExpect(status().isBadRequest())
.andExpect(content().string("Team not found"));
}

/**
* Test Remove Member from Team
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,16 @@

import static org.junit.jupiter.api.Assertions.*;

import java.util.List;

import org.junit.jupiter.api.Test;
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.ActiveProfiles;

import jakarta.transaction.Transactional;

import com.example.task_manager.DTO.IsMemberOfDTO;
import com.example.task_manager.DTO.TeamDTO;
import com.example.task_manager.DTO.TeamMemberDTO;
import com.example.task_manager.test_helpers.ServiceTestHelper;
Expand Down Expand Up @@ -60,10 +63,88 @@ void testAddMemberToSameTeamTwice() {
isMemberOfService.addMemberToTeam(teamMember.getAccountId(), team.getTeamId());

Exception exception = assertThrows(RuntimeException.class,
() -> isMemberOfService.addMemberToTeam(teamMember.getAccountId(), team.getTeamId()));
() -> isMemberOfService.addMemberToTeam(teamMember.getAccountId(), team.getTeamId()));

assertTrue(exception.getMessage().contains("Team Member is already in this team"));
}

@Test
void testMassAddMembersToTeam() {
TeamMemberDTO teamLead = createUniqueTeamMemberDTO();
TeamDTO team = createUniqueTeamDTO(teamLead);

TeamMemberDTO member1 = createUniqueTeamMemberDTO();
TeamMemberDTO member2 = createUniqueTeamMemberDTO();
TeamMemberDTO member3 = createUniqueTeamMemberDTO();

List<Integer> memberIds = List.of(
member1.getAccountId(),
member2.getAccountId(),
member3.getAccountId()
);

List<IsMemberOfDTO> results = isMemberOfService.massAssignToTeam(team.getTeamId(), memberIds);

assertEquals(3, results.size());

assertTrue(isMemberOfService.isMemberOfTeam(member1.getAccountId(), team.getTeamId()));
assertTrue(isMemberOfService.isMemberOfTeam(member2.getAccountId(), team.getTeamId()));
assertTrue(isMemberOfService.isMemberOfTeam(member3.getAccountId(), team.getTeamId()));
}

@Test
void testMassAddMembersWithOneNonExistentId() {
TeamMemberDTO teamLead = createUniqueTeamMemberDTO();
TeamDTO team = createUniqueTeamDTO(teamLead);

TeamMemberDTO member1 = createUniqueTeamMemberDTO();
TeamMemberDTO member2 = createUniqueTeamMemberDTO();
int nonExistentId = 999999;

List<Integer> memberIds = List.of(
member1.getAccountId(),
nonExistentId,
member2.getAccountId()
);

Exception exception = assertThrows(RuntimeException.class, () ->
isMemberOfService.massAssignToTeam(team.getTeamId(), memberIds)
);

assertTrue(exception.getMessage().contains("Team Member not found"));
}

@Test
void testMassAddMembersToNonExistentTeam() {
TeamMemberDTO member = createUniqueTeamMemberDTO();

Exception exception = assertThrows(RuntimeException.class, () ->
isMemberOfService.massAssignToTeam(999999, List.of(member.getAccountId()))
);

assertTrue(exception.getMessage().contains("Team not found"));
}

@Test
void testMassAddMembersAlreadyInTeam() {
TeamMemberDTO teamLead = createUniqueTeamMemberDTO();
TeamDTO team = createUniqueTeamDTO(teamLead);

TeamMemberDTO member1 = createUniqueTeamMemberDTO();
TeamMemberDTO member2 = createUniqueTeamMemberDTO();

isMemberOfService.addMemberToTeam(member1.getAccountId(), team.getTeamId());

List<Integer> memberIds = List.of(
member1.getAccountId(), // already in team
member2.getAccountId()
);

List<IsMemberOfDTO> results = isMemberOfService.massAssignToTeam(team.getTeamId(), memberIds);

assertEquals(1, results.size());
assertTrue(isMemberOfService.isMemberOfTeam(member2.getAccountId(), team.getTeamId()));
}

@Test
void testRemoveMemberFromTeam() {
Expand Down
Loading