From e609e4a0ddab60438332fa9c28b1694650449587 Mon Sep 17 00:00:00 2001 From: Dayeon-Hong Date: Tue, 28 May 2024 16:21:43 +0900 Subject: [PATCH] =?UTF-8?q?feat=20:=20=EC=B5=9C=EA=B7=BC=EC=97=90=20?= =?UTF-8?q?=EC=83=9D=EC=84=B1=ED=95=9C=20=EC=97=AC=ED=96=89=20=EC=9D=BC?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../service/FlightOfferServiceImpl.java | 2 +- .../controller/ScheduleController.java | 10 +++- .../schedule/dto/request/DailySchedule.java | 2 +- ...Detail.java => ScheduleDetailRequest.java} | 2 +- .../dto/response/FastestScheduleResponse.java | 4 +- .../dto/response/LatestCreateResponse.java | 26 ++++++++++ .../schedule/mapper/ScheduleMapper.java | 51 ++++++++++++++----- .../repository/ScheduleRepository.java | 3 +- .../schedule/service/ScheduleService.java | 7 +++ .../schedule/service/ScheduleServiceImpl.java | 20 ++++++-- .../scheduleDetail/entity/ScheduleDetail.java | 2 +- .../scheduleDetail/entity/ScheduleType.java | 8 ++- 12 files changed, 108 insertions(+), 29 deletions(-) rename backend/src/main/java/com/isp/backend/domain/schedule/dto/request/{ScheduleDetail.java => ScheduleDetailRequest.java} (93%) create mode 100644 backend/src/main/java/com/isp/backend/domain/schedule/dto/response/LatestCreateResponse.java diff --git a/backend/src/main/java/com/isp/backend/domain/flight/service/FlightOfferServiceImpl.java b/backend/src/main/java/com/isp/backend/domain/flight/service/FlightOfferServiceImpl.java index 59cae898..917c07a3 100644 --- a/backend/src/main/java/com/isp/backend/domain/flight/service/FlightOfferServiceImpl.java +++ b/backend/src/main/java/com/isp/backend/domain/flight/service/FlightOfferServiceImpl.java @@ -91,7 +91,7 @@ public String generateSkyscannerUrl(SkyScannerRequest request) { if (request.getTransferCount() == 0) { url += "&preferdirects=true"; } else if (request.getTransferCount() == 1) { - url += "&preferdirects=false&stops=!direct"; + url += "&preferdirects=false&stops=!direct"; } else { url += "&preferdirects=false&stops=!direct,!oneStop,!oneStop"; } diff --git a/backend/src/main/java/com/isp/backend/domain/schedule/controller/ScheduleController.java b/backend/src/main/java/com/isp/backend/domain/schedule/controller/ScheduleController.java index 4548ce95..b903363d 100644 --- a/backend/src/main/java/com/isp/backend/domain/schedule/controller/ScheduleController.java +++ b/backend/src/main/java/com/isp/backend/domain/schedule/controller/ScheduleController.java @@ -1,6 +1,7 @@ package com.isp.backend.domain.schedule.controller; import com.isp.backend.domain.schedule.dto.response.FastestScheduleResponse; +import com.isp.backend.domain.schedule.dto.response.LatestCreateResponse; import com.isp.backend.domain.schedule.dto.response.ScheduleListResponse; import com.isp.backend.domain.schedule.dto.request.ScheduleSaveRequest; import com.isp.backend.domain.schedule.service.ScheduleService; @@ -77,7 +78,14 @@ public ResponseEntity getFastestSchedule(@Authenticatio /** 내가 최근 생성한 5개 일정 조회 API **/ -// public ResponseEntity<> + @GetMapping("/latest") + public ResponseEntity> getLatestCreatedSchedules( + @AuthenticationPrincipal CustomUserDetails userDetails, + @RequestParam(value = "limit", defaultValue = "6") int limit) { // 출력할 세부 일정 개수 조절 + String memberUid = userDetails.getUsername(); + List responses = scheduleService.getLatestCreatedSchedules(memberUid, limit); + return ResponseEntity.ok(responses); + } } \ No newline at end of file diff --git a/backend/src/main/java/com/isp/backend/domain/schedule/dto/request/DailySchedule.java b/backend/src/main/java/com/isp/backend/domain/schedule/dto/request/DailySchedule.java index 80589d6a..d34f4565 100644 --- a/backend/src/main/java/com/isp/backend/domain/schedule/dto/request/DailySchedule.java +++ b/backend/src/main/java/com/isp/backend/domain/schedule/dto/request/DailySchedule.java @@ -15,6 +15,6 @@ public class DailySchedule { private String date; // 일정 날짜 - private List schedules; // 해당 날짜의 일정 목록 + private List schedules; // 해당 날짜의 일정 목록 } diff --git a/backend/src/main/java/com/isp/backend/domain/schedule/dto/request/ScheduleDetail.java b/backend/src/main/java/com/isp/backend/domain/schedule/dto/request/ScheduleDetailRequest.java similarity index 93% rename from backend/src/main/java/com/isp/backend/domain/schedule/dto/request/ScheduleDetail.java rename to backend/src/main/java/com/isp/backend/domain/schedule/dto/request/ScheduleDetailRequest.java index 6933e629..c5e82f7d 100644 --- a/backend/src/main/java/com/isp/backend/domain/schedule/dto/request/ScheduleDetail.java +++ b/backend/src/main/java/com/isp/backend/domain/schedule/dto/request/ScheduleDetailRequest.java @@ -11,7 +11,7 @@ @Setter @NoArgsConstructor @AllArgsConstructor -public class ScheduleDetail { +public class ScheduleDetailRequest { private String todo; // 할 일 diff --git a/backend/src/main/java/com/isp/backend/domain/schedule/dto/response/FastestScheduleResponse.java b/backend/src/main/java/com/isp/backend/domain/schedule/dto/response/FastestScheduleResponse.java index 37ed6fbb..49ffc7e5 100644 --- a/backend/src/main/java/com/isp/backend/domain/schedule/dto/response/FastestScheduleResponse.java +++ b/backend/src/main/java/com/isp/backend/domain/schedule/dto/response/FastestScheduleResponse.java @@ -15,8 +15,8 @@ public class FastestScheduleResponse { private String scheduleName; // 여행지 이름 - private String dday; // 디데이 + private String dday; - private String imageUrl; // 이미지 url + private String imageUrl; } diff --git a/backend/src/main/java/com/isp/backend/domain/schedule/dto/response/LatestCreateResponse.java b/backend/src/main/java/com/isp/backend/domain/schedule/dto/response/LatestCreateResponse.java new file mode 100644 index 00000000..d56c9509 --- /dev/null +++ b/backend/src/main/java/com/isp/backend/domain/schedule/dto/response/LatestCreateResponse.java @@ -0,0 +1,26 @@ +package com.isp.backend.domain.schedule.dto.response; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; +import lombok.Setter; + +import java.util.List; + +@Getter +@Setter +@NoArgsConstructor +@AllArgsConstructor +public class LatestCreateResponse { + + private Long id; + + private String scheduleName; + + private String city; // 여행지 장소 + + private String imageUrl; // 이미지 url + + private List plan ; // 여행 일정 리스트 + +} diff --git a/backend/src/main/java/com/isp/backend/domain/schedule/mapper/ScheduleMapper.java b/backend/src/main/java/com/isp/backend/domain/schedule/mapper/ScheduleMapper.java index 5e7c7462..4ccfffe4 100644 --- a/backend/src/main/java/com/isp/backend/domain/schedule/mapper/ScheduleMapper.java +++ b/backend/src/main/java/com/isp/backend/domain/schedule/mapper/ScheduleMapper.java @@ -3,11 +3,13 @@ import com.isp.backend.domain.country.entity.Country; import com.isp.backend.domain.member.entity.Member; import com.isp.backend.domain.schedule.dto.request.DailySchedule; -import com.isp.backend.domain.schedule.dto.request.ScheduleDetail; +import com.isp.backend.domain.schedule.dto.request.ScheduleDetailRequest; import com.isp.backend.domain.schedule.dto.response.FastestScheduleResponse; +import com.isp.backend.domain.schedule.dto.response.LatestCreateResponse; import com.isp.backend.domain.schedule.dto.response.ScheduleListResponse; import com.isp.backend.domain.schedule.dto.request.ScheduleSaveRequest; import com.isp.backend.domain.schedule.entity.Schedule; +import com.isp.backend.domain.scheduleDetail.entity.ScheduleDetail; import lombok.RequiredArgsConstructor; import org.springframework.stereotype.Component; @@ -25,7 +27,7 @@ public class ScheduleMapper { /** * 일정 저장 **/ - // 여행 일정 요청 DTO -> 엔티티로 변환 +// 여행 일정 요청 DTO -> 엔티티로 변환 public Schedule toScheduleEntity(ScheduleSaveRequest scheduleSaveRequest, Member member, Country country) { // 여행 일정 엔티티 생성 Schedule schedule = Schedule.builder() @@ -37,11 +39,11 @@ public Schedule toScheduleEntity(ScheduleSaveRequest scheduleSaveRequest, Member .build(); // 여행 일정 세부 항목 리스트 생성 - List scheduleDetails = scheduleSaveRequest.getDailySchedules().stream() + List scheduleDetails = scheduleSaveRequest.getDailySchedules().stream() .flatMap(dailySchedule -> { AtomicInteger num = new AtomicInteger(1); // 날짜별 일정 순서 카운터 return dailySchedule.getSchedules().stream() - .map(scheduleDetail -> toScheduleDetailEntity(scheduleDetail, dailySchedule, schedule, num.getAndIncrement())); + .map(scheduleDetailDTO -> toScheduleDetailEntity(scheduleDetailDTO, dailySchedule, schedule, num.getAndIncrement())); }) .collect(Collectors.toList()); @@ -52,8 +54,8 @@ public Schedule toScheduleEntity(ScheduleSaveRequest scheduleSaveRequest, Member } // 일정 세부 DTO를 엔티티로 변환 - private com.isp.backend.domain.scheduleDetail.entity.ScheduleDetail toScheduleDetailEntity(ScheduleDetail scheduleDetailDTO, DailySchedule dailySchedule, Schedule schedule, int num) { - com.isp.backend.domain.scheduleDetail.entity.ScheduleDetail scheduleDetail = com.isp.backend.domain.scheduleDetail.entity.ScheduleDetail.builder() + private ScheduleDetail toScheduleDetailEntity(ScheduleDetailRequest scheduleDetailDTO, DailySchedule dailySchedule, Schedule schedule, int num) { + ScheduleDetail scheduleDetail = ScheduleDetail.builder() .todo(scheduleDetailDTO.getTodo()) .place(scheduleDetailDTO.getPlace()) .budget(scheduleDetailDTO.getBudget()) @@ -96,13 +98,13 @@ public ScheduleListResponse toScheduleListResponseDTO(Schedule schedule) { public ScheduleSaveRequest toScheduleResponseDTO(Schedule schedule) { // 일정 세부를 날짜별로 그룹화하고, 날짜를 기준으로 정렬 List sortedDailySchedules = schedule.getScheduleDetails().stream() - .sorted(Comparator.comparing(com.isp.backend.domain.scheduleDetail.entity.ScheduleDetail::getDate)) - .collect(Collectors.groupingBy(com.isp.backend.domain.scheduleDetail.entity.ScheduleDetail::getDate)) + .sorted(Comparator.comparing(ScheduleDetail::getDate)) + .collect(Collectors.groupingBy(ScheduleDetail::getDate)) .entrySet().stream() .map(entry -> new DailySchedule( entry.getKey(), entry.getValue().stream() - .sorted(Comparator.comparingInt(com.isp.backend.domain.scheduleDetail.entity.ScheduleDetail::getNum)) + .sorted(Comparator.comparingInt(ScheduleDetail::getNum)) .map(this::toScheduleDetailDTO) .collect(Collectors.toList()) )) @@ -111,7 +113,7 @@ public ScheduleSaveRequest toScheduleResponseDTO(Schedule schedule) { return new ScheduleSaveRequest( schedule.getScheduleName(), - schedule.getCountry().getCity(), + schedule.getCountry().getCity(), // 국가에서 도시 가져오기로 수정 schedule.getStartDate(), schedule.getEndDate(), sortedDailySchedules @@ -119,8 +121,8 @@ public ScheduleSaveRequest toScheduleResponseDTO(Schedule schedule) { } // ScheduleDetail 엔티티를 ScheduleDetailDTO로 변환하는 메서드 - private ScheduleDetail toScheduleDetailDTO(com.isp.backend.domain.scheduleDetail.entity.ScheduleDetail scheduleDetail) { - return new ScheduleDetail( + private ScheduleDetailRequest toScheduleDetailDTO(ScheduleDetail scheduleDetail) { + ScheduleDetailRequest scheduleDetailDTO = new ScheduleDetailRequest( scheduleDetail.getTodo(), scheduleDetail.getPlace(), scheduleDetail.getScheduleType(), @@ -128,6 +130,7 @@ private ScheduleDetail toScheduleDetailDTO(com.isp.backend.domain.scheduleDetail scheduleDetail.getLatitude(), scheduleDetail.getLongitude() ); + return scheduleDetailDTO; } @@ -135,7 +138,7 @@ private ScheduleDetail toScheduleDetailDTO(com.isp.backend.domain.scheduleDetail * 일정 수정 **/ // ScheduleDetailDTO 목록을 ScheduleDetail 엔티티 목록으로 변환하는 메서드 - public List updateSchedulesEntity(ScheduleSaveRequest scheduleSaveRequest, Schedule schedule) { + public List updateSchedulesEntity(ScheduleSaveRequest scheduleSaveRequest, Schedule schedule) { return scheduleSaveRequest.getDailySchedules().stream() .flatMap(dailySchedule -> { AtomicInteger num = new AtomicInteger(1); // 날짜별 일정 순서 카운터 @@ -173,6 +176,28 @@ private String calculateDday(String startDateString) { + /** + * 최근에 생성한 여행 일정 top 5 + **/ + public LatestCreateResponse toLatestCreateResponse(Schedule schedule, int limit) { + List limitedPlan = schedule.getScheduleDetails().stream() + .sorted(Comparator.comparing(ScheduleDetail::getDate) + .thenComparing(ScheduleDetail::getNum)) + .map(ScheduleDetail::getTodo) + .limit(limit) // 최대 개수로 제한 + .collect(Collectors.toList()); + + return new LatestCreateResponse( + schedule.getId(), + schedule.getScheduleName(), + schedule.getCountry().getCity(), // 국가에서 도시 가져오기로 수정 + schedule.getCountry().getImageUrl(), // 이미지 URL 추가 (엔티티에 이 필드가 있다고 가정) + limitedPlan + ); + } + + + } diff --git a/backend/src/main/java/com/isp/backend/domain/schedule/repository/ScheduleRepository.java b/backend/src/main/java/com/isp/backend/domain/schedule/repository/ScheduleRepository.java index 350bd950..5891e71f 100644 --- a/backend/src/main/java/com/isp/backend/domain/schedule/repository/ScheduleRepository.java +++ b/backend/src/main/java/com/isp/backend/domain/schedule/repository/ScheduleRepository.java @@ -2,6 +2,7 @@ import com.isp.backend.domain.member.entity.Member; import com.isp.backend.domain.schedule.entity.Schedule; +import org.springframework.data.domain.Pageable; import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.Query; import org.springframework.data.repository.query.Param; @@ -11,8 +12,8 @@ public interface ScheduleRepository extends JpaRepository { Optional findByIdAndActivatedIsTrue(Long scheduleId); - @Query("SELECT s FROM Schedule s WHERE s.member = :member AND s.activated = true ORDER BY s.updatedAt DESC") List findSchedulesByMember(@Param("member") Member member); + List findTop5ByMemberOrderByIdDesc(Member member); } diff --git a/backend/src/main/java/com/isp/backend/domain/schedule/service/ScheduleService.java b/backend/src/main/java/com/isp/backend/domain/schedule/service/ScheduleService.java index 9dcf87a2..c735b622 100644 --- a/backend/src/main/java/com/isp/backend/domain/schedule/service/ScheduleService.java +++ b/backend/src/main/java/com/isp/backend/domain/schedule/service/ScheduleService.java @@ -3,11 +3,14 @@ import com.isp.backend.domain.country.entity.Country; import com.isp.backend.domain.member.entity.Member; import com.isp.backend.domain.schedule.dto.response.FastestScheduleResponse; +import com.isp.backend.domain.schedule.dto.response.LatestCreateResponse; import com.isp.backend.domain.schedule.dto.response.ScheduleListResponse; import com.isp.backend.domain.schedule.dto.request.ScheduleSaveRequest; import com.isp.backend.domain.schedule.entity.Schedule; +import java.time.LocalDate; import java.util.List; +import java.util.Optional; public interface ScheduleService { @@ -23,6 +26,8 @@ public interface ScheduleService { ScheduleSaveRequest updateSchedule(String uid, Long scheduleId, ScheduleSaveRequest updateRequestDTO); + Optional findClosestSchedule(List schedules, LocalDate today); + void calculateTotalPrice(Schedule schedule); Member validateUserCheck(String uid); @@ -30,4 +35,6 @@ public interface ScheduleService { Schedule validateSchedule(Long scheduleId); Country validateCountry(String countryName); + + List getLatestCreatedSchedules(String uid, int limit); } diff --git a/backend/src/main/java/com/isp/backend/domain/schedule/service/ScheduleServiceImpl.java b/backend/src/main/java/com/isp/backend/domain/schedule/service/ScheduleServiceImpl.java index 72617171..4baf26f5 100644 --- a/backend/src/main/java/com/isp/backend/domain/schedule/service/ScheduleServiceImpl.java +++ b/backend/src/main/java/com/isp/backend/domain/schedule/service/ScheduleServiceImpl.java @@ -2,10 +2,10 @@ import com.isp.backend.domain.country.entity.Country; import com.isp.backend.domain.country.repository.CountryRepository; -import com.isp.backend.domain.member.dto.response.MemberDetailResponse; import com.isp.backend.domain.member.entity.Member; import com.isp.backend.domain.member.repository.MemberRepository; import com.isp.backend.domain.schedule.dto.response.FastestScheduleResponse; +import com.isp.backend.domain.schedule.dto.response.LatestCreateResponse; import com.isp.backend.domain.schedule.dto.response.ScheduleListResponse; import com.isp.backend.domain.schedule.dto.request.ScheduleSaveRequest; import com.isp.backend.domain.schedule.entity.Schedule; @@ -23,7 +23,7 @@ import org.springframework.transaction.annotation.Transactional; import java.time.LocalDate; -import java.time.temporal.ChronoUnit; +import java.util.ArrayList; import java.util.Comparator; import java.util.List; import java.util.Optional; @@ -133,6 +133,7 @@ public void deleteSchedule(String uid, Long scheduleId) { } /** 나의 여행 D-day 출력 **/ + @Override public FastestScheduleResponse getFastestSchedule(String uid) { Member findMember = validateUserCheck(uid); List schedules = scheduleRepository.findSchedulesByMember(findMember); @@ -151,7 +152,8 @@ public FastestScheduleResponse getFastestSchedule(String uid) { /** 가장 가까운 일정 찾기 **/ - private Optional findClosestSchedule(List schedules, LocalDate today) { + @Override + public Optional findClosestSchedule(List schedules, LocalDate today) { return schedules.stream() .filter(schedule -> LocalDate.parse(schedule.getStartDate()).isAfter(today)) // 오늘 이후의 일정 .min(Comparator.comparing(s -> LocalDate.parse(s.getStartDate()))); // 시작일이 가장 빠른 순으로 정렬 @@ -196,6 +198,18 @@ public Country validateCountry(String countryName) { } + /** 최근에 생성한 여행 일정 top 5**/ + @Override + public List getLatestCreatedSchedules(String uid, int limit) { + Member findMember = validateUserCheck(uid); + List topSchedules = scheduleRepository.findTop5ByMemberOrderByIdDesc(findMember); + List responses = new ArrayList<>(); + for (Schedule schedule : topSchedules) { + LatestCreateResponse response = scheduleMapper.toLatestCreateResponse(schedule, limit); + responses.add(response); + } + return responses; + } } diff --git a/backend/src/main/java/com/isp/backend/domain/scheduleDetail/entity/ScheduleDetail.java b/backend/src/main/java/com/isp/backend/domain/scheduleDetail/entity/ScheduleDetail.java index 10a9bcfd..2851dc96 100644 --- a/backend/src/main/java/com/isp/backend/domain/scheduleDetail/entity/ScheduleDetail.java +++ b/backend/src/main/java/com/isp/backend/domain/scheduleDetail/entity/ScheduleDetail.java @@ -4,11 +4,11 @@ import jakarta.persistence.*; import lombok.*; -@Getter @AllArgsConstructor @Entity @Setter @Builder +@Getter @NoArgsConstructor(access = AccessLevel.PROTECTED) @Table(name = "schedule_detail") public class ScheduleDetail { diff --git a/backend/src/main/java/com/isp/backend/domain/scheduleDetail/entity/ScheduleType.java b/backend/src/main/java/com/isp/backend/domain/scheduleDetail/entity/ScheduleType.java index 7bb0c77b..0bafc8dc 100644 --- a/backend/src/main/java/com/isp/backend/domain/scheduleDetail/entity/ScheduleType.java +++ b/backend/src/main/java/com/isp/backend/domain/scheduleDetail/entity/ScheduleType.java @@ -7,10 +7,8 @@ @AllArgsConstructor public enum ScheduleType { - AIRPLANE, // 비행기 - - HOTEL, // 호텧 - - PLACE, // 관광지 장소 + AIRPLANE, + HOTEL, + PLACE, };