-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* feat: 학교버스 시간표 관련 API 2개 구현 /courses/shuttle 학교버스 노선 조회 API 구현 /timetable/shuttle 학교버스 시간표 조회 API 구현 * feat: 학교버스 노선 조회 response 스웨거 명세 * chore: 메서드 이름 변경 * feat: 학교버스 노선 조회 DTO 분리 모델 객체와 DTO 분리 컨트롤러 메서드 이름 변경 * feat: 학기 종류에 따른 노선 반환하도록 변경 정규학기, 계절학기, 방학에 따라 다른 노선 반환 * chore: response 스웨거 명세 정보 수정 * feat: response 구조 변경 전체 노선 조회 response 구조 변경 * feat: response 순서대로 반환 지역 순서대로 반환 (천안, 서울, 청주) 노선 종류 순서대로 반환 (순환, 주중, 주말) * refactor: 리뷰 반영 uri 수정: /bus/timetable/shuttle/{id} ShuttleBusService 구현 dto 책임 분리 dto 이름 변경 * refactor: enum 도입 지역, 노선종류 속성 enum 대체 정렬 로직 개선 * refactor: dto 변환 책임 분리 from service * chore: detail 속성 추가 노선 정보에 detail 속성 추가 노선 지역 response 이름 수정
- Loading branch information
Showing
11 changed files
with
412 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
78 changes: 78 additions & 0 deletions
78
src/main/java/in/koreatech/koin/domain/bus/dto/ShuttleBusRoutesResponse.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
package in.koreatech.koin.domain.bus.dto; | ||
|
||
import static com.fasterxml.jackson.databind.PropertyNamingStrategies.SnakeCaseStrategy; | ||
|
||
import java.util.Comparator; | ||
import java.util.List; | ||
import java.util.stream.Collectors; | ||
|
||
import com.fasterxml.jackson.databind.annotation.JsonNaming; | ||
|
||
import in.koreatech.koin.domain.bus.model.enums.ShuttleBusRegion; | ||
import in.koreatech.koin.domain.bus.model.enums.ShuttleRouteType; | ||
import in.koreatech.koin.domain.bus.model.mongo.ShuttleBusRoute; | ||
import in.koreatech.koin.domain.version.dto.VersionMessageResponse; | ||
import io.swagger.v3.oas.annotations.media.Schema; | ||
|
||
@JsonNaming(SnakeCaseStrategy.class) | ||
@Schema(description = "셔틀버스 경로 응답") | ||
public record ShuttleBusRoutesResponse( | ||
@Schema(description = "노선 지역 분류 목록") List<RouteRegion> routeRegions, | ||
@Schema(description = "학기 정보") RouteSemester semesterInfo | ||
) { | ||
|
||
@JsonNaming(SnakeCaseStrategy.class) | ||
@Schema(description = "노선 지역 정보") | ||
public record RouteRegion( | ||
@Schema(description = "지역 이름", example = "천안") | ||
String region, | ||
|
||
@Schema(description = "해당 지역의 경로 목록") | ||
List<RouteName> routes | ||
) { | ||
} | ||
|
||
@JsonNaming(SnakeCaseStrategy.class) | ||
@Schema(description = "노선 세부 정보") | ||
public record RouteName( | ||
@Schema(description = "노선 ID", example = "675013f9465776d6265ddfdb") String id, | ||
@Schema(description = "노선 종류", example = "주말") String type, | ||
@Schema(description = "노선 이름", example = "대학원") String routeName, | ||
@Schema(description = "노선 부가 이름", example = "토요일") String subName | ||
) { | ||
} | ||
|
||
@JsonNaming(SnakeCaseStrategy.class) | ||
@Schema(description = "학기 정보") | ||
public record RouteSemester( | ||
@Schema(description = "학기 이름", example = "정규학기") String name, | ||
@Schema(description = "학기 시작 날짜", example = "2024-09-02") String from, | ||
@Schema(description = "학기 종료 날짜", example = "2024-12-20") String to | ||
) { | ||
} | ||
|
||
public static ShuttleBusRoutesResponse of(List<ShuttleBusRoute> shuttleBusRoutes, | ||
VersionMessageResponse versionMessageResponse) { | ||
List<RouteRegion> categories = mapCategories(shuttleBusRoutes); | ||
String[] term = versionMessageResponse.content().split("~"); | ||
RouteSemester routeSemester = new RouteSemester(versionMessageResponse.title(), term[0].trim(), term[1].trim()); | ||
return new ShuttleBusRoutesResponse(categories, routeSemester); | ||
} | ||
|
||
private static List<RouteRegion> mapCategories(List<ShuttleBusRoute> shuttleBusRoutes) { | ||
return shuttleBusRoutes.stream() | ||
.collect(Collectors.groupingBy(ShuttleBusRoute::getRegion)) | ||
.entrySet().stream() | ||
.map(entry -> new RouteRegion(entry.getKey().getLabel(), mapRouteNames(entry.getValue()))) | ||
.sorted(Comparator.comparingInt(o -> ShuttleBusRegion.getOrdinalByLabel(o.region()))) | ||
.toList(); | ||
} | ||
|
||
private static List<RouteName> mapRouteNames(List<ShuttleBusRoute> routes) { | ||
return routes.stream() | ||
.map(route -> new RouteName(route.getId(), route.getRouteType().getLabel(), route.getRouteName(), | ||
route.getSubName())) | ||
.sorted(Comparator.comparingInt(o -> ShuttleRouteType.getOrdinalByLabel(o.type()))) | ||
.toList(); | ||
} | ||
} |
78 changes: 78 additions & 0 deletions
78
src/main/java/in/koreatech/koin/domain/bus/dto/ShuttleBusTimetableResponse.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
package in.koreatech.koin.domain.bus.dto; | ||
|
||
import java.util.List; | ||
|
||
import com.fasterxml.jackson.databind.PropertyNamingStrategies.SnakeCaseStrategy; | ||
import com.fasterxml.jackson.databind.annotation.JsonNaming; | ||
|
||
import in.koreatech.koin.domain.bus.model.mongo.ShuttleBusRoute; | ||
import io.swagger.v3.oas.annotations.media.Schema; | ||
|
||
@JsonNaming(SnakeCaseStrategy.class) | ||
@Schema(description = "셔틀버스 노선 응답") | ||
public record ShuttleBusTimetableResponse( | ||
@Schema(description = "노선 ID", example = "675013f9465776d6265ddfdb") | ||
String id, | ||
|
||
@Schema(description = "지역 이름", example = "천안") | ||
String region, | ||
|
||
@Schema(description = "노선 타입", example = "순환") | ||
String routeType, | ||
|
||
@Schema(description = "노선 이름", example = "천안 셔틀") | ||
String routeName, | ||
|
||
@Schema(description = "노선 부가 이름", example = "null") | ||
String subName, | ||
|
||
@Schema(description = "정류장 정보 목록") | ||
List<NodeInfoResponse> nodeInfo, | ||
|
||
@Schema(description = "회차 정보 목록") | ||
List<RouteInfoResponse> routeInfo | ||
) { | ||
|
||
@JsonNaming(SnakeCaseStrategy.class) | ||
@Schema(description = "정류장 정보") | ||
public record NodeInfoResponse( | ||
@Schema(description = "정류장 이름", example = "캠퍼스 정문") | ||
String name, | ||
|
||
@Schema(description = "정류장 세부 정보", example = "정문 앞 정류장") | ||
String detail | ||
) { | ||
} | ||
|
||
@JsonNaming(SnakeCaseStrategy.class) | ||
@Schema(description = "노선 정보") | ||
public record RouteInfoResponse( | ||
@Schema(description = "노선 이름", example = "1회") | ||
String name, | ||
|
||
@Schema(description = "노선 세부 정보", example = "등교") | ||
String detail, | ||
|
||
@Schema(description = "도착 시간 목록", example = "[\"08:00\", \"09:00\"]") | ||
List<String> arrivalTime | ||
) { | ||
} | ||
|
||
public static ShuttleBusTimetableResponse from(ShuttleBusRoute shuttleBusRoute) { | ||
List<NodeInfoResponse> nodeInfoResponses = shuttleBusRoute.getNodeInfo().stream() | ||
.map(node -> new NodeInfoResponse(node.getName(), node.getDetail())) | ||
.toList(); | ||
List<RouteInfoResponse> routeInfoResponses = shuttleBusRoute.getRouteInfo().stream() | ||
.map(route -> new RouteInfoResponse(route.getName(), route.getDetail(), route.getArrivalTime())) | ||
.toList(); | ||
return new ShuttleBusTimetableResponse( | ||
shuttleBusRoute.getId(), | ||
shuttleBusRoute.getRegion().getLabel(), | ||
shuttleBusRoute.getRouteType().getLabel(), | ||
shuttleBusRoute.getRouteName(), | ||
shuttleBusRoute.getSubName(), | ||
nodeInfoResponses, | ||
routeInfoResponses | ||
); | ||
} | ||
} |
20 changes: 20 additions & 0 deletions
20
src/main/java/in/koreatech/koin/domain/bus/exception/BusIllegalRegionException.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package in.koreatech.koin.domain.bus.exception; | ||
|
||
import in.koreatech.koin.global.exception.KoinIllegalArgumentException; | ||
|
||
public class BusIllegalRegionException extends KoinIllegalArgumentException { | ||
|
||
private static final String DEFAULT_MESSAGE = "버스 지역 구분이 잘못되었습니다."; | ||
|
||
public BusIllegalRegionException(String message) { | ||
super(message); | ||
} | ||
|
||
public BusIllegalRegionException(String message, String detail) { | ||
super(message, detail); | ||
} | ||
|
||
public static BusIllegalStationException withDetail(String detail) { | ||
return new BusIllegalStationException(DEFAULT_MESSAGE, detail); | ||
} | ||
} |
20 changes: 20 additions & 0 deletions
20
src/main/java/in/koreatech/koin/domain/bus/exception/BusIllegalRouteTypeException.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
package in.koreatech.koin.domain.bus.exception; | ||
|
||
import in.koreatech.koin.global.exception.KoinIllegalArgumentException; | ||
|
||
public class BusIllegalRouteTypeException extends KoinIllegalArgumentException { | ||
|
||
private static final String DEFAULT_MESSAGE = "버스 노선 구분이 잘못되었습니다."; | ||
|
||
public BusIllegalRouteTypeException(String message) { | ||
super(message); | ||
} | ||
|
||
public BusIllegalRouteTypeException(String message, String detail) { | ||
super(message, detail); | ||
} | ||
|
||
public static BusIllegalStationException withDetail(String detail) { | ||
return new BusIllegalStationException(DEFAULT_MESSAGE, detail); | ||
} | ||
} |
26 changes: 26 additions & 0 deletions
26
src/main/java/in/koreatech/koin/domain/bus/model/enums/ShuttleBusRegion.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package in.koreatech.koin.domain.bus.model.enums; | ||
|
||
import in.koreatech.koin.domain.bus.exception.BusIllegalRegionException; | ||
import lombok.Getter; | ||
import lombok.RequiredArgsConstructor; | ||
|
||
@Getter | ||
@RequiredArgsConstructor | ||
public enum ShuttleBusRegion { | ||
CHEONAN_ASAN("천안·아산"), | ||
CHEONGJU("청주"), | ||
SEOUL("서울"), | ||
DAEJEON_SEJONG("대전·세종"), | ||
; | ||
|
||
private final String label; | ||
|
||
public static int getOrdinalByLabel(String label) { | ||
for (ShuttleBusRegion region : ShuttleBusRegion.values()) { | ||
if (region.getLabel().equals(label)) { | ||
return region.ordinal(); | ||
} | ||
} | ||
throw BusIllegalRegionException.withDetail("displayName: " + label); | ||
} | ||
} |
25 changes: 25 additions & 0 deletions
25
src/main/java/in/koreatech/koin/domain/bus/model/enums/ShuttleRouteType.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
package in.koreatech.koin.domain.bus.model.enums; | ||
|
||
import in.koreatech.koin.domain.bus.exception.BusIllegalRouteTypeException; | ||
import lombok.Getter; | ||
import lombok.RequiredArgsConstructor; | ||
|
||
@Getter | ||
@RequiredArgsConstructor | ||
public enum ShuttleRouteType { | ||
SHUTTLE("순환"), | ||
WEEKDAYS("주중"), | ||
WEEKEND("주말"), | ||
; | ||
|
||
private final String label; | ||
|
||
public static int getOrdinalByLabel(String label) { | ||
for (ShuttleRouteType shuttleRouteType : ShuttleRouteType.values()) { | ||
if (shuttleRouteType.getLabel().equals(label)) { | ||
return shuttleRouteType.ordinal(); | ||
} | ||
} | ||
throw BusIllegalRouteTypeException.withDetail("displayName: " + label); | ||
} | ||
} |
Oops, something went wrong.