Skip to content

Commit

Permalink
Merge branch 'be-dev' into feature/#189
Browse files Browse the repository at this point in the history
  • Loading branch information
Arachneee authored Aug 5, 2024
2 parents 8057a90 + 135fdd6 commit 4661cef
Show file tree
Hide file tree
Showing 13 changed files with 214 additions and 8 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/backend-dev.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ on:

jobs:
build:
runs-on: ubuntu-latest
runs-on: [ self-hosted, backend-dev ]

defaults:
run:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/backend-pull-request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ on:

jobs:
build:
runs-on: ubuntu-latest
runs-on: [ self-hosted, backend-dev ]

defaults:
run:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@
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;
import server.haengdong.application.response.MembersAppResponse;
import server.haengdong.domain.action.BillAction;
import server.haengdong.domain.action.BillActionRepository;
import server.haengdong.domain.action.MemberAction;
Expand Down Expand Up @@ -88,4 +90,31 @@ private List<ActionAppResponse> getActionAppResponses(

return actionAppResponses;
}

public MembersAppResponse findAllMembers(String token) {
Event event = eventRepository.findByToken(token)
.orElseThrow(() -> new HaengdongException(HaengdongErrorCode.NOT_FOUND_EVENT));

List<String> memberNames = memberActionRepository.findAllUniqueMemberByEvent(event);

return new MembersAppResponse(memberNames);
}

@Transactional
public void updateMember(String token, String memberName, MemberUpdateAppRequest request) {
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));
}

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
@@ -0,0 +1,8 @@
package server.haengdong.application.response;

import java.util.List;

public record MembersAppResponse(
List<String> memberNames
) {
}
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 @@ -15,6 +15,13 @@ public interface MemberActionRepository extends JpaRepository<MemberAction, Long
@Query("select m from MemberAction m join fetch m.action where m.action.event = :event")
List<MemberAction> findAllByEvent(@Param("event") Event event);

@Query("""
select distinct m.memberName
from MemberAction m
where m.action.event = :event
""")
List<String> findAllUniqueMemberByEvent(Event event);

@Modifying
@Query("""
delete
Expand All @@ -32,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,12 +6,15 @@
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;
import server.haengdong.presentation.response.StepsResponse;

@RequiredArgsConstructor
Expand Down Expand Up @@ -40,4 +43,22 @@ public ResponseEntity<StepsResponse> findActions(@PathVariable("eventId") String

return ResponseEntity.ok(stepsResponse);
}

@GetMapping("/api/events/{eventId}/members")
public ResponseEntity<MembersResponse> findAllMembers(@PathVariable("eventId") String token) {
MembersResponse response = MembersResponse.of(eventService.findAllMembers(token));

return ResponseEntity.ok(response);
}

@PutMapping("/api/events/{eventId}/members/{memberName}")
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
@@ -0,0 +1,13 @@
package server.haengdong.presentation.response;

import java.util.List;
import server.haengdong.application.response.MembersAppResponse;

public record MembersResponse(
List<String> memberNames
) {

public static MembersResponse of(MembersAppResponse response) {
return new MembersResponse(response.memberNames());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@


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;
import static server.haengdong.domain.action.MemberActionStatus.OUT;

import java.util.List;
import org.junit.jupiter.api.AfterEach;
Expand All @@ -13,19 +16,21 @@
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;
import server.haengdong.application.response.MembersAppResponse;
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.action.MemberActionStatus;
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 @@ -84,9 +89,9 @@ void findEventTest() {
void findActionsTest() {
Event event = new Event("ν–‰λ™λŒ€μž₯ νšŒμ‹", "웨디_토큰");
Action action = new Action(event, 1L);
MemberAction memberAction = new MemberAction(action, "토닀리", MemberActionStatus.IN, 1L);
MemberAction memberAction = new MemberAction(action, "토닀리", IN, 1L);
Action action1 = new Action(event, 2L);
MemberAction memberAction1 = new MemberAction(action1, "μΏ ν‚€", MemberActionStatus.IN, 1L);
MemberAction memberAction1 = new MemberAction(action1, "μΏ ν‚€", IN, 1L);
Action action2 = new Action(event, 3L);
BillAction billAction = new BillAction(action2, "λ½•λ‚˜λ¬΄μŸμ΄μ‘±λ°œ", 30000L);
eventRepository.save(event);
Expand All @@ -107,4 +112,72 @@ void findActionsTest() {
tuple(3L, "λ½•λ‚˜λ¬΄μŸμ΄μ‘±λ°œ", 30000L, 3L, "BILL")
);
}

@DisplayName("행사에 μ°Έμ—¬ν•œ 전체 인원을 쀑볡 없이 μ‘°νšŒν•œλ‹€.")
@Test
void findAllMembersTest() {
String token = "웨디_토큰";
Event event = new Event("ν–‰λ™λŒ€μž₯ νšŒμ‹", token);
Action action1 = new Action(event, 1L);
Action action2 = new Action(event, 2L);
Action action3 = new Action(event, 3L);
Action action4 = new Action(event, 4L);
BillAction billAction = new BillAction(action3, "λ½•λ‚˜λ¬΄μŸμ΄μ‘±λ°œ", 30000L);
MemberAction memberAction1 = new MemberAction(action1, "토닀리", IN, 1L);
MemberAction memberAction2 = new MemberAction(action2, "μΏ ν‚€", IN, 1L);
MemberAction memberAction3 = new MemberAction(action4, "μΏ ν‚€", OUT, 1L);
eventRepository.save(event);
billActionRepository.save(billAction);
memberActionRepository.saveAll(List.of(memberAction1, memberAction2, memberAction3));

MembersAppResponse membersAppResponse = eventService.findAllMembers(token);

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
@@ -1,14 +1,17 @@
package server.haengdong.presentation;

import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
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;

import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.List;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
Expand All @@ -20,7 +23,9 @@
import server.haengdong.application.request.EventAppRequest;
import server.haengdong.application.response.EventAppResponse;
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 @@ -63,4 +68,32 @@ void findEventTest() throws Exception {
.andExpect(status().isOk())
.andExpect(jsonPath("$.eventName").value("ν–‰λ™λŒ€μž₯ νšŒμ‹"));
}

@DisplayName("행사에 μ°Έμ—¬ν•œ 전체 인원을 쀑볡 없이 μ‘°νšŒν•œλ‹€.")
@Test
void findAllMembersTest() throws Exception {
MembersAppResponse memberAppResponse = new MembersAppResponse(List.of("토닀리", "μΏ ν‚€"));
given(eventService.findAllMembers(anyString())).willReturn(memberAppResponse);

mockMvc.perform(get("/api/events/{eventId}/members", "TOKEN"))
.andDo(print())
.andExpect(status().isOk())
.andExpect(jsonPath("$.memberNames").isArray())
.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());
}
}

0 comments on commit 4661cef

Please sign in to comment.