Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BE] 행사 참여 인원 이름 변경 기능 구현 #197

Merged
merged 3 commits into from
Aug 5, 2024
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
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import server.haengdong.application.request.EventAppRequest;
import server.haengdong.application.request.MemberUpdateAppRequest;
import server.haengdong.application.response.ActionAppResponse;
import server.haengdong.application.response.EventAppResponse;
import server.haengdong.application.response.EventDetailAppResponse;
Expand Down Expand Up @@ -98,4 +99,22 @@ public MembersAppResponse findAllMembers(String token) {

return new MembersAppResponse(memberNames);
}

@Transactional
public void updateMember(String token, String memberName, MemberUpdateAppRequest request) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a: memberName에 해당하는 멤버가 존재하는지 검증할 필요가 있을지 논의가 필요해요.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

필요가 있지 않을까요?

Event event = eventRepository.findByToken(token)
.orElseThrow(() -> new HaengdongException(HaengdongErrorCode.NOT_FOUND_EVENT));
String updatedMemberName = request.name();
validateMemberNameUnique(event, updatedMemberName);

memberActionRepository.findAllByAction_EventAndMemberName(event, memberName)
.forEach(memberAction -> memberAction.updateMemberName(updatedMemberName));
Comment on lines +110 to +111
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

r: update와 where절로 쿼리 하나로 처리할 수 있을 것 같아요. 지금은 select와 update 쿼리가 n개 발생해요.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

성능을 비교해서 알려주세요. 👍

}

private void validateMemberNameUnique(Event event, String updatedMemberName) {
boolean isMemberNameExist = memberActionRepository.existsByAction_EventAndMemberName(event, updatedMemberName);
if (isMemberNameExist) {
throw new HaengdongException(HaengdongErrorCode.DUPLICATED_MEMBER_NAME);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package server.haengdong.application.request;

public record MemberUpdateAppRequest(String name) {
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ public MemberAction(Action action, String memberName, MemberActionStatus status,
this.memberGroupId = memberGroupId;
}

public boolean isSameName(String name) {
return memberName.equals(name);
public void updateMemberName(String memberName) {
this.memberName = memberName;
}

public boolean isIn() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,8 @@ public interface MemberActionRepository extends JpaRepository<MemberAction, Long
where m.memberName = :memberName and m.action.sequence >= :sequence
""")
void deleteAllByMemberNameAndMinSequence(String memberName, Long sequence);

List<MemberAction> findAllByAction_EventAndMemberName(Event event, String memberName);

boolean existsByAction_EventAndMemberName(Event event, String updatedMemberName);
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,15 @@ public enum HaengdongErrorCode {
BAD_REQUEST("R_001", "잘못된 요청입니다."),
NO_RESOURCE_REQUEST("R_002", "잘못된 엔드포인트입니다."),
MESSAGE_NOT_READABLE("R_003", "읽을 수 없는 요청 형식입니다."),
INTERNAL_SERVER_ERROR("S_001", "서버 내부에서 에러가 발생했습니다."),
DUPLICATED_MEMBER_NAME("EV_001", "중복된 행사 참여 인원 이름이 존재합니다."),
NOT_FOUND_EVENT("EV_400", "존재하지 않는 행사입니다."),
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_BILL_ACTION("BA_400", "존재하지 않는 지출 액션입니다."),
NOT_FOUND_ACTION("AC_400", "존재하지 않는 액션입니다."),
INTERNAL_SERVER_ERROR("S_001", "서버 내부에서 에러가 발생했습니다."),
;

private final String code;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import server.haengdong.application.EventService;
import server.haengdong.presentation.request.EventSaveRequest;
import server.haengdong.presentation.request.MemberUpdateRequest;
import server.haengdong.presentation.response.EventDetailResponse;
import server.haengdong.presentation.response.EventResponse;
import server.haengdong.presentation.response.MembersResponse;
Expand Down Expand Up @@ -48,4 +50,15 @@ public ResponseEntity<MembersResponse> findAllMembers(@PathVariable("eventId") S

return ResponseEntity.ok(response);
}

@PutMapping("/api/events/{eventId}/members/{memberName}")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a: API 명세대로 잘 구현되었는데요, memberName을 PathVariable 대신에 body에 넣는 것은 어떤가요?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

나중에는 memberName 대신 memberId를 사용할 것 같아서 현재의 방식을 사용해도 괜찮을 것 같아요.

public ResponseEntity<Void> updateMember(
@PathVariable("eventId") String token,
@PathVariable("memberName") String memberName,
@Valid @RequestBody MemberUpdateRequest request
) {
eventService.updateMember(token, memberName, request.toAppRequest());

return ResponseEntity.ok().build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package server.haengdong.presentation.request;

import jakarta.validation.constraints.NotBlank;
import server.haengdong.application.request.MemberUpdateAppRequest;

public record MemberUpdateRequest(
@NotBlank String name
) {

public MemberUpdateAppRequest toAppRequest() {
return new MemberUpdateAppRequest(name);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@


import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.assertj.core.api.Assertions.tuple;
import static org.mockito.BDDMockito.given;
import static server.haengdong.domain.action.MemberActionStatus.IN;
Expand All @@ -15,6 +16,7 @@
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import server.haengdong.application.request.EventAppRequest;
import server.haengdong.application.request.MemberUpdateAppRequest;
import server.haengdong.application.response.ActionAppResponse;
import server.haengdong.application.response.EventAppResponse;
import server.haengdong.application.response.EventDetailAppResponse;
Expand All @@ -28,6 +30,7 @@
import server.haengdong.domain.event.Event;
import server.haengdong.domain.event.EventRepository;
import server.haengdong.domain.event.EventTokenProvider;
import server.haengdong.exception.HaengdongException;

@SpringBootTest
class EventServiceTest {
Expand Down Expand Up @@ -131,4 +134,50 @@ void findAllMembersTest() {

assertThat(membersAppResponse.memberNames()).containsExactlyInAnyOrder("토다리", "쿠키");
}

@DisplayName("행사 참여 인원의 이름을 변경한다.")
@Test
void updateMember() {
String token = "행동대장 회식";
Event event = new Event("행동대장 회식", token);
MemberAction memberAction1 = new MemberAction(new Action(event, 1L), "토다리", IN, 1L);
MemberAction memberAction2 = new MemberAction(new Action(event, 2L), "쿠키", IN, 1L);
MemberAction memberAction3 = new MemberAction(new Action(event, 3L), "웨디", IN, 2L);
MemberAction memberAction4 = new MemberAction(new Action(event, 4L), "쿠키", OUT, 3L);
MemberAction memberAction5 = new MemberAction(new Action(event, 5L), "쿠키", IN, 4L);
MemberAction memberAction6 = new MemberAction(new Action(event, 6L), "쿠키", OUT, 5L);
eventRepository.save(event);
memberActionRepository.saveAll(List.of(
memberAction1, memberAction2, memberAction3, memberAction4, memberAction5, memberAction6
));

eventService.updateMember(token, "쿠키", new MemberUpdateAppRequest("쿡쿡"));

List<MemberAction> foundMemberActions = memberActionRepository.findAllByEvent(event);
assertThat(foundMemberActions)
.extracting(MemberAction::getId, MemberAction::getMemberName)
.contains(
tuple(memberAction1.getId(), "토다리"),
tuple(memberAction2.getId(), "쿡쿡"),
tuple(memberAction3.getId(), "웨디"),
tuple(memberAction4.getId(), "쿡쿡"),
tuple(memberAction5.getId(), "쿡쿡"),
tuple(memberAction6.getId(), "쿡쿡")
);
}

@DisplayName("참여 인원 이름을 이미 존재하는 행사 참여 인원과 동일한 이름으로 변경할 수 없다.")
@Test
void updateMember1() {
String token = "행동대장 회식";
Event event = new Event("행동대장 회식", token);
MemberAction memberAction1 = new MemberAction(new Action(event, 1L), "토다리", IN, 1L);
MemberAction memberAction2 = new MemberAction(new Action(event, 2L), "쿠키", IN, 1L);
MemberAction memberAction3 = new MemberAction(new Action(event, 3L), "웨디", IN, 2L);
eventRepository.save(event);
memberActionRepository.saveAll(List.of(memberAction1, memberAction2, memberAction3));

assertThatThrownBy(() -> eventService.updateMember(token, "쿠키", new MemberUpdateAppRequest("토다리")))
.isInstanceOf(HaengdongException.class);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import static org.mockito.BDDMockito.given;
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.request.MockMvcRequestBuilders.put;
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;
Expand All @@ -24,6 +25,7 @@
import server.haengdong.application.response.EventDetailAppResponse;
import server.haengdong.application.response.MembersAppResponse;
import server.haengdong.presentation.request.EventSaveRequest;
import server.haengdong.presentation.request.MemberUpdateRequest;

@WebMvcTest(EventController.class)
class EventControllerTest {
Expand Down Expand Up @@ -80,4 +82,18 @@ void findAllMembersTest() throws Exception {
.andExpect(jsonPath("$.memberNames[0]").value("토다리"))
.andExpect(jsonPath("$.memberNames[1]").value("쿠키"));
}

@DisplayName("행사 참여 인원의 이름을 수정한다.")
@Test
void updateMember() throws Exception {
String token = "TOKEN";
MemberUpdateRequest memberUpdateRequest = new MemberUpdateRequest("변경된 이름");
String requestBody = objectMapper.writeValueAsString(memberUpdateRequest);

mockMvc.perform(put("/api/events/{eventId}/members/{memberName}", token, "변경 전 이름")
.contentType(MediaType.APPLICATION_JSON)
.content(requestBody))
.andDo(print())
.andExpect(status().isOk());
}
}
Loading