Skip to content

Commit

Permalink
feat: 맴버 액션 삭제 기능 구현
Browse files Browse the repository at this point in the history
  • Loading branch information
kunsanglee committed Aug 2, 2024
1 parent f798c9b commit 595fac3
Show file tree
Hide file tree
Showing 11 changed files with 132 additions and 67 deletions.
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
package server.haengdong.application;

import java.util.List;
import java.util.Optional;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import server.haengdong.application.response.MemberBillReportAppResponse;
import server.haengdong.domain.action.Action;
import server.haengdong.domain.action.ActionRepository;
import server.haengdong.domain.action.BillAction;
import server.haengdong.domain.action.BillActionRepository;
import server.haengdong.domain.action.MemberAction;
Expand All @@ -24,7 +21,6 @@ public class ActionService {
private final BillActionRepository billActionRepository;
private final MemberActionRepository memberActionRepository;
private final EventRepository eventRepository;
private final ActionRepository actionRepository;

public List<MemberBillReportAppResponse> getMemberBillReports(String token) {
Event event = eventRepository.findByToken(token)
Expand All @@ -38,20 +34,4 @@ public List<MemberBillReportAppResponse> getMemberBillReports(String token) {
.map(entry -> new MemberBillReportAppResponse(entry.getKey(), entry.getValue()))
.toList();
}

public void deleteAction(String token, Long actionId) {
Event event = eventRepository.findByToken(token)
.orElseThrow(() -> new HaengdongException(HaengdongErrorCode.NOT_FOUND_EVENT));
Action action = actionRepository.findByIdAndEvent(actionId, event)
.orElseThrow(() -> new HaengdongException(HaengdongErrorCode.NOT_FOUND_ACTION));
Optional<BillAction> billAction = billActionRepository.findByAction(action);
Optional<MemberAction> memberAction = memberActionRepository.findByAction(action);

if (billAction.isPresent()) {
billActionRepository.delete(billAction.get());
return;
}

memberAction.ifPresent(memberActionRepository::delete);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,16 @@ private Event findEvent(String token) {
return eventRepository.findByToken(token)
.orElseThrow(() -> new HaengdongException(HaengdongErrorCode.NOT_FOUND_EVENT));
}

@Transactional
public void deleteMemberAction(String token, Long actionId) {
Event event = eventRepository.findByToken(token)
.orElseThrow(() -> new HaengdongException(HaengdongErrorCode.NOT_FOUND_EVENT));
Action action = actionRepository.findByIdAndEvent(actionId, event)
.orElseThrow(() -> new HaengdongException(HaengdongErrorCode.NOT_FOUND_ACTION));
MemberAction memberAction = memberActionRepository.findByAction(action)
.orElseThrow(() -> new HaengdongException(HaengdongErrorCode.NOT_FOUND_MEMBER_ACTION));

memberActionRepository.deleteAllByMemberAction(memberAction.getMemberName(), memberAction.getSequence());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import java.util.List;
import java.util.Optional;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
Expand All @@ -15,4 +16,12 @@ public interface MemberActionRepository extends JpaRepository<MemberAction, Long
List<MemberAction> findAllByEvent(@Param("event") Event event);

Optional<MemberAction> findByAction(Action action);

@Modifying
@Query("""
delete
from MemberAction m
where m.memberName = :memberName and m.action.sequence >= :sequence
""")
void deleteAllByMemberAction(String memberName, Long sequence);
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@ public enum HaengdongErrorCode {
DUPLICATED_MEMBER_ACTION("MA_001", "중복된 인원이 존재합니다."),
INVALID_MEMBER_IN_ACTION("MA_002", "현재 참여하고 있는 인원이 존재합니다."),
INVALID_MEMBER_OUT_ACTION("MA_003", "현재 참여하고 있지 않는 인원이 존재합니다."),
NOT_FOUND_MEMBER_ACTION("MA_400", "존재하지 않는 멤버 액션입니다."),
NOT_FOUND_EVENT("EV_400", "존재하지 않는 행사입니다."),
INTERNAL_SERVER_ERROR("S_001", "서버 내부에서 에러가 발생했습니다."),
NOT_FOUND_ACTION("AC_400", "존재하지 않는 액션입니다.");
NOT_FOUND_ACTION("AC_400", "존재하지 않는 액션입니다."),
INTERNAL_SERVER_ERROR("S_001", "서버 내부에서 에러가 발생했습니다.");

private final String code;
private final String message;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
Expand All @@ -24,14 +23,4 @@ public ResponseEntity<MemberBillReportsResponse> getMemberBillReports(@PathVaria
return ResponseEntity.ok()
.body(MemberBillReportsResponse.of(memberBillReports));
}

@DeleteMapping("/api/events/{eventId}/actions/{actionId}")
public ResponseEntity<Void> deleteAction(
@PathVariable("eventId") String token,
@PathVariable("actionId") Long actionId
) {
actionService.deleteAction(token, actionId);

return ResponseEntity.noContent().build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
Expand Down Expand Up @@ -36,4 +37,14 @@ public ResponseEntity<CurrentMembersResponse> getCurrentMembers(@PathVariable("e
return ResponseEntity.ok()
.body(CurrentMembersResponse.of(currentMembers));
}

@DeleteMapping("/api/events/{eventId}/actions/{actionId}/members")
public ResponseEntity<Void> deleteMemberAction(
@PathVariable("eventId") String token,
@PathVariable("actionId") Long actionId
) {
memberActionService.deleteMemberAction(token, actionId);

return ResponseEntity.ok().build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,18 @@
import static server.haengdong.domain.action.MemberActionStatus.OUT;

import java.util.List;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import server.haengdong.application.response.MemberBillReportAppResponse;
import server.haengdong.domain.action.*;
import server.haengdong.domain.action.Action;
import server.haengdong.domain.action.ActionRepository;
import server.haengdong.domain.action.BillAction;
import server.haengdong.domain.action.BillActionRepository;
import server.haengdong.domain.action.MemberAction;
import server.haengdong.domain.action.MemberActionRepository;
import server.haengdong.domain.event.Event;
import server.haengdong.domain.event.EventRepository;
import server.haengdong.exception.HaengdongErrorCode;
Expand All @@ -27,12 +33,23 @@ class ActionServiceTest {
@Autowired
private EventRepository eventRepository;

@Autowired
private ActionRepository actionRepository;

@Autowired
private BillActionRepository billActionRepository;

@Autowired
private MemberActionRepository memberActionRepository;

@AfterEach
void tearDown() {
billActionRepository.deleteAllInBatch();
memberActionRepository.deleteAllInBatch();
actionRepository.deleteAllInBatch();
eventRepository.deleteAllInBatch();
}

@DisplayName("참여자별 정산 현황을 조회한다.")
@Test
void getMemberBillReports() {
Expand Down Expand Up @@ -72,20 +89,4 @@ void getMemberBillReports1() {
.isInstanceOf(HaengdongException.class)
.hasMessage(HaengdongErrorCode.NOT_FOUND_EVENT.getMessage());
}

@DisplayName("액션을 삭제합니다.")
@Test
void deleteAction() {
Event event = new Event("potato", "potatoHi");
eventRepository.save(event);

Action action = new Action(event, 1L);
MemberAction memberAction = new MemberAction(action, "웨디", MemberActionStatus.IN, 1L);
MemberAction savedMemberAction = memberActionRepository.save(memberAction);
Long memberActionId = savedMemberAction.getId();

actionService.deleteAction("potatoHi", memberActionId);

assertThat(memberActionRepository.findById(memberActionId)).isEmpty();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,16 @@
import static org.assertj.core.api.Assertions.tuple;

import java.util.List;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import server.haengdong.application.request.BillActionAppRequest;
import server.haengdong.domain.action.ActionRepository;
import server.haengdong.domain.action.BillAction;
import server.haengdong.domain.event.Event;
import server.haengdong.domain.action.BillActionRepository;
import server.haengdong.domain.event.Event;
import server.haengdong.domain.event.EventRepository;
import server.haengdong.exception.HaengdongException;

Expand All @@ -22,12 +24,22 @@ class BillActionServiceTest {
@Autowired
private BillActionService billActionService;

@Autowired
private ActionRepository actionRepository;

@Autowired
private EventRepository eventRepository;

@Autowired
private BillActionRepository billActionRepository;

@AfterEach
void tearDown() {
billActionRepository.deleteAllInBatch();
actionRepository.deleteAllInBatch();
eventRepository.deleteAllInBatch();
}

@DisplayName("지출 내역을 생성한다.")
@Test
void saveAllBillAction() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package server.haengdong.application;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatCode;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.assertj.core.api.Assertions.tuple;
import static server.haengdong.domain.action.MemberActionStatus.IN;
import static server.haengdong.domain.action.MemberActionStatus.OUT;

Expand All @@ -17,6 +19,7 @@
import server.haengdong.domain.action.ActionRepository;
import server.haengdong.domain.action.MemberAction;
import server.haengdong.domain.action.MemberActionRepository;
import server.haengdong.domain.action.MemberActionStatus;
import server.haengdong.domain.event.Event;
import server.haengdong.domain.event.EventRepository;
import server.haengdong.exception.HaengdongException;
Expand Down Expand Up @@ -48,7 +51,7 @@ void tearDown() {
void saveMemberActionTest() {
Event event = eventRepository.save(new Event("test", "TOKEN"));
Action action = new Action(event, 1L);
MemberAction memberAction = new MemberAction(action, "망쵸", IN, 1L);
MemberAction memberAction = createMemberAction(action, "망쵸", IN, 1L);
memberActionRepository.save(memberAction);

assertThatCode(() -> memberActionService.saveMemberAction("TOKEN", new MemberActionsSaveAppRequest(
Expand All @@ -61,11 +64,11 @@ void saveMemberActionTest() {
void saveMemberActionTest1() {
Event event = eventRepository.save(new Event("test", "TOKEN"));
Action actionOne = new Action(event, 1L);
MemberAction memberActionOne = new MemberAction(actionOne, "망쵸", IN, 1L);
MemberAction memberActionOne = createMemberAction(actionOne, "망쵸", IN, 1L);
memberActionRepository.save(memberActionOne);

Action actionTwo = new Action(event, 2L);
MemberAction memberActionTwo = new MemberAction(actionTwo, "망쵸", OUT, 1L);
MemberAction memberActionTwo = createMemberAction(actionTwo, "망쵸", OUT, 1L);
memberActionRepository.save(memberActionTwo);

assertThatCode(() -> memberActionService.saveMemberAction("TOKEN", new MemberActionsSaveAppRequest(
Expand All @@ -89,4 +92,49 @@ void getCurrentMembers() {
assertThatThrownBy(() -> memberActionService.getCurrentMembers("token"))
.isInstanceOf(HaengdongException.class);
}

@DisplayName("이벤트에 속한 멤버 액션을 삭제하면 이후에 기록된 해당 참여자의 모든 멤버 액션을 삭제한다.")
@Test
void deleteMemberAction() {
String token = "TOKEN";
Event event = new Event("행동대장 회식", token);
eventRepository.save(event);
Action action = Action.createFirst(event);
MemberAction memberAction1 = createMemberAction(action, "토다리", IN, 1L);
Action targetAction = action.next();
MemberAction memberAction2 = createMemberAction(targetAction, "토다리", OUT, 2L);
MemberAction memberAction3 = createMemberAction(action.next(), "쿠키", IN, 3L);
MemberAction memberAction4 = createMemberAction(action.next(), "웨디", IN, 4L);
MemberAction memberAction5 = createMemberAction(action.next(), "토다리", IN, 5L);
MemberAction memberAction6 = createMemberAction(action.next(), "토다리", OUT, 6L);
MemberAction memberAction7 = createMemberAction(action.next(), "쿠키", OUT, 7L);
memberActionRepository.saveAll(
List.of(memberAction1,
memberAction2,
memberAction3,
memberAction4,
memberAction5,
memberAction6,
memberAction7)
);

memberActionService.deleteMemberAction(token, targetAction.getId());
List<MemberAction> memberActions = memberActionRepository.findAll();

assertThat(memberActions).hasSize(4)
.extracting("id", "memberName", "status")
.containsExactly(
tuple(memberAction1.getId(), "토다리", IN),
tuple(memberAction3.getId(), "쿠키", IN),
tuple(memberAction4.getId(), "웨디", IN),
tuple(memberAction7.getId(), "쿠키", OUT)
);
}

private static MemberAction createMemberAction(Action action,
String memberName,
MemberActionStatus memberActionStatus,
long memberGroupId) {
return new MemberAction(action, memberName, memberActionStatus, memberGroupId);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
import static org.hamcrest.Matchers.equalTo;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.BDDMockito.given;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
Expand Down Expand Up @@ -47,13 +46,4 @@ void getMemberBillReports() throws Exception {
.andExpect(MockMvcResultMatchers.jsonPath("$.reports[1].price").value(equalTo(200_000)));

}

@DisplayName("액션을 삭제한다.")
@Test
void deleteAction() throws Exception {
mockMvc.perform(delete("/api/events/{eventId}/actions/{actionId}", "token", "1")
.accept(MediaType.APPLICATION_JSON))
.andDo(print())
.andExpect(status().isNoContent());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@
import static org.hamcrest.Matchers.equalTo;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.BDDMockito.given;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.delete;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

import com.fasterxml.jackson.databind.ObjectMapper;
Expand All @@ -17,7 +19,6 @@
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import server.haengdong.application.MemberActionService;
import server.haengdong.application.response.CurrentMemberAppResponse;
import server.haengdong.presentation.request.MemberActionsSaveRequest;
Expand Down Expand Up @@ -61,7 +62,18 @@ void getCurrentMembers() throws Exception {
.accept(MediaType.APPLICATION_JSON))
.andDo(print())
.andExpect(status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("$.members[0].name").value(equalTo("소하")))
.andExpect(MockMvcResultMatchers.jsonPath("$.members[1].name").value(equalTo("토다리")));
.andExpect(jsonPath("$.members[0].name").value(equalTo("소하")))
.andExpect(jsonPath("$.members[1].name").value(equalTo("토다리")));
}

@DisplayName("이벤트에 속한 멤버 액션을 삭제하면 이후에 기록된 해당 참여자의 모든 멤버 액션을 삭제한다.")
@Test
void deleteMemberAction() throws Exception {
String token = "TOKEN";
Long memberActionId = 2L;

mockMvc.perform(delete(String.format("/api/events/%s/actions/%d/members", token, memberActionId)))
.andDo(print())
.andExpect(status().isOk());
}
}

0 comments on commit 595fac3

Please sign in to comment.