Skip to content

Commit

Permalink
Merge pull request #3 from kookmin-sw/backend/feat/#1
Browse files Browse the repository at this point in the history
✨ 여행의 CRUD 구현
  • Loading branch information
J-Yong99 authored Mar 20, 2024
2 parents 76c3614 + 9e8e9dd commit b8558d4
Show file tree
Hide file tree
Showing 11 changed files with 137 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import com.moment.core.dto.request.TripRequestDTO;
import com.moment.core.dto.response.TripResponseDTO;
import com.moment.core.service.TripService;
import com.moment.core.service.UserService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
Expand All @@ -24,6 +25,7 @@
@RequestMapping("/core/trip")
public class TripController {
private final TripService tripService;
private final UserService userService;

// 여행 등록
@PostMapping("/register")
Expand All @@ -33,6 +35,7 @@ public class TripController {
@ApiResponse(responseCode = "400", description = "옳바르지 않은 요청 방식, 존재하지 않는 유저, 이미 등록된 여행날짜",content = @Content(schema = @Schema(implementation = ErrorResponse.class))),
})
public ResponseEntity<APIResponse> registerTrip(
@RequestHeader Long userId,
@RequestBody TripRequestDTO.RegisterTrip registerTrip
) {
tripService.register(registerTrip);
Expand All @@ -47,9 +50,43 @@ public ResponseEntity<APIResponse> registerTrip(
@ApiResponse(responseCode = "400", description = "옳바르지 않은 요청 방식",content = @Content(schema = @Schema(implementation = ErrorResponse.class))),
})
public ResponseEntity<APIResponse<TripResponseDTO.GetAllTrip>> getAllTrip(
@RequestParam Long userId
@RequestHeader Long userId
) {
TripResponseDTO.GetAllTrip allTrip = tripService.getAllTrip(userId);
return ResponseEntity.ok(APIResponse.of(SuccessCode.SELECT_SUCCESS, allTrip));
}

// 여행 삭제
@DeleteMapping()
@Operation(summary = "여행 삭제", description = "여행을 삭제합니다.")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "성공"),
@ApiResponse(responseCode = "400", description = "옳바르지 않은 요청 방식, 여행 또는 유저 없음",content = @Content(schema = @Schema(implementation = ErrorResponse.class))),
@ApiResponse(responseCode = "401", description = "해당 여행의 접근권한이 없는 유저",content = @Content(schema = @Schema(implementation = ErrorResponse.class))),
})
public ResponseEntity<APIResponse> deleteTrip(
@RequestHeader Long userId,
@RequestParam Long tripId
) {
userService.validateUserWithTrip(userId, tripId);
tripService.delete(tripId);
return ResponseEntity.ok(APIResponse.of(SuccessCode.DELETE_SUCCESS));
}

// 여행 수정
@PutMapping()
@Operation(summary = "여행 수정", description = "여행을 수정합니다.")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "성공"),
@ApiResponse(responseCode = "400", description = "옳바르지 않은 요청 방식, 여행 또는 유저 없음",content = @Content(schema = @Schema(implementation = ErrorResponse.class))),
@ApiResponse(responseCode = "401", description = "해당 여행의 접근권한이 없는 유저",content = @Content(schema = @Schema(implementation = ErrorResponse.class))),
})
public ResponseEntity<APIResponse> updateTrip(
@RequestHeader Long userId,
@RequestBody TripRequestDTO.UpdateTrip updateTrip
) {
userService.validateUserWithTrip(userId, updateTrip.getTripId());
tripService.update(userId, updateTrip);
return ResponseEntity.ok(APIResponse.of(SuccessCode.UPDATE_SUCCESS));
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.moment.core.domain.alreadyBookedDate;

import com.moment.core.domain.user.User;
import org.springframework.data.jpa.repository.JpaRepository;

import java.time.LocalDate;
Expand All @@ -8,4 +9,6 @@ public interface AlreadyBookedDateRepository extends JpaRepository<AlreadyBooked
boolean existsByUserIdAndYearDate(Long userId, LocalDate date);

boolean existsByUserIdAndYearDateBetween(Long userId, LocalDate stDate, LocalDate endDate);

void deleteByUserAndYearDateBetween(User user, LocalDate startDate, LocalDate endDate);
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
package com.moment.core.domain.cardView;

import com.moment.core.domain.tripFile.TripFile;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.Collection;
import java.util.List;

public interface CardViewRepository extends JpaRepository<CardView, Long> {
List<CardView> findAllByTripFile_Id(Long tripFileId);

List<CardView> findByTripFile(TripFile tripFile);
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.moment.core.domain.tripFile;

import com.moment.core.domain.trip.Trip;
import com.moment.core.domain.user.User;
import org.springframework.data.jpa.repository.JpaRepository;

Expand All @@ -13,4 +14,6 @@ public interface TripFileRepository extends JpaRepository<TripFile, Long> {


List<TripFile> findByUserAndTrip_Id(User user, Long tripId);

List<TripFile> findByTrip(Trip trip);
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,22 @@ public static class RegisterTrip {
@Schema(description = "여행 이름")
private String tripName;
}

@Schema(description = "여행 수정 요청")
@Getter
@Builder
public static class UpdateTrip {

@Schema(description = "여행 ID")
private final Long tripId;

@Schema(description = "출발일")
private LocalDate startDate;

@Schema(description = "도착일")
private LocalDate endDate;

@Schema(description = "여행 이름")
private String tripName;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,17 @@ protected ResponseEntity<ErrorResponse> AlreadyBookedDateExceptionHandler(Alread
final ErrorResponse response = ErrorResponse.of(ErrorCode.ALREADY_BOOKED_DATE, ex.getMessage());
return new ResponseEntity<>(response, HttpStatus.BAD_REQUEST);
}

/*
* [Exception] 해당 유저의 접근 권한이 없는 리소스
*/
@ExceptionHandler(UserNotValidException.class)
protected ResponseEntity<ErrorResponse> UserNotValidExceptionHandler(UserNotValidException ex) {
log.error("UserNotValidException", ex);
final ErrorResponse response = ErrorResponse.of(ErrorCode.UNAUTHORIZED_ERROR, ex.getMessage());
return new ResponseEntity<>(response, HttpStatus.UNAUTHORIZED);
}
// 토큰 401에러
// @ExceptionHandler({
// io.jsonwebtoken.security.SecurityException.class,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.moment.core.exception;

public class UserNotValidException extends RuntimeException{
public UserNotValidException(String message) {
super(message);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,8 @@ public boolean isAlreadyBookedDate(Long userId, LocalDate stDate, LocalDate endD
// stDate부터 endDate까지의 날짜사이에 이미 예약된 여행이 있는지 확인
return alreadyBookedDateRepository.existsByUserIdAndYearDateBetween(userId, stDate, endDate);
}

public void deleteAll(User user, LocalDate startDate, LocalDate endDate) {
alreadyBookedDateRepository.deleteByUserAndYearDateBetween(user, startDate, endDate);
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.moment.core.service;

import com.moment.core.domain.cardView.CardViewRepository;
import com.moment.core.domain.trip.Trip;
import com.moment.core.domain.tripFile.TripFile;
import com.moment.core.domain.tripFile.TripFileRepository;
Expand All @@ -9,6 +10,7 @@
import com.moment.core.exception.UserNotFoundException;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.util.ArrayList;
Expand All @@ -20,6 +22,7 @@
public class TripFileService {
private final TripFileRepository tripFileRepository;
private final UserRepository userRepository;
private final CardViewRepository cardViewRepository;

// 날짜를 받아서 이미 존재하면 해당 여행으로 업데이트, 없으면 새로 생성
public Integer findByDateAndUpdate(Trip trip, LocalDate date) {
Expand Down Expand Up @@ -63,4 +66,18 @@ public TripFileResponseDTO.GetAllTripFile getTripFiles(Long userId, Long tripId)
}


// 여행 삭제 시 여행에 연결된 여행파일들을 삭제하거나 untitled 여행으로 옮긴다.
// 카드뷰가 하나도 없는 여행파일은 삭제, 하나라도 있다면 untitled 여행으로 옮긴다.
@Transactional
public void deleteByTripOrUntitled(Trip trip, Trip untitledTrip) {
tripFileRepository.findByTrip(trip).forEach(tripFile -> {
if (cardViewRepository.findByTripFile(tripFile).isEmpty()) {
tripFileRepository.delete(tripFile);
} else {
tripFile.setTrip(untitledTrip);
tripFileRepository.save(tripFile);
}
}
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,29 @@ public void save(Trip trip) {
tripRepository.save(trip);
}

public void delete(Long tripId) {
tripRepository.deleteById(tripId);
// 1. 여행을 삭제한다.
// 2. 엮여있는 여행파일들 탐색
// 3. 내부가 비어있는 여행파일들은 그냥 삭제, 내부가 비어있지 않다면 untitled 여행으로 넣는다.
// 4. alreadyBookedDate에서 삭제한다.
@Transactional
public Trip delete(Long tripId) {
Trip trip = tripRepository.findById(tripId).orElseThrow(() -> new RuntimeException("존재하지 않는 여행입니다."));
Trip untitledTrip = getUntitledTrip(trip.getUser());
tripFileService.deleteByTripOrUntitled(trip, untitledTrip);
alreadyBookedDateService.deleteAll(trip.getUser(), trip.getStartDate(), trip.getEndDate());
tripRepository.delete(trip);
return trip;
}

public void update(Trip trip) {
tripRepository.save(trip);
@Transactional
public void update(Long userId, TripRequestDTO.UpdateTrip trip) {
Trip oldTrip = this.delete(trip.getTripId());
this.register(TripRequestDTO.RegisterTrip.builder()
.userId(userId)
.startDate(oldTrip.getStartDate())
.endDate(oldTrip.getEndDate())
.tripName(oldTrip.getTripName())
.build());
}


Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package com.moment.core.service;

import com.moment.core.domain.trip.Trip;
import com.moment.core.domain.trip.TripRepository;
import com.moment.core.domain.user.User;
import com.moment.core.domain.user.UserRepository;
import com.moment.core.exception.UserAlreadyExistException;
import com.moment.core.exception.UserNotValidException;
import jakarta.persistence.EntityManager;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
Expand All @@ -14,6 +16,7 @@
public class UserService {
private final UserRepository userRepository;
private final TripService tripService;
private final TripRepository tripRepository;
private final EntityManager em;

@Transactional
Expand All @@ -40,4 +43,12 @@ public User save(String loginId, String password) {
);
return userRepository.save(user);
}

public void validateUserWithTrip(Long userId, Long tripId) {
User user = userRepository.findById(userId).orElseThrow(() -> new IllegalArgumentException("존재하지 않는 유저입니다."));
Trip trip = tripRepository.findById(tripId).orElseThrow(() -> new IllegalArgumentException("존재하지 않는 여행입니다."));
if (!trip.getUser().equals(user)) {
throw new UserNotValidException("해당 여행은 유저의 여행이 아닙니다.");
}
}
}

0 comments on commit b8558d4

Please sign in to comment.