From c0f179fa649ec75db99dd5ae0110c7557b3463ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EB=8F=99=ED=9B=88?= <2dh2@naver.com> Date: Tue, 18 Nov 2025 11:50:32 +0900 Subject: [PATCH 01/21] =?UTF-8?q?chore:=20=EA=B0=9C=ED=96=89=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bus/shuttle/dto/request/AdminShuttleBusUpdateRequest.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/in/koreatech/koin/admin/bus/shuttle/dto/request/AdminShuttleBusUpdateRequest.java b/src/main/java/in/koreatech/koin/admin/bus/shuttle/dto/request/AdminShuttleBusUpdateRequest.java index f97d91e26..a264193af 100644 --- a/src/main/java/in/koreatech/koin/admin/bus/shuttle/dto/request/AdminShuttleBusUpdateRequest.java +++ b/src/main/java/in/koreatech/koin/admin/bus/shuttle/dto/request/AdminShuttleBusUpdateRequest.java @@ -57,7 +57,9 @@ public List toRouteInfoEntity() { return routeInfo.stream() .map(innerRouteInfoRequest -> InnerRouteInfoRequest.toEntity( - innerRouteInfoRequest.name, innerRouteInfoRequest.detail, innerRouteInfoRequest.arrivalTime + innerRouteInfoRequest.name, + innerRouteInfoRequest.detail, + innerRouteInfoRequest.arrivalTime ) ).toList(); } From d6d84a40f33ce0faf6e8ed7e309622812427ef67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EB=8F=99=ED=9B=88?= <2dh2@naver.com> Date: Tue, 18 Nov 2025 11:53:45 +0900 Subject: [PATCH 02/21] =?UTF-8?q?refactor:=20=EC=9D=B4=EB=84=88=20?= =?UTF-8?q?=ED=81=B4=EB=9E=98=EC=8A=A4=20=EB=AA=85=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AdminShuttleBusTimetableResponse.java | 22 ++++++++++--------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/src/main/java/in/koreatech/koin/admin/bus/shuttle/dto/response/AdminShuttleBusTimetableResponse.java b/src/main/java/in/koreatech/koin/admin/bus/shuttle/dto/response/AdminShuttleBusTimetableResponse.java index 1acc96c9a..96cef4d62 100644 --- a/src/main/java/in/koreatech/koin/admin/bus/shuttle/dto/response/AdminShuttleBusTimetableResponse.java +++ b/src/main/java/in/koreatech/koin/admin/bus/shuttle/dto/response/AdminShuttleBusTimetableResponse.java @@ -28,22 +28,24 @@ public record AdminShuttleBusTimetableResponse( String subName, @Schema(description = "정류소 정보 리스트") - List nodeInfo, + List nodeInfo, @Schema(description = "회차별 도착 시간 및 운행 요일 정보 리스트") - List routeInfo + List routeInfo ) { public static AdminShuttleBusTimetableResponse from(ShuttleBusTimetable table) { - List nodeInfos = table.getNodeInfos().stream() - .map(n -> new AdminShuttleBusTimetableResponse.NodeInfo( + List nodeInfo = table.getNodeInfos() + .stream() + .map(n -> new InnerNodeInfoResponse( n.getName(), n.getDetail() )) .toList(); - List routeInfos = table.getRouteInfos().stream() - .map(r -> new AdminShuttleBusTimetableResponse.RouteInfo( + List routeInfo = table.getRouteInfos() + .stream() + .map(r -> new InnerRouteInfoResponse( r.getName(), r.getDetail(), r.getArrivalTime() @@ -51,9 +53,9 @@ public static AdminShuttleBusTimetableResponse from(ShuttleBusTimetable table) { .toList(); return AdminShuttleBusTimetableResponse.builder() - .nodeInfo(nodeInfos) + .nodeInfo(nodeInfo) .region(table.getRegion()) - .routeInfo(routeInfos) + .routeInfo(routeInfo) .routeName(table.getRouteName()) .routeType(table.getRouteType()) .subName(table.getSubName()) @@ -61,7 +63,7 @@ public static AdminShuttleBusTimetableResponse from(ShuttleBusTimetable table) { } @JsonNaming(SnakeCaseStrategy.class) - public record NodeInfo( + public record InnerNodeInfoResponse( @Schema(description = "정류소 이름", example = "한기대", requiredMode = REQUIRED) String name, @@ -71,7 +73,7 @@ public record NodeInfo( } @JsonNaming(SnakeCaseStrategy.class) - public record RouteInfo( + public record InnerRouteInfoResponse( @Schema(description = "회차 이름", example = "1회", requiredMode = REQUIRED) String name, From 19212ba93da180fbc32809eb8baada2f9e3816f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EB=8F=99=ED=9B=88?= <2dh2@naver.com> Date: Tue, 18 Nov 2025 11:55:30 +0900 Subject: [PATCH 03/21] =?UTF-8?q?docs:=20=EC=8A=A4=EC=9B=A8=EA=B1=B0=20?= =?UTF-8?q?=EB=AA=85=EC=84=B8=20=EC=98=88=EC=8B=9C=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dto/response/AdminShuttleBusTimetableResponse.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/in/koreatech/koin/admin/bus/shuttle/dto/response/AdminShuttleBusTimetableResponse.java b/src/main/java/in/koreatech/koin/admin/bus/shuttle/dto/response/AdminShuttleBusTimetableResponse.java index 96cef4d62..904fb6f42 100644 --- a/src/main/java/in/koreatech/koin/admin/bus/shuttle/dto/response/AdminShuttleBusTimetableResponse.java +++ b/src/main/java/in/koreatech/koin/admin/bus/shuttle/dto/response/AdminShuttleBusTimetableResponse.java @@ -80,7 +80,11 @@ public record InnerRouteInfoResponse( @Schema(description = "회차 세부 이름", example = "(청주역→본교)", requiredMode = NOT_REQUIRED) String detail, - @Schema(description = "각 정류소 별 도착 시간 (미정차인 경우 null)", requiredMode = REQUIRED) + @Schema( + description = "각 정류소 별 도착 시간 (미정차인 경우 null)", + example = "[\"08:00\", \"09:00\"]", + requiredMode = REQUIRED + ) List arrivalTime ) { } From d95df9f09ad7a4f3a248c33200c1ab6a93679976 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EB=8F=99=ED=9B=88?= <2dh2@naver.com> Date: Tue, 18 Nov 2025 15:13:42 +0900 Subject: [PATCH 04/21] =?UTF-8?q?refactor:=20=EC=9D=B4=EB=A6=84,=20?= =?UTF-8?q?=EC=84=B8=EB=B6=80=20=EC=9D=B4=EB=A6=84=20=ED=8C=8C=EC=8B=B1=20?= =?UTF-8?q?=EB=A1=9C=EC=A7=81=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bus/shuttle/util/ExcelStringUtil.java | 21 --------------- .../admin/bus/shuttle/util/NameParser.java | 27 +++++++++++++++++++ 2 files changed, 27 insertions(+), 21 deletions(-) create mode 100644 src/main/java/in/koreatech/koin/admin/bus/shuttle/util/NameParser.java diff --git a/src/main/java/in/koreatech/koin/admin/bus/shuttle/util/ExcelStringUtil.java b/src/main/java/in/koreatech/koin/admin/bus/shuttle/util/ExcelStringUtil.java index 6d802af34..0a73c95cd 100644 --- a/src/main/java/in/koreatech/koin/admin/bus/shuttle/util/ExcelStringUtil.java +++ b/src/main/java/in/koreatech/koin/admin/bus/shuttle/util/ExcelStringUtil.java @@ -12,25 +12,4 @@ public static String getCellValueToString(Cell cell) { return value != null ? value.trim() : ""; } - - public static String extractDetailFromBrackets(String str) { - int openIdx = str.indexOf('('); - int closeIdx = str.indexOf(')'); - - if (openIdx != -1 && closeIdx != -1 && closeIdx > openIdx) { - return str.substring(openIdx + 1, closeIdx).trim(); - } - - return null; - } - - public static String extractNameWithoutBrackets(String str) { - int openIdx = str.indexOf('('); - - if (openIdx != -1) { - return str.substring(0, openIdx).trim(); - } - - return str.trim(); - } } diff --git a/src/main/java/in/koreatech/koin/admin/bus/shuttle/util/NameParser.java b/src/main/java/in/koreatech/koin/admin/bus/shuttle/util/NameParser.java new file mode 100644 index 000000000..d6651f8e6 --- /dev/null +++ b/src/main/java/in/koreatech/koin/admin/bus/shuttle/util/NameParser.java @@ -0,0 +1,27 @@ +package in.koreatech.koin.admin.bus.shuttle.util; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class NameParser { + + private static final Pattern PATTERN = Pattern.compile("^(.*?)\\s*(?:\\((.*?)\\))?$"); + + public static ParsedName parse(String raw) { + if (raw == null || raw.trim().isEmpty()) { + return new ParsedName("", null); + } + + Matcher m = PATTERN.matcher(raw.trim()); + + if (m.matches()) { + String name = m.group(1).trim(); + String detail = m.group(2) != null ? m.group(2).trim() : null; + return new ParsedName(name, detail); + } + + return new ParsedName(raw.trim(), null); + } + + public record ParsedName(String name, String detail) {} +} From 0422d99e5a90001f7f5281a7598b6320672d5344 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EB=8F=99=ED=9B=88?= <2dh2@naver.com> Date: Tue, 18 Nov 2025 15:14:22 +0900 Subject: [PATCH 05/21] =?UTF-8?q?refactor:=20=EB=AC=B8=EC=9E=90=EC=97=B4?= =?UTF-8?q?=20=EB=B6=84=EB=A6=AC=20=EB=A1=9C=EC=A7=81=20=EB=AA=A8=EB=8D=B8?= =?UTF-8?q?=EC=97=90=EC=84=9C=20=ED=98=B8=EC=B6=9C=ED=95=98=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../koreatech/koin/admin/bus/shuttle/model/RouteName.java | 7 +++++-- .../koin/admin/bus/shuttle/model/ShuttleBusTimetable.java | 8 +++++--- .../koreatech/koin/admin/bus/shuttle/model/SubName.java | 7 +++++-- .../admin/bus/shuttle/util/ShuttleBusMetaDataParser.java | 8 ++------ .../admin/bus/shuttle/util/ShuttleBusNodeInfoParser.java | 5 +---- 5 files changed, 18 insertions(+), 17 deletions(-) diff --git a/src/main/java/in/koreatech/koin/admin/bus/shuttle/model/RouteName.java b/src/main/java/in/koreatech/koin/admin/bus/shuttle/model/RouteName.java index 298c78cc6..e4de826fd 100644 --- a/src/main/java/in/koreatech/koin/admin/bus/shuttle/model/RouteName.java +++ b/src/main/java/in/koreatech/koin/admin/bus/shuttle/model/RouteName.java @@ -1,5 +1,6 @@ package in.koreatech.koin.admin.bus.shuttle.model; +import in.koreatech.koin.admin.bus.shuttle.util.NameParser; import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.Getter; @@ -10,7 +11,9 @@ public class RouteName { private String name; - public static RouteName of(String name) { - return new RouteName(name); + public static RouteName of(String sheetName) { + NameParser.ParsedName parsedName = NameParser.parse(sheetName); + + return new RouteName(parsedName.name()); } } diff --git a/src/main/java/in/koreatech/koin/admin/bus/shuttle/model/ShuttleBusTimetable.java b/src/main/java/in/koreatech/koin/admin/bus/shuttle/model/ShuttleBusTimetable.java index 8706ac6d3..78169e484 100644 --- a/src/main/java/in/koreatech/koin/admin/bus/shuttle/model/ShuttleBusTimetable.java +++ b/src/main/java/in/koreatech/koin/admin/bus/shuttle/model/ShuttleBusTimetable.java @@ -3,6 +3,7 @@ import java.util.List; import in.koreatech.koin.admin.bus.shuttle.enums.RunningDays; +import in.koreatech.koin.admin.bus.shuttle.util.NameParser; import in.koreatech.koin.domain.bus.enums.ShuttleBusRegion; import lombok.AccessLevel; import lombok.AllArgsConstructor; @@ -30,10 +31,11 @@ public static class NodeInfo { private String name; private String detail; - public static NodeInfo of(String name, String detail) { - return new NodeInfo(name, detail); - } + public static NodeInfo of(String nameWithDetail) { + NameParser.ParsedName parsedName = NameParser.parse(nameWithDetail); + return new NodeInfo(parsedName.name(), parsedName.detail()); + } } @AllArgsConstructor(access = AccessLevel.PROTECTED) diff --git a/src/main/java/in/koreatech/koin/admin/bus/shuttle/model/SubName.java b/src/main/java/in/koreatech/koin/admin/bus/shuttle/model/SubName.java index d204569fc..c210467e2 100644 --- a/src/main/java/in/koreatech/koin/admin/bus/shuttle/model/SubName.java +++ b/src/main/java/in/koreatech/koin/admin/bus/shuttle/model/SubName.java @@ -1,5 +1,6 @@ package in.koreatech.koin.admin.bus.shuttle.model; +import in.koreatech.koin.admin.bus.shuttle.util.NameParser; import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.Getter; @@ -10,7 +11,9 @@ public class SubName { private String name; - public static SubName of(String name) { - return new SubName(name); + public static SubName of(String sheetName) { + NameParser.ParsedName parsedName = NameParser.parse(sheetName); + + return new SubName(parsedName.detail()); } } diff --git a/src/main/java/in/koreatech/koin/admin/bus/shuttle/util/ShuttleBusMetaDataParser.java b/src/main/java/in/koreatech/koin/admin/bus/shuttle/util/ShuttleBusMetaDataParser.java index d1b74d077..a17ed4906 100644 --- a/src/main/java/in/koreatech/koin/admin/bus/shuttle/util/ShuttleBusMetaDataParser.java +++ b/src/main/java/in/koreatech/koin/admin/bus/shuttle/util/ShuttleBusMetaDataParser.java @@ -30,17 +30,13 @@ public static RouteType getRouteTypeFromSheet(Sheet sheet) { public static RouteName getRouteNameFromSheet(Sheet sheet) { String sheetName = sheet.getSheetName(); - String routeName = ExcelStringUtil.extractNameWithoutBrackets(sheetName); - - return RouteName.of(routeName); + return RouteName.of(sheetName); } public static SubName getSubNameFromSheet(Sheet sheet) { String sheetName = sheet.getSheetName(); - String subName = ExcelStringUtil.extractDetailFromBrackets(sheetName); - - return SubName.of(subName); + return SubName.of(sheetName); } private static String getCellValue(Sheet sheet, int rowIndex, int colIndex) { diff --git a/src/main/java/in/koreatech/koin/admin/bus/shuttle/util/ShuttleBusNodeInfoParser.java b/src/main/java/in/koreatech/koin/admin/bus/shuttle/util/ShuttleBusNodeInfoParser.java index 6b2abd0d7..1e4481bd7 100644 --- a/src/main/java/in/koreatech/koin/admin/bus/shuttle/util/ShuttleBusNodeInfoParser.java +++ b/src/main/java/in/koreatech/koin/admin/bus/shuttle/util/ShuttleBusNodeInfoParser.java @@ -34,10 +34,7 @@ public static List getNodeInfos(Sheet sheet) { nameWithDetail = nameWithDetail.trim(); - String name = ExcelStringUtil.extractNameWithoutBrackets(nameWithDetail); - String detail = ExcelStringUtil.extractDetailFromBrackets(nameWithDetail); - - nodeInfos.add(NodeInfo.of(name, detail)); + nodeInfos.add(NodeInfo.of(nameWithDetail)); } return nodeInfos; From 695adad8dbf4f2ee9452fd1196b1c15a9de873c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EB=8F=99=ED=9B=88?= <2dh2@naver.com> Date: Tue, 18 Nov 2025 15:16:00 +0900 Subject: [PATCH 06/21] =?UTF-8?q?refactor:=20=ED=8C=8C=EC=84=9C=20?= =?UTF-8?q?=ED=8C=A8=ED=82=A4=EC=A7=80=20=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../in/koreatech/koin/admin/bus/shuttle/model/RouteName.java | 2 +- .../koin/admin/bus/shuttle/model/ShuttleBusTimetable.java | 2 +- .../java/in/koreatech/koin/admin/bus/shuttle/model/SubName.java | 2 +- .../koin/admin/bus/shuttle/{util => parser}/NameParser.java | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) rename src/main/java/in/koreatech/koin/admin/bus/shuttle/{util => parser}/NameParser.java (93%) diff --git a/src/main/java/in/koreatech/koin/admin/bus/shuttle/model/RouteName.java b/src/main/java/in/koreatech/koin/admin/bus/shuttle/model/RouteName.java index e4de826fd..f4439247b 100644 --- a/src/main/java/in/koreatech/koin/admin/bus/shuttle/model/RouteName.java +++ b/src/main/java/in/koreatech/koin/admin/bus/shuttle/model/RouteName.java @@ -1,6 +1,6 @@ package in.koreatech.koin.admin.bus.shuttle.model; -import in.koreatech.koin.admin.bus.shuttle.util.NameParser; +import in.koreatech.koin.admin.bus.shuttle.parser.NameParser; import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.Getter; diff --git a/src/main/java/in/koreatech/koin/admin/bus/shuttle/model/ShuttleBusTimetable.java b/src/main/java/in/koreatech/koin/admin/bus/shuttle/model/ShuttleBusTimetable.java index 78169e484..293105db5 100644 --- a/src/main/java/in/koreatech/koin/admin/bus/shuttle/model/ShuttleBusTimetable.java +++ b/src/main/java/in/koreatech/koin/admin/bus/shuttle/model/ShuttleBusTimetable.java @@ -3,7 +3,7 @@ import java.util.List; import in.koreatech.koin.admin.bus.shuttle.enums.RunningDays; -import in.koreatech.koin.admin.bus.shuttle.util.NameParser; +import in.koreatech.koin.admin.bus.shuttle.parser.NameParser; import in.koreatech.koin.domain.bus.enums.ShuttleBusRegion; import lombok.AccessLevel; import lombok.AllArgsConstructor; diff --git a/src/main/java/in/koreatech/koin/admin/bus/shuttle/model/SubName.java b/src/main/java/in/koreatech/koin/admin/bus/shuttle/model/SubName.java index c210467e2..af593df1e 100644 --- a/src/main/java/in/koreatech/koin/admin/bus/shuttle/model/SubName.java +++ b/src/main/java/in/koreatech/koin/admin/bus/shuttle/model/SubName.java @@ -1,6 +1,6 @@ package in.koreatech.koin.admin.bus.shuttle.model; -import in.koreatech.koin.admin.bus.shuttle.util.NameParser; +import in.koreatech.koin.admin.bus.shuttle.parser.NameParser; import lombok.AccessLevel; import lombok.AllArgsConstructor; import lombok.Getter; diff --git a/src/main/java/in/koreatech/koin/admin/bus/shuttle/util/NameParser.java b/src/main/java/in/koreatech/koin/admin/bus/shuttle/parser/NameParser.java similarity index 93% rename from src/main/java/in/koreatech/koin/admin/bus/shuttle/util/NameParser.java rename to src/main/java/in/koreatech/koin/admin/bus/shuttle/parser/NameParser.java index d6651f8e6..31cf82ca9 100644 --- a/src/main/java/in/koreatech/koin/admin/bus/shuttle/util/NameParser.java +++ b/src/main/java/in/koreatech/koin/admin/bus/shuttle/parser/NameParser.java @@ -1,4 +1,4 @@ -package in.koreatech.koin.admin.bus.shuttle.util; +package in.koreatech.koin.admin.bus.shuttle.parser; import java.util.regex.Matcher; import java.util.regex.Pattern; From 1ef21050cb0fa07d27fde84cc4decac548219033 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EB=8F=99=ED=9B=88?= <2dh2@naver.com> Date: Tue, 18 Nov 2025 15:17:11 +0900 Subject: [PATCH 07/21] =?UTF-8?q?refactor:=20=EC=97=91=EC=85=80=20?= =?UTF-8?q?=EB=8D=B0=EC=9D=B4=ED=84=B0=20=EC=B6=94=EC=B6=9C=20=ED=81=B4?= =?UTF-8?q?=EB=9E=98=EC=8A=A4=20=EB=AA=85=20Parser=20->=20Extractor?= =?UTF-8?q?=EB=A1=9C=20=EB=B3=80=EA=B2=BD=20=EB=B0=8F=20=ED=8C=A8=ED=82=A4?= =?UTF-8?q?=EC=A7=80=20=EC=9D=B4=EB=8F=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ShuttleBusMetaDataExtractor.java} | 4 ++-- .../ShuttleBusNodeInfoExtractor.java} | 6 ++++-- .../ShuttleBusRouteInfoExtractor.java} | 6 ++++-- .../service/AdminShuttleBusExcelService.java | 18 +++++++++--------- 4 files changed, 19 insertions(+), 15 deletions(-) rename src/main/java/in/koreatech/koin/admin/bus/shuttle/{util/ShuttleBusMetaDataParser.java => extractor/ShuttleBusMetaDataExtractor.java} (94%) rename src/main/java/in/koreatech/koin/admin/bus/shuttle/{util/ShuttleBusNodeInfoParser.java => extractor/ShuttleBusNodeInfoExtractor.java} (87%) rename src/main/java/in/koreatech/koin/admin/bus/shuttle/{util/ShuttleBusRouteInfoParser.java => extractor/ShuttleBusRouteInfoExtractor.java} (94%) diff --git a/src/main/java/in/koreatech/koin/admin/bus/shuttle/util/ShuttleBusMetaDataParser.java b/src/main/java/in/koreatech/koin/admin/bus/shuttle/extractor/ShuttleBusMetaDataExtractor.java similarity index 94% rename from src/main/java/in/koreatech/koin/admin/bus/shuttle/util/ShuttleBusMetaDataParser.java rename to src/main/java/in/koreatech/koin/admin/bus/shuttle/extractor/ShuttleBusMetaDataExtractor.java index a17ed4906..ef87578cb 100644 --- a/src/main/java/in/koreatech/koin/admin/bus/shuttle/util/ShuttleBusMetaDataParser.java +++ b/src/main/java/in/koreatech/koin/admin/bus/shuttle/extractor/ShuttleBusMetaDataExtractor.java @@ -1,4 +1,4 @@ -package in.koreatech.koin.admin.bus.shuttle.util; +package in.koreatech.koin.admin.bus.shuttle.extractor; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Row; @@ -11,7 +11,7 @@ import in.koreatech.koin.global.code.ApiResponseCode; import in.koreatech.koin.global.exception.CustomException; -public class ShuttleBusMetaDataParser { +public class ShuttleBusMetaDataExtractor { private static final int REGION_ROW = 0; private static final int REGION_COL = 1; diff --git a/src/main/java/in/koreatech/koin/admin/bus/shuttle/util/ShuttleBusNodeInfoParser.java b/src/main/java/in/koreatech/koin/admin/bus/shuttle/extractor/ShuttleBusNodeInfoExtractor.java similarity index 87% rename from src/main/java/in/koreatech/koin/admin/bus/shuttle/util/ShuttleBusNodeInfoParser.java rename to src/main/java/in/koreatech/koin/admin/bus/shuttle/extractor/ShuttleBusNodeInfoExtractor.java index 1e4481bd7..e23bf06bd 100644 --- a/src/main/java/in/koreatech/koin/admin/bus/shuttle/util/ShuttleBusNodeInfoParser.java +++ b/src/main/java/in/koreatech/koin/admin/bus/shuttle/extractor/ShuttleBusNodeInfoExtractor.java @@ -1,4 +1,4 @@ -package in.koreatech.koin.admin.bus.shuttle.util; +package in.koreatech.koin.admin.bus.shuttle.extractor; import static in.koreatech.koin.admin.bus.shuttle.model.ShuttleBusTimetable.NodeInfo; @@ -10,7 +10,9 @@ import org.apache.poi.ss.usermodel.Sheet; import org.springframework.util.StringUtils; -public class ShuttleBusNodeInfoParser { +import in.koreatech.koin.admin.bus.shuttle.util.ExcelStringUtil; + +public class ShuttleBusNodeInfoExtractor { private static final int START_BUS_STOP_ROW = 5; private static final int START_BUS_STOP_COL = 0; diff --git a/src/main/java/in/koreatech/koin/admin/bus/shuttle/util/ShuttleBusRouteInfoParser.java b/src/main/java/in/koreatech/koin/admin/bus/shuttle/extractor/ShuttleBusRouteInfoExtractor.java similarity index 94% rename from src/main/java/in/koreatech/koin/admin/bus/shuttle/util/ShuttleBusRouteInfoParser.java rename to src/main/java/in/koreatech/koin/admin/bus/shuttle/extractor/ShuttleBusRouteInfoExtractor.java index 8c6f06b4c..0e2d89978 100644 --- a/src/main/java/in/koreatech/koin/admin/bus/shuttle/util/ShuttleBusRouteInfoParser.java +++ b/src/main/java/in/koreatech/koin/admin/bus/shuttle/extractor/ShuttleBusRouteInfoExtractor.java @@ -1,4 +1,4 @@ -package in.koreatech.koin.admin.bus.shuttle.util; +package in.koreatech.koin.admin.bus.shuttle.extractor; import static in.koreatech.koin.admin.bus.shuttle.model.ShuttleBusTimetable.RouteInfo; import static in.koreatech.koin.admin.bus.shuttle.model.ShuttleBusTimetable.RouteInfo.InnerNameDetail; @@ -15,8 +15,10 @@ import in.koreatech.koin.admin.bus.shuttle.enums.RunningDays; import in.koreatech.koin.admin.bus.shuttle.model.ArrivalTime; +import in.koreatech.koin.admin.bus.shuttle.util.ExcelRangeUtil; +import in.koreatech.koin.admin.bus.shuttle.util.ExcelStringUtil; -public class ShuttleBusRouteInfoParser { +public class ShuttleBusRouteInfoExtractor { private static final int START_HEADER_ROW = 3; private static final int START_DETAIL_ROW = 4; diff --git a/src/main/java/in/koreatech/koin/admin/bus/shuttle/service/AdminShuttleBusExcelService.java b/src/main/java/in/koreatech/koin/admin/bus/shuttle/service/AdminShuttleBusExcelService.java index c68495302..7c36d8cd4 100644 --- a/src/main/java/in/koreatech/koin/admin/bus/shuttle/service/AdminShuttleBusExcelService.java +++ b/src/main/java/in/koreatech/koin/admin/bus/shuttle/service/AdminShuttleBusExcelService.java @@ -20,9 +20,9 @@ import in.koreatech.koin.admin.bus.shuttle.model.RouteType; import in.koreatech.koin.admin.bus.shuttle.model.ShuttleBusTimetable; import in.koreatech.koin.admin.bus.shuttle.model.SubName; -import in.koreatech.koin.admin.bus.shuttle.util.ShuttleBusMetaDataParser; -import in.koreatech.koin.admin.bus.shuttle.util.ShuttleBusNodeInfoParser; -import in.koreatech.koin.admin.bus.shuttle.util.ShuttleBusRouteInfoParser; +import in.koreatech.koin.admin.bus.shuttle.extractor.ShuttleBusMetaDataExtractor; +import in.koreatech.koin.admin.bus.shuttle.extractor.ShuttleBusNodeInfoExtractor; +import in.koreatech.koin.admin.bus.shuttle.extractor.ShuttleBusRouteInfoExtractor; import in.koreatech.koin.domain.bus.enums.ShuttleBusRegion; import in.koreatech.koin.global.code.ApiResponseCode; import in.koreatech.koin.global.exception.CustomException; @@ -46,13 +46,13 @@ private List extractShuttleBusTimetableData(Wo List shuttleBusTimetables = new ArrayList<>(); for (Sheet sheet : workBook) { - List nodeInfos = ShuttleBusNodeInfoParser.getNodeInfos(sheet); - List routeInfos = ShuttleBusRouteInfoParser.getRouteInfos(sheet); + List nodeInfos = ShuttleBusNodeInfoExtractor.getNodeInfos(sheet); + List routeInfos = ShuttleBusRouteInfoExtractor.getRouteInfos(sheet); - RouteName routeName = ShuttleBusMetaDataParser.getRouteNameFromSheet(sheet); - SubName subName = ShuttleBusMetaDataParser.getSubNameFromSheet(sheet); - ShuttleBusRegion region = ShuttleBusMetaDataParser.getRegionFromSheet(sheet); - RouteType routeType = ShuttleBusMetaDataParser.getRouteTypeFromSheet(sheet); + RouteName routeName = ShuttleBusMetaDataExtractor.getRouteNameFromSheet(sheet); + SubName subName = ShuttleBusMetaDataExtractor.getSubNameFromSheet(sheet); + ShuttleBusRegion region = ShuttleBusMetaDataExtractor.getRegionFromSheet(sheet); + RouteType routeType = ShuttleBusMetaDataExtractor.getRouteTypeFromSheet(sheet); shuttleBusTimetables.add( ShuttleBusTimetable.from(nodeInfos, routeInfos, region, routeName, subName, routeType) From a45914333c027fb90db715a5147eb211c45a87d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EB=8F=99=ED=9B=88?= <2dh2@naver.com> Date: Tue, 18 Nov 2025 15:24:46 +0900 Subject: [PATCH 08/21] =?UTF-8?q?refactor:=20=EC=85=80=20=EB=82=B4?= =?UTF-8?q?=EC=9A=A9=20=EC=B6=94=EC=B6=9C=20=ED=81=B4=EB=9E=98=EC=8A=A4=20?= =?UTF-8?q?=EC=9D=B4=EB=A6=84=20=EB=B3=80=EA=B2=BD=20=EB=B0=8F=20=EB=A9=94?= =?UTF-8?q?=EC=86=8C=EB=93=9C=20=EB=AA=85=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../PoiCellExtractor.java} | 6 +++--- .../bus/shuttle/extractor/ShuttleBusNodeInfoExtractor.java | 4 +--- .../bus/shuttle/extractor/ShuttleBusRouteInfoExtractor.java | 3 +-- 3 files changed, 5 insertions(+), 8 deletions(-) rename src/main/java/in/koreatech/koin/admin/bus/shuttle/{util/ExcelStringUtil.java => extractor/PoiCellExtractor.java} (66%) diff --git a/src/main/java/in/koreatech/koin/admin/bus/shuttle/util/ExcelStringUtil.java b/src/main/java/in/koreatech/koin/admin/bus/shuttle/extractor/PoiCellExtractor.java similarity index 66% rename from src/main/java/in/koreatech/koin/admin/bus/shuttle/util/ExcelStringUtil.java rename to src/main/java/in/koreatech/koin/admin/bus/shuttle/extractor/PoiCellExtractor.java index 0a73c95cd..2548ea477 100644 --- a/src/main/java/in/koreatech/koin/admin/bus/shuttle/util/ExcelStringUtil.java +++ b/src/main/java/in/koreatech/koin/admin/bus/shuttle/extractor/PoiCellExtractor.java @@ -1,13 +1,13 @@ -package in.koreatech.koin.admin.bus.shuttle.util; +package in.koreatech.koin.admin.bus.shuttle.extractor; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.DataFormatter; -public class ExcelStringUtil { +public class PoiCellExtractor { private static final DataFormatter FORMATTER = new DataFormatter(); - public static String getCellValueToString(Cell cell) { + public static String extractStringValue(Cell cell) { String value = FORMATTER.formatCellValue(cell); return value != null ? value.trim() : ""; diff --git a/src/main/java/in/koreatech/koin/admin/bus/shuttle/extractor/ShuttleBusNodeInfoExtractor.java b/src/main/java/in/koreatech/koin/admin/bus/shuttle/extractor/ShuttleBusNodeInfoExtractor.java index e23bf06bd..586132433 100644 --- a/src/main/java/in/koreatech/koin/admin/bus/shuttle/extractor/ShuttleBusNodeInfoExtractor.java +++ b/src/main/java/in/koreatech/koin/admin/bus/shuttle/extractor/ShuttleBusNodeInfoExtractor.java @@ -10,8 +10,6 @@ import org.apache.poi.ss.usermodel.Sheet; import org.springframework.util.StringUtils; -import in.koreatech.koin.admin.bus.shuttle.util.ExcelStringUtil; - public class ShuttleBusNodeInfoExtractor { private static final int START_BUS_STOP_ROW = 5; @@ -28,7 +26,7 @@ public static List getNodeInfos(Sheet sheet) { } Cell cell = row.getCell(START_BUS_STOP_COL); - String nameWithDetail = ExcelStringUtil.getCellValueToString(cell); + String nameWithDetail = PoiCellExtractor.extractStringValue(cell); if (cell == null || !StringUtils.hasText(nameWithDetail)) { break; diff --git a/src/main/java/in/koreatech/koin/admin/bus/shuttle/extractor/ShuttleBusRouteInfoExtractor.java b/src/main/java/in/koreatech/koin/admin/bus/shuttle/extractor/ShuttleBusRouteInfoExtractor.java index 0e2d89978..9583cf256 100644 --- a/src/main/java/in/koreatech/koin/admin/bus/shuttle/extractor/ShuttleBusRouteInfoExtractor.java +++ b/src/main/java/in/koreatech/koin/admin/bus/shuttle/extractor/ShuttleBusRouteInfoExtractor.java @@ -16,7 +16,6 @@ import in.koreatech.koin.admin.bus.shuttle.enums.RunningDays; import in.koreatech.koin.admin.bus.shuttle.model.ArrivalTime; import in.koreatech.koin.admin.bus.shuttle.util.ExcelRangeUtil; -import in.koreatech.koin.admin.bus.shuttle.util.ExcelStringUtil; public class ShuttleBusRouteInfoExtractor { @@ -95,7 +94,7 @@ private static List extractArrivalTimes(Sheet sheet) { } Cell cell = row.getCell(colNum); - String strTime = ExcelStringUtil.getCellValueToString(cell); + String strTime = PoiCellExtractor.extractStringValue(cell); if (cell == null || !StringUtils.hasText(strTime)) { times.add(null); From 1b2bab615fba5d4783e25431dc6bcad4de00b97a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EB=8F=99=ED=9B=88?= <2dh2@naver.com> Date: Tue, 18 Nov 2025 15:57:05 +0900 Subject: [PATCH 09/21] =?UTF-8?q?refactor:=20=ED=8C=8C=EC=9D=BC=20?= =?UTF-8?q?=EC=97=85=EB=A1=9C=EB=93=9C=20=EB=AF=B8=EB=A6=AC=EB=B3=B4?= =?UTF-8?q?=EA=B8=B0=20=EB=A9=94=EC=86=8C=EB=93=9C=20=EC=9D=B4=EB=A6=84=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bus/shuttle/controller/AdminShuttleBusTimetableApi.java | 2 +- .../shuttle/controller/AdminShuttleBusTimetableController.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/in/koreatech/koin/admin/bus/shuttle/controller/AdminShuttleBusTimetableApi.java b/src/main/java/in/koreatech/koin/admin/bus/shuttle/controller/AdminShuttleBusTimetableApi.java index 706a7ac0b..90f86af99 100644 --- a/src/main/java/in/koreatech/koin/admin/bus/shuttle/controller/AdminShuttleBusTimetableApi.java +++ b/src/main/java/in/koreatech/koin/admin/bus/shuttle/controller/AdminShuttleBusTimetableApi.java @@ -37,7 +37,7 @@ public interface AdminShuttleBusTimetableApi { @Operation(summary = "엑셀 파일을 업로드하여 파싱된 데이터를 미리보기 한다.") @AdminActivityLogging(domain = SHUTTLE_BUS) @PostMapping("/excel") - ResponseEntity> previewShuttleBusTimetable( + ResponseEntity> uploadTimetableExcelForPreview( @Auth(permit = {ADMIN}) Integer adminId, @RequestParam(name = "shuttle-bus-timetable") MultipartFile file ); diff --git a/src/main/java/in/koreatech/koin/admin/bus/shuttle/controller/AdminShuttleBusTimetableController.java b/src/main/java/in/koreatech/koin/admin/bus/shuttle/controller/AdminShuttleBusTimetableController.java index 01bdd1e1f..428eaaad1 100644 --- a/src/main/java/in/koreatech/koin/admin/bus/shuttle/controller/AdminShuttleBusTimetableController.java +++ b/src/main/java/in/koreatech/koin/admin/bus/shuttle/controller/AdminShuttleBusTimetableController.java @@ -34,7 +34,7 @@ public class AdminShuttleBusTimetableController implements AdminShuttleBusTimeta @AdminActivityLogging(domain = SHUTTLE_BUS) @PostMapping("/excel") - public ResponseEntity> previewShuttleBusTimetable( + public ResponseEntity> uploadTimetableExcelForPreview( @Auth(permit = {ADMIN}) Integer adminId, @RequestParam(name = "shuttle-bus-timetable") MultipartFile file ) { From 85e12c01c403c85c176854b0f2e079349b7cb9ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EB=8F=99=ED=9B=88?= <2dh2@naver.com> Date: Tue, 18 Nov 2025 16:21:17 +0900 Subject: [PATCH 10/21] =?UTF-8?q?refactor:=20=EC=97=91=EC=85=80=20?= =?UTF-8?q?=EC=85=80=20=EB=AC=B8=EC=9E=90=EC=97=B4=20=EC=B6=94=EC=B6=9C?= =?UTF-8?q?=EC=9D=84=20PoiExtractor=EB=A1=9C=20=ED=86=B5=EC=9D=BC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ShuttleBusMetaDataExtractor.java | 28 ++++++------------- 1 file changed, 8 insertions(+), 20 deletions(-) diff --git a/src/main/java/in/koreatech/koin/admin/bus/shuttle/extractor/ShuttleBusMetaDataExtractor.java b/src/main/java/in/koreatech/koin/admin/bus/shuttle/extractor/ShuttleBusMetaDataExtractor.java index ef87578cb..715631caf 100644 --- a/src/main/java/in/koreatech/koin/admin/bus/shuttle/extractor/ShuttleBusMetaDataExtractor.java +++ b/src/main/java/in/koreatech/koin/admin/bus/shuttle/extractor/ShuttleBusMetaDataExtractor.java @@ -8,8 +8,6 @@ import in.koreatech.koin.admin.bus.shuttle.model.RouteType; import in.koreatech.koin.admin.bus.shuttle.model.SubName; import in.koreatech.koin.domain.bus.enums.ShuttleBusRegion; -import in.koreatech.koin.global.code.ApiResponseCode; -import in.koreatech.koin.global.exception.CustomException; public class ShuttleBusMetaDataExtractor { @@ -20,11 +18,17 @@ public class ShuttleBusMetaDataExtractor { private static final int ROUTE_TYPE_COL = 1; public static ShuttleBusRegion getRegionFromSheet(Sheet sheet) { - return ShuttleBusRegion.of(getCellValue(sheet, REGION_ROW, REGION_COL)); + Row row = sheet.getRow(REGION_ROW); + Cell cell = row.getCell(REGION_COL); + + return ShuttleBusRegion.of(PoiCellExtractor.extractStringValue(cell)); } public static RouteType getRouteTypeFromSheet(Sheet sheet) { - return RouteType.of(getCellValue(sheet, ROUTE_TYPE_ROW, ROUTE_TYPE_COL)); + Row row = sheet.getRow(ROUTE_TYPE_ROW); + Cell cell = row.getCell(ROUTE_TYPE_COL); + + return RouteType.of(PoiCellExtractor.extractStringValue(cell)); } public static RouteName getRouteNameFromSheet(Sheet sheet) { @@ -38,20 +42,4 @@ public static SubName getSubNameFromSheet(Sheet sheet) { return SubName.of(sheetName); } - - private static String getCellValue(Sheet sheet, int rowIndex, int colIndex) { - Row row = sheet.getRow(rowIndex); - - if (row == null) { - throw CustomException.of(ApiResponseCode.INVALID_EXCEL_ROW); - } - - Cell cell = row.getCell(colIndex); - - if (cell == null) { - throw CustomException.of(ApiResponseCode.INVALID_EXCEL_COL); - } - - return cell.toString(); - } } From c5a1cb774d5d509163d623a08db75c9444be522d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EB=8F=99=ED=9B=88?= <2dh2@naver.com> Date: Tue, 18 Nov 2025 16:44:10 +0900 Subject: [PATCH 11/21] =?UTF-8?q?refactor:=20Extractor=20=ED=81=B4?= =?UTF-8?q?=EB=9E=98=EC=8A=A4=20stateful=ED=95=98=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../extractor/ShuttleBusMetaDataExtractor.java | 13 +++++++++---- .../extractor/ShuttleBusNodeInfoExtractor.java | 7 ++++++- .../extractor/ShuttleBusRouteInfoExtractor.java | 10 +++++++--- .../service/AdminShuttleBusExcelService.java | 16 ++++++++++------ 4 files changed, 32 insertions(+), 14 deletions(-) diff --git a/src/main/java/in/koreatech/koin/admin/bus/shuttle/extractor/ShuttleBusMetaDataExtractor.java b/src/main/java/in/koreatech/koin/admin/bus/shuttle/extractor/ShuttleBusMetaDataExtractor.java index 715631caf..66f6aa24b 100644 --- a/src/main/java/in/koreatech/koin/admin/bus/shuttle/extractor/ShuttleBusMetaDataExtractor.java +++ b/src/main/java/in/koreatech/koin/admin/bus/shuttle/extractor/ShuttleBusMetaDataExtractor.java @@ -8,36 +8,41 @@ import in.koreatech.koin.admin.bus.shuttle.model.RouteType; import in.koreatech.koin.admin.bus.shuttle.model.SubName; import in.koreatech.koin.domain.bus.enums.ShuttleBusRegion; +import lombok.RequiredArgsConstructor; +@RequiredArgsConstructor public class ShuttleBusMetaDataExtractor { + private final Sheet sheet; + private static final int REGION_ROW = 0; private static final int REGION_COL = 1; private static final int ROUTE_TYPE_ROW = 1; private static final int ROUTE_TYPE_COL = 1; - public static ShuttleBusRegion getRegionFromSheet(Sheet sheet) { + + public ShuttleBusRegion getRegionFromSheet() { Row row = sheet.getRow(REGION_ROW); Cell cell = row.getCell(REGION_COL); return ShuttleBusRegion.of(PoiCellExtractor.extractStringValue(cell)); } - public static RouteType getRouteTypeFromSheet(Sheet sheet) { + public RouteType getRouteTypeFromSheet() { Row row = sheet.getRow(ROUTE_TYPE_ROW); Cell cell = row.getCell(ROUTE_TYPE_COL); return RouteType.of(PoiCellExtractor.extractStringValue(cell)); } - public static RouteName getRouteNameFromSheet(Sheet sheet) { + public RouteName getRouteNameFromSheet() { String sheetName = sheet.getSheetName(); return RouteName.of(sheetName); } - public static SubName getSubNameFromSheet(Sheet sheet) { + public SubName getSubNameFromSheet() { String sheetName = sheet.getSheetName(); return SubName.of(sheetName); diff --git a/src/main/java/in/koreatech/koin/admin/bus/shuttle/extractor/ShuttleBusNodeInfoExtractor.java b/src/main/java/in/koreatech/koin/admin/bus/shuttle/extractor/ShuttleBusNodeInfoExtractor.java index 586132433..e55c2b7f5 100644 --- a/src/main/java/in/koreatech/koin/admin/bus/shuttle/extractor/ShuttleBusNodeInfoExtractor.java +++ b/src/main/java/in/koreatech/koin/admin/bus/shuttle/extractor/ShuttleBusNodeInfoExtractor.java @@ -10,12 +10,17 @@ import org.apache.poi.ss.usermodel.Sheet; import org.springframework.util.StringUtils; +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor public class ShuttleBusNodeInfoExtractor { + private final Sheet sheet; + private static final int START_BUS_STOP_ROW = 5; private static final int START_BUS_STOP_COL = 0; - public static List getNodeInfos(Sheet sheet) { + public List getNodeInfos() { List nodeInfos = new ArrayList<>(); for (int i = START_BUS_STOP_ROW; i <= sheet.getLastRowNum(); i++) { diff --git a/src/main/java/in/koreatech/koin/admin/bus/shuttle/extractor/ShuttleBusRouteInfoExtractor.java b/src/main/java/in/koreatech/koin/admin/bus/shuttle/extractor/ShuttleBusRouteInfoExtractor.java index 9583cf256..7a84a698e 100644 --- a/src/main/java/in/koreatech/koin/admin/bus/shuttle/extractor/ShuttleBusRouteInfoExtractor.java +++ b/src/main/java/in/koreatech/koin/admin/bus/shuttle/extractor/ShuttleBusRouteInfoExtractor.java @@ -16,16 +16,20 @@ import in.koreatech.koin.admin.bus.shuttle.enums.RunningDays; import in.koreatech.koin.admin.bus.shuttle.model.ArrivalTime; import in.koreatech.koin.admin.bus.shuttle.util.ExcelRangeUtil; +import lombok.RequiredArgsConstructor; +@RequiredArgsConstructor public class ShuttleBusRouteInfoExtractor { + private final Sheet sheet; + private static final int START_HEADER_ROW = 3; private static final int START_DETAIL_ROW = 4; private static final int START_TIME_DATA_ROW = 5; private static final int START_COL = 1; - public static List getRouteInfos(Sheet sheet) { + public List getRouteInfos() { List innerNameDetails = extractRouteNameDetails(sheet); List runningDays = innerNameDetails.stream() @@ -43,7 +47,7 @@ public static List getRouteInfos(Sheet sheet) { .toList(); } - private static List extractRouteNameDetails(Sheet sheet) { + private List extractRouteNameDetails() { List innerNameDetails = new ArrayList<>(); Row headerRow = sheet.getRow(START_HEADER_ROW); @@ -74,7 +78,7 @@ private static List extractRouteNameDetails(Sheet sheet) { return innerNameDetails; } - private static List extractArrivalTimes(Sheet sheet) { + private List extractArrivalTimes() { List arrivalTimes = new ArrayList<>(); for (int colNum = START_COL; diff --git a/src/main/java/in/koreatech/koin/admin/bus/shuttle/service/AdminShuttleBusExcelService.java b/src/main/java/in/koreatech/koin/admin/bus/shuttle/service/AdminShuttleBusExcelService.java index 7c36d8cd4..6c01dc531 100644 --- a/src/main/java/in/koreatech/koin/admin/bus/shuttle/service/AdminShuttleBusExcelService.java +++ b/src/main/java/in/koreatech/koin/admin/bus/shuttle/service/AdminShuttleBusExcelService.java @@ -46,13 +46,17 @@ private List extractShuttleBusTimetableData(Wo List shuttleBusTimetables = new ArrayList<>(); for (Sheet sheet : workBook) { - List nodeInfos = ShuttleBusNodeInfoExtractor.getNodeInfos(sheet); - List routeInfos = ShuttleBusRouteInfoExtractor.getRouteInfos(sheet); + ShuttleBusNodeInfoExtractor nodeInfoExtractor = new ShuttleBusNodeInfoExtractor(sheet); + ShuttleBusRouteInfoExtractor routeInfoExtractor = new ShuttleBusRouteInfoExtractor(sheet); + ShuttleBusMetaDataExtractor metaDataExtractor = new ShuttleBusMetaDataExtractor(sheet); - RouteName routeName = ShuttleBusMetaDataExtractor.getRouteNameFromSheet(sheet); - SubName subName = ShuttleBusMetaDataExtractor.getSubNameFromSheet(sheet); - ShuttleBusRegion region = ShuttleBusMetaDataExtractor.getRegionFromSheet(sheet); - RouteType routeType = ShuttleBusMetaDataExtractor.getRouteTypeFromSheet(sheet); + List nodeInfos = nodeInfoExtractor.getNodeInfos(); + List routeInfos = routeInfoExtractor.getRouteInfos(); + + RouteName routeName = metaDataExtractor.getRouteNameFromSheet(); + SubName subName = metaDataExtractor.getSubNameFromSheet(); + ShuttleBusRegion region = metaDataExtractor.getRegionFromSheet(); + RouteType routeType = metaDataExtractor.getRouteTypeFromSheet(); shuttleBusTimetables.add( ShuttleBusTimetable.from(nodeInfos, routeInfos, region, routeName, subName, routeType) From 9c2a47fd058a94d07aeeeae91693431e896f70e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EB=8F=99=ED=9B=88?= <2dh2@naver.com> Date: Tue, 18 Nov 2025 18:13:18 +0900 Subject: [PATCH 12/21] =?UTF-8?q?refactor:=20PoiCellExtractor.extractStrin?= =?UTF-8?q?gValue()=20=ED=98=B8=EC=B6=9C=ED=95=98=EB=8F=84=EB=A1=9D=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../shuttle/extractor/ShuttleBusRouteInfoExtractor.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/in/koreatech/koin/admin/bus/shuttle/extractor/ShuttleBusRouteInfoExtractor.java b/src/main/java/in/koreatech/koin/admin/bus/shuttle/extractor/ShuttleBusRouteInfoExtractor.java index 7a84a698e..c22373e7e 100644 --- a/src/main/java/in/koreatech/koin/admin/bus/shuttle/extractor/ShuttleBusRouteInfoExtractor.java +++ b/src/main/java/in/koreatech/koin/admin/bus/shuttle/extractor/ShuttleBusRouteInfoExtractor.java @@ -30,13 +30,13 @@ public class ShuttleBusRouteInfoExtractor { private static final int START_COL = 1; public List getRouteInfos() { - List innerNameDetails = extractRouteNameDetails(sheet); + List innerNameDetails = extractRouteNameDetails(); List runningDays = innerNameDetails.stream() .map(RunningDays::from) .toList(); - List arrivalTimes = extractArrivalTimes(sheet); + List arrivalTimes = extractArrivalTimes(); return IntStream.range(0, innerNameDetails.size()) .mapToObj(i -> from( @@ -64,12 +64,12 @@ private List extractRouteNameDetails() { break; } - String name = nameCell.getStringCellValue().trim(); + String name = PoiCellExtractor.extractStringValue(nameCell); Cell detailCell = detailRow.getCell(col); String detail = (detailCell != null && StringUtils.hasText(detailCell.toString())) - ? detailCell.getStringCellValue().trim() + ? PoiCellExtractor.extractStringValue(detailCell) : null; innerNameDetails.add(InnerNameDetail.of(name, detail)); From d115bfe557e192b15c2ba6ff732e9ec6754753d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EB=8F=99=ED=9B=88?= <2dh2@naver.com> Date: Tue, 18 Nov 2025 18:24:14 +0900 Subject: [PATCH 13/21] =?UTF-8?q?refactor:=20=EC=85=80=20=EB=82=B4?= =?UTF-8?q?=EC=9A=A9=20=EC=B6=94=EC=B6=9C=20=EC=8B=9C=20=EC=84=9C=EC=8B=9D?= =?UTF-8?q?=EC=97=90=20=EB=8C=80=ED=95=9C=20=EB=AC=B8=EC=A0=9C=20=EB=B0=A9?= =?UTF-8?q?=EC=A7=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/bus/shuttle/util/ExcelRangeUtil.java | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/main/java/in/koreatech/koin/admin/bus/shuttle/util/ExcelRangeUtil.java b/src/main/java/in/koreatech/koin/admin/bus/shuttle/util/ExcelRangeUtil.java index 6fb78c491..cd1c6a761 100644 --- a/src/main/java/in/koreatech/koin/admin/bus/shuttle/util/ExcelRangeUtil.java +++ b/src/main/java/in/koreatech/koin/admin/bus/shuttle/util/ExcelRangeUtil.java @@ -1,12 +1,23 @@ package in.koreatech.koin.admin.bus.shuttle.util; import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.DataFormatter; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.springframework.util.StringUtils; public class ExcelRangeUtil { + private static final DataFormatter FORMATTER = new DataFormatter(); + + private static String getCellStringValue(Cell cell) { + if (cell == null) { + return ""; + } + + return FORMATTER.formatCellValue(cell).trim(); + } + public static int countUsedRowsInColumn(Sheet sheet, int startRow, int checkColumn) { int cnt = 0; @@ -19,7 +30,7 @@ public static int countUsedRowsInColumn(Sheet sheet, int startRow, int checkColu Cell cell = row.getCell(checkColumn); - if (cell == null || !StringUtils.hasText(cell.getStringCellValue())) { + if (!StringUtils.hasText(getCellStringValue(cell))) { break; } @@ -41,7 +52,7 @@ public static int countUsedColumnsInRow(Sheet sheet, int checkRow, int startCol) for (int col = startCol; col < row.getLastCellNum(); col++) { Cell cell = row.getCell(col); - if (cell != null && StringUtils.hasText(cell.getStringCellValue())) { + if (StringUtils.hasText(getCellStringValue(cell))) { lastCol = col; } } From 3254c093f5d0c3ecc2e74a5368de07e7239a73a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EB=8F=99=ED=9B=88?= <2dh2@naver.com> Date: Tue, 18 Nov 2025 18:44:21 +0900 Subject: [PATCH 14/21] =?UTF-8?q?refactor:=20=EC=9D=91=EB=8B=B5=20DTO=20?= =?UTF-8?q?=EA=B5=AC=EC=A1=B0=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../AdminShuttleBusTimetableApi.java | 4 +- .../AdminShuttleBusTimetableController.java | 6 +- .../AdminShuttleBusTimetableResponse.java | 141 +++++++++--------- .../service/AdminShuttleBusExcelService.java | 21 +-- 4 files changed, 88 insertions(+), 84 deletions(-) diff --git a/src/main/java/in/koreatech/koin/admin/bus/shuttle/controller/AdminShuttleBusTimetableApi.java b/src/main/java/in/koreatech/koin/admin/bus/shuttle/controller/AdminShuttleBusTimetableApi.java index 90f86af99..6e8e8802e 100644 --- a/src/main/java/in/koreatech/koin/admin/bus/shuttle/controller/AdminShuttleBusTimetableApi.java +++ b/src/main/java/in/koreatech/koin/admin/bus/shuttle/controller/AdminShuttleBusTimetableApi.java @@ -4,8 +4,6 @@ import static in.koreatech.koin.domain.user.model.UserType.ADMIN; import static in.koreatech.koin.global.code.ApiResponseCode.*; -import java.util.List; - import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PutMapping; @@ -37,7 +35,7 @@ public interface AdminShuttleBusTimetableApi { @Operation(summary = "엑셀 파일을 업로드하여 파싱된 데이터를 미리보기 한다.") @AdminActivityLogging(domain = SHUTTLE_BUS) @PostMapping("/excel") - ResponseEntity> uploadTimetableExcelForPreview( + ResponseEntity uploadTimetableExcelForPreview( @Auth(permit = {ADMIN}) Integer adminId, @RequestParam(name = "shuttle-bus-timetable") MultipartFile file ); diff --git a/src/main/java/in/koreatech/koin/admin/bus/shuttle/controller/AdminShuttleBusTimetableController.java b/src/main/java/in/koreatech/koin/admin/bus/shuttle/controller/AdminShuttleBusTimetableController.java index 428eaaad1..a8e73ff6f 100644 --- a/src/main/java/in/koreatech/koin/admin/bus/shuttle/controller/AdminShuttleBusTimetableController.java +++ b/src/main/java/in/koreatech/koin/admin/bus/shuttle/controller/AdminShuttleBusTimetableController.java @@ -3,8 +3,6 @@ import static in.koreatech.koin.admin.history.enums.DomainType.SHUTTLE_BUS; import static in.koreatech.koin.domain.user.model.UserType.ADMIN; -import java.util.List; - import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.PutMapping; @@ -34,11 +32,11 @@ public class AdminShuttleBusTimetableController implements AdminShuttleBusTimeta @AdminActivityLogging(domain = SHUTTLE_BUS) @PostMapping("/excel") - public ResponseEntity> uploadTimetableExcelForPreview( + public ResponseEntity uploadTimetableExcelForPreview( @Auth(permit = {ADMIN}) Integer adminId, @RequestParam(name = "shuttle-bus-timetable") MultipartFile file ) { - List response = adminShuttleBusExcelService + AdminShuttleBusTimetableResponse response = adminShuttleBusExcelService .previewShuttleBusTimetable(file); return ResponseEntity.ok(response); diff --git a/src/main/java/in/koreatech/koin/admin/bus/shuttle/dto/response/AdminShuttleBusTimetableResponse.java b/src/main/java/in/koreatech/koin/admin/bus/shuttle/dto/response/AdminShuttleBusTimetableResponse.java index 904fb6f42..bfa4dfe90 100644 --- a/src/main/java/in/koreatech/koin/admin/bus/shuttle/dto/response/AdminShuttleBusTimetableResponse.java +++ b/src/main/java/in/koreatech/koin/admin/bus/shuttle/dto/response/AdminShuttleBusTimetableResponse.java @@ -13,79 +13,84 @@ import lombok.Builder; @JsonNaming(SnakeCaseStrategy.class) -@Builder public record AdminShuttleBusTimetableResponse( - @Schema(description = "운행 지역", example = "CHEONAN_ASAN", requiredMode = REQUIRED) - String region, - - @Schema(description = "노선 타입", example = "SHUTTLE", requiredMode = REQUIRED) - String routeType, - - @Schema(description = "노선 이름", example = "천안 셔틀", requiredMode = REQUIRED) - String routeName, - - @Schema(description = "노선 부제목", example = "토요일, 일요일", requiredMode = NOT_REQUIRED) - String subName, - - @Schema(description = "정류소 정보 리스트") - List nodeInfo, - - @Schema(description = "회차별 도착 시간 및 운행 요일 정보 리스트") - List routeInfo + @Schema(description = "셔틀 버스 시간표 정보 리스트") + List shuttleBusTimetables ) { + @JsonNaming(SnakeCaseStrategy.class) + @Builder + public record InnerAdminShuttleBusTimetableResponse( + @Schema(description = "운행 지역", example = "CHEONAN_ASAN", requiredMode = REQUIRED) + String region, - public static AdminShuttleBusTimetableResponse from(ShuttleBusTimetable table) { - List nodeInfo = table.getNodeInfos() - .stream() - .map(n -> new InnerNodeInfoResponse( - n.getName(), - n.getDetail() - )) - .toList(); - - List routeInfo = table.getRouteInfos() - .stream() - .map(r -> new InnerRouteInfoResponse( - r.getName(), - r.getDetail(), - r.getArrivalTime() - )) - .toList(); - - return AdminShuttleBusTimetableResponse.builder() - .nodeInfo(nodeInfo) - .region(table.getRegion()) - .routeInfo(routeInfo) - .routeName(table.getRouteName()) - .routeType(table.getRouteType()) - .subName(table.getSubName()) - .build(); - } + @Schema(description = "노선 타입", example = "SHUTTLE", requiredMode = REQUIRED) + String routeType, - @JsonNaming(SnakeCaseStrategy.class) - public record InnerNodeInfoResponse( - @Schema(description = "정류소 이름", example = "한기대", requiredMode = REQUIRED) - String name, + @Schema(description = "노선 이름", example = "천안 셔틀", requiredMode = REQUIRED) + String routeName, - @Schema(description = "정류소 이름 추가 설명 (없으면 null)", example = "학화호두과자 앞", requiredMode = NOT_REQUIRED) - String detail - ) { - } + @Schema(description = "노선 부제목", example = "토요일, 일요일", requiredMode = NOT_REQUIRED) + String subName, - @JsonNaming(SnakeCaseStrategy.class) - public record InnerRouteInfoResponse( - @Schema(description = "회차 이름", example = "1회", requiredMode = REQUIRED) - String name, - - @Schema(description = "회차 세부 이름", example = "(청주역→본교)", requiredMode = NOT_REQUIRED) - String detail, - - @Schema( - description = "각 정류소 별 도착 시간 (미정차인 경우 null)", - example = "[\"08:00\", \"09:00\"]", - requiredMode = REQUIRED - ) - List arrivalTime + @Schema(description = "정류소 정보 리스트") + List nodeInfo, + + @Schema(description = "회차별 도착 시간 및 운행 요일 정보 리스트") + List routeInfo ) { + public static InnerAdminShuttleBusTimetableResponse from(ShuttleBusTimetable table) { + List nodeInfo = table.getNodeInfos() + .stream() + .map(n -> new InnerNodeInfoResponse( + n.getName(), + n.getDetail() + )) + .toList(); + + List routeInfo = table.getRouteInfos() + .stream() + .map(r -> new InnerRouteInfoResponse( + r.getName(), + r.getDetail(), + r.getArrivalTime() + )) + .toList(); + + return InnerAdminShuttleBusTimetableResponse.builder() + .nodeInfo(nodeInfo) + .region(table.getRegion()) + .routeInfo(routeInfo) + .routeName(table.getRouteName()) + .routeType(table.getRouteType()) + .subName(table.getSubName()) + .build(); + } + + @JsonNaming(SnakeCaseStrategy.class) + public record InnerNodeInfoResponse( + @Schema(description = "정류소 이름", example = "한기대", requiredMode = REQUIRED) + String name, + + @Schema(description = "정류소 이름 추가 설명 (없으면 null)", example = "학화호두과자 앞", requiredMode = NOT_REQUIRED) + String detail + ) { + } + + @JsonNaming(SnakeCaseStrategy.class) + public record InnerRouteInfoResponse( + @Schema(description = "회차 이름", example = "1회", requiredMode = REQUIRED) + String name, + + @Schema(description = "회차 세부 이름", example = "(청주역→본교)", requiredMode = NOT_REQUIRED) + String detail, + + @Schema( + description = "각 정류소 별 도착 시간 (미정차인 경우 null)", + example = "[\"08:00\", \"09:00\"]", + requiredMode = REQUIRED + ) + List arrivalTime + ) { + } } -} +} \ No newline at end of file diff --git a/src/main/java/in/koreatech/koin/admin/bus/shuttle/service/AdminShuttleBusExcelService.java b/src/main/java/in/koreatech/koin/admin/bus/shuttle/service/AdminShuttleBusExcelService.java index 6c01dc531..fb800c237 100644 --- a/src/main/java/in/koreatech/koin/admin/bus/shuttle/service/AdminShuttleBusExcelService.java +++ b/src/main/java/in/koreatech/koin/admin/bus/shuttle/service/AdminShuttleBusExcelService.java @@ -1,7 +1,6 @@ package in.koreatech.koin.admin.bus.shuttle.service; -import static in.koreatech.koin.admin.bus.shuttle.model.ShuttleBusTimetable.NodeInfo; -import static in.koreatech.koin.admin.bus.shuttle.model.ShuttleBusTimetable.RouteInfo; +import static in.koreatech.koin.admin.bus.shuttle.dto.response.AdminShuttleBusTimetableResponse.InnerAdminShuttleBusTimetableResponse; import java.io.IOException; import java.io.InputStream; @@ -16,13 +15,15 @@ import org.springframework.web.multipart.MultipartFile; import in.koreatech.koin.admin.bus.shuttle.dto.response.AdminShuttleBusTimetableResponse; +import in.koreatech.koin.admin.bus.shuttle.extractor.ShuttleBusMetaDataExtractor; +import in.koreatech.koin.admin.bus.shuttle.extractor.ShuttleBusNodeInfoExtractor; +import in.koreatech.koin.admin.bus.shuttle.extractor.ShuttleBusRouteInfoExtractor; import in.koreatech.koin.admin.bus.shuttle.model.RouteName; import in.koreatech.koin.admin.bus.shuttle.model.RouteType; import in.koreatech.koin.admin.bus.shuttle.model.ShuttleBusTimetable; +import in.koreatech.koin.admin.bus.shuttle.model.ShuttleBusTimetable.NodeInfo; +import in.koreatech.koin.admin.bus.shuttle.model.ShuttleBusTimetable.RouteInfo; import in.koreatech.koin.admin.bus.shuttle.model.SubName; -import in.koreatech.koin.admin.bus.shuttle.extractor.ShuttleBusMetaDataExtractor; -import in.koreatech.koin.admin.bus.shuttle.extractor.ShuttleBusNodeInfoExtractor; -import in.koreatech.koin.admin.bus.shuttle.extractor.ShuttleBusRouteInfoExtractor; import in.koreatech.koin.domain.bus.enums.ShuttleBusRegion; import in.koreatech.koin.global.code.ApiResponseCode; import in.koreatech.koin.global.exception.CustomException; @@ -31,7 +32,7 @@ @Transactional(readOnly = true) public class AdminShuttleBusExcelService { - public List previewShuttleBusTimetable(MultipartFile file) { + public AdminShuttleBusTimetableResponse previewShuttleBusTimetable(MultipartFile file) { try ( InputStream inputStream = file.getInputStream(); Workbook workbook = WorkbookFactory.create(inputStream) @@ -42,7 +43,7 @@ public List previewShuttleBusTimetable(Multipa } } - private List extractShuttleBusTimetableData(Workbook workBook) { + private AdminShuttleBusTimetableResponse extractShuttleBusTimetableData(Workbook workBook) { List shuttleBusTimetables = new ArrayList<>(); for (Sheet sheet : workBook) { @@ -63,8 +64,10 @@ private List extractShuttleBusTimetableData(Wo ); } - return shuttleBusTimetables.stream() - .map(AdminShuttleBusTimetableResponse::from) + List innerResponses = shuttleBusTimetables.stream() + .map(InnerAdminShuttleBusTimetableResponse::from) .toList(); + + return new AdminShuttleBusTimetableResponse(innerResponses); } } From 414117e87744c72e585dc02401c7b5da861b48fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EB=8F=99=ED=9B=88?= <2dh2@naver.com> Date: Tue, 18 Nov 2025 18:46:43 +0900 Subject: [PATCH 15/21] =?UTF-8?q?refactor:=20=EB=A9=94=EC=86=8C=EB=93=9C?= =?UTF-8?q?=20=EB=AA=85=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../extractor/ShuttleBusMetaDataExtractor.java | 8 ++++---- .../extractor/ShuttleBusNodeInfoExtractor.java | 2 +- .../extractor/ShuttleBusRouteInfoExtractor.java | 2 +- .../shuttle/service/AdminShuttleBusExcelService.java | 12 ++++++------ 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/main/java/in/koreatech/koin/admin/bus/shuttle/extractor/ShuttleBusMetaDataExtractor.java b/src/main/java/in/koreatech/koin/admin/bus/shuttle/extractor/ShuttleBusMetaDataExtractor.java index 66f6aa24b..ca7a07b2c 100644 --- a/src/main/java/in/koreatech/koin/admin/bus/shuttle/extractor/ShuttleBusMetaDataExtractor.java +++ b/src/main/java/in/koreatech/koin/admin/bus/shuttle/extractor/ShuttleBusMetaDataExtractor.java @@ -22,27 +22,27 @@ public class ShuttleBusMetaDataExtractor { private static final int ROUTE_TYPE_COL = 1; - public ShuttleBusRegion getRegionFromSheet() { + public ShuttleBusRegion extractRegion() { Row row = sheet.getRow(REGION_ROW); Cell cell = row.getCell(REGION_COL); return ShuttleBusRegion.of(PoiCellExtractor.extractStringValue(cell)); } - public RouteType getRouteTypeFromSheet() { + public RouteType extractRouteType() { Row row = sheet.getRow(ROUTE_TYPE_ROW); Cell cell = row.getCell(ROUTE_TYPE_COL); return RouteType.of(PoiCellExtractor.extractStringValue(cell)); } - public RouteName getRouteNameFromSheet() { + public RouteName extractRouteName() { String sheetName = sheet.getSheetName(); return RouteName.of(sheetName); } - public SubName getSubNameFromSheet() { + public SubName extractSubName() { String sheetName = sheet.getSheetName(); return SubName.of(sheetName); diff --git a/src/main/java/in/koreatech/koin/admin/bus/shuttle/extractor/ShuttleBusNodeInfoExtractor.java b/src/main/java/in/koreatech/koin/admin/bus/shuttle/extractor/ShuttleBusNodeInfoExtractor.java index e55c2b7f5..f158cffbd 100644 --- a/src/main/java/in/koreatech/koin/admin/bus/shuttle/extractor/ShuttleBusNodeInfoExtractor.java +++ b/src/main/java/in/koreatech/koin/admin/bus/shuttle/extractor/ShuttleBusNodeInfoExtractor.java @@ -20,7 +20,7 @@ public class ShuttleBusNodeInfoExtractor { private static final int START_BUS_STOP_ROW = 5; private static final int START_BUS_STOP_COL = 0; - public List getNodeInfos() { + public List extractNodeInfos() { List nodeInfos = new ArrayList<>(); for (int i = START_BUS_STOP_ROW; i <= sheet.getLastRowNum(); i++) { diff --git a/src/main/java/in/koreatech/koin/admin/bus/shuttle/extractor/ShuttleBusRouteInfoExtractor.java b/src/main/java/in/koreatech/koin/admin/bus/shuttle/extractor/ShuttleBusRouteInfoExtractor.java index c22373e7e..e39f0baa9 100644 --- a/src/main/java/in/koreatech/koin/admin/bus/shuttle/extractor/ShuttleBusRouteInfoExtractor.java +++ b/src/main/java/in/koreatech/koin/admin/bus/shuttle/extractor/ShuttleBusRouteInfoExtractor.java @@ -29,7 +29,7 @@ public class ShuttleBusRouteInfoExtractor { private static final int START_COL = 1; - public List getRouteInfos() { + public List extractRouteInfos() { List innerNameDetails = extractRouteNameDetails(); List runningDays = innerNameDetails.stream() diff --git a/src/main/java/in/koreatech/koin/admin/bus/shuttle/service/AdminShuttleBusExcelService.java b/src/main/java/in/koreatech/koin/admin/bus/shuttle/service/AdminShuttleBusExcelService.java index fb800c237..37e96fecc 100644 --- a/src/main/java/in/koreatech/koin/admin/bus/shuttle/service/AdminShuttleBusExcelService.java +++ b/src/main/java/in/koreatech/koin/admin/bus/shuttle/service/AdminShuttleBusExcelService.java @@ -51,13 +51,13 @@ private AdminShuttleBusTimetableResponse extractShuttleBusTimetableData(Workbook ShuttleBusRouteInfoExtractor routeInfoExtractor = new ShuttleBusRouteInfoExtractor(sheet); ShuttleBusMetaDataExtractor metaDataExtractor = new ShuttleBusMetaDataExtractor(sheet); - List nodeInfos = nodeInfoExtractor.getNodeInfos(); - List routeInfos = routeInfoExtractor.getRouteInfos(); + List nodeInfos = nodeInfoExtractor.extractNodeInfos(); + List routeInfos = routeInfoExtractor.extractRouteInfos(); - RouteName routeName = metaDataExtractor.getRouteNameFromSheet(); - SubName subName = metaDataExtractor.getSubNameFromSheet(); - ShuttleBusRegion region = metaDataExtractor.getRegionFromSheet(); - RouteType routeType = metaDataExtractor.getRouteTypeFromSheet(); + RouteName routeName = metaDataExtractor.extractRouteName(); + SubName subName = metaDataExtractor.extractSubName(); + ShuttleBusRegion region = metaDataExtractor.extractRegion(); + RouteType routeType = metaDataExtractor.extractRouteType(); shuttleBusTimetables.add( ShuttleBusTimetable.from(nodeInfos, routeInfos, region, routeName, subName, routeType) From b8861582b1ec60b5f55be2c83b3915df6a6bc3ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EB=8F=99=ED=9B=88?= <2dh2@naver.com> Date: Tue, 18 Nov 2025 18:47:50 +0900 Subject: [PATCH 16/21] =?UTF-8?q?chore:=20=EC=BD=94=EB=93=9C=20=ED=8F=AC?= =?UTF-8?q?=EB=A7=B7=ED=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bus/shuttle/extractor/ShuttleBusMetaDataExtractor.java | 1 - .../in/koreatech/koin/admin/bus/shuttle/parser/NameParser.java | 3 ++- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/in/koreatech/koin/admin/bus/shuttle/extractor/ShuttleBusMetaDataExtractor.java b/src/main/java/in/koreatech/koin/admin/bus/shuttle/extractor/ShuttleBusMetaDataExtractor.java index ca7a07b2c..05186e43f 100644 --- a/src/main/java/in/koreatech/koin/admin/bus/shuttle/extractor/ShuttleBusMetaDataExtractor.java +++ b/src/main/java/in/koreatech/koin/admin/bus/shuttle/extractor/ShuttleBusMetaDataExtractor.java @@ -21,7 +21,6 @@ public class ShuttleBusMetaDataExtractor { private static final int ROUTE_TYPE_ROW = 1; private static final int ROUTE_TYPE_COL = 1; - public ShuttleBusRegion extractRegion() { Row row = sheet.getRow(REGION_ROW); Cell cell = row.getCell(REGION_COL); diff --git a/src/main/java/in/koreatech/koin/admin/bus/shuttle/parser/NameParser.java b/src/main/java/in/koreatech/koin/admin/bus/shuttle/parser/NameParser.java index 31cf82ca9..94764c111 100644 --- a/src/main/java/in/koreatech/koin/admin/bus/shuttle/parser/NameParser.java +++ b/src/main/java/in/koreatech/koin/admin/bus/shuttle/parser/NameParser.java @@ -23,5 +23,6 @@ public static ParsedName parse(String raw) { return new ParsedName(raw.trim(), null); } - public record ParsedName(String name, String detail) {} + public record ParsedName(String name, String detail) { + } } From 9bc0db6fe602c432a6b3e6c75bac824a383fd355 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EB=8F=99=ED=9B=88?= <2dh2@naver.com> Date: Tue, 18 Nov 2025 18:59:43 +0900 Subject: [PATCH 17/21] =?UTF-8?q?refactor:=20=EC=84=9C=EB=B9=84=EC=8A=A4?= =?UTF-8?q?=20=EB=A9=94=EC=86=8C=EB=93=9C=20=EB=AA=85=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../shuttle/controller/AdminShuttleBusTimetableController.java | 2 +- .../admin/bus/shuttle/service/AdminShuttleBusExcelService.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/in/koreatech/koin/admin/bus/shuttle/controller/AdminShuttleBusTimetableController.java b/src/main/java/in/koreatech/koin/admin/bus/shuttle/controller/AdminShuttleBusTimetableController.java index a8e73ff6f..5f5a8f29d 100644 --- a/src/main/java/in/koreatech/koin/admin/bus/shuttle/controller/AdminShuttleBusTimetableController.java +++ b/src/main/java/in/koreatech/koin/admin/bus/shuttle/controller/AdminShuttleBusTimetableController.java @@ -37,7 +37,7 @@ public ResponseEntity uploadTimetableExcelForP @RequestParam(name = "shuttle-bus-timetable") MultipartFile file ) { AdminShuttleBusTimetableResponse response = adminShuttleBusExcelService - .previewShuttleBusTimetable(file); + .getShuttleBusTimetablePreview(file); return ResponseEntity.ok(response); } diff --git a/src/main/java/in/koreatech/koin/admin/bus/shuttle/service/AdminShuttleBusExcelService.java b/src/main/java/in/koreatech/koin/admin/bus/shuttle/service/AdminShuttleBusExcelService.java index 37e96fecc..8d4a54857 100644 --- a/src/main/java/in/koreatech/koin/admin/bus/shuttle/service/AdminShuttleBusExcelService.java +++ b/src/main/java/in/koreatech/koin/admin/bus/shuttle/service/AdminShuttleBusExcelService.java @@ -32,7 +32,7 @@ @Transactional(readOnly = true) public class AdminShuttleBusExcelService { - public AdminShuttleBusTimetableResponse previewShuttleBusTimetable(MultipartFile file) { + public AdminShuttleBusTimetableResponse getShuttleBusTimetablePreview(MultipartFile file) { try ( InputStream inputStream = file.getInputStream(); Workbook workbook = WorkbookFactory.create(inputStream) From adbca27928a1d0ce7df2c09c8754c3d856f33797 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EB=8F=99=ED=9B=88?= <2dh2@naver.com> Date: Mon, 24 Nov 2025 14:18:26 +0900 Subject: [PATCH 18/21] =?UTF-8?q?fix:=20=EC=97=85=EB=A1=9C=EB=93=9C=20API?= =?UTF-8?q?=EC=97=90=EC=84=9C=20=EC=9A=94=EC=B2=AD=20Content-Type=EC=9D=84?= =?UTF-8?q?=20=ED=8C=8C=EC=9D=BC=EB=A1=9C=20=EC=A7=80=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bus/shuttle/controller/AdminShuttleBusTimetableApi.java | 3 ++- .../shuttle/controller/AdminShuttleBusTimetableController.java | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/in/koreatech/koin/admin/bus/shuttle/controller/AdminShuttleBusTimetableApi.java b/src/main/java/in/koreatech/koin/admin/bus/shuttle/controller/AdminShuttleBusTimetableApi.java index 6e8e8802e..920a5f1f3 100644 --- a/src/main/java/in/koreatech/koin/admin/bus/shuttle/controller/AdminShuttleBusTimetableApi.java +++ b/src/main/java/in/koreatech/koin/admin/bus/shuttle/controller/AdminShuttleBusTimetableApi.java @@ -3,6 +3,7 @@ import static in.koreatech.koin.admin.history.enums.DomainType.SHUTTLE_BUS; import static in.koreatech.koin.domain.user.model.UserType.ADMIN; import static in.koreatech.koin.global.code.ApiResponseCode.*; +import static org.springframework.http.MediaType.MULTIPART_FORM_DATA_VALUE; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.PostMapping; @@ -34,7 +35,7 @@ public interface AdminShuttleBusTimetableApi { }) @Operation(summary = "엑셀 파일을 업로드하여 파싱된 데이터를 미리보기 한다.") @AdminActivityLogging(domain = SHUTTLE_BUS) - @PostMapping("/excel") + @PostMapping(value = "/excel", consumes = MULTIPART_FORM_DATA_VALUE) ResponseEntity uploadTimetableExcelForPreview( @Auth(permit = {ADMIN}) Integer adminId, @RequestParam(name = "shuttle-bus-timetable") MultipartFile file diff --git a/src/main/java/in/koreatech/koin/admin/bus/shuttle/controller/AdminShuttleBusTimetableController.java b/src/main/java/in/koreatech/koin/admin/bus/shuttle/controller/AdminShuttleBusTimetableController.java index 5f5a8f29d..c3acbe3fa 100644 --- a/src/main/java/in/koreatech/koin/admin/bus/shuttle/controller/AdminShuttleBusTimetableController.java +++ b/src/main/java/in/koreatech/koin/admin/bus/shuttle/controller/AdminShuttleBusTimetableController.java @@ -2,6 +2,7 @@ import static in.koreatech.koin.admin.history.enums.DomainType.SHUTTLE_BUS; import static in.koreatech.koin.domain.user.model.UserType.ADMIN; +import static org.springframework.http.MediaType.MULTIPART_FORM_DATA_VALUE; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.PostMapping; @@ -31,7 +32,7 @@ public class AdminShuttleBusTimetableController implements AdminShuttleBusTimeta private final AdminShuttleBusService adminShuttleBusService; @AdminActivityLogging(domain = SHUTTLE_BUS) - @PostMapping("/excel") + @PostMapping(value = "/excel", consumes = MULTIPART_FORM_DATA_VALUE) public ResponseEntity uploadTimetableExcelForPreview( @Auth(permit = {ADMIN}) Integer adminId, @RequestParam(name = "shuttle-bus-timetable") MultipartFile file From eae0999ce7050dce7a951f4432693344dd719697 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EB=8F=99=ED=9B=88?= <2dh2@naver.com> Date: Wed, 26 Nov 2025 11:11:04 +0900 Subject: [PATCH 19/21] =?UTF-8?q?chore:=20EOF=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../shuttle/dto/response/AdminShuttleBusTimetableResponse.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/in/koreatech/koin/admin/bus/shuttle/dto/response/AdminShuttleBusTimetableResponse.java b/src/main/java/in/koreatech/koin/admin/bus/shuttle/dto/response/AdminShuttleBusTimetableResponse.java index bfa4dfe90..06e3a99b3 100644 --- a/src/main/java/in/koreatech/koin/admin/bus/shuttle/dto/response/AdminShuttleBusTimetableResponse.java +++ b/src/main/java/in/koreatech/koin/admin/bus/shuttle/dto/response/AdminShuttleBusTimetableResponse.java @@ -93,4 +93,4 @@ public record InnerRouteInfoResponse( ) { } } -} \ No newline at end of file +} From e2533d9f74535b520bfda17612f2e3afa9251f66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EB=8F=99=ED=9B=88?= <2dh2@naver.com> Date: Wed, 26 Nov 2025 11:18:36 +0900 Subject: [PATCH 20/21] =?UTF-8?q?fix:=20cell=20=EA=B0=92=20=EC=B6=94?= =?UTF-8?q?=EC=B6=9C=20=EC=8B=9C=20null-safe=20=EC=B2=98=EB=A6=AC=ED=95=98?= =?UTF-8?q?=EB=8F=84=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bus/shuttle/extractor/ShuttleBusNodeInfoExtractor.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/in/koreatech/koin/admin/bus/shuttle/extractor/ShuttleBusNodeInfoExtractor.java b/src/main/java/in/koreatech/koin/admin/bus/shuttle/extractor/ShuttleBusNodeInfoExtractor.java index f158cffbd..9d40a7bff 100644 --- a/src/main/java/in/koreatech/koin/admin/bus/shuttle/extractor/ShuttleBusNodeInfoExtractor.java +++ b/src/main/java/in/koreatech/koin/admin/bus/shuttle/extractor/ShuttleBusNodeInfoExtractor.java @@ -31,9 +31,9 @@ public List extractNodeInfos() { } Cell cell = row.getCell(START_BUS_STOP_COL); - String nameWithDetail = PoiCellExtractor.extractStringValue(cell); + String nameWithDetail = (cell == null) ? "" : PoiCellExtractor.extractStringValue(cell); - if (cell == null || !StringUtils.hasText(nameWithDetail)) { + if (!StringUtils.hasText(nameWithDetail)) { break; } From dd6c17c5416af08ce377af58c4d38cecefb7016a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=9D=B4=EB=8F=99=ED=9B=88?= <2dh2@naver.com> Date: Thu, 27 Nov 2025 19:01:55 +0900 Subject: [PATCH 21/21] =?UTF-8?q?chore:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20=EA=B0=9C=ED=96=89=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../shuttle/controller/AdminShuttleBusTimetableController.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/in/koreatech/koin/admin/bus/shuttle/controller/AdminShuttleBusTimetableController.java b/src/main/java/in/koreatech/koin/admin/bus/shuttle/controller/AdminShuttleBusTimetableController.java index c3acbe3fa..63987e06e 100644 --- a/src/main/java/in/koreatech/koin/admin/bus/shuttle/controller/AdminShuttleBusTimetableController.java +++ b/src/main/java/in/koreatech/koin/admin/bus/shuttle/controller/AdminShuttleBusTimetableController.java @@ -37,8 +37,7 @@ public ResponseEntity uploadTimetableExcelForP @Auth(permit = {ADMIN}) Integer adminId, @RequestParam(name = "shuttle-bus-timetable") MultipartFile file ) { - AdminShuttleBusTimetableResponse response = adminShuttleBusExcelService - .getShuttleBusTimetablePreview(file); + AdminShuttleBusTimetableResponse response = adminShuttleBusExcelService.getShuttleBusTimetablePreview(file); return ResponseEntity.ok(response); }