Skip to content

Commit

Permalink
Merge pull request #31 from Team-Going/feature/27
Browse files Browse the repository at this point in the history
[feat] 여행 생성 API 구현
  • Loading branch information
gardening-y authored Jan 8, 2024
2 parents 8cc7002 + e531138 commit 32d2c81
Show file tree
Hide file tree
Showing 8 changed files with 163 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,22 +5,30 @@
import org.doorip.common.ApiResponse;
import org.doorip.common.ApiResponseUtil;
import org.doorip.message.SuccessMessage;
import org.doorip.trip.dto.request.TripCreateRequest;
import org.doorip.trip.dto.response.TripCreateResponse;
import org.doorip.trip.dto.response.TripGetResponse;
import org.doorip.trip.service.TripService;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.*;

@RequiredArgsConstructor
@RequestMapping("/api/trips")
@Controller
public class TripApiController {
private final TripService tripService;

@PostMapping
public ResponseEntity<ApiResponse<?>> createTrip(@UserId final Long userId,
@RequestBody final TripCreateRequest request) {
TripCreateResponse response = tripService.createTripAndParticipant(userId, request);
return ApiResponseUtil.success(SuccessMessage.CREATED, response);
}

@GetMapping
public ResponseEntity<ApiResponse<?>> getTrips(@UserId final Long userId, @RequestParam final String progress) {
public ResponseEntity<ApiResponse<?>> getTrips(@UserId final Long userId,
@RequestParam final String progress) {
final TripGetResponse response = tripService.getTrips(userId, progress);
return ApiResponseUtil.success(SuccessMessage.OK, response);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package org.doorip.trip.dto.request;

import com.fasterxml.jackson.annotation.JsonFormat;

import java.time.LocalDate;

public record TripCreateRequest(
String title,
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd", timezone = "Asia/Seoul")
LocalDate startDate,
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd", timezone = "Asia/Seoul")
LocalDate endDate,
int styleA,
int styleB,
int styleC,
int styleD,
int styleE
) {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package org.doorip.trip.dto.response;

import com.fasterxml.jackson.annotation.JsonFormat;
import org.doorip.trip.domain.Trip;

import java.time.LocalDate;

import static java.time.Period.between;

public record TripCreateResponse(
Long tripId,
String title,
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd", timezone = "Asia/Seoul")
LocalDate startDate,
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd", timezone = "Asia/Seoul")
LocalDate endDate,
String code,
int day
) {

public static TripCreateResponse of(Trip trip) {
return new TripCreateResponse(
trip.getId(),
trip.getTitle(),
trip.getStartDate(),
trip.getEndDate(),
trip.getCode(),
between(LocalDate.now(), trip.getStartDate()).getDays()
);
}
}
61 changes: 56 additions & 5 deletions doorip-api/src/main/java/org/doorip/trip/service/TripService.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
package org.doorip.trip.service;

import lombok.RequiredArgsConstructor;
import org.doorip.common.Constants;
import org.doorip.exception.EntityNotFoundException;
import org.doorip.exception.InvalidValueException;
import org.doorip.message.ErrorMessage;
import org.doorip.trip.domain.Participant;
import org.doorip.trip.domain.Role;
import org.doorip.trip.domain.Trip;
import org.doorip.trip.dto.request.TripCreateRequest;
import org.doorip.trip.dto.response.TripCreateResponse;
import org.doorip.trip.repository.ParticipantRepository;
import org.doorip.common.Constants;
import org.doorip.trip.dto.response.TripGetResponse;
import org.doorip.trip.repository.TripRepository;
import org.doorip.user.domain.User;
Expand All @@ -14,24 +19,61 @@
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.util.UUID;

import static org.doorip.trip.domain.Participant.createParticipant;
import static org.doorip.trip.domain.Trip.createTrip;
import java.util.List;

@RequiredArgsConstructor
@Transactional(readOnly = true)
@Service
public class TripService {
private final UserRepository userRepository;
private final TripRepository tripRepository;
private final ParticipantRepository participantRepository;
private final UserRepository userRepository;

@Transactional
public TripCreateResponse createTripAndParticipant(Long userId, TripCreateRequest request) {
User findUser = getUser(userId);
validateDate(request.startDate(), request.endDate());
String code = createCode();
Trip trip = createTrip(request, code);
createParticipant(request, findUser, trip);
tripRepository.save(trip);

return TripCreateResponse.of(trip);
}

public TripGetResponse getTrips(Long userId, String progress) {
User findUser = getUser(userId);
List<Trip> trips = getTripsAccordingToProgress(userId, progress);
return TripGetResponse.of(findUser.getName(), trips);
}

private User getUser(Long userId) {
return userRepository.findById(userId)
.orElseThrow(() -> new EntityNotFoundException(ErrorMessage.USER_NOT_FOUND));
private void validateDate(LocalDate startDate, LocalDate endDate) {
if (endDate.isBefore(LocalDate.now()) || endDate.isBefore(startDate)) {
throw new InvalidValueException(ErrorMessage.INVALID_DATE_TYPE);
}
}

private String createCode() {
String code;
do {
String uuid = UUID.randomUUID().toString();
code = uuid.substring(0, 6);
} while (isDuplicateCode(code));

return code;
}

private Trip createTrip(TripCreateRequest request, String code) {
return Trip.createTrip(request.title(), request.startDate(), request.endDate(), code);
}

private void createParticipant(TripCreateRequest request, User user, Trip trip) {
Participant.createParticipant(Role.HOST, request.styleA(), request.styleB(),
request.styleC(), request.styleD(), request.styleE(), user, trip);
}

private List<Trip> getTripsAccordingToProgress(Long userId, String progress) {
Expand All @@ -42,4 +84,13 @@ private List<Trip> getTripsAccordingToProgress(Long userId, String progress) {
}
throw new InvalidValueException(ErrorMessage.INVALID_REQUEST_PARAMETER_VALUE);
}

private User getUser(Long userId) {
return userRepository.findById(userId)
.orElseThrow(() -> new EntityNotFoundException(ErrorMessage.USER_NOT_FOUND));
}

private boolean isDuplicateCode(String code) {
return tripRepository.existsByCode(code);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ public enum ErrorMessage {
INVALID_PLATFORM_TYPE(HttpStatus.BAD_REQUEST, "e4001", "유효하지 않은 플랫폼 타입입니다."),
INVALID_REQUEST_PARAMETER_VALUE(HttpStatus.BAD_REQUEST, "e4002", "유효하지 않은 요청 파라미터 값입니다."),
INVALID_ALLOCATOR_COUNT(HttpStatus.BAD_REQUEST, "e4003", "여행 TODO를 생성하기 위해 최소 1명 이상의 배정자가 필요합니다."),
INVALID_DATE_TYPE(HttpStatus.BAD_REQUEST, "e4004", "유효하지 않은 날짜 타입입니다."),

/**
* 401 Unauthorized
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,30 @@ public class Participant extends BaseTimeEntity {
@OneToMany(mappedBy = "participant", fetch = FetchType.LAZY, cascade = CascadeType.REMOVE)
private List<Allocator> allocators = new ArrayList<>();

public static Participant createParticipant(Role role, int styleA, int styleB, int styleC, int styleD, int styleE, User user, Trip trip){
Participant participant = Participant.builder()
.role(role)
.styleA(styleA)
.styleB(styleB)
.styleC(styleC)
.styleD(styleD)
.styleE(styleE)
.user(user)
.trip(trip)
.build();
participant.changeTrip(trip);

return participant;
}

public void changeTrip(Trip trip) {
if (this.trip != null) {
this.trip.removeParticipant(this);
}
this.trip = trip;
trip.addParticipant(this);
}

public void addAllocator(Allocator allocator) {
allocators.add(allocator);
}
Expand Down
19 changes: 18 additions & 1 deletion doorip-domain/src/main/java/org/doorip/trip/domain/Trip.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,29 @@ public class Trip extends BaseTimeEntity {
@Column(nullable = false)
private String code;
@Builder.Default
@OneToMany(mappedBy = "trip", cascade = CascadeType.REMOVE)
@OneToMany(mappedBy = "trip", cascade = {CascadeType.REMOVE, CascadeType.PERSIST})
private List<Participant> participants = new ArrayList<>();
@Builder.Default
@OneToMany(mappedBy = "trip", cascade = CascadeType.REMOVE)
private List<Todo> todos = new ArrayList<>();

public static Trip createTrip(String title, LocalDate startDate, LocalDate endDate, String code) {
return Trip.builder()
.title(title)
.startDate(startDate)
.endDate(endDate)
.code(code)
.build();
}

public void addParticipant(Participant participant) {
participants.add(participant);
}

public void removeParticipant(Participant participant) {
participants.remove(participant);
}

public void addTodo(Todo todo) {
todos.add(todo);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,6 @@ public interface TripRepository extends JpaRepository<Trip, Long> {
"and datediff(t.endDate, :now) < 0 " +
"order by datediff(:now, t.endDate)")
List<Trip> findCompleteTripsByUserId(@Param("userId") Long userId, @Param("now") LocalDate now);

boolean existsByCode(String code);
}

0 comments on commit 32d2c81

Please sign in to comment.