Skip to content

Commit

Permalink
Merge pull request #214 from sopt-makers/yongtaek/#213
Browse files Browse the repository at this point in the history
[FEAT] 일정 리스트 조회 기능
  • Loading branch information
thguss authored Dec 30, 2023
2 parents 2ffe65f + 1926679 commit 1580274
Show file tree
Hide file tree
Showing 9 changed files with 260 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,10 @@ public enum ResponseMessage {
SUCCESS_CREATE_ALARM("알림 생성 성공"),
SUCCESS_GET_ALARMS("알림 리스트 조회 성공"),
SUCCESS_GET_ALARM("알림 상세 조회 성공"),
SUCCESS_DELETE_ALARM("알림 삭제 성공")
SUCCESS_DELETE_ALARM("알림 삭제 성공"),

/** schedule **/
SUCCESS_GET_SCHEDULES("일정 리스트 조회 성공")
;

private final String message;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package org.sopt.makers.operation.controller.app;

import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.val;
import org.sopt.makers.operation.common.ApiResponse;
import org.sopt.makers.operation.service.ScheduleService;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;

import static org.sopt.makers.operation.common.ApiResponse.success;
import static org.sopt.makers.operation.common.ResponseMessage.*;

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/v1/app/schedules")
public class AppScheduleController {
private final ScheduleService scheduleService;

@ApiOperation("일정 리스트 조회")
@GetMapping
public ResponseEntity<ApiResponse> getAlarms(
@RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime start,
@RequestParam @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) LocalDateTime end
) {
val response = scheduleService.getSchedules(start, end);
return ResponseEntity.ok(success(SUCCESS_GET_SCHEDULES.getMessage(), response));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package org.sopt.makers.operation.dto.schedule;

import lombok.*;
import org.sopt.makers.operation.entity.lecture.Attribute;
import org.sopt.makers.operation.entity.schedule.Schedule;

import java.time.LocalDate;
import java.time.format.TextStyle;
import java.util.List;
import java.util.Locale;
import java.util.Map;

public record SchedulesResponseDTO(
List<DateVO> dates
) {
public static SchedulesResponseDTO of(Map<LocalDate, List<Schedule>> scheduleMap) {
return new SchedulesResponseDTO(
scheduleMap.keySet().stream().sorted()
.map(key -> DateVO.of(key, scheduleMap.get(key)))
.toList()
);
}

@Builder
record DateVO(
String date,
String dayOfWeek,
List<ScheduleVO> schedules
) {
static DateVO of(LocalDate date, List<Schedule> schedules) {
return DateVO.builder()
.date(date.toString())
.dayOfWeek(date.getDayOfWeek().getDisplayName(TextStyle.SHORT, Locale.KOREAN))
.schedules(schedules.stream().map(ScheduleVO::of).toList())
.build();
}
}

@Builder
record ScheduleVO(
Long scheduleId,
String startDate,
String endDate,
Attribute attribute,
String title
) {
static ScheduleVO of(Schedule schedule) {
return ScheduleVO.builder()
.scheduleId(schedule.getId())
.startDate(schedule.getStartDate().toString())
.endDate(schedule.getEndDate().toString())
.attribute(schedule.getAttribute())
.title(schedule.getTitle())
.build();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package org.sopt.makers.operation.entity.schedule;

import lombok.Getter;
import lombok.NoArgsConstructor;
import org.sopt.makers.operation.entity.BaseEntity;
import org.sopt.makers.operation.entity.lecture.Attribute;

import javax.persistence.*;
import java.time.LocalDateTime;

import static javax.persistence.EnumType.STRING;
import static javax.persistence.GenerationType.IDENTITY;

@Entity
@NoArgsConstructor
@Getter
public class Schedule extends BaseEntity {
@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name = "schedule_id")
private Long id;

private LocalDateTime startDate;

private LocalDateTime endDate;

@Column(nullable = false)
@Enumerated(value = STRING)
private Attribute attribute;

private String title;

private String location;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package org.sopt.makers.operation.repository.schedule;

import org.sopt.makers.operation.entity.schedule.Schedule;

import java.time.LocalDateTime;
import java.util.List;

public interface ScheduleCustomRepository {
List<Schedule> findBetweenStartAndEnd(LocalDateTime start, LocalDateTime end);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package org.sopt.makers.operation.repository.schedule;

import org.sopt.makers.operation.entity.Member;
import org.springframework.data.jpa.repository.JpaRepository;

public interface ScheduleRepository extends JpaRepository<Member, Long>, ScheduleCustomRepository {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package org.sopt.makers.operation.repository.schedule;

import com.querydsl.core.types.dsl.BooleanExpression;
import com.querydsl.jpa.impl.JPAQueryFactory;

import lombok.RequiredArgsConstructor;

import org.sopt.makers.operation.entity.schedule.Schedule;
import org.springframework.stereotype.Repository;

import java.time.LocalDateTime;
import java.util.List;

import static org.sopt.makers.operation.entity.schedule.QSchedule.schedule;

@Repository
@RequiredArgsConstructor
public class ScheduleRepositoryImpl implements ScheduleCustomRepository {

private final JPAQueryFactory queryFactory;

@Override
public List<Schedule> findBetweenStartAndEnd(LocalDateTime start, LocalDateTime end) {
return queryFactory
.select(schedule)
.from(schedule)
.where(
schedule.startDate.between(start, end)
.or(schedule.endDate.between(start, end))
)
.orderBy(schedule.startDate.asc())
.fetch();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package org.sopt.makers.operation.service;

import org.sopt.makers.operation.dto.schedule.SchedulesResponseDTO;

import java.time.LocalDateTime;

public interface ScheduleService {
SchedulesResponseDTO getSchedules(LocalDateTime start, LocalDateTime end);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package org.sopt.makers.operation.service;

import lombok.RequiredArgsConstructor;
import lombok.val;
import org.sopt.makers.operation.dto.schedule.SchedulesResponseDTO;
import org.sopt.makers.operation.entity.schedule.Schedule;
import org.sopt.makers.operation.repository.schedule.ScheduleRepository;
import org.springframework.stereotype.Service;

import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.LongStream;

@Service
@RequiredArgsConstructor
public class ScheduleServiceImpl implements ScheduleService {
private final ScheduleRepository scheduleRepository;

@Override
public SchedulesResponseDTO getSchedules(LocalDateTime start, LocalDateTime end) {
val schedules = scheduleRepository.findBetweenStartAndEnd(start, end);
val scheduleMap = classifiedByDate(schedules, start, end);
return SchedulesResponseDTO.of(scheduleMap);
}

private Map<LocalDate, List<Schedule>> classifiedByDate(List<Schedule> schedules, LocalDateTime startAt, LocalDateTime endAt) {
val scheduleMap = initScheduleMap(startAt, endAt);
schedules.forEach(schedule -> putScheduleMap(scheduleMap, schedule));
return scheduleMap;
}

private Map<LocalDate, List<Schedule>> initScheduleMap(LocalDateTime startAt, LocalDateTime endAt) {
//TODO: 클라이언트 개발 시간 리소스 절약을 위해 해당 메소드 활용, 가능한 일정이 존재하는 날짜만 key로 가지는 HashMap로 변경 요망
val duration = Duration.between(startAt, endAt).toDays() + 1;
validDuration(duration);
return LongStream.range(0, duration)
.mapToObj(startAt::plusDays)
.collect(Collectors.toMap(
LocalDateTime::toLocalDate,
date -> new ArrayList<>()));
}

private void validDuration(long duration) {
//TODO: 추후 응답 값 형식 변경 후 삭제될 수 있는 메소드
if (duration > 50) {
throw new IllegalStateException("조회할 날짜 기간은 50일을 넘길 수 없습니다.");
}
}

private void putScheduleMap(Map<LocalDate, List<Schedule>> scheduleMap, Schedule schedule) {
val duration = ChronoUnit.DAYS.between(schedule.getStartDate(), schedule.getEndDate());
scheduleMap.computeIfAbsent(schedule.getStartDate().toLocalDate(), k -> new ArrayList<>()).add(schedule);
if (duration >= 1) {
scheduleMap.computeIfAbsent(schedule.getEndDate().toLocalDate(), k -> new ArrayList<>()).add(schedule);
if (duration >= 2) {
putScheduleMapBetween(scheduleMap, schedule, (int)duration);
}
}
}

private void putScheduleMapBetween(Map<LocalDate, List<Schedule>> scheduleMap, Schedule schedule, int duration) {
for (int i = 1; i < duration; i++) {
val date = schedule.getStartDate().plusDays(i).toLocalDate();
scheduleMap.computeIfAbsent(date, k -> new ArrayList<>()).add(schedule);
}
}
}

0 comments on commit 1580274

Please sign in to comment.