Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FEAT] 지하철 시간표 관련 코드 구현 #88

Merged
merged 21 commits into from
Aug 20, 2024
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
2d6c324
feature: SubwayStation 관련 기능 추가
ss0ngcode Aug 10, 2024
8423257
feature: SubwayConfusion 관련 기능 추가
ss0ngcode Aug 10, 2024
127e64c
feature: TimeSlot 변경시 누락 수정본
ss0ngcode Aug 10, 2024
7c03c4a
feature: 엔티티 및 request, response 변경
ss0ngcode Aug 12, 2024
67a0bd3
Merge branch 'develop' into feature/#59
ss0ngcode Aug 13, 2024
0f94345
git merge 충돌 해결
ss0ngcode Aug 16, 2024
f8988b7
Merge branch 'develop' into feature/#59
ss0ngcode Aug 16, 2024
ca90c0c
feature: Enum 전달 방식 변경에 따른 코드수정 및 테스트 코드 작성
ss0ngcode Aug 16, 2024
96dff41
feature: 지하철 역 관련 리팩토링
ss0ngcode Aug 16, 2024
6c41dab
feature: PR 리뷰내용 반영
ss0ngcode Aug 16, 2024
a61a41c
Merge branch 'develop' into feature/#59
ss0ngcode Aug 17, 2024
65a8c5d
feature: InvalidLineEnumException 제거
ss0ngcode Aug 17, 2024
94ff006
Merge branch 'develop' into feature/#59
ss0ngcode Aug 17, 2024
a77bcd8
feature: 지하철 혼잡도 관련 리팩토링
ss0ngcode Aug 17, 2024
7ecf3ed
feature: 지하철 혼잡도 response 필드 추가 및 일부 수정
ss0ngcode Aug 18, 2024
37ce3dd
Merge branch 'develop' into feature/#59
ss0ngcode Aug 18, 2024
be81cda
feature: SubwayTimetable 관련 기능 추가
ss0ngcode Aug 19, 2024
f8a44c2
Merge branch 'develop' into feature/#59
ss0ngcode Aug 19, 2024
49023c8
feature: PR 리뷰 수정사항 반영
ss0ngcode Aug 19, 2024
4c97313
feature: PR 리뷰내용 (isExisted 메서드 삭제) 반영
ss0ngcode Aug 20, 2024
0805f20
Merge branch 'develop' into feature/#59
ss0ngcode Aug 20, 2024
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package com.talkka.server.subway.controller;

import java.time.format.DateTimeParseException;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.talkka.server.common.exception.InvalidTypeException;
import com.talkka.server.subway.exception.StationNotFoundException;
import com.talkka.server.subway.exception.TimetableNotFoundException;
import com.talkka.server.subway.service.SubwayTimetableService;

import lombok.RequiredArgsConstructor;

@RestController
@RequiredArgsConstructor
@RequestMapping("/api/subway/timetable")
public class SubwayTimetableController {

private final SubwayTimetableService timetableService;

@GetMapping("/{stationId}")
public ResponseEntity<?> getTimetable(
@PathVariable Long stationId,
@RequestParam String dayTypeCode,
@RequestParam String updownCode,
@RequestParam String time
) {
ResponseEntity<?> response;
try {
response = ResponseEntity.ok(
timetableService.getTimetable(stationId, dayTypeCode, updownCode, time));
} catch (DateTimeParseException exception) {
response = ResponseEntity.badRequest().body("해당 시간 형식은 올바르지 않습니다.");
} catch (StationNotFoundException | InvalidTypeException exception) {
response = ResponseEntity.badRequest().body(exception.getMessage());
} catch (TimetableNotFoundException exception) {
response = ResponseEntity.status(HttpStatus.NOT_FOUND).body(exception.getMessage());
}
return response;
}

// 첫차 = 5:00:00, 막차 = 0:30:30 기준으로 널널하게 잡음
@GetMapping("/{stationId}/list")
public ResponseEntity<?> getTimetableList(
@PathVariable Long stationId,
@RequestParam String dayTypeCode,
@RequestParam String updownCode,
@RequestParam(required = false, defaultValue = "4:00:00") String startTime,
@RequestParam(required = false, defaultValue = "1:00:00") String endTime
ss0ngcode marked this conversation as resolved.
Show resolved Hide resolved
) {
ResponseEntity<?> response;
try {
response = ResponseEntity.ok(
timetableService.getTimetableList(stationId, dayTypeCode, updownCode, startTime, endTime));
} catch (DateTimeParseException exception) {
response = ResponseEntity.badRequest().body("해당 시간 형식은 올바르지 않습니다.");
} catch (StationNotFoundException | InvalidTypeException exception) {
response = ResponseEntity.badRequest().body(exception.getMessage());
}
return response;
}
}
Original file line number Diff line number Diff line change
@@ -1,8 +1,23 @@
package com.talkka.server.subway.dao;

import org.hibernate.type.descriptor.converter.spi.JpaAttributeConverter;
import java.time.LocalTime;
import java.util.List;
import java.util.Optional;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import com.talkka.server.subway.enums.DayType;
import com.talkka.server.subway.enums.Updown;

@Repository
public interface SubwayTimetableRepository extends JpaAttributeConverter<SubwayTimetableEntity, Long> {
public interface SubwayTimetableRepository extends JpaRepository<SubwayTimetableEntity, Long> {

Optional<SubwayTimetableEntity> findBySubwayStationIdAndDayTypeAndUpdownAndArrivalTime(
Long stationId, DayType dayType, Updown updown, LocalTime time
);

List<SubwayTimetableEntity> findBySubwayStationIdAndDayTypeAndUpdownAndArrivalTimeBetween(
Long stationId, DayType dayType, Updown updown, LocalTime startTime, LocalTime endTime
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package com.talkka.server.subway.dto;

import java.time.LocalTime;

import com.talkka.server.subway.dao.SubwayTimetableEntity;
import com.talkka.server.subway.enums.DayType;
import com.talkka.server.subway.enums.Express;
import com.talkka.server.subway.enums.Line;
import com.talkka.server.subway.enums.Updown;

import lombok.Builder;

@Builder
public record SubwayTimetableRespDto(
Long stationId,
ss0ngcode marked this conversation as resolved.
Show resolved Hide resolved
String stationName,
Line line,
DayType dayType,
Updown updown,
Express express,
LocalTime arrivalTime,
String startStationName,
String endStationName
) {
public static SubwayTimetableRespDto of(SubwayTimetableEntity subwayTimetableEntity) {
return new SubwayTimetableRespDto(
subwayTimetableEntity.getSubwayStation().getId(),
subwayTimetableEntity.getStationName(),
subwayTimetableEntity.getLine(),
subwayTimetableEntity.getDayType(),
subwayTimetableEntity.getUpdown(),
subwayTimetableEntity.getExpress(),
subwayTimetableEntity.getArrivalTime(),
subwayTimetableEntity.getStartStationName(),
subwayTimetableEntity.getEndStationName());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package com.talkka.server.subway.exception;

public class TimetableNotFoundException extends RuntimeException {
private static final String MESSAGE = "조회 가능한 시간표 정보가 없습니다.";

public TimetableNotFoundException() {
super(MESSAGE);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package com.talkka.server.subway.service;

import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.List;

import org.springframework.stereotype.Service;

import com.talkka.server.common.exception.InvalidTypeException;
import com.talkka.server.subway.dao.SubwayStationRepository;
import com.talkka.server.subway.dao.SubwayTimetableEntity;
import com.talkka.server.subway.dao.SubwayTimetableRepository;
import com.talkka.server.subway.dto.SubwayTimetableRespDto;
import com.talkka.server.subway.enums.DayType;
import com.talkka.server.subway.enums.Updown;
import com.talkka.server.subway.exception.StationNotFoundException;
import com.talkka.server.subway.exception.TimetableNotFoundException;

import lombok.RequiredArgsConstructor;

@Service
@RequiredArgsConstructor
public class SubwayTimetableService {

private final SubwayTimetableRepository timetableRepository;
private final SubwayStationRepository stationRepository;

public SubwayTimetableRespDto getTimetable(
Long stationId, String dayTypeCode, String updownCode, String time
) throws DateTimeParseException, StationNotFoundException, TimetableNotFoundException, InvalidTypeException {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("H:mm:ss");
LocalTime parseTime = LocalTime.parse(time, formatter);

isExisted(stationId);

SubwayTimetableEntity entity = timetableRepository.findBySubwayStationIdAndDayTypeAndUpdownAndArrivalTime(
stationId, DayType.valueOfEnumString(dayTypeCode), Updown.valueOfEnumString(updownCode), parseTime
).orElseThrow(TimetableNotFoundException::new);

return SubwayTimetableRespDto.of(entity);
}

public List<SubwayTimetableRespDto> getTimetableList(
Long stationId, String dayTypeCode, String updownCode, String startTime, String endTime
) throws DateTimeParseException, StationNotFoundException, InvalidTypeException {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("H:mm:ss");
LocalTime start = LocalTime.parse(startTime, formatter);
LocalTime end = LocalTime.parse(endTime, formatter);

isExisted(stationId);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is... method 의 경우 boolean 반환을 하는 것이 적합합니다. 그렇게 될 경우 throw의 책임은 상위 메소드인 getTimeTableList() 에서 가지게됩니다.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

만약 throw를 해당 부분에서 원한다면 check... 와 같은 부분으로 변경하는 것이 조금 더 적합해보이고, 더 나아가서는 해당 Validator를 별도로 생성하는 것이 좋지 않을까요?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NOTE: private method 의 경우 테스트가 불가하기 때문... 만약에 여기서만 사용한다면, existsById 를 그냥 호출하고 체크하는 것이 더 나을 것 같음.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

저도 작성하면서 뭔가 걸리는게 있었는데 이거였군요...
isExisted 메서드 제거하고 existsById를 바로 호출하는 것으로 변경했습니다!


List<SubwayTimetableEntity> entityList = timetableRepository.findBySubwayStationIdAndDayTypeAndUpdownAndArrivalTimeBetween(
stationId, DayType.valueOfEnumString(dayTypeCode), Updown.valueOfEnumString(updownCode), start, end
);

return entityList.stream()
.map(SubwayTimetableRespDto::of)
.toList();
}

private void isExisted(Long stationId) {
if (!stationRepository.existsById(stationId)) {
throw new StationNotFoundException(stationId);
}
}
}
Loading
Loading