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
39 changes: 31 additions & 8 deletions src/main/java/com/retrip/trip/application/in/TripService.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,15 @@
import com.retrip.trip.application.in.response.*;
import com.retrip.trip.application.in.usecase.*;
import com.retrip.trip.application.out.crypto.TripPasswordEncoder;
import com.retrip.trip.application.out.repository.*;
import com.retrip.trip.domain.entity.Itinerary;
import com.retrip.trip.domain.entity.Trip;
import com.retrip.trip.domain.entity.TripConfirmationDemand;
import com.retrip.trip.application.out.repository.TripConfirmationDemandRepository;
import com.retrip.trip.application.out.repository.TripItineraryQueryRepository;
import com.retrip.trip.application.out.repository.TripQueryRepository;
import com.retrip.trip.application.out.repository.TripRepository;
import com.retrip.trip.domain.entity.*;
import com.retrip.trip.domain.exception.TripNotFoundException;
import com.retrip.trip.domain.exception.common.BusinessException;
import com.retrip.trip.domain.exception.common.InvalidValueException;
import com.retrip.trip.domain.vo.TripPassword;
import com.retrip.trip.domain.vo.TripPeriod;
import com.retrip.trip.domain.vo.TripStatus;
import com.retrip.trip.domain.vo.*;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
Expand Down Expand Up @@ -56,6 +54,31 @@ public TripCreateResponse createTripWithItineraries(UUID memberId, TripCreateReq
return TripCreateResponse.of(savedTrip);
}

@Override
public TripUpdateResponse updateTrip(UUID memberId, UUID tripId, TripUpdateRequest request) {
Trip trip = findTrip(tripId);

TripTitle tripTitle = request.toTripTitle();
TripDescription tripDescription = request.toTripDescription();
TripPeriod tripPeriod = request.toTripPeriod();
TripHashTags tripHashTags = request.toHashTags(trip);

//List<Itinerary> itineraries = tripItineraryQueryRepository.findByIdsWithItineraryDetails(trip.getItinerariesIds());
trip.update(
memberId,
request.locationId(),
tripTitle,
tripDescription,
tripHashTags,
request.maxParticipants(),
request.imageUrl(),
request.category()
);
trip.updatePeriod(tripPeriod, memberId);

return TripUpdateResponse.of(trip);
}

@Override
public TripUpdateVisibilityResponse updateTripVisibility(UUID tripId, TripUpdateVisibilityRequest request) {
Trip trip = findTrip(tripId);
Expand All @@ -70,7 +93,7 @@ public Page<TripResponse> getTrips(Pageable page) {
Page<Trip> tripsPage = tripQueryRepository.findTrips(page);
List<Trip> trips = tripsPage.getContent();
List<TripHashTag> hashTags = tripQueryRepository.findHashTags(trips);

return new PageImpl<>(TripResponse.of(trips, hashTags), page, tripsPage.getTotalElements());
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package com.retrip.trip.application.in.request;

import com.retrip.trip.domain.entity.Trip;
import com.retrip.trip.domain.entity.TripHashTags;
import com.retrip.trip.domain.vo.*;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.FutureOrPresent;
import jakarta.validation.constraints.NotNull;

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

@Schema(description = "여행 수정 Request")
public record TripUpdateRequest(
@Schema(description = "여행 제목", example = "유럽 배낭여행")
@NotNull
String title,

@Schema(description = "여행 설명", example = "파리, 런던, 로마를 여행하는 일정입니다.")
String description,

@Schema(description = "여행 위치 ID", example = "550e8400-e29b-41d4-a716-446655440001")
@NotNull
UUID locationId,

@Schema(description = "여행 시작 날짜", example = "2025-06-15")
@FutureOrPresent
LocalDate start,

@Schema(description = "여행 종료 날짜", example = "2025-06-25")
@FutureOrPresent
LocalDate end,

@Schema(description = "여행 최대 참가 인원")
Integer maxParticipants,

@Schema(description = "HashTag")
List<String> hashTags,

@Schema(description = "여행 대표 이미지 URL")
String imageUrl,

@Schema(description = "여행 카테고리")
TripCategory category
) {
public TripTitle toTripTitle() {
if (title != null) {
return new TripTitle(title);
}
return null;
}

public TripDescription toTripDescription() {
if (description != null) {
return new TripDescription(description);
}
return null;
}

public TripPeriod toTripPeriod() {
if (start != null && end != null) {
return new TripPeriod(start, end);
}
return null;
}

public TripHashTags toHashTags(Trip trip) {
if (hashTags != null) {
return new TripHashTags(trip, hashTags);
}
return null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package com.retrip.trip.application.in.response;

import com.retrip.trip.domain.entity.Trip;
import com.retrip.trip.domain.entity.TripHashTag;
import io.swagger.v3.oas.annotations.media.Schema;

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

@Schema(description = "여행 생성 Response")
public record TripUpdateResponse(
@Schema(description = "여행 ID", example = "550e8400-e29b-41d4-a716-446655440000")
UUID id,

@Schema(description = "여행 목적지 ID", example = "550e8400-e29b-41d4-a716-446655440001")
UUID destinationId,

@Schema(description = "여행 제목", example = "파리 여행")
String title,

@Schema(description = "여행 설명")
String description,

@Schema(description = "여행 시작 날짜")
LocalDate start,

@Schema(description = "여행 종료 날짜")
LocalDate end,

@Schema(description = "여행 최대 참가 인원")
int maxParticipants,

@Schema(description = "여행 카테고리")
List<String> hashTags,

@Schema(description = "여행 카테고리")
String category,

@Schema(description = "여행 대표 이미지 url")
String imageUrl,

@Schema(description = "여행 일정 리스트")
List<ItineraryUpdateResponse> itineraries
) {
public static TripUpdateResponse of(Trip trip) {
return new TripUpdateResponse(
trip.getId(),
trip.getDestinationId(),
trip.getTitle().getValue(),
trip.getDescription().getValue(),
trip.getPeriod().getStart(),
trip.getPeriod().getEnd(),
trip.getTripParticipants().getMaxParticipants(),
trip.getHashTags().getValues().stream().map(TripHashTag::getName).toList(),
trip.getCategory().getViewName(),
trip.getImageUrl(),
trip.getItineraries() == null ? new ArrayList<>() :
trip.getItineraries().getValues().stream()
.map(i -> new ItineraryUpdateResponse(i.getId(), i.getName(), i.getDate()))
.toList()
);
}

@Schema(description = "여행 일정 Response")
private record ItineraryUpdateResponse(
@Schema(description = "일정 ID")
UUID id,

@Schema(description = "일정 이름")
String name,

@Schema(description = "일정 날짜")
LocalDate date
) {
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package com.retrip.trip.application.in.usecase;

import com.retrip.trip.application.in.request.TripCreateRequest;
import com.retrip.trip.application.in.request.TripUpdateRequest;
import com.retrip.trip.application.in.request.TripUpdateVisibilityRequest;
import com.retrip.trip.application.in.response.TripCreateResponse;
import com.retrip.trip.application.in.response.TripUpdateResponse;
import com.retrip.trip.application.in.response.TripUpdateVisibilityResponse;

import java.util.List;
Expand All @@ -13,6 +15,8 @@ public interface TripManageUseCase {

TripCreateResponse createTripWithItineraries(UUID memberId, TripCreateRequest request);

TripUpdateResponse updateTrip(UUID memberId, UUID tripId, TripUpdateRequest request);

TripUpdateVisibilityResponse updateTripVisibility(UUID tripId, TripUpdateVisibilityRequest request);

void banMembers(UUID memberId, UUID tripId, List<UUID> memberIds);
Expand Down
49 changes: 44 additions & 5 deletions src/main/java/com/retrip/trip/domain/entity/Trip.java
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
package com.retrip.trip.domain.entity;

import com.retrip.trip.domain.exception.LeaderCannotLeaveException;
import com.retrip.trip.domain.exception.NotParticipantException;
import com.retrip.trip.domain.exception.PeriodUpdateFailedException;
import com.retrip.trip.domain.exception.TripNotReadyException;
import com.retrip.trip.domain.exception.*;
import com.retrip.trip.domain.exception.common.BusinessException;
import com.retrip.trip.domain.vo.*;
import jakarta.persistence.*;
Expand Down Expand Up @@ -205,4 +202,46 @@
public boolean isNotTripRecruitingStatus() {
return !TripStatus.RECRUITING.equals(status);
}
}


public void update(

Check warning on line 207 in src/main/java/com/retrip/trip/domain/entity/Trip.java

View check run for this annotation

Codacy Production / Codacy Static Code Analysis

src/main/java/com/retrip/trip/domain/entity/Trip.java#L207

The method 'update(UUID, UUID, TripTitle, TripDescription, TripHashTags, Integer, String, TripCategory)' has an NPath complexity of 256, current threshold is 200
UUID memberId,
UUID destinationId,
TripTitle tripTitle,
TripDescription tripDescription,
TripHashTags tripHashTags,
Integer maxParticipants,
String imageUrl,
TripCategory category
) {
if (!tripParticipants.updatableByLeader(memberId)) {
throw new TripUpdateFailedException();
}

if (destinationId != null) {
this.destinationId = destinationId;
}

if (tripTitle != null) {
this.title = tripTitle;
}
if (tripDescription != null) {
this.description = tripDescription;
}

if (tripHashTags != null) {
this.hashTags.getValues().clear();
this.hashTags.getValues().addAll(tripHashTags.getValues());
}

if (maxParticipants != null) {
this.tripParticipants.updateMaxParticipants(maxParticipants, memberId);
}
if (imageUrl != null) {
this.imageUrl = imageUrl;
}
if (category != null) {
this.category = category;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.retrip.trip.domain.exception;

import com.retrip.trip.domain.exception.common.BusinessException;
import com.retrip.trip.domain.exception.common.ErrorCode;

public class TripUpdateFailedException extends BusinessException {
private static final ErrorCode errorCode = ErrorCode.TRIP_UPDATE_FAIL;

public TripUpdateFailedException() {
super(errorCode);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public enum ErrorCode {
ILLEGAL_ARGUMENT(BAD_REQUEST, "Common-006", "Illegal argument"),

TRIP_NOT_FOUND(BAD_REQUEST, "Trip-001", "트립 엔티티를 찾을 수 없습니다."),
PERIOD_UPDATE_FAIL(INTERNAL_SERVER_ERROR, "Trip-002", "여행 일정을 변경할 수 없습니다."),
PERIOD_UPDATE_FAIL(BAD_REQUEST, "Trip-002", "여행 일정을 변경할 수 없습니다."),
NOT_TRIP_LEADER(BAD_REQUEST, "Trip-003", "여행 리더가 아니면 접근할 수 없습니다."),
TRIP_INVITATION_DUPLICATE(BAD_REQUEST, "Trip-004", "사용자를 여행에 중복 초대할 수 없습니다."),
MEMBER_IS_NOT_LEADER(BAD_REQUEST, "Trip-005", "여행 리더가 아니면 접근할 수 없습니다."),
Expand All @@ -39,8 +39,8 @@ public enum ErrorCode {
TRIP_PASSWORD_INVALID(BAD_REQUEST, "Trip-023", "비공개 여행 비밀번호의 길이가 적절하지 않습니다."),
TRIP_DEMAND_NOT_ALLOWED(BAD_REQUEST, "Trip-024", "이미 참여를 요청했거나 참여 중인 여행이므로 참여 요청을 다시 할 수 없습니다."),
TRIP_DEMAND_STATUS_NOT_PENDING(BAD_REQUEST, "Trip-025", "현재 참여 요청 상태가 ‘대기’가 아니므로 해당 요청을 수행할 수 없습니다."),
INVALID_MAX_PARTICIPANTS_VALUE(BAD_REQUEST,"Trip-026","최대 참여 인원은 1명 이상이어야 합니다."),
MAX_PARTICIPANTS_LESS_THAN_CURRENT(BAD_REQUEST,"Trip-027","현재 참여 인원보다 적은 수로 변경할 수 없습니다."),
INVALID_MAX_PARTICIPANTS_VALUE(BAD_REQUEST, "Trip-026", "최대 참여 인원은 1명 이상이어야 합니다."),
MAX_PARTICIPANTS_LESS_THAN_CURRENT(BAD_REQUEST, "Trip-027", "현재 참여 인원보다 적은 수로 변경할 수 없습니다."),
INVALID_HASHTAG_LENGTH(BAD_REQUEST, "Trip-028", "HashTag는 1~10자 사이여야 합니다."),
PRIVATE_TRIP_PASSWORD_REQUIRED(BAD_REQUEST, "Trip-029", "비공개 여행은 비밀번호를 반드시 입력해야 합니다."),
TRIP_DAY_MUST_BE_POSITIVE(BAD_REQUEST, "Trip-030", "여행 일차는 1보다 작을 수 없습니다."),
Expand All @@ -58,6 +58,7 @@ public enum ErrorCode {
TRIP_PASSWORD_MISMATCH(BAD_REQUEST, "Trip-042", "여행 비밀번호가 일치하지 않습니다."),
VOTE_MODIFY_FORBIDDEN(BAD_REQUEST, "Trip-043", "투표를 만든 사람이 아니면 수정, 종료, 삭제 할 수 없습니다."),
EXTENSION_NOT_FOUND(BAD_REQUEST, "Trip-044", "지원하지 않는 이미지 확장자입니다."),
TRIP_UPDATE_FAIL(BAD_REQUEST, "Trip-045", "여행을 수정할 수 없습니다."),
;

private final HttpStatus status;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,19 @@ public ApiResponse<TripCreateResponse> createTrip(
return ApiResponse.created(trip);
}

@Operation(
summary = "여행 수정",
description = "여행을 수정하는 API"
)
@PutMapping("/{tripId}")
public ApiResponse<TripUpdateResponse> updateTrip(
@WithUserContext UserContext userContext,
@PathVariable UUID tripId,
@RequestBody TripUpdateRequest request) {
TripUpdateResponse trip = tripManageUseCase.updateTrip(userContext.memberId(), tripId, request);
return ApiResponse.ok(trip);
}

@Operation(
summary = "일정이 포함된 여행 생성",
description = "일정이 포함된 여행을 생성하는 API -> 이거는 사용하는지 확인해봐야함 일정을 별도로 생기는거로 바뀌었던 거 같아서"
Expand All @@ -79,7 +92,7 @@ public ApiResponse<TripCreateResponse> createTripWithItineraries(
description = "여행 공개 여부를 변경하는 API"
)
@ApiErrorCodeExamples({TRIP_NOT_FOUND, PRIVATE_TRIP_PASSWORD_REQUIRED, TRIP_PASSWORD_INVALID})
@PutMapping("/{tripId}")
@PutMapping("/open/{tripId}")
public ApiResponse<TripUpdateVisibilityResponse> updateTripVisibility(
@PathVariable UUID tripId, @RequestBody TripUpdateVisibilityRequest request) {
TripUpdateVisibilityResponse trip = tripManageUseCase.updateTripVisibility(tripId, request);
Expand Down
7 changes: 4 additions & 3 deletions src/main/resources/data.sql
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,14 @@ VALUES (random_uuid(), x'11111111111111111111111111111111', x'999999999999999999

-- 방장(HOST) 데이터
INSERT INTO trip_participant (id, trip_id, member_id, status, role, created_at)
VALUES (random_uuid(), x'11111111111111111111111111111111', x'99999999999999999999999999999993', 1, 'HOST', now());
VALUES (random_uuid(), x'11111111111111111111111111111111', x'99999999999999999999999999999993', 1, 'LEADER', now());

-- 일반 참여자(MEMBER) 데이터 (Member ID를 다르게 설정)
INSERT INTO trip_participant (id, trip_id, member_id, status, role, created_at)
VALUES (random_uuid(), x'11111111111111111111111111111112', x'99999999999999999999999999999991', 1, 'HOST', now());
VALUES (random_uuid(), x'11111111111111111111111111111112', x'99999999999999999999999999999991', 1, 'LEADER', now());
INSERT INTO trip_participant (id, trip_id, member_id, status, role, created_at)
VALUES (random_uuid(), x'11111111111111111111111111111112', x'99999999999999999999999999999992', 1, 'MEMBER', now());
VALUES (random_uuid(), x'11111111111111111111111111111112', x'99999999999999999999999999999992', 1, 'PARTICIPANT',
now());

-- 7. Vote (투표 생성)
INSERT INTO vote (id, trip_id, title, description, status, version, max_selections, anonymous, allow_add_option,
Expand Down