Skip to content
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 @@ -19,6 +19,7 @@ public enum SuccessCode implements SuccessResultCode {
ACTIVITY_TRACK_GET_SUCCESS(HttpStatus.OK, "활동 경로 데이터 조회에 성공했습니다."),
ARCHIVE_ACTIVITY_LIST_GET_SUCCESS(HttpStatus.OK, "특정 날짜의 활동 목록 조회에 성공했습니다."),
IMAGE_UPLOAD_URL_CREATED(HttpStatus.OK, "이미지 업로드 URL 발급에 성공했습니다."),
ROUTE_LIST_UPDATE_SUCCESS(HttpStatus.OK, "루트 목록 수정에 성공했습니다."),
ROUTE_LIST_GET_SUCCESS(HttpStatus.OK, "루트 목록 조회에 성공했습니다."),
TIMELINE_DELETED(HttpStatus.OK, "타임라인 삭제에 성공했습니다."),
TIMELINE_LIST_GET_SUCCESS(HttpStatus.OK, "타임라인 목록 조회에 성공했습니다."),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
import java.util.List;

import org.sopt.routee.activity.internal.code.SuccessCode;
import org.sopt.routee.activity.internal.controller.dto.request.CreateRoutesRequest;
import org.sopt.routee.activity.internal.controller.dto.request.RoutesCreateRequest;
import org.sopt.routee.activity.internal.controller.dto.request.RoutesUpdateRequest;
import org.sopt.routee.activity.internal.controller.dto.response.RouteListResponse;
import org.sopt.routee.activity.internal.service.RouteService;
import org.sopt.routee.activity.internal.service.dto.result.RouteResult;
Expand All @@ -14,6 +15,7 @@
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.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
Expand All @@ -31,14 +33,24 @@ public class RouteController implements RouteControllerDocs {
@PostMapping("/{activityId}/route")
public ResponseEntity<SuccessResponse<RouteListResponse>> createRoutes(
@PathVariable(name = "activityId") Long activityId,
@Valid @RequestBody CreateRoutesRequest request
@Valid @RequestBody RoutesCreateRequest request
) {
List<RouteResult> results = routeService.createRoutes(activityId, request.toCommands());

return ResponseEntity.status(HttpStatus.CREATED)
.body(ApiResponse.success(SuccessCode.ROUTE_LIST_CREATE_SUCCESS, RouteListResponse.of(activityId, results)));
}

@PutMapping("/{activityId}/route")
public ResponseEntity<SuccessResponse<RouteListResponse>> updateRoutes(
@PathVariable(name = "activityId") Long activityId,
@Valid @RequestBody RoutesUpdateRequest request
) {
List<RouteResult> results = routeService.updateRoutes(activityId, request.toCommands());

return ResponseEntity.ok(ApiResponse.success(SuccessCode.ROUTE_LIST_UPDATE_SUCCESS, RouteListResponse.of(activityId, results)));
}

@GetMapping("/{activityId}/route")
public ResponseEntity<SuccessResponse<RouteListResponse>> getRoutes(
@PathVariable(name = "activityId") Long activityId
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package org.sopt.routee.activity.internal.controller;

import org.sopt.routee.activity.internal.controller.dto.request.CreateRoutesRequest;
import org.sopt.routee.activity.internal.controller.dto.request.RoutesCreateRequest;
import org.sopt.routee.activity.internal.controller.dto.request.RoutesUpdateRequest;
import org.sopt.routee.activity.internal.controller.dto.response.RouteListResponse;
import org.sopt.routee.response.FailureResponse;
import org.sopt.routee.response.SuccessResponse;
Expand Down Expand Up @@ -49,7 +50,23 @@ public interface RouteControllerDocs {
})
ResponseEntity<SuccessResponse<RouteListResponse>> createRoutes(
@PathVariable(name = "activityId") Long activityId,
@Valid @RequestBody CreateRoutesRequest request
@Valid @RequestBody RoutesCreateRequest request
);

@Operation(summary = "루트 목록 수정", description = "활동 기록의 기존 루트 목록을 요청한 루트 목록 전체로 수정합니다.")
@ApiResponses({
@ApiResponse(responseCode = "200", description = "루트 목록 수정 성공",
content = @Content(schema = @Schema(implementation = RouteListResponse.class))),
@ApiResponse(responseCode = "400", description = "요청 값이 올바르지 않음",
content = @Content(schema = @Schema(implementation = FailureResponse.class))),
@ApiResponse(responseCode = "401", description = "인증 실패",
content = @Content(schema = @Schema(implementation = FailureResponse.class))),
@ApiResponse(responseCode = "404", description = "활동 기록이 존재하지 않음",
content = @Content(schema = @Schema(implementation = FailureResponse.class)))
})
ResponseEntity<SuccessResponse<RouteListResponse>> updateRoutes(
@PathVariable(name = "activityId") Long activityId,
@Valid @RequestBody RoutesUpdateRequest request
);

@Operation(summary = "루트 목록 조회", description = "활동 기록에 속하는 루트 목록을 조회합니다.")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.Size;

public record CreateRoutesRequest(
public record RoutesCreateRequest(
@Valid
@NotEmpty(message = "루트 목록 생성 시 최소 1개 이상의 루트를 입력해야 합니다.")
@Size(max = 20, message = "루트는 최대 20개까지 등록할 수 있습니다.")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package org.sopt.routee.activity.internal.controller.dto.request;

import java.util.List;

import org.sopt.routee.activity.internal.service.dto.command.UpdateRouteCommand;

import jakarta.validation.Valid;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;

public record RoutesUpdateRequest(
@Valid
@NotNull(message = "routes는 필수입니다.")
@Size(max = 20, message = "루트는 최대 20개까지 등록할 수 있습니다.")
List<@NotNull(message = "루트는 null일 수 없습니다.") RouteRequest> routes
) {
public List<UpdateRouteCommand> toCommands() {
return routes.stream()
.map(route -> new UpdateRouteCommand(route.name(), route.sequence()))
.toList();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import org.sopt.routee.activity.internal.entity.activity.Activity;
import org.sopt.routee.activity.internal.entity.route.Route;
import org.sopt.routee.activity.internal.service.dto.command.CreateRouteCommand;
import org.sopt.routee.activity.internal.service.dto.command.UpdateRouteCommand;
import org.sopt.routee.activity.internal.service.dto.result.RouteResult;

public class RouteMapper {
Expand All @@ -15,6 +16,14 @@ public static Route toEntity(CreateRouteCommand command, Activity activity) {
.build();
}

public static Route toEntity(UpdateRouteCommand command, Activity activity) {
return Route.builder()
.name(command.name())
.sequence(command.sequence())
.activity(activity)
.build();
}

public static RouteResult toResult(Route route) {
return new RouteResult(route.getId(), route.getName(), route.getSequence());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ public interface RouteRepository extends JpaRepository<Route, Long> {

boolean existsByActivityId(Long activityId);

@Modifying
@Query("DELETE FROM Route r WHERE r.activity.id = :activityId")
void deleteByActivityId(@Param("activityId") Long activityId);

@Modifying
@Query("DELETE FROM Route r WHERE r.activity.memberId = :memberId")
void deleteByMemberId(@Param("memberId") Long memberId);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.sopt.routee.activity.internal.service;

import java.util.Comparator;
import java.util.List;

import org.sopt.routee.activity.internal.entity.activity.Activity;
Expand All @@ -10,6 +11,7 @@
import org.sopt.routee.activity.internal.repository.ActivityRepository;
import org.sopt.routee.activity.internal.repository.RouteRepository;
import org.sopt.routee.activity.internal.service.dto.command.CreateRouteCommand;
import org.sopt.routee.activity.internal.service.dto.command.UpdateRouteCommand;
import org.sopt.routee.activity.internal.service.dto.result.RouteResult;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
Expand Down Expand Up @@ -42,6 +44,38 @@ public List<RouteResult> createRoutes(Long activityId, List<CreateRouteCommand>
.toList();
}

@Transactional
public List<RouteResult> updateRoutes(Long activityId, List<UpdateRouteCommand> commands) {
if (!activityRepository.existsById(activityId)) {
throw new ActivityNotFoundException();
}

List<UpdateRouteCommand> sortedCommands = commands.stream()
.sorted(Comparator.comparingInt(UpdateRouteCommand::sequence))
.toList();

List<Route> existingRoutes = routeRepository.findByActivityIdOrderBySequenceAsc(activityId);
List<UpdateRouteCommand> existingCommands = existingRoutes.stream()
.map(route -> new UpdateRouteCommand(route.getName(), route.getSequence()))
.toList();
if (existingCommands.equals(sortedCommands)) {
return existingRoutes.stream()
.map(RouteMapper::toResult)
.toList();
}
Comment on lines +57 to +65

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

기존과 Route와 동일한 경우에 early return 하는 방법은 정말 좋은 것 같아요!


routeRepository.deleteByActivityId(activityId);
Activity activity = activityRepository.getReferenceById(activityId);

List<Route> routes = sortedCommands.stream()
.map(command -> RouteMapper.toEntity(command, activity))
.toList();

return routeRepository.saveAll(routes).stream()
.map(RouteMapper::toResult)
.toList();
}

@Transactional(readOnly = true)
public List<RouteResult> getRoutes(Long activityId) {
if (!activityRepository.existsById(activityId)) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package org.sopt.routee.activity.internal.service.dto.command;

public record UpdateRouteCommand(
String name,
int sequence
) {
}
Loading