Skip to content

Commit

Permalink
Merge pull request #949 from woowacourse-teams/BE/feature/#948-comple…
Browse files Browse the repository at this point in the history
…te_pair_room

[BE] 페어룸 종료 기능 추가
  • Loading branch information
JiHyeonL authored Nov 11, 2024
2 parents dcc9270 + 5c6a19d commit 4a6bcd9
Show file tree
Hide file tree
Showing 17 changed files with 145 additions and 64 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@

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 @@ -95,10 +94,18 @@ public ResponseEntity<PairRoomExistResponse> pairRoomExists(@RequestParam("acces
return ResponseEntity.ok(response);
}

@DeleteMapping("/pair-room/{accessCode}")
@PatchMapping("/pair-room/{accessCode}/complete")
public ResponseEntity<Void> completePairRoom(@PathVariable("accessCode") final String accessCode) {
pairRoomService.completePairRoom(accessCode);
return ResponseEntity.noContent()
.build();
}

@PatchMapping("/pair-room/{accessCode}/delete")
public ResponseEntity<Void> deletePairRoom(@PathVariable("accessCode") final String accessCode) {
pairRoomService.deletePairRoom(accessCode);
return ResponseEntity.noContent().build();
return ResponseEntity.noContent()
.build();
}

@GetMapping("/member/{accessCode}/exists")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,13 @@
import site.coduo.common.controller.response.ApiErrorResponse;
import site.coduo.pairroom.controller.error.PairRoomApiError;
import site.coduo.pairroom.exception.DuplicatePairNameException;
import site.coduo.pairroom.exception.InactivePairRoomException;
import site.coduo.pairroom.exception.InvalidAccessCodeException;
import site.coduo.pairroom.exception.InvalidNameFormatException;
import site.coduo.pairroom.exception.InvalidPairRoomStatusException;
import site.coduo.pairroom.exception.PairRoomException;
import site.coduo.pairroom.exception.PairRoomMemberNotFoundException;
import site.coduo.pairroom.exception.PairRoomNotFoundException;
import site.coduo.pairroom.exception.InvalidPairRoomStatusException;

@Slf4j
@RestControllerAdvice
Expand All @@ -31,6 +33,14 @@ public ResponseEntity<ApiErrorResponse> handleDuplicatePairNameException(final D
.body(new ApiErrorResponse(PairRoomApiError.INVALID_PAIR_NAME.getMessage()));
}

@ExceptionHandler(InactivePairRoomException.class)
public ResponseEntity<ApiErrorResponse> handleInactivePairRoomException(final InactivePairRoomException e) {
log.warn(e.getMessage());

return ResponseEntity.status(PairRoomApiError.INACTIVE_PAIR_ROOM.getHttpStatus())
.body(new ApiErrorResponse(PairRoomApiError.INACTIVE_PAIR_ROOM.getMessage()));
}

@ExceptionHandler(InvalidAccessCodeException.class)
public ResponseEntity<ApiErrorResponse> handleInvalidAccessCodeException(final InvalidAccessCodeException e) {
log.warn(e.getMessage());
Expand All @@ -49,7 +59,8 @@ public ResponseEntity<ApiErrorResponse> handleInvalidPropertiesFormatException(
}

@ExceptionHandler(InvalidPairRoomStatusException.class)
public ResponseEntity<ApiErrorResponse> handlePairRoomStatusNotFoundException(final InvalidPairRoomStatusException e) {
public ResponseEntity<ApiErrorResponse> handlePairRoomStatusNotFoundException(
final InvalidPairRoomStatusException e) {
log.warn(e.getMessage());

return ResponseEntity.status(PairRoomApiError.INVALID_PROPERTIES_FORMAT.getHttpStatus())
Expand All @@ -64,6 +75,15 @@ public ResponseEntity<ApiErrorResponse> handlePairRoomNotFoundException(final Pa
.body(new ApiErrorResponse(PairRoomApiError.PAIR_ROOM_NOT_FOUND.getMessage()));
}

@ExceptionHandler(PairRoomMemberNotFoundException.class)
public ResponseEntity<ApiErrorResponse> handlePairRoomMemberNotFoundException(
final PairRoomMemberNotFoundException e) {
log.warn(e.getMessage());

return ResponseEntity.status(PairRoomApiError.PAIR_ROOM_MEMBER_NOT_FOUND.getHttpStatus())
.body(new ApiErrorResponse(PairRoomApiError.PAIR_ROOM_MEMBER_NOT_FOUND.getMessage()));
}

@ExceptionHandler(PairRoomException.class)
public ResponseEntity<ApiErrorResponse> handlePairRoomException(final PairRoomException e) {
log.warn(e.getMessage());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,13 @@ ResponseEntity<Void> deletePairRoom(
String accessCode
);

@Operation(summary = "페어룸을 종료한다.")
@ApiResponse(responseCode = "204", description = "페어룸 종료 성공")
ResponseEntity<Void> completePairRoom(
@Parameter(description = "페어룸 접근 코드", required = true)
String accessCode
);

@Operation(summary = "특정 회원이 특정 페어룸에 존재하는지 여부를 조회한다.")
@ApiResponse(responseCode = "200", description = "회원 페어룸 참여 여부 조회 성공", content = @Content(mediaType = MediaType.APPLICATION_JSON_VALUE,
schema = @Schema(implementation = ExistMemberInPairRoomResponse.class)))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ public enum PairRoomApiError {
INVALID_PAIR_NAME(HttpStatus.BAD_REQUEST, "올바르지 않은 페어 이름입니다."),
INVALID_ACCESS_CODE(HttpStatus.BAD_REQUEST, "올바르지 않은 접근 코드입니다."),
PAIR_ROOM_NOT_FOUND(HttpStatus.NOT_FOUND, "페어룸이 존재하지 않습니다."),
INVALID_PROPERTIES_FORMAT(HttpStatus.BAD_REQUEST, "올바르지 않은 데이터 형식입니다.");
PAIR_ROOM_MEMBER_NOT_FOUND(HttpStatus.NOT_FOUND, "페어룸-멤버가 존재하지 않습니다."),
INVALID_PROPERTIES_FORMAT(HttpStatus.BAD_REQUEST, "올바르지 않은 데이터 형식입니다."),
INACTIVE_PAIR_ROOM(HttpStatus.BAD_REQUEST, "이미 종료되거나 삭제된 페어룸입니다.");

private final HttpStatus httpStatus;
private final String message;
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package site.coduo.pairroom.exception;

public class InactivePairRoomException extends PairRoomException {

public InactivePairRoomException(final String message) {
super(message);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,11 @@ public void swapNavigatorWithDriver() {
this.driver = temp;
}

public boolean isDelete() {
public boolean isActive() {
return status != PairRoomStatus.COMPLETED && status != PairRoomStatus.DELETED;
}

public boolean isDeleted() {
return status == PairRoomStatus.DELETED;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
import site.coduo.pairroom.domain.accesscode.generator.AccessCodeGenerator;
import site.coduo.pairroom.domain.accesscode.generator.EasyAccessCodeGenerator;
import site.coduo.pairroom.domain.accesscode.generator.UUIDAccessCodeGenerator;
import site.coduo.pairroom.exception.DeletePairRoomException;
import site.coduo.pairroom.exception.InactivePairRoomException;
import site.coduo.pairroom.repository.PairRoomEntity;
import site.coduo.pairroom.repository.PairRoomMemberEntity;
import site.coduo.pairroom.repository.PairRoomMemberRepository;
Expand Down Expand Up @@ -101,38 +101,38 @@ private boolean isAlreadyExistAccessCode(final AccessCodeGenerator accessCodeGen
@Transactional
public void updateNavigatorWithDriver(final String accessCode) {
final PairRoomEntity pairRoomEntity = pairRoomRepository.fetchByAccessCode(accessCode);
checkDeletePairRoom(pairRoomEntity);
checkPairRoomIsActive(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);
checkPairRoomIsActive(pairRoomEntity);
final PairRoomStatus status = PairRoomStatus.findByName(statusName);
pairRoomEntity.updateStatus(status);
}

public PairRoomReadResponse findPairRoomAndTimer(final String accessCode) {
final PairRoomEntity pairRoomEntity = pairRoomRepository.fetchByAccessCode(accessCode);
checkDeletePairRoom(pairRoomEntity);
checkPairRoomIsDeleted(pairRoomEntity);
final TimerEntity timerEntity = timerRepository.fetchTimerByPairRoomEntity(pairRoomEntity);
return PairRoomReadResponse.of(pairRoomEntity.toDomain(), timerEntity.toDomain());
}

private void checkPairRoomIsActive(final PairRoomEntity pairRoomEntity) {
if (!pairRoomEntity.isActive()) {
throw new InactivePairRoomException("종료되거나 삭제된 페어룸을 조작할 수 없습니다.");
}
}

public List<PairRoomMemberResponse> findPairRooms(final String token) {
final Member member = memberService.findMemberByCredential(token);

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

return pairRoomEntities.stream()
Expand All @@ -143,10 +143,23 @@ public List<PairRoomMemberResponse> findPairRooms(final String token) {
@Transactional
public void deletePairRoom(final String accessCode) {
final PairRoomEntity pairRoomEntity = pairRoomRepository.fetchByAccessCode(accessCode);
checkDeletePairRoom(pairRoomEntity);
checkPairRoomIsDeleted(pairRoomEntity);
pairRoomEntity.updateStatus(PairRoomStatus.DELETED);
}

@Transactional
public void completePairRoom(final String accessCode) {
final PairRoomEntity pairRoomEntity = pairRoomRepository.fetchByAccessCode(accessCode);
checkPairRoomIsActive(pairRoomEntity);
pairRoomEntity.updateStatus(PairRoomStatus.COMPLETED);
}

private void checkPairRoomIsDeleted(final PairRoomEntity pairRoomEntity) {
if (pairRoomEntity.isDeleted()) {
throw new InactivePairRoomException("삭제된 페어룸을 삭제할 수 없습니다.");
}
}

public boolean existMemberInPairRoom(final String credentialToken, final String pairRoomAccessCode) {
final PairRoomEntity pairRoom = pairRoomRepository.fetchByAccessCode(pairRoomAccessCode);
final Member member = memberService.findMemberByCredential(credentialToken);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import lombok.RequiredArgsConstructor;
import site.coduo.pairroom.domain.accesscode.AccessCode;
import site.coduo.pairroom.exception.InactivePairRoomException;
import site.coduo.pairroom.repository.PairRoomEntity;
import site.coduo.pairroom.repository.PairRoomRepository;
import site.coduo.referencelink.domain.Category;
Expand Down Expand Up @@ -41,6 +42,7 @@ public List<CategoryReadResponse> findAllByPairRoomAccessCode(final String acces

public CategoryCreateResponse createCategory(final String accessCode, final CategoryCreateRequest request) {
final PairRoomEntity pairRoomEntity = pairRoomRepository.fetchByAccessCode(new AccessCode(accessCode));
checkPairRoomIsActive(pairRoomEntity);
validateDuplicated(request.value(), pairRoomEntity);
final CategoryEntity categoryEntity = categoryRepository.save(
new CategoryEntity(pairRoomEntity, new Category(request.value())));
Expand All @@ -56,6 +58,7 @@ private void validateDuplicated(final String categoryName, final PairRoomEntity

public CategoryUpdateResponse updateCategoryName(final String accessCode, final CategoryUpdateRequest request) {
final PairRoomEntity pairRoomEntity = pairRoomRepository.fetchByAccessCode(new AccessCode(accessCode));
checkPairRoomIsActive(pairRoomEntity);
validateDuplicated(request.updatedCategoryName(), pairRoomEntity);
final CategoryEntity category = categoryRepository.fetchByPairRoomAndCategoryId(pairRoomEntity,
request.categoryId());
Expand All @@ -65,11 +68,18 @@ public CategoryUpdateResponse updateCategoryName(final String accessCode, final

public void deleteCategory(final String accessCode, final Long categoryId) {
final PairRoomEntity pairRoomEntity = pairRoomRepository.fetchByAccessCode(new AccessCode(accessCode));
checkPairRoomIsActive(pairRoomEntity);
if (categoryRepository.existsByIdAndPairRoomEntity(categoryId, pairRoomEntity)) {
final List<ReferenceLinkEntity> referenceLinks = referenceLinkService.findReferenceLinksEntityByCategory(
accessCode, categoryId);
referenceLinks.forEach(ReferenceLinkEntity::updateCategoryToNull);
categoryRepository.deleteCategoryByPairRoomEntityAndId(pairRoomEntity, categoryId);
}
}

private void checkPairRoomIsActive(final PairRoomEntity pairRoomEntity) {
if (!pairRoomEntity.isActive()) {
throw new InactivePairRoomException("이미 종료되었거나 삭제된 페어룸의 카테고리를 조작할 수 없습니다.");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import site.coduo.pairroom.domain.accesscode.AccessCode;
import site.coduo.pairroom.exception.InactivePairRoomException;
import site.coduo.pairroom.repository.PairRoomEntity;
import site.coduo.pairroom.repository.PairRoomRepository;
import site.coduo.referencelink.domain.Category;
Expand All @@ -34,10 +35,13 @@ public class ReferenceLinkService {
private final CategoryRepository categoryRepository;
private final OpenGraphService openGraphService;

public ReferenceLinkResponse createReferenceLink(final String accessCodeText,
final ReferenceLinkCreateRequest request) {
public ReferenceLinkResponse createReferenceLink(
final String accessCodeText,
final ReferenceLinkCreateRequest request
) {
final AccessCode accessCode = new AccessCode(accessCodeText);
final PairRoomEntity pairRoomEntity = pairRoomRepository.fetchByAccessCode(accessCode);
checkPairRoomIsActive(pairRoomEntity);
final URL url = makeUrl(request.url());
final ReferenceLink referenceLink = new ReferenceLink(url, accessCode);

Expand All @@ -54,9 +58,10 @@ private URL makeUrl(final String requestUrl) {
}
}

private ReferenceLinkEntity saveReferenceLink(final ReferenceLinkCreateRequest request,
final PairRoomEntity pairRoomEntity,
final ReferenceLink referenceLink
private ReferenceLinkEntity saveReferenceLink(
final ReferenceLinkCreateRequest request,
final PairRoomEntity pairRoomEntity,
final ReferenceLink referenceLink
) {
if (request.categoryId() == null) {
return referenceLinkRepository.save(new ReferenceLinkEntity(referenceLink, pairRoomEntity));
Expand Down Expand Up @@ -118,10 +123,18 @@ private ReferenceLinkResponse makeReferenceLinkResponse(final ReferenceLinkEntit
}

public void deleteReferenceLink(final String accessCodeText, final long id) {
final PairRoomEntity pairRoomEntity = pairRoomRepository.fetchByAccessCode(accessCodeText);
checkPairRoomIsActive(pairRoomEntity);
final ReferenceLinkEntity referenceLinkEntity = referenceLinkRepository.fetchById(id);
if (referenceLinkEntity.isSameAccessCode(new AccessCode(accessCodeText))) {
openGraphService.deleteByReferenceLink(referenceLinkEntity);
referenceLinkRepository.delete(referenceLinkEntity);
}
}

private void checkPairRoomIsActive(final PairRoomEntity pairRoomEntity) {
if (!pairRoomEntity.isActive()) {
throw new InactivePairRoomException("이미 종료되었거나 삭제된 페어룸의 링크를 조작할 수 없습니다.");
}
}
}
28 changes: 18 additions & 10 deletions backend/src/main/java/site/coduo/todo/service/TodoService.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import org.springframework.transaction.annotation.Transactional;

import lombok.RequiredArgsConstructor;
import site.coduo.pairroom.exception.PairRoomNotFoundException;
import site.coduo.pairroom.exception.InactivePairRoomException;
import site.coduo.pairroom.repository.PairRoomEntity;
import site.coduo.pairroom.repository.PairRoomRepository;
import site.coduo.todo.domain.Todo;
Expand All @@ -29,9 +29,7 @@ public class TodoService {

@Transactional(readOnly = true)
public List<Todo> getAllOrderBySort(final String accessCode) {
final PairRoomEntity pairRoom = pairRoomRepository.findByAccessCode(accessCode)
.orElseThrow(() -> new PairRoomNotFoundException("해당 Access Code의 페어룸은 존재하지 않습니다. - " + accessCode));

final PairRoomEntity pairRoom = pairRoomRepository.fetchByAccessCode(accessCode);
return todoRepository.findAllByPairRoomEntity(pairRoom)
.stream()
.map(TodoEntity::toDomain)
Expand All @@ -40,11 +38,11 @@ public List<Todo> getAllOrderBySort(final String accessCode) {
}

public void createTodo(final String accessCode, final String content) {
final PairRoomEntity pairRoom = pairRoomRepository.findByAccessCode(accessCode)
.orElseThrow(() -> new PairRoomNotFoundException("해당 Access Code의 페어룸은 존재하지 않습니다. - " + accessCode));
final TodoSort nextToLastSort = getLastTodoSort(pairRoom);
final PairRoomEntity pairRoomEntity = pairRoomRepository.fetchByAccessCode(accessCode);
checkPairRoomIsActive(pairRoomEntity);
final TodoSort nextToLastSort = getLastTodoSort(pairRoomEntity);
final Todo todo = new Todo(null, content, nextToLastSort.getSort(), INITIAL_TODO_CHECKED);
final TodoEntity todoEntity = new TodoEntity(todo, pairRoom);
final TodoEntity todoEntity = new TodoEntity(todo, pairRoomEntity);

todoRepository.save(todoEntity);
}
Expand All @@ -59,19 +57,20 @@ private TodoSort getLastTodoSort(final PairRoomEntity pairRoom) {

public void updateTodoContent(final Long todoId, final String content) {
final TodoEntity todoEntity = todoRepository.fetchById(todoId);

checkPairRoomIsActive(todoEntity.getPairRoomEntity());
todoEntity.updateContent(content);
}

public void toggleTodoChecked(final Long todoId) {
final TodoEntity todoEntity = todoRepository.fetchById(todoId);

checkPairRoomIsActive(todoEntity.getPairRoomEntity());
todoEntity.toggleTodoChecked();
}

public void updateTodoSort(final Long targetTodoId, final int destinationSort) {
final TodoEntity targetTodo = todoRepository.findById(targetTodoId)
.orElseThrow(() -> new TodoNotFoundException("존재하지 않은 todo id입니다." + targetTodoId));
checkPairRoomIsActive(targetTodo.getPairRoomEntity());
final List<Todo> allByPairRoom = todoRepository
.findAllByPairRoomEntity(targetTodo.getPairRoomEntity())
.stream()
Expand All @@ -85,6 +84,15 @@ public void updateTodoSort(final Long targetTodoId, final int destinationSort) {
}

public void deleteTodo(final Long todoId) {
final TodoEntity todoEntity = todoRepository.findById(todoId)
.orElseThrow(() -> new TodoNotFoundException("존재하지 않은 todo id입니다." + todoId));
checkPairRoomIsActive(todoEntity.getPairRoomEntity());
todoRepository.deleteById(todoId);
}

private void checkPairRoomIsActive(final PairRoomEntity pairRoomEntity) {
if (!pairRoomEntity.isActive()) {
throw new InactivePairRoomException("이미 종료되거나 삭제된 페어룸의 투두를 조작할 수 없습니다.");
}
}
}
Loading

0 comments on commit 4a6bcd9

Please sign in to comment.