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] 페어룸 삭제 기능 구현 #753

Merged
merged 8 commits into from
Oct 11, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.PathVariable;
Expand Down Expand Up @@ -92,4 +93,10 @@ public ResponseEntity<PairRoomExistResponse> pairRoomExists(@RequestParam("acces

return ResponseEntity.ok(response);
}

@DeleteMapping("/pair-room/{accessCode}")
public ResponseEntity<Void> deletePairRoom(@PathVariable("accessCode") final String accessCode) {
pairRoomService.deletePairRoom(accessCode);
return ResponseEntity.noContent().build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -74,4 +74,11 @@ ResponseEntity<List<PairRoomMemberResponse>> getPairRooms(
@ApiResponse(responseCode = "200", description = "페어룸 존재 여부", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE,
schema = @Schema(implementation = PairRoomExistResponse.class)))
ResponseEntity<PairRoomExistResponse> pairRoomExists(String accessCode);

Copy link
Member

Choose a reason for hiding this comment

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

문서화 구웃

Copy link
Contributor Author

Choose a reason for hiding this comment

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

끼욧

@Operation(summary = "페어룸을 삭제한다.")
@ApiResponse(responseCode = "204", description = "페어룸 삭제 성공")
ResponseEntity<Void> deletePairRoom(
@Parameter(description = "페어룸 접근 코드", required = true)
String accessCode
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@
public enum PairRoomStatus {

IN_PROGRESS,
COMPLETED;
COMPLETED,
DELETE;
Copy link
Member

Choose a reason for hiding this comment

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

mysql 컬럼이 현재 enum으로 되어 있어서 변경해줘야 할 거 같은데 그건 제가 하겠습니다

Copy link
Contributor Author

Choose a reason for hiding this comment

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

감사합니당!

Copy link
Member

Choose a reason for hiding this comment

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

아 생각해보니까 delete 보나 deleted가 더 좋을 거 같아요..!


private static final Map<String, PairRoomStatus> STATUS = Arrays.stream(values())
.collect(Collectors.toMap(PairRoomStatus::name, Function.identity()));
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package site.coduo.pairroom.exception;

public class DeletePairRoomException extends PairRoomException {

public DeletePairRoomException(final String message) {
super(message);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,10 @@ public void swapNavigatorWithDriver() {
this.driver = temp;
}

public boolean isDelete() {
return status == PairRoomStatus.DELETE;
}

@Override
public boolean equals(final Object o) {
if (this == o) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import org.springframework.data.jpa.repository.JpaRepository;

import site.coduo.pairroom.domain.PairRoomStatus;
import site.coduo.pairroom.domain.accesscode.AccessCode;
import site.coduo.pairroom.exception.PairRoomNotFoundException;

Expand All @@ -22,4 +23,6 @@ default PairRoomEntity fetchByAccessCode(AccessCode accessCode) {
}

boolean existsByAccessCode(String generatedAccessCode);

boolean existsByAccessCodeAndStatusNot(String accessCode, PairRoomStatus status);
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import site.coduo.pairroom.domain.PairRoomStatus;
import site.coduo.pairroom.domain.accesscode.AccessCode;
import site.coduo.pairroom.domain.accesscode.UUIDAccessCodeGenerator;
import site.coduo.pairroom.exception.DeletePairRoomException;
import site.coduo.pairroom.repository.PairRoomEntity;
import site.coduo.pairroom.repository.PairRoomMemberEntity;
import site.coduo.pairroom.repository.PairRoomMemberRepository;
Expand Down Expand Up @@ -56,7 +57,7 @@ public String savePairRoom(final PairRoomCreateRequest request, @Nullable final
}

public boolean existsByAccessCode(final String accessCode) {
return pairRoomRepository.existsByAccessCode(accessCode);
return pairRoomRepository.existsByAccessCodeAndStatusNot(accessCode, PairRoomStatus.DELETE);
}

private PairRoom createPairRoom(final PairRoomCreateRequest request) {
Expand All @@ -77,18 +78,27 @@ private AccessCode generateAccessCode() {
@Transactional
public void updateNavigatorWithDriver(final String accessCode) {
final PairRoomEntity pairRoomEntity = pairRoomRepository.fetchByAccessCode(accessCode);
checkDeletePairRoom(pairRoomEntity);
pairRoomEntity.swapNavigatorWithDriver();
}

private void checkDeletePairRoom(final PairRoomEntity pairRoomEntity) {
if (pairRoomEntity.isDelete()) {
throw new DeletePairRoomException("삭제된 페어룸입니다.");
}
}

@Transactional
public void updatePairRoomStatus(final String accessCode, final String statusName) {
final PairRoomEntity pairRoomEntity = pairRoomRepository.fetchByAccessCode(accessCode);
checkDeletePairRoom(pairRoomEntity);
final PairRoomStatus status = PairRoomStatus.findByName(statusName);
final PairRoomEntity entity = pairRoomRepository.fetchByAccessCode(accessCode);
entity.updateStatus(status);
pairRoomEntity.updateStatus(status);
}

public PairRoomReadResponse findPairRoomAndTimer(final String accessCode) {
final PairRoomEntity pairRoomEntity = pairRoomRepository.fetchByAccessCode(accessCode);
checkDeletePairRoom(pairRoomEntity);
final TimerEntity timerEntity = timerRepository.fetchTimerByPairRoomEntity(pairRoomEntity);
return PairRoomReadResponse.of(pairRoomEntity.toDomain(), timerEntity.toDomain());
}
Expand All @@ -97,10 +107,20 @@ public List<PairRoomMemberResponse> findPairRooms(final String token) {
final Member member = memberService.findMemberByCredential(token);

final List<PairRoomMemberEntity> pairRooms = pairRoomMemberRepository.findByMember(member);

return pairRooms.stream()
final List<PairRoomEntity> pairRoomEntities = pairRooms.stream()
.map(PairRoomMemberEntity::getPairRoom)
.filter(pairRoomEntity -> !pairRoomEntity.isDelete())
.toList();

return pairRoomEntities.stream()
.map(PairRoomMemberResponse::from)
.toList();
}

@Transactional
public void deletePairRoom(final String accessCode) {
final PairRoomEntity pairRoomEntity = pairRoomRepository.fetchByAccessCode(accessCode);
checkDeletePairRoom(pairRoomEntity);
pairRoomEntity.updateStatus(PairRoomStatus.DELETE);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -151,4 +151,24 @@ void exist_pair_room_false() {

assertThat(response.exists()).isFalse();
}

@Test
@DisplayName("페어룸을 삭제한다.")
void delete_pair_room() {
// given
final PairRoomCreateResponse accessCode =
createPairRoom(new PairRoomCreateRequest("레디", "프람", 1000L, 100L, "IN_PROGRESS"));

// when & then
RestAssured
.given()
.log()
.all()

.when()
.delete("/api/pair-room/{access-code}", accessCode.accessCode())

.then()
.statusCode(204);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,15 @@
import org.junit.jupiter.api.Test;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.transaction.annotation.Transactional;

import io.restassured.RestAssured;
import io.restassured.http.ContentType;
import site.coduo.pairroom.service.dto.PairRoomCreateRequest;
import site.coduo.pairroom.service.dto.PairRoomCreateResponse;
import site.coduo.referencelink.service.dto.CategoryCreateRequest;
import site.coduo.referencelink.service.dto.CategoryCreateResponse;
import site.coduo.referencelink.service.dto.ReferenceLinkResponse;

@Transactional
class ReferenceAcceptanceTest extends AcceptanceFixture {

@Test
Expand Down Expand Up @@ -101,18 +100,22 @@ void read_reference_link_without_open_graph() {
.body("[0].image", is(""));
}

void createReferenceLink(final String url, String accessCodeText, String categoryName) {
ReferenceLinkResponse createReferenceLink(final String url, String accessCodeText, String categoryName) {
final CategoryCreateResponse response = CategoryAcceptanceTest.createCategory(
accessCodeText, new CategoryCreateRequest(categoryName));
final Map<String, Object> request = Map.of("url", url, "categoryId", response.id());

RestAssured
return RestAssured
.given()
.contentType(ContentType.JSON)
.body(request)

.when()
.post("/api/" + accessCodeText + "/reference-link");
.post("/api/" + accessCodeText + "/reference-link")

.then()
.extract()
.as(ReferenceLinkResponse.class);
}

@Test
Expand All @@ -122,7 +125,8 @@ void delete_reference_link_request() {
final PairRoomCreateResponse pairRoom =
createPairRoom(new PairRoomCreateRequest("레모네", "프람", 1000L, 1000L, "IN_PROGRESS"));

createReferenceLink("http://www.delete.com", pairRoom.accessCode(), "카테고리 이름");
final ReferenceLinkResponse response = createReferenceLink("http://www.delete.com", pairRoom.accessCode(),
"카테고리 이름");

// when & then
RestAssured
Expand All @@ -131,7 +135,7 @@ void delete_reference_link_request() {

.when()
.log().all()
.delete("/api/" + pairRoom.accessCode() + "/reference-link/1")
.delete("/api/" + pairRoom.accessCode() + "/reference-link/" + response.id())

.then()
.assertThat()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,38 @@ void change_nav_and_driver() {
.extracting("navigator", "driver")
.contains("dri", "navi");
}

@Test
@DisplayName("페어룸 상태가 DELETE면 true를 반환한다.")
void pairRoomEntityStatusIsDelete() {
// Given
final PairRoomEntity sut = PairRoomEntity.from(
new PairRoom(PairRoomStatus.DELETE,
new Pair(new PairName("navi"), new PairName("dri")),
new AccessCode("access"))
);

// When
final boolean isDelete = sut.isDelete();

// Then
assertThat(isDelete).isTrue();
}

@Test
@DisplayName("페어룸 상태가 DELETE가 아니면 false를 반환한다.")
void pairRoomEntityStatusIsNotDelete() {
// Given
final PairRoomEntity sut = PairRoomEntity.from(
new PairRoom(PairRoomStatus.IN_PROGRESS,
new Pair(new PairName("navi"), new PairName("dri")),
new AccessCode("access"))
);

// When
final boolean isDelete = sut.isDelete();

// Then
assertThat(isDelete).isFalse();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import site.coduo.pairroom.domain.PairRoom;
import site.coduo.pairroom.domain.PairRoomStatus;
import site.coduo.pairroom.domain.accesscode.AccessCode;
import site.coduo.pairroom.exception.DeletePairRoomException;
import site.coduo.pairroom.exception.PairRoomNotFoundException;
import site.coduo.pairroom.repository.PairRoomEntity;
import site.coduo.pairroom.repository.PairRoomRepository;
Expand Down Expand Up @@ -91,6 +92,21 @@ void throw_exception_when_find_not_exist_access_code() {
.isExactlyInstanceOf(PairRoomNotFoundException.class);
}

@Test
@Transactional
Copy link
Member

Choose a reason for hiding this comment

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

이거 안붙히고 테스트 개선 안될가요?

@DisplayName("삭제된 페어룸의 접근 코드를 찾으면 예외가 발생한다.")
void throw_exception_when_find_delete_pair_room_access_code() {
// given
final PairRoomCreateRequest request =
new PairRoomCreateRequest("레디", "프람", 1000L, 100L,
PairRoomStatus.DELETE.name());
final String accessCode = pairRoomService.savePairRoom(request, null);

// when & then
assertThatThrownBy(() -> pairRoomService.findPairRoomAndTimer(accessCode))
.isExactlyInstanceOf(DeletePairRoomException.class);
}

@Test
@DisplayName("페어룸 상태를 변경한다.")
void update_pair_room_status() {
Expand All @@ -107,6 +123,19 @@ void update_pair_room_status() {
.isEqualTo(PairRoomStatus.COMPLETED);
}

@Test
@DisplayName("삭제된 페어룸 상태를 변경하려고 하면 예외를 발생시킨다.")
void update_delete_pair_room_status() {
// given
final PairRoomCreateRequest request =
new PairRoomCreateRequest("레디", "프람", 1000L, 100L, PairRoomStatus.DELETE.name());
final String accessCode = pairRoomService.savePairRoom(request, null);

// when & then
assertThatThrownBy(() -> pairRoomService.updatePairRoomStatus(accessCode, PairRoomStatus.COMPLETED.name()))
.isExactlyInstanceOf(DeletePairRoomException.class);
}

@Test
@DisplayName("페어 역할을 변경한다.")
void change_pair_room() {
Expand All @@ -127,8 +156,24 @@ void change_pair_room() {
.contains("lemonL", "fram");
}

@Test
@DisplayName("삭제된 페어룸의 페어 역할을 변경하려하면 예외를 발생시킨다.")
void change_delete_pair_room_role() {
// given
final PairRoomEntity entity = PairRoomEntity.from(
new PairRoom(PairRoomStatus.DELETE,
new Pair(new PairName("fram"), new PairName("lemonL")),
new AccessCode("1234"))
);
pairRoomRepository.save(entity);

@DisplayName("멤버의 방 목록을 가져온다.")
// when & then
assertThatThrownBy(() -> pairRoomService.updateNavigatorWithDriver(entity.getAccessCode()))
.isExactlyInstanceOf(DeletePairRoomException.class);
}


@DisplayName("삭제되지 않은, 멤버의 방 목록을 가져온다.")
@Test
void find_rooms_by_member() {
//given
Expand All @@ -143,6 +188,12 @@ void find_rooms_by_member() {
final String accessCodeB_1 = pairRoomService.savePairRoom(pairRoomCreateRequest, memberB.getAccessToken());
pairRoomService.savePairRoom(pairRoomCreateRequest, null);

final PairRoomCreateRequest deletePairRoomCreateRequest = new PairRoomCreateRequest("레디", "잉크", 1, 1,
"DELETE");
pairRoomService.savePairRoom(deletePairRoomCreateRequest, memberA.getAccessToken());
pairRoomService.savePairRoom(deletePairRoomCreateRequest, memberA.getAccessToken());
pairRoomService.savePairRoom(deletePairRoomCreateRequest, memberA.getAccessToken());

final List<String> memberAExpected = List.of(accessCodeA_1, accessCodeA_2);
final List<String> memberBExpected = List.of(accessCodeB_1);

Expand Down
Loading